[Toybox] [PATCH] Make yesno printf-like.

enh enh at google.com
Tue Sep 1 18:35:39 PDT 2015


Make yesno printf-like.

In addition to making most existing code slightly simpler, this will
let us move "if (!isatty(0)) return def;" into yesno so we can avoid
printing a prompt in non-interactive situations.

diff --git a/lib/lib.c b/lib/lib.c
index c16cffe..78d8742 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -630,12 +630,17 @@ void base64_init(char *p)
   *(p++) = '/';
 }

-int yesno(char *prompt, int def)
+int yesno(int def, char *prompt, ...)
 {
   char buf;

-  fprintf(stderr, "%s (%c/%c):", prompt, def ? 'Y' : 'y', def ? 'n' : 'N');
+  va_list va;
+  va_start(va, prompt);
+  vfprintf(stderr, prompt, va);
+  va_end(va);
+  fprintf(stderr, " (%c/%c):", def ? 'Y' : 'y', def ? 'n' : 'N');
   fflush(stderr);
+
   while (fread(&buf, 1, 1, stdin)) {
     int new;

diff --git a/lib/lib.h b/lib/lib.h
index 17a4a97..25b5bc2 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -176,7 +176,7 @@ void delete_tempfile(int fdin, int fdout, char **tempname);
 void replace_tempfile(int fdin, int fdout, char **tempname);
 void crc_init(unsigned int *crc_table, int little_endian);
 void base64_init(char *p);
-int yesno(char *prompt, int def);
+int yesno(int def, char *prompt, ...) printf_format;
 #define HR_SPACE 1
 #define HR_B 2
 int human_readable(char *buf, unsigned long long num, int style);
diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c
index 478f761..2aefc8b 100644
--- a/toys/lsb/killall.c
+++ b/toys/lsb/killall.c
@@ -40,8 +40,7 @@ static int kill_process(pid_t pid, char *name)
   if (pid == TT.cur_pid) return 0;

   if (toys.optflags & FLAG_i) {
-    snprintf(toybuf, sizeof(toybuf), "Signal %s(%d) ?", name, (int)pid);
-    if (!yesno(toybuf, 0)) return 0;
+    if (!yesno(0, "Signal %s(%d) ?", name, (int)pid)) return 0;
   }

   errno = 0;
diff --git a/toys/pending/crontab.c b/toys/pending/crontab.c
index 35f6d65..f0aa160 100644
--- a/toys/pending/crontab.c
+++ b/toys/pending/crontab.c
@@ -317,9 +317,8 @@ RETRY:
   }
   printf("%s: installing new crontab\n", toys.which->name);
   if (parse_crontab(tname)) {
-    snprintf(toybuf, sizeof(toybuf), "errors in crontab file, can't install.\n"
-        "Do you want to retry the same edit? ");
-    if (!yesno(toybuf, 0)) {
+    if (!yesno(0, "errors in crontab file, can't install.\n"
+               "Do you want to retry the same edit? ")) {
       error_msg("edits left in '%s'", tname);
       return;
     }
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index 5a55f40..a9c1b8d 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -173,7 +173,7 @@ int cp_node(struct dirtree *try)
         fprintf(stderr, "%s: overwrite '%s'", toys.which->name,
           s = dirtree_path(try, 0));
         free(s);
-        if (!yesno("", 1)) return 0;
+        if (!yesno(1, "")) return 0;
       }
     }

@@ -380,8 +380,8 @@ void cp_main(void)
         if (!stat(TT.destname, &st)
           && ((toys.optflags & FLAG_i) || !(st.st_mode & 0222)))
         {
-          fprintf(stderr, "%s: overwrite '%s'", toys.which->name, TT.destname);
-          if (!yesno("", 1)) rc = 0;
+          if (!yesno(1, "%s: overwrite '%s'", toys.which->name, TT.destname))
+            rc = 0;
           else unlink(TT.destname);
         }
       }
diff --git a/toys/posix/find.c b/toys/posix/find.c
index 99cf5e2..0f064ca 100644
--- a/toys/posix/find.c
+++ b/toys/posix/find.c
@@ -421,10 +421,7 @@ static int do_find(struct dirtree *new)
           if (aa->dir) aa->prev = (void *)1;

           if (*s == 'o') {
-            char *prompt = xmprintf("[%s] %s", ss1, name);
-            test = yesno(prompt, 0);
-            free(prompt);
-            if (!test) {
+            if (!yesno(0, "[%s] %s", ss1, name)) {
               free(name);
               goto cont;
             }
diff --git a/toys/posix/rm.c b/toys/posix/rm.c
index 5523a98..e5c5ae2 100644
--- a/toys/posix/rm.c
+++ b/toys/posix/rm.c
@@ -39,8 +39,7 @@ static int do_rm(struct dirtree *try)
     && (!S_ISLNK(try->st.st_mode) && faccessat(fd, try->name, W_OK, 0))) or++;
   if (!(dir && try->again) && ((or && isatty(0)) || (flags & FLAG_i))) {
     char *s = dirtree_path(try, 0);
-    fprintf(stderr, "rm %s%s", or ? "ro " : "", dir ? "dir " : "");
-    or = yesno(s, 0);
+    or = yesno(0, "rm %s%s%s", or ? "ro " : "", dir ? "dir " : "", s);
     free(s);
     if (!or) goto nodelete;
   }
@@ -58,8 +57,7 @@ static int do_rm(struct dirtree *try)
     if (flags & FLAG_i) {
       char *s = dirtree_path(try, 0);
       // This is the section 2(d) prompt. (Yes, posix says to prompt twice.)
-      fprintf(stderr, "rmdir ");
-      or = yesno(s, 0);
+      or = yesno(0, "rmdir %s", s);
       free(s);
       if (!or) goto nodelete;
     }
diff --git a/www/code.html b/www/code.html
index a1c08ef..61c9847 100644
--- a/www/code.html
+++ b/www/code.html
@@ -768,7 +768,7 @@ struct passwd *xgetpwnam(char *name)</b></p>
 <li><b>void replace_tempfile(int fdin, int fdout, char **tempname)</b></li>
 <li><b>void crc_init(unsigned int *crc_table, int little_endian)</b></li>
 <li><b>int terminal_size(unsigned *xx, unsigned *yy)</b></li>
-<li><b>int yesno(char *prompt, int def)</b></li>
+<li><b>int yesno(int def, char *prompt, ...)</b></li>
 <li><b>void generic_signal(int sig)</b></li>
 <li><b>void sigatexit(void *handler)</b></li>
 <li><b>int sig_to_num(char *pidstr)</b></li>


More information about the Toybox mailing list