diff --git a/ChangeLog b/ChangeLog index fd138616..787ebda0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-12-26 Nicolas François + + Merge Debian's patch 466_fflush-prompt + * libmisc/Makefile.am, lib/prototypes.h, libmisc/yesno.c, src/grpck.c, + src/pwck.c: move yes_or_no() from grpck/pwck to a separate + libmisc/yesno.c (with a read_only argument). + * libmisc/fields.c, libmisc/yesno.c: Make sure stdout is flushed before + reading the user's answer. + 2007-12-26 Nicolas François Merge Debian's patch 480_getopt_args_reorder diff --git a/lib/prototypes.h b/lib/prototypes.h index f88f3db3..64b205cd 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -194,4 +194,7 @@ extern struct group *xgetgrgid (gid_t); /* xgetspnam.c */ extern struct spwd *xgetspnam(const char *); +/* yesno.c */ +extern int yes_or_no (int read_only); + #endif /* _PROTOTYPES_H */ diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am index 95ce28cd..3df8885e 100644 --- a/libmisc/Makefile.am +++ b/libmisc/Makefile.am @@ -55,4 +55,5 @@ libmisc_a_SOURCES = \ xgetgrnam.c \ xgetgrgid.c \ xgetspnam.c \ - xmalloc.c + xmalloc.c \ + yesno.c diff --git a/libmisc/fields.c b/libmisc/fields.c index 10dc3520..e021f06d 100644 --- a/libmisc/fields.c +++ b/libmisc/fields.c @@ -71,6 +71,7 @@ void change_field (char *buf, size_t maxsize, const char *prompt) maxsize = sizeof (newf); printf ("\t%s [%s]: ", prompt, buf); + fflush (stdout); if (fgets (newf, maxsize, stdin) != newf) return; diff --git a/libmisc/yesno.c b/libmisc/yesno.c new file mode 100644 index 00000000..e5364561 --- /dev/null +++ b/libmisc/yesno.c @@ -0,0 +1,75 @@ +/* + * Copyright 1992 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Common code for yes/no prompting + * + * Used by pwck.c and grpck.c + */ + +#include "config.h" + +#ident "$Id$" + +#include +#include "prototypes.h" + +/* + * yes_or_no - get answer to question from the user + * + * It returns 0 if no. + * + * If the read_only flag is set, it will print No, and will return 0. + */ +int yes_or_no (int read_only) +{ + char buf[80]; + + /* + * In read-only mode all questions are answered "no". + */ + if (read_only) { + printf (_("No\n")); + return 0; + } + + /* + * Typically, there's a prompt on stdout, sometimes unflushed. + */ + fflush (stdout); + + /* + * Get a line and see what the first character is. + */ + /* TODO: use gettext */ + if (fgets (buf, sizeof buf, stdin)) + return buf[0] == 'y' || buf[0] == 'Y'; + + return 0; +} diff --git a/src/grpck.c b/src/grpck.c index 1b761598..ecf22b17 100644 --- a/src/grpck.c +++ b/src/grpck.c @@ -74,7 +74,6 @@ static int read_only = 0; /* local function prototypes */ static void usage (void); -static int yes_or_no (void); static void delete_member (char **, const char *); /* @@ -90,30 +89,6 @@ static void usage (void) exit (E_USAGE); } -/* - * yes_or_no - get answer to question from the user - */ -static int yes_or_no (void) -{ - char buf[80]; - - /* - * In read-only mode all questions are answered "no". - */ - if (read_only) { - printf (_("No\n")); - return 0; - } - - /* - * Get a line and see what the first character is. - */ - if (fgets (buf, sizeof buf, stdin)) - return buf[0] == 'y' || buf[0] == 'Y'; - - return 0; -} - /* * delete_member - delete an entry in a list of members */ @@ -296,7 +271,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (!yes_or_no ()) + if (!yes_or_no (read_only)) continue; /* @@ -352,7 +327,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (yes_or_no ()) + if (yes_or_no (read_only)) goto delete_gr; } @@ -389,7 +364,7 @@ int main (int argc, char **argv) grp->gr_name, grp->gr_mem[i]); printf (_("delete member '%s'? "), grp->gr_mem[i]); - if (!yes_or_no ()) + if (!yes_or_no (read_only)) continue; SYSLOG ((LOG_INFO, "delete member '%s' group '%s'", @@ -414,7 +389,7 @@ int main (int argc, char **argv) printf (_("add group '%s' in %s ?"), grp->gr_name, sgr_file); errors++; - if (yes_or_no ()) { + if (yes_or_no (read_only)) { struct sgrp sg; struct group gr; static char *empty = NULL; @@ -501,7 +476,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (!yes_or_no ()) + if (!yes_or_no (read_only)) continue; /* @@ -557,7 +532,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (yes_or_no ()) + if (yes_or_no (read_only)) goto delete_sg; } @@ -570,7 +545,7 @@ int main (int argc, char **argv) grp_file); printf (_("delete line '%s'? "), sge->line); errors++; - if (yes_or_no ()) + if (yes_or_no (read_only)) goto delete_sg; } else { /** @@ -612,7 +587,7 @@ int main (int argc, char **argv) printf (_("delete administrative member '%s'? "), sgr->sg_adm[i]); - if (!yes_or_no ()) + if (!yes_or_no (read_only)) continue; SYSLOG ((LOG_INFO, @@ -640,7 +615,7 @@ int main (int argc, char **argv) sgr->sg_name, sgr->sg_mem[i]); printf (_("delete member '%s'? "), sgr->sg_mem[i]); - if (!yes_or_no ()) + if (!yes_or_no (read_only)) continue; SYSLOG ((LOG_INFO, diff --git a/src/pwck.c b/src/pwck.c index 5fdf79b4..8bc57626 100644 --- a/src/pwck.c +++ b/src/pwck.c @@ -73,7 +73,6 @@ static int quiet = 0; /* don't report warnings, only errors */ /* local function prototypes */ static void usage (void); -static int yes_or_no (void); /* * usage - print syntax message and exit @@ -85,31 +84,6 @@ static void usage (void) exit (E_USAGE); } -/* - * yes_or_no - get answer to question from the user - */ -static int yes_or_no (void) -{ - char buf[80]; - - /* - * In read-only mode all questions are answered "no". - */ - - if (read_only) { - printf (_("No\n")); - return 0; - } - - /* - * Get a line and see what the first character is. - */ - if (fgets (buf, sizeof buf, stdin)) - return buf[0] == 'y' || buf[0] == 'Y'; - - return 0; -} - /* * pwck - verify password file integrity */ @@ -261,7 +235,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (!yes_or_no ()) + if (!yes_or_no (read_only)) continue; /* @@ -316,7 +290,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (yes_or_no ()) + if (yes_or_no (read_only)) goto delete_pw; } @@ -383,7 +357,7 @@ int main (int argc, char **argv) printf (_("add user '%s' in %s? "), pwd->pw_name, spw_file); errors++; - if (yes_or_no ()) { + if (yes_or_no (read_only)) { struct spwd sp; struct passwd pw; @@ -462,7 +436,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (!yes_or_no ()) + if (!yes_or_no (read_only)) continue; /* @@ -517,7 +491,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (yes_or_no ()) + if (yes_or_no (read_only)) goto delete_spw; } @@ -538,7 +512,7 @@ int main (int argc, char **argv) /* * prompt the user to delete the entry or not */ - if (yes_or_no ()) + if (yes_or_no (read_only)) goto delete_spw; }