69029a2c63377d7cba2090add9abb05c85ee6188
[platform/upstream/toybox.git] / lib / lib.c
1 /* vi: set sw=4 ts=4 :*/
2 /* lib.c - reusable stuff.
3  *
4  * Functions with the x prefix are wrappers for library functions.  They either
5  * succeed or kill the program with an error message, but never return failure.
6  * They usually have the same arguments and return value as the function they
7  * wrap.
8  *
9  * Copyright 2006 Rob Landley <rob@landley.net>
10  */
11
12 #include "toys.h"
13
14 // Strcpy with size checking: exit if there's not enough space for the string.
15 void xstrcpy(char *dest, char *src, size_t size)
16 {
17         if (strlen(src)+1 > size) error_exit("xstrcpy");
18         strcpy(dest, src);
19 }
20
21 void verror_msg(char *msg, int err, va_list va)
22 {
23         char *s = ": %s";
24
25         fprintf(stderr, "%s: ", toys.which->name);
26         if (msg) vfprintf(stderr, msg, va);
27         else s+=2;
28         if (err) fprintf(stderr, s, strerror(err));
29         putc('\n', stderr);
30 }
31
32 void error_msg(char *msg, ...)
33 {
34         va_list va;
35
36         va_start(va, msg);
37         verror_msg(msg, 0, va);
38         va_end(va);
39 }
40
41 void perror_msg(char *msg, ...)
42 {
43         va_list va;
44
45         va_start(va, msg);
46         verror_msg(msg, errno, va);
47         va_end(va);
48 }
49
50 // Die with an error message.
51 void error_exit(char *msg, ...)
52 {
53         va_list va;
54
55         if (CFG_HELP && toys.exithelp) {
56                 *toys.optargs=*toys.argv;
57                 USE_HELP(help_main();)  // dear gcc: shut up.
58                 fprintf(stderr,"\n");
59         }
60
61         va_start(va, msg);
62         verror_msg(msg, 0, va);
63         va_end(va);
64
65         exit(!toys.exitval ? 1 : toys.exitval);
66 }
67
68
69 // Die with an error message and strerror(errno)
70 void perror_exit(char *msg, ...)
71 {
72         va_list va;
73
74         va_start(va, msg);
75         verror_msg(msg, errno, va);
76         va_end(va);
77
78         exit(!toys.exitval ? 1 : toys.exitval);
79 }
80
81 // Die unless we can allocate memory.
82 void *xmalloc(size_t size)
83 {
84         void *ret = malloc(size);
85         if (!ret) error_exit("xmalloc");
86
87         return ret;
88 }
89
90 // Die unless we can allocate prezeroed memory.
91 void *xzalloc(size_t size)
92 {
93         void *ret = xmalloc(size);
94         memset(ret, 0, size);
95         return ret;
96 }
97
98 // Die unless we can change the size of an existing allocation, possibly
99 // moving it.  (Notice different arguments from libc function.)
100 void *xrealloc(void *ptr, size_t size)
101 {
102         ptr = realloc(ptr, size);
103         if (!ptr) error_exit("xrealloc");
104
105         return ptr;
106 }
107
108 // Die unless we can allocate a copy of this many bytes of string.
109 char *xstrndup(char *s, size_t n)
110 {
111         char *ret = xmalloc(++n);
112         strncpy(ret, s, n);
113         ret[--n]=0;
114
115         return ret;
116 }
117
118 // Die unless we can allocate a copy of this string.
119 char *xstrdup(char *s)
120 {
121         return xstrndup(s, strlen(s));
122 }
123
124 // Die unless we can allocate enough space to sprintf() into.
125 char *xmsprintf(char *format, ...)
126 {
127         va_list va, va2;
128         int len;
129         char *ret;
130
131         va_start(va, format);
132         va_copy(va2, va);
133
134         // How long is it?
135         len = vsnprintf(0, 0, format, va);
136         len++;
137         va_end(va);
138
139         // Allocate and do the sprintf()
140         ret = xmalloc(len);
141         vsnprintf(ret, len, format, va2);
142         va_end(va2);
143
144         return ret;
145 }
146
147 void xprintf(char *format, ...)
148 {
149         va_list va;
150         va_start(va, format);
151
152         vprintf(format, va);
153         if (ferror(stdout)) perror_exit("write");
154 }
155
156 void xputs(char *s)
157 {
158         if (EOF == puts(s)) perror_exit("write");
159 }
160
161 void xputc(char c)
162 {
163         if (EOF == fputc(c, stdout)) perror_exit("write");
164 }
165
166 void xflush(void)
167 {
168         if (fflush(stdout)) perror_exit("write");;
169 }
170
171 // Die unless we can exec argv[] (or run builtin command).  Note that anything
172 // with a path isn't a builtin, so /bin/sh won't match the builtin sh.
173 void xexec(char **argv)
174 {
175         toy_exec(argv);
176         execvp(argv[0], argv);
177
178         perror_exit("exec %s", argv[0]);
179 }
180
181 void xaccess(char *path, int flags)
182 {
183         if (access(path, flags)) perror_exit("Can't access '%s'", path);
184 }
185
186 // Die unless we can delete a file.  (File must exist to be deleted.)
187 void xunlink(char *path)
188 {
189         if (unlink(path)) perror_exit("unlink '%s'", path);
190 }
191
192 // Die unless we can open/create a file, returning file descriptor.
193 int xcreate(char *path, int flags, int mode)
194 {
195         int fd = open(path, flags, mode);
196         if (fd == -1) perror_exit("%s", path);
197         return fd;
198 }
199
200 // Die unless we can open a file, returning file descriptor.
201 int xopen(char *path, int flags)
202 {
203         return xcreate(path, flags, 0);
204 }
205
206 void xclose(int fd)
207 {
208         if (close(fd)) perror_exit("xclose");
209 }
210
211 int xdup(int fd)
212 {
213         if (fd != -1) {
214                 fd = dup(fd);
215                 if (fd == -1) perror_exit("xdup");
216         }
217         return fd;
218 }
219
220 // Die unless we can open/create a file, returning FILE *.
221 FILE *xfopen(char *path, char *mode)
222 {
223         FILE *f = fopen(path, mode);
224         if (!f) perror_exit("No file %s", path);
225         return f;
226 }
227
228 // Keep reading until full or EOF
229 ssize_t readall(int fd, void *buf, size_t len)
230 {
231         size_t count = 0;
232
233         while (count<len) {
234                 int i = read(fd, buf+count, len-count);
235                 if (!i) break;
236                 if (i<0) return i;
237                 count += i;
238         }
239
240         return count;
241 }
242
243 // Keep writing until done or EOF
244 ssize_t writeall(int fd, void *buf, size_t len)
245 {
246         size_t count = 0;
247         while (count<len) {
248                 int i = write(fd, buf+count, len-count);
249                 if (i<1) return i;
250                 count += i;
251         }
252
253         return count;
254 }
255
256 // Die if there's an error other than EOF.
257 size_t xread(int fd, void *buf, size_t len)
258 {
259         ssize_t ret = read(fd, buf, len);
260         if (ret < 0) perror_exit("xread");
261
262         return ret;
263 }
264
265 void xreadall(int fd, void *buf, size_t len)
266 {
267         if (len != readall(fd, buf, len)) perror_exit("xreadall");
268 }
269
270 // There's no xwriteall(), just xwrite().  When we read, there may or may not
271 // be more data waiting.  When we write, there is data and it had better go
272 // somewhere.
273
274 void xwrite(int fd, void *buf, size_t len)
275 {
276         if (len != writeall(fd, buf, len)) perror_exit("xwrite");
277 }
278
279 // Die if lseek fails, probably due to being called on a pipe.
280
281 off_t xlseek(int fd, off_t offset, int whence)
282 {
283         offset = lseek(fd, offset, whence);
284         if (offset<0) perror_exit("lseek");
285
286         return offset;
287 }
288
289 off_t lskip(int fd, off_t offset)
290 {
291         off_t and = lseek(fd, offset, SEEK_CUR);
292
293         if (and != -1 && offset >= lseek(fd, offset, SEEK_END)
294                 && offset+and == lseek(fd, offset+and, SEEK_SET)) return 0;
295         else {
296                 char buf[4096];
297                 while (offset>0) {
298                         int try = offset>sizeof(buf) ? sizeof(buf) : offset, or;
299
300                         or = readall(fd, buf, try);
301                         if (or < 0) perror_msg("lskip to %lld", (long long)offset);
302                         else offset -= try;
303                         if (or < try) break;
304                 }
305
306                 return offset;
307         }
308 }
309
310 char *xgetcwd(void)
311 {
312         char *buf = getcwd(NULL, 0);
313         if (!buf) perror_exit("xgetcwd");
314
315         return buf;
316 }
317
318 void xstat(char *path, struct stat *st)
319 {
320         if(stat(path, st)) perror_exit("Can't stat %s", path);
321 }
322
323 // Cannonicalizes path by removing ".", "..", and "//" elements.  This is not
324 // the same as realpath(), where "dir/.." could wind up somewhere else by
325 // following symlinks.
326 char *xabspath(char *path)
327 {
328         char *from, *to;
329
330         // If this isn't an absolute path, make it one with cwd.
331         if (path[0]!='/') {
332                 char *cwd=xgetcwd();
333                 path = xmsprintf("%s/%s", cwd, path);
334                 free(cwd);
335         } else path = xstrdup(path);
336
337         // Loop through path elements
338         from = to = path;
339         while (*from) {
340
341                 // Continue any current path component.
342                 if (*from!='/') {
343                         *(to++) = *(from++);
344                         continue;
345                 }
346
347                 // Skip duplicate slashes.
348                 while (*from=='/') from++;
349
350                 // Start of a new filename.  Handle . and ..
351                 while (*from=='.') {
352                         // Skip .
353                         if (from[1]=='/') from += 2;
354                         else if (!from[1]) from++;
355                         // Back up for ..
356                         else if (from[1]=='.') {
357                                 if (from[2]=='/') from +=3;
358                                 else if(!from[2]) from+=2;
359                                 else break;
360                                 while (to>path && *(--to)!='/');
361                         } else break;
362                 }
363                 // Add directory separator slash.
364                 *(to++) = '/';
365         }
366         *to = 0;
367
368         return path;
369 }
370
371 // Resolve all symlinks, returning malloc() memory.
372 char *xrealpath(char *path)
373 {
374         char *new = realpath(path, NULL);
375         if (!new) perror_exit("realpath '%s'", path);
376         return new;
377 }
378
379 void xchdir(char *path)
380 {
381         if (chdir(path)) error_exit("chdir '%s'", path);
382 }
383
384 // Ensure entire path exists.
385 // If mode != -1 set permissions on newly created dirs.
386 // Requires that path string be writable (for temporary null terminators).
387 void xmkpath(char *path, int mode)
388 {
389         char *p, old;
390         mode_t mask;
391         int rc;
392         struct stat st;
393
394         for (p = path; ; p++) {
395                 if (!*p || *p == '/') {
396                         old = *p;
397                         *p = rc = 0;
398                         if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
399                                 if (mode != -1) {
400                                         mask=umask(0);
401                                         rc = mkdir(path, mode);
402                                         umask(mask);
403                                 } else rc = mkdir(path, 0777);
404                         }
405                         *p = old;
406                         if(rc) perror_exit("mkpath '%s'", path);
407                 }
408                 if (!*p) break;
409         }
410 }
411
412 // setuid() can fail (for example, too many processes belonging to that user),
413 // which opens a security hole if the process continues as the original user.
414
415 void xsetuid(uid_t uid)
416 {
417         if (setuid(uid)) perror_exit("xsetuid");
418 }
419
420
421 // Find all file in a colon-separated path with access type "type" (generally
422 // X_OK or R_OK).  Returns a list of absolute paths to each file found, in
423 // order.
424
425 struct string_list *find_in_path(char *path, char *filename)
426 {
427         struct string_list *rlist = NULL, **prlist=&rlist;
428         char *cwd = xgetcwd();
429
430         for (;;) {
431                 char *next = path ? strchr(path, ':') : NULL;
432                 int len = next ? next-path : strlen(path);
433                 struct string_list *rnext;
434                 struct stat st;
435
436                 rnext = xmalloc(sizeof(void *) + strlen(filename)
437                         + (len ? len : strlen(cwd)) + 2);
438                 if (!len) sprintf(rnext->str, "%s/%s", cwd, filename);
439                 else {
440                         char *res = rnext->str;
441                         strncpy(res, path, len);
442                         res += len;
443                         *(res++) = '/';
444                         strcpy(res, filename);
445                 }
446
447                 // Confirm it's not a directory.
448                 if (!stat(rnext->str, &st) && S_ISREG(st.st_mode)) {
449                         *prlist = rnext;
450                         rnext->next = NULL;
451                         prlist = &(rnext->next);
452                 } else free(rnext);
453
454                 if (!next) break;
455                 path += len;
456                 path++;
457         }
458         free(cwd);
459
460         return rlist;
461 }
462
463 // Convert unsigned int to ascii, writing into supplied buffer.  A truncated
464 // result contains the first few digits of the result ala strncpy, and is
465 // always null terminated (unless buflen is 0).
466 void utoa_to_buf(unsigned n, char *buf, unsigned buflen)
467 {
468         int i, out = 0;
469
470         if (buflen) {
471                 for (i=1000000000; i; i/=10) {
472                         int res = n/i;
473
474                         if ((res || out || i == 1) && --buflen>0) {
475                                 out++;
476                                 n -= res*i;
477                                 *buf++ = '0' + res;
478                         }
479                 }
480                 *buf = 0;
481         }
482 }
483
484 // Convert signed integer to ascii, using utoa_to_buf()
485 void itoa_to_buf(int n, char *buf, unsigned buflen)
486 {
487         if (buflen && n<0) {
488                 n = -n;
489                 *buf++ = '-';
490                 buflen--;
491         }
492         utoa_to_buf((unsigned)n, buf, buflen);
493 }
494
495 // This static buffer is used by both utoa() and itoa(), calling either one a
496 // second time will overwrite the previous results.
497 //
498 // The longest 32 bit integer is -2 billion plus a null terminator: 12 bytes.
499 // Note that int is always 32 bits on any remotely unix-like system, see
500 // http://www.unix.org/whitepapers/64bit.html for details.
501
502 static char itoa_buf[12];
503
504 // Convert unsigned integer to ascii, returning a static buffer.
505 char *utoa(unsigned n)
506 {
507         utoa_to_buf(n, itoa_buf, sizeof(itoa_buf));
508
509         return itoa_buf;
510 }
511
512 char *itoa(int n)
513 {
514         itoa_to_buf(n, itoa_buf, sizeof(itoa_buf));
515
516         return itoa_buf;
517 }
518
519 // atol() with the kilo/mega/giga/tera/peta/exa extensions.
520 // (zetta and yotta don't fit in 64 bits.)
521 long atolx(char *numstr)
522 {
523         char *c, *suffixes="bkmgtpe", *end;
524         long val = strtol(numstr, &c, 0);
525
526         if (*c) {
527                 if (c != numstr && (end = strchr(suffixes, tolower(*c)))) {
528                         int shift = end-suffixes;
529                         if (shift--) val *= 1024L<<(shift*10);
530                 } else {
531                         while (isspace(*c)) c++;
532                         if (*c) error_exit("not integer: %s", numstr);
533                 }
534         }
535
536         return val;
537 }
538
539 int numlen(long l)
540 {
541     int len = 0;
542     while (l) {
543        l /= 10;
544        len++;
545     }
546     return len;
547 }
548
549 int stridx(char *haystack, char needle)
550 {
551         char *off;
552
553         if (!needle) return -1;
554         off = strchr(haystack, needle);
555         if (!off) return -1;
556
557         return off-haystack;
558 }
559
560 // Return how long the file at fd is, if there's any way to determine it.
561 off_t fdlength(int fd)
562 {
563         off_t bottom = 0, top = 0, pos, old;
564         int size;
565
566         // If the ioctl works for this, return it.
567
568         if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512L;
569
570         // If not, do a binary search for the last location we can read.  (Some
571         // block devices don't do BLKGETSIZE right.)  This should probably have
572         // a CONFIG option...
573
574         old = lseek(fd, 0, SEEK_CUR);
575         do {
576                 char temp;
577
578                 pos = bottom + (top - bottom) / 2;
579
580                 // If we can read from the current location, it's bigger.
581
582                 if (lseek(fd, pos, 0)>=0 && read(fd, &temp, 1)==1) {
583                         if (bottom == top) bottom = top = (top+1) * 2;
584                         else bottom = pos;
585
586                         // If we can't, it's smaller.
587
588                 } else {
589                         if (bottom == top) {
590                                 if (!top) return 0;
591                                 bottom = top/2;
592                         } else top = pos;
593                 }
594         } while (bottom + 1 != top);
595
596         lseek(fd, old, SEEK_SET);
597
598         return pos + 1;
599 }
600
601 // This can return null (meaning file not found).  It just won't return null
602 // for memory allocation reasons.
603 char *xreadlink(char *name)
604 {
605         int len, size = 0;
606         char *buf = 0;
607
608         // Grow by 64 byte chunks until it's big enough.
609         for(;;) {
610                 size +=64;
611                 buf = xrealloc(buf, size);
612                 len = readlink(name, buf, size);
613
614                 if (len<0) {
615                         free(buf);
616                         return 0;
617                 }
618                 if (len<size) {
619                         buf[len]=0;
620                         return buf;
621                 }
622         }
623 }
624
625 /*
626  This might be of use or might not.  Unknown yet...
627
628 // Read contents of file as a single freshly allocated nul-terminated string.
629 char *readfile(char *name)
630 {
631         off_t len;
632         int fd;
633         char *buf;
634
635         fd = open(name, O_RDONLY);
636         if (fd == -1) return 0;
637         len = fdlength(fd);
638         buf = xmalloc(len+1);
639         buf[readall(fd, buf, len)] = 0;
640
641         return buf;
642 }
643
644 char *xreadfile(char *name)
645 {
646         char *buf = readfile(name);
647         if (!buf) perror_exit("xreadfile %s", name);
648         return buf;
649 }
650
651 */
652
653 // Open a /var/run/NAME.pid file, dying if we can't write it or if it currently
654 // exists and is this executable.
655 void xpidfile(char *name)
656 {
657         char pidfile[256], spid[32];
658         int i, fd;
659         pid_t pid;
660         
661         sprintf(pidfile, "/var/run/%s.pid", name);
662         // Try three times to open the sucker.
663         for (i=0; i<3; i++) {
664                 fd = open(pidfile, O_CREAT|O_EXCL, 0644);
665                 if (fd != -1) break;
666
667                 // If it already existed, read it.  Loop for race condition.
668                 fd = open(pidfile, O_RDONLY);
669                 if (fd == -1) continue;
670
671                 // Is the old program still there?
672                 spid[xread(fd, spid, sizeof(spid)-1)] = 0;
673                 close(fd);
674                 pid = atoi(spid);
675                 if (fd < 1 || kill(pid, 0) == ESRCH) unlink(pidfile);
676
677                 // An else with more sanity checking might be nice here.
678         }
679
680         if (i == 3) error_exit("xpidfile %s", name);
681
682         xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid()));
683         close(fd);
684 }
685
686 // Iterate through an array of files, opening each one and calling a function
687 // on that filehandle and name.  The special filename "-" means stdin if
688 // flags is O_RDONLY, stdout otherwise.  An empty argument list calls
689 // function() on just stdin/stdout.
690 //
691 // Note: read only filehandles are automatically closed when function()
692 // returns, but writeable filehandles must be close by function()
693 void loopfiles_rw(char **argv, int flags, int permissions, int failok,
694         void (*function)(int fd, char *name))
695 {
696         int fd;
697
698         // If no arguments, read from stdin.
699         if (!*argv) function(flags ? 1 : 0, "-");
700         else do {
701                 // Filename "-" means read from stdin.
702                 // Inability to open a file prints a warning, but doesn't exit.
703
704                 if (!strcmp(*argv,"-")) fd=0;
705                 else if (0>(fd = open(*argv, flags, permissions)) && !failok) {
706                         perror_msg("%s", *argv);
707                         toys.exitval = 1;
708                         continue;
709                 }
710                 function(fd, *argv);
711                 if (!flags) close(fd);
712         } while (*++argv);
713 }
714
715 // Call loopfiles_rw with O_RDONLY and !failok (common case).
716 void loopfiles(char **argv, void (*function)(int fd, char *name))
717 {
718         loopfiles_rw(argv, O_RDONLY, 0, 0, function);
719 }
720
721 // Slow, but small.
722
723 char *get_rawline(int fd, long *plen, char end)
724 {
725         char c, *buf = NULL;
726         long len = 0;
727
728         for (;;) {
729                 if (1>read(fd, &c, 1)) break;
730                 if (!(len & 63)) buf=xrealloc(buf, len+65);
731                 if ((buf[len++]=c) == end) break;
732         }
733         if (buf) buf[len]=0;
734         if (plen) *plen = len;
735
736         return buf;
737 }
738
739 char *get_line(int fd)
740 {
741         long len;
742         char *buf = get_rawline(fd, &len, '\n');
743
744         if (buf && buf[--len]=='\n') buf[len]=0;
745
746         return buf;
747 }
748
749 // Copy the rest of in to out and close both files.
750
751 void xsendfile(int in, int out)
752 {
753         long len;
754         char buf[4096];
755
756         if (in<0) return;
757         for (;;) {
758                 len = xread(in, buf, 4096);
759                 if (len<1) break;
760                 xwrite(out, buf, len);
761         }
762 }
763
764 int wfchmodat(int fd, char *name, mode_t mode)
765 {
766         int rc = fchmodat(fd, name, mode, 0);
767
768         if (rc) {
769                 perror_msg("chmod '%s' to %04o", name, mode);
770                 toys.exitval=1;
771         }
772         return rc;
773 }
774
775 // Open a temporary file to copy an existing file into.
776 int copy_tempfile(int fdin, char *name, char **tempname)
777 {
778         struct stat statbuf;
779         int fd;
780
781         *tempname = xstrndup(name, strlen(name)+6);
782         strcat(*tempname,"XXXXXX");
783         if(-1 == (fd = mkstemp(*tempname))) error_exit("no temp file");
784
785         // Set permissions of output file
786
787         fstat(fdin, &statbuf);
788         fchmod(fd, statbuf.st_mode);
789
790         return fd;
791 }
792
793 // Abort the copy and delete the temporary file.
794 void delete_tempfile(int fdin, int fdout, char **tempname)
795 {
796         close(fdin);
797         close(fdout);
798         unlink(*tempname);
799         free(*tempname);
800         *tempname = NULL;
801 }
802
803 // Copy the rest of the data and replace the original with the copy.
804 void replace_tempfile(int fdin, int fdout, char **tempname)
805 {
806         char *temp = xstrdup(*tempname);
807
808         temp[strlen(temp)-6]=0;
809         if (fdin != -1) {
810                 xsendfile(fdin, fdout);
811                 xclose(fdin);
812         }
813         xclose(fdout);
814         rename(*tempname, temp);
815         free(*tempname);
816         free(temp);
817         *tempname = NULL;
818 }
819
820 // Create a 256 entry CRC32 lookup table.
821
822 void crc_init(unsigned int *crc_table, int little_endian)
823 {
824         unsigned int i;
825
826         // Init the CRC32 table (big endian)
827         for (i=0; i<256; i++) {
828                 unsigned int j, c = little_endian ? i : i<<24;
829                 for (j=8; j; j--)
830                         if (little_endian) c = (c&1) ? (c>>1)^0xEDB88320 : c>>1;
831                         else c=c&0x80000000 ? (c<<1)^0x04c11db7 : (c<<1);
832                 crc_table[i] = c;
833         }
834 }
835
836 // Quick and dirty query size of terminal, doesn't do ANSI probe fallback.
837 // set *x=0 and *y=0 before calling to detect failure to set either, or
838 // x=80 y=25 to provide defaults
839
840 void terminal_size(unsigned *x, unsigned *y)
841 {
842         struct winsize ws;
843         int i;
844
845         //memset(&ws, 0, sizeof(ws));
846         for (i=0; i<3; i++) {
847                 if (ioctl(i, TIOCGWINSZ, &ws)) continue;
848                 if (x) *x = ws.ws_col;
849                 if (y) *y = ws.ws_row;
850         }
851         if (x) {
852                 char *s = getenv("COLUMNS");
853
854                 i = s ? atoi(s) : 0;
855                 if (i>0) *x = i;
856         }
857         if (y) {
858                 char *s = getenv("ROWS");
859
860                 i = s ? atoi(s) : 0;
861                 if (i>0) *y = i;
862         }
863 }
864
865 // This should use a raw tty, fixit later.
866 int yesno(char *prompt, int def)
867 {
868         FILE *fps[] = {stdin, stdout, stderr};
869         int i;
870         char buf;
871
872         for (i=0; i<3; i++) if (isatty(i)) break;
873         if (i == 3) return 1;
874
875         fprintf(fps[i], "%s (%c/%c):", prompt, def ? 'Y' : 'y', def ? 'n' : 'N');
876         fflush(fps[i]);
877         while (fread(&buf, 1, 1, fps[i])) {
878                 if (tolower(buf) == 'y') def = 1;
879                 if (tolower(buf) == 'n') def = 0;
880                 else if (!isspace(buf)) continue;
881
882                 break;
883         }
884
885         return def;
886 }
887
888 // Execute a callback for each PID that matches a process name from a list.
889 void for_each_pid_with_name_in(char **names, void (*callback)(pid_t pid))
890 {
891     DIR *dp;
892     struct dirent *entry;
893     char cmd[sizeof(toybuf)], path[64];
894     char **curname;
895
896     if (!(dp = opendir("/proc"))) perror_exit("opendir");
897
898     while ((entry = readdir(dp))) {
899         int fd, n;
900
901         if (!isdigit(*entry->d_name)) continue;
902
903         if (sizeof(path) <= snprintf(path, sizeof(path), "/proc/%s/cmdline", 
904             entry->d_name)) continue;
905
906         if (-1 == (fd=open(path, O_RDONLY))) continue;
907         n = read(fd, cmd, sizeof(cmd));
908         close(fd);
909         if (n<1) continue;
910
911         for (curname = names; *curname; curname++)
912             if (!strcmp(basename(cmd), *curname))
913                 callback(atol(entry->d_name));
914     }
915
916     closedir(dp);
917 }
918
919 struct signame {
920         int num;
921         char *name;
922 };
923
924 // Signals required by POSIX 2008:
925 // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
926
927 #define SIGNIFY(x) {SIG##x, #x}
928
929 static struct signame signames[] = {
930         SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS), SIGNIFY(CHLD), SIGNIFY(CONT),
931         SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL),
932         SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(STOP), SIGNIFY(TERM),
933         SIGNIFY(TSTP), SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(USR1), SIGNIFY(USR2),
934         SIGNIFY(SYS), SIGNIFY(TRAP), SIGNIFY(URG), SIGNIFY(VTALRM), SIGNIFY(XCPU),
935         SIGNIFY(XFSZ)
936 };
937
938 // not in posix: SIGNIFY(STKFLT), SIGNIFY(WINCH), SIGNIFY(IO), SIGNIFY(PWR)
939 // obsolete: SIGNIFY(PROF) SIGNIFY(POLL)
940
941 // Convert name to signal number.  If name == NULL print names.
942 int sig_to_num(char *pidstr)
943 {
944         int i;
945
946         if (pidstr) {
947                 char *s;
948                 i = strtol(pidstr, &s, 10);
949                 if (!*s) return i;
950
951                 if (!strncasecmp(pidstr, "sig", 3)) pidstr+=3;
952         }
953         for (i = 0; i < sizeof(signames)/sizeof(struct signame); i++)
954                 if (!pidstr) xputs(signames[i].name);
955                 else if (!strcasecmp(pidstr, signames[i].name))
956                         return signames[i].num;
957
958         return -1;
959 }
960
961 char *num_to_sig(int sig)
962 {
963         int i;
964
965         for (i=0; i<sizeof(signames)/sizeof(struct signame); i++)
966                 if (signames[i].num == sig) return signames[i].name;
967         return NULL;
968 }
969
970
971 mode_t string_to_mode(char *modestr, mode_t mode)
972 {
973         char *whos = "ogua", *hows = "=+-", *whats = "xwrstX", *whys = "ogu";
974         char *s, *str = modestr;
975
976         // Handle octal mode
977         if (isdigit(*str)) {
978                 mode = strtol(str, &s, 8);
979                 if (*s || (mode & ~(07777))) goto barf;
980
981                 return mode;
982         }
983
984         // Gaze into the bin of permission...
985         for (;;) {
986                 int i, j, dowho, dohow, dowhat, amask;
987
988                 dowho = dohow = dowhat = amask = 0;
989
990                 // Find the who, how, and what stanzas, in that order
991                 while (*str && (s = strchr(whos, *str))) {
992                         dowho |= 1<<(s-whos);
993                         str++;
994                 }
995                 // If who isn't specified, like "a" but honoring umask.
996                 if (!dowho) {
997                         dowho = 8;
998                         umask(amask=umask(0));
999                 }
1000                 if (!*str || !(s = strchr(hows, *str))) goto barf;
1001                 dohow = *(str++);
1002
1003                 if (!dohow) goto barf;
1004                 while (*str && (s = strchr(whats, *str))) {
1005                         dowhat |= 1<<(s-whats);
1006                         str++;
1007                 }
1008
1009                 // Convert X to x for directory or if already executable somewhere
1010                 if ((dowhat&32) &&  (S_ISDIR(mode) || (mode&0111))) dowhat |= 1;
1011
1012                 // Copy mode from another category?
1013                 if (!dowhat && *str && (s = strchr(whys, *str))) {
1014                         dowhat = (mode>>(3*(s-whys)))&7;
1015                         str++;
1016                 }
1017
1018                 // Are we ready to do a thing yet?
1019                 if (*str && *(str++) != ',') goto barf;
1020
1021                 // Ok, apply the bits to the mode.
1022                 for (i=0; i<4; i++) {
1023                         for (j=0; j<3; j++) {
1024                                 mode_t bit = 0;
1025                                 int where = 1<<((3*i)+j);
1026
1027                                 if (amask & where) continue;
1028
1029                                 // Figure out new value at this location
1030                                 if (i == 3) {
1031                                         // suid/sticky bit.
1032                                         if (j) {
1033                                                 if ((dowhat & 8) && (dowho&(8|(1<<i)))) bit++;
1034                                         } else if (dowhat & 16) bit++;
1035                                 } else {
1036                                         if (!(dowho&(8|(1<<i)))) continue;
1037                                         if (dowhat&(1<<j)) bit++;
1038                                 }
1039
1040                                 // When selection active, modify bit
1041
1042                                 if (dohow == '=' || (bit && dohow == '-'))
1043                                         mode &= ~where;
1044                                 if (bit && dohow != '-') mode |= where;
1045                         }
1046                 }
1047
1048                 if (!*str) break;
1049         }
1050         return mode;
1051 barf:
1052         error_exit("bad mode '%s'", modestr);
1053 }