From 7aa651a6a4496d848f86de9b1e6b3a003256a01f Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 13 Nov 2012 17:14:08 -0600 Subject: Reindent to two spaces per level. Remove vi: directives that haven't worked right in years (ubuntu broke its' vim implementation). Remove trailing spaces. Add/remove blank lines. Re-wordwrap in places. Update documentation with new coding style. The actual code should be the same afterward, this is just cosmetic refactoring. --- lib/args.c | 633 ++++++++++++----------- lib/bunzip.c | 1039 +++++++++++++++++++------------------ lib/dirtree.c | 206 ++++---- lib/getmountlist.c | 47 +- lib/lib.c | 1217 ++++++++++++++++++++++---------------------- lib/lib.h | 43 +- lib/llist.c | 51 +- lib/password.c | 238 +++++---- lib/portability.c | 93 ++-- lib/xregcomp.c | 17 +- main.c | 169 +++--- scripts/config2help.sh | 4 +- scripts/install.c | 31 +- scripts/test/basename.test | 2 +- scripts/test/cat.test | 2 +- scripts/test/cp.test | 2 +- scripts/test/dirname.test | 2 +- scripts/test/xargs.test | 2 +- toys.h | 25 +- toys/e2fs.h | 196 ++++--- toys/lsb/dmesg.c | 69 ++- toys/lsb/hostname.c | 31 +- toys/lsb/killall.c | 79 ++- toys/lsb/md5sum.c | 7 +- toys/lsb/mknod.c | 47 +- toys/lsb/mktemp.c | 54 +- toys/lsb/passwd.c | 389 +++++++------- toys/lsb/pidof.c | 27 +- toys/lsb/seq.c | 58 +-- toys/lsb/sync.c | 16 +- toys/other/bzcat.c | 18 +- toys/other/catv.c | 82 ++- toys/other/chroot.c | 21 +- toys/other/chvt.c | 48 +- toys/other/clear.c | 14 +- toys/other/count.c | 36 +- toys/other/dos2unix.c | 72 ++- toys/other/free.c | 76 ++- toys/other/hello.c | 52 +- toys/other/help.c | 44 +- toys/other/insmod.c | 53 +- toys/other/login.c | 286 +++++------ toys/other/lsmod.c | 48 +- toys/other/mdev.c | 346 +++++++------ toys/other/mke2fs.c | 1014 ++++++++++++++++++------------------ toys/other/mkswap.c | 42 +- toys/other/modinfo.c | 119 ++--- toys/other/mountpoint.c | 77 ++- toys/other/netcat.c | 355 +++++++------ toys/other/oneit.c | 45 +- toys/other/printenv.c | 55 +- toys/other/readlink.c | 46 +- toys/other/realpath.c | 29 +- toys/other/rmmod.c | 57 +-- toys/other/setsid.c | 29 +- toys/other/swapoff.c | 17 +- toys/other/swapon.c | 26 +- toys/other/switch_root.c | 130 ++--- toys/other/tac.c | 68 ++- toys/other/taskset.c | 144 +++--- toys/other/truncate.c | 43 +- toys/other/unshare.c | 46 +- toys/other/uptime.c | 67 ++- toys/other/usleep.c | 26 +- toys/other/vconfig.c | 193 ++++--- toys/other/vmstat.c | 317 ++++++------ toys/other/w.c | 35 +- toys/other/which.c | 81 ++- toys/other/whoami.c | 28 +- toys/other/yes.c | 32 +- toys/posix/basename.c | 50 +- toys/posix/cal.c | 206 ++++---- toys/posix/cat.c | 40 +- toys/posix/chgrp.c | 174 ++++--- toys/posix/chmod.c | 68 ++- toys/posix/cksum.c | 107 ++-- toys/posix/cmp.c | 110 ++-- toys/posix/comm.c | 105 ++-- toys/posix/cp.c | 354 +++++++------ toys/posix/date.c | 138 +++-- toys/posix/df.c | 263 +++++----- toys/posix/dirname.c | 16 +- toys/posix/du.c | 282 +++++----- toys/posix/echo.c | 132 +++-- toys/posix/env.c | 64 ++- toys/posix/false.c | 14 +- toys/posix/head.c | 67 ++- toys/posix/id.c | 156 +++--- toys/posix/kill.c | 87 ++-- toys/posix/link.c | 20 +- toys/posix/ln.c | 86 ++-- toys/posix/logname.c | 20 +- toys/posix/ls.c | 705 +++++++++++++------------ toys/posix/mkdir.c | 78 ++- toys/posix/mkfifo.c | 44 +- toys/posix/nice.c | 32 +- toys/posix/nohup.c | 50 +- toys/posix/od.c | 434 ++++++++-------- toys/posix/patch.c | 664 ++++++++++++------------ toys/posix/pwd.c | 20 +- toys/posix/rmdir.c | 42 +- toys/posix/sed.c | 133 +++-- toys/posix/sh.c | 484 +++++++++--------- toys/posix/sleep.c | 60 ++- toys/posix/sort.c | 591 +++++++++++---------- toys/posix/tail.c | 348 +++++++------ toys/posix/tee.c | 73 ++- toys/posix/true.c | 14 +- toys/posix/tty.c | 24 +- toys/posix/uname.c | 72 ++- toys/posix/uniq.c | 189 ++++--- toys/posix/unlink.c | 18 +- toys/posix/wc.c | 126 +++-- toys/posix/who.c | 43 +- toys/posix/xargs.c | 312 ++++++------ www/code.html | 9 +- www/design.html | 4 +- 117 files changed, 7996 insertions(+), 8245 deletions(-) mode change 100644 => 100755 scripts/test/dirname.test diff --git a/lib/args.c b/lib/args.c index 2f6132ab..b7119651 100644 --- a/lib/args.c +++ b/lib/args.c @@ -1,5 +1,4 @@ -/* vi: set sw=4 ts=4 : - * args.c - Command line argument parsing. +/* args.c - Command line argument parsing. * * Copyright 2006 Rob Landley */ @@ -34,6 +33,7 @@ // ~X enabling this disables X (switch off) // !X die with error if X already set (x!x die if x supplied twice) // [yz] needs at least one of y or z. TODO +// // at the beginning: // ^ stop at first nonoption argument // <0 die if less than # leftover arguments (default 0) @@ -48,19 +48,19 @@ // - is a synonym for stdin in file arguments // -abc means -a -b -c -/* This uses a getopt-like option string, but not getopt() itself. We call +/* This uses a getopt-like option string, but not getopt() itself. We call * it the get_opt string. * * Each option in the get_opt string corresponds to a bit position in the - * return value. The rightmost argument is (1<<0), the next to last is (1<<1) - * and so on. If the option isn't seen in argv[], its bit remains 0. + * return value. The rightmost argument is (1<<0), the next to last is (1<<1) + * and so on. If the option isn't seen in argv[], its bit remains 0. * * Options which have an argument fill in the corresponding slot in the global * union "this" (see generated/globals.h), which it treats as an array of longs * (note that sizeof(long)==sizeof(pointer) is guaranteed by LP64). * * You don't have to free the option strings, which point into the environment - * space. List objects should be freed by main() when command_main() returns. + * space. List objects should be freed by main() when command_main() returns. * * Example: * Calling get_optflags() when toys.which->options="ab:c:d" and @@ -79,343 +79,334 @@ // Linked list of all known options (get_opt string is parsed into this). struct opts { - struct opts *next; - long *arg; // Pointer into union "this" to store arguments at. - uint32_t edx[3]; // Flag mask to enable/disable/exclude. - int c; // Short argument character - int flags; // |=1, ^=2 - char type; // Type of arguments to store - union { - long l; - FLOAT f; - } val[3]; // low, high, default - range of allowed values + struct opts *next; + long *arg; // Pointer into union "this" to store arguments at. + uint32_t edx[3]; // Flag mask to enable/disable/exclude. + int c; // Short argument character + int flags; // |=1, ^=2 + char type; // Type of arguments to store + union { + long l; + FLOAT f; + } val[3]; // low, high, default - range of allowed values }; struct longopts { - struct longopts *next; - struct opts *opt; - char *str; - int len; + struct longopts *next; + struct opts *opt; + char *str; + int len; }; // State during argument parsing. struct getoptflagstate { - int argc, minargs, maxargs, nodash; - char *arg; - struct opts *opts, *this; - struct longopts *longopts; - int noerror, nodash_now, stopearly; - uint32_t excludes; + int argc, minargs, maxargs, nodash; + char *arg; + struct opts *opts, *this; + struct longopts *longopts; + int noerror, nodash_now, stopearly; + uint32_t excludes; }; // Parse one command line option. static int gotflag(struct getoptflagstate *gof) { - int type; - struct opts *opt = gof->this; - - // Did we recognize this option? - if (!opt) { - if (gof->noerror) return 1; - error_exit("Unknown option %s", gof->arg); - } - - // Set flags - toys.optflags |= opt->edx[0]; - toys.optflags &= ~opt->edx[1]; - gof->excludes = opt->edx[2]; - if (opt->flags&2) gof->stopearly=2; - - // Does this option take an argument? - gof->arg++; - type = opt->type; - if (type) { - char *arg = gof->arg; - - // Handle "-xblah" and "-x blah", but also a third case: "abxc blah" - // to make "tar xCjfv blah1 blah2 thingy" work like - // "tar -x -C blah1 -j -f blah2 -v thingy" - - if (gof->nodash_now || !arg[0]) arg = toys.argv[++gof->argc]; - // TODO: The following line doesn't display --longopt correctly - if (!arg) error_exit("Missing argument to -%c", opt->c); - - if (type == ':') *(opt->arg) = (long)arg; - else if (type == '*') { - struct arg_list **list; - - list = (struct arg_list **)opt->arg; - while (*list) list=&((*list)->next); - *list = xzalloc(sizeof(struct arg_list)); - (*list)->arg = arg; - } else if (type == '#' || type == '-') { - long l = atolx(arg); - if (type == '-' && !ispunct(*arg)) l*=-1; - if (l < opt->val[0].l) - error_exit("-%c < %ld", opt->c, opt->val[0].l); - if (l > opt->val[1].l) - error_exit("-%c > %ld", opt->c, opt->val[1].l); - - *(opt->arg) = l; - } else if (CFG_TOYBOX_FLOAT && type == '.') { - FLOAT *f = (FLOAT *)(opt->arg); - - *f = strtod(arg, &arg); - if (opt->val[0].l != LONG_MIN && *f < opt->val[0].f) - error_exit("-%c < %lf", opt->c, (double)opt->val[0].f); - if (opt->val[1].l != LONG_MAX && *f > opt->val[1].f) - error_exit("-%c > %lf", opt->c, (double)opt->val[1].f); - } else if (type == '@') ++*(opt->arg); - - if (!gof->nodash_now) gof->arg = ""; - } - - gof->this = NULL; - return 0; + int type; + struct opts *opt = gof->this; + + // Did we recognize this option? + if (!opt) { + if (gof->noerror) return 1; + error_exit("Unknown option %s", gof->arg); + } + + // Set flags + toys.optflags |= opt->edx[0]; + toys.optflags &= ~opt->edx[1]; + gof->excludes = opt->edx[2]; + if (opt->flags&2) gof->stopearly=2; + + // Does this option take an argument? + gof->arg++; + type = opt->type; + if (type) { + char *arg = gof->arg; + + // Handle "-xblah" and "-x blah", but also a third case: "abxc blah" + // to make "tar xCjfv blah1 blah2 thingy" work like + // "tar -x -C blah1 -j -f blah2 -v thingy" + + if (gof->nodash_now || !arg[0]) arg = toys.argv[++gof->argc]; + // TODO: The following line doesn't display --longopt correctly + if (!arg) error_exit("Missing argument to -%c", opt->c); + + if (type == ':') *(opt->arg) = (long)arg; + else if (type == '*') { + struct arg_list **list; + + list = (struct arg_list **)opt->arg; + while (*list) list=&((*list)->next); + *list = xzalloc(sizeof(struct arg_list)); + (*list)->arg = arg; + } else if (type == '#' || type == '-') { + long l = atolx(arg); + if (type == '-' && !ispunct(*arg)) l*=-1; + if (l < opt->val[0].l) error_exit("-%c < %ld", opt->c, opt->val[0].l); + if (l > opt->val[1].l) error_exit("-%c > %ld", opt->c, opt->val[1].l); + + *(opt->arg) = l; + } else if (CFG_TOYBOX_FLOAT && type == '.') { + FLOAT *f = (FLOAT *)(opt->arg); + + *f = strtod(arg, &arg); + if (opt->val[0].l != LONG_MIN && *f < opt->val[0].f) + error_exit("-%c < %lf", opt->c, (double)opt->val[0].f); + if (opt->val[1].l != LONG_MAX && *f > opt->val[1].f) + error_exit("-%c > %lf", opt->c, (double)opt->val[1].f); + } else if (type == '@') ++*(opt->arg); + + if (!gof->nodash_now) gof->arg = ""; + } + + gof->this = NULL; + return 0; } // Fill out toys.optflags and toys.optargs. void parse_optflaglist(struct getoptflagstate *gof) { - char *options = toys.which->options; - long *nextarg = (long *)&this; - struct opts *new = 0; - - // Parse option format string - memset(gof, 0, sizeof(struct getoptflagstate)); - gof->maxargs = INT_MAX; - if (!options) return; - - // Parse leading special behavior indicators - for (;;) { - if (*options == '^') gof->stopearly++; - else if (*options == '<') gof->minargs=*(++options)-'0'; - else if (*options == '>') gof->maxargs=*(++options)-'0'; - else if (*options == '?') gof->noerror++; - else if (*options == '&') gof->nodash++; - else break; - options++; - } - - // Parse the rest of the option string into a linked list - // of options with attributes. - - if (!*options) gof->stopearly++; - while (*options) { - char *temp; - int idx; - - // Allocate a new list entry when necessary - if (!new) { - new = xzalloc(sizeof(struct opts)); - new->next = gof->opts; - gof->opts = new; - new->val[0].l = LONG_MIN; - new->val[1].l = LONG_MAX; - ++*(new->edx); - } - // Each option must start with "(" or an option character. (Bare - // longopts only come at the start of the string.) - if (*options == '(') { - char *end; - struct longopts *lo = xmalloc(sizeof(struct longopts)); - - // Find the end of the longopt - for (end = ++options; *end && *end != ')'; end++); - if (CFG_TOYBOX_DEBUG && !*end) - error_exit("(longopt) didn't end"); - - // init a new struct longopts - lo->next = gof->longopts; - lo->opt = new; - lo->str = options; - lo->len = end-options; - gof->longopts = lo; - options = end; - - // Mark this struct opt as used, even when no short opt. - if (!new->c) new->c = -1; - - // If this is the start of a new option that wasn't a longopt, - - } else if (strchr(":*#@.-", *options)) { - if (CFG_TOYBOX_DEBUG && new->type) - error_exit("multiple types %c:%c%c", new->c, new->type, *options); - new->type = *options; - } else if (-1 != (idx = stridx("+~!", *options))) { - struct opts *opt; - int i; - - if (!*++options && CFG_TOYBOX_DEBUG) - error_exit("+~! no target"); - // Find this option flag (in previously parsed struct opt) - for (i=0, opt = new; ; opt = opt->next) { - if (CFG_TOYBOX_DEBUG && !opt) - error_exit("+~! unknown target"); - if (opt->c == *options) break; - i++; - } - new->edx[idx] |= 1<flags |= 1<=", *options))) { - if (new->type == '#') { - long l = strtol(++options, &temp, 10); - if (temp != options) new->val[idx].l = l; - } else if (CFG_TOYBOX_FLOAT && new->type == '.') { - FLOAT f = strtod(++options, &temp); - if (temp != options) new->val[idx].f = f; - } else if (CFG_TOYBOX_DEBUG) error_exit("<>= only after .#"); - options = --temp; - } - - // At this point, we've hit the end of the previous option. The - // current character is the start of a new option. If we've already - // assigned an option to this struct, loop to allocate a new one. - // (It'll get back here afterwards and fall through to next else.) - else if (new->c) { - new = NULL; - continue; - - // Claim this option, loop to see what's after it. - } else new->c = *options; - - options++; - } - - // Initialize enable/disable/exclude masks and pointers to store arguments. - // (We have to calculate all this ahead of time because longopts jump into - // the middle of the list. We have to do this after creating the list - // because we reverse direction: last entry created gets first global slot.) - int pos = 0; - for (new = gof->opts; new; new = new->next) { - int i; - - for (i=0;i<3;i++) new->edx[i] <<= pos; - pos++; - if (new->type) { - new->arg = (void *)nextarg; - *(nextarg++) = new->val[2].l; - } - } + char *options = toys.which->options; + long *nextarg = (long *)&this; + struct opts *new = 0; + + // Parse option format string + memset(gof, 0, sizeof(struct getoptflagstate)); + gof->maxargs = INT_MAX; + if (!options) return; + + // Parse leading special behavior indicators + for (;;) { + if (*options == '^') gof->stopearly++; + else if (*options == '<') gof->minargs=*(++options)-'0'; + else if (*options == '>') gof->maxargs=*(++options)-'0'; + else if (*options == '?') gof->noerror++; + else if (*options == '&') gof->nodash++; + else break; + options++; + } + + // Parse the rest of the option string into a linked list + // of options with attributes. + + if (!*options) gof->stopearly++; + while (*options) { + char *temp; + int idx; + + // Allocate a new list entry when necessary + if (!new) { + new = xzalloc(sizeof(struct opts)); + new->next = gof->opts; + gof->opts = new; + new->val[0].l = LONG_MIN; + new->val[1].l = LONG_MAX; + ++*(new->edx); + } + // Each option must start with "(" or an option character. (Bare + // longopts only come at the start of the string.) + if (*options == '(') { + char *end; + struct longopts *lo = xmalloc(sizeof(struct longopts)); + + // Find the end of the longopt + for (end = ++options; *end && *end != ')'; end++); + if (CFG_TOYBOX_DEBUG && !*end) error_exit("(longopt) didn't end"); + + // init a new struct longopts + lo->next = gof->longopts; + lo->opt = new; + lo->str = options; + lo->len = end-options; + gof->longopts = lo; + options = end; + + // Mark this struct opt as used, even when no short opt. + if (!new->c) new->c = -1; + + // If this is the start of a new option that wasn't a longopt, + + } else if (strchr(":*#@.-", *options)) { + if (CFG_TOYBOX_DEBUG && new->type) + error_exit("multiple types %c:%c%c", new->c, new->type, *options); + new->type = *options; + } else if (-1 != (idx = stridx("+~!", *options))) { + struct opts *opt; + int i; + + if (!*++options && CFG_TOYBOX_DEBUG) error_exit("+~! no target"); + // Find this option flag (in previously parsed struct opt) + for (i=0, opt = new; ; opt = opt->next) { + if (CFG_TOYBOX_DEBUG && !opt) error_exit("+~! unknown target"); + if (opt->c == *options) break; + i++; + } + new->edx[idx] |= 1<flags |= 1<=", *options))) { + if (new->type == '#') { + long l = strtol(++options, &temp, 10); + if (temp != options) new->val[idx].l = l; + } else if (CFG_TOYBOX_FLOAT && new->type == '.') { + FLOAT f = strtod(++options, &temp); + if (temp != options) new->val[idx].f = f; + } else if (CFG_TOYBOX_DEBUG) error_exit("<>= only after .#"); + options = --temp; + } + + // At this point, we've hit the end of the previous option. The + // current character is the start of a new option. If we've already + // assigned an option to this struct, loop to allocate a new one. + // (It'll get back here afterwards and fall through to next else.) + else if (new->c) { + new = NULL; + continue; + + // Claim this option, loop to see what's after it. + } else new->c = *options; + + options++; + } + + // Initialize enable/disable/exclude masks and pointers to store arguments. + // (We have to calculate all this ahead of time because longopts jump into + // the middle of the list. We have to do this after creating the list + // because we reverse direction: last entry created gets first global slot.) + int pos = 0; + for (new = gof->opts; new; new = new->next) { + int i; + + for (i=0;i<3;i++) new->edx[i] <<= pos; + pos++; + if (new->type) { + new->arg = (void *)nextarg; + *(nextarg++) = new->val[2].l; + } + } } void get_optflags(void) { - struct getoptflagstate gof; - long saveflags; - char *letters[]={"s",""}; - - // Option parsing is a two stage process: parse the option string into - // a struct opts list, then use that list to process argv[]; - - if (CFG_HELP) toys.exithelp++; - // Allocate memory for optargs - saveflags = 0; - while (toys.argv[saveflags++]); - toys.optargs = xzalloc(sizeof(char *)*saveflags); - - parse_optflaglist(&gof); - - // Iterate through command line arguments, skipping argv[0] - for (gof.argc=1; toys.argv[gof.argc]; gof.argc++) { - gof.arg = toys.argv[gof.argc]; - gof.this = NULL; - - // Parse this argument - if (gof.stopearly>1) goto notflag; - - gof.nodash_now = 0; - - // Various things with dashes - if (*gof.arg == '-') { - - // Handle - - if (!gof.arg[1]) goto notflag; - gof.arg++; - if (*gof.arg=='-') { - struct longopts *lo; - - gof.arg++; - // Handle -- - if (!*gof.arg) { - gof.stopearly += 2; - goto notflag; - } - // Handle --longopt - - for (lo = gof.longopts; lo; lo = lo->next) { - if (!strncmp(gof.arg, lo->str, lo->len)) { - if (gof.arg[lo->len]) { - if (gof.arg[lo->len]=='=' && lo->opt->type) - gof.arg += lo->len; - else continue; - } - // It's a match. - gof.arg = ""; - gof.this = lo->opt; - break; - } - } - - // Should we handle this --longopt as a non-option argument? - if (!lo && gof.noerror) { - gof.arg-=2; - goto notflag; - } - - // Long option parsed, handle option. - gotflag(&gof); - continue; - } - - // Handle things that don't start with a dash. - } else { - if (gof.nodash && (gof.nodash>1 || gof.argc == 1)) - gof.nodash_now = 1; - else goto notflag; - } - - // At this point, we have the args part of -args. Loop through - // each entry (could be -abc meaning -a -b -c) - saveflags = toys.optflags; - while (*gof.arg) { - - // Identify next option char. - for (gof.this = gof.opts; gof.this; gof.this = gof.this->next) - if (*gof.arg == gof.this->c) - if (!((gof.this->flags&4) && gof.arg[1])) break; - - // Handle option char (advancing past what was used) - if (gotflag(&gof) ) { - toys.optflags = saveflags; - gof.arg = toys.argv[gof.argc]; - goto notflag; - } - } - continue; - - // Not a flag, save value in toys.optargs[] + struct getoptflagstate gof; + long saveflags; + char *letters[]={"s",""}; + + // Option parsing is a two stage process: parse the option string into + // a struct opts list, then use that list to process argv[]; + + if (CFG_HELP) toys.exithelp++; + // Allocate memory for optargs + saveflags = 0; + while (toys.argv[saveflags++]); + toys.optargs = xzalloc(sizeof(char *)*saveflags); + + parse_optflaglist(&gof); + + // Iterate through command line arguments, skipping argv[0] + for (gof.argc=1; toys.argv[gof.argc]; gof.argc++) { + gof.arg = toys.argv[gof.argc]; + gof.this = NULL; + + // Parse this argument + if (gof.stopearly>1) goto notflag; + + gof.nodash_now = 0; + + // Various things with dashes + if (*gof.arg == '-') { + + // Handle - + if (!gof.arg[1]) goto notflag; + gof.arg++; + if (*gof.arg=='-') { + struct longopts *lo; + + gof.arg++; + // Handle -- + if (!*gof.arg) { + gof.stopearly += 2; + goto notflag; + } + // Handle --longopt + + for (lo = gof.longopts; lo; lo = lo->next) { + if (!strncmp(gof.arg, lo->str, lo->len)) { + if (gof.arg[lo->len]) { + if (gof.arg[lo->len]=='=' && lo->opt->type) gof.arg += lo->len; + else continue; + } + // It's a match. + gof.arg = ""; + gof.this = lo->opt; + break; + } + } + + // Should we handle this --longopt as a non-option argument? + if (!lo && gof.noerror) { + gof.arg-=2; + goto notflag; + } + + // Long option parsed, handle option. + gotflag(&gof); + continue; + } + + // Handle things that don't start with a dash. + } else { + if (gof.nodash && (gof.nodash>1 || gof.argc == 1)) gof.nodash_now = 1; + else goto notflag; + } + + // At this point, we have the args part of -args. Loop through + // each entry (could be -abc meaning -a -b -c) + saveflags = toys.optflags; + while (*gof.arg) { + + // Identify next option char. + for (gof.this = gof.opts; gof.this; gof.this = gof.this->next) + if (*gof.arg == gof.this->c) + if (!((gof.this->flags&4) && gof.arg[1])) break; + + // Handle option char (advancing past what was used) + if (gotflag(&gof) ) { + toys.optflags = saveflags; + gof.arg = toys.argv[gof.argc]; + goto notflag; + } + } + continue; + + // Not a flag, save value in toys.optargs[] notflag: - if (gof.stopearly) gof.stopearly++; - toys.optargs[toys.optc++] = toys.argv[gof.argc]; - } - - // Sanity check - if (toys.optcgof.maxargs) - error_exit("Max %d argument%s", gof.maxargs, letters[!(gof.maxargs-1)]); - if (CFG_HELP) toys.exithelp = 0; - - if (CFG_TOYBOX_FREE) { - llist_traverse(gof.opts, free); - llist_traverse(gof.longopts, free); - } + if (gof.stopearly) gof.stopearly++; + toys.optargs[toys.optc++] = toys.argv[gof.argc]; + } + + // Sanity check + if (toys.optcgof.maxargs) + error_exit("Max %d argument%s", gof.maxargs, letters[!(gof.maxargs-1)]); + if (CFG_HELP) toys.exithelp = 0; + + if (CFG_TOYBOX_FREE) { + llist_traverse(gof.opts, free); + llist_traverse(gof.longopts, free); + } } diff --git a/lib/bunzip.c b/lib/bunzip.c index f860aa64..2836d38c 100644 --- a/lib/bunzip.c +++ b/lib/bunzip.c @@ -1,14 +1,13 @@ -/* vi: set sw=4 ts=4: */ /* micro-bunzip, a small, simple bzip2 decompression implementation. - - Copyright 2003, 2006 by Rob Landley (rob@landley.net). - - Based on a close reading (but not the actual code) of the original bzip2 - decompression code by Julian R Seward (jseward@acm.org), which also - acknowledges contributions by Mike Burrows, David Wheeler, Peter Fenwick, - Alistair Moffat, Radford Neal, Ian H. Witten, Robert Sedgewick, and - Jon L. Bentley. -*/ + * + * Copyright 2003, 2006 by Rob Landley (rob@landley.net). + * + * Based on a close reading (but not the actual code) of the original bzip2 + * decompression code by Julian R Seward (jseward@acm.org), which also + * acknowledges contributions by Mike Burrows, David Wheeler, Peter Fenwick, + * Alistair Moffat, Radford Neal, Ian H. Witten, Robert Sedgewick, and + * Jon L. Bentley. + */ #include "toys.h" @@ -32,93 +31,92 @@ #define RETVAL_OBSOLETE_INPUT (-3) char *bunzip_errors[]={ - NULL, - "Not bzip data", - "Data error", - "Obsolete (pre 0.9.5) bzip format not supported." + NULL, + "Not bzip data", + "Data error", + "Obsolete (pre 0.9.5) bzip format not supported." }; // This is what we know about each huffman coding group struct group_data { - int limit[MAX_HUFCODE_BITS+1], base[MAX_HUFCODE_BITS], permute[MAX_SYMBOLS]; - char minLen, maxLen; + int limit[MAX_HUFCODE_BITS+1], base[MAX_HUFCODE_BITS], permute[MAX_SYMBOLS]; + char minLen, maxLen; }; // Data for burrows wheeler transform struct bwdata { - unsigned int origPtr; - int byteCount[256]; - // State saved when interrupting output - int writePos, writeRun, writeCount, writeCurrent; - unsigned int dataCRC, headerCRC; - unsigned int *dbuf; + unsigned int origPtr; + int byteCount[256]; + // State saved when interrupting output + int writePos, writeRun, writeCount, writeCurrent; + unsigned int dataCRC, headerCRC; + unsigned int *dbuf; }; // Structure holding all the housekeeping data, including IO buffers and // memory that persists between calls to bunzip struct bunzip_data { + // Input stream, input buffer, input bit buffer + int in_fd, inbufCount, inbufPos; + char *inbuf; + unsigned int inbufBitCount, inbufBits; - // Input stream, input buffer, input bit buffer - int in_fd, inbufCount, inbufPos; - char *inbuf; - unsigned int inbufBitCount, inbufBits; - - // Output buffer - char outbuf[IOBUF_SIZE]; - int outbufPos; + // Output buffer + char outbuf[IOBUF_SIZE]; + int outbufPos; - unsigned int totalCRC; + unsigned int totalCRC; - // First pass decompression data (Huffman and MTF decoding) - char selectors[32768]; // nSelectors=15 bits - struct group_data groups[MAX_GROUPS]; // huffman coding tables - int symTotal, groupCount, nSelectors; - unsigned char symToByte[256], mtfSymbol[256]; + // First pass decompression data (Huffman and MTF decoding) + char selectors[32768]; // nSelectors=15 bits + struct group_data groups[MAX_GROUPS]; // huffman coding tables + int symTotal, groupCount, nSelectors; + unsigned char symToByte[256], mtfSymbol[256]; - // The CRC values stored in the block header and calculated from the data - unsigned int crc32Table[256]; + // The CRC values stored in the block header and calculated from the data + unsigned int crc32Table[256]; - // Second pass decompression data (burrows-wheeler transform) - unsigned int dbufSize; - struct bwdata bwdata[THREADS]; + // Second pass decompression data (burrows-wheeler transform) + unsigned int dbufSize; + struct bwdata bwdata[THREADS]; }; // Return the next nnn bits of input. All reads from the compressed input // are done through this function. All reads are big endian. static unsigned int get_bits(struct bunzip_data *bd, char bits_wanted) { - unsigned int bits = 0; - - // If we need to get more data from the byte buffer, do so. (Loop getting - // one byte at a time to enforce endianness and avoid unaligned access.) - while (bd->inbufBitCount < bits_wanted) { - - // If we need to read more data from file into byte buffer, do so - if (bd->inbufPos == bd->inbufCount) { - if (0 >= (bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE))) - error_exit("Unexpected input EOF"); - bd->inbufPos = 0; - } - - // Avoid 32-bit overflow (dump bit buffer to top of output) - if (bd->inbufBitCount>=24) { - bits = bd->inbufBits&((1<inbufBitCount)-1); - bits_wanted -= bd->inbufBitCount; - bits <<= bits_wanted; - bd->inbufBitCount = 0; - } - - // Grab next 8 bits of input from buffer. - bd->inbufBits = (bd->inbufBits<<8) | bd->inbuf[bd->inbufPos++]; - bd->inbufBitCount += 8; - } - - // Calculate result - bd->inbufBitCount -= bits_wanted; - bits |= (bd->inbufBits>>bd->inbufBitCount) & ((1<inbufBitCount < bits_wanted) { + + // If we need to read more data from file into byte buffer, do so + if (bd->inbufPos == bd->inbufCount) { + if (0 >= (bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE))) + error_exit("Unexpected input EOF"); + bd->inbufPos = 0; + } + + // Avoid 32-bit overflow (dump bit buffer to top of output) + if (bd->inbufBitCount>=24) { + bits = bd->inbufBits&((1<inbufBitCount)-1); + bits_wanted -= bd->inbufBitCount; + bits <<= bits_wanted; + bd->inbufBitCount = 0; + } + + // Grab next 8 bits of input from buffer. + bd->inbufBits = (bd->inbufBits<<8) | bd->inbuf[bd->inbufPos++]; + bd->inbufBitCount += 8; + } + + // Calculate result + bd->inbufBitCount -= bits_wanted; + bits |= (bd->inbufBits>>bd->inbufBitCount) & ((1<headerCRC = get_bits(bd,32); - - // Is this the EOF block with CRC for whole file? (Constant is "e") - if (ii==0x177245 && jj==0x385090) return RETVAL_LAST_BLOCK; - - // Is this a valid data block? (Constant is "pi".) - if (ii!=0x314159 || jj!=0x265359) return RETVAL_NOT_BZIP_DATA; - - // We can add support for blockRandomised if anybody complains. - if (get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT; - if ((bw->origPtr = get_bits(bd,24)) > bd->dbufSize) - return RETVAL_DATA_ERROR; - - // mapping table: if some byte values are never used (encoding things - // like ascii text), the compression code removes the gaps to have fewer - // symbols to deal with, and writes a sparse bitfield indicating which - // values were present. We make a translation table to convert the symbols - // back to the corresponding bytes. - hh = get_bits(bd, 16); - bd->symTotal = 0; - for (ii=0; ii<16; ii++) { - if (hh & (1 << (15 - ii))) { - kk = get_bits(bd, 16); - for (jj=0; jj<16; jj++) - if (kk & (1 << (15 - jj))) - bd->symToByte[bd->symTotal++] = (16 * ii) + jj; - } - } - - // How many different huffman coding groups does this block use? - bd->groupCount = get_bits(bd,3); - if (bd->groupCount<2 || bd->groupCount>MAX_GROUPS) return RETVAL_DATA_ERROR; - - // nSelectors: Every GROUP_SIZE many symbols we switch huffman coding - // tables. Each group has a selector, which is an index into the huffman - // coding table arrays. - // - // Read in the group selector array, which is stored as MTF encoded - // bit runs. (MTF = Move To Front. Every time a symbol occurs it's moved - // to the front of the table, so it has a shorter encoding next time.) - if (!(bd->nSelectors = get_bits(bd, 15))) return RETVAL_DATA_ERROR; - for (ii=0; iigroupCount; ii++) bd->mtfSymbol[ii] = ii; - for (ii=0; iinSelectors; ii++) { - - // Get next value - for(jj=0;get_bits(bd,1);jj++) - if (jj>=bd->groupCount) return RETVAL_DATA_ERROR; - - // Decode MTF to get the next selector, and move it to the front. - uc = bd->mtfSymbol[jj]; - memmove(bd->mtfSymbol+1, bd->mtfSymbol, jj); - bd->mtfSymbol[0] = bd->selectors[ii] = uc; - } - - // Read the huffman coding tables for each group, which code for symTotal - // literal symbols, plus two run symbols (RUNA, RUNB) - symCount = bd->symTotal+2; - for (jj=0; jjgroupCount; jj++) { - unsigned char length[MAX_SYMBOLS]; - unsigned temp[MAX_HUFCODE_BITS+1]; - int minLen, maxLen, pp; - - // Read lengths - hh = get_bits(bd, 5); - for (ii = 0; ii < symCount; ii++) { - for(;;) { - // !hh || hh > MAX_HUFCODE_BITS in one test. - if (MAX_HUFCODE_BITS-1 < (unsigned)hh-1) - return RETVAL_DATA_ERROR; - // Grab 2 bits instead of 1 (slightly smaller/faster). Stop if - // first bit is 0, otherwise second bit says whether to - // increment or decrement. - kk = get_bits(bd, 2); - if (kk & 2) hh += 1 - ((kk&1)<<1); - else { - bd->inbufBitCount++; - break; - } - } - length[ii] = hh; - } - - // Find largest and smallest lengths in this group - minLen = maxLen = length[0]; - for (ii = 1; ii < symCount; ii++) { - if(length[ii] > maxLen) maxLen = length[ii]; - else if(length[ii] < minLen) minLen = length[ii]; - } - - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. It contains symbol values sorted by length. - * - * base[] is the amount to subtract from the value of a huffman symbol - * of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. It lets us know when to stop reading. - * - * To use these, keep reading bits until value <= limit[bitcount] or - * you've read over 20 bits (error). Then the decoded symbol - * equals permute[hufcode_value - base[hufcode_bitcount]]. - */ - hufGroup = bd->groups+jj; - hufGroup->minLen = minLen; - hufGroup->maxLen = maxLen; - - // Note that minLen can't be smaller than 1, so we adjust the base - // and limit array pointers so we're not always wasting the first - // entry. We do this again when using them (during symbol decoding). - base = hufGroup->base-1; - limit = hufGroup->limit-1; - - // zero temp[] and limit[], and calculate permute[] - pp = 0; - for (ii = minLen; ii <= maxLen; ii++) { - temp[ii] = limit[ii] = 0; - for (hh = 0; hh < symCount; hh++) - if (length[hh] == ii) - hufGroup->permute[pp++] = hh; - } - - // Count symbols coded for at each bit length - for (ii = 0; ii < symCount; ii++) temp[length[ii]]++; - - /* Calculate limit[] (the largest symbol-coding value at each bit - * length, which is (previous limit<<1)+symbols at this level), and - * base[] (number of symbols to ignore at each bit length, which is - * limit minus the cumulative count of symbols coded for already). */ - pp = hh = 0; - for (ii = minLen; ii < maxLen; ii++) { - pp += temp[ii]; - limit[ii] = pp-1; - pp <<= 1; - base[ii+1] = pp-(hh+=temp[ii]); - } - limit[maxLen] = pp+temp[maxLen]-1; - limit[maxLen+1] = INT_MAX; - base[minLen] = 0; - } - - return 0; + struct group_data *hufGroup; + int hh, ii, jj, kk, symCount, *base, *limit; + unsigned char uc; + + // Read in header signature and CRC (which is stored big endian) + ii = get_bits(bd, 24); + jj = get_bits(bd, 24); + bw->headerCRC = get_bits(bd,32); + + // Is this the EOF block with CRC for whole file? (Constant is "e") + if (ii==0x177245 && jj==0x385090) return RETVAL_LAST_BLOCK; + + // Is this a valid data block? (Constant is "pi".) + if (ii!=0x314159 || jj!=0x265359) return RETVAL_NOT_BZIP_DATA; + + // We can add support for blockRandomised if anybody complains. + if (get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT; + if ((bw->origPtr = get_bits(bd,24)) > bd->dbufSize) return RETVAL_DATA_ERROR; + + // mapping table: if some byte values are never used (encoding things + // like ascii text), the compression code removes the gaps to have fewer + // symbols to deal with, and writes a sparse bitfield indicating which + // values were present. We make a translation table to convert the symbols + // back to the corresponding bytes. + hh = get_bits(bd, 16); + bd->symTotal = 0; + for (ii=0; ii<16; ii++) { + if (hh & (1 << (15 - ii))) { + kk = get_bits(bd, 16); + for (jj=0; jj<16; jj++) + if (kk & (1 << (15 - jj))) + bd->symToByte[bd->symTotal++] = (16 * ii) + jj; + } + } + + // How many different huffman coding groups does this block use? + bd->groupCount = get_bits(bd,3); + if (bd->groupCount<2 || bd->groupCount>MAX_GROUPS) return RETVAL_DATA_ERROR; + + // nSelectors: Every GROUP_SIZE many symbols we switch huffman coding + // tables. Each group has a selector, which is an index into the huffman + // coding table arrays. + // + // Read in the group selector array, which is stored as MTF encoded + // bit runs. (MTF = Move To Front. Every time a symbol occurs it's moved + // to the front of the table, so it has a shorter encoding next time.) + if (!(bd->nSelectors = get_bits(bd, 15))) return RETVAL_DATA_ERROR; + for (ii=0; iigroupCount; ii++) bd->mtfSymbol[ii] = ii; + for (ii=0; iinSelectors; ii++) { + + // Get next value + for(jj=0;get_bits(bd,1);jj++) + if (jj>=bd->groupCount) return RETVAL_DATA_ERROR; + + // Decode MTF to get the next selector, and move it to the front. + uc = bd->mtfSymbol[jj]; + memmove(bd->mtfSymbol+1, bd->mtfSymbol, jj); + bd->mtfSymbol[0] = bd->selectors[ii] = uc; + } + + // Read the huffman coding tables for each group, which code for symTotal + // literal symbols, plus two run symbols (RUNA, RUNB) + symCount = bd->symTotal+2; + for (jj=0; jjgroupCount; jj++) { + unsigned char length[MAX_SYMBOLS]; + unsigned temp[MAX_HUFCODE_BITS+1]; + int minLen, maxLen, pp; + + // Read lengths + hh = get_bits(bd, 5); + for (ii = 0; ii < symCount; ii++) { + for(;;) { + // !hh || hh > MAX_HUFCODE_BITS in one test. + if (MAX_HUFCODE_BITS-1 < (unsigned)hh-1) return RETVAL_DATA_ERROR; + // Grab 2 bits instead of 1 (slightly smaller/faster). Stop if + // first bit is 0, otherwise second bit says whether to + // increment or decrement. + kk = get_bits(bd, 2); + if (kk & 2) hh += 1 - ((kk&1)<<1); + else { + bd->inbufBitCount++; + break; + } + } + length[ii] = hh; + } + + // Find largest and smallest lengths in this group + minLen = maxLen = length[0]; + for (ii = 1; ii < symCount; ii++) { + if(length[ii] > maxLen) maxLen = length[ii]; + else if(length[ii] < minLen) minLen = length[ii]; + } + + /* Calculate permute[], base[], and limit[] tables from length[]. + * + * permute[] is the lookup table for converting huffman coded symbols + * into decoded symbols. It contains symbol values sorted by length. + * + * base[] is the amount to subtract from the value of a huffman symbol + * of a given length when using permute[]. + * + * limit[] indicates the largest numerical value a symbol with a given + * number of bits can have. It lets us know when to stop reading. + * + * To use these, keep reading bits until value <= limit[bitcount] or + * you've read over 20 bits (error). Then the decoded symbol + * equals permute[hufcode_value - base[hufcode_bitcount]]. + */ + hufGroup = bd->groups+jj; + hufGroup->minLen = minLen; + hufGroup->maxLen = maxLen; + + // Note that minLen can't be smaller than 1, so we adjust the base + // and limit array pointers so we're not always wasting the first + // entry. We do this again when using them (during symbol decoding). + base = hufGroup->base-1; + limit = hufGroup->limit-1; + + // zero temp[] and limit[], and calculate permute[] + pp = 0; + for (ii = minLen; ii <= maxLen; ii++) { + temp[ii] = limit[ii] = 0; + for (hh = 0; hh < symCount; hh++) + if (length[hh] == ii) hufGroup->permute[pp++] = hh; + } + + // Count symbols coded for at each bit length + for (ii = 0; ii < symCount; ii++) temp[length[ii]]++; + + /* Calculate limit[] (the largest symbol-coding value at each bit + * length, which is (previous limit<<1)+symbols at this level), and + * base[] (number of symbols to ignore at each bit length, which is + * limit minus the cumulative count of symbols coded for already). */ + pp = hh = 0; + for (ii = minLen; ii < maxLen; ii++) { + pp += temp[ii]; + limit[ii] = pp-1; + pp <<= 1; + base[ii+1] = pp-(hh+=temp[ii]); + } + limit[maxLen] = pp+temp[maxLen]-1; + limit[maxLen+1] = INT_MAX; + base[minLen] = 0; + } + + return 0; } /* First pass, read block's symbols into dbuf[dbufCount]. @@ -300,191 +295,188 @@ static int read_block_header(struct bunzip_data *bd, struct bwdata *bw) static int read_huffman_data(struct bunzip_data *bd, struct bwdata *bw) { - struct group_data *hufGroup; - int hh, ii, jj, kk, runPos, dbufCount, symCount, selector, nextSym, - *byteCount, *base, *limit; - unsigned int *dbuf = bw->dbuf; - unsigned char uc; - - // We've finished reading and digesting the block header. Now read this - // block's huffman coded symbols from the file and undo the huffman coding - // and run length encoding, saving the result into dbuf[dbufCount++] = uc - - // Initialize symbol occurrence counters and symbol mtf table - byteCount = bw->byteCount; - for(ii=0; ii<256; ii++) { - byteCount[ii] = 0; - bd->mtfSymbol[ii] = ii; - } - - // Loop through compressed symbols. This is the first "tight inner loop" - // that needs to be micro-optimized for speed. (This one fills out dbuf[] - // linearly, staying in cache more, so isn't as limited by DRAM access.) - runPos = dbufCount = symCount = selector = 0; - // Some unnecessary initializations to shut gcc up. - base = limit = 0; - hufGroup = 0; - hh = 0; - - for (;;) { - - // Have we reached the end of this huffman group? - if (!(symCount--)) { - // Determine which huffman coding group to use. - symCount = GROUP_SIZE-1; - if (selector >= bd->nSelectors) return RETVAL_DATA_ERROR; - hufGroup = bd->groups + bd->selectors[selector++]; - base = hufGroup->base-1; - limit = hufGroup->limit-1; - } - - // Read next huffman-coded symbol (into jj). - ii = hufGroup->minLen; - jj = get_bits(bd, ii); - while (jj > limit[ii]) { - // if (ii > hufGroup->maxLen) return RETVAL_DATA_ERROR; - ii++; - - // Unroll get_bits() to avoid a function call when the data's in - // the buffer already. - kk = bd->inbufBitCount - ? (bd->inbufBits >> --(bd->inbufBitCount)) & 1 - : get_bits(bd, 1); - jj = (jj << 1) | kk; - } - // Huffman decode jj into nextSym (with bounds checking) - jj-=base[ii]; - - if (ii > hufGroup->maxLen || (unsigned)jj >= MAX_SYMBOLS) - return RETVAL_DATA_ERROR; - nextSym = hufGroup->permute[jj]; - - // If this is a repeated run, loop collecting data - if ((unsigned)nextSym <= SYMBOL_RUNB) { - - // If this is the start of a new run, zero out counter - if(!runPos) { - runPos = 1; - hh = 0; - } - - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - hh += (runPos << nextSym); // +runPos if RUNA; +2*runPos if RUNB - runPos <<= 1; - continue; - } - - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if (runPos) { - runPos = 0; - if (dbufCount+hh >= bd->dbufSize) return RETVAL_DATA_ERROR; - - uc = bd->symToByte[bd->mtfSymbol[0]]; - byteCount[uc] += hh; - while (hh--) dbuf[dbufCount++] = uc; - } - - // Is this the terminating symbol? - if (nextSym>bd->symTotal) break; - - /* At this point, the symbol we just decoded indicates a new literal - character. Subtract one to get the position in the MTF array - at which this literal is currently to be found. (Note that the - result can't be -1 or 0, because 0 and 1 are RUNA and RUNB. - Another instance of the first symbol in the mtf array, position 0, - would have been handled as part of a run.) */ - if (dbufCount>=bd->dbufSize) return RETVAL_DATA_ERROR; - ii = nextSym - 1; - uc = bd->mtfSymbol[ii]; - // On my laptop, unrolling this memmove() into a loop shaves 3.5% off - // the total running time. - while(ii--) bd->mtfSymbol[ii+1] = bd->mtfSymbol[ii]; - bd->mtfSymbol[0] = uc; - uc = bd->symToByte[uc]; - - // We have our literal byte. Save it into dbuf. - byteCount[uc]++; - dbuf[dbufCount++] = (unsigned int)uc; - } - - // Now we know what dbufCount is, do a better sanity check on origPtr. - if (bw->origPtr >= (bw->writeCount = dbufCount)) return RETVAL_DATA_ERROR; - - return 0; + struct group_data *hufGroup; + int hh, ii, jj, kk, runPos, dbufCount, symCount, selector, nextSym, + *byteCount, *base, *limit; + unsigned int *dbuf = bw->dbuf; + unsigned char uc; + + // We've finished reading and digesting the block header. Now read this + // block's huffman coded symbols from the file and undo the huffman coding + // and run length encoding, saving the result into dbuf[dbufCount++] = uc + + // Initialize symbol occurrence counters and symbol mtf table + byteCount = bw->byteCount; + for(ii=0; ii<256; ii++) { + byteCount[ii] = 0; + bd->mtfSymbol[ii] = ii; + } + + // Loop through compressed symbols. This is the first "tight inner loop" + // that needs to be micro-optimized for speed. (This one fills out dbuf[] + // linearly, staying in cache more, so isn't as limited by DRAM access.) + runPos = dbufCount = symCount = selector = 0; + // Some unnecessary initializations to shut gcc up. + base = limit = 0; + hufGroup = 0; + hh = 0; + + for (;;) { + // Have we reached the end of this huffman group? + if (!(symCount--)) { + // Determine which huffman coding group to use. + symCount = GROUP_SIZE-1; + if (selector >= bd->nSelectors) return RETVAL_DATA_ERROR; + hufGroup = bd->groups + bd->selectors[selector++]; + base = hufGroup->base-1; + limit = hufGroup->limit-1; + } + + // Read next huffman-coded symbol (into jj). + ii = hufGroup->minLen; + jj = get_bits(bd, ii); + while (jj > limit[ii]) { + // if (ii > hufGroup->maxLen) return RETVAL_DATA_ERROR; + ii++; + + // Unroll get_bits() to avoid a function call when the data's in + // the buffer already. + kk = bd->inbufBitCount + ? (bd->inbufBits >> --(bd->inbufBitCount)) & 1 : get_bits(bd, 1); + jj = (jj << 1) | kk; + } + // Huffman decode jj into nextSym (with bounds checking) + jj-=base[ii]; + + if (ii > hufGroup->maxLen || (unsigned)jj >= MAX_SYMBOLS) + return RETVAL_DATA_ERROR; + nextSym = hufGroup->permute[jj]; + + // If this is a repeated run, loop collecting data + if ((unsigned)nextSym <= SYMBOL_RUNB) { + // If this is the start of a new run, zero out counter + if(!runPos) { + runPos = 1; + hh = 0; + } + + /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at + each bit position, add 1 or 2 instead. For example, + 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. + You can make any bit pattern that way using 1 less symbol than + the basic or 0/1 method (except all bits 0, which would use no + symbols, but a run of length 0 doesn't mean anything in this + context). Thus space is saved. */ + hh += (runPos << nextSym); // +runPos if RUNA; +2*runPos if RUNB + runPos <<= 1; + continue; + } + + /* When we hit the first non-run symbol after a run, we now know + how many times to repeat the last literal, so append that many + copies to our buffer of decoded symbols (dbuf) now. (The last + literal used is the one at the head of the mtfSymbol array.) */ + if (runPos) { + runPos = 0; + if (dbufCount+hh >= bd->dbufSize) return RETVAL_DATA_ERROR; + + uc = bd->symToByte[bd->mtfSymbol[0]]; + byteCount[uc] += hh; + while (hh--) dbuf[dbufCount++] = uc; + } + + // Is this the terminating symbol? + if (nextSym>bd->symTotal) break; + + /* At this point, the symbol we just decoded indicates a new literal + character. Subtract one to get the position in the MTF array + at which this literal is currently to be found. (Note that the + result can't be -1 or 0, because 0 and 1 are RUNA and RUNB. + Another instance of the first symbol in the mtf array, position 0, + would have been handled as part of a run.) */ + if (dbufCount>=bd->dbufSize) return RETVAL_DATA_ERROR; + ii = nextSym - 1; + uc = bd->mtfSymbol[ii]; + // On my laptop, unrolling this memmove() into a loop shaves 3.5% off + // the total running time. + while(ii--) bd->mtfSymbol[ii+1] = bd->mtfSymbol[ii]; + bd->mtfSymbol[0] = uc; + uc = bd->symToByte[uc]; + + // We have our literal byte. Save it into dbuf. + byteCount[uc]++; + dbuf[dbufCount++] = (unsigned int)uc; + } + + // Now we know what dbufCount is, do a better sanity check on origPtr. + if (bw->origPtr >= (bw->writeCount = dbufCount)) return RETVAL_DATA_ERROR; + + return 0; } // Flush output buffer to disk void flush_bunzip_outbuf(struct bunzip_data *bd, int out_fd) { - if (bd->outbufPos) { - if (write(out_fd, bd->outbuf, bd->outbufPos) != bd->outbufPos) - error_exit("Unexpected output EOF"); - bd->outbufPos = 0; - } + if (bd->outbufPos) { + if (write(out_fd, bd->outbuf, bd->outbufPos) != bd->outbufPos) + error_exit("Unexpected output EOF"); + bd->outbufPos = 0; + } } void burrows_wheeler_prep(struct bunzip_data *bd, struct bwdata *bw) { - int ii, jj; - unsigned int *dbuf = bw->dbuf; - int *byteCount = bw->byteCount; - - // Technically this part is preparation for the burrows-wheeler - // transform, but it's quick and convenient to do here. - - // Turn byteCount into cumulative occurrence counts of 0 to n-1. - jj = 0; - for (ii=0; ii<256; ii++) { - int kk = jj + byteCount[ii]; - byteCount[ii] = jj; - jj = kk; - } - - // Use occurrence counts to quickly figure out what order dbuf would be in - // if we sorted it. - for (ii=0; ii < bw->writeCount; ii++) { - unsigned char uc = dbuf[ii]; - dbuf[byteCount[uc]] |= (ii << 8); - byteCount[uc]++; - } - - // blockRandomised support would go here. - - // Using ii as position, jj as previous character, hh as current character, - // and uc as run count. - bw->dataCRC = 0xffffffffL; - - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence uc=255, which will either wrap - to 1 or get reset). */ - if (bw->writeCount) { - bw->writePos = dbuf[bw->origPtr]; - bw->writeCurrent = (unsigned char)bw->writePos; - bw->writePos >>= 8; - bw->writeRun = -1; - } + int ii, jj; + unsigned int *dbuf = bw->dbuf; + int *byteCount = bw->byteCount; + + // Technically this part is preparation for the burrows-wheeler + // transform, but it's quick and convenient to do here. + + // Turn byteCount into cumulative occurrence counts of 0 to n-1. + jj = 0; + for (ii=0; ii<256; ii++) { + int kk = jj + byteCount[ii]; + byteCount[ii] = jj; + jj = kk; + } + + // Use occurrence counts to quickly figure out what order dbuf would be in + // if we sorted it. + for (ii=0; ii < bw->writeCount; ii++) { + unsigned char uc = dbuf[ii]; + dbuf[byteCount[uc]] |= (ii << 8); + byteCount[uc]++; + } + + // blockRandomised support would go here. + + // Using ii as position, jj as previous character, hh as current character, + // and uc as run count. + bw->dataCRC = 0xffffffffL; + + /* Decode first byte by hand to initialize "previous" byte. Note that it + doesn't get output, and if the first three characters are identical + it doesn't qualify as a run (hence uc=255, which will either wrap + to 1 or get reset). */ + if (bw->writeCount) { + bw->writePos = dbuf[bw->origPtr]; + bw->writeCurrent = (unsigned char)bw->writePos; + bw->writePos >>= 8; + bw->writeRun = -1; + } } // Decompress a block of text to intermediate buffer int read_bunzip_data(struct bunzip_data *bd) { - int rc = read_block_header(bd, bd->bwdata); - if (!rc) rc=read_huffman_data(bd, bd->bwdata); + int rc = read_block_header(bd, bd->bwdata); + if (!rc) rc=read_huffman_data(bd, bd->bwdata); - // First thing that can be done by a background thread. - burrows_wheeler_prep(bd, bd->bwdata); + // First thing that can be done by a background thread. + burrows_wheeler_prep(bd, bd->bwdata); - return rc; + return rc; } // Undo burrows-wheeler transform on intermediate buffer to produce output. @@ -497,149 +489,144 @@ int read_bunzip_data(struct bunzip_data *bd) int write_bunzip_data(struct bunzip_data *bd, struct bwdata *bw, int out_fd, char *outbuf, int len) { - unsigned int *dbuf = bw->dbuf; - int count, pos, current, run, copies, outbyte, previous, gotcount = 0; - - for (;;) { - - // If last read was short due to end of file, return last block now - if (bw->writeCount < 0) return bw->writeCount; - - // If we need to refill dbuf, do it. - if (!bw->writeCount) { - int i = read_bunzip_data(bd); - if (i) { - if (i == RETVAL_LAST_BLOCK) { - bw->writeCount = i; - return gotcount; - } else return i; - } - } - - // loop generating output - count = bw->writeCount; - pos = bw->writePos; - current = bw->writeCurrent; - run = bw->writeRun; - while (count) { - - // If somebody (like tar) wants a certain number of bytes of - // data from memory instead of written to a file, humor them. - if (len && bd->outbufPos>=len) goto dataus_interruptus; - count--; - - // Follow sequence vector to undo Burrows-Wheeler transform. - previous = current; - pos = dbuf[pos]; - current = pos&0xff; - pos >>= 8; - - // Whenever we see 3 consecutive copies of the same byte, - // the 4th is a repeat count - if (run++ == 3) { - copies = current; - outbyte = previous; - current = -1; - } else { - copies = 1; - outbyte = current; - } - - // Output bytes to buffer, flushing to file if necessary - while (copies--) { - if (bd->outbufPos == IOBUF_SIZE) flush_bunzip_outbuf(bd,out_fd); - bd->outbuf[bd->outbufPos++] = outbyte; - bw->dataCRC = (bw->dataCRC << 8) - ^ bd->crc32Table[(bw->dataCRC >> 24) ^ outbyte]; - } - if (current!=previous) run=0; - } - - // decompression of this block completed successfully - bw->dataCRC = ~(bw->dataCRC); - bd->totalCRC = ((bd->totalCRC << 1) | (bd->totalCRC >> 31)) - ^ bw->dataCRC; - - // if this block had a crc error, force file level crc error. - if (bw->dataCRC != bw->headerCRC) { - bd->totalCRC = bw->headerCRC+1; - - return RETVAL_LAST_BLOCK; - } + unsigned int *dbuf = bw->dbuf; + int count, pos, current, run, copies, outbyte, previous, gotcount = 0; + + for (;;) { + // If last read was short due to end of file, return last block now + if (bw->writeCount < 0) return bw->writeCount; + + // If we need to refill dbuf, do it. + if (!bw->writeCount) { + int i = read_bunzip_data(bd); + if (i) { + if (i == RETVAL_LAST_BLOCK) { + bw->writeCount = i; + return gotcount; + } else return i; + } + } + + // loop generating output + count = bw->writeCount; + pos = bw->writePos; + current = bw->writeCurrent; + run = bw->writeRun; + while (count) { + + // If somebody (like tar) wants a certain number of bytes of + // data from memory instead of written to a file, humor them. + if (len && bd->outbufPos>=len) goto dataus_interruptus; + count--; + + // Follow sequence vector to undo Burrows-Wheeler transform. + previous = current; + pos = dbuf[pos]; + current = pos&0xff; + pos >>= 8; + + // Whenever we see 3 consecutive copies of the same byte, + // the 4th is a repeat count + if (run++ == 3) { + copies = current; + outbyte = previous; + current = -1; + } else { + copies = 1; + outbyte = current; + } + + // Output bytes to buffer, flushing to file if necessary + while (copies--) { + if (bd->outbufPos == IOBUF_SIZE) flush_bunzip_outbuf(bd,out_fd); + bd->outbuf[bd->outbufPos++] = outbyte; + bw->dataCRC = (bw->dataCRC << 8) + ^ bd->crc32Table[(bw->dataCRC >> 24) ^ outbyte]; + } + if (current!=previous) run=0; + } + + // decompression of this block completed successfully + bw->dataCRC = ~(bw->dataCRC); + bd->totalCRC = ((bd->totalCRC << 1) | (bd->totalCRC >> 31)) ^ bw->dataCRC; + + // if this block had a crc error, force file level crc error. + if (bw->dataCRC != bw->headerCRC) { + bd->totalCRC = bw->headerCRC+1; + + return RETVAL_LAST_BLOCK; + } dataus_interruptus: - bw->writeCount = count; - if (len) { - gotcount += bd->outbufPos; - memcpy(outbuf, bd->outbuf, len); - - // If we got enough data, checkpoint loop state and return - if ((len-=bd->outbufPos)<1) { - bd->outbufPos -= len; - if (bd->outbufPos) - memmove(bd->outbuf, bd->outbuf+len, bd->outbufPos); - bw->writePos = pos; - bw->writeCurrent = current; - bw->writeRun = run; - - return gotcount; - } - } - } + bw->writeCount = count; + if (len) { + gotcount += bd->outbufPos; + memcpy(outbuf, bd->outbuf, len); + + // If we got enough data, checkpoint loop state and return + if ((len-=bd->outbufPos)<1) { + bd->outbufPos -= len; + if (bd->outbufPos) memmove(bd->outbuf, bd->outbuf+len, bd->outbufPos); + bw->writePos = pos; + bw->writeCurrent = current; + bw->writeRun = run; + + return gotcount; + } + } + } } -// Allocate the structure, read file header. If !len, src_fd contains -// filehandle to read from. Else inbuf contains data. +// Allocate the structure, read file header. If !len, src_fd contains +// filehandle to read from. Else inbuf contains data. int start_bunzip(struct bunzip_data **bdp, int src_fd, char *inbuf, int len) { - struct bunzip_data *bd; - unsigned int i; - - // Figure out how much data to allocate. - i = sizeof(struct bunzip_data); - if (!len) i += IOBUF_SIZE; - - // Allocate bunzip_data. Most fields initialize to zero. - bd = *bdp = xzalloc(i); - if (len) { - bd->inbuf = inbuf; - bd->inbufCount = len; - bd->in_fd = -1; - } else { - bd->inbuf = (char *)(bd+1); - bd->in_fd = src_fd; - } - - crc_init(bd->crc32Table, 0); - - // Ensure that file starts with "BZh". - for (i=0;i<3;i++) - if (get_bits(bd,8)!="BZh"[i]) return RETVAL_NOT_BZIP_DATA; - - // Next byte ascii '1'-'9', indicates block size in units of 100k of - // uncompressed data. Allocate intermediate buffer for block. - i = get_bits(bd, 8); - if (i<'1' || i>'9') return RETVAL_NOT_BZIP_DATA; - bd->dbufSize = 100000*(i-'0')*THREADS; - for (i=0; ibwdata[i].dbuf = xmalloc(bd->dbufSize * sizeof(int)); - - return 0; + struct bunzip_data *bd; + unsigned int i; + + // Figure out how much data to allocate. + i = sizeof(struct bunzip_data); + if (!len) i += IOBUF_SIZE; + + // Allocate bunzip_data. Most fields initialize to zero. + bd = *bdp = xzalloc(i); + if (len) { + bd->inbuf = inbuf; + bd->inbufCount = len; + bd->in_fd = -1; + } else { + bd->inbuf = (char *)(bd+1); + bd->in_fd = src_fd; + } + + crc_init(bd->crc32Table, 0); + + // Ensure that file starts with "BZh". + for (i=0;i<3;i++) if (get_bits(bd,8)!="BZh"[i]) return RETVAL_NOT_BZIP_DATA; + + // Next byte ascii '1'-'9', indicates block size in units of 100k of + // uncompressed data. Allocate intermediate buffer for block. + i = get_bits(bd, 8); + if (i<'1' || i>'9') return RETVAL_NOT_BZIP_DATA; + bd->dbufSize = 100000*(i-'0')*THREADS; + for (i=0; ibwdata[i].dbuf = xmalloc(bd->dbufSize * sizeof(int)); + + return 0; } -// Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, +// Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, // not end of file.) void bunzipStream(int src_fd, int dst_fd) { - struct bunzip_data *bd; - int i, j; - - if (!(i = start_bunzip(&bd,src_fd,0,0))) { - i = write_bunzip_data(bd,bd->bwdata,dst_fd,0,0); - if (i==RETVAL_LAST_BLOCK && bd->bwdata[0].headerCRC==bd->totalCRC) - i = 0; - } - flush_bunzip_outbuf(bd,dst_fd); - for (j=0; jbwdata[j].dbuf); - free(bd); - if (i) error_exit(bunzip_errors[-i]); + struct bunzip_data *bd; + int i, j; + + if (!(i = start_bunzip(&bd,src_fd,0,0))) { + i = write_bunzip_data(bd,bd->bwdata,dst_fd,0,0); + if (i==RETVAL_LAST_BLOCK && bd->bwdata[0].headerCRC==bd->totalCRC) i = 0; + } + flush_bunzip_outbuf(bd,dst_fd); + for (j=0; jbwdata[j].dbuf); + free(bd); + if (i) error_exit(bunzip_errors[-i]); } diff --git a/lib/dirtree.c b/lib/dirtree.c index 3f5a2935..d1de40ee 100644 --- a/lib/dirtree.c +++ b/lib/dirtree.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4 :*/ /* dirtree.c - Functions for dealing with directory trees. * * Copyright 2007 Rob Landley @@ -12,76 +11,75 @@ struct dirtree *dirtree_add_node(int dirfd, char *name, int symfollow) { - struct dirtree *dt = NULL; - struct stat st; - char buf[4096]; - int len = 0, linklen = 0; - - if (name) { - if (fstatat(dirfd, name, &st, symfollow ? 0 : AT_SYMLINK_NOFOLLOW)) - goto error; - if (S_ISLNK(st.st_mode)) { - if (0>(linklen = readlinkat(dirfd, name, buf, 4095))) goto error; - buf[linklen++]=0; - } - len = strlen(name); - } - dt = xzalloc((len = sizeof(struct dirtree)+len+1)+linklen); - if (name) { - memcpy(&(dt->st), &st, sizeof(struct stat)); - strcpy(dt->name, name); - - if (linklen) { - dt->symlink = memcpy(len+(char *)dt, buf, linklen); - dt->data = --linklen; - } - } - - return dt; + struct dirtree *dt = NULL; + struct stat st; + char buf[4096]; + int len = 0, linklen = 0; + + if (name) { + if (fstatat(dirfd, name, &st, symfollow ? 0 : AT_SYMLINK_NOFOLLOW)) + goto error; + if (S_ISLNK(st.st_mode)) { + if (0>(linklen = readlinkat(dirfd, name, buf, 4095))) goto error; + buf[linklen++]=0; + } + len = strlen(name); + } + dt = xzalloc((len = sizeof(struct dirtree)+len+1)+linklen); + if (name) { + memcpy(&(dt->st), &st, sizeof(struct stat)); + strcpy(dt->name, name); + + if (linklen) { + dt->symlink = memcpy(len+(char *)dt, buf, linklen); + dt->data = --linklen; + } + } + + return dt; error: - perror_msg("%s",name); - free(dt); - return 0; + perror_msg("%s",name); + free(dt); + return 0; } // Return path to this node, assembled recursively. char *dirtree_path(struct dirtree *node, int *plen) { - char *path; - int len; - - if (!node || !node->name) { - path = xmalloc(*plen); - *plen = 0; - return path; - } - - len = (plen ? *plen : 0)+strlen(node->name)+1; - path = dirtree_path(node->parent, &len); - if (len && path[len-1] != '/') path[len++]='/'; - len = (stpcpy(path+len, node->name) - path); - if (plen) *plen = len; - - return path; + char *path; + int len; + + if (!node || !node->name) { + path = xmalloc(*plen); + *plen = 0; + return path; + } + + len = (plen ? *plen : 0)+strlen(node->name)+1; + path = dirtree_path(node->parent, &len); + if (len && path[len-1] != '/') path[len++]='/'; + len = (stpcpy(path+len, node->name) - path); + if (plen) *plen = len; + + return path; } // Default callback, filters out "." and "..". int dirtree_notdotdot(struct dirtree *catch) { - // Should we skip "." and ".."? - if (catch->name[0]=='.' && (!catch->name[1] || - (catch->name[1]=='.' && !catch->name[2]))) - return 0; + // Should we skip "." and ".."? + if (catch->name[0]=='.' && (!catch->name[1] || + (catch->name[1]=='.' && !catch->name[2]))) return 0; - return DIRTREE_SAVE|DIRTREE_RECURSE; + return DIRTREE_SAVE|DIRTREE_RECURSE; } int dirtree_parentfd(struct dirtree *node) { - return node->parent ? node->parent->data : AT_FDCWD; + return node->parent ? node->parent->data : AT_FDCWD; } // Handle callback for a node in the tree. Returns saved node(s) or NULL. @@ -93,69 +91,69 @@ int dirtree_parentfd(struct dirtree *node) // struct dirtree *handle_callback(struct dirtree *new, - int (*callback)(struct dirtree *node)) + int (*callback)(struct dirtree *node)) { - int flags, dir = S_ISDIR(new->st.st_mode); + int flags, dir = S_ISDIR(new->st.st_mode); - if (!callback) callback = dirtree_notdotdot; + if (!callback) callback = dirtree_notdotdot; - flags = callback(new); + flags = callback(new); - if (dir) { - if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) { - new->data = openat(dirtree_parentfd(new), new->name, 0); - dirtree_recurse(new, callback, flags & DIRTREE_SYMFOLLOW); - if (flags & DIRTREE_COMEAGAIN) flags = callback(new); - } - } + if (dir) { + if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) { + new->data = openat(dirtree_parentfd(new), new->name, 0); + dirtree_recurse(new, callback, flags & DIRTREE_SYMFOLLOW); + if (flags & DIRTREE_COMEAGAIN) flags = callback(new); + } + } - // If this had children, it was callback's job to free them already. - if (!(flags & DIRTREE_SAVE)) { - free(new); - new = NULL; - } + // If this had children, it was callback's job to free them already. + if (!(flags & DIRTREE_SAVE)) { + free(new); + new = NULL; + } - return (flags & DIRTREE_ABORT)==DIRTREE_ABORT ? DIRTREE_ABORTVAL : new; + return (flags & DIRTREE_ABORT)==DIRTREE_ABORT ? DIRTREE_ABORTVAL : new; } // Recursively read/process children of directory node (with dirfd in data), // filtering through callback(). void dirtree_recurse(struct dirtree *node, - int (*callback)(struct dirtree *node), int symfollow) + int (*callback)(struct dirtree *node), int symfollow) { - struct dirtree *new, **ddt = &(node->child); - struct dirent *entry; - DIR *dir; - - if (!(dir = fdopendir(node->data))) { - char *path = dirtree_path(node, 0); - perror_msg("No %s", path); - free(path); - close(node->data); - - return; - } - - // according to the fddir() man page, the filehandle in the DIR * can still - // be externally used by things that don't lseek() it. - - // The extra parentheses are to shut the stupid compiler up. - while ((entry = readdir(dir))) { - if (!(new = dirtree_add_node(node->data, entry->d_name, symfollow))) - continue; - new->parent = node; - new = handle_callback(new, callback); - if (new == DIRTREE_ABORTVAL) break; - if (new) { - *ddt = new; - ddt = &((*ddt)->next); - } - } - - // This closes filehandle as well, so note it - closedir(dir); - node->data = -1; + struct dirtree *new, **ddt = &(node->child); + struct dirent *entry; + DIR *dir; + + if (!(dir = fdopendir(node->data))) { + char *path = dirtree_path(node, 0); + perror_msg("No %s", path); + free(path); + close(node->data); + + return; + } + + // according to the fddir() man page, the filehandle in the DIR * can still + // be externally used by things that don't lseek() it. + + // The extra parentheses are to shut the stupid compiler up. + while ((entry = readdir(dir))) { + if (!(new = dirtree_add_node(node->data, entry->d_name, symfollow))) + continue; + new->parent = node; + new = handle_callback(new, callback); + if (new == DIRTREE_ABORTVAL) break; + if (new) { + *ddt = new; + ddt = &((*ddt)->next); + } + } + + // This closes filehandle as well, so note it + closedir(dir); + node->data = -1; } // Create dirtree from path, using callback to filter nodes. @@ -165,7 +163,7 @@ void dirtree_recurse(struct dirtree *node, struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)) { - struct dirtree *root = dirtree_add_node(AT_FDCWD, path, 0); + struct dirtree *root = dirtree_add_node(AT_FDCWD, path, 0); - return root ? handle_callback(root, callback) : DIRTREE_ABORTVAL; + return root ? handle_callback(root, callback) : DIRTREE_ABORTVAL; } diff --git a/lib/getmountlist.c b/lib/getmountlist.c index 1b235446..efbcff13 100644 --- a/lib/getmountlist.c +++ b/lib/getmountlist.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4 : */ /* getmountlist.c - Get a linked list of mount points, with stat information. * * Copyright 2006 Rob Landley @@ -16,28 +15,28 @@ char *path_mounts = "/proc/mounts"; struct mtab_list *getmountlist(int die) { - FILE *fp; - struct mtab_list *mtlist, *mt; - struct mntent me; - char evilbuf[2*PATH_MAX]; + FILE *fp; + struct mtab_list *mtlist, *mt; + struct mntent me; + char evilbuf[2*PATH_MAX]; - mtlist = 0; - if (!(fp = setmntent(path_mounts, "r"))) { - if (die) error_exit("cannot open %s", path_mounts); - } else { - while (getmntent_r(fp, &me, evilbuf, sizeof(evilbuf))) { - mt = xzalloc(sizeof(struct mtab_list) + strlen(me.mnt_fsname) + - strlen(me.mnt_dir) + strlen(me.mnt_type) + 3); - mt->next = mtlist; - // Get information about this filesystem. Yes, we need both. - stat(me.mnt_dir, &(mt->stat)); - statvfs(me.mnt_dir, &(mt->statvfs)); - // Remember information from /proc/mounts - mt->dir = stpcpy(mt->type, me.mnt_type) + 1; - mt->device = stpcpy(mt->dir, me.mnt_dir) + 1; - strcpy(mt->device, me.mnt_fsname); - mtlist = mt; - } - } - return mtlist; + mtlist = 0; + if (!(fp = setmntent(path_mounts, "r"))) { + if (die) error_exit("cannot open %s", path_mounts); + } else { + while (getmntent_r(fp, &me, evilbuf, sizeof(evilbuf))) { + mt = xzalloc(sizeof(struct mtab_list) + strlen(me.mnt_fsname) + + strlen(me.mnt_dir) + strlen(me.mnt_type) + 3); + mt->next = mtlist; + // Get information about this filesystem. Yes, we need both. + stat(me.mnt_dir, &(mt->stat)); + statvfs(me.mnt_dir, &(mt->statvfs)); + // Remember information from /proc/mounts + mt->dir = stpcpy(mt->type, me.mnt_type) + 1; + mt->device = stpcpy(mt->dir, me.mnt_dir) + 1; + strcpy(mt->device, me.mnt_fsname); + mtlist = mt; + } + } + return mtlist; } diff --git a/lib/lib.c b/lib/lib.c index 2c2ea63e..06828a40 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4 :*/ /* lib.c - reusable stuff. * * Functions with the x prefix are wrappers for library functions. They either @@ -14,257 +13,257 @@ // Strcpy with size checking: exit if there's not enough space for the string. void xstrcpy(char *dest, char *src, size_t size) { - if (strlen(src)+1 > size) error_exit("xstrcpy"); - strcpy(dest, src); + if (strlen(src)+1 > size) error_exit("xstrcpy"); + strcpy(dest, src); } void verror_msg(char *msg, int err, va_list va) { - char *s = ": %s"; + char *s = ": %s"; - fprintf(stderr, "%s: ", toys.which->name); - if (msg) vfprintf(stderr, msg, va); - else s+=2; - if (err) fprintf(stderr, s, strerror(err)); - putc('\n', stderr); + fprintf(stderr, "%s: ", toys.which->name); + if (msg) vfprintf(stderr, msg, va); + else s+=2; + if (err) fprintf(stderr, s, strerror(err)); + putc('\n', stderr); } void error_msg(char *msg, ...) { - va_list va; + va_list va; - va_start(va, msg); - verror_msg(msg, 0, va); - va_end(va); + va_start(va, msg); + verror_msg(msg, 0, va); + va_end(va); } void perror_msg(char *msg, ...) { - va_list va; + va_list va; - va_start(va, msg); - verror_msg(msg, errno, va); - va_end(va); + va_start(va, msg); + verror_msg(msg, errno, va); + va_end(va); } // Die with an error message. void error_exit(char *msg, ...) { - va_list va; + va_list va; - if (CFG_HELP && toys.exithelp) { - *toys.optargs=*toys.argv; - USE_HELP(help_main();) // dear gcc: shut up. - fprintf(stderr,"\n"); - } + if (CFG_HELP && toys.exithelp) { + *toys.optargs=*toys.argv; + USE_HELP(help_main();) // dear gcc: shut up. + fprintf(stderr,"\n"); + } - va_start(va, msg); - verror_msg(msg, 0, va); - va_end(va); + va_start(va, msg); + verror_msg(msg, 0, va); + va_end(va); - exit(!toys.exitval ? 1 : toys.exitval); + exit(!toys.exitval ? 1 : toys.exitval); } // Die with an error message and strerror(errno) void perror_exit(char *msg, ...) { - va_list va; + va_list va; - va_start(va, msg); - verror_msg(msg, errno, va); - va_end(va); + va_start(va, msg); + verror_msg(msg, errno, va); + va_end(va); - exit(!toys.exitval ? 1 : toys.exitval); + exit(!toys.exitval ? 1 : toys.exitval); } // Die unless we can allocate memory. void *xmalloc(size_t size) { - void *ret = malloc(size); - if (!ret) error_exit("xmalloc"); + void *ret = malloc(size); + if (!ret) error_exit("xmalloc"); - return ret; + return ret; } // Die unless we can allocate prezeroed memory. void *xzalloc(size_t size) { - void *ret = xmalloc(size); - memset(ret, 0, size); - return ret; + void *ret = xmalloc(size); + memset(ret, 0, size); + return ret; } // Die unless we can change the size of an existing allocation, possibly // moving it. (Notice different arguments from libc function.) void *xrealloc(void *ptr, size_t size) { - ptr = realloc(ptr, size); - if (!ptr) error_exit("xrealloc"); + ptr = realloc(ptr, size); + if (!ptr) error_exit("xrealloc"); - return ptr; + return ptr; } // Die unless we can allocate a copy of this many bytes of string. char *xstrndup(char *s, size_t n) { - char *ret = xmalloc(++n); - strncpy(ret, s, n); - ret[--n]=0; + char *ret = xmalloc(++n); + strncpy(ret, s, n); + ret[--n]=0; - return ret; + return ret; } // Die unless we can allocate a copy of this string. char *xstrdup(char *s) { - return xstrndup(s, strlen(s)); + return xstrndup(s, strlen(s)); } // Die unless we can allocate enough space to sprintf() into. char *xmsprintf(char *format, ...) { - va_list va, va2; - int len; - char *ret; + va_list va, va2; + int len; + char *ret; - va_start(va, format); - va_copy(va2, va); + va_start(va, format); + va_copy(va2, va); - // How long is it? - len = vsnprintf(0, 0, format, va); - len++; - va_end(va); + // How long is it? + len = vsnprintf(0, 0, format, va); + len++; + va_end(va); - // Allocate and do the sprintf() - ret = xmalloc(len); - vsnprintf(ret, len, format, va2); - va_end(va2); + // Allocate and do the sprintf() + ret = xmalloc(len); + vsnprintf(ret, len, format, va2); + va_end(va2); - return ret; + return ret; } void xprintf(char *format, ...) { - va_list va; - va_start(va, format); + va_list va; + va_start(va, format); - vprintf(format, va); - if (ferror(stdout)) perror_exit("write"); + vprintf(format, va); + if (ferror(stdout)) perror_exit("write"); } void xputs(char *s) { - if (EOF == puts(s)) perror_exit("write"); + if (EOF == puts(s)) perror_exit("write"); } void xputc(char c) { - if (EOF == fputc(c, stdout) || fflush(stdout)) perror_exit("write"); + if (EOF == fputc(c, stdout) || fflush(stdout)) perror_exit("write"); } void xflush(void) { - if (fflush(stdout)) perror_exit("write");; + if (fflush(stdout)) perror_exit("write");; } // Die unless we can exec argv[] (or run builtin command). Note that anything // with a path isn't a builtin, so /bin/sh won't match the builtin sh. void xexec(char **argv) { - toy_exec(argv); - execvp(argv[0], argv); + toy_exec(argv); + execvp(argv[0], argv); - perror_exit("exec %s", argv[0]); + perror_exit("exec %s", argv[0]); } void xaccess(char *path, int flags) { - if (access(path, flags)) perror_exit("Can't access '%s'", path); + if (access(path, flags)) perror_exit("Can't access '%s'", path); } // Die unless we can delete a file. (File must exist to be deleted.) void xunlink(char *path) { - if (unlink(path)) perror_exit("unlink '%s'", path); + if (unlink(path)) perror_exit("unlink '%s'", path); } // Die unless we can open/create a file, returning file descriptor. int xcreate(char *path, int flags, int mode) { - int fd = open(path, flags, mode); - if (fd == -1) perror_exit("%s", path); - return fd; + int fd = open(path, flags, mode); + if (fd == -1) perror_exit("%s", path); + return fd; } // Die unless we can open a file, returning file descriptor. int xopen(char *path, int flags) { - return xcreate(path, flags, 0); + return xcreate(path, flags, 0); } void xclose(int fd) { - if (close(fd)) perror_exit("xclose"); + if (close(fd)) perror_exit("xclose"); } int xdup(int fd) { - if (fd != -1) { - fd = dup(fd); - if (fd == -1) perror_exit("xdup"); - } - return fd; + if (fd != -1) { + fd = dup(fd); + if (fd == -1) perror_exit("xdup"); + } + return fd; } // Die unless we can open/create a file, returning FILE *. FILE *xfopen(char *path, char *mode) { - FILE *f = fopen(path, mode); - if (!f) perror_exit("No file %s", path); - return f; + FILE *f = fopen(path, mode); + if (!f) perror_exit("No file %s", path); + return f; } // Keep reading until full or EOF ssize_t readall(int fd, void *buf, size_t len) { - size_t count = 0; + size_t count = 0; - while (count= lseek(fd, offset, SEEK_END) - && offset+and == lseek(fd, offset+and, SEEK_SET)) return 0; - else { - char buf[4096]; - while (offset>0) { - int try = offset>sizeof(buf) ? sizeof(buf) : offset, or; + if (and != -1 && offset >= lseek(fd, offset, SEEK_END) + && offset+and == lseek(fd, offset+and, SEEK_SET)) return 0; + else { + char buf[4096]; + while (offset>0) { + int try = offset>sizeof(buf) ? sizeof(buf) : offset, or; - or = readall(fd, buf, try); - if (or < 0) perror_msg("lskip to %lld", (long long)offset); - else offset -= try; - if (or < try) break; - } + or = readall(fd, buf, try); + if (or < 0) perror_msg("lskip to %lld", (long long)offset); + else offset -= try; + if (or < try) break; + } - return offset; - } + return offset; + } } char *xgetcwd(void) { - char *buf = getcwd(NULL, 0); - if (!buf) perror_exit("xgetcwd"); + char *buf = getcwd(NULL, 0); + if (!buf) perror_exit("xgetcwd"); - return buf; + return buf; } void xstat(char *path, struct stat *st) { - if(stat(path, st)) perror_exit("Can't stat %s", path); + if(stat(path, st)) perror_exit("Can't stat %s", path); } // Cannonicalizes path by removing ".", "..", and "//" elements. This is not @@ -325,60 +324,60 @@ void xstat(char *path, struct stat *st) // following symlinks. char *xabspath(char *path) { - char *from, *to; - - // If this isn't an absolute path, make it one with cwd. - if (path[0]!='/') { - char *cwd=xgetcwd(); - path = xmsprintf("%s/%s", cwd, path); - free(cwd); - } else path = xstrdup(path); - - // Loop through path elements - from = to = path; - while (*from) { - - // Continue any current path component. - if (*from!='/') { - *(to++) = *(from++); - continue; - } - - // Skip duplicate slashes. - while (*from=='/') from++; - - // Start of a new filename. Handle . and .. - while (*from=='.') { - // Skip . - if (from[1]=='/') from += 2; - else if (!from[1]) from++; - // Back up for .. - else if (from[1]=='.') { - if (from[2]=='/') from +=3; - else if(!from[2]) from+=2; - else break; - while (to>path && *(--to)!='/'); - } else break; - } - // Add directory separator slash. - *(to++) = '/'; - } - *to = 0; - - return path; + char *from, *to; + + // If this isn't an absolute path, make it one with cwd. + if (path[0]!='/') { + char *cwd=xgetcwd(); + path = xmsprintf("%s/%s", cwd, path); + free(cwd); + } else path = xstrdup(path); + + // Loop through path elements + from = to = path; + while (*from) { + + // Continue any current path component. + if (*from!='/') { + *(to++) = *(from++); + continue; + } + + // Skip duplicate slashes. + while (*from=='/') from++; + + // Start of a new filename. Handle . and .. + while (*from=='.') { + // Skip . + if (from[1]=='/') from += 2; + else if (!from[1]) from++; + // Back up for .. + else if (from[1]=='.') { + if (from[2]=='/') from +=3; + else if(!from[2]) from+=2; + else break; + while (to>path && *(--to)!='/'); + } else break; + } + // Add directory separator slash. + *(to++) = '/'; + } + *to = 0; + + return path; } // Resolve all symlinks, returning malloc() memory. char *xrealpath(char *path) { - char *new = realpath(path, NULL); - if (!new) perror_exit("realpath '%s'", path); - return new; + char *new = realpath(path, NULL); + if (!new) perror_exit("realpath '%s'", path); + return new; } void xchdir(char *path) { - if (chdir(path)) error_exit("chdir '%s'", path); + if (chdir(path)) error_exit("chdir '%s'", path); } // Ensure entire path exists. @@ -386,27 +385,27 @@ void xchdir(char *path) // Requires that path string be writable (for temporary null terminators). void xmkpath(char *path, int mode) { - char *p, old; - mode_t mask; - int rc; - struct stat st; - - for (p = path; ; p++) { - if (!*p || *p == '/') { - old = *p; - *p = rc = 0; - if (stat(path, &st) || !S_ISDIR(st.st_mode)) { - if (mode != -1) { - mask=umask(0); - rc = mkdir(path, mode); - umask(mask); - } else rc = mkdir(path, 0777); - } - *p = old; - if(rc) perror_exit("mkpath '%s'", path); - } - if (!*p) break; - } + char *p, old; + mode_t mask; + int rc; + struct stat st; + + for (p = path; ; p++) { + if (!*p || *p == '/') { + old = *p; + *p = rc = 0; + if (stat(path, &st) || !S_ISDIR(st.st_mode)) { + if (mode != -1) { + mask=umask(0); + rc = mkdir(path, mode); + umask(mask); + } else rc = mkdir(path, 0777); + } + *p = old; + if(rc) perror_exit("mkpath '%s'", path); + } + if (!*p) break; + } } // setuid() can fail (for example, too many processes belonging to that user), @@ -414,7 +413,7 @@ void xmkpath(char *path, int mode) void xsetuid(uid_t uid) { - if (setuid(uid)) perror_exit("xsetuid"); + if (setuid(uid)) perror_exit("xsetuid"); } @@ -424,40 +423,40 @@ void xsetuid(uid_t uid) struct string_list *find_in_path(char *path, char *filename) { - struct string_list *rlist = NULL, **prlist=&rlist; - char *cwd = xgetcwd(); - - for (;;) { - char *next = path ? strchr(path, ':') : NULL; - int len = next ? next-path : strlen(path); - struct string_list *rnext; - struct stat st; - - rnext = xmalloc(sizeof(void *) + strlen(filename) - + (len ? len : strlen(cwd)) + 2); - if (!len) sprintf(rnext->str, "%s/%s", cwd, filename); - else { - char *res = rnext->str; - strncpy(res, path, len); - res += len; - *(res++) = '/'; - strcpy(res, filename); - } - - // Confirm it's not a directory. - if (!stat(rnext->str, &st) && S_ISREG(st.st_mode)) { - *prlist = rnext; - rnext->next = NULL; - prlist = &(rnext->next); - } else free(rnext); - - if (!next) break; - path += len; - path++; - } - free(cwd); - - return rlist; + struct string_list *rlist = NULL, **prlist=&rlist; + char *cwd = xgetcwd(); + + for (;;) { + char *next = path ? strchr(path, ':') : NULL; + int len = next ? next-path : strlen(path); + struct string_list *rnext; + struct stat st; + + rnext = xmalloc(sizeof(void *) + strlen(filename) + + (len ? len : strlen(cwd)) + 2); + if (!len) sprintf(rnext->str, "%s/%s", cwd, filename); + else { + char *res = rnext->str; + strncpy(res, path, len); + res += len; + *(res++) = '/'; + strcpy(res, filename); + } + + // Confirm it's not a directory. + if (!stat(rnext->str, &st) && S_ISREG(st.st_mode)) { + *prlist = rnext; + rnext->next = NULL; + prlist = &(rnext->next); + } else free(rnext); + + if (!next) break; + path += len; + path++; + } + free(cwd); + + return rlist; } // Convert unsigned int to ascii, writing into supplied buffer. A truncated @@ -465,31 +464,31 @@ struct string_list *find_in_path(char *path, char *filename) // always null terminated (unless buflen is 0). void utoa_to_buf(unsigned n, char *buf, unsigned buflen) { - int i, out = 0; + int i, out = 0; - if (buflen) { - for (i=1000000000; i; i/=10) { - int res = n/i; + if (buflen) { + for (i=1000000000; i; i/=10) { + int res = n/i; - if ((res || out || i == 1) && --buflen>0) { - out++; - n -= res*i; - *buf++ = '0' + res; - } - } - *buf = 0; - } + if ((res || out || i == 1) && --buflen>0) { + out++; + n -= res*i; + *buf++ = '0' + res; + } + } + *buf = 0; + } } // Convert signed integer to ascii, using utoa_to_buf() void itoa_to_buf(int n, char *buf, unsigned buflen) { - if (buflen && n<0) { - n = -n; - *buf++ = '-'; - buflen--; - } - utoa_to_buf((unsigned)n, buf, buflen); + if (buflen && n<0) { + n = -n; + *buf++ = '-'; + buflen--; + } + utoa_to_buf((unsigned)n, buf, buflen); } // This static buffer is used by both utoa() and itoa(), calling either one a @@ -504,122 +503,122 @@ static char itoa_buf[12]; // Convert unsigned integer to ascii, returning a static buffer. char *utoa(unsigned n) { - utoa_to_buf(n, itoa_buf, sizeof(itoa_buf)); + utoa_to_buf(n, itoa_buf, sizeof(itoa_buf)); - return itoa_buf; + return itoa_buf; } char *itoa(int n) { - itoa_to_buf(n, itoa_buf, sizeof(itoa_buf)); + itoa_to_buf(n, itoa_buf, sizeof(itoa_buf)); - return itoa_buf; + return itoa_buf; } // atol() with the kilo/mega/giga/tera/peta/exa extensions. // (zetta and yotta don't fit in 64 bits.) long atolx(char *numstr) { - char *c, *suffixes="bkmgtpe", *end; - long val = strtol(numstr, &c, 0); + char *c, *suffixes="bkmgtpe", *end; + long val = strtol(numstr, &c, 0); - if (*c) { - if (c != numstr && (end = strchr(suffixes, tolower(*c)))) { - int shift = end-suffixes; - if (shift--) val *= 1024L<<(shift*10); - } else { - while (isspace(*c)) c++; - if (*c) error_exit("not integer: %s", numstr); - } - } + if (*c) { + if (c != numstr && (end = strchr(suffixes, tolower(*c)))) { + int shift = end-suffixes; + if (shift--) val *= 1024L<<(shift*10); + } else { + while (isspace(*c)) c++; + if (*c) error_exit("not integer: %s", numstr); + } + } - return val; + return val; } int numlen(long l) { - int len = 0; - while (l) { - l /= 10; - len++; - } - return len; + int len = 0; + while (l) { + l /= 10; + len++; + } + return len; } int stridx(char *haystack, char needle) { - char *off; + char *off; - if (!needle) return -1; - off = strchr(haystack, needle); - if (!off) return -1; + if (!needle) return -1; + off = strchr(haystack, needle); + if (!off) return -1; - return off-haystack; + return off-haystack; } // Return how long the file at fd is, if there's any way to determine it. off_t fdlength(int fd) { - off_t bottom = 0, top = 0, pos, old; - int size; + off_t bottom = 0, top = 0, pos, old; + int size; - // If the ioctl works for this, return it. + // If the ioctl works for this, return it. - if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512L; + if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512L; - // If not, do a binary search for the last location we can read. (Some - // block devices don't do BLKGETSIZE right.) This should probably have - // a CONFIG option... + // If not, do a binary search for the last location we can read. (Some + // block devices don't do BLKGETSIZE right.) This should probably have + // a CONFIG option... - old = lseek(fd, 0, SEEK_CUR); - do { - char temp; + old = lseek(fd, 0, SEEK_CUR); + do { + char temp; - pos = bottom + (top - bottom) / 2; + pos = bottom + (top - bottom) / 2; - // If we can read from the current location, it's bigger. + // If we can read from the current location, it's bigger. - if (lseek(fd, pos, 0)>=0 && read(fd, &temp, 1)==1) { - if (bottom == top) bottom = top = (top+1) * 2; - else bottom = pos; + if (lseek(fd, pos, 0)>=0 && read(fd, &temp, 1)==1) { + if (bottom == top) bottom = top = (top+1) * 2; + else bottom = pos; - // If we can't, it's smaller. + // If we can't, it's smaller. - } else { - if (bottom == top) { - if (!top) return 0; - bottom = top/2; - } else top = pos; - } - } while (bottom + 1 != top); + } else { + if (bottom == top) { + if (!top) return 0; + bottom = top/2; + } else top = pos; + } + } while (bottom + 1 != top); - lseek(fd, old, SEEK_SET); + lseek(fd, old, SEEK_SET); - return pos + 1; + return pos + 1; } // This can return null (meaning file not found). It just won't return null // for memory allocation reasons. char *xreadlink(char *name) { - int len, size = 0; - char *buf = 0; + int len, size = 0; + char *buf = 0; - // Grow by 64 byte chunks until it's big enough. - for(;;) { - size +=64; - buf = xrealloc(buf, size); - len = readlink(name, buf, size); + // Grow by 64 byte chunks until it's big enough. + for(;;) { + size +=64; + buf = xrealloc(buf, size); + len = readlink(name, buf, size); - if (len<0) { - free(buf); - return 0; - } - if (len(fd = open(*argv, flags, permissions)) && !failok) { - perror_msg("%s", *argv); - toys.exitval = 1; - continue; - } - function(fd, *argv); - if (flags == O_RDONLY) close(fd); - } while (*++argv); + if (!strcmp(*argv,"-")) fd=0; + else if (0>(fd = open(*argv, flags, permissions)) && !failok) { + perror_msg("%s", *argv); + toys.exitval = 1; + continue; + } + function(fd, *argv); + if (flags == O_RDONLY) close(fd); + } while (*++argv); } // Call loopfiles_rw with O_RDONLY and !failok (common case). void loopfiles(char **argv, void (*function)(int fd, char *name)) { - loopfiles_rw(argv, O_RDONLY, 0, 0, function); + loopfiles_rw(argv, O_RDONLY, 0, 0, function); } // Slow, but small. char *get_rawline(int fd, long *plen, char end) { - char c, *buf = NULL; - long len = 0; + char c, *buf = NULL; + long len = 0; - for (;;) { - if (1>read(fd, &c, 1)) break; - if (!(len & 63)) buf=xrealloc(buf, len+65); - if ((buf[len++]=c) == end) break; - } - if (buf) buf[len]=0; - if (plen) *plen = len; + for (;;) { + if (1>read(fd, &c, 1)) break; + if (!(len & 63)) buf=xrealloc(buf, len+65); + if ((buf[len++]=c) == end) break; + } + if (buf) buf[len]=0; + if (plen) *plen = len; - return buf; + return buf; } char *get_line(int fd) { - long len; - char *buf = get_rawline(fd, &len, '\n'); + long len; + char *buf = get_rawline(fd, &len, '\n'); - if (buf && buf[--len]=='\n') buf[len]=0; + if (buf && buf[--len]=='\n') buf[len]=0; - return buf; + return buf; } // Copy the rest of in to out and close both files. void xsendfile(int in, int out) { - long len; - char buf[4096]; + long len; + char buf[4096]; - if (in<0) return; - for (;;) { - len = xread(in, buf, 4096); - if (len<1) break; - xwrite(out, buf, len); - } + if (in<0) return; + for (;;) { + len = xread(in, buf, 4096); + if (len<1) break; + xwrite(out, buf, len); + } } int wfchmodat(int fd, char *name, mode_t mode) { - int rc = fchmodat(fd, name, mode, 0); + int rc = fchmodat(fd, name, mode, 0); - if (rc) { - perror_msg("chmod '%s' to %04o", name, mode); - toys.exitval=1; - } - return rc; + if (rc) { + perror_msg("chmod '%s' to %04o", name, mode); + toys.exitval=1; + } + return rc; } static char *tempfile2zap; static void tempfile_handler(int i) { - if (1 < (long)tempfile2zap) unlink(tempfile2zap); - _exit(1); + if (1 < (long)tempfile2zap) unlink(tempfile2zap); + _exit(1); } // Open a temporary file to copy an existing file into. int copy_tempfile(int fdin, char *name, char **tempname) { - struct stat statbuf; - int fd; + struct stat statbuf; + int fd; - *tempname = xstrndup(name, strlen(name)+6); - strcat(*tempname,"XXXXXX"); - if(-1 == (fd = mkstemp(*tempname))) error_exit("no temp file"); - if (!tempfile2zap) sigatexit(tempfile_handler); - tempfile2zap = *tempname; + *tempname = xstrndup(name, strlen(name)+6); + strcat(*tempname,"XXXXXX"); + if(-1 == (fd = mkstemp(*tempname))) error_exit("no temp file"); + if (!tempfile2zap) sigatexit(tempfile_handler); + tempfile2zap = *tempname; - // Set permissions of output file + // Set permissions of output file - fstat(fdin, &statbuf); - fchmod(fd, statbuf.st_mode); + fstat(fdin, &statbuf); + fchmod(fd, statbuf.st_mode); - return fd; + return fd; } // Abort the copy and delete the temporary file. void delete_tempfile(int fdin, int fdout, char **tempname) { - close(fdin); - close(fdout); - unlink(*tempname); - tempfile2zap = (char *)1; - free(*tempname); - *tempname = NULL; + close(fdin); + close(fdout); + unlink(*tempname); + tempfile2zap = (char *)1; + free(*tempname); + *tempname = NULL; } // Copy the rest of the data and replace the original with the copy. void replace_tempfile(int fdin, int fdout, char **tempname) { - char *temp = xstrdup(*tempname); + char *temp = xstrdup(*tempname); - temp[strlen(temp)-6]=0; - if (fdin != -1) { - xsendfile(fdin, fdout); - xclose(fdin); - } - xclose(fdout); - rename(*tempname, temp); - tempfile2zap = (char *)1; - free(*tempname); - free(temp); - *tempname = NULL; + temp[strlen(temp)-6]=0; + if (fdin != -1) { + xsendfile(fdin, fdout); + xclose(fdin); + } + xclose(fdout); + rename(*tempname, temp); + tempfile2zap = (char *)1; + free(*tempname); + free(temp); + *tempname = NULL; } // Create a 256 entry CRC32 lookup table. void crc_init(unsigned int *crc_table, int little_endian) { - unsigned int i; + unsigned int i; - // Init the CRC32 table (big endian) - for (i=0; i<256; i++) { - unsigned int j, c = little_endian ? i : i<<24; - for (j=8; j; j--) - if (little_endian) c = (c&1) ? (c>>1)^0xEDB88320 : c>>1; - else c=c&0x80000000 ? (c<<1)^0x04c11db7 : (c<<1); - crc_table[i] = c; - } + // Init the CRC32 table (big endian) + for (i=0; i<256; i++) { + unsigned int j, c = little_endian ? i : i<<24; + for (j=8; j; j--) + if (little_endian) c = (c&1) ? (c>>1)^0xEDB88320 : c>>1; + else c=c&0x80000000 ? (c<<1)^0x04c11db7 : (c<<1); + crc_table[i] = c; + } } // Quick and dirty query size of terminal, doesn't do ANSI probe fallback. @@ -850,86 +849,85 @@ void crc_init(unsigned int *crc_table, int little_endian) void terminal_size(unsigned *x, unsigned *y) { - struct winsize ws; - int i; + struct winsize ws; + int i; - //memset(&ws, 0, sizeof(ws)); - for (i=0; i<3; i++) { - if (ioctl(i, TIOCGWINSZ, &ws)) continue; - if (x) *x = ws.ws_col; - if (y) *y = ws.ws_row; - } - if (x) { - char *s = getenv("COLUMNS"); + //memset(&ws, 0, sizeof(ws)); + for (i=0; i<3; i++) { + if (ioctl(i, TIOCGWINSZ, &ws)) continue; + if (x) *x = ws.ws_col; + if (y) *y = ws.ws_row; + } + if (x) { + char *s = getenv("COLUMNS"); - i = s ? atoi(s) : 0; - if (i>0) *x = i; - } - if (y) { - char *s = getenv("ROWS"); + i = s ? atoi(s) : 0; + if (i>0) *x = i; + } + if (y) { + char *s = getenv("ROWS"); - i = s ? atoi(s) : 0; - if (i>0) *y = i; - } + i = s ? atoi(s) : 0; + if (i>0) *y = i; + } } // This should use a raw tty, fixit later. int yesno(char *prompt, int def) { - FILE *fps[] = {stdin, stdout, stderr}; - int i; - char buf; + FILE *fps[] = {stdin, stdout, stderr}; + int i; + char buf; - for (i=0; i<3; i++) if (isatty(i)) break; - if (i == 3) return 1; + for (i=0; i<3; i++) if (isatty(i)) break; + if (i == 3) return 1; - fprintf(fps[i], "%s (%c/%c):", prompt, def ? 'Y' : 'y', def ? 'n' : 'N'); - fflush(fps[i]); - while (fread(&buf, 1, 1, fps[i])) { - if (tolower(buf) == 'y') def = 1; - if (tolower(buf) == 'n') def = 0; - else if (!isspace(buf)) continue; + fprintf(fps[i], "%s (%c/%c):", prompt, def ? 'Y' : 'y', def ? 'n' : 'N'); + fflush(fps[i]); + while (fread(&buf, 1, 1, fps[i])) { + if (tolower(buf) == 'y') def = 1; + if (tolower(buf) == 'n') def = 0; + else if (!isspace(buf)) continue; - break; - } + break; + } - return def; + return def; } // Execute a callback for each PID that matches a process name from a list. void for_each_pid_with_name_in(char **names, void (*callback)(pid_t pid)) { - DIR *dp; - struct dirent *entry; - char cmd[sizeof(toybuf)], path[64]; - char **curname; + DIR *dp; + struct dirent *entry; + char cmd[sizeof(toybuf)], path[64]; + char **curname; - if (!(dp = opendir("/proc"))) perror_exit("opendir"); + if (!(dp = opendir("/proc"))) perror_exit("opendir"); - while ((entry = readdir(dp))) { - int fd, n; + while ((entry = readdir(dp))) { + int fd, n; - if (!isdigit(*entry->d_name)) continue; + if (!isdigit(*entry->d_name)) continue; - if (sizeof(path) <= snprintf(path, sizeof(path), "/proc/%s/cmdline", - entry->d_name)) continue; + if (sizeof(path) <= snprintf(path, sizeof(path), "/proc/%s/cmdline", + entry->d_name)) continue; - if (-1 == (fd=open(path, O_RDONLY))) continue; - n = read(fd, cmd, sizeof(cmd)); - close(fd); - if (n<1) continue; + if (-1 == (fd=open(path, O_RDONLY))) continue; + n = read(fd, cmd, sizeof(cmd)); + close(fd); + if (n<1) continue; - for (curname = names; *curname; curname++) - if (!strcmp(basename(cmd), *curname)) - callback(atol(entry->d_name)); - } + for (curname = names; *curname; curname++) + if (!strcmp(basename(cmd), *curname)) callback(atol(entry->d_name)); + } - closedir(dp); + closedir(dp); } struct signame { - int num; - char *name; + int num; + char *name; }; // Signals required by POSIX 2008: @@ -938,16 +936,16 @@ struct signame { #define SIGNIFY(x) {SIG##x, #x} static struct signame signames[] = { - SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS), - SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL), - SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(TERM), - SIGNIFY(USR1), SIGNIFY(USR2), SIGNIFY(SYS), SIGNIFY(TRAP), - SIGNIFY(VTALRM), SIGNIFY(XCPU), SIGNIFY(XFSZ), + SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS), + SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL), + SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(TERM), + SIGNIFY(USR1), SIGNIFY(USR2), SIGNIFY(SYS), SIGNIFY(TRAP), + SIGNIFY(VTALRM), SIGNIFY(XCPU), SIGNIFY(XFSZ), - // Start of non-terminal signals + // Start of non-terminal signals - SIGNIFY(CHLD), SIGNIFY(CONT), SIGNIFY(STOP), SIGNIFY(TSTP), - SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(URG) + SIGNIFY(CHLD), SIGNIFY(CONT), SIGNIFY(STOP), SIGNIFY(TSTP), + SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(URG) }; // not in posix: SIGNIFY(STKFLT), SIGNIFY(WINCH), SIGNIFY(IO), SIGNIFY(PWR) @@ -956,147 +954,144 @@ static struct signame signames[] = { // Install the same handler on every signal that defaults to killing the process void sigatexit(void *handler) { - int i; - for (i=0; signames[i].num != SIGCHLD; i++) - signal(signames[i].num, handler); + int i; + for (i=0; signames[i].num != SIGCHLD; i++) signal(signames[i].num, handler); } // Convert name to signal number. If name == NULL print names. int sig_to_num(char *pidstr) { - int i; + int i; - if (pidstr) { - char *s; - i = strtol(pidstr, &s, 10); - if (!*s) return i; + if (pidstr) { + char *s; + i = strtol(pidstr, &s, 10); + if (!*s) return i; - if (!strncasecmp(pidstr, "sig", 3)) pidstr+=3; - } - for (i = 0; i < sizeof(signames)/sizeof(struct signame); i++) - if (!pidstr) xputs(signames[i].name); - else if (!strcasecmp(pidstr, signames[i].name)) - return signames[i].num; + if (!strncasecmp(pidstr, "sig", 3)) pidstr+=3; + } + for (i = 0; i < sizeof(signames)/sizeof(struct signame); i++) + if (!pidstr) xputs(signames[i].name); + else if (!strcasecmp(pidstr, signames[i].name)) return signames[i].num; - return -1; + return -1; } char *num_to_sig(int sig) { - int i; + int i; - for (i=0; i>(3*(s-whys)))&7; - str++; - } - - // Are we ready to do a thing yet? - if (*str && *(str++) != ',') goto barf; - - // Ok, apply the bits to the mode. - for (i=0; i<4; i++) { - for (j=0; j<3; j++) { - mode_t bit = 0; - int where = 1<<((3*i)+j); - - if (amask & where) continue; - - // Figure out new value at this location - if (i == 3) { - // suid/sticky bit. - if (j) { - if ((dowhat & 8) && (dowho&(8|(1<>(3*(s-whys)))&7; + str++; + } + + // Are we ready to do a thing yet? + if (*str && *(str++) != ',') goto barf; + + // Ok, apply the bits to the mode. + for (i=0; i<4; i++) { + for (j=0; j<3; j++) { + mode_t bit = 0; + int where = 1<<((3*i)+j); + + if (amask & where) continue; + + // Figure out new value at this location + if (i == 3) { + // suid/sticky bit. + if (j) { + if ((dowhat & 8) && (dowho&(8|(1<= 1024) { + frac = size%1024; + size /= 1024; + index++; } - else { - static char units[] = {'\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'}; - int index = 0; - while(size >= 1024) { - frac = size%1024; - size /= 1024; - index++; - } - frac = (frac/102) + ((frac%102)?1:0); - if(frac >= 10) { - size += 1; - frac = 0; - } - if(frac) return xmsprintf("%llu.%u%c", size, frac, units[index]); - else return xmsprintf("%llu%c", size, units[index]); + frac = (frac/102) + ((frac%102)?1:0); + if(frac >= 10) { + size += 1; + frac = 0; } - return NULL; //not reached + if(frac) return xmsprintf("%llu.%u%c", size, frac, units[index]); + else return xmsprintf("%llu%c", size, units[index]); + } + return NULL; //not reached } diff --git a/lib/lib.h b/lib/lib.h index d81e2d94..2b452566 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -1,4 +1,3 @@ -/* vi: set ts=4 :*/ /* lib.h - header file for lib directory * * Copyright 2006 Rob Landley @@ -21,18 +20,18 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); // is always next pointer, so next = (mytype *)&struct. struct string_list { - struct string_list *next; - char str[0]; + struct string_list *next; + char str[0]; }; struct arg_list { - struct arg_list *next; - char *arg; + struct arg_list *next; + char *arg; }; struct double_list { - struct double_list *next, *prev; - char *data; + struct double_list *next, *prev; + char *data; }; void llist_traverse(void *list, void (*using)(void *data)); @@ -63,12 +62,12 @@ void get_optflags(void); #define DIRTREE_ABORTVAL ((struct dirtree *)1) struct dirtree { - struct dirtree *next, *parent, *child; - long extra; // place for user to store their stuff (can be pointer) - struct stat st; - char *symlink; - int data; // dirfd for directory, linklen for symlink, -1 = comeagain - char name[]; + struct dirtree *next, *parent, *child; + long extra; // place for user to store their stuff (can be pointer) + struct stat st; + char *symlink; + int data; // dirfd for directory, linklen for symlink, -1 = comeagain + char name[]; }; struct dirtree *dirtree_add_node(int dirfd, char *name, int symfollow); @@ -76,9 +75,9 @@ char *dirtree_path(struct dirtree *node, int *plen); int dirtree_notdotdot(struct dirtree *catch); int dirtree_parentfd(struct dirtree *node); struct dirtree *handle_callback(struct dirtree *new, - int (*callback)(struct dirtree *node)); + int (*callback)(struct dirtree *node)); void dirtree_recurse(struct dirtree *node, - int (*callback)(struct dirtree *node), int symfollow); + int (*callback)(struct dirtree *node), int symfollow); struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)); // lib.c @@ -133,7 +132,7 @@ int stridx(char *haystack, char needle); off_t fdlength(int fd); char *xreadlink(char *name); void loopfiles_rw(char **argv, int flags, int permissions, int failok, - void (*function)(int fd, char *name)); + void (*function)(int fd, char *name)); void loopfiles(char **argv, void (*function)(int fd, char *name)); char *get_rawline(int fd, long *plen, char end); char *get_line(int fd); @@ -150,12 +149,12 @@ void for_each_pid_with_name_in(char **names, void (*callback)(pid_t pid)); // getmountlist.c struct mtab_list { - struct mtab_list *next; - struct stat stat; - struct statvfs statvfs; - char *dir; - char *device; - char type[0]; + struct mtab_list *next; + struct stat stat; + struct statvfs statvfs; + char *dir; + char *device; + char type[0]; }; struct mtab_list *getmountlist(int die); diff --git a/lib/llist.c b/lib/llist.c index 4799db1c..9b6c2950 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -1,5 +1,4 @@ -/* vi: set sw=4 ts=4 : - * llist.c - Linked list functions +/* llist.c - Linked list functions * * Linked list structures have a next pointer as their first element. */ @@ -9,47 +8,47 @@ // Call a function (such as free()) on each element of a linked list. void llist_traverse(void *list, void (*using)(void *data)) { - while (list) { - void *pop = llist_pop(&list); - using(pop); + while (list) { + void *pop = llist_pop(&list); + using(pop); - // End doubly linked list too. - if (list==pop) break; - } + // End doubly linked list too. + if (list==pop) break; + } } // Return the first item from the list, advancing the list (which must be called // as &list) void *llist_pop(void *list) { - // I'd use a void ** for the argument, and even accept the typecast in all - // callers as documentation you need the &, except the stupid compiler - // would then scream about type-punned pointers. Screw it. - void **llist = (void **)list; - void **next = (void **)*llist; - *llist = *next; - - return (void *)next; + // I'd use a void ** for the argument, and even accept the typecast in all + // callers as documentation you need the &, except the stupid compiler + // would then scream about type-punned pointers. Screw it. + void **llist = (void **)list; + void **next = (void **)*llist; + *llist = *next; + + return (void *)next; } void dlist_add_nomalloc(struct double_list **list, struct double_list *new) { - if (*list) { - new->next = *list; - new->prev = (*list)->prev; - (*list)->prev->next = new; - (*list)->prev = new; - } else *list = new->next = new->prev = new; + if (*list) { + new->next = *list; + new->prev = (*list)->prev; + (*list)->prev->next = new; + (*list)->prev = new; + } else *list = new->next = new->prev = new; } // Add an entry to the end of a doubly linked list struct double_list *dlist_add(struct double_list **list, char *data) { - struct double_list *new = xmalloc(sizeof(struct double_list)); + struct double_list *new = xmalloc(sizeof(struct double_list)); - new->data = data; - dlist_add_nomalloc(list, new); + new->data = data; + dlist_add_nomalloc(list, new); - return new; + return new; } diff --git a/lib/password.c b/lib/password.c index 8221a022..d1489eb3 100644 --- a/lib/password.c +++ b/lib/password.c @@ -1,5 +1,4 @@ -/* vi: set sw=4 ts=4 : - * pwdutils.c - password read/update helper functions. +/* pwdutils.c - password read/update helper functions. * * Copyright 2012 Ashwini Kumar */ @@ -7,136 +6,131 @@ #include "toys.h" #include - int read_password(char * buff, int buflen, char* mesg) -{ - int i = 0; - struct termios termio, oldtermio; - tcgetattr(0, &oldtermio); - tcflush(0, TCIFLUSH); - termio = oldtermio; - - termio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY); - termio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP); - tcsetattr(0, TCSANOW, &termio); - - fputs(mesg, stdout); - fflush(stdout); - - while (1) { - int ret = read(0, &buff[i], 1); - if ( ret < 0 ) { - buff[0] = 0; - tcsetattr(0, TCSANOW, &oldtermio); - return 1; - } - else if ( ret == 0 || buff[i] == '\n' || - buff[i] == '\r' || buflen == i+1) { - buff[i] = '\0'; - break; - } - i++; - } - - tcsetattr(0, TCSANOW, &oldtermio); - puts(""); - fflush(stdout); - return 0; +{ + int i = 0; + struct termios termio, oldtermio; + tcgetattr(0, &oldtermio); + tcflush(0, TCIFLUSH); + termio = oldtermio; + + termio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY); + termio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP); + tcsetattr(0, TCSANOW, &termio); + + fputs(mesg, stdout); + fflush(stdout); + + while (1) { + int ret = read(0, &buff[i], 1); + if ( ret < 0 ) { + buff[0] = 0; + tcsetattr(0, TCSANOW, &oldtermio); + return 1; + } else if (ret == 0 || buff[i] == '\n' || buff[i] == '\r' || buflen == i+1) + { + buff[i] = '\0'; + break; + } + i++; + } + + tcsetattr(0, TCSANOW, &oldtermio); + puts(""); + fflush(stdout); + return 0; } static char *get_nextcolon(const char *line, char delim) { - char *current_ptr = NULL; - if((current_ptr = strchr(line, ':')) == NULL) - error_exit("Invalid Entry\n"); - return current_ptr; + char *current_ptr = NULL; + if((current_ptr = strchr(line, ':')) == NULL) error_exit("Invalid Entry\n"); + return current_ptr; } int update_password(char *filename, char* username, char* encrypted) { - char *filenamesfx = NULL, *namesfx = NULL; - char *shadow = NULL, *sfx = NULL; - FILE *exfp, *newfp; - int ret = -1; //fail - struct flock lock; - char *line = NULL; - - shadow = strstr(filename, "shadow"); - filenamesfx = xmsprintf("%s+", filename); - sfx = strchr(filenamesfx, '+'); - - exfp = fopen(filename, "r+"); - if(!exfp) { - perror_msg("Couldn't open file %s",filename); - goto free_storage; + char *filenamesfx = NULL, *namesfx = NULL; + char *shadow = NULL, *sfx = NULL; + FILE *exfp, *newfp; + int ret = -1; //fail + struct flock lock; + char *line = NULL; + + shadow = strstr(filename, "shadow"); + filenamesfx = xmsprintf("%s+", filename); + sfx = strchr(filenamesfx, '+'); + + exfp = fopen(filename, "r+"); + if(!exfp) { + perror_msg("Couldn't open file %s",filename); + goto free_storage; + } + + *sfx = '-'; + ret = unlink(filenamesfx); + ret = link(filename, filenamesfx); + if(ret < 0) error_msg("can't create backup file"); + + *sfx = '+'; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + + ret = fcntl(fileno(exfp), F_SETLK, &lock); + if(ret < 0) perror_msg("Couldn't lock file %s",filename); + + lock.l_type = F_UNLCK; //unlocking at a later stage + + newfp = fopen(filenamesfx, "w+"); + if(!newfp) { + error_msg("couldn't open file for writing"); + ret = -1; + fclose(exfp); + goto free_storage; + } + + ret = 0; + namesfx = xmsprintf("%s:",username); + while((line = get_line(fileno(exfp))) != NULL) + { + if(strncmp(line, namesfx, strlen(namesfx)) != 0) + fprintf(newfp, "%s\n", line); + else { + char *current_ptr = NULL; + fprintf(newfp, "%s%s:",namesfx,encrypted); + current_ptr = get_nextcolon(line, ':'); //past username + current_ptr++; //past colon ':' after username + current_ptr = get_nextcolon(current_ptr, ':'); //past passwd + current_ptr++; //past colon ':' after passwd + if(shadow) { + fprintf(newfp, "%u:",(unsigned)(time(NULL))/(24*60*60)); + current_ptr = get_nextcolon(current_ptr, ':'); + current_ptr++; //past time stamp colon. + fprintf(newfp, "%s\n",current_ptr); + } + else fprintf(newfp, "%s\n",current_ptr); } - *sfx = '-'; - ret = unlink(filenamesfx); - ret = link(filename, filenamesfx); - if(ret < 0) error_msg("can't create backup file"); - - *sfx = '+'; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - - ret = fcntl(fileno(exfp), F_SETLK, &lock); - if(ret < 0) perror_msg("Couldn't lock file %s",filename); - - lock.l_type = F_UNLCK; //unlocking at a later stage - - newfp = fopen(filenamesfx, "w+"); - if(!newfp) { - error_msg("couldn't open file for writing"); - ret = -1; - fclose(exfp); - goto free_storage; - } - - ret = 0; - namesfx = xmsprintf("%s:",username); - while((line = get_line(fileno(exfp))) != NULL) - { - if(strncmp(line, namesfx, strlen(namesfx)) != 0) - fprintf(newfp, "%s\n", line); - else { - char *current_ptr = NULL; - fprintf(newfp, "%s%s:",namesfx,encrypted); - current_ptr = get_nextcolon(line, ':'); //past username - current_ptr++; //past colon ':' after username - current_ptr = get_nextcolon(current_ptr, ':'); //past passwd - current_ptr++; //past colon ':' after passwd - if(shadow) { - fprintf(newfp, "%u:",(unsigned)(time(NULL))/(24*60*60)); - current_ptr = get_nextcolon(current_ptr, ':'); - current_ptr++; //past time stamp colon. - fprintf(newfp, "%s\n",current_ptr); - } - else { - fprintf(newfp, "%s\n",current_ptr); - } - } - - free(line); - } - free(namesfx); - fcntl(fileno(exfp), F_SETLK, &lock); - fclose(exfp); - - errno = 0; - fflush(newfp); - fsync(fileno(newfp)); - fclose(newfp); - rename(filenamesfx, filename); - if(errno) { - perror_msg("File Writing/Saving failed: "); - unlink(filenamesfx); - ret = -1; - } + free(line); + } + free(namesfx); + fcntl(fileno(exfp), F_SETLK, &lock); + fclose(exfp); + + errno = 0; + fflush(newfp); + fsync(fileno(newfp)); + fclose(newfp); + rename(filenamesfx, filename); + if(errno) { + perror_msg("File Writing/Saving failed: "); + unlink(filenamesfx); + ret = -1; + } free_storage: - free(filenamesfx); - return ret; -} + free(filenamesfx); + return ret; +} diff --git a/lib/portability.c b/lib/portability.c index b1c448c8..d901a4b6 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4 :*/ /* portability.c - code to workaround the deficiencies of various platforms. * * Copyright 2012 Rob Landley @@ -10,66 +9,64 @@ #if defined(__APPLE__) || defined(__ANDROID__) ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) { - int ch; - size_t new_len; - ssize_t i = 0; - char *line, *new_line; + int ch; + size_t new_len; + ssize_t i = 0; + char *line, *new_line; - // Invalid input - if (!linep || !np) { - errno = EINVAL; - return -1; - } + // Invalid input + if (!linep || !np) { + errno = EINVAL; + return -1; + } - if (*linep == NULL || *np == 0) { - *np = 1024; - *linep = calloc(1, *np); - if (*linep == NULL) - return -1; - } - line = *linep; + if (*linep == NULL || *np == 0) { + *np = 1024; + *linep = calloc(1, *np); + if (*linep == NULL) return -1; + } + line = *linep; - while ((ch = getc(stream)) != EOF) { - if (i > *np) { - // Need more space - new_len = *np + 1024; - new_line = realloc(*linep, new_len); - if (!new_line) - return -1; - *np = new_len; - *linep = new_line; - } + while ((ch = getc(stream)) != EOF) { + if (i > *np) { + // Need more space + new_len = *np + 1024; + new_line = realloc(*linep, new_len); + if (!new_line) return -1; + *np = new_len; + *linep = new_line; + } - line[i] = ch; - if (ch == delim) - break; - i += 1; - } + line[i] = ch; + if (ch == delim) break; + i += 1; + } - if (i > *np) { - // Need more space - new_len = i + 2; - new_line = realloc(*linep, new_len); - if (!new_line) - return -1; - *np = new_len; - *linep = new_line; - } - line[i + 1] = '\0'; + if (i > *np) { + // Need more space + new_len = i + 2; + new_line = realloc(*linep, new_len); + if (!new_line) return -1; + *np = new_len; + *linep = new_line; + } + line[i + 1] = '\0'; - return i > 0 ? i : -1; + return i > 0 ? i : -1; } -ssize_t getline(char **linep, size_t *np, FILE *stream) { - return getdelim(linep, np, '\n', stream); +ssize_t getline(char **linep, size_t *np, FILE *stream) +{ + return getdelim(linep, np, '\n', stream); } #endif #if defined(__APPLE__) extern char **environ; -int clearenv(void) { - *environ = NULL; - return 0; +int clearenv(void) +{ + *environ = NULL; + return 0; } #endif diff --git a/lib/xregcomp.c b/lib/xregcomp.c index 732ce4db..ec7d1b79 100644 --- a/lib/xregcomp.c +++ b/lib/xregcomp.c @@ -1,5 +1,4 @@ -/* vi: set ts=4: - * Call regcomp() and handle errors. +/* Call regcomp() and handle errors. * * Copyright 2007 Rob Landley * @@ -12,12 +11,12 @@ void xregcomp(regex_t *preg, char *regex, int cflags) { - int rc = regcomp(preg, regex, cflags); + int rc = regcomp(preg, regex, cflags); - if (rc) { - char msg[256]; - regerror(rc, preg, msg, 255); - msg[255]=0; - error_exit("xregcomp: %s", msg); - } + if (rc) { + char msg[256]; + regerror(rc, preg, msg, 255); + msg[255]=0; + error_exit("xregcomp: %s", msg); + } } diff --git a/main.c b/main.c index 8bd0feef..c705d645 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,3 @@ -/* vi: set ts=4 :*/ /* Toybox infrastructure. * * Copyright 2006 Rob Landley @@ -25,27 +24,27 @@ char toybuf[4096]; struct toy_list *toy_find(char *name) { - int top, bottom, middle; + int top, bottom, middle; - // If the name starts with "toybox" accept that as a match. Otherwise - // skip the first entry, which is out of order. + // If the name starts with "toybox" accept that as a match. Otherwise + // skip the first entry, which is out of order. - if (!strncmp(name,"toybox",6)) return toy_list; - bottom = 1; + if (!strncmp(name,"toybox",6)) return toy_list; + bottom = 1; - // Binary search to find this applet. + // Binary search to find this applet. - top = ARRAY_LEN(toy_list)-1; - for (;;) { - int result; + top = ARRAY_LEN(toy_list)-1; + for (;;) { + int result; - middle = (top+bottom)/2; - if (middletop) return NULL; - result = strcmp(name,toy_list[middle].name); - if (!result) return toy_list+middle; - if (result<0) top=--middle; - else bottom = ++middle; - } + middle = (top+bottom)/2; + if (middletop) return NULL; + result = strcmp(name,toy_list[middle].name); + if (!result) return toy_list+middle; + if (result<0) top=--middle; + else bottom = ++middle; + } } // Figure out whether or not anything is using the option parsing logic, @@ -65,44 +64,42 @@ static const int NEED_OPTIONS = void toy_init(struct toy_list *which, char *argv[]) { - // Drop permissions for non-suid commands. + // Drop permissions for non-suid commands. - if (CFG_TOYBOX_SUID) { - uid_t uid = getuid(), euid = geteuid(); + if (CFG_TOYBOX_SUID) { + uid_t uid = getuid(), euid = geteuid(); - if (!(which->flags & TOYFLAG_STAYROOT)) { - if (uid != euid) xsetuid(euid=uid); - } else if (CFG_TOYBOX_DEBUG && uid) - error_exit("Not installed suid root"); + if (!(which->flags & TOYFLAG_STAYROOT)) { + if (uid != euid) xsetuid(euid=uid); + } else if (CFG_TOYBOX_DEBUG && uid) error_exit("Not installed suid root"); - if ((which->flags & TOYFLAG_NEEDROOT) && euid) - error_exit("Not root"); - } + if ((which->flags & TOYFLAG_NEEDROOT) && euid) error_exit("Not root"); + } - // Free old toys contents (to be reentrant) + // Free old toys contents (to be reentrant) - if (toys.optargs != toys.argv+1) free(toys.optargs); - memset(&toys, 0, sizeof(struct toy_context)); + if (toys.optargs != toys.argv+1) free(toys.optargs); + memset(&toys, 0, sizeof(struct toy_context)); - toys.which = which; - toys.argv = argv; - if (NEED_OPTIONS && which->options) get_optflags(); - else toys.optargs = argv+1; - toys.old_umask = umask(0); - if (!(which->flags & TOYFLAG_UMASK)) umask(toys.old_umask); + toys.which = which; + toys.argv = argv; + if (NEED_OPTIONS && which->options) get_optflags(); + else toys.optargs = argv+1; + toys.old_umask = umask(0); + if (!(which->flags & TOYFLAG_UMASK)) umask(toys.old_umask); } // Like exec() but runs an internal toybox command instead of another file. // Only returns if it can't find the command, otherwise exit() when done. void toy_exec(char *argv[]) { - struct toy_list *which; + struct toy_list *which; - which = toy_find(argv[0]); - if (!which) return; - toy_init(which, argv); - toys.which->toy_main(); - exit(toys.exitval); + which = toy_find(argv[0]); + if (!which) return; + toy_init(which, argv); + toys.which->toy_main(); + exit(toys.exitval); } // Multiplexer command, first argument is command to run, rest are args to that. @@ -110,52 +107,52 @@ void toy_exec(char *argv[]) void toybox_main(void) { - static char *toy_paths[]={"usr/","bin/","sbin/",0}; - int i, len = 0; - - if (toys.argv[1]) { - if (toys.argv[1][0]!='-') { - toy_exec(toys.argv+1); - toys.which = toy_list; - error_exit("Unknown command %s",toys.argv[1]); - } - } - - // Output list of applets. - for (i=1; i65) { - xputc('\n'); - len=0; - } - } - } - xputc('\n'); + static char *toy_paths[]={"usr/","bin/","sbin/",0}; + int i, len = 0; + + if (toys.argv[1]) { + if (toys.argv[1][0]!='-') { + toy_exec(toys.argv+1); + toys.which = toy_list; + error_exit("Unknown command %s",toys.argv[1]); + } + } + + // Output list of applets. + for (i=1; i65) { + xputc('\n'); + len=0; + } + } + } + xputc('\n'); } int main(int argc, char *argv[]) { - // Artificial scope to eat less stack for things we call - { - char *name; - - // Trim path off of command name - name = strrchr(argv[0], '/'); - if (!name) name=argv[0]; - else name++; - argv[0] = name; - } - - // Call the multiplexer, adjusting this argv[] to be its' argv[1]. - // (It will adjust it back before calling toy_exec().) - toys.argv = argv-1; - toybox_main(); - return 0; + // Artificial scope to eat less stack for things we call + { + char *name; + + // Trim path off of command name + name = strrchr(argv[0], '/'); + if (!name) name=argv[0]; + else name++; + argv[0] = name; + } + + // Call the multiplexer, adjusting this argv[] to be its' argv[1]. + // (It will adjust it back before calling toy_exec().) + toys.argv = argv-1; + toybox_main(); + return 0; } diff --git a/scripts/config2help.sh b/scripts/config2help.sh index 63d6c6f0..8f96e39e 100755 --- a/scripts/config2help.sh +++ b/scripts/config2help.sh @@ -29,7 +29,7 @@ if test "$0" != "bash"; then configs=$(echo "$filetxt" | egrep -ne "^config *" | cut -d\: -f1) endmenus=$(echo "$filetxt" | egrep -ne "^endmenu *" | cut -d\: -f1) let last=$(echo "$filetxt" | wc -l)+2 - + declare -i i c s e for i in $configs; do # echo -n "c:$i" >&2 @@ -40,7 +40,7 @@ if test "$0" != "bash"; then test $e -ge $s # echo " s:$s e:$e" >&2 print_h "$filetxt" $i $s $e - done + done for fle in $(cat "$file" | egrep -e "^[ \t]*source " | sed -e "s,^[ \t]*source *\(.*\),\\1,"); do $0 $fle done diff --git a/scripts/install.c b/scripts/install.c index 317b180c..cda8fc22 100644 --- a/scripts/install.c +++ b/scripts/install.c @@ -1,4 +1,3 @@ -/* vi: set ts=4 :*/ /* Wrapper to make installation easier with cross-compiling. * * Copyright 2006 Rob Landley @@ -21,20 +20,20 @@ struct toy_list toy_list[] = { int main(int argc, char *argv[]) { - static char *toy_paths[]={"usr/","bin/","sbin/",0}; - int i, len = 0; + static char *toy_paths[]={"usr/","bin/","sbin/",0}; + int i, len = 0; - // Output list of applets. - for (i=1; i1) { - int j; - for (j=0; toy_paths[j]; j++) - if (fl & (1<1) { + int j; + for (j=0; toy_paths[j]; j++) + if (fl & (1< file1 && diff -u /bin/cat file1 && echo yes" \ + "cat /proc/self/exe > file1 && diff -u /proc/self/exe file1 && echo yes" \ "yes\n" "" "" #testing "cat file1 file2" "cat /bin/cat file1 > file2 && diff -u - diff --git a/scripts/test/cp.test b/scripts/test/cp.test index 8abcc284..eea0471d 100755 --- a/scripts/test/cp.test +++ b/scripts/test/cp.test @@ -24,7 +24,7 @@ testing "cp file->dir/file" \ "yes\n" "" "" testing "cp -r dir->missing" \ "cp -r two three && cmp random three/random && echo yes" \ - "yes\n" "" "" + "yes\n" "" "" touch walrus testing "cp -r dir->file [fail]" \ "cp -r two walrus 2>/dev/null || echo yes" "yes\n" "" "" diff --git a/scripts/test/dirname.test b/scripts/test/dirname.test old mode 100644 new mode 100755 index 9afa4508..a0075384 --- a/scripts/test/dirname.test +++ b/scripts/test/dirname.test @@ -6,5 +6,5 @@ testing "dirname /-only" "dirname ///////" "/\n" "" "" testing "dirname trailing /" "dirname a//////" ".\n" "" "" -testing "dirname combined" "dirname /////a///b///c///d/////" "/////a///b///c\n" "" "" +testing "dirname combined" "dirname /////a///b///c///d/////" "/////a///b///c\n" "" "" testing "dirname /a/" "dirname /////a///" "/\n" "" "" diff --git a/scripts/test/xargs.test b/scripts/test/xargs.test index 2d3946b3..e49445d6 100755 --- a/scripts/test/xargs.test +++ b/scripts/test/xargs.test @@ -26,7 +26,7 @@ rm one two three exit -testing "xargs -n exact match" +testing "xargs -n exact match" testing "xargs -s exact match" testing "xargs -s 0" testing "xargs -s impossible" diff --git a/toys.h b/toys.h index eb7c67f6..72670cd7 100644 --- a/toys.h +++ b/toys.h @@ -1,4 +1,3 @@ -/* vi: set ts=4 :*/ /* Toybox infrastructure. * * Copyright 2006 Rob Landley @@ -87,23 +86,23 @@ void toy_exec(char *argv[]); // Array of available applets extern struct toy_list { - char *name; - void (*toy_main)(void); - char *options; - int flags; + char *name; + void (*toy_main)(void); + char *options; + int flags; } toy_list[]; // Global context shared by all commands. extern struct toy_context { - struct toy_list *which; // Which entry in toy_list is this one? - int exitval; // Value error_exit feeds to exit() - char **argv; // Original command line arguments - unsigned optflags; // Command line option flags from get_optflags() - char **optargs; // Arguments left over from get_optflags() - int optc; // Count of optargs - int exithelp; // Should error_exit print a usage message first? - int old_umask; // Old umask preserved by TOYFLAG_UMASK + struct toy_list *which; // Which entry in toy_list is this one? + int exitval; // Value error_exit feeds to exit() + char **argv; // Original command line arguments + unsigned optflags; // Command line option flags from get_optflags() + char **optargs; // Arguments left over from get_optflags() + int optc; // Count of optargs + int exithelp; // Should error_exit print a usage message first? + int old_umask; // Old umask preserved by TOYFLAG_UMASK } toys; // One big temporary buffer, for use by commands (not library functions). diff --git a/toys/e2fs.h b/toys/e2fs.h index 13474804..43594114 100644 --- a/toys/e2fs.h +++ b/toys/e2fs.h @@ -1,6 +1,4 @@ -/* vi: set ts=4: - * - * mke2fs.h - Headers for ext2 +/* mke2fs.h - Headers for ext2 * * Copyright 2006 Rob Landley */ @@ -10,103 +8,103 @@ #define EXT2_SUPER_MAGIC 0xEF53 struct ext2_superblock { - uint32_t inodes_count; // Inodes count - uint32_t blocks_count; // Blocks count - uint32_t r_blocks_count; // Reserved blocks count - uint32_t free_blocks_count; // Free blocks count - uint32_t free_inodes_count; // Free inodes count - uint32_t first_data_block; // First Data Block - uint32_t log_block_size; // Block size - uint32_t log_frag_size; // Fragment size - uint32_t blocks_per_group; // Blocks per group - uint32_t frags_per_group; // Fragments per group - uint32_t inodes_per_group; // Inodes per group - uint32_t mtime; // Mount time - uint32_t wtime; // Write time - uint16_t mnt_count; // Mount count - uint16_t max_mnt_count; // Maximal mount count - uint16_t magic; // Magic signature - uint16_t state; // File system state - uint16_t errors; // Behaviour when detecting errors - uint16_t minor_rev_level; // minor revision level - uint32_t lastcheck; // time of last check - uint32_t checkinterval; // max. time between checks - uint32_t creator_os; // OS - uint32_t rev_level; // Revision level - uint16_t def_resuid; // Default uid for reserved blocks - uint16_t def_resgid; // Default gid for reserved blocks - uint32_t first_ino; // First non-reserved inode - uint16_t inode_size; // size of inode structure - uint16_t block_group_nr; // block group # of this superblock - uint32_t feature_compat; // compatible feature set - uint32_t feature_incompat; // incompatible feature set - uint32_t feature_ro_compat; // readonly-compatible feature set - char uuid[16]; // 128-bit uuid for volume - char volume_name[16]; // volume name - char last_mounted[64]; // directory where last mounted - uint32_t alg_usage_bitmap; // For compression - // For EXT2_COMPAT_PREALLOC - uint8_t prealloc_blocks; // Nr of blocks to try to preallocate - uint8_t prealloc_dir_blocks; //Nr to preallocate for dirs - uint16_t padding1; - // For EXT3_FEATURE_COMPAT_HAS_JOURNAL - uint8_t journal_uuid[16]; // uuid of journal superblock - uint32_t journal_inum; // inode number of journal file - uint32_t journal_dev; // device number of journal file - uint32_t last_orphan; // start of list of inodes to delete - uint32_t hash_seed[4]; // HTREE hash seed - uint8_t def_hash_version; // Default hash version to use - uint8_t padding2[3]; - uint32_t default_mount_opts; - uint32_t first_meta_bg; // First metablock block group - uint32_t mkfs_time; // Creation timestamp - uint32_t jnl_blocks[17]; // Backup of journal inode - // uint32_t reserved[172]; // Padding to the end of the block + uint32_t inodes_count; // Inodes count + uint32_t blocks_count; // Blocks count + uint32_t r_blocks_count; // Reserved blocks count + uint32_t free_blocks_count; // Free blocks count + uint32_t free_inodes_count; // Free inodes count + uint32_t first_data_block; // First Data Block + uint32_t log_block_size; // Block size + uint32_t log_frag_size; // Fragment size + uint32_t blocks_per_group; // Blocks per group + uint32_t frags_per_group; // Fragments per group + uint32_t inodes_per_group; // Inodes per group + uint32_t mtime; // Mount time + uint32_t wtime; // Write time + uint16_t mnt_count; // Mount count + uint16_t max_mnt_count; // Maximal mount count + uint16_t magic; // Magic signature + uint16_t state; // File system state + uint16_t errors; // Behaviour when detecting errors + uint16_t minor_rev_level; // minor revision level + uint32_t lastcheck; // time of last check + uint32_t checkinterval; // max. time between checks + uint32_t creator_os; // OS + uint32_t rev_level; // Revision level + uint16_t def_resuid; // Default uid for reserved blocks + uint16_t def_resgid; // Default gid for reserved blocks + uint32_t first_ino; // First non-reserved inode + uint16_t inode_size; // size of inode structure + uint16_t block_group_nr; // block group # of this superblock + uint32_t feature_compat; // compatible feature set + uint32_t feature_incompat; // incompatible feature set + uint32_t feature_ro_compat; // readonly-compatible feature set + char uuid[16]; // 128-bit uuid for volume + char volume_name[16]; // volume name + char last_mounted[64]; // directory where last mounted + uint32_t alg_usage_bitmap; // For compression + // For EXT2_COMPAT_PREALLOC + uint8_t prealloc_blocks; // Nr of blocks to try to preallocate + uint8_t prealloc_dir_blocks; //Nr to preallocate for dirs + uint16_t padding1; + // For EXT3_FEATURE_COMPAT_HAS_JOURNAL + uint8_t journal_uuid[16]; // uuid of journal superblock + uint32_t journal_inum; // inode number of journal file + uint32_t journal_dev; // device number of journal file + uint32_t last_orphan; // start of list of inodes to delete + uint32_t hash_seed[4]; // HTREE hash seed + uint8_t def_hash_version; // Default hash version to use + uint8_t padding2[3]; + uint32_t default_mount_opts; + uint32_t first_meta_bg; // First metablock block group + uint32_t mkfs_time; // Creation timestamp + uint32_t jnl_blocks[17]; // Backup of journal inode + // uint32_t reserved[172]; // Padding to the end of the block }; struct ext2_group { - uint32_t block_bitmap; // Block number of block bitmap - uint32_t inode_bitmap; // Block number of inode bitmap - uint32_t inode_table; // Block number of inode table - uint16_t free_blocks_count; // How many free blocks in this group? - uint16_t free_inodes_count; // How many free inodes in this group? - uint16_t used_dirs_count; // How many directories? - uint16_t reserved[7]; // pad to 32 bytes + uint32_t block_bitmap; // Block number of block bitmap + uint32_t inode_bitmap; // Block number of inode bitmap + uint32_t inode_table; // Block number of inode table + uint16_t free_blocks_count; // How many free blocks in this group? + uint16_t free_inodes_count; // How many free inodes in this group? + uint16_t used_dirs_count; // How many directories? + uint16_t reserved[7]; // pad to 32 bytes }; struct ext2_dentry { - uint32_t inode; // Inode number - uint16_t rec_len; // Directory entry length - uint8_t name_len; // Name length - uint8_t file_type; - char name[0]; // File name + uint32_t inode; // Inode number + uint16_t rec_len; // Directory entry length + uint8_t name_len; // Name length + uint8_t file_type; + char name[0]; // File name }; struct ext2_inode { - uint16_t mode; // File mode - uint16_t uid; // Low 16 bits of Owner Uid - uint32_t size; // Size in bytes - uint32_t atime; // Access time - uint32_t ctime; // Creation time - uint32_t mtime; // Modification time - uint32_t dtime; // Deletion Time - uint16_t gid; // Low 16 bits of Group Id - uint16_t links_count; // Links count - uint32_t blocks; // Blocks count - uint32_t flags; // File flags - uint32_t reserved1; - uint32_t block[15]; // Pointers to blocks - uint32_t generation; // File version (for NFS) - uint32_t file_acl; // File ACL - uint32_t dir_acl; // Directory ACL (or top bits of file length) - uint32_t faddr; // Last block in file - uint8_t frag; // Fragment number - uint8_t fsize; // Fragment size - uint16_t pad1; - uint16_t uid_high; // High bits of uid - uint16_t gid_high; // High bits of gid - uint32_t reserved2; + uint16_t mode; // File mode + uint16_t uid; // Low 16 bits of Owner Uid + uint32_t size; // Size in bytes + uint32_t atime; // Access time + uint32_t ctime; // Creation time + uint32_t mtime; // Modification time + uint32_t dtime; // Deletion Time + uint16_t gid; // Low 16 bits of Group Id + uint16_t links_count; // Links count + uint32_t blocks; // Blocks count + uint32_t flags; // File flags + uint32_t reserved1; + uint32_t block[15]; // Pointers to blocks + uint32_t generation; // File version (for NFS) + uint32_t file_acl; // File ACL + uint32_t dir_acl; // Directory ACL (or top bits of file length) + uint32_t faddr; // Last block in file + uint8_t frag; // Fragment number + uint8_t fsize; // Fragment size + uint16_t pad1; + uint16_t uid_high; // High bits of uid + uint16_t gid_high; // High bits of gid + uint32_t reserved2; }; #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 @@ -132,13 +130,13 @@ struct ext2_inode { // other bits are reserved for now. enum { - EXT2_FT_UNKNOWN, - EXT2_FT_REG_FILE, - EXT2_FT_DIR, - EXT2_FT_CHRDEV, - EXT2_FT_BLKDEV, - EXT2_FT_FIFO, - EXT2_FT_SOCK, - EXT2_FT_SYMLINK, - EXT2_FT_MAX + EXT2_FT_UNKNOWN, + EXT2_FT_REG_FILE, + EXT2_FT_DIR, + EXT2_FT_CHRDEV, + EXT2_FT_BLKDEV, + EXT2_FT_FIFO, + EXT2_FT_SOCK, + EXT2_FT_SYMLINK, + EXT2_FT_MAX }; diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c index 8d73513b..10032562 100644 --- a/toys/lsb/dmesg.c +++ b/toys/lsb/dmesg.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * dmesg.c - display/control kernel ring buffer. +/* dmesg.c - display/control kernel ring buffer. * * Copyright 2006, 2007 Rob Landley * @@ -9,16 +7,16 @@ USE_DMESG(NEWTOY(dmesg, "s#n#c", TOYFLAG_BIN)) config DMESG - bool "dmesg" - default y - help - usage: dmesg [-n level] [-s bufsize] | -c + bool "dmesg" + default y + help + usage: dmesg [-n level] [-s bufsize] | -c - Print or control the kernel ring buffer. + Print or control the kernel ring buffer. - -n Set kernel logging level (1-9). - -s Size of buffer to read (in bytes), default 16384. - -c Clear the ring buffer after printing. + -n Set kernel logging level (1-9). + -s Size of buffer to read (in bytes), default 16384. + -c Clear the ring buffer after printing. */ #define FOR_dmesg @@ -26,33 +24,32 @@ config DMESG #include GLOBALS( - long level; - long size; + long level; + long size; ) void dmesg_main(void) { - // For -n just tell kernel to which messages to keep. - if (toys.optflags & 2) { - if (klogctl(8, NULL, TT.level)) - error_exit("klogctl"); - } else { - int size, i, last = '\n'; - char *data; - - // Figure out how much data we need, and fetch it. - size = TT.size; - if (size<2) size = 16384; - data = xmalloc(size); - size = klogctl(3 + (toys.optflags&1), data, size); - if (size < 0) error_exit("klogctl"); - - // Display data, filtering out level markers. - for (i=0; i * @@ -9,12 +7,12 @@ USE_HOSTNAME(NEWTOY(hostname, NULL, TOYFLAG_BIN)) config HOSTNAME - bool "hostname" - default y - help - usage: hostname [newname] + bool "hostname" + default y + help + usage: hostname [newname] - Get/Set the current hostname + Get/Set the current hostname */ #define FOR_hostname @@ -22,13 +20,12 @@ config HOSTNAME void hostname_main(void) { - const char *hostname = toys.optargs[0]; - if (hostname) { - if (sethostname(hostname, strlen(hostname))) - perror_exit("set failed '%s'", hostname); - } else { - if (gethostname(toybuf, sizeof(toybuf))) - perror_exit("get failed"); - xputs(toybuf); - } + const char *hostname = toys.optargs[0]; + if (hostname) { + if (sethostname(hostname, strlen(hostname))) + perror_exit("set failed '%s'", hostname); + } else { + if (gethostname(toybuf, sizeof(toybuf))) perror_exit("get failed"); + xputs(toybuf); + } } diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c index ec9df62e..7883c53d 100644 --- a/toys/lsb/killall.c +++ b/toys/lsb/killall.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * killall.c - Send signal (default: TERM) to all processes with given names. +/* killall.c - Send signal (default: TERM) to all processes with given names. * * Copyright 2012 Andreas Heck * @@ -9,68 +7,67 @@ USE_KILLALL(NEWTOY(killall, "<1?lq", TOYFLAG_USR|TOYFLAG_BIN)) config KILLALL - bool "killall" - default y - help - usage: killall [-l] [-q] [-SIG] PROCESS_NAME... + bool "killall" + default y + help + usage: killall [-l] [-q] [-SIG] PROCESS_NAME... - Send a signal (default: TERM) to all processes with the given names. + Send a signal (default: TERM) to all processes with the given names. - -l print list of all available signals - -q don't print any warnings or error messages + -l print list of all available signals + -q don't print any warnings or error messages */ #define FOR_killall #include "toys.h" GLOBALS( - int signum; + int signum; ) static void kill_process(pid_t pid) { - int ret; + int ret; - toys.exitval = 0; - ret = kill(pid, TT.signum); + toys.exitval = 0; + ret = kill(pid, TT.signum); - if (ret == -1 && !(toys.optflags & FLAG_q)) perror("kill"); + if (ret == -1 && !(toys.optflags & FLAG_q)) perror("kill"); } void killall_main(void) { - char **names; + char **names; - if (toys.optflags & FLAG_l) { - sig_to_num(NULL); - return; - } + if (toys.optflags & FLAG_l) { + sig_to_num(NULL); + return; + } - TT.signum = SIGTERM; - toys.exitval++; + TT.signum = SIGTERM; + toys.exitval++; - if (!*toys.optargs) { - toys.exithelp = 1; - error_exit("Process name missing!"); - } + if (!*toys.optargs) { + toys.exithelp = 1; + error_exit("Process name missing!"); + } - names = toys.optargs; + names = toys.optargs; - if (**names == '-') { - if (0 > (TT.signum = sig_to_num((*names)+1))) { - if (toys.optflags & FLAG_q) exit(1); - error_exit("Invalid signal"); - } - names++; + if (**names == '-') { + if (0 > (TT.signum = sig_to_num((*names)+1))) { + if (toys.optflags & FLAG_q) exit(1); + error_exit("Invalid signal"); + } + names++; - if (!*names) { - toys.exithelp++; - error_exit("Process name missing!"); - } - } + if (!*names) { + toys.exithelp++; + error_exit("Process name missing!"); + } + } - for_each_pid_with_name_in(names, kill_process); + for_each_pid_with_name_in(names, kill_process); - if (toys.exitval && !(toys.optflags & FLAG_q)) - error_exit("No such process"); + if (toys.exitval && !(toys.optflags & FLAG_q)) error_exit("No such process"); } diff --git a/toys/lsb/md5sum.c b/toys/lsb/md5sum.c index b0b35419..3b5571bb 100644 --- a/toys/lsb/md5sum.c +++ b/toys/lsb/md5sum.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * md5sum.c - Calculate RFC 1321 md5 hash and sha1 hash. +/* md5sum.c - Calculate RFC 1321 md5 hash and sha1 hash. * * Copyright 2012 Rob Landley * @@ -219,8 +217,7 @@ static void do_hash(int fd, char *name) buf = 0; } while ((TT.count & 63) != 56); if (sha1) count=bswap_64(count); - for (i = 0; i < 8; i++) - TT.buffer.c[56+i] = count >> (8*i); + for (i = 0; i < 8; i++) TT.buffer.c[56+i] = count >> (8*i); transform(); if (sha1) diff --git a/toys/lsb/mknod.c b/toys/lsb/mknod.c index c1d78b10..bf9288ae 100644 --- a/toys/lsb/mknod.c +++ b/toys/lsb/mknod.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mknod.c - make block or character special file +/* mknod.c - make block or character special file * * Copyright 2012 Elie De Brauwer * @@ -9,15 +7,15 @@ USE_MKNOD(NEWTOY(mknod, "<2>4", TOYFLAG_BIN)) config MKNOD - bool "mknod" - default y - help - usage: mknod NAME TYPE [MAJOR MINOR] - - Create a special file NAME with a given type, possible types are - b block device - c or u character device - p named pipe (ignores MAJOR/MINOR) + bool "mknod" + default y + help + usage: mknod NAME TYPE [MAJOR MINOR] + + Create a special file NAME with a given type, possible types are + b block device + c or u character device + p named pipe (ignores MAJOR/MINOR) */ #define FOR_mknod @@ -25,20 +23,19 @@ config MKNOD void mknod_main(void) { - mode_t modes[] = {S_IFIFO, S_IFCHR, S_IFCHR, S_IFBLK}; - int major=0, minor=0, type; - int mode = 0660; - - type = stridx("pcub", *toys.optargs[1]); - if (type == -1) perror_exit("bad type '%c'", *toys.optargs[1]); - if (type) { - if (toys.optc != 4) perror_exit("need major/minor"); + mode_t modes[] = {S_IFIFO, S_IFCHR, S_IFCHR, S_IFBLK}; + int major=0, minor=0, type; + int mode = 0660; - major = atoi(toys.optargs[2]); - minor = atoi(toys.optargs[3]); - } + type = stridx("pcub", *toys.optargs[1]); + if (type == -1) perror_exit("bad type '%c'", *toys.optargs[1]); + if (type) { + if (toys.optc != 4) perror_exit("need major/minor"); - if (mknod(toys.optargs[0], mode | modes[type], makedev(major, minor))) - perror_exit("mknod %s failed", toys.optargs[0]); + major = atoi(toys.optargs[2]); + minor = atoi(toys.optargs[3]); + } + if (mknod(toys.optargs[0], mode | modes[type], makedev(major, minor))) + perror_exit("mknod %s failed", toys.optargs[0]); } diff --git a/toys/lsb/mktemp.c b/toys/lsb/mktemp.c index 1b2222c0..86c2033e 100644 --- a/toys/lsb/mktemp.c +++ b/toys/lsb/mktemp.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mktemp.c - Create a temporary file or directory. +/* mktemp.c - Create a temporary file or directory. * * Copyright 2012 Elie De Brauwer * @@ -9,46 +7,46 @@ USE_MKTEMP(NEWTOY(mktemp, ">1q(directory)d(tmpdir)p:", TOYFLAG_BIN)) config MKTEMP - bool "mktemp" - default y - help - usage: mktemp [-dq] [-p DIR] [TEMPLATE] + bool "mktemp" + default y + help + usage: mktemp [-dq] [-p DIR] [TEMPLATE] - Safely create new file and print its name. Default TEMPLATE is - /tmp/tmp.XXXXXX and each trailing X is replaced with random char. + Safely create new file and print its name. Default TEMPLATE is + /tmp/tmp.XXXXXX and each trailing X is replaced with random char. - -d, --directory Create directory instead of file - -p DIR, --tmpdir=DIR Put new file in DIR - -q Quiet + -d, --directory Create directory instead of file + -p DIR, --tmpdir=DIR Put new file in DIR + -q Quiet */ #define FOR_mktemp #include "toys.h" GLOBALS( - char * tmpdir; + char * tmpdir; ) void mktemp_main(void) { - int d_flag = toys.optflags & FLAG_d; - char *tmp; + int d_flag = toys.optflags & FLAG_d; + char *tmp; - tmp = *toys.optargs; + tmp = *toys.optargs; - if (!tmp) { - if (!TT.tmpdir) TT.tmpdir = "/tmp"; - tmp = "tmp.xxxxxx"; - } - if (TT.tmpdir) tmp = xmsprintf("%s/%s", TT.tmpdir ? TT.tmpdir : "/tmp", - *toys.optargs ? *toys.optargs : "tmp.XXXXXX"); + if (!tmp) { + if (!TT.tmpdir) TT.tmpdir = "/tmp"; + tmp = "tmp.xxxxxx"; + } + if (TT.tmpdir) tmp = xmsprintf("%s/%s", TT.tmpdir ? TT.tmpdir : "/tmp", + *toys.optargs ? *toys.optargs : "tmp.XXXXXX"); - if (d_flag ? mkdtemp(tmp) == NULL : mkstemp(tmp) == -1) - if (toys.optflags & FLAG_q) - perror_exit("Failed to create temporary %s", - d_flag ? "directory" : "file"); + if (d_flag ? mkdtemp(tmp) == NULL : mkstemp(tmp) == -1) + if (toys.optflags & FLAG_q) + perror_exit("Failed to create temporary %s", + d_flag ? "directory" : "file"); - xputs(tmp); + xputs(tmp); - if (CFG_TOYBOX_FREE && TT.tmpdir) free(tmp); + if (CFG_TOYBOX_FREE && TT.tmpdir) free(tmp); } diff --git a/toys/lsb/passwd.c b/toys/lsb/passwd.c index ef119c5d..ff109f14 100644 --- a/toys/lsb/passwd.c +++ b/toys/lsb/passwd.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * passwd.c - Program to upadte user password. +/* passwd.c - Program to update user password. * * Copyright 2012 Ashwini Kumar * Modified 2012 Jason Kyungwan Han @@ -10,18 +8,17 @@ USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN)) config PASSWD - bool "passwd" - default y - help - usage: passwd [-a ALGO] [-d] [-l] [-u] - - update user’s authentication tokens. Default : current user + bool "passwd" + default y + help + usage: passwd [-a ALGO] [-d] [-l] [-u] - -a ALGO Encryption method (des, md5, sha256, sha512) default: des - -d Set password to '' - -l Lock (disable) account - -u Unlock (enable) account + update user’s authentication tokens. Default : current user + -a ALGO Encryption method (des, md5, sha256, sha512) default: des + -d Set password to '' + -l Lock (disable) account + -u Unlock (enable) account */ #define FOR_passwd @@ -29,7 +26,7 @@ config PASSWD #include GLOBALS( - char *algo; + char *algo; ) #define MAX_SALT_LEN 20 //3 for id, 16 for key, 1 for '\0' @@ -41,227 +38,225 @@ char *strcasestr(const char *haystack, const char *needle); unsigned int random_number_generator(int fd) { - unsigned int randnum; - xreadall(fd, &randnum, sizeof(randnum)); - return randnum; + unsigned int randnum; + xreadall(fd, &randnum, sizeof(randnum)); + return randnum; } - - char inttoc(int i) { - // salt value uses 64 chracters in "./0-9a-zA-Z" - const char character_set[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - i &= 0x3f; // masking for using 10 bits only - return character_set[i]; + // salt value uses 64 chracters in "./0-9a-zA-Z" + const char character_set[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + i &= 0x3f; // masking for using 10 bits only + return character_set[i]; } int get_salt(char *salt) -{ - int i, salt_length = 0; - int randfd; - if(!strncmp(TT.algo,"des",3)){ - // 2 bytes salt value is used in des - salt_length = 2; - } else { - *salt++ = '$'; - if(!strncmp(TT.algo,"md5",3)){ - *salt++ = '1'; - // 8 bytes salt value is used in md5 - salt_length = 8; - } else if(!strncmp(TT.algo,"sha256",6)){ - *salt++ = '5'; - // 16 bytes salt value is used in sha256 - salt_length = 16; - } else if(!strncmp(TT.algo,"sha512",6)){ - *salt++ = '6'; - // 16 bytes salt value is used in sha512 - salt_length = 16; - } else return 1; - - *salt++ = '$'; - } - - randfd = xopen(URANDOM_PATH, O_RDONLY); - for(i=0; ipw_name); - - pw = getpwnam(name); - if(!pw) error_exit("Unknown user '%s'",name); - - if(myuid != 0 && (myuid != pw->pw_uid)) - error_exit("You need to be root to change '%s' password\n", name); - - pass = pw->pw_passwd; - if(pw->pw_passwd[0] == 'x') { - /*get shadow passwd */ - sp = getspnam(name); - if(sp) - pass = sp->sp_pwdp; + uid_t myuid; + struct passwd *pw; + struct spwd *sp; + char *name = NULL; + char *pass = NULL, *encrypted = NULL, *newp = NULL; + char *orig = (char *)""; + char salt[MAX_SALT_LEN]; + int ret = -1; + + myuid = getuid(); + if((myuid != 0) && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) + error_exit("You need to be root to do these actions\n"); + + pw = getpwuid(myuid); + + if(!pw) + error_exit("Unknown uid '%u'",myuid); + + if(toys.optargs[0]) + name = toys.optargs[0]; + else + name = xstrdup(pw->pw_name); + + pw = getpwnam(name); + if(!pw) error_exit("Unknown user '%s'",name); + + if(myuid != 0 && (myuid != pw->pw_uid)) + error_exit("You need to be root to change '%s' password\n", name); + + pass = pw->pw_passwd; + if(pw->pw_passwd[0] == 'x') { + /*get shadow passwd */ + sp = getspnam(name); + if(sp) + pass = sp->sp_pwdp; + } + + + if(!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) { + printf("Changing password for %s\n",name); + if(pass[0] == '!') + error_exit("Can't change, password is locked for %s",name); + if(myuid != 0) { + /*Validate user */ + + if(read_password(toybuf, sizeof(toybuf), "Origial password:")) { + if(!toys.optargs[0]) free(name); + return; + } + orig = toybuf; + if(verify_passwd(pass)) + error_exit("Authentication failed\n"); } + orig = xstrdup(orig); - if(!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) { - printf("Changing password for %s\n",name); - if(pass[0] == '!') - error_exit("Can't change, password is locked for %s",name); - if(myuid != 0) { - /*Validate user */ - - if(read_password(toybuf, sizeof(toybuf), "Origial password:")) { - if(!toys.optargs[0]) free(name); - return; - } - orig = toybuf; - if(verify_passwd(pass)) - error_exit("Authentication failed\n"); - } - - orig = xstrdup(orig); - - /*Get new password */ - newp = new_password(orig, name); - if(!newp) { - free(orig); - if(!toys.optargs[0]) free(name); - return; //new password is not set well. - } - - /*Encrypt the passwd */ - if(!(toys.optflags & FLAG_a)) TT.algo = "des"; - - if(get_salt(salt)) - error_exit("Error: Unkown encryption algorithm\n"); - - encrypted = crypt(newp, salt); - free(newp); - free(orig); + /*Get new password */ + newp = new_password(orig, name); + if(!newp) { + free(orig); + if(!toys.optargs[0]) free(name); + return; //new password is not set well. } - else if(toys.optflags & FLAG_l) { - if(pass[0] == '!') - error_exit("password is already locked for %s",name); - printf("Locking password for %s\n",name); - encrypted = xmsprintf("!%s",pass); - } - else if(toys.optflags & FLAG_u) { - if(pass[0] != '!') - error_exit("password is already unlocked for %s",name); - printf("Unlocking password for %s\n",name); - encrypted = xstrdup(&pass[1]); - } - else if(toys.optflags & FLAG_d) { - printf("Deleting password for %s\n",name); - encrypted = (char*)xzalloc(sizeof(char)*2); //1 = "", 2 = '\0' - } + /*Encrypt the passwd */ + if(!(toys.optflags & FLAG_a)) TT.algo = "des"; - /*Update the passwd */ - if(pw->pw_passwd[0] == 'x') - ret = update_password("/etc/shadow", name, encrypted); - else - ret = update_password("/etc/passwd", name, encrypted); + if(get_salt(salt)) + error_exit("Error: Unkown encryption algorithm\n"); - if((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) - free(encrypted); - - if(!toys.optargs[0]) free(name); - if(!ret) - error_msg("Success"); - else - error_msg("Failure"); + encrypted = crypt(newp, salt); + free(newp); + free(orig); + } + else if(toys.optflags & FLAG_l) { + if(pass[0] == '!') + error_exit("password is already locked for %s",name); + printf("Locking password for %s\n",name); + encrypted = xmsprintf("!%s",pass); + } + else if(toys.optflags & FLAG_u) { + if(pass[0] != '!') + error_exit("password is already unlocked for %s",name); + + printf("Unlocking password for %s\n",name); + encrypted = xstrdup(&pass[1]); + } + else if(toys.optflags & FLAG_d) { + printf("Deleting password for %s\n",name); + encrypted = (char*)xzalloc(sizeof(char)*2); //1 = "", 2 = '\0' + } + + /*Update the passwd */ + if(pw->pw_passwd[0] == 'x') + ret = update_password("/etc/shadow", name, encrypted); + else + ret = update_password("/etc/passwd", name, encrypted); + + if((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) + free(encrypted); + + if(!toys.optargs[0]) free(name); + if(!ret) + error_msg("Success"); + else + error_msg("Failure"); } diff --git a/toys/lsb/pidof.c b/toys/lsb/pidof.c index 45c398b4..03643015 100644 --- a/toys/lsb/pidof.c +++ b/toys/lsb/pidof.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * pidof.c - Print the PIDs of all processes with the given names. +/* pidof.c - Print the Process IDs of all processes with the given names. * * Copyright 2012 Andreas Heck * @@ -9,24 +7,25 @@ USE_PIDOF(NEWTOY(pidof, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config PIDOF - bool "pidof" - default y - help - usage: pidof [NAME]... + bool "pidof" + default y + help + usage: pidof [NAME]... - Print the PIDs of all processes with the given names. + Print the PIDs of all processes with the given names. */ #include "toys.h" -static void print_pid(pid_t pid) { - xprintf("%s%ld", toys.exitval ? "" : " ", (long)pid); - toys.exitval = 0; +static void print_pid(pid_t pid) +{ + xprintf("%s%ld", toys.exitval ? "" : " ", (long)pid); + toys.exitval = 0; } void pidof_main(void) { - toys.exitval = 1; - for_each_pid_with_name_in(toys.optargs, print_pid); - if (!toys.exitval) xputc('\n'); + toys.exitval = 1; + for_each_pid_with_name_in(toys.optargs, print_pid); + if (!toys.exitval) xputc('\n'); } diff --git a/toys/lsb/seq.c b/toys/lsb/seq.c index 2f8538cf..22e45dde 100644 --- a/toys/lsb/seq.c +++ b/toys/lsb/seq.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * seq.c - Count from first to last, by increment. +/* seq.c - Count from first to last, by increment. * * Copyright 2006 Rob Landley * @@ -9,40 +7,40 @@ USE_SEQ(NEWTOY(seq, "<1>3?", TOYFLAG_USR|TOYFLAG_BIN)) config SEQ - bool "seq" - depends on TOYBOX_FLOAT - default y - help - usage: seq [first] [increment] last + bool "seq" + depends on TOYBOX_FLOAT + default y + help + usage: seq [first] [increment] last - Count from first to last, by increment. Omitted arguments default - to 1. Two arguments are used as first and last. Arguments can be - negative or floating point. + Count from first to last, by increment. Omitted arguments default + to 1. Two arguments are used as first and last. Arguments can be + negative or floating point. */ #include "toys.h" void seq_main(void) { - double first, increment, last, dd; + double first, increment, last, dd; - // Parse command line arguments, with appropriate defaults. - // Note that any non-numeric arguments are treated as zero. - first = increment = 1; - switch (toys.optc) { - case 3: - increment = atof(toys.optargs[1]); - case 2: - first = atof(*toys.optargs); - default: - last = atof(toys.optargs[toys.optc-1]); - } + // Parse command line arguments, with appropriate defaults. + // Note that any non-numeric arguments are treated as zero. + first = increment = 1; + switch (toys.optc) { + case 3: + increment = atof(toys.optargs[1]); + case 2: + first = atof(*toys.optargs); + default: + last = atof(toys.optargs[toys.optc-1]); + } - // Yes, we're looping on a double. Yes rounding errors can accumulate if - // you use a non-integer increment. Deal with it. - for (dd=first; (increment>0 && dd<=last) || (increment <0 && dd>=last); - dd+=increment) - { - printf("%g\n", dd); - } + // Yes, we're looping on a double. Yes rounding errors can accumulate if + // you use a non-integer increment. Deal with it. + for (dd=first; (increment>0 && dd<=last) || (increment<0 && dd>=last); + dd+=increment) + { + printf("%g\n", dd); + } } diff --git a/toys/lsb/sync.c b/toys/lsb/sync.c index 0d167147..b12a8cca 100644 --- a/toys/lsb/sync.c +++ b/toys/lsb/sync.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sync.c - Write all pending data to disk. +/* sync.c - Write all pending data to disk. * * Copyright 2007 Rob Landley * @@ -9,17 +7,17 @@ USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN)) config SYNC - bool "sync" - default y - help - usage: sync + bool "sync" + default y + help + usage: sync - Write pending cached data to disk (synchronize), blocking until done. + Write pending cached data to disk (synchronize), blocking until done. */ #include "toys.h" void sync_main(void) { - sync(); + sync(); } diff --git a/toys/other/bzcat.c b/toys/other/bzcat.c index c0c2b96a..8266484c 100644 --- a/toys/other/bzcat.c +++ b/toys/other/bzcat.c @@ -1,28 +1,26 @@ -/* vi: set sw=4 ts=4: - * - * bzcat.c - decompress stdin to stdout using bunzip2. +/* bzcat.c - decompress stdin to stdout using bunzip2. * * Copyright 2007 Rob Landley USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config BZCAT - bool "bzcat" - default y - help - usage: bzcat [filename...] + bool "bzcat" + default y + help + usage: bzcat [filename...] - Decompress listed files to stdout. Use stdin if no files listed. + Decompress listed files to stdout. Use stdin if no files listed. */ #include "toys.h" static void do_bzcat(int fd, char *name) { - bunzipStream(fd, 1); + bunzipStream(fd, 1); } void bzcat_main(void) { - loopfiles(toys.optargs, do_bzcat); + loopfiles(toys.optargs, do_bzcat); } diff --git a/toys/other/catv.c b/toys/other/catv.c index a0790a9b..62520c41 100644 --- a/toys/other/catv.c +++ b/toys/other/catv.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cat -v implementation for toybox +/* cat -v implementation for toybox * * Copyright (C) 2006, 2007 Rob Landley * @@ -10,17 +8,17 @@ USE_CATV(NEWTOY(catv, "vte", TOYFLAG_USR|TOYFLAG_BIN)) config CATV - bool "catv" - default y - help - usage: catv [-evt] [filename...] + bool "catv" + default y + help + usage: catv [-evt] [filename...] - Display nonprinting characters as escape sequences. Use M-x for - high ascii characters (>127), and ^x for other nonprinting chars. + Display nonprinting characters as escape sequences. Use M-x for + high ascii characters (>127), and ^x for other nonprinting chars. - -e Mark each newline with $ - -t Show tabs as ^I - -v Don't use ^x or M-x escapes. + -e Mark each newline with $ + -t Show tabs as ^I + -v Don't use ^x or M-x escapes. */ #define FOR_catv @@ -30,40 +28,40 @@ config CATV static void do_catv(int fd, char *name) { - for(;;) { - int i, len; + for(;;) { + int i, len; - len = read(fd, toybuf, sizeof(toybuf)); - if (len < 0) toys.exitval = EXIT_FAILURE; - if (len < 1) break; - for (i=0; i 126 && (toys.optflags & FLAG_v)) { - if (c > 127) { - printf("M-"); - c -= 128; - } - if (c == 127) { - printf("^?"); - continue; - } - } - if (c < 32) { - if (c == 10) { - if (toys.optflags & FLAG_e) xputc('$'); - } else if (toys.optflags & (c==9 ? FLAG_t : FLAG_v)) { - printf("^%c", c+'@'); - continue; - } - } - xputc(c); - } - } + if (c > 126 && (toys.optflags & FLAG_v)) { + if (c > 127) { + printf("M-"); + c -= 128; + } + if (c == 127) { + printf("^?"); + continue; + } + } + if (c < 32) { + if (c == 10) { + if (toys.optflags & FLAG_e) xputc('$'); + } else if (toys.optflags & (c==9 ? FLAG_t : FLAG_v)) { + printf("^%c", c+'@'); + continue; + } + } + xputc(c); + } + } } void catv_main(void) { - toys.optflags ^= FLAG_v; - loopfiles(toys.optargs, do_catv); + toys.optflags ^= FLAG_v; + loopfiles(toys.optargs, do_catv); } diff --git a/toys/other/chroot.c b/toys/other/chroot.c index 003ed072..c9ff10c7 100644 --- a/toys/other/chroot.c +++ b/toys/other/chroot.c @@ -1,26 +1,23 @@ -/* vi: set sw=4 ts=4: - * - * chroot.c - Run command in new root directory. +/* chroot.c - Run command in new root directory. * * Copyright 2007 Rob Landley USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN)) config CHROOT - bool "chroot" - default y - help - usage: chroot NEWPATH [commandline...] + bool "chroot" + default y + help + usage: chroot NEWPATH [commandline...] - Run command within a new root directory. If no command, run /bin/sh. + Run command within a new root directory. If no command, run /bin/sh. */ #include "toys.h" void chroot_main(void) { - char *binsh[] = {"/bin/sh", "-i", 0}; - if (chdir(*toys.optargs) || chroot(".")) - perror_exit("%s", *toys.optargs); - xexec(toys.optargs[1] ? toys.optargs+1 : binsh); + char *binsh[] = {"/bin/sh", "-i", 0}; + if (chdir(*toys.optargs) || chroot(".")) perror_exit("%s", *toys.optargs); + xexec(toys.optargs[1] ? toys.optargs+1 : binsh); } diff --git a/toys/other/chvt.c b/toys/other/chvt.c index 80eeadc4..7a0119c9 100644 --- a/toys/other/chvt.c +++ b/toys/other/chvt.c @@ -1,22 +1,20 @@ -/* vi: set sw=4 ts=4: - * - * chvt.c - switch virtual terminals +/* chvt.c - switch virtual terminals * * Copyright (C) 2008 David Anders USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_SBIN)) config CHVT - bool "chvt" - default y - help - usage: chvt N + bool "chvt" + default y + help + usage: chvt N - Change to virtual terminal number N. (This only works in text mode.) + Change to virtual terminal number N. (This only works in text mode.) - Virtual terminals are the Linux VGA text mode displays, ordinarily - switched between via alt-F1, alt-F2, etc. Use ctrl-alt-F1 to switch - from X to a virtual terminal, and alt-F6 (or F7, or F8) to get back. + Virtual terminals are the Linux VGA text mode displays, ordinarily + switched between via alt-F1, alt-F2, etc. Use ctrl-alt-F1 to switch + from X to a virtual terminal, and alt-F6 (or F7, or F8) to get back. */ #include "toys.h" @@ -24,26 +22,26 @@ config CHVT /* Note: get_console_fb() will need to be moved into a seperate lib section */ int get_console_fd() { - int fd; - char *consoles[]={"/dev/console", "/dev/vc/0", "/dev/tty", NULL}, **cc; + int fd; + char *consoles[]={"/dev/console", "/dev/vc/0", "/dev/tty", NULL}, **cc; - cc = consoles; - while (*cc) { - fd = open(*cc++, O_RDWR); - if (fd >= 0) return fd; - } + cc = consoles; + while (*cc) { + fd = open(*cc++, O_RDWR); + if (fd >= 0) return fd; + } - return -1; + return -1; } void chvt_main(void) { - int vtnum, fd; + int vtnum, fd; - vtnum=atoi(*toys.optargs); + vtnum=atoi(*toys.optargs); - fd=get_console_fd(); - // These numbers are VT_ACTIVATE and VT_WAITACTIVE from linux/vt.h - if (fd < 0 || ioctl(fd, 0x5606, vtnum) || ioctl(fd, 0x5607, vtnum)) - perror_exit(NULL); + fd=get_console_fd(); + // These numbers are VT_ACTIVATE and VT_WAITACTIVE from linux/vt.h + if (fd < 0 || ioctl(fd, 0x5606, vtnum) || ioctl(fd, 0x5607, vtnum)) + perror_exit(NULL); } diff --git a/toys/other/clear.c b/toys/other/clear.c index 7647f669..2515f735 100644 --- a/toys/other/clear.c +++ b/toys/other/clear.c @@ -1,21 +1,19 @@ -/* vi: set sw=4 ts=4: - * - * clear.c - clear the screen +/* clear.c - clear the screen * * Copyright 2012 Rob Landley USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config CLEAR - bool "clear" - default y - help - Clear the screen. + bool "clear" + default y + help + Clear the screen. */ #include "toys.h" void clear_main(void) { - write(1, "\e[2J\e[H", 7); + write(1, "\e[2J\e[H", 7); } diff --git a/toys/other/count.c b/toys/other/count.c index 22a06a1c..f3b6f821 100644 --- a/toys/other/count.c +++ b/toys/other/count.c @@ -1,34 +1,32 @@ -/* vi: set sw=4 ts=4: - * - * count.c - Progress indicator from stdin to stdout +/* count.c - Progress indicator from stdin to stdout * * Copyright 2002 Rob Landley USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config COUNT - bool "count" - default y - help - usage: count + bool "count" + default y + help + usage: count - Copy stdin to stdout, displaying simple progress indicator to stderr. + Copy stdin to stdout, displaying simple progress indicator to stderr. */ #include "toys.h" void count_main(void) { - uint64_t size = 0; - int len; - char buf[32]; + uint64_t size = 0; + int len; + char buf[32]; - for (;;) { - len = xread(0, toybuf, sizeof(toybuf)); - if (!len) break; - size += len; - xwrite(1, toybuf, len); - xwrite(2, buf, sprintf(buf, "%"PRIu64" bytes\r", size)); - } - xwrite(2, "\n", 1); + for (;;) { + len = xread(0, toybuf, sizeof(toybuf)); + if (!len) break; + size += len; + xwrite(1, toybuf, len); + xwrite(2, buf, sprintf(buf, "%"PRIu64" bytes\r", size)); + } + xwrite(2, "\n", 1); } diff --git a/toys/other/dos2unix.c b/toys/other/dos2unix.c index 15cc1706..59cd6a53 100644 --- a/toys/other/dos2unix.c +++ b/toys/other/dos2unix.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * dos2unix.c - convert newline format +/* dos2unix.c - convert newline format * * Copyright 2012 Rob Landley @@ -8,60 +6,60 @@ USE_DOS2UNIX(NEWTOY(dos2unix, NULL, TOYFLAG_BIN)) USE_DOS2UNIX(OLDTOY(unix2dos, dos2unix, NULL, TOYFLAG_BIN)) config DOS2UNIX - bool "dos2unix/unix2dos" - default y - help - usage: dos2unix/unix2dos [file...] + bool "dos2unix/unix2dos" + default y + help + usage: dos2unix/unix2dos [file...] - Convert newline format between dos (\r\n) and unix (just \n) - If no files listed copy from stdin, "-" is a synonym for stdin. + Convert newline format between dos (\r\n) and unix (just \n) + If no files listed copy from stdin, "-" is a synonym for stdin. */ #define FOR_dos2unix #include "toys.h" GLOBALS( - char *tempfile; + char *tempfile; ) static void do_dos2unix(int fd, char *name) { - char c = toys.which->name[0]; - int outfd = 1, catch = 0; + char c = toys.which->name[0]; + int outfd = 1, catch = 0; - if (fd) outfd = copy_tempfile(fd, name, &TT.tempfile); + if (fd) outfd = copy_tempfile(fd, name, &TT.tempfile); - for (;;) { - int len, in, out; + for (;;) { + int len, in, out; - len = read(fd, toybuf+(sizeof(toybuf)/2), sizeof(toybuf)/2); - if (len<0) { - perror_msg("%s",name); - toys.exitval = 1; - } - if (len<1) break; + len = read(fd, toybuf+(sizeof(toybuf)/2), sizeof(toybuf)/2); + if (len<0) { + perror_msg("%s",name); + toys.exitval = 1; + } + if (len<1) break; - for (in = out = 0; in < len; in++) { - char x = toybuf[in+sizeof(toybuf)/2]; + for (in = out = 0; in < len; in++) { + char x = toybuf[in+sizeof(toybuf)/2]; - // Drop \r only if followed by \n in dos2unix mode - if (catch) { - if (c == 'u' || x != '\n') toybuf[out++] = '\r'; - catch = 0; - // Add \r only if \n not after \r in unix2dos mode - } else if (c == 'u' && x == '\n') toybuf[out++] = '\r'; + // Drop \r only if followed by \n in dos2unix mode + if (catch) { + if (c == 'u' || x != '\n') toybuf[out++] = '\r'; + catch = 0; + // Add \r only if \n not after \r in unix2dos mode + } else if (c == 'u' && x == '\n') toybuf[out++] = '\r'; - if (x == '\r') catch++; - else toybuf[out++] = x; - } - xwrite(outfd, toybuf, out); - } - if (catch) xwrite(outfd, "\r", 1); + if (x == '\r') catch++; + else toybuf[out++] = x; + } + xwrite(outfd, toybuf, out); + } + if (catch) xwrite(outfd, "\r", 1); - if (fd) replace_tempfile(-1, outfd, &TT.tempfile); + if (fd) replace_tempfile(-1, outfd, &TT.tempfile); } void dos2unix_main(void) { - loopfiles(toys.optargs, do_dos2unix); + loopfiles(toys.optargs, do_dos2unix); } diff --git a/toys/other/free.c b/toys/other/free.c index aa344928..3281d79b 100644 --- a/toys/other/free.c +++ b/toys/other/free.c @@ -1,59 +1,57 @@ -/* vi: set sw=4 ts=4: - * - * free.c - Display amount of free and used memory in the system. +/* free.c - Display amount of free and used memory in the system. * * Copyright 2012 Elie De Brauwer USE_FREE(NEWTOY(free, "gmkb", TOYFLAG_USR|TOYFLAG_BIN)) config FREE - bool "free" - default y - help - usage: free [-bkmg] + bool "free" + default y + help + usage: free [-bkmg] - Display the total, free and used amount of physical memory and - swap space. + Display the total, free and used amount of physical memory and + swap space. - -bkmg Output in bytes (default), KB, MB or GB + -bkmg Output in bytes (default), KB, MB or GB */ #define FOR_free #include "toys.h" static unsigned long long convert(unsigned long d, unsigned int iscale, - unsigned int oscale) + unsigned int oscale) { - return ((unsigned long long)d*iscale)>>oscale; + return ((unsigned long long)d*iscale)>>oscale; } void free_main(void) { - struct sysinfo info; - unsigned int iscale = 1; - unsigned int oscale = 0; - - sysinfo(&info); - if (info.mem_unit) iscale = info.mem_unit; - if (toys.optflags & FLAG_b) oscale = 0; - if (toys.optflags & FLAG_k) oscale = 10; - if (toys.optflags & FLAG_m) oscale = 20; - if (toys.optflags & FLAG_g) oscale = 30; - - xprintf("\t\ttotal used free shared buffers\n"); - xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n", - convert(info.totalram, iscale, oscale), - convert(info.totalram-info.freeram, iscale, oscale), - convert(info.freeram, iscale, oscale), - convert(info.sharedram, iscale, oscale), - convert(info.bufferram, iscale, oscale)); - - xprintf("-/+ buffers/cache:%15llu%12llu\n", - convert(info.totalram - info.freeram - info.bufferram, iscale, oscale), - convert(info.freeram + info.bufferram, iscale, oscale)); - - xprintf("Swap:%16llu%12llu%12llu\n", - convert(info.totalswap, iscale, oscale), - convert(info.totalswap - info.freeswap, iscale, oscale), - convert(info.freeswap, iscale, oscale)); + struct sysinfo info; + unsigned int iscale = 1; + unsigned int oscale = 0; + + sysinfo(&info); + if (info.mem_unit) iscale = info.mem_unit; + if (toys.optflags & FLAG_b) oscale = 0; + if (toys.optflags & FLAG_k) oscale = 10; + if (toys.optflags & FLAG_m) oscale = 20; + if (toys.optflags & FLAG_g) oscale = 30; + + xprintf("\t\ttotal used free shared buffers\n"); + xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n", + convert(info.totalram, iscale, oscale), + convert(info.totalram-info.freeram, iscale, oscale), + convert(info.freeram, iscale, oscale), + convert(info.sharedram, iscale, oscale), + convert(info.bufferram, iscale, oscale)); + + xprintf("-/+ buffers/cache:%15llu%12llu\n", + convert(info.totalram - info.freeram - info.bufferram, iscale, oscale), + convert(info.freeram + info.bufferram, iscale, oscale)); + + xprintf("Swap:%16llu%12llu%12llu\n", + convert(info.totalswap, iscale, oscale), + convert(info.totalswap - info.freeswap, iscale, oscale), + convert(info.freeswap, iscale, oscale)); } diff --git a/toys/other/hello.c b/toys/other/hello.c index 2b469591..aa256155 100644 --- a/toys/other/hello.c +++ b/toys/other/hello.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * hello.c - A hello world program. (Template for new commands.) +/* hello.c - A hello world program. (Template for new commands.) * * Copyright 2012 Rob Landley * @@ -10,15 +8,15 @@ USE_HELLO(NEWTOY(hello, "e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN)) config HELLO - bool "hello" - default n - help - usage: hello [-a] [-b string] [-c number] [-d list] [-e count] [...] + bool "hello" + default n + help + usage: hello [-a] [-b string] [-c number] [-d list] [-e count] [...] - A hello world program. You don't need this. + A hello world program. You don't need this. - Mostly used as an example/skeleton file for adding new commands, - occasionally nice to test kernel booting via "init=/bin/hello". + Mostly used as an example/skeleton file for adding new commands, + occasionally nice to test kernel booting via "init=/bin/hello". */ #define FOR_hello @@ -27,26 +25,26 @@ config HELLO // Hello doesn't use these globals, they're here for example/skeleton purposes. GLOBALS( - char *b_string; - long c_number; - struct arg_list *d_list; - long e_count; + char *b_string; + long c_number; + struct arg_list *d_list; + long e_count; - int more_globals; + int more_globals; ) void hello_main(void) { - printf("Hello world\n"); - - if (toys.optflags & FLAG_a) printf("Saw a\n"); - if (toys.optflags & FLAG_b) printf("b=%s\n", TT.b_string); - if (toys.optflags & FLAG_c) printf("c=%ld\n", TT.c_number); - while (TT.d_list) { - printf("d=%s\n", TT.d_list->arg); - TT.d_list = TT.d_list->next; - } - if (TT.e_count) printf("e was seen %ld times", TT.e_count); - - while (*toys.optargs) printf("optarg=%s\n", *(toys.optargs++)); + printf("Hello world\n"); + + if (toys.optflags & FLAG_a) printf("Saw a\n"); + if (toys.optflags & FLAG_b) printf("b=%s\n", TT.b_string); + if (toys.optflags & FLAG_c) printf("c=%ld\n", TT.c_number); + while (TT.d_list) { + printf("d=%s\n", TT.d_list->arg); + TT.d_list = TT.d_list->next; + } + if (TT.e_count) printf("e was seen %ld times", TT.e_count); + + while (*toys.optargs) printf("optarg=%s\n", *(toys.optargs++)); } diff --git a/toys/other/help.c b/toys/other/help.c index 2c175552..68bc3aab 100644 --- a/toys/other/help.c +++ b/toys/other/help.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * help.c - Show help for toybox commands +/* help.c - Show help for toybox commands * * Copyright 2007 Rob Landley * @@ -9,15 +7,15 @@ USE_HELP(NEWTOY(help, "<1", TOYFLAG_BIN)) config HELP - bool "help" - default y - help - usage: help [command] + bool "help" + default y + help + usage: help [command] - Show usage information for toybox commands. - Run "toybox" with no arguments for a list of available commands. + Show usage information for toybox commands. + Run "toybox" with no arguments for a list of available commands. */ - + #include "toys.h" #include "generated/help.h" @@ -32,17 +30,17 @@ static char *help_data = void help_main(void) { - struct toy_list *t = toy_find(*toys.optargs); - int i = t-toy_list; - char *s = help_data; - - if (!t) error_exit("Unknown command '%s'", *toys.optargs); - for (;;) { - while (i--) s += strlen(s) + 1; - if (*s != 255) break; - i = toy_find(++s)-toy_list; - s = help_data; - } - - fprintf(toys.exithelp ? stderr : stdout, "%s", s); + struct toy_list *t = toy_find(*toys.optargs); + int i = t-toy_list; + char *s = help_data; + + if (!t) error_exit("Unknown command '%s'", *toys.optargs); + for (;;) { + while (i--) s += strlen(s) + 1; + if (*s != 255) break; + i = toy_find(++s)-toy_list; + s = help_data; + } + + fprintf(toys.exithelp ? stderr : stdout, "%s", s); } diff --git a/toys/other/insmod.c b/toys/other/insmod.c index 3eae538a..8aa959a9 100644 --- a/toys/other/insmod.c +++ b/toys/other/insmod.c @@ -1,18 +1,16 @@ -/* vi: set sw=4 ts=4: - * - * insmod.c - Load a module into the Linux kernel. +/* insmod.c - Load a module into the Linux kernel. * * Copyright 2012 Elie De Brauwer USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config INSMOD - bool "insmod" - default y - help - usage: insmod MODULE [MODULE_OPTIONS] + bool "insmod" + default y + help + usage: insmod MODULE [MODULE_OPTIONS] - Load the module named MODULE passing options if given. + Load the module named MODULE passing options if given. */ #include "toys.h" @@ -22,24 +20,23 @@ config INSMOD void insmod_main(void) { - char * buf = NULL; - int len, res, i; - int fd = xopen(toys.optargs[0], O_RDONLY); - - len = fdlength(fd); - buf = xmalloc(len); - xreadall(fd, buf, len); - - i = 1; - while(toys.optargs[i] && - strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) { - strcat(toybuf, toys.optargs[i++]); - strcat(toybuf, " "); - } - - res = init_module(buf, len, toybuf); - if (CFG_TOYBOX_FREE && buf != toybuf) free(buf); - - if (res) - perror_exit("failed to load %s", toys.optargs[0]); + char * buf = NULL; + int len, res, i; + int fd = xopen(toys.optargs[0], O_RDONLY); + + len = fdlength(fd); + buf = xmalloc(len); + xreadall(fd, buf, len); + + i = 1; + while(toys.optargs[i] && + strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) { + strcat(toybuf, toys.optargs[i++]); + strcat(toybuf, " "); + } + + res = init_module(buf, len, toybuf); + if (CFG_TOYBOX_FREE && buf != toybuf) free(buf); + + if (res) perror_exit("failed to load %s", toys.optargs[0]); } diff --git a/toys/other/login.c b/toys/other/login.c index a9e7562c..72d7063e 100644 --- a/toys/other/login.c +++ b/toys/other/login.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * login.c - Start a session on the system. +/* login.c - Start a session on the system. * * Copyright 2012 Elie De Brauwer * @@ -10,15 +8,15 @@ USE_LOGIN(NEWTOY(login, ">1fph:", TOYFLAG_BIN)) config LOGIN - bool "login" - default y - help - usage: login [-p] [-h host] [[-f] username] - - Establish a new session with the system. - -p Preserve environment - -h The name of the remote host for this login - -f Do not perform authentication + bool "login" + default y + help + usage: login [-p] [-h host] [[-f] username] + + Establish a new session with the system. + -p Preserve environment + -h The name of the remote host for this login + -f Do not perform authentication */ #define FOR_login @@ -30,215 +28,199 @@ config LOGIN #define HOSTNAME_SIZE 32 GLOBALS( - char *hostname; + char *hostname; ) static void login_timeout_handler(int sig __attribute__((unused))) { - printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); - exit(0); + printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); + exit(0); } static char *forbid[] = { - "BASH_ENV", - "ENV", - "HOME", - "IFS", - "LD_LIBRARY_PATH", - "LD_PRELOAD", - "LD_TRACE_LOADED_OBJECTS", - "LD_BIND_NOW", - "LD_AOUT_LIBRARY_PATH", - "LD_AOUT_PRELOAD", - "LD_NOWARN", - "LD_KEEPDIR", - "SHELL", - NULL + "BASH_ENV", "ENV", "HOME", "IFS", "LD_LIBRARY_PATH", "LD_PRELOAD", + "LD_TRACE_LOADED_OBJECTS", "LD_BIND_NOW", "LD_AOUT_LIBRARY_PATH", + "LD_AOUT_PRELOAD", "LD_NOWARN", "LD_KEEPDIR", "SHELL", NULL }; int verify_password(char * pwd) { - char *pass; + char *pass; - if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; - if (!pwd) return 1; - if (pwd[0] == '!' || pwd[0] == '*') return 1; + if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; + if (!pwd) return 1; + if (pwd[0] == '!' || pwd[0] == '*') return 1; - pass = crypt(toybuf, pwd); - if (pass && !strcmp(pass, pwd)) return 0; + pass = crypt(toybuf, pwd); + if (pass && !strcmp(pass, pwd)) return 0; - return 1; + return 1; } void read_user(char * buff, int size) { - char hostname[HOSTNAME_SIZE+1]; - int i = 0; - hostname[HOSTNAME_SIZE] = 0; - if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout); - - fputs(" login: ", stdout); - fflush(stdout); - - do { - buff[0] = getchar(); - if (buff[0] == EOF) - exit(EXIT_FAILURE); - } while (isblank(buff[0])); - - if (buff[0] != '\n') - if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) - _exit(1); - - while(ipw_name,pwd->pw_gid)) return 1; - if (setgid(pwd->pw_uid)) return 1; - if (setuid(pwd->pw_uid)) return 1; + if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1; + if (setgid(pwd->pw_uid)) return 1; + if (setuid(pwd->pw_uid)) return 1; - return 0; + return 0; } void spawn_shell(const char *shell) { - const char * exec_name = strrchr(shell,'/'); - if (exec_name) exec_name++; - else exec_name = shell; + const char * exec_name = strrchr(shell,'/'); + if (exec_name) exec_name++; + else exec_name = shell; - snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); - execl(shell, toybuf, NULL); - error_exit("Failed to spawn shell"); + snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); + execl(shell, toybuf, NULL); + error_exit("Failed to spawn shell"); } void setup_environment(const struct passwd *pwd, int clear_env) { - if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); - - if (clear_env) { - const char * term = getenv("TERM"); - clearenv(); - if (term) setenv("TERM", term, 1); - } - - setenv("USER", pwd->pw_name, 1); - setenv("LOGNAME", pwd->pw_name, 1); - setenv("HOME", pwd->pw_dir, 1); - setenv("SHELL", pwd->pw_shell, 1); + if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); + + if (clear_env) { + const char * term = getenv("TERM"); + clearenv(); + if (term) setenv("TERM", term, 1); + } + + setenv("USER", pwd->pw_name, 1); + setenv("LOGNAME", pwd->pw_name, 1); + setenv("HOME", pwd->pw_dir, 1); + setenv("SHELL", pwd->pw_shell, 1); } void login_main(void) { - int f_flag = toys.optflags & FLAG_f; - int h_flag = toys.optflags & FLAG_h; - char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; - struct passwd * pwd = NULL; - struct spwd * spwd = NULL; - int auth_fail_cnt = 0; + int f_flag = toys.optflags & FLAG_f; + int h_flag = toys.optflags & FLAG_h; + char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; + struct passwd * pwd = NULL; + struct spwd * spwd = NULL; + int auth_fail_cnt = 0; - if (f_flag && toys.optc != 1) - error_exit("-f requires username"); + if (f_flag && toys.optc != 1) error_exit("-f requires username"); - if (geteuid()) error_exit("not root"); + if (geteuid()) error_exit("not root"); - if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); + if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); - openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); - signal(SIGALRM, login_timeout_handler); - alarm(LOGIN_TIMEOUT); + openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); + signal(SIGALRM, login_timeout_handler); + alarm(LOGIN_TIMEOUT); - for (ss = forbid; *ss; ss++) unsetenv(*ss); + for (ss = forbid; *ss; ss++) unsetenv(*ss); - while (1) { - tcflush(0, TCIFLUSH); + while (1) { + tcflush(0, TCIFLUSH); - username[USER_NAME_MAX_SIZE] = 0; - if (toys.optargs[0]) - strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); - else { - read_user(username, USER_NAME_MAX_SIZE+1); - if (username[0] == 0) continue; - } + username[USER_NAME_MAX_SIZE] = 0; + if (toys.optargs[0]) strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); + else { + read_user(username, USER_NAME_MAX_SIZE+1); + if (username[0] == 0) continue; + } - pwd = getpwnam(username); - if (!pwd) goto query_pass; // Non-existing user + pwd = getpwnam(username); + if (!pwd) goto query_pass; // Non-existing user - if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') - goto query_pass; // Locked account + if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') + goto query_pass; // Locked account - if (f_flag) break; // Pre-authenticated + if (f_flag) break; // Pre-authenticated - if (!pwd->pw_passwd[0]) break; // Password-less account + if (!pwd->pw_passwd[0]) break; // Password-less account - pass = pwd->pw_passwd; - if (pwd->pw_passwd[0] == 'x') { - spwd = getspnam (username); - if (spwd) pass = spwd->sp_pwdp; - } + pass = pwd->pw_passwd; + if (pwd->pw_passwd[0] == 'x') { + spwd = getspnam (username); + if (spwd) pass = spwd->sp_pwdp; + } query_pass: - if (!verify_password(pass)) break; + if (!verify_password(pass)) break; - f_flag = 0; - syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, - ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); + f_flag = 0; + syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); - sleep(LOGIN_FAIL_TIMEOUT); - puts("Login incorrect"); + sleep(LOGIN_FAIL_TIMEOUT); + puts("Login incorrect"); - if (++auth_fail_cnt == 3) - error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); + if (++auth_fail_cnt == 3) + error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); - username[0] = 0; - pwd = NULL; - spwd = NULL; - } + username[0] = 0; + pwd = NULL; + spwd = NULL; + } - alarm(0); + alarm(0); - if (pwd->pw_uid) handle_nologin(); + if (pwd->pw_uid) handle_nologin(); - if (change_identity(pwd)) error_exit("Failed to change identity"); + if (change_identity(pwd)) error_exit("Failed to change identity"); - setup_environment(pwd, !(toys.optflags & FLAG_p)); + setup_environment(pwd, !(toys.optflags & FLAG_p)); - handle_motd(); + handle_motd(); - syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, - ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); + syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); - spawn_shell(pwd->pw_shell); + spawn_shell(pwd->pw_shell); } diff --git a/toys/other/lsmod.c b/toys/other/lsmod.c index 821243b8..b8f5d820 100644 --- a/toys/other/lsmod.c +++ b/toys/other/lsmod.c @@ -1,40 +1,36 @@ -/* vi: set sw=4 ts=4: - * - * lsmod.c - Show the status of modules in the kernel +/* lsmod.c - Show the status of modules in the kernel * * Copyright 2012 Elie De Brauwer USE_LSMOD(NEWTOY(lsmod, NULL, TOYFLAG_BIN)) config LSMOD - bool "lsmod" - default y - help - usage: lsmod + bool "lsmod" + default y + help + usage: lsmod - Display the currently loaded modules, their sizes and their - dependencies. + Display the currently loaded modules, their sizes and their dependencies. */ #include "toys.h" void lsmod_main(void) { - char *modfile = "/proc/modules"; - FILE * file = xfopen(modfile, "r"); - - xprintf("%-23s Size Used by\n", "Module"); - - while (fgets(toybuf, sizeof(toybuf), file)) { - char *name = strtok(toybuf, " "), *size = strtok(NULL, " "), - *refcnt = strtok(NULL, " "), *users = strtok(NULL, " "); - - if(users) { - int len = strlen(users)-1; - if (users[len] == ',' || users[len] == '-') - users[len] = 0; - xprintf("%-19s %8s %s %s\n", name, size, refcnt, users); - } else perror_exit("bad %s", modfile); - } - fclose(file); + char *modfile = "/proc/modules"; + FILE * file = xfopen(modfile, "r"); + + xprintf("%-23s Size Used by\n", "Module"); + + while (fgets(toybuf, sizeof(toybuf), file)) { + char *name = strtok(toybuf, " "), *size = strtok(NULL, " "), + *refcnt = strtok(NULL, " "), *users = strtok(NULL, " "); + + if(users) { + int len = strlen(users)-1; + if (users[len] == ',' || users[len] == '-') users[len] = 0; + xprintf("%-19s %8s %s %s\n", name, size, refcnt, users); + } else perror_exit("bad %s", modfile); + } + fclose(file); } diff --git a/toys/other/mdev.c b/toys/other/mdev.c index 6d030d14..b89ac2ca 100644 --- a/toys/other/mdev.c +++ b/toys/other/mdev.c @@ -1,6 +1,4 @@ -/* vi:set ts=4: - * - * mdev.c - Populate /dev directory and handle hotplug events +/* mdev.c - Populate /dev directory and handle hotplug events * * Copyright 2005, 2008 Rob Landley * Copyright 2005 Frank Sorenson @@ -8,27 +6,27 @@ USE_MDEV(NEWTOY(mdev, "s", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK)) config MDEV - bool "mdev" - default n - help - usage: mdev [-s] + bool "mdev" + default n + help + usage: mdev [-s] - Create devices in /dev using information from /sys. + Create devices in /dev using information from /sys. - -s Scan all entries in /sys to populate /dev. + -s Scan all entries in /sys to populate /dev. config MDEV_CONF - bool "Configuration file for mdev" - default y - depends on MDEV - help - The mdev config file (/etc/mdev.conf) contains lines that look like: - hd[a-z][0-9]* 0:3 660 - - Each line must contain three whitespace separated fields. The first - field is a regular expression matching one or more device names, and - the second and third fields are uid:gid and file permissions for - matching devies. + bool "Configuration file for mdev" + default y + depends on MDEV + help + The mdev config file (/etc/mdev.conf) contains lines that look like: + hd[a-z][0-9]* 0:3 660 + + Each line must contain three whitespace separated fields. The first + field is a regular expression matching one or more device names, and + the second and third fields are uid:gid and file permissions for + matching devies. */ #include "toys.h" @@ -39,173 +37,173 @@ config MDEV_CONF // mknod in /dev based on a path like "/sys/block/hda/hda1" static void make_device(char *path) { - char *device_name, *s, *temp; - int major, minor, type, len, fd; - int mode = 0660; - uid_t uid = 0; - gid_t gid = 0; - - // Try to read major/minor string - - temp = strrchr(path, '/'); - fd = open(path, O_RDONLY); - *temp=0; - temp = toybuf; - len = read(fd, temp, 64); - close(fd); - if (len<1) return; - temp[len] = 0; - - // Determine device name, type, major and minor - - device_name = strrchr(path, '/') + 1; - type = path[5]=='c' ? S_IFCHR : S_IFBLK; - major = minor = 0; - sscanf(temp, "%u:%u", &major, &minor); - - // If we have a config file, look up permissions for this device - - if (CFG_MDEV_CONF) { - char *conf, *pos, *end; - - // mmap the config file - if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) { - len = fdlength(fd); - conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); - if (conf) { - int line = 0; - - // Loop through lines in mmaped file - for (pos = conf; pos-confpw_uid; - } - s++; - // parse GID - gid = strtoul(s,&s2,10); - if (end2!=s2) { - struct group *grp; - char *str = strndup(s, end2-s); - grp = getgrnam(str); - free(str); - if (!grp) goto end_line; - gid = grp->gr_gid; - } - break; - } - // mode - case 1: - { - mode = strtoul(pos, &pos, 8); - if (pos!=end2) goto end_line; - goto found_device; - } - } - pos=end2; - } + char *device_name, *s, *temp; + int major, minor, type, len, fd; + int mode = 0660; + uid_t uid = 0; + gid_t gid = 0; + + // Try to read major/minor string + + temp = strrchr(path, '/'); + fd = open(path, O_RDONLY); + *temp=0; + temp = toybuf; + len = read(fd, temp, 64); + close(fd); + if (len<1) return; + temp[len] = 0; + + // Determine device name, type, major and minor + + device_name = strrchr(path, '/') + 1; + type = path[5]=='c' ? S_IFCHR : S_IFBLK; + major = minor = 0; + sscanf(temp, "%u:%u", &major, &minor); + + // If we have a config file, look up permissions for this device + + if (CFG_MDEV_CONF) { + char *conf, *pos, *end; + + // mmap the config file + if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) { + len = fdlength(fd); + conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); + if (conf) { + int line = 0; + + // Loop through lines in mmaped file + for (pos = conf; pos-confpw_uid; + } + s++; + // parse GID + gid = strtoul(s,&s2,10); + if (end2!=s2) { + struct group *grp; + char *str = strndup(s, end2-s); + grp = getgrnam(str); + free(str); + if (!grp) goto end_line; + gid = grp->gr_gid; + } + break; + } + // mode + case 1: + { + mode = strtoul(pos, &pos, 8); + if (pos!=end2) goto end_line; + goto found_device; + } + } + pos=end2; + } end_line: - // Did everything parse happily? - if (field && field!=3) error_exit("Bad line %d", line); + // Did everything parse happily? + if (field && field!=3) error_exit("Bad line %d", line); - // Next line - pos = ++end; - } + // Next line + pos = ++end; + } found_device: - munmap(conf, len); - } - close(fd); - } - } + munmap(conf, len); + } + close(fd); + } + } - sprintf(temp, "/dev/%s", device_name); - if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) - perror_exit("mknod %s failed", temp); + sprintf(temp, "/dev/%s", device_name); + if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) + perror_exit("mknod %s failed", temp); - if (CFG_MDEV_CONF) mode=chown(temp, uid, gid); + if (CFG_MDEV_CONF) mode=chown(temp, uid, gid); } static int callback(struct dirtree *node) { - // Entries in /sys/class/block aren't char devices, so skip 'em. (We'll - // get block devices out of /sys/block.) - if(!strcmp(node->name, "block")) return 0; - - // Does this directory have a "dev" entry in it? - // This is path based because the hotplug callbacks are - if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) { - int len=4; - char *dev = dirtree_path(node, &len); - strcpy(dev+len, "/dev"); - if (!access(dev, R_OK)) make_device(dev); - free(dev); - } - - // Circa 2.6.25 the entries more than 2 deep are all either redundant - // (mouse#, event#) or unnamed (every usb_* entry is called "device"). - - return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE; + // Entries in /sys/class/block aren't char devices, so skip 'em. (We'll + // get block devices out of /sys/block.) + if(!strcmp(node->name, "block")) return 0; + + // Does this directory have a "dev" entry in it? + // This is path based because the hotplug callbacks are + if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) { + int len=4; + char *dev = dirtree_path(node, &len); + strcpy(dev+len, "/dev"); + if (!access(dev, R_OK)) make_device(dev); + free(dev); + } + + // Circa 2.6.25 the entries more than 2 deep are all either redundant + // (mouse#, event#) or unnamed (every usb_* entry is called "device"). + + return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE; } void mdev_main(void) { - // Handle -s + // Handle -s - if (toys.optflags) { - dirtree_read("/sys/class", callback); - dirtree_read("/sys/block", callback); - } + if (toys.optflags) { + dirtree_read("/sys/class", callback); + dirtree_read("/sys/block", callback); + } - // hotplug support goes here + // hotplug support goes here } diff --git a/toys/other/mke2fs.c b/toys/other/mke2fs.c index 5745d519..1a83e4f6 100644 --- a/toys/other/mke2fs.c +++ b/toys/other/mke2fs.c @@ -1,6 +1,4 @@ -/* vi: set ts=4: - * - * mke2fs.c - Create an ext2 filesystem image. +/* mke2fs.c - Create an ext2 filesystem image. * * Copyright 2006, 2007 Rob Landley @@ -8,155 +6,155 @@ USE_MKE2FS(NEWTOY(mke2fs, "<1>2g:Fnqm#N#i#b#", TOYFLAG_SBIN)) config MKE2FS - bool "mke2fs (unfinished and broken by dirtree changes)" - default n - help - usage: mke2fs [-Fnq] [-b ###] [-N|i ###] [-m ###] device + bool "mke2fs (unfinished and broken by dirtree changes)" + default n + help + usage: mke2fs [-Fnq] [-b ###] [-N|i ###] [-m ###] device - Create an ext2 filesystem on a block device or filesystem image. + Create an ext2 filesystem on a block device or filesystem image. - -F Force to run on a mounted device - -n Don't write to device - -q Quiet (no output) - -b size Block size (1024, 2048, or 4096) - -N inodes Allocate this many inodes - -i bytes Allocate one inode for every XXX bytes of device - -m percent Reserve this percent of filesystem space for root user + -F Force to run on a mounted device + -n Don't write to device + -q Quiet (no output) + -b size Block size (1024, 2048, or 4096) + -N inodes Allocate this many inodes + -i bytes Allocate one inode for every XXX bytes of device + -m percent Reserve this percent of filesystem space for root user config MKE2FS_JOURNAL - bool "Journaling support (ext3)" - default n - depends on MKE2FS - help - usage: [-j] [-J size=###,device=XXX] + bool "Journaling support (ext3)" + default n + depends on MKE2FS + help + usage: [-j] [-J size=###,device=XXX] - -j Create journal (ext3) - -J Journal options - size: Number of blocks (1024-102400) - device: Specify an external journal + -j Create journal (ext3) + -J Journal options + size: Number of blocks (1024-102400) + device: Specify an external journal config MKE2FS_GEN - bool "Generate (gene2fs)" - default n - depends on MKE2FS - help - usage: gene2fs [options] device filename + bool "Generate (gene2fs)" + default n + depends on MKE2FS + help + usage: gene2fs [options] device filename - The [options] are the same as mke2fs. + The [options] are the same as mke2fs. config MKE2FS_LABEL - bool "Label support" - default n - depends on MKE2FS - help - usage: mke2fs [-L label] [-M path] [-o string] + bool "Label support" + default n + depends on MKE2FS + help + usage: mke2fs [-L label] [-M path] [-o string] - -L Volume label - -M Path to mount point - -o Created by + -L Volume label + -M Path to mount point + -o Created by config MKE2FS_EXTENDED - bool "Extended options" - default n - depends on MKE2FS - help - usage: mke2fs [-E stride=###] [-O option[,option]] - - -E stride= Set RAID stripe size (in blocks) - -O [opts] Specify fewer ext2 option flags (for old kernels) - All of these are on by default (as appropriate) - none Clear default options (all but journaling) - dir_index Use htree indexes for large directories - filetype Store file type info in directory entry - has_journal Set by -j - journal_dev Set by -J device=XXX - sparse_super Don't allocate huge numbers of redundant superblocks + bool "Extended options" + default n + depends on MKE2FS + help + usage: mke2fs [-E stride=###] [-O option[,option]] + + -E stride= Set RAID stripe size (in blocks) + -O [opts] Specify fewer ext2 option flags (for old kernels) + All of these are on by default (as appropriate) + none Clear default options (all but journaling) + dir_index Use htree indexes for large directories + filetype Store file type info in directory entry + has_journal Set by -j + journal_dev Set by -J device=XXX + sparse_super Don't allocate huge numbers of redundant superblocks */ #define FOR_mke2fs #include "toys.h" GLOBALS( - // Command line arguments. - long blocksize; - long bytes_per_inode; - long inodes; // Total inodes in filesystem. - long reserved_percent; // Integer precent of space to reserve for root. - char *gendir; // Where to read dirtree from. - - // Internal data. - struct dirtree *dt; // Tree of files to copy into the new filesystem. - unsigned treeblocks; // Blocks used by dt - unsigned treeinodes; // Inodes used by dt - - unsigned blocks; // Total blocks in the filesystem. - unsigned freeblocks; // Free blocks in the filesystem. - unsigned inodespg; // Inodes per group - unsigned groups; // Total number of block groups. - unsigned blockbits; // Bits per block. (Also blocks per group.) - - // For gene2fs - unsigned nextblock; // Next data block to allocate - unsigned nextgroup; // Next group we'll be allocating from - int fsfd; // File descriptor of filesystem (to output to). - - struct ext2_superblock sb; + // Command line arguments. + long blocksize; + long bytes_per_inode; + long inodes; // Total inodes in filesystem. + long reserved_percent; // Integer precent of space to reserve for root. + char *gendir; // Where to read dirtree from. + + // Internal data. + struct dirtree *dt; // Tree of files to copy into the new filesystem. + unsigned treeblocks; // Blocks used by dt + unsigned treeinodes; // Inodes used by dt + + unsigned blocks; // Total blocks in the filesystem. + unsigned freeblocks; // Free blocks in the filesystem. + unsigned inodespg; // Inodes per group + unsigned groups; // Total number of block groups. + unsigned blockbits; // Bits per block. (Also blocks per group.) + + // For gene2fs + unsigned nextblock; // Next data block to allocate + unsigned nextgroup; // Next group we'll be allocating from + int fsfd; // File descriptor of filesystem (to output to). + + struct ext2_superblock sb; ) #define INODES_RESERVED 10 static uint32_t div_round_up(uint32_t a, uint32_t b) { - uint32_t c = a/b; + uint32_t c = a/b; - if (a%b) c++; - return c; + if (a%b) c++; + return c; } // Calculate data blocks plus index blocks needed to hold a file. static uint32_t file_blocks_used(uint64_t size, uint32_t *blocklist) { - uint32_t dblocks = (uint32_t)((size+(TT.blocksize-1))/TT.blocksize); - uint32_t idx=TT.blocksize/4, iblocks=0, diblocks=0, tiblocks=0; + uint32_t dblocks = (uint32_t)((size+(TT.blocksize-1))/TT.blocksize); + uint32_t idx=TT.blocksize/4, iblocks=0, diblocks=0, tiblocks=0; - // Fill out index blocks in inode. + // Fill out index blocks in inode. - if (blocklist) { - int i; + if (blocklist) { + int i; - // Direct index blocks - for (i=0; i<13 && i 13+idx) blocklist[13] = 13+idx; - // Doubly indirect index blocks - idx = 13 + idx + (idx*idx); - if (dblocks > idx) blocklist[14] = idx; + // Direct index blocks + for (i=0; i<13 && i 13+idx) blocklist[13] = 13+idx; + // Doubly indirect index blocks + idx = 13 + idx + (idx*idx); + if (dblocks > idx) blocklist[14] = idx; - return 0; - } + return 0; + } - // Account for direct, singly, doubly, and triply indirect index blocks + // Account for direct, singly, doubly, and triply indirect index blocks - if (dblocks > 12) { - iblocks = ((dblocks-13)/idx)+1; - if (iblocks > 1) { - diblocks = ((iblocks-2)/idx)+1; - if (diblocks > 1) - tiblocks = ((diblocks-2)/idx)+1; - } - } + if (dblocks > 12) { + iblocks = ((dblocks-13)/idx)+1; + if (iblocks > 1) { + diblocks = ((iblocks-2)/idx)+1; + if (diblocks > 1) + tiblocks = ((diblocks-2)/idx)+1; + } + } - return dblocks + iblocks + diblocks + tiblocks; + return dblocks + iblocks + diblocks + tiblocks; } // Use the parent pointer to iterate through the tree non-recursively. static struct dirtree *treenext(struct dirtree *this) { - while (this && !this->next) this = this->parent; - if (this) this = this->next; + while (this && !this->next) this = this->parent; + if (this) this = this->next; - return this; + return this; } // Recursively calculate the number of blocks used by each inode in the tree. @@ -165,27 +163,27 @@ static struct dirtree *treenext(struct dirtree *this) static long check_treesize(struct dirtree *that, off_t *size) { - long blocks; - - while (that) { - *size += sizeof(struct ext2_dentry) + strlen(that->name); - - if (that->child) - that->st.st_blocks = check_treesize(that->child, &that->st.st_size); - else if (S_ISREG(that->st.st_mode)) { - that->st.st_blocks = file_blocks_used(that->st.st_size, 0); - TT.treeblocks += that->st.st_blocks; - } - that = that->next; - } - TT.treeblocks += blocks = file_blocks_used(*size, 0); - TT.treeinodes++; - - return blocks; + long blocks; + + while (that) { + *size += sizeof(struct ext2_dentry) + strlen(that->name); + + if (that->child) + that->st.st_blocks = check_treesize(that->child, &that->st.st_size); + else if (S_ISREG(that->st.st_mode)) { + that->st.st_blocks = file_blocks_used(that->st.st_size, 0); + TT.treeblocks += that->st.st_blocks; + } + that = that->next; + } + TT.treeblocks += blocks = file_blocks_used(*size, 0); + TT.treeinodes++; + + return blocks; } // Calculate inode numbers and link counts. -// +// // To do this right I need to copy the tree and sort it, but here's a really // ugly n^2 way of dealing with the problem that doesn't scale well to large // numbers of files (> 100,000) but can be done in very little code. @@ -193,32 +191,32 @@ static long check_treesize(struct dirtree *that, off_t *size) static void check_treelinks(struct dirtree *tree) { - struct dirtree *current=tree, *that; - long inode = INODES_RESERVED; - - while (current) { - ++inode; - // Since we can't hardlink to directories, we know their link count. - if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2; - else { - dev_t new = current->st.st_dev; - - if (!new) continue; - - // Look for other copies of current node - current->st.st_nlink = 0; - for (that = tree; that; that = treenext(that)) { - if (current->st.st_ino == that->st.st_ino && - current->st.st_dev == that->st.st_dev) - { - current->st.st_nlink++; - current->st.st_ino = inode; - } - } - } - current->st.st_ino = inode; - current = treenext(current); - } + struct dirtree *current=tree, *that; + long inode = INODES_RESERVED; + + while (current) { + ++inode; + // Since we can't hardlink to directories, we know their link count. + if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2; + else { + dev_t new = current->st.st_dev; + + if (!new) continue; + + // Look for other copies of current node + current->st.st_nlink = 0; + for (that = tree; that; that = treenext(that)) { + if (current->st.st_ino == that->st.st_ino && + current->st.st_dev == that->st.st_dev) + { + current->st.st_nlink++; + current->st.st_ino = inode; + } + } + } + current->st.st_ino = inode; + current = treenext(current); + } } // According to http://www.opengroup.org/onlinepubs/9629399/apdxa.htm @@ -231,202 +229,202 @@ static void check_treelinks(struct dirtree *tree) static void create_uuid(char *uuid) { - // Read 128 random bits - int fd = xopen("/dev/urandom", O_RDONLY); - xreadall(fd, uuid, 16); - close(fd); - - // Claim to be a DCE format UUID. - uuid[6] = (uuid[6] & 0x0F) | 0x40; - uuid[8] = (uuid[8] & 0x3F) | 0x80; - - // rfc2518 section 6.4.1 suggests if we're not using a macaddr, we should - // set bit 1 of the node ID, which is the mac multicast bit. This means we - // should never collide with anybody actually using a macaddr. - uuid[11] = uuid[11] | 128; + // Read 128 random bits + int fd = xopen("/dev/urandom", O_RDONLY); + xreadall(fd, uuid, 16); + close(fd); + + // Claim to be a DCE format UUID. + uuid[6] = (uuid[6] & 0x0F) | 0x40; + uuid[8] = (uuid[8] & 0x3F) | 0x80; + + // rfc2518 section 6.4.1 suggests if we're not using a macaddr, we should + // set bit 1 of the node ID, which is the mac multicast bit. This means we + // should never collide with anybody actually using a macaddr. + uuid[11] = uuid[11] | 128; } // Calculate inodes per group from total inodes. static uint32_t get_inodespg(uint32_t inodes) { - uint32_t temp; + uint32_t temp; - // Round up to fill complete inode blocks. - temp = (inodes + TT.groups - 1) / TT.groups; - inodes = TT.blocksize/sizeof(struct ext2_inode); - return ((temp + inodes - 1)/inodes)*inodes; + // Round up to fill complete inode blocks. + temp = (inodes + TT.groups - 1) / TT.groups; + inodes = TT.blocksize/sizeof(struct ext2_inode); + return ((temp + inodes - 1)/inodes)*inodes; } // Fill out superblock and TT structures. static void init_superblock(struct ext2_superblock *sb) { - uint32_t temp; + uint32_t temp; - // Set log_block_size and log_frag_size. + // Set log_block_size and log_frag_size. - for (temp = 0; temp < 4; temp++) if (TT.blocksize == 1024<log_block_size = sb->log_frag_size = SWAP_LE32(temp); + for (temp = 0; temp < 4; temp++) if (TT.blocksize == 1024<log_block_size = sb->log_frag_size = SWAP_LE32(temp); - // Fill out blocks_count, r_blocks_count, first_data_block + // Fill out blocks_count, r_blocks_count, first_data_block - sb->blocks_count = SWAP_LE32(TT.blocks); - sb->free_blocks_count = SWAP_LE32(TT.freeblocks); - temp = (TT.blocks * (uint64_t)TT.reserved_percent) / 100; - sb->r_blocks_count = SWAP_LE32(temp); + sb->blocks_count = SWAP_LE32(TT.blocks); + sb->free_blocks_count = SWAP_LE32(TT.freeblocks); + temp = (TT.blocks * (uint64_t)TT.reserved_percent) / 100; + sb->r_blocks_count = SWAP_LE32(temp); - sb->first_data_block = SWAP_LE32(TT.blocksize == 1024 ? 1 : 0); + sb->first_data_block = SWAP_LE32(TT.blocksize == 1024 ? 1 : 0); - // Set blocks_per_group and frags_per_group, which is the size of an - // allocation bitmap that fits in one block (I.E. how many bits per block)? + // Set blocks_per_group and frags_per_group, which is the size of an + // allocation bitmap that fits in one block (I.E. how many bits per block)? - sb->blocks_per_group = sb->frags_per_group = SWAP_LE32(TT.blockbits); + sb->blocks_per_group = sb->frags_per_group = SWAP_LE32(TT.blockbits); - // Set inodes_per_group and total inodes_count - sb->inodes_per_group = SWAP_LE32(TT.inodespg); - sb->inodes_count = SWAP_LE32(TT.inodespg * TT.groups); + // Set inodes_per_group and total inodes_count + sb->inodes_per_group = SWAP_LE32(TT.inodespg); + sb->inodes_count = SWAP_LE32(TT.inodespg * TT.groups); - // Determine free inodes. - temp = TT.inodespg*TT.groups - INODES_RESERVED; - if (temp < TT.treeinodes) error_exit("Not enough inodes.\n"); - sb->free_inodes_count = SWAP_LE32(temp - TT.treeinodes); + // Determine free inodes. + temp = TT.inodespg*TT.groups - INODES_RESERVED; + if (temp < TT.treeinodes) error_exit("Not enough inodes.\n"); + sb->free_inodes_count = SWAP_LE32(temp - TT.treeinodes); - // Fill out the rest of the superblock. - sb->max_mnt_count=0xFFFF; - sb->wtime = sb->lastcheck = sb->mkfs_time = SWAP_LE32(time(NULL)); - sb->magic = SWAP_LE32(0xEF53); - sb->state = sb->errors = SWAP_LE16(1); + // Fill out the rest of the superblock. + sb->max_mnt_count=0xFFFF; + sb->wtime = sb->lastcheck = sb->mkfs_time = SWAP_LE32(time(NULL)); + sb->magic = SWAP_LE32(0xEF53); + sb->state = sb->errors = SWAP_LE16(1); - sb->rev_level = SWAP_LE32(1); - sb->first_ino = SWAP_LE32(INODES_RESERVED+1); - sb->inode_size = SWAP_LE16(sizeof(struct ext2_inode)); - sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE); - sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER); + sb->rev_level = SWAP_LE32(1); + sb->first_ino = SWAP_LE32(INODES_RESERVED+1); + sb->inode_size = SWAP_LE16(sizeof(struct ext2_inode)); + sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE); + sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER); - create_uuid(sb->uuid); - - // TODO If we're called as mke3fs or mkfs.ext3, do a journal. + create_uuid(sb->uuid); - //if (strchr(toys.which->name,'3')) - // sb->feature_compat |= SWAP_LE32(EXT3_FEATURE_COMPAT_HAS_JOURNAL); + // TODO If we're called as mke3fs or mkfs.ext3, do a journal. + + //if (strchr(toys.which->name,'3')) + // sb->feature_compat |= SWAP_LE32(EXT3_FEATURE_COMPAT_HAS_JOURNAL); } // Does this group contain a superblock backup (and group descriptor table)? static int is_sb_group(uint32_t group) { - int i; - - // Superblock backups are on groups 0, 1, and powers of 3, 5, and 7. - if(!group || group==1) return 1; - for (i=3; i<9; i+=2) { - int j = i; - while (j sizeof(toybuf) ? sizeof(toybuf) : len; - xwrite(TT.fsfd, toybuf, out); - len -= out; - } - } + if(-1 == lseek(TT.fsfd, len, SEEK_SET)) { + memset(toybuf, 0, sizeof(toybuf)); + while (len) { + int out = len > sizeof(toybuf) ? sizeof(toybuf) : len; + xwrite(TT.fsfd, toybuf, out); + len -= out; + } + } } // Fill out an inode structure from struct stat info in dirtree. static void fill_inode(struct ext2_inode *in, struct dirtree *that) { - uint32_t fbu[15]; - int temp; - - file_blocks_used(that->st.st_size, fbu); - - // If that inode needs data blocks allocated to it. - if (that->st.st_size) { - int i, group = TT.nextblock/TT.blockbits; - - // TODO: teach this about indirect blocks. - for (i=0; i<15; i++) { - // If we just jumped into a new group, skip group overhead blocks. - while (group >= TT.nextgroup) - TT.nextblock += group_overhead(TT.nextgroup++); - } - } - // TODO : S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m) - in->mode = SWAP_LE32(that->st.st_mode); - - in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF); - in->uid_high = SWAP_LE16(that->st.st_uid >> 16); - in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF); - in->gid_high = SWAP_LE16(that->st.st_gid >> 16); - in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF); - - // Contortions to make the compiler not generate a warning for x>>32 - // when x is 32 bits. The optimizer should clean this up. - if (sizeof(that->st.st_size) > 4) temp = 32; - else temp = 0; - if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp); - - in->atime = SWAP_LE32(that->st.st_atime); - in->ctime = SWAP_LE32(that->st.st_ctime); - in->mtime = SWAP_LE32(that->st.st_mtime); - - in->links_count = SWAP_LE16(that->st.st_nlink); - in->blocks = SWAP_LE32(that->st.st_blocks); - // in->faddr + uint32_t fbu[15]; + int temp; + + file_blocks_used(that->st.st_size, fbu); + + // If that inode needs data blocks allocated to it. + if (that->st.st_size) { + int i, group = TT.nextblock/TT.blockbits; + + // TODO: teach this about indirect blocks. + for (i=0; i<15; i++) { + // If we just jumped into a new group, skip group overhead blocks. + while (group >= TT.nextgroup) + TT.nextblock += group_overhead(TT.nextgroup++); + } + } + // TODO : S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m) + in->mode = SWAP_LE32(that->st.st_mode); + + in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF); + in->uid_high = SWAP_LE16(that->st.st_uid >> 16); + in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF); + in->gid_high = SWAP_LE16(that->st.st_gid >> 16); + in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF); + + // Contortions to make the compiler not generate a warning for x>>32 + // when x is 32 bits. The optimizer should clean this up. + if (sizeof(that->st.st_size) > 4) temp = 32; + else temp = 0; + if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp); + + in->atime = SWAP_LE32(that->st.st_atime); + in->ctime = SWAP_LE32(that->st.st_ctime); + in->mtime = SWAP_LE32(that->st.st_mtime); + + in->links_count = SWAP_LE16(that->st.st_nlink); + in->blocks = SWAP_LE32(that->st.st_blocks); + // in->faddr } // Works like an archiver. @@ -435,224 +433,224 @@ static void fill_inode(struct ext2_inode *in, struct dirtree *that) void mke2fs_main(void) { - int i, temp; - off_t length; - uint32_t usedblocks, usedinodes, dtiblk, dtbblk; - struct dirtree *dti, *dtb; - - // Handle command line arguments. - - if (toys.optargs[1]) { - sscanf(toys.optargs[1], "%u", &TT.blocks); - temp = O_RDWR|O_CREAT; - } else temp = O_RDWR; - if (!TT.reserved_percent) TT.reserved_percent = 5; - - // TODO: Check if filesystem is mounted here - - // For mke?fs, open file. For gene?fs, create file. - TT.fsfd = xcreate(*toys.optargs, temp, 0777); - - // Determine appropriate block size and block count from file length. - // (If no length, default to 4k. They can override it on the cmdline.) - - length = fdlength(TT.fsfd); - if (!TT.blocksize) TT.blocksize = (length && length < 1<<29) ? 1024 : 4096; - TT.blockbits = 8*TT.blocksize; - if (!TT.blocks) TT.blocks = length/TT.blocksize; - - // Collect gene2fs list or lost+found, calculate requirements. - - if (TT.gendir) { - strncpy(toybuf, TT.gendir, sizeof(toybuf)); - dti = dirtree_read(toybuf, NULL, NULL); - } else { - dti = xzalloc(sizeof(struct dirtree)+11); - strcpy(dti->name, "lost+found"); - dti->st.st_mode = S_IFDIR|0755; - dti->st.st_ctime = dti->st.st_mtime = time(NULL); - } - - // Add root directory inode. This is iterated through for when finding - // blocks, but not when finding inodes. The tree's parent pointers don't - // point back into this. - - dtb = xzalloc(sizeof(struct dirtree)+1); - dtb->st.st_mode = S_IFDIR|0755; - dtb->st.st_ctime = dtb->st.st_mtime = time(NULL); - dtb->child = dti; - - // Figure out how much space is used by preset files - length = check_treesize(dtb, &(dtb->st.st_size)); - check_treelinks(dtb); - - // Figure out how many total inodes we need. - - if (!TT.inodes) { - if (!TT.bytes_per_inode) TT.bytes_per_inode = 8192; - TT.inodes = (TT.blocks * (uint64_t)TT.blocksize) / TT.bytes_per_inode; - } - - // If we're generating a filesystem and have no idea how many blocks it - // needs, start with a minimal guess, find the overhead of that many - // groups, and loop until this is enough groups to store this many blocks. - if (!TT.blocks) TT.groups = (TT.treeblocks/TT.blockbits)+1; - else TT.groups = div_round_up(TT.blocks, TT.blockbits); - - for (;;) { - temp = TT.treeblocks; - - for (i = 0; i TT.blocks) end = TT.blocks & (TT.blockbits-1); - - // Blocks used by inode table - itable = (TT.inodespg*sizeof(struct ext2_inode))/TT.blocksize; - - // If a superblock goes here, write it out. - start = group_superblock_overhead(i); - if (start) { - struct ext2_group *bg = (struct ext2_group *)toybuf; - int treeblocks = TT.treeblocks, treeinodes = TT.treeinodes; - - TT.sb.block_group_nr = SWAP_LE16(i); - - // Write superblock and pad it up to block size - xwrite(TT.fsfd, &TT.sb, sizeof(struct ext2_superblock)); - temp = TT.blocksize - sizeof(struct ext2_superblock); - if (!i && TT.blocksize > 1024) temp -= 1024; - memset(toybuf, 0, TT.blocksize); - xwrite(TT.fsfd, toybuf, temp); - - // Loop through groups to write group descriptor table. - for(j=0; j treeinodes) { - treeinodes -= temp; - temp = 0; - } else { - temp -= treeinodes; - treeinodes = 0; - } - bg[slot].free_inodes_count = SWAP_LE16(temp); - - // How many free blocks in this group? - temp = TT.inodespg/(TT.blocksize/sizeof(struct ext2_inode)) + 2; - temp = end-used-temp; - if (temp > treeblocks) { - treeblocks -= temp; - temp = 0; - } else { - temp -= treeblocks; - treeblocks = 0; - } - bg[slot].free_blocks_count = SWAP_LE32(temp); - - // Fill out rest of group structure - used += j*TT.blockbits; - bg[slot].block_bitmap = SWAP_LE32(used++); - bg[slot].inode_bitmap = SWAP_LE32(used++); - bg[slot].inode_table = SWAP_LE32(used); - bg[slot].used_dirs_count = 0; // (TODO) - } - xwrite(TT.fsfd, bg, TT.blocksize); - } - - // Now write out stuff that every block group has. - - // Write block usage bitmap - - start += 2 + itable; - memset(toybuf, 0, TT.blocksize); - bits_set(toybuf, 0, start); - bits_set(toybuf, end, TT.blockbits-end); - temp = TT.treeblocks - usedblocks; - if (temp) { - if (end-start > temp) temp = end-start; - bits_set(toybuf, start, temp); - } - xwrite(TT.fsfd, toybuf, TT.blocksize); - - // Write inode bitmap - memset(toybuf, 0, TT.blocksize); - j = 0; - if (!i) bits_set(toybuf, 0, j = INODES_RESERVED); - bits_set(toybuf, TT.inodespg, slot = TT.blockbits-TT.inodespg); - temp = TT.treeinodes - usedinodes; - if (temp) { - if (slot-j > temp) temp = slot-j; - bits_set(toybuf, j, temp); - } - xwrite(TT.fsfd, toybuf, TT.blocksize); - - // Write inode table for this group (TODO) - for (j = 0; jname, "lost+found"); + dti->st.st_mode = S_IFDIR|0755; + dti->st.st_ctime = dti->st.st_mtime = time(NULL); + } + + // Add root directory inode. This is iterated through for when finding + // blocks, but not when finding inodes. The tree's parent pointers don't + // point back into this. + + dtb = xzalloc(sizeof(struct dirtree)+1); + dtb->st.st_mode = S_IFDIR|0755; + dtb->st.st_ctime = dtb->st.st_mtime = time(NULL); + dtb->child = dti; + + // Figure out how much space is used by preset files + length = check_treesize(dtb, &(dtb->st.st_size)); + check_treelinks(dtb); + + // Figure out how many total inodes we need. + + if (!TT.inodes) { + if (!TT.bytes_per_inode) TT.bytes_per_inode = 8192; + TT.inodes = (TT.blocks * (uint64_t)TT.blocksize) / TT.bytes_per_inode; + } + + // If we're generating a filesystem and have no idea how many blocks it + // needs, start with a minimal guess, find the overhead of that many + // groups, and loop until this is enough groups to store this many blocks. + if (!TT.blocks) TT.groups = (TT.treeblocks/TT.blockbits)+1; + else TT.groups = div_round_up(TT.blocks, TT.blockbits); + + for (;;) { + temp = TT.treeblocks; + + for (i = 0; i TT.blocks) end = TT.blocks & (TT.blockbits-1); + + // Blocks used by inode table + itable = (TT.inodespg*sizeof(struct ext2_inode))/TT.blocksize; + + // If a superblock goes here, write it out. + start = group_superblock_overhead(i); + if (start) { + struct ext2_group *bg = (struct ext2_group *)toybuf; + int treeblocks = TT.treeblocks, treeinodes = TT.treeinodes; + + TT.sb.block_group_nr = SWAP_LE16(i); + + // Write superblock and pad it up to block size + xwrite(TT.fsfd, &TT.sb, sizeof(struct ext2_superblock)); + temp = TT.blocksize - sizeof(struct ext2_superblock); + if (!i && TT.blocksize > 1024) temp -= 1024; + memset(toybuf, 0, TT.blocksize); + xwrite(TT.fsfd, toybuf, temp); + + // Loop through groups to write group descriptor table. + for(j=0; j treeinodes) { + treeinodes -= temp; + temp = 0; + } else { + temp -= treeinodes; + treeinodes = 0; + } + bg[slot].free_inodes_count = SWAP_LE16(temp); + + // How many free blocks in this group? + temp = TT.inodespg/(TT.blocksize/sizeof(struct ext2_inode)) + 2; + temp = end-used-temp; + if (temp > treeblocks) { + treeblocks -= temp; + temp = 0; + } else { + temp -= treeblocks; + treeblocks = 0; + } + bg[slot].free_blocks_count = SWAP_LE32(temp); + + // Fill out rest of group structure + used += j*TT.blockbits; + bg[slot].block_bitmap = SWAP_LE32(used++); + bg[slot].inode_bitmap = SWAP_LE32(used++); + bg[slot].inode_table = SWAP_LE32(used); + bg[slot].used_dirs_count = 0; // (TODO) + } + xwrite(TT.fsfd, bg, TT.blocksize); + } + + // Now write out stuff that every block group has. + + // Write block usage bitmap + + start += 2 + itable; + memset(toybuf, 0, TT.blocksize); + bits_set(toybuf, 0, start); + bits_set(toybuf, end, TT.blockbits-end); + temp = TT.treeblocks - usedblocks; + if (temp) { + if (end-start > temp) temp = end-start; + bits_set(toybuf, start, temp); + } + xwrite(TT.fsfd, toybuf, TT.blocksize); + + // Write inode bitmap + memset(toybuf, 0, TT.blocksize); + j = 0; + if (!i) bits_set(toybuf, 0, j = INODES_RESERVED); + bits_set(toybuf, TT.inodespg, slot = TT.blockbits-TT.inodespg); + temp = TT.treeinodes - usedinodes; + if (temp) { + if (slot-j > temp) temp = slot-j; + bits_set(toybuf, j, temp); + } + xwrite(TT.fsfd, toybuf, TT.blocksize); + + // Write inode table for this group (TODO) + for (j = 0; j USE_MKSWAP(NEWTOY(mkswap, "<1>1", TOYFLAG_SBIN)) config MKSWAP - bool "mkswap" - default y - help - usage: mkswap DEVICE + bool "mkswap" + default y + help + usage: mkswap DEVICE - Sets up a Linux swap area on a device or file. + Sets up a Linux swap area on a device or file. */ #include "toys.h" void mkswap_main(void) { - int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE); - off_t len = fdlength(fd); - unsigned int pages = (len/pagesize)-1, *swap = (unsigned int *)toybuf; + int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE); + off_t len = fdlength(fd); + unsigned int pages = (len/pagesize)-1, *swap = (unsigned int *)toybuf; - // Write header. Note that older kernel versions checked signature - // on disk (not in cache) during swapon, so sync after writing. + // Write header. Note that older kernel versions checked signature + // on disk (not in cache) during swapon, so sync after writing. - swap[0] = 1; - swap[1] = pages; - xlseek(fd, 1024, SEEK_SET); - xwrite(fd, swap, 129*sizeof(unsigned int)); - xlseek(fd, pagesize-10, SEEK_SET); - xwrite(fd, "SWAPSPACE2", 10); - fsync(fd); + swap[0] = 1; + swap[1] = pages; + xlseek(fd, 1024, SEEK_SET); + xwrite(fd, swap, 129*sizeof(unsigned int)); + xlseek(fd, pagesize-10, SEEK_SET); + xwrite(fd, "SWAPSPACE2", 10); + fsync(fd); - if (CFG_TOYBOX_FREE) close(fd); + if (CFG_TOYBOX_FREE) close(fd); - printf("Swapspace size: %luk\n", pages*(unsigned long)(pagesize/1024)); + printf("Swapspace size: %luk\n", pages*(unsigned long)(pagesize/1024)); } diff --git a/toys/other/modinfo.c b/toys/other/modinfo.c index 0c5f177f..36a38382 100644 --- a/toys/other/modinfo.c +++ b/toys/other/modinfo.c @@ -1,101 +1,92 @@ -/* vi: set sw=4 ts=4: - * - * modinfo.c - Display module info +/* modinfo.c - Display module info * * Copyright 2012 Andre Renaud - * USE_MODINFO(NEWTOY(modinfo, "<1F:0", TOYFLAG_BIN)) config MODINFO - bool "modinfo" - default y - help - usage: modinfo [-0] [-F field] [modulename...] + bool "modinfo" + default y + help + usage: modinfo [-0] [-F field] [modulename...] */ #define FOR_modinfo #include "toys.h" GLOBALS( - char *field; + char *field; ) static const char *modinfo_tags[] = { - "alias", "license", "description", "author", "vermagic", - "srcversion", "intree", "parm", "depends", + "alias", "license", "description", "author", "vermagic", + "srcversion", "intree", "parm", "depends", }; static void output_field(const char *field, const char *value) { - int len; - - if (TT.field && strcmp(TT.field, field) != 0) - return; - - len = strlen(field); - - if (TT.field) - xprintf("%s", value); - else - xprintf("%s:%*s%s", - field, 15 - len, "", value); - if (toys.optflags & FLAG_0) - xwrite(fileno(stdout), "\0", 1); - else - xputs(""); + int len; + + if (TT.field && strcmp(TT.field, field) != 0) return; + + len = strlen(field); + + if (TT.field) xprintf("%s", value); + else xprintf("%s:%*s%s", field, 15 - len, "", value); + if (toys.optflags & FLAG_0) xwrite(fileno(stdout), "\0", 1); + else xputs(""); } static void modinfo_file(struct dirtree *dir) { - int fd, len, i; - char *buf, *pos; - char *full_name; - - full_name = dirtree_path(dir, NULL); - - output_field("filename", full_name); - fd = xopen(full_name, O_RDONLY); - len = fdlength(fd); - buf = xmalloc(len); - xreadall(fd, buf, len); - - for (pos = buf; pos < buf + len + 10; pos++) { - if (*pos) - continue; - - for (i = 0; i < sizeof(modinfo_tags) / sizeof(modinfo_tags[0]); i++) { - const char *str = modinfo_tags[i]; - int len = strlen(str); - if (strncmp(pos + 1, str, len) == 0 && pos[len + 1] == '=') - output_field(str, &pos[len + 2]); - } + int fd, len, i; + char *buf, *pos; + char *full_name; + + full_name = dirtree_path(dir, NULL); + + output_field("filename", full_name); + fd = xopen(full_name, O_RDONLY); + len = fdlength(fd); + buf = xmalloc(len); + xreadall(fd, buf, len); + + for (pos = buf; pos < buf + len + 10; pos++) { + if (*pos) continue; + + for (i = 0; i < sizeof(modinfo_tags) / sizeof(modinfo_tags[0]); i++) { + const char *str = modinfo_tags[i]; + int len = strlen(str); + if (strncmp(pos + 1, str, len) == 0 && pos[len + 1] == '=') + output_field(str, &pos[len + 2]); } + } - free(full_name); - free(buf); - close(fd); + free(full_name); + free(buf); + close(fd); } static int check_module(struct dirtree *new) { - if (S_ISREG(new->st.st_mode)) { - char **s; - for (s = toys.optargs; *s; s++) { - int len = strlen(*s); - if (!strncmp(*s, new->name, len) && !strcmp(new->name+len, ".ko")) - modinfo_file(new); - } + if (S_ISREG(new->st.st_mode)) { + char **s; + for (s = toys.optargs; *s; s++) { + int len = strlen(*s); + if (!strncmp(*s, new->name, len) && !strcmp(new->name+len, ".ko")) + modinfo_file(new); } + } - return dirtree_notdotdot(new); + return dirtree_notdotdot(new); } void modinfo_main(void) { - struct utsname uts; - if (uname(&uts) < 0) perror_exit("bad uname"); - sprintf(toybuf, "/lib/modules/%s", uts.release); - dirtree_read(toybuf, check_module); + struct utsname uts; + + if (uname(&uts) < 0) perror_exit("bad uname"); + sprintf(toybuf, "/lib/modules/%s", uts.release); + dirtree_read(toybuf, check_module); } diff --git a/toys/other/mountpoint.c b/toys/other/mountpoint.c index fe63b725..29b8ae67 100644 --- a/toys/other/mountpoint.c +++ b/toys/other/mountpoint.c @@ -1,20 +1,19 @@ -/* vi: set sw=4 ts=4: - * - * mountpoint.c - Check if a directory is a mountpoint. +/* mountpoint.c - Check if a directory is a mountpoint. * * Copyright 2012 Elie De Brauwer USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx", TOYFLAG_BIN)) config MOUNTPOINT - bool "mountpoint" - default y - help - usage: mountpoint [-q] [-d] directory - mountpoint [-q] [-x] device - -q Be quiet, return zero if directory is a mountpoint - -d Print major/minor device number of the directory - -x Print major/minor device number of the block device + bool "mountpoint" + default y + help + usage: mountpoint [-q] [-d] directory + mountpoint [-q] [-x] device + + -q Be quiet, return zero if directory is a mountpoint + -d Print major/minor device number of the directory + -x Print major/minor device number of the block device */ #define FOR_mountpoint @@ -22,34 +21,34 @@ config MOUNTPOINT void mountpoint_main(void) { - struct stat st1, st2; - int res = 0; - int quiet = toys.optflags & FLAG_q; - toys.exitval = 1; // be pessimistic - strncpy(toybuf, toys.optargs[0], sizeof(toybuf)); - if (((toys.optflags & FLAG_x) && lstat(toybuf, &st1)) || stat(toybuf, &st1)) - perror_exit("%s", toybuf); + struct stat st1, st2; + int res = 0; + int quiet = toys.optflags & FLAG_q; + toys.exitval = 1; // be pessimistic + strncpy(toybuf, toys.optargs[0], sizeof(toybuf)); + if (((toys.optflags & FLAG_x) && lstat(toybuf, &st1)) || stat(toybuf, &st1)) + perror_exit("%s", toybuf); - if (toys.optflags & FLAG_x){ - if (S_ISBLK(st1.st_mode)) { - if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev)); - toys.exitval = 0; - return; - } - if (!quiet) printf("%s: not a block device\n", toybuf); - return; - } + if (toys.optflags & FLAG_x){ + if (S_ISBLK(st1.st_mode)) { + if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev)); + toys.exitval = 0; + return; + } + if (!quiet) printf("%s: not a block device\n", toybuf); + return; + } - if(!S_ISDIR(st1.st_mode)){ - if (!quiet) printf("%s: not a directory\n", toybuf); - return; - } - strncat(toybuf, "/..", sizeof(toybuf)); - stat(toybuf, &st2); - res = (st1.st_dev != st2.st_dev) || - (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); - if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not "); - if (toys.optflags & FLAG_d) - printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev)); - toys.exitval = res ? 0 : 1; + if(!S_ISDIR(st1.st_mode)){ + if (!quiet) printf("%s: not a directory\n", toybuf); + return; + } + strncat(toybuf, "/..", sizeof(toybuf)); + stat(toybuf, &st2); + res = (st1.st_dev != st2.st_dev) || + (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); + if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not "); + if (toys.optflags & FLAG_d) + printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev)); + toys.exitval = res ? 0 : 1; } diff --git a/toys/other/netcat.c b/toys/other/netcat.c index 2e90737d..0173e6db 100644 --- a/toys/other/netcat.c +++ b/toys/other/netcat.c @@ -1,46 +1,42 @@ -/* vi: set sw=4 ts=4: - * - * netcat.c - Forward stdin/stdout to a file or network connection. +/* netcat.c - Forward stdin/stdout to a file or network connection. * * Copyright 2007 Rob Landley * * TODO: udp, ipv6, genericize for telnet/microcom/tail-f - USE_NETCAT(OLDTOY(nc, netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN)) USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN)) config NETCAT - bool "netcat" - default y - help - usage: netcat [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|-let} [-e COMMAND] - - -w SECONDS timeout for connection - -p local port number - -s local ipv4 address - -q SECONDS quit this many seconds after EOF on stdin. - -f use FILENAME (ala /dev/ttyS0) instead of network + bool "netcat" + default y + help + usage: netcat [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|-let} [-e COMMAND] - Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with - netcat -f to connect to a serial port. + -w SECONDS timeout for connection + -p local port number + -s local ipv4 address + -q SECONDS quit this many seconds after EOF on stdin. + -f use FILENAME (ala /dev/ttyS0) instead of network + Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with + netcat -f to connect to a serial port. config NETCAT_LISTEN - bool "netcat server options (-let)" - default y - depends on NETCAT - help - -t allocate tty (must come before -l or -L) - -l listen for one incoming connection. - -L listen for multiple incoming connections (server mode). - - Any additional command line arguments after -l or -L are executed - to handle each incoming connection. If none, the connection is - forwarded to stdin/stdout. - - For a quick-and-dirty server, try something like: - netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l + bool "netcat server options (-let)" + default y + depends on NETCAT + help + -t allocate tty (must come before -l or -L) + -l listen for one incoming connection. + -L listen for multiple incoming connections (server mode). + + Any additional command line arguments after -l or -L are executed + to handle each incoming connection. If none, the connection is + forwarded to stdin/stdout. + + For a quick-and-dirty server, try something like: + netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l */ #define FOR_netcat @@ -48,33 +44,33 @@ config NETCAT_LISTEN #include "toynet.h" GLOBALS( - char *filename; // -f read from filename instead of network - long quit_delay; // -q Exit after EOF from stdin after # seconds. - char *source_address; // -s Bind to a specific source address. - long port; // -p Bind to a specific source port. - long wait; // -w Wait # seconds for a connection. + char *filename; // -f read from filename instead of network + long quit_delay; // -q Exit after EOF from stdin after # seconds. + char *source_address; // -s Bind to a specific source address. + long port; // -p Bind to a specific source port. + long wait; // -w Wait # seconds for a connection. ) static void timeout(int signum) { - if (TT.wait) error_exit("Timeout"); - exit(0); + if (TT.wait) error_exit("Timeout"); + exit(0); } static void set_alarm(int seconds) { - signal(SIGALRM, seconds ? timeout : SIG_DFL); - alarm(seconds); + signal(SIGALRM, seconds ? timeout : SIG_DFL); + alarm(seconds); } // Translate x.x.x.x numeric IPv4 address, or else DNS lookup an IPv4 name. static void lookup_name(char *name, uint32_t *result) { - struct hostent *hostbyname; + struct hostent *hostbyname; - hostbyname = gethostbyname(name); - if (!hostbyname) error_exit("no host '%s'", name); - *result = *(uint32_t *)*hostbyname->h_addr_list; + hostbyname = gethostbyname(name); + if (!hostbyname) error_exit("no host '%s'", name); + *result = *(uint32_t *)*hostbyname->h_addr_list; } // Worry about a fancy lookup later. @@ -85,143 +81,142 @@ static void lookup_port(char *str, uint16_t *port) void netcat_main(void) { - int sockfd=-1, pollcount=2; - struct pollfd pollfds[2]; - - memset(pollfds, 0, 2*sizeof(struct pollfd)); - pollfds[0].events = pollfds[1].events = POLLIN; - set_alarm(TT.wait); - - // The argument parsing logic can't make "<2" conditional on other - // arguments like -f and -l, so we do it by hand here. - if (toys.optflags&FLAG_f) { - if (toys.optc) toys.exithelp++; - } else if (!(toys.optflags&(FLAG_l|FLAG_L)) && toys.optc!=2) toys.exithelp++; - - if (toys.exithelp) error_exit("Argument count wrong"); - - if (TT.filename) pollfds[0].fd = xopen(TT.filename, O_RDWR); - else { - int temp; - struct sockaddr_in address; - - // Setup socket - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (-1 == sockfd) perror_exit("socket"); - fcntl(sockfd, F_SETFD, FD_CLOEXEC); - temp = 1; - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp)); - memset(&address, 0, sizeof(address)); - address.sin_family = AF_INET; - if (TT.source_address || TT.port) { - address.sin_port = SWAP_BE16(TT.port); - if (TT.source_address) - lookup_name(TT.source_address, (uint32_t *)&address.sin_addr); - if (bind(sockfd, (struct sockaddr *)&address, sizeof(address))) - perror_exit("bind"); - } - - // Dial out - - if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) { - // Figure out where to dial out to. - lookup_name(*toys.optargs, (uint32_t *)&address.sin_addr); - lookup_port(toys.optargs[1], &address.sin_port); - temp = connect(sockfd, (struct sockaddr *)&address, sizeof(address)); - if (temp<0) perror_exit("connect"); - pollfds[0].fd = sockfd; - - // Listen for incoming connections - - } else { - socklen_t len = sizeof(address); - - if (listen(sockfd, 5)) error_exit("listen"); - if (!TT.port) { - getsockname(sockfd, (struct sockaddr *)&address, &len); - printf("%d\n", SWAP_BE16(address.sin_port)); - fflush(stdout); - } - // Do we need to return immediately because -l has arguments? - - if ((toys.optflags&FLAG_l) && toys.optc) { - if (fork()) goto cleanup; - close(0); - close(1); - close(2); - } - - for (;;) { - pid_t child = 0; - - // For -l, call accept from the _new_ thread. - - pollfds[0].fd = accept(sockfd, (struct sockaddr *)&address, - &len); - if (pollfds[0].fd<0) perror_exit("accept"); - - // Do we need a tty? - - if (toys.optflags&FLAG_t) - child = forkpty(&(pollfds[1].fd), NULL, NULL, NULL); - - // Do we need to fork and/or redirect for exec? - - else { - if (toys.optflags&FLAG_L) child = fork(); - if (!child && toys.optc) { - int fd = pollfds[0].fd; - - if (!temp) close(sockfd); - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - if (fd>2) close(fd); - } - } - - if (child<0) error_msg("Fork failed\n"); - if (child<1) break; - close(pollfds[0].fd); - } - } - } - - // We have a connection. Disarm timeout. - // (Does not play well with -L, but what _should_ that do?) - set_alarm(0); - - if (CFG_NETCAT_LISTEN && (toys.optflags&(FLAG_L|FLAG_l) && toys.optc)) { - execvp(*toys.optargs, toys.optargs); - error_exit("Exec failed"); - } - - // Poll loop copying stdin->socket and socket->stdout. - for (;;) { - int i; - - if (0>poll(pollfds, pollcount, -1)) perror_exit("poll"); - - for (i=0; i2) close(fd); + } + } + + if (child<0) error_msg("Fork failed\n"); + if (child<1) break; + close(pollfds[0].fd); + } + } + } + + // We have a connection. Disarm timeout. + // (Does not play well with -L, but what _should_ that do?) + set_alarm(0); + + if (CFG_NETCAT_LISTEN && (toys.optflags&(FLAG_L|FLAG_l) && toys.optc)) { + execvp(*toys.optargs, toys.optargs); + error_exit("Exec failed"); + } + + // Poll loop copying stdin->socket and socket->stdout. + for (;;) { + int i; + + if (0>poll(pollfds, pollcount, -1)) perror_exit("poll"); + + for (i=0; i. USE_ONEIT(NEWTOY(oneit, "^<1c:p", TOYFLAG_SBIN)) config ONEIT - bool "oneit" - default y - help - usage: oneit [-p] [-c /dev/tty0] command [...] + bool "oneit" + default y + help + usage: oneit [-p] [-c /dev/tty0] command [...] - A simple init program that runs a single supplied command line with a - controlling tty (so CTRL-C can kill it). + A simple init program that runs a single supplied command line with a + controlling tty (so CTRL-C can kill it). - -p Power off instead of rebooting when command exits. - -c Which console device to use. + -p Power off instead of rebooting when command exits. + -c Which console device to use. - The oneit command runs the supplied command line as a child process - (because PID 1 has signals blocked), attached to /dev/tty0, in its - own session. Then oneit reaps zombies until the child exits, at - which point it reboots (or with -p, powers off) the system. + The oneit command runs the supplied command line as a child process + (because PID 1 has signals blocked), attached to /dev/tty0, in its + own session. Then oneit reaps zombies until the child exits, at + which point it reboots (or with -p, powers off) the system. */ #define FOR_oneit @@ -29,7 +27,7 @@ config ONEIT #include GLOBALS( - char *console; + char *console; ) // The minimum amount of work necessary to get ctrl-c and such to work is: @@ -53,22 +51,21 @@ void oneit_main(void) if (pid) { // pid 1 just reaps zombies until it gets its child, then halts the system. - while (pid!=wait(&i)); + while (pid != wait(&i)); sync(); - // PID 1 can't call reboot() because it kills the task that calls it, - // which causes the kernel to panic before the actual reboot happens. - if (!vfork()) - reboot((toys.optflags & FLAG_p) ? RB_POWER_OFF : RB_AUTOBOOT); - sleep(5); - _exit(1); + // PID 1 can't call reboot() because it kills the task that calls it, + // which causes the kernel to panic before the actual reboot happens. + if (!vfork()) reboot((toys.optflags & FLAG_p) ? RB_POWER_OFF : RB_AUTOBOOT); + sleep(5); + _exit(1); } // Redirect stdio to /dev/tty0, with new session ID, so ctrl-c works. setsid(); for (i=0; i<3; i++) { close(i); - xopen(TT.console ? TT.console : "/dev/tty0",O_RDWR); + xopen(TT.console ? TT.console : "/dev/tty0", O_RDWR); } // Can't xexec() here, because we vforked so we don't want to error_exit(). diff --git a/toys/other/printenv.c b/toys/other/printenv.c index d5177468..e8bcf29b 100644 --- a/toys/other/printenv.c +++ b/toys/other/printenv.c @@ -1,20 +1,18 @@ -/* vi: set sw=4 ts=4: - * - * printenv.c - Print environment variables. +/* printenv.c - Print environment variables. * * Copyright 2012 Georgi Chorbadzhiyski USE_PRINTENV(NEWTOY(printenv, "0(null)", TOYFLAG_USR|TOYFLAG_BIN)) config PRINTENV - bool "printenv" - default y - help - usage: printenv [-0] [env_var...] + bool "printenv" + default y + help + usage: printenv [-0] [env_var...] - Print environment variables. + Print environment variables. - -0 Use \0 as delimiter instead of \n + -0 Use \0 as delimiter instead of \n */ #include "toys.h" @@ -23,24 +21,23 @@ extern char **environ; void printenv_main(void) { - char **env, **var = toys.optargs; - char delim = '\n'; - - if (toys.optflags) delim = 0; - - do { - int catch = 0, len = *var ? strlen(*var) : 0; - - for (env = environ; *env; env++) { - char *out = *env; - if (*var) { - if (!strncmp(out, *var, len) && out[len] == '=') - out += len +1; - else continue; - } - xprintf("%s%c", out, delim); - catch++; - } - if (*var && !catch) toys.exitval = 1; - } while (*var && *(++var)); + char **env, **var = toys.optargs; + char delim = '\n'; + + if (toys.optflags) delim = 0; + + do { + int catch = 0, len = *var ? strlen(*var) : 0; + + for (env = environ; *env; env++) { + char *out = *env; + if (*var) { + if (!strncmp(out, *var, len) && out[len] == '=') out += len +1; + else continue; + } + xprintf("%s%c", out, delim); + catch++; + } + if (*var && !catch) toys.exitval = 1; + } while (*var && *(++var)); } diff --git a/toys/other/readlink.c b/toys/other/readlink.c index c579635c..b7f77f91 100644 --- a/toys/other/readlink.c +++ b/toys/other/readlink.c @@ -1,43 +1,41 @@ -/* vi: set sw=4 ts=4: - * - * readlink.c - Return string representation of a symbolic link. +/* readlink.c - Return string representation of a symbolic link. * * Copyright 2007 Rob Landley USE_READLINK(NEWTOY(readlink, "<1f", TOYFLAG_BIN)) config READLINK - bool "readlink" - default n - help - usage: readlink + bool "readlink" + default n + help + usage: readlink - Show what a symbolic link points to. + Show what a symbolic link points to. config READLINK_F - bool "readlink -f" - default n - depends on READLINK - help - usage: readlink [-f] - - -f Show full cannonical path, with no symlinks in it. Returns - nonzero if nothing could currently exist at this location. + bool "readlink -f" + default n + depends on READLINK + help + usage: readlink [-f] + + -f Show full cannonical path, with no symlinks in it. Returns + nonzero if nothing could currently exist at this location. */ #include "toys.h" void readlink_main(void) { - char *s; + char *s; - // Calculating full cannonical path? + // Calculating full cannonical path? - if (CFG_READLINK_F && toys.optflags) s = xrealpath(*toys.optargs); - else s = xreadlink(*toys.optargs); + if (CFG_READLINK_F && toys.optflags) s = xrealpath(*toys.optargs); + else s = xreadlink(*toys.optargs); - if (s) { - xputs(s); - if (CFG_TOYBOX_FREE) free(s); - } else toys.exitval = 1; + if (s) { + xputs(s); + if (CFG_TOYBOX_FREE) free(s); + } else toys.exitval = 1; } diff --git a/toys/other/realpath.c b/toys/other/realpath.c index 1503c455..dc75840b 100644 --- a/toys/other/realpath.c +++ b/toys/other/realpath.c @@ -1,29 +1,28 @@ -/* vi: set sw=4 ts=4: - * - * realpath.c - Return the canonical version of a pathname +/* realpath.c - Return the canonical version of a pathname * * Copyright 2012 Andre Renaud USE_REALPATH(NEWTOY(realpath, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config REALPATH - bool "realpath" - default y - help - usage: realpath FILE... + bool "realpath" + default y + help + usage: realpath FILE... - Display the canonical absolute pathname + Display the canonical absolute pathname */ #include "toys.h" void realpath_main(void) { - char **s = toys.optargs; - for (s = toys.optargs; *s; s++) { - if (!realpath(*s, toybuf)) { - perror_msg("cannot access '%s'", *s); - toys.exitval = 1; - } else xputs(toybuf); - } + char **s = toys.optargs; + + for (s = toys.optargs; *s; s++) { + if (!realpath(*s, toybuf)) { + perror_msg("cannot access '%s'", *s); + toys.exitval = 1; + } else xputs(toybuf); + } } diff --git a/toys/other/rmmod.c b/toys/other/rmmod.c index 18ace3fa..093eb8a1 100644 --- a/toys/other/rmmod.c +++ b/toys/other/rmmod.c @@ -1,20 +1,18 @@ -/* vi: set sw=4 ts=4: - * - * rmmod.c - Remove a module from the Linux kernel. +/* rmmod.c - Remove a module from the Linux kernel. * * Copyright 2012 Elie De Brauwer USE_RMMOD(NEWTOY(rmmod, "<1wf", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config RMMOD - bool "rmmod" - default y - help - usage: rmmod [-wf] [MODULE] + bool "rmmod" + default y + help + usage: rmmod [-wf] [MODULE] - Unload the module named MODULE from the Linux kernel. - -f Force unload of a module - -w Wait until the module is no longer used. + Unload the module named MODULE from the Linux kernel. + -f Force unload of a module + -w Wait until the module is no longer used. */ @@ -26,25 +24,22 @@ config RMMOD void rmmod_main(void) { - unsigned int flags = O_NONBLOCK|O_EXCL; - char * mod_name; - int len; - - // Basename - mod_name = strrchr(toys.optargs[0],'/'); - if (mod_name) - mod_name++; - else - mod_name = toys.optargs[0]; - - // Remove .ko if present - len = strlen(mod_name); - if (len > 3 && !strcmp(&mod_name[len-3], ".ko" )) - mod_name[len-3] = 0; - - if (toys.optflags & FLAG_f) flags |= O_TRUNC; - if (toys.optflags & FLAG_w) flags &= ~O_NONBLOCK; - - if (delete_module(mod_name, flags)) - perror_exit("failed to unload %s", mod_name); + unsigned int flags = O_NONBLOCK|O_EXCL; + char * mod_name; + int len; + + // Basename + mod_name = strrchr(toys.optargs[0],'/'); + if (mod_name) mod_name++; + else mod_name = toys.optargs[0]; + + // Remove .ko if present + len = strlen(mod_name); + if (len > 3 && !strcmp(&mod_name[len-3], ".ko" )) mod_name[len-3] = 0; + + if (toys.optflags & FLAG_f) flags |= O_TRUNC; + if (toys.optflags & FLAG_w) flags &= ~O_NONBLOCK; + + if (delete_module(mod_name, flags)) + perror_exit("failed to unload %s", mod_name); } diff --git a/toys/other/setsid.c b/toys/other/setsid.c index 0f08cc03..59a1d78f 100644 --- a/toys/other/setsid.c +++ b/toys/other/setsid.c @@ -1,31 +1,28 @@ -/* vi: set sw=4 ts=4: - * - * setsid.c - Run program in a new session ID. +/* setsid.c - Run program in a new session ID. * * Copyright 2006 Rob Landley USE_SETSID(NEWTOY(setsid, "^<1t", TOYFLAG_USR|TOYFLAG_BIN)) config SETSID - bool "setsid" - default y - help - usage: setsid [-t] command [args...] + bool "setsid" + default y + help + usage: setsid [-t] command [args...] - Run process in a new session. + Run process in a new session. - -t Grab tty (become foreground process, receiving keyboard signals) + -t Grab tty (become foreground process, receiving keyboard signals) */ #include "toys.h" void setsid_main(void) { - while (setsid()<0) - if (vfork()) _exit(0); - if (toys.optflags) { - setpgid(0,0); - tcsetpgrp(0, getpid()); - } - xexec(toys.optargs); + while (setsid()<0) if (vfork()) _exit(0); + if (toys.optflags) { + setpgid(0,0); + tcsetpgrp(0, getpid()); + } + xexec(toys.optargs); } diff --git a/toys/other/swapoff.c b/toys/other/swapoff.c index cac15732..b89e915c 100644 --- a/toys/other/swapoff.c +++ b/toys/other/swapoff.c @@ -1,24 +1,21 @@ -/* vi: set sw=4 ts=4: - * - * swapoff.c - Disable region for swapping +/* swapoff.c - Disable region for swapping * * Copyright 2012 Elie De Brauwer USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config SWAPOFF - bool "swapoff" - default y - help - usage: swapoff swapregion + bool "swapoff" + default y + help + usage: swapoff swapregion - Disable swapping on a given swapregion. + Disable swapping on a given swapregion. */ #include "toys.h" void swapoff_main(void) { - if (swapoff(toys.optargs[0])) - perror_exit("failed to remove swaparea"); + if (swapoff(toys.optargs[0])) perror_exit("failed to remove swaparea"); } diff --git a/toys/other/swapon.c b/toys/other/swapon.c index db7c45b0..49f12499 100644 --- a/toys/other/swapon.c +++ b/toys/other/swapon.c @@ -1,34 +1,32 @@ -/* vi: set sw=4 ts=4: - * - * swapon.c - Enable region for swapping +/* swapon.c - Enable region for swapping * * Copyright 2012 Elie De Brauwer USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) config SWAPON - bool "swapon" - default y - help - usage: swapon [-p priority] filename + bool "swapon" + default y + help + usage: swapon [-p priority] filename - Enable swapping on a given device/file. + Enable swapping on a given device/file. */ #define FOR_swapon #include "toys.h" GLOBALS( - long priority; + long priority; ) void swapon_main(void) { - int flags = 0; + int flags = 0; - if (toys.optflags) - flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT); + if (toys.optflags) + flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT); - if (swapon(*toys.optargs, flags)) - perror_exit("Couldn't swapon '%s'", *toys.optargs); + if (swapon(*toys.optargs, flags)) + perror_exit("Couldn't swapon '%s'", *toys.optargs); } diff --git a/toys/other/switch_root.c b/toys/other/switch_root.c index 6451ec15..1dfa20de 100644 --- a/toys/other/switch_root.c +++ b/toys/other/switch_root.c @@ -5,16 +5,16 @@ USE_SWITCH_ROOT(NEWTOY(switch_root, "<2c:h", TOYFLAG_SBIN)) config SWITCH_ROOT - bool "switch_root" - default y - help - usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT... + bool "switch_root" + default y + help + usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT... - Use from PID 1 under initramfs to free initramfs, chroot to NEW_ROOT, - and exec NEW_INIT. + Use from PID 1 under initramfs to free initramfs, chroot to NEW_ROOT, + and exec NEW_INIT. - -c Redirect console to device in NEW_ROOT - -h Hang instead of exiting on failure (avoids kernel panic) + -c Redirect console to device in NEW_ROOT + -h Hang instead of exiting on failure (avoids kernel panic) */ #define FOR_switch_root @@ -22,72 +22,72 @@ config SWITCH_ROOT #include GLOBALS( - char *console; + char *console; - dev_t rootdev; + dev_t rootdev; ) static int del_node(struct dirtree *node) { - if (node->st.st_dev == TT.rootdev && dirtree_notdotdot(node)) { - int flag = 0; - if (S_ISDIR(node->st.st_mode)) { - if (node->data != -1) return DIRTREE_COMEAGAIN; - flag = AT_REMOVEDIR; - } - unlinkat(dirtree_parentfd(node), node->name, flag); - } - - return 0; + if (node->st.st_dev == TT.rootdev && dirtree_notdotdot(node)) { + int flag = 0; + if (S_ISDIR(node->st.st_mode)) { + if (node->data != -1) return DIRTREE_COMEAGAIN; + flag = AT_REMOVEDIR; + } + unlinkat(dirtree_parentfd(node), node->name, flag); + } + + return 0; } void switch_root_main(void) { - char *newroot = *toys.optargs, **cmdline = toys.optargs+1; - struct stat st1, st2; - struct statfs stfs; - int console = console; // gcc's "may be used" warnings are broken. - - if (getpid() != 1) error_exit("not pid 1"); - - // Root filesystem we're leaving must be ramfs or tmpfs - if (statfs("/", &stfs) || - (stfs.f_type != 0x858458f6 && stfs.f_type != 0x01021994)) - { - error_msg("not ramfs"); - goto panic; - } - - // New directory must be different filesystem instance - if (chdir(newroot) || stat(".", &st1) || stat("/", &st2) || - st1.st_dev == st2.st_dev) - { - error_msg("bad newroot '%s'", newroot); - goto panic; - } - TT.rootdev=st2.st_dev; - - // init program must exist and be an executable file - if (stat("init", &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { - error_msg("bad init"); - goto panic; - } - - if (TT.console && -1 == (console = open(TT.console, O_RDWR))) { - perror_msg("bad console '%s'", TT.console); - goto panic; - } + char *newroot = *toys.optargs, **cmdline = toys.optargs+1; + struct stat st1, st2; + struct statfs stfs; + int console = console; // gcc's "may be used" warnings are broken. + + if (getpid() != 1) error_exit("not pid 1"); + + // Root filesystem we're leaving must be ramfs or tmpfs + if (statfs("/", &stfs) || + (stfs.f_type != 0x858458f6 && stfs.f_type != 0x01021994)) + { + error_msg("not ramfs"); + goto panic; + } + + // New directory must be different filesystem instance + if (chdir(newroot) || stat(".", &st1) || stat("/", &st2) || + st1.st_dev == st2.st_dev) + { + error_msg("bad newroot '%s'", newroot); + goto panic; + } + TT.rootdev=st2.st_dev; + + // init program must exist and be an executable file + if (stat("init", &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { + error_msg("bad init"); + goto panic; + } + + if (TT.console && -1 == (console = open(TT.console, O_RDWR))) { + perror_msg("bad console '%s'", TT.console); + goto panic; + } - // Ok, enough safety checks: wipe root partition. - dirtree_read("/", del_node); - - if (TT.console) { - int i; - for (i=0; i<3; i++) if (console != i) dup2(console, i); - if (console>2) close(console); - } - execv(*cmdline, cmdline); - perror_msg("Failed to exec '%s'", *cmdline); + // Ok, enough safety checks: wipe root partition. + dirtree_read("/", del_node); + + if (TT.console) { + int i; + for (i=0; i<3; i++) if (console != i) dup2(console, i); + if (console>2) close(console); + } + execv(*cmdline, cmdline); + perror_msg("Failed to exec '%s'", *cmdline); panic: - if (toys.optflags & FLAG_h) for (;;) wait(NULL); + if (toys.optflags & FLAG_h) for (;;) wait(NULL); } diff --git a/toys/other/tac.c b/toys/other/tac.c index 7a8bb4ae..78b22866 100644 --- a/toys/other/tac.c +++ b/toys/other/tac.c @@ -1,53 +1,51 @@ -/* vi: set sw=4 ts=4: - * - * tac.c - output lines in reverse order +/* tac.c - output lines in reverse order * * Copyright 2012 Rob Landley USE_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config TAC - bool "tac" - default y - help - usage: tac [FILE...] + bool "tac" + default y + help + usage: tac [FILE...] - Output lines in reverse order. + Output lines in reverse order. */ #include "toys.h" void do_tac(int fd, char *name) { - struct arg_list *list = NULL; - char *c; - - // Read in lines - for (;;) { - struct arg_list *temp; - int len; - - if (!(c = get_line(fd))) break; - - len = strlen(c); - if (len && c[len-1]=='\n') c[len-1] = 0; - temp = xmalloc(sizeof(struct arg_list)); - temp->next = list; - temp->arg = c; - list = temp; - } - - // Play them back. - while (list) { - struct arg_list *temp = list->next; - xputs(list->arg); - free(list->arg); - free(list); - list = temp; - } + struct arg_list *list = NULL; + char *c; + + // Read in lines + for (;;) { + struct arg_list *temp; + int len; + + if (!(c = get_line(fd))) break; + + len = strlen(c); + if (len && c[len-1]=='\n') c[len-1] = 0; + temp = xmalloc(sizeof(struct arg_list)); + temp->next = list; + temp->arg = c; + list = temp; + } + + // Play them back. + while (list) { + struct arg_list *temp = list->next; + xputs(list->arg); + free(list->arg); + free(list); + list = temp; + } } void tac_main(void) { - loopfiles(toys.optargs, do_tac); + loopfiles(toys.optargs, do_tac); } diff --git a/toys/other/taskset.c b/toys/other/taskset.c index 74cbfffa..967bf70f 100644 --- a/toys/other/taskset.c +++ b/toys/other/taskset.c @@ -1,25 +1,23 @@ -/* vi: set sw=4 ts=4: - * - * taskset.c - Retrieve or set the CPU affinity of a process. +/* taskset.c - Retrieve or set the CPU affinity of a process. * * Copyright 2012 Elie De Brauwer USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_BIN|TOYFLAG_STAYROOT)) config TASKSET - bool "taskset" - default y - help - usage: taskset [-ap] [mask] [PID | cmd [args...]] + bool "taskset" + default y + help + usage: taskset [-ap] [mask] [PID | cmd [args...]] - Launch a new task which may only run on certain processors, or change - the processor affinity of an exisitng PID. + Launch a new task which may only run on certain processors, or change + the processor affinity of an exisitng PID. - Mask is a hex string where each bit represents a processor the process - is allowed to run on. PID without a mask displays existing affinity. + Mask is a hex string where each bit represents a processor the process + is allowed to run on. PID without a mask displays existing affinity. - -p Set/get the affinity of given PID instead of a new command. - -a Set/get the affinity of all threads of the PID. + -p Set/get the affinity of given PID instead of a new command. + -a Set/get the affinity of all threads of the PID. */ #define FOR_taskset @@ -34,73 +32,73 @@ int sched_getaffinity(pid_t pid, size_t size, void *cpuset); static void do_taskset(pid_t pid, int quiet) { - unsigned long *mask = (unsigned long *)toybuf; - char *s = *toys.optargs, *failed = "failed to %s %d's affinity"; - int i, j, k; - - for (i=0; ; i++) { - if (!quiet) { - int j = sizeof(toybuf), flag = 0; - - if (sched_getaffinity(pid, sizeof(toybuf), (void *)mask)) - perror_exit(failed, "get", pid); - - printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current"); - - while (j--) { - int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1)))); - - if (flag) printf("%02x", x); - else if (x) { - flag++; - printf("%x", x); - } - } - putchar('\n'); - } - - if (i || toys.optc < 2) return; - - memset(toybuf, 0, sizeof(toybuf)); - k = strlen(s = *toys.optargs); - s += k; - for (j = 0; j 9) digit = 10 + tolower(*s)-'a'; - if (digit > 15) error_exit("bad mask '%s'", *toys.optargs); - mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1)); - } - - if (sched_setaffinity(pid, sizeof(toybuf), (void *)mask)) - perror_exit(failed, "set", pid); - } + unsigned long *mask = (unsigned long *)toybuf; + char *s = *toys.optargs, *failed = "failed to %s %d's affinity"; + int i, j, k; + + for (i=0; ; i++) { + if (!quiet) { + int j = sizeof(toybuf), flag = 0; + + if (sched_getaffinity(pid, sizeof(toybuf), (void *)mask)) + perror_exit(failed, "get", pid); + + printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current"); + + while (j--) { + int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1)))); + + if (flag) printf("%02x", x); + else if (x) { + flag++; + printf("%x", x); + } + } + putchar('\n'); + } + + if (i || toys.optc < 2) return; + + memset(toybuf, 0, sizeof(toybuf)); + k = strlen(s = *toys.optargs); + s += k; + for (j = 0; j 9) digit = 10 + tolower(*s)-'a'; + if (digit > 15) error_exit("bad mask '%s'", *toys.optargs); + mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1)); + } + + if (sched_setaffinity(pid, sizeof(toybuf), (void *)mask)) + perror_exit(failed, "set", pid); + } } static int task_callback(struct dirtree *new) { - if (!new->parent) return DIRTREE_RECURSE; - if (isdigit(*new->name)) do_taskset(atoi(new->name), 0); + if (!new->parent) return DIRTREE_RECURSE; + if (isdigit(*new->name)) do_taskset(atoi(new->name), 0); - return 0; + return 0; } void taskset_main(void) { - if (!(toys.optflags & FLAG_p)) { - if (toys.optc < 2) error_exit("Needs 2 args"); - do_taskset(getpid(), 1); - xexec(toys.optargs+1); - } else { - char *c; - pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10); - - if (*c) error_exit("Not int %s", toys.optargs[1]); - - if (toys.optflags & FLAG_a) { - char buf[33]; - sprintf(buf, "/proc/%ld/task/", (long)pid); - dirtree_read(buf, task_callback); - } else do_taskset(pid, 0); - } + if (!(toys.optflags & FLAG_p)) { + if (toys.optc < 2) error_exit("Needs 2 args"); + do_taskset(getpid(), 1); + xexec(toys.optargs+1); + } else { + char *c; + pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10); + + if (*c) error_exit("Not int %s", toys.optargs[1]); + + if (toys.optflags & FLAG_a) { + char buf[33]; + sprintf(buf, "/proc/%ld/task/", (long)pid); + dirtree_read(buf, task_callback); + } else do_taskset(pid, 0); + } } diff --git a/toys/other/truncate.c b/toys/other/truncate.c index 47b07583..5ed9f61b 100644 --- a/toys/other/truncate.c +++ b/toys/other/truncate.c @@ -1,44 +1,43 @@ -/* vi: set sw=4 ts=4: - * - * truncate.c - set file length, extending sparsely if necessary +/* truncate.c - set file length, extending sparsely if necessary * * Copyright 2011 Rob Landley USE_TRUNCATE(NEWTOY(truncate, "<1s#|c", TOYFLAG_BIN)) config TRUNCATE - bool "truncate" - default y - help - usage: truncate [-c] -s file... - Set length of file(s), extending sparsely if necessary. - - -c Don't create file if it doesn't exist. - -s New size + bool "truncate" + default y + help + usage: truncate [-c] -s file... + + Set length of file(s), extending sparsely if necessary. + + -c Don't create file if it doesn't exist. + -s New size */ #define FOR_truncate #include "toys.h" GLOBALS( - long size; + long size; ) static void do_truncate(int fd, char *name) { - if (fd<0) return; - if (ftruncate(fd, TT.size)) { - perror_msg("failed to set '%s' to '%ld'", name, TT.size); - toys.exitval = EXIT_FAILURE; - } + if (fd<0) return; + if (ftruncate(fd, TT.size)) { + perror_msg("failed to set '%s' to '%ld'", name, TT.size); + toys.exitval = EXIT_FAILURE; + } } void truncate_main(void) { - int cr = !(toys.optflags&1); + int cr = !(toys.optflags&1); - // Create files with mask rwrwrw. - // Nonexistent files are only an error if we're supposed to create them. - loopfiles_rw(toys.optargs, O_WRONLY|(cr ? O_CREAT : 0), 0666, cr, - do_truncate); + // Create files with mask rwrwrw. + // Nonexistent files are only an error if we're supposed to create them. + loopfiles_rw(toys.optargs, O_WRONLY|(cr ? O_CREAT : 0), 0666, cr, + do_truncate); } diff --git a/toys/other/unshare.c b/toys/other/unshare.c index bdee66bc..9a938186 100644 --- a/toys/other/unshare.c +++ b/toys/other/unshare.c @@ -1,26 +1,24 @@ -/* vi: set sw=4 ts=4: - * - * unshare.c - run command in new context +/* unshare.c - run command in new context * * Copyright 2011 Rob Landley USE_UNSHARE(NEWTOY(unshare, "<1^nium", TOYFLAG_USR|TOYFLAG_BIN)) config UNSHARE - bool "unshare" - default y - depends on TOYBOX_CONTAINER - help - usage: unshare [-muin] COMMAND... - - Create new namespace(s) for this process and its children, so some - attribute is not shared with the parent process. This is part of - Linux Containers. Each process can have its own: - - -m Mount/unmount tree - -u Host and domain names - -i SysV IPC (message queues, semaphores, shared memory) - -n Network address, sockets, routing, iptables + bool "unshare" + default y + depends on TOYBOX_CONTAINER + help + usage: unshare [-muin] COMMAND... + + Create new namespace(s) for this process and its children, so some + attribute is not shared with the parent process. This is part of + Linux Containers. Each process can have its own: + + -m Mount/unmount tree + -u Host and domain names + -i SysV IPC (message queues, semaphores, shared memory) + -n Network address, sockets, routing, iptables */ #include "toys.h" @@ -29,15 +27,13 @@ extern int unshare (int __flags); void unshare_main(void) { - unsigned flags[]={CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWNET,0}; - unsigned f=0; - int i; + unsigned flags[]={CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWNET, 0}; + unsigned f=0; + int i; - for (i=0; flags[i]; i++) - if (toys.optflags & (1< USE_UPTIME(NEWTOY(uptime, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config UPTIME - bool "uptime" - default y - help - usage: uptime + bool "uptime" + default y + help + usage: uptime - Tell how long the system has been running and the system load - averages for the past 1, 5 and 15 minutes. + Tell how long the system has been running and the system load + averages for the past 1, 5 and 15 minutes. */ #include "toys.h" void uptime_main(void) { - struct sysinfo info; - time_t tmptime; - struct tm * now; - unsigned int days, hours, minutes; - - // Obtain the data we need. - sysinfo(&info); - time(&tmptime); - now = localtime(&tmptime); - - // Time - xprintf(" %02d:%02d:%02d up ", now->tm_hour, now->tm_min, now->tm_sec); - // Uptime - info.uptime /= 60; - minutes = info.uptime%60; - info.uptime /= 60; - hours = info.uptime%24; - days = info.uptime/24; - if (days) xprintf("%d day%s, ", days, (days!=1)?"s":""); - if (hours) - xprintf("%2d:%02d, ", hours, minutes); - else - printf("%d min, ", minutes); - - printf(" load average: %.02f %.02f %.02f\n", info.loads[0]/65536.0, - info.loads[1]/65536.0, info.loads[2]/65536.0); - + struct sysinfo info; + time_t tmptime; + struct tm * now; + unsigned int days, hours, minutes; + + // Obtain the data we need. + sysinfo(&info); + time(&tmptime); + now = localtime(&tmptime); + + // Time + xprintf(" %02d:%02d:%02d up ", now->tm_hour, now->tm_min, now->tm_sec); + // Uptime + info.uptime /= 60; + minutes = info.uptime%60; + info.uptime /= 60; + hours = info.uptime%24; + days = info.uptime/24; + if (days) xprintf("%d day%s, ", days, (days!=1)?"s":""); + if (hours) xprintf("%2d:%02d, ", hours, minutes); + else printf("%d min, ", minutes); + + printf(" load average: %.02f %.02f %.02f\n", info.loads[0]/65536.0, + info.loads[1]/65536.0, info.loads[2]/65536.0); } diff --git a/toys/other/usleep.c b/toys/other/usleep.c index ff7fe88b..6040cc06 100644 --- a/toys/other/usleep.c +++ b/toys/other/usleep.c @@ -1,30 +1,26 @@ -/* vi: set sw=4 ts=4: - * - * usleep.c - Wait for a number of microseconds. +/* usleep.c - Wait for a number of microseconds. * * Copyright 2012 Elie De Brauwer USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN)) config USLEEP - bool "usleep" - default y - help - usage: usleep MICROSECONDS - - Pause for MICROSECONDS microseconds. + bool "usleep" + default y + help + usage: usleep MICROSECONDS + Pause for MICROSECONDS microseconds. */ #include "toys.h" void usleep_main(void) { - struct timespec tv; - long delay = atol(*toys.optargs); - - tv.tv_sec = delay/1000000; - tv.tv_nsec = (delay%1000000) * 1000; - toys.exitval = !!nanosleep(&tv, NULL); + struct timespec tv; + long delay = atol(*toys.optargs); + tv.tv_sec = delay/1000000; + tv.tv_nsec = (delay%1000000) * 1000; + toys.exitval = !!nanosleep(&tv, NULL); } diff --git a/toys/other/vconfig.c b/toys/other/vconfig.c index 92d9d7f0..18225fc4 100644 --- a/toys/other/vconfig.c +++ b/toys/other/vconfig.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * vconfig.c - Creates virtual ethernet devices. +/* vconfig.c - Creates virtual ethernet devices. * * Copyright 2012 Sandeep Sharma , Kyungwan Han * @@ -9,20 +7,19 @@ USE_VCONFIG(NEWTOY(vconfig, "<2>4", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) config VCONFIG - bool "vconfig" - default y - help - usage: vconfig COMMAND [OPTIONS] + bool "vconfig" + default y + help + usage: vconfig COMMAND [OPTIONS] - add [interface-name] [vlan_id] - rem [vlan-name] - set_flag [interface-name] [flag-num] [0 | 1] - set_egress_map [vlan-name] [skb_priority] [vlan_qos] - set_ingress_map [vlan-name] [skb_priority] [vlan_qos] - set_name_type [name-type] - - Create and remove virtual ethernet devices + add [interface-name] [vlan_id] + rem [vlan-name] + set_flag [interface-name] [flag-num] [0 | 1] + set_egress_map [vlan-name] [skb_priority] [vlan_qos] + set_ingress_map [vlan-name] [skb_priority] [vlan_qos] + set_name_type [name-type] + Create and remove virtual ethernet devices */ #include "toys.h" @@ -34,16 +31,15 @@ config VCONFIG */ static int strtol_range(char *str, int min, int max) { - char *endptr = NULL; - errno = 0; - long ret_value = strtol(str, &endptr, 10); - if(errno) perror_exit("Invalid num %s", str); - else { - if(endptr && (*endptr != '\0' || endptr == str)) - perror_exit("Not a valid num %s", str); - } - if(ret_value >= min && ret_value <= max) return ret_value; - else perror_exit("Number %s is not in valid [%d-%d] Range\n", str, min, max); + char *endptr = NULL; + errno = 0; + long ret_value = strtol(str, &endptr, 10); + + if(errno) perror_exit("Invalid num %s", str); + else if(endptr && (*endptr != '\0' || endptr == str)) + perror_exit("Not a valid num %s", str); + if(ret_value >= min && ret_value <= max) return ret_value; + else perror_exit("Number %s is not in valid [%d-%d] Range\n", str, min, max); } /* * vconfig main function. @@ -51,83 +47,84 @@ static int strtol_range(char *str, int min, int max) void vconfig_main(void) { #define MAX_VLAN_ID 4094 - struct vlan_ioctl_args request; - char *interface_name = NULL; - unsigned int name_type = VLAN_NAME_TYPE_PLUS_VID; - char *cmd; - int fd = 0; - int vlan_id = 0; - - if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror_exit("Can't open socket"); //Use socket instead of open - memset(&request, 0, sizeof(struct vlan_ioctl_args)); // Null set all the VLAN info's. - cmd = toys.optargs[0]; // Fetch cmd and proceed. - if(strcmp(cmd, "set_name_type") == 0) { - if(strcmp(toys.optargs[1], "VLAN_PLUS_VID") == 0) { - name_type = VLAN_NAME_TYPE_PLUS_VID; - } - else if(strcmp(toys.optargs[1], "VLAN_PLUS_VID_NO_PAD") == 0) { - name_type = VLAN_NAME_TYPE_PLUS_VID_NO_PAD; - } - else if(strcmp(toys.optargs[1], "DEV_PLUS_VID") == 0) { - name_type = VLAN_NAME_TYPE_RAW_PLUS_VID; - } - else if(strcmp(toys.optargs[1], "DEV_PLUS_VID_NO_PAD") == 0) { - name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; - } - else perror_exit("ERROR: Invalid name type"); - - request.u.name_type = name_type; - request.cmd = SET_VLAN_NAME_TYPE_CMD; - if(ioctl(fd, SIOCSIFVLAN, &request) == 0) { - xprintf("Successful set_name_type for VLAN subsystem\n"); - exit(EXIT_SUCCESS); - } - else perror_exit("Failed to set set_name_type:"); - } - else { - interface_name = toys.optargs[1]; // Store interface name. - if(strlen(interface_name) > 15) perror_exit("ERROR:if_name length can not be greater than 15"); - strcpy(request.device1, interface_name); //we had exited if interface_name length greater than 15, so here it never overflows. - } + struct vlan_ioctl_args request; + char *interface_name = NULL; + unsigned int name_type = VLAN_NAME_TYPE_PLUS_VID; + char *cmd; + int fd = 0; + int vlan_id = 0; - if(strcmp(cmd, "add") == 0) { - request.cmd = ADD_VLAN_CMD; - if(toys.optargs[2]) vlan_id = strtol_range(toys.optargs[2], 0, MAX_VLAN_ID); - else vlan_id = 0; - request.u.VID = vlan_id; - } - else if(strcmp(cmd, "rem") == 0) { - request.cmd = DEL_VLAN_CMD; - } - else if(strcmp(cmd, "set_flag") == 0) { - request.cmd = SET_VLAN_FLAG_CMD; - if(toys.optargs[2]) request.u.flag = strtol_range(toys.optargs[2], 0, 1); - else request.u.flag = 0; - if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); - else request.vlan_qos = 0; + if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror_exit("Can't open socket"); //Use socket instead of open + memset(&request, 0, sizeof(struct vlan_ioctl_args)); // Null set all the VLAN info's. + cmd = toys.optargs[0]; // Fetch cmd and proceed. + if(strcmp(cmd, "set_name_type") == 0) { + if(strcmp(toys.optargs[1], "VLAN_PLUS_VID") == 0) { + name_type = VLAN_NAME_TYPE_PLUS_VID; } - else if(strcmp(cmd, "set_egress_map") == 0) { - request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD; - if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); - else request.u.skb_priority = 0; - if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); - else request.vlan_qos = 0; + else if(strcmp(toys.optargs[1], "VLAN_PLUS_VID_NO_PAD") == 0) { + name_type = VLAN_NAME_TYPE_PLUS_VID_NO_PAD; } - else if(strcmp(cmd, "set_ingress_map") == 0) { - request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD; - if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); - else request.u.skb_priority = 0; - if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); //To set flag we must have to set vlan_qos - else request.vlan_qos = 0; + else if(strcmp(toys.optargs[1], "DEV_PLUS_VID") == 0) { + name_type = VLAN_NAME_TYPE_RAW_PLUS_VID; } - else { - xclose(fd); - perror_exit("Unknown command %s", cmd); + else if(strcmp(toys.optargs[1], "DEV_PLUS_VID_NO_PAD") == 0) { + name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; } + else perror_exit("ERROR: Invalid name type"); + + request.u.name_type = name_type; + request.cmd = SET_VLAN_NAME_TYPE_CMD; if(ioctl(fd, SIOCSIFVLAN, &request) == 0) { - if(strcmp(cmd, "add") == 0 && vlan_id == 1) - xprintf("WARNING: VLAN 1 does not work with many switches,consider another number if you have problems.\n"); - xprintf("Successful %s on device %s\n", cmd, interface_name); + xprintf("Successful set_name_type for VLAN subsystem\n"); + exit(EXIT_SUCCESS); } - else perror_exit("Failed to %s, on vlan subsystem %s.", cmd, interface_name); -} + else perror_exit("Failed to set set_name_type:"); + } + else { + interface_name = toys.optargs[1]; // Store interface name. + if(strlen(interface_name) > 15) perror_exit("ERROR:if_name length can not be greater than 15"); + strcpy(request.device1, interface_name); //we had exited if interface_name length greater than 15, so here it never overflows. + } + + if(strcmp(cmd, "add") == 0) { + request.cmd = ADD_VLAN_CMD; + if(toys.optargs[2]) vlan_id = strtol_range(toys.optargs[2], 0, MAX_VLAN_ID); + else vlan_id = 0; + request.u.VID = vlan_id; + } + else if(strcmp(cmd, "rem") == 0) { + request.cmd = DEL_VLAN_CMD; + } + else if(strcmp(cmd, "set_flag") == 0) { + request.cmd = SET_VLAN_FLAG_CMD; + if(toys.optargs[2]) request.u.flag = strtol_range(toys.optargs[2], 0, 1); + else request.u.flag = 0; + if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); + else request.vlan_qos = 0; + } + else if(strcmp(cmd, "set_egress_map") == 0) { + request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD; + if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); + else request.u.skb_priority = 0; + if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); + else request.vlan_qos = 0; + } + else if(strcmp(cmd, "set_ingress_map") == 0) { + request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD; + if(toys.optargs[2]) request.u.skb_priority = strtol_range(toys.optargs[2], 0, INT_MAX); + else request.u.skb_priority = 0; + //To set flag we must have to set vlan_qos + if(toys.optargs[3]) request.vlan_qos = strtol_range(toys.optargs[3], 0, 7); + else request.vlan_qos = 0; + } + else { + xclose(fd); + perror_exit("Unknown command %s", cmd); + } + if(ioctl(fd, SIOCSIFVLAN, &request) == 0) { + if(strcmp(cmd, "add") == 0 && vlan_id == 1) + xprintf("WARNING: VLAN 1 does not work with many switches,consider another number if you have problems.\n"); + xprintf("Successful %s on device %s\n", cmd, interface_name); + } + else perror_exit("Failed to %s, on vlan subsystem %s.", cmd, interface_name); +} diff --git a/toys/other/vmstat.c b/toys/other/vmstat.c index 1c348f2a..16d45f2a 100644 --- a/toys/other/vmstat.c +++ b/toys/other/vmstat.c @@ -1,189 +1,184 @@ -/* vi: set sw=4 ts=4: - * - * vmstat.c - Report virtual memory statistics. +/* vmstat.c - Report virtual memory statistics. * * Copyright 2012 Elie De Brauwer USE_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN)) config VMSTAT - bool "vmstat" - default y - help - usage: vmstat [-n] [delay [count]] - -n Display the header only once - delay The delay between updates in seconds, when not specified - the average since boot is displayed. - count Number of updates to display, the default is inifinite. + bool "vmstat" + default y + help + usage: vmstat [-n] [delay [count]] + -n Display the header only once + delay The delay between updates in seconds, when not specified + the average since boot is displayed. + count Number of updates to display, the default is inifinite. */ #include "toys.h" -void read_proc_stat(unsigned int * proc_running, unsigned int * proc_blocked, - uint64_t * sys_irq, uint64_t * sys_ctxt, - uint64_t * cpu_user, uint64_t * cpu_sys, uint64_t * cpu_idle, uint64_t * cpu_wait) +void read_proc_stat(unsigned int *proc_running, unsigned int *proc_blocked, + uint64_t *sys_irq, uint64_t *sys_ctxt, uint64_t *cpu_user, uint64_t *cpu_sys, + uint64_t *cpu_idle, uint64_t *cpu_wait) { - char * off; - uint64_t c_user, c_nice, c_sys, c_irq, c_sirq; - int fd = xopen("/proc/stat", O_RDONLY); - size_t s = xread(fd, toybuf, sizeof(toybuf)-1); - toybuf[s] = 0; - if ( s == sizeof(toybuf)-1) - error_exit("/proc/stat is too large"); - - off = strstr(toybuf, "cpu "); - // Ignoring steal and guest fields for now. - if (off) sscanf(off, "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 \ - " %"PRIu64" %"PRIu64" %"PRIu64, &c_user, &c_nice, &c_sys, cpu_idle, - cpu_wait, &c_irq, &c_sirq); - *cpu_user = c_user + c_nice; - *cpu_sys = c_sys + c_irq + c_sirq; - off = strstr(toybuf, "intr"); - if (off) sscanf(off, "intr %"PRIu64, sys_irq); - - off = strstr(toybuf, "ctxt"); - if (off) sscanf(off, "ctxt %"PRIu64, sys_ctxt); - - off = strstr(toybuf, "procs_running"); - if (off) sscanf(off, "procs_running %u", proc_running); - (*proc_running)--; // look, i'm invisible. - - off = strstr(toybuf, "procs_blocked"); - if (off) sscanf(off, "procs_blocked %u", proc_blocked); - - close(fd); + char * off; + uint64_t c_user, c_nice, c_sys, c_irq, c_sirq; + int fd = xopen("/proc/stat", O_RDONLY); + size_t s = xread(fd, toybuf, sizeof(toybuf)-1); + + toybuf[s] = 0; + if (s == sizeof(toybuf)-1) error_exit("/proc/stat is too large"); + + off = strstr(toybuf, "cpu "); + // Ignoring steal and guest fields for now. + if (off) sscanf(off, "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 \ + " %"PRIu64" %"PRIu64" %"PRIu64, &c_user, &c_nice, &c_sys, cpu_idle, + cpu_wait, &c_irq, &c_sirq); + *cpu_user = c_user + c_nice; + *cpu_sys = c_sys + c_irq + c_sirq; + off = strstr(toybuf, "intr"); + if (off) sscanf(off, "intr %"PRIu64, sys_irq); + + off = strstr(toybuf, "ctxt"); + if (off) sscanf(off, "ctxt %"PRIu64, sys_ctxt); + + off = strstr(toybuf, "procs_running"); + if (off) sscanf(off, "procs_running %u", proc_running); + (*proc_running)--; // look, i'm invisible. + + off = strstr(toybuf, "procs_blocked"); + if (off) sscanf(off, "procs_blocked %u", proc_blocked); + + close(fd); } -void read_proc_meminfo(unsigned long * mem_swapped, unsigned long * mem_free, - unsigned long * mem_buff, unsigned long * mem_cache) +void read_proc_meminfo(unsigned long *mem_swapped, unsigned long *mem_free, + unsigned long *mem_buff, unsigned long *mem_cache) { - char * off; - unsigned long swap_total, swap_free; - int fd = xopen("/proc/meminfo", O_RDONLY); - size_t s = xread(fd, toybuf, sizeof(toybuf)-1); - toybuf[s] = 0; - if ( s == sizeof(toybuf)-1) - error_exit("/proc/meminfo is too large"); + char * off; + unsigned long swap_total, swap_free; + int fd = xopen("/proc/meminfo", O_RDONLY); + size_t s = xread(fd, toybuf, sizeof(toybuf)-1); + + toybuf[s] = 0; + if (s == sizeof(toybuf)-1) error_exit("/proc/meminfo is too large"); - off = strstr(toybuf, "MemFree"); - if (off) sscanf(off, "MemFree: %lu kB", mem_free); + off = strstr(toybuf, "MemFree"); + if (off) sscanf(off, "MemFree: %lu kB", mem_free); - off = strstr(toybuf, "Buffers"); - if (off) sscanf(off, "Buffers: %lu kB", mem_buff); + off = strstr(toybuf, "Buffers"); + if (off) sscanf(off, "Buffers: %lu kB", mem_buff); - off = strstr(toybuf, "Cached"); - if (off) sscanf(off, "Cached: %lu kB", mem_cache); + off = strstr(toybuf, "Cached"); + if (off) sscanf(off, "Cached: %lu kB", mem_cache); - off = strstr(toybuf, "SwapFree"); - if (off) sscanf(off, "SwapFree: %lu kB", &swap_free); + off = strstr(toybuf, "SwapFree"); + if (off) sscanf(off, "SwapFree: %lu kB", &swap_free); - off = strstr(toybuf, "SwapTotal"); - if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total); - *mem_swapped = swap_total - swap_free; + off = strstr(toybuf, "SwapTotal"); + if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total); + *mem_swapped = swap_total - swap_free; - close(fd); + close(fd); } -void read_proc_vmstat(unsigned long * io_pages_in, unsigned long * io_pages_out, - unsigned long * swap_bytes_in, unsigned long * swap_bytes_out) +void read_proc_vmstat(unsigned long *io_pages_in, unsigned long *io_pages_out, + unsigned long *swap_bytes_in, unsigned long *swap_bytes_out) { - char * off; - unsigned long s_pages_in, s_pages_out; - unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L; - int fd = xopen("/proc/vmstat", O_RDONLY); - size_t s = xread(fd, toybuf, sizeof(toybuf)-1); - toybuf[s] = 0; - if ( s == sizeof(toybuf)-1) - error_exit("/proc/vmstat is too large"); - - off = strstr(toybuf, "pgpgin"); - if (off) sscanf(off, "pgpgin %lu", io_pages_in); - - off = strstr(toybuf, "pgpgout"); - if (off) sscanf(off, "pgpgout %lu", io_pages_out); - - off = strstr(toybuf, "pswpin"); - if (off) sscanf(off, "pswpin %lu", &s_pages_in); - *swap_bytes_in = s_pages_in * pagesize_kb; - - off = strstr(toybuf, "pswpout"); - if (off) sscanf(off, "pswpout %lu", &s_pages_out); - *swap_bytes_out = s_pages_out * pagesize_kb; - - close(fd); + char *off; + unsigned long s_pages_in, s_pages_out; + unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L; + int fd = xopen("/proc/vmstat", O_RDONLY); + size_t s = xread(fd, toybuf, sizeof(toybuf)-1); + + toybuf[s] = 0; + if (s == sizeof(toybuf)-1) error_exit("/proc/vmstat is too large"); + + off = strstr(toybuf, "pgpgin"); + if (off) sscanf(off, "pgpgin %lu", io_pages_in); + + off = strstr(toybuf, "pgpgout"); + if (off) sscanf(off, "pgpgout %lu", io_pages_out); + + off = strstr(toybuf, "pswpin"); + if (off) sscanf(off, "pswpin %lu", &s_pages_in); + *swap_bytes_in = s_pages_in * pagesize_kb; + + off = strstr(toybuf, "pswpout"); + if (off) sscanf(off, "pswpout %lu", &s_pages_out); + *swap_bytes_out = s_pages_out * pagesize_kb; + + close(fd); } void vmstat_main(void) { - const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n"; - unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0; - unsigned int running = 0, blocked = 0; - unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0; - unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2]; - uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2]; - int first_run = 1; - int no_header = toys.optflags; - unsigned num_rows = 22; - - if (toys.optc >= 1) - loop_delay = atoi(toys.optargs[0]); - if (toys.optc >= 2) - loop_max_num = atoi(toys.optargs[1]); - - if (loop_max_num < 0 || loop_delay < 0) - error_exit("Invalid arguments"); - - while(1) { - uint64_t total_jif; - int idx = loop_num%2; - - if(first_run || (!(loop_num % num_rows) && !no_header)) { - unsigned rows = 0, cols = 0; - terminal_size(&cols, &rows); - num_rows = (rows > 3)? rows - 3 : 22; - printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n"); - printf(" r b swpd free buff cache si so bi bo in cs us sy id wa\n"); - } - - read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx], - &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]); - read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache); - read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]); - - if (first_run) { - struct sysinfo inf; - sysinfo(&inf); - first_run = 0; - total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx]; - printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, - (unsigned) (swap_bytes_in[idx]/inf.uptime), - (unsigned) (swap_bytes_out[idx]/inf.uptime), - (unsigned) (io_pages_in[idx]/inf.uptime), - (unsigned) (io_pages_out[idx]/inf.uptime), - (unsigned) (sys_irq[idx]/inf.uptime), - (unsigned) (sys_ctxt[idx]/inf.uptime), - (unsigned) (100*cpu_user[idx]/total_jif), - (unsigned) (100*cpu_sys[idx]/total_jif), - (unsigned) (100*cpu_idle[idx]/total_jif), - (unsigned) (100*cpu_wait[idx]/total_jif)); - }else{ - total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx]; - printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, - (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay), - (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay), - (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay), - (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay), - (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay), - (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay), - (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif), - (unsigned) (100*(cpu_sys[idx] - cpu_sys[!idx]) /total_jif), - (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif), - (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif)); - } - - loop_num++; - if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num)) - break; - sleep(loop_delay); - } + const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n"; + unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0; + unsigned int running = 0, blocked = 0; + unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0; + unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2]; + uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2]; + int first_run = 1; + int no_header = toys.optflags; + unsigned num_rows = 22; + + if (toys.optc >= 1) loop_delay = atoi(toys.optargs[0]); + if (toys.optc >= 2) loop_max_num = atoi(toys.optargs[1]); + + if (loop_max_num < 0 || loop_delay < 0) error_exit("Invalid arguments"); + + while(1) { + uint64_t total_jif; + int idx = loop_num%2; + + if(first_run || (!(loop_num % num_rows) && !no_header)) { + unsigned rows = 0, cols = 0; + terminal_size(&cols, &rows); + num_rows = (rows > 3)? rows - 3 : 22; + printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n"); + printf(" r b swpd free buff cache si so bi bo in cs us sy id wa\n"); + } + + read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx], + &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]); + read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache); + read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]); + + if (first_run) { + struct sysinfo inf; + sysinfo(&inf); + first_run = 0; + total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx]; + printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, + (unsigned) (swap_bytes_in[idx]/inf.uptime), + (unsigned) (swap_bytes_out[idx]/inf.uptime), + (unsigned) (io_pages_in[idx]/inf.uptime), + (unsigned) (io_pages_out[idx]/inf.uptime), + (unsigned) (sys_irq[idx]/inf.uptime), + (unsigned) (sys_ctxt[idx]/inf.uptime), + (unsigned) (100*cpu_user[idx]/total_jif), + (unsigned) (100*cpu_sys[idx]/total_jif), + (unsigned) (100*cpu_idle[idx]/total_jif), + (unsigned) (100*cpu_wait[idx]/total_jif)); + }else{ + total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx]; + printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, + (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay), + (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay), + (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay), + (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay), + (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay), + (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay), + (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif), + (unsigned) (100*(cpu_sys[idx] - cpu_sys[!idx]) /total_jif), + (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif), + (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif)); + } + + loop_num++; + if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num)) + break; + sleep(loop_delay); + } } diff --git a/toys/other/w.c b/toys/other/w.c index 097a4386..c271e8bd 100644 --- a/toys/other/w.c +++ b/toys/other/w.c @@ -1,34 +1,33 @@ -/* vi: set sw=4 ts=4: - * - * w.c - shows logged in users +/* w.c - shows logged in users * * Copyright 2012 Gaurang Shastri USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config W - bool "w" - default y - help - usage: w + bool "w" + default y + help + usage: w - Show who is logged on and since how long they logged in. + Show who is logged on and since how long they logged in. */ #include "toys.h" void w_main(void) { - struct utmpx *x; + struct utmpx *x; - xprintf("USER TTY LOGIN@ FROM"); - setutxent(); - while ((x=getutxent()) != NULL) - if (x->ut_type==7) { - time_t tt = x->ut_tv.tv_sec; + xprintf("USER TTY LOGIN@ FROM"); + setutxent(); + while ((x=getutxent()) != NULL) { + if (x->ut_type==7) { + time_t tt = x->ut_tv.tv_sec; - xprintf("\n%-9.8s%-9.8s %-4.24s (%-1.12s)", x->ut_user, x->ut_line, - ctime(&tt), x->ut_host); - } - xputc('\n'); + xprintf("\n%-9.8s%-9.8s %-4.24s (%-1.12s)", x->ut_user, x->ut_line, + ctime(&tt), x->ut_host); + } + } + xputc('\n'); } diff --git a/toys/other/which.c b/toys/other/which.c index 44b1f568..fc65fe8a 100644 --- a/toys/other/which.c +++ b/toys/other/which.c @@ -1,20 +1,18 @@ -/* vi: set sw=4 ts=4: - * - * which.c - Find executable files in $PATH. +/* which.c - Find executable files in $PATH. * * Copyright 2006 Rob landley USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN)) config WHICH - bool "which" - default y - help - usage: which [-a] filename ... + bool "which" + default y + help + usage: which [-a] filename ... - Search $PATH for executable files matching filename(s). + Search $PATH for executable files matching filename(s). - -a Show all matches + -a Show all matches */ #include "toys.h" @@ -24,46 +22,47 @@ config WHICH static int which_in_path(char *filename) { - struct string_list *list; + struct string_list *list; - // If they gave us a path, don't worry about $PATH or -a + // If they gave us a path, don't worry about $PATH or -a - if (strchr(filename, '/')) { - // Confirm it has the executable bit set, and it's not a directory. - if (!access(filename, X_OK)) { - struct stat st; + if (strchr(filename, '/')) { + // Confirm it has the executable bit set, and it's not a directory. + if (!access(filename, X_OK)) { + struct stat st; - if (!stat(filename, &st) && S_ISREG(st.st_mode)) { - puts(filename); - return 0; - } - return 1; - } - } + if (!stat(filename, &st) && S_ISREG(st.st_mode)) { + puts(filename); + return 0; + } + return 1; + } + } - // Search $PATH for matches. - list = find_in_path(getenv("PATH"), filename); - if (!list) return 1; + // Search $PATH for matches. + list = find_in_path(getenv("PATH"), filename); + if (!list) return 1; - // Print out matches - while (list) { - if (!access(list->str, X_OK)) { - puts(list->str); - // If we should stop at one match, do so - if (!toys.optflags) { - llist_traverse(list, free); - break; - } - } - free(llist_pop(&list)); - } + // Print out matches + while (list) { + if (!access(list->str, X_OK)) { + puts(list->str); + // If we should stop at one match, do so + if (!toys.optflags) { + llist_traverse(list, free); + break; + } + } + free(llist_pop(&list)); + } - return 0; + return 0; } void which_main(void) { - int i; - for (i=0; toys.optargs[i]; i++) - toys.exitval |= which_in_path(toys.optargs[i]); + int i; + + for (i=0; toys.optargs[i]; i++) + toys.exitval |= which_in_path(toys.optargs[i]); } diff --git a/toys/other/whoami.c b/toys/other/whoami.c index e6131498..a7ed047a 100644 --- a/toys/other/whoami.c +++ b/toys/other/whoami.c @@ -1,31 +1,29 @@ -/* vi: set sw=4 ts=4: - * - * whoami.c - Print effective user name +/* whoami.c - Print effective user name * * Copyright 2012 Georgi Chorbadzhiyski USE_WHOAMI(NEWTOY(whoami, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config WHOAMI - bool "whoami" - default y - help - usage: whoami + bool "whoami" + default y + help + usage: whoami - Print effective user name. + Print effective user name. */ #include "toys.h" void whoami_main(void) { - struct passwd *pw = getpwuid(geteuid()); + struct passwd *pw = getpwuid(geteuid()); - if (!pw) { - perror("getpwuid"); - toys.exitval = 1; - return; - } + if (!pw) { + perror("getpwuid"); + toys.exitval = 1; + return; + } - xputs(pw->pw_name); + xputs(pw->pw_name); } diff --git a/toys/other/yes.c b/toys/other/yes.c index 90bf522d..773a5a88 100644 --- a/toys/other/yes.c +++ b/toys/other/yes.c @@ -1,31 +1,29 @@ -/* vi: set sw=4 ts=4: - * - * yes.c - Repeatedly output a string. +/* yes.c - Repeatedly output a string. * * Copyright 2007 Rob Landley USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN)) config YES - bool "yes" - default y - help - usage: yes [args...] + bool "yes" + default y + help + usage: yes [args...] - Repeatedly output line until killed. If no args, output 'y'. + Repeatedly output line until killed. If no args, output 'y'. */ #include "toys.h" void yes_main(void) { - for (;;) { - int i; - for (i=0; toys.optargs[i]; i++) { - if (i) xputc(' '); - xprintf("%s", toys.optargs[i]); - } - if (!i) xputc('y'); - xputc('\n'); - } + for (;;) { + int i; + for (i=0; toys.optargs[i]; i++) { + if (i) xputc(' '); + xprintf("%s", toys.optargs[i]); + } + if (!i) xputc('y'); + xputc('\n'); + } } diff --git a/toys/posix/basename.c b/toys/posix/basename.c index 9f228b41..75f3baa4 100644 --- a/toys/posix/basename.c +++ b/toys/posix/basename.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * basename.c - Return non-directory portion of a pathname +/* basename.c - Return non-directory portion of a pathname * * Copyright 2012 Tryn Mirell * @@ -10,36 +8,36 @@ USE_BASENAME(NEWTOY(basename, "<1>2", TOYFLAG_USR|TOYFLAG_BIN)) config BASENAME - bool "basename" - default y - help - usage: basename string [suffix] + bool "basename" + default y + help + usage: basename string [suffix] - Return non-directory portion of a pathname removing suffix + Return non-directory portion of a pathname removing suffix */ #include "toys.h" void basename_main(void) { - char *arg = toys.optargs[0], *suffix = toys.optargs[1], *base; - - while ((base = strrchr(arg, '/'))) { - if (base == arg) break; - if (!base[1]) *base = 0; - else { - base++; - break; - } + char *arg = toys.optargs[0], *suffix = toys.optargs[1], *base; + + while ((base = strrchr(arg, '/'))) { + if (base == arg) break; + if (!base[1]) *base = 0; + else { + base++; + break; } + } - if (!base) base = arg; - - // chop off the suffix if provided - if (suffix) { - arg = base + strlen(base) - strlen(suffix); - if (arg > base && !strcmp(arg, suffix)) *arg = 0; - } - - puts(base); + if (!base) base = arg; + + // chop off the suffix if provided + if (suffix) { + arg = base + strlen(base) - strlen(suffix); + if (arg > base && !strcmp(arg, suffix)) *arg = 0; + } + + puts(base); } diff --git a/toys/posix/cal.c b/toys/posix/cal.c index 1c018e2f..e4301a64 100644 --- a/toys/posix/cal.c +++ b/toys/posix/cal.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cal.c - show calendar. +/* cal.c - show calendar. * * Copyright 2011 Rob Landley * @@ -9,14 +7,14 @@ USE_CAL(NEWTOY(cal, ">2", TOYFLAG_USR|TOYFLAG_BIN)) config CAL - bool "cal" - default y - help - usage: cal [[month] year] - Print a calendar. - - With one argument, prints all months of the specified year. - With two arguments, prints calendar for month and year. + bool "cal" + default y + help + usage: cal [[month] year] + Print a calendar. + + With one argument, prints all months of the specified year. + With two arguments, prints calendar for month and year. */ #include "toys.h" @@ -26,51 +24,51 @@ config CAL static char *calstrings(char *buf, struct tm *tm) { - char temp[21]; - int wday, mday, start, len, line; - - // header - len = strftime(temp, 21, "%B %Y", tm); - len += (20-len)/2; - buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, ""); - buf++; - buf += sprintf(buf, "Su Mo Tu We Th Fr Sa "); - buf++; - - // What day of the week does this month start on? - if (tm->tm_mday>1) - start = (36+tm->tm_wday-tm->tm_mday)%7; - else start = tm->tm_wday; - - // What day does this month end on? Alas, libc doesn't tell us... - len = 31; - if (tm->tm_mon == 1) { - int year = tm->tm_year; - len = 28; - if (!(year & 3) && !((year&100) && !(year&400))) len++; - } else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30; - - for (mday=line=0;line<6;line++) { - for (wday=0; wday<7; wday++) { - char *pat = " "; - if (!mday ? wday==start : mdaytm_mday>1) + start = (36+tm->tm_wday-tm->tm_mday)%7; + else start = tm->tm_wday; + + // What day does this month end on? Alas, libc doesn't tell us... + len = 31; + if (tm->tm_mon == 1) { + int year = tm->tm_year; + len = 28; + if (!(year & 3) && !((year&100) && !(year&400))) len++; + } else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30; + + for (mday=line=0;line<6;line++) { + for (wday=0; wday<7; wday++) { + char *pat = " "; + if (!mday ? wday==start : mday high) error_exit(err, val, "greater", high); + if (val < low) error_exit(err, val, "less", low); + if (val > high) error_exit(err, val, "greater", high); } // Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line @@ -78,57 +76,57 @@ void xcheckrange(long val, long low, long high) void cal_main(void) { - struct tm *tm; - char *buf = toybuf; - - if (toys.optc) { - // Conveniently starts zeroed - tm = (struct tm *)toybuf; - buf += sizeof(struct tm); - - // Last argument is year, one before that (if any) is month. - xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999); - tm->tm_year -= 1900; - tm->tm_mday = 1; - tm->tm_hour = 12; // noon to avoid timezone weirdness - if (toys.optc) { - xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12); - tm->tm_mon--; - - // Print 12 months of the year - - } else { - char *bufs[12]; - int i, j, k; - - for (i=0; i<12; i++) { - tm->tm_mon=i; - mktime(tm); - buf = calstrings(bufs[i]=buf, tm); - } - - // 4 rows, 6 lines each, 3 columns - for (i=0; i<4; i++) { - for (j=0; j<8; j++) { - for(k=0; k<3; k++) { - char **b = bufs+(k+i*3); - *b += printf("%s ", *b); - } - puts(""); - } - } - return; - } - - // What day of the week does that start on? - mktime(tm); - - } else { - time_t now; - time(&now); - tm = localtime(&now); - } - - calstrings(buf, tm); - while (*buf) buf += printf("%s\n", buf); + struct tm *tm; + char *buf = toybuf; + + if (toys.optc) { + // Conveniently starts zeroed + tm = (struct tm *)toybuf; + buf += sizeof(struct tm); + + // Last argument is year, one before that (if any) is month. + xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999); + tm->tm_year -= 1900; + tm->tm_mday = 1; + tm->tm_hour = 12; // noon to avoid timezone weirdness + if (toys.optc) { + xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12); + tm->tm_mon--; + + // Print 12 months of the year + + } else { + char *bufs[12]; + int i, j, k; + + for (i=0; i<12; i++) { + tm->tm_mon=i; + mktime(tm); + buf = calstrings(bufs[i]=buf, tm); + } + + // 4 rows, 6 lines each, 3 columns + for (i=0; i<4; i++) { + for (j=0; j<8; j++) { + for(k=0; k<3; k++) { + char **b = bufs+(k+i*3); + *b += printf("%s ", *b); + } + puts(""); + } + } + return; + } + + // What day of the week does that start on? + mktime(tm); + + } else { + time_t now; + time(&now); + tm = localtime(&now); + } + + calstrings(buf, tm); + while (*buf) buf += printf("%s\n", buf); } diff --git a/toys/posix/cat.c b/toys/posix/cat.c index 160bd6ff..431c7751 100644 --- a/toys/posix/cat.c +++ b/toys/posix/cat.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cat.c - copy inputs to stdout. +/* cat.c - copy inputs to stdout. * * Copyright 2006 Rob Landley * @@ -9,34 +7,34 @@ USE_CAT(NEWTOY(cat, "u", TOYFLAG_BIN)) config CAT - bool "cat" - default y - help - usage: cat [-u] [file...] - Copy (concatenate) files to stdout. If no files listed, copy from stdin. - Filename "-" is a synonym for stdin. + bool "cat" + default y + help + usage: cat [-u] [file...] + Copy (concatenate) files to stdout. If no files listed, copy from stdin. + Filename "-" is a synonym for stdin. - -u Copy one byte at a time (slow). + -u Copy one byte at a time (slow). */ #include "toys.h" static void do_cat(int fd, char *name) { - int len, size=toys.optflags ? 1 : sizeof(toybuf); + int len, size=toys.optflags ? 1 : sizeof(toybuf); - for (;;) { - len = read(fd, toybuf, size); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - xwrite(1, toybuf, len); - } + for (;;) { + len = read(fd, toybuf, size); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + xwrite(1, toybuf, len); + } } void cat_main(void) { - loopfiles(toys.optargs, do_cat); + loopfiles(toys.optargs, do_cat); } diff --git a/toys/posix/chgrp.c b/toys/posix/chgrp.c index 48ce6751..ed2ff9b2 100644 --- a/toys/posix/chgrp.c +++ b/toys/posix/chgrp.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * chown.c - Change ownership +/* chgrp.c - Change user and group ownership * * Copyright 2012 Georgi Chorbadzhiyski * @@ -13,103 +11,103 @@ USE_CHGRP(NEWTOY(chgrp, "<2hPLHRfv", TOYFLAG_BIN)) USE_CHGRP(OLDTOY(chown, chgrp, "<2hPLHRfv", TOYFLAG_BIN)) config CHGRP - bool "chgrp/chown" - default y - help - usage: chown [-RHLP] [-fvh] [owner][:group] file... - usage: chgrp [-RHLP] [-fvh] group file... - - Change ownership of one or more files. - - -f suppress most error messages. - -h change symlinks instead of what they point to - -R recurse into subdirectories (implies -h). - -H with -R change target of symlink, follow command line symlinks - -L with -R change target of symlink, follow all symlinks - -P with -R change symlink, do not follow symlinks (default) - -v verbose output. + bool "chgrp/chown" + default y + help + usage: chown [-RHLP] [-fvh] [owner][:group] file... + usage: chgrp [-RHLP] [-fvh] group file... + + Change ownership of one or more files. + + -f suppress most error messages. + -h change symlinks instead of what they point to + -R recurse into subdirectories (implies -h). + -H with -R change target of symlink, follow command line symlinks + -L with -R change target of symlink, follow all symlinks + -P with -R change symlink, do not follow symlinks (default) + -v verbose output. */ #define FOR_chgrp #include "toys.h" GLOBALS( - uid_t owner; - gid_t group; - char *owner_name, *group_name; - int symfollow; + uid_t owner; + gid_t group; + char *owner_name, *group_name; + int symfollow; ) static int do_chgrp(struct dirtree *node) { - int fd, ret, flags = toys.optflags; - - // Depth first search - if (!dirtree_notdotdot(node)) return 0; - if ((flags & FLAG_R) && node->data != -1 && S_ISDIR(node->st.st_mode)) - return DIRTREE_COMEAGAIN|((flags&FLAG_L) ? DIRTREE_SYMFOLLOW : 0); - - fd = dirtree_parentfd(node); - ret = fchownat(fd, node->name, TT.owner, TT.group, - (flags&(FLAG_L|FLAG_H)) || !(flags&(FLAG_h|FLAG_R)) - ? 0 : AT_SYMLINK_NOFOLLOW); - - if (ret || (flags & FLAG_v)) { - char *path = dirtree_path(node, 0); - if (flags & FLAG_v) - xprintf("%s %s%s%s %s\n", toys.which->name, - TT.owner_name ? TT.owner_name : "", - toys.which->name[2]=='o' && TT.group_name ? ":" : "", - TT.group_name ? TT.group_name : "", path); - if (ret == -1 && !(toys.optflags & FLAG_f)) - perror_msg("changing owner:group of '%s' to '%s:%s'", path, - TT.owner_name, TT.group_name); - free(path); - } - toys.exitval |= ret; - - return 0; + int fd, ret, flags = toys.optflags; + + // Depth first search + if (!dirtree_notdotdot(node)) return 0; + if ((flags & FLAG_R) && node->data != -1 && S_ISDIR(node->st.st_mode)) + return DIRTREE_COMEAGAIN|((flags&FLAG_L) ? DIRTREE_SYMFOLLOW : 0); + + fd = dirtree_parentfd(node); + ret = fchownat(fd, node->name, TT.owner, TT.group, + (flags&(FLAG_L|FLAG_H)) || !(flags&(FLAG_h|FLAG_R)) + ? 0 : AT_SYMLINK_NOFOLLOW); + + if (ret || (flags & FLAG_v)) { + char *path = dirtree_path(node, 0); + if (flags & FLAG_v) + xprintf("%s %s%s%s %s\n", toys.which->name, + TT.owner_name ? TT.owner_name : "", + toys.which->name[2]=='o' && TT.group_name ? ":" : "", + TT.group_name ? TT.group_name : "", path); + if (ret == -1 && !(toys.optflags & FLAG_f)) + perror_msg("changing owner:group of '%s' to '%s:%s'", path, + TT.owner_name, TT.group_name); + free(path); + } + toys.exitval |= ret; + + return 0; } void chgrp_main(void) { - int ischown = toys.which->name[2] == 'o'; - char **s, *own; - - // Distinguish chown from chgrp - if (ischown) { - char *grp; - struct passwd *p; - - own = xstrdup(*toys.optargs); - if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) { - *(grp++) = 0; - TT.group_name = grp; - } - if (*own) { - TT.owner_name = own; - p = getpwnam(own); - // TODO: trailing garbage? - if (!p && isdigit(*own)) p=getpwuid(atoi(own)); - if (!p) error_exit("no user '%s'", own); - TT.owner = p->pw_uid; - } - } else TT.group_name = *toys.optargs; - - if (TT.group_name) { - struct group *g; - g = getgrnam(TT.group_name); - if (!g) g=getgrgid(atoi(TT.group_name)); - if (!g) error_exit("no group '%s'", TT.group_name); - TT.group = g->gr_gid; - } - - for (s=toys.optargs+1; *s; s++) { - struct dirtree *new = dirtree_add_node(AT_FDCWD, *s, - toys.optflags&(FLAG_H|FLAG_L)); - if (new) handle_callback(new, do_chgrp); - else toys.exitval = 1; - } - - if (CFG_TOYBOX_FREE) free(own); + int ischown = toys.which->name[2] == 'o'; + char **s, *own; + + // Distinguish chown from chgrp + if (ischown) { + char *grp; + struct passwd *p; + + own = xstrdup(*toys.optargs); + if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) { + *(grp++) = 0; + TT.group_name = grp; + } + if (*own) { + TT.owner_name = own; + p = getpwnam(own); + // TODO: trailing garbage? + if (!p && isdigit(*own)) p=getpwuid(atoi(own)); + if (!p) error_exit("no user '%s'", own); + TT.owner = p->pw_uid; + } + } else TT.group_name = *toys.optargs; + + if (TT.group_name) { + struct group *g; + g = getgrnam(TT.group_name); + if (!g) g=getgrgid(atoi(TT.group_name)); + if (!g) error_exit("no group '%s'", TT.group_name); + TT.group = g->gr_gid; + } + + for (s=toys.optargs+1; *s; s++) { + struct dirtree *new = dirtree_add_node(AT_FDCWD, *s, + toys.optflags&(FLAG_H|FLAG_L)); + if (new) handle_callback(new, do_chgrp); + else toys.exitval = 1; + } + + if (CFG_TOYBOX_FREE) free(own); } diff --git a/toys/posix/chmod.c b/toys/posix/chmod.c index dcef9751..89b6e083 100644 --- a/toys/posix/chmod.c +++ b/toys/posix/chmod.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * chmod.c - Change file mode bits +/* chmod.c - Change file mode bits * * Copyright 2012 Rob Landley * @@ -9,59 +7,59 @@ USE_CHMOD(NEWTOY(chmod, "<2?vR", TOYFLAG_BIN)) config CHMOD - bool "chmod" - default y - help - usage: chmod [-R] MODE FILE... + bool "chmod" + default y + help + usage: chmod [-R] MODE FILE... - Change mode of listed file[s] (recursively with -R). + Change mode of listed file[s] (recursively with -R). - MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo] + MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo] - Stanzas are applied in order: For each category (u = user, - g = group, o = other, a = all three, if none specified default is a), - set (+), clear (-), or copy (=), r = read, w = write, x = execute. - s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s). - suid/sgid: execute as the user/group who owns the file. - sticky: can't delete files you don't own out of this directory - X = x for directories or if any category already has x set. + Stanzas are applied in order: For each category (u = user, + g = group, o = other, a = all three, if none specified default is a), + set (+), clear (-), or copy (=), r = read, w = write, x = execute. + s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s). + suid/sgid: execute as the user/group who owns the file. + sticky: can't delete files you don't own out of this directory + X = x for directories or if any category already has x set. - Or MODE can be an octal value up to 7777 ug uuugggooo top + - bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1 sstrwxrwxrwx bottom + Or MODE can be an octal value up to 7777 ug uuugggooo top + + bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1 sstrwxrwxrwx bottom - Examples: - chmod u+w file - allow owner of "file" to write to it. - chmod 744 file - user can read/write/execute, everyone else read only + Examples: + chmod u+w file - allow owner of "file" to write to it. + chmod 744 file - user can read/write/execute, everyone else read only */ #define FOR_chmod #include "toys.h" GLOBALS( - char *mode; + char *mode; ) int do_chmod(struct dirtree *try) { - mode_t mode; + mode_t mode; - if (!dirtree_notdotdot(try)) return 0; + if (!dirtree_notdotdot(try)) return 0; - mode = string_to_mode(TT.mode, try->st.st_mode); - if (toys.optflags & FLAG_v) { - char *s = dirtree_path(try, 0); - printf("chmod '%s' to %04o\n", s, mode); - free(s); - } - wfchmodat(dirtree_parentfd(try), try->name, mode); + mode = string_to_mode(TT.mode, try->st.st_mode); + if (toys.optflags & FLAG_v) { + char *s = dirtree_path(try, 0); + printf("chmod '%s' to %04o\n", s, mode); + free(s); + } + wfchmodat(dirtree_parentfd(try), try->name, mode); - return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0; + return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0; } void chmod_main(void) { - TT.mode = *toys.optargs; - char **file; + TT.mode = *toys.optargs; + char **file; - for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod); + for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod); } diff --git a/toys/posix/cksum.c b/toys/posix/cksum.c index 3e27b4cb..1192077c 100644 --- a/toys/posix/cksum.c +++ b/toys/posix/cksum.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cksum.c - produce crc32 checksum value for each input +/* cksum.c - produce crc32 checksum value for each input * * Copyright 2008 Rob Landley * @@ -9,78 +7,77 @@ USE_CKSUM(NEWTOY(cksum, "IPLN", TOYFLAG_BIN)) config CKSUM - bool "cksum" - default y - help - usage: cksum [-IPLN] [file...] - - For each file, output crc32 checksum value, length and name of file. - If no files listed, copy from stdin. Filename "-" is a synonym for stdin. - - -L Little endian (defaults to big endian) - -P Pre-inversion - -I Skip post-inversion - -N Do not include length in CRC calculation + bool "cksum" + default y + help + usage: cksum [-IPLN] [file...] + + For each file, output crc32 checksum value, length and name of file. + If no files listed, copy from stdin. Filename "-" is a synonym for stdin. + + -L Little endian (defaults to big endian) + -P Pre-inversion + -I Skip post-inversion + -N Do not include length in CRC calculation */ #define FOR_cksum #include "toys.h" GLOBALS( - unsigned crc_table[256]; + unsigned crc_table[256]; ) static unsigned cksum_be(unsigned crc, unsigned char c) { - return (crc<<8)^TT.crc_table[(crc>>24)^c]; + return (crc<<8)^TT.crc_table[(crc>>24)^c]; } static unsigned cksum_le(unsigned crc, unsigned char c) { - return TT.crc_table[(crc^c)&0xff] ^ (crc>>8); + return TT.crc_table[(crc^c)&0xff] ^ (crc>>8); } static void do_cksum(int fd, char *name) { - unsigned crc = (toys.optflags&4) ? 0xffffffff : 0; - uint64_t llen = 0, llen2; - unsigned (*cksum)(unsigned crc, unsigned char c); - - - cksum = (toys.optflags&2) ? cksum_le : cksum_be; - // CRC the data - - for (;;) { - int len, i; - - len = read(fd, toybuf, sizeof(toybuf)); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - - llen += len; - for (i=0; i>= 8; - } - } - - printf("%u %"PRIu64, (toys.optflags&8) ? crc : ~crc, llen2); - if (strcmp("-", name)) printf(" %s", name); - xputc('\n'); + unsigned crc = (toys.optflags&4) ? 0xffffffff : 0; + uint64_t llen = 0, llen2; + unsigned (*cksum)(unsigned crc, unsigned char c); + + cksum = (toys.optflags&2) ? cksum_le : cksum_be; + // CRC the data + + for (;;) { + int len, i; + + len = read(fd, toybuf, sizeof(toybuf)); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + + llen += len; + for (i=0; i>= 8; + } + } + + printf("%u %"PRIu64, (toys.optflags&8) ? crc : ~crc, llen2); + if (strcmp("-", name)) printf(" %s", name); + xputc('\n'); } void cksum_main(void) { - crc_init(TT.crc_table, toys.optflags&2); - loopfiles(toys.optargs, do_cksum); + crc_init(TT.crc_table, toys.optflags&2); + loopfiles(toys.optargs, do_cksum); } diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c index 4bbd3f30..13990d45 100644 --- a/toys/posix/cmp.c +++ b/toys/posix/cmp.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cmp.c - Compare two files. +/* cmp.c - Compare two files. * * Copyright 2012 Timothy Elliott * @@ -9,80 +7,78 @@ USE_CMP(NEWTOY(cmp, "<2>2ls", TOYFLAG_USR|TOYFLAG_BIN)) config CMP - bool "cmp" - default y - help - usage: cmp [-l] [-s] FILE1 FILE2 + bool "cmp" + default y + help + usage: cmp [-l] [-s] FILE1 FILE2 - Compare the contents of two files. + Compare the contents of two files. - -l show all differing bytes - -s silent + -l show all differing bytes + -s silent */ #define FOR_cmp #include "toys.h" GLOBALS( - int fd; - char *name; + int fd; + char *name; ) -// This handles opening the file and +// This handles opening the file and void do_cmp(int fd, char *name) { - int i, len1, len2, min_len, size = sizeof(toybuf)/2; - long byte_no = 1, line_no = 1; - char *buf2 = toybuf+size; + int i, len1, len2, min_len, size = sizeof(toybuf)/2; + long byte_no = 1, line_no = 1; + char *buf2 = toybuf+size; - // First time through, cache the data and return. - if (!TT.fd) { - TT.name = name; - // On return the old filehandle is closed, and this assures that even - // if we were called with stdin closed, the new filehandle != 0. - TT.fd = dup(fd); - return; - } + // First time through, cache the data and return. + if (!TT.fd) { + TT.name = name; + // On return the old filehandle is closed, and this assures that even + // if we were called with stdin closed, the new filehandle != 0. + TT.fd = dup(fd); + return; + } - for (;;) { - len1 = readall(TT.fd, toybuf, size); - len2 = readall(fd, buf2, size); + for (;;) { + len1 = readall(TT.fd, toybuf, size); + len2 = readall(fd, buf2, size); - min_len = len1 < len2 ? len1 : len2; - for (i=0; i * @@ -10,18 +8,18 @@ USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN)) config COMM - bool "comm" - default y - help - usage: comm [-123] FILE1 FILE2 + bool "comm" + default y + help + usage: comm [-123] FILE1 FILE2 - Reads FILE1 and FILE2, which should be ordered, and produces three text - columns as output: lines only in FILE1; lines only in FILE2; and lines - in both files. Filename "-" is a synonym for stdin. + Reads FILE1 and FILE2, which should be ordered, and produces three text + columns as output: lines only in FILE1; lines only in FILE2; and lines + in both files. Filename "-" is a synonym for stdin. - -1 suppress the output column of lines unique to FILE1 - -2 suppress the output column of lines unique to FILE2 - -3 suppress the output column of lines duplicated in FILE1 and FILE2 + -1 suppress the output column of lines unique to FILE1 + -2 suppress the output column of lines unique to FILE2 + -3 suppress the output column of lines duplicated in FILE1 and FILE2 */ #define FOR_comm @@ -29,54 +27,55 @@ config COMM static void writeline(const char *line, int col) { - if (col == 0 && toys.optflags & FLAG_1) return; - else if (col == 1) { - if (toys.optflags & FLAG_2) return; - if (!(toys.optflags & FLAG_1)) putchar('\t'); - } else if (col == 2) { - if (toys.optflags & FLAG_3) return; - if (!(toys.optflags & FLAG_1)) putchar('\t'); - if (!(toys.optflags & FLAG_2)) putchar('\t'); - } - puts(line); + if (col == 0 && toys.optflags & FLAG_1) return; + else if (col == 1) { + if (toys.optflags & FLAG_2) return; + if (!(toys.optflags & FLAG_1)) putchar('\t'); + } else if (col == 2) { + if (toys.optflags & FLAG_3) return; + if (!(toys.optflags & FLAG_1)) putchar('\t'); + if (!(toys.optflags & FLAG_2)) putchar('\t'); + } + puts(line); } void comm_main(void) { - int file[2]; - char *line[2]; - int i; + int file[2]; + char *line[2]; + int i; - if (toys.optflags == 7) return; + if (toys.optflags == 7) return; - for (i = 0; i < 2; i++) { - file[i] = strcmp("-", toys.optargs[i]) ? xopen(toys.optargs[i], O_RDONLY) : 0; - line[i] = get_line(file[i]); - } + for (i = 0; i < 2; i++) { + file[i] = strcmp("-", toys.optargs[i]) + ? xopen(toys.optargs[i], O_RDONLY) : 0; + line[i] = get_line(file[i]); + } - while (line[0] && line[1]) { - int order = strcmp(line[0], line[1]); + while (line[0] && line[1]) { + int order = strcmp(line[0], line[1]); - if (order == 0) { - writeline(line[0], 2); - for (i = 0; i < 2; i++) { - free(line[i]); - line[i] = get_line(file[i]); - } - } else { - i = order < 0 ? 0 : 1; - writeline(line[i], i); - free(line[i]); - line[i] = get_line(file[i]); - } - } + if (order == 0) { + writeline(line[0], 2); + for (i = 0; i < 2; i++) { + free(line[i]); + line[i] = get_line(file[i]); + } + } else { + i = order < 0 ? 0 : 1; + writeline(line[i], i); + free(line[i]); + line[i] = get_line(file[i]); + } + } - /* print rest of the longer file */ - for (i = line[0] ? 0 : 1; line[i];) { - writeline(line[i], i); - free(line[i]); - line[i] = get_line(file[i]); - } + /* print rest of the longer file */ + for (i = line[0] ? 0 : 1; line[i];) { + writeline(line[i], i); + free(line[i]); + line[i] = get_line(file[i]); + } - if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i--) xclose(file[i]); + if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i--) xclose(file[i]); } diff --git a/toys/posix/cp.c b/toys/posix/cp.c index b7834e86..e25dad46 100644 --- a/toys/posix/cp.c +++ b/toys/posix/cp.c @@ -1,8 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * cp.c - Copy files. - * - * Copyright 2008 Rob Landley +/* Copyright 2008 Rob Landley * * See http://opengroup.org/onlinepubs/9699919799/utilities/cp.html * @@ -11,35 +7,35 @@ USE_CP(NEWTOY(cp, "<2"USE_CP_MORE("rdavsl")"RHLPfip", TOYFLAG_BIN)) config CP - bool "cp (broken by dirtree changes)" - default n - help - usage: cp [-fipRHLP] SOURCE... DEST - - Copy files from SOURCE to DEST. If more than one SOURCE, DEST must - be a directory. - - -f force copy by deleting destination file - -i interactive, prompt before overwriting existing DEST - -p preserve timestamps, ownership, and permissions - -R recurse into subdirectories (DEST must be a directory) - -H Follow symlinks listed on command line - -L Follow all symlinks - -P Do not follow symlinks [default] + bool "cp (broken by dirtree changes)" + default n + help + usage: cp [-fipRHLP] SOURCE... DEST + + Copy files from SOURCE to DEST. If more than one SOURCE, DEST must + be a directory. + + -f force copy by deleting destination file + -i interactive, prompt before overwriting existing DEST + -p preserve timestamps, ownership, and permissions + -R recurse into subdirectories (DEST must be a directory) + -H Follow symlinks listed on command line + -L Follow all symlinks + -P Do not follow symlinks [default] config CP_MORE - bool "cp -rdavsl options" - default y - depends on CP - help - usage: cp [-rdavsl] - - -r synonym for -R - -d don't dereference symlinks - -a same as -dpr - -l hard link instead of copy - -s symlink instead of copy - -v verbose + bool "cp -rdavsl options" + default y + depends on CP + help + usage: cp [-rdavsl] + + -r synonym for -R + -d don't dereference symlinks + -a same as -dpr + -l hard link instead of copy + -s symlink instead of copy + -v verbose */ #define FOR_cp @@ -48,180 +44,176 @@ config CP_MORE // TODO: PLHlsd GLOBALS( - char *destname; - int destisdir; - int keep_symlinks; + char *destname; + int destisdir; + int keep_symlinks; ) // Copy an individual file or directory to target. void cp_file(char *src, char *dst, struct stat *srcst) { - int fdout = -1; - - // -i flag is specified and dst file exists. - if ((toys.optflags&FLAG_i) && !access(dst, R_OK) - && !yesno("cp: overwrite", 1)) - return; - - if (toys.optflags & FLAG_v) - printf("'%s' -> '%s'\n", src, dst); - - // Copy directory or file to destination. - - if (S_ISDIR(srcst->st_mode)) { - struct stat st2; - - // Always make directory writeable to us, so we can create files in it. - // - // Yes, there's a race window between mkdir() and open() so it's - // possible that -p can be made to chown a directory other than the one - // we created. The closest we can do to closing this is make sure - // that what we open _is_ a directory rather than something else. - - if ((mkdir(dst, srcst->st_mode | 0200) && errno != EEXIST) - || 0>(fdout=open(dst, 0)) || fstat(fdout, &st2) - || !S_ISDIR(st2.st_mode)) - { - perror_exit("mkdir '%s'", dst); - } - } else if (TT.keep_symlinks && S_ISLNK(srcst->st_mode)) { - char *link = xreadlink(src); - - // Note: -p currently has no effect on symlinks. How do you get a - // filehandle to them? O_NOFOLLOW causes the open to fail. - if (!link || symlink(link, dst)) perror_msg("link '%s'", dst); - free(link); - return; - } else if (toys.optflags & FLAG_l) { - if (link(src, dst)) perror_msg("link '%s'"); - return; - } else { - int fdin, i; - - fdin = xopen(src, O_RDONLY); - for (i=2 ; i; i--) { - fdout = open(dst, O_RDWR|O_CREAT|O_TRUNC, srcst->st_mode); - if (fdout>=0 || !(toys.optflags & FLAG_f)) break; - unlink(dst); - } - if (fdout<0) perror_exit("%s", dst); - xsendfile(fdin, fdout); - close(fdin); - } - - // Inability to set these isn't fatal, some require root access. - // Can't do fchmod() etc here because -p works on mkdir, too. - - if (toys.optflags & (FLAG_p|FLAG_a)) { - int mask = umask(0); - struct utimbuf ut; - - (void) fchown(fdout,srcst->st_uid, srcst->st_gid); - ut.actime = srcst->st_atime; - ut.modtime = srcst->st_mtime; - utime(dst, &ut); - umask(mask); - } - xclose(fdout); + int fdout = -1; + + // -i flag is specified and dst file exists. + if ((toys.optflags&FLAG_i) && !access(dst, R_OK) + && !yesno("cp: overwrite", 1)) + return; + + if (toys.optflags & FLAG_v) printf("'%s' -> '%s'\n", src, dst); + + // Copy directory or file to destination. + + if (S_ISDIR(srcst->st_mode)) { + struct stat st2; + + // Always make directory writeable to us, so we can create files in it. + // + // Yes, there's a race window between mkdir() and open() so it's + // possible that -p can be made to chown a directory other than the one + // we created. The closest we can do to closing this is make sure + // that what we open _is_ a directory rather than something else. + + if ((mkdir(dst, srcst->st_mode | 0200) && errno != EEXIST) + || 0>(fdout=open(dst, 0)) || fstat(fdout, &st2) || !S_ISDIR(st2.st_mode)) + { + perror_exit("mkdir '%s'", dst); + } + } else if (TT.keep_symlinks && S_ISLNK(srcst->st_mode)) { + char *link = xreadlink(src); + + // Note: -p currently has no effect on symlinks. How do you get a + // filehandle to them? O_NOFOLLOW causes the open to fail. + if (!link || symlink(link, dst)) perror_msg("link '%s'", dst); + free(link); + return; + } else if (toys.optflags & FLAG_l) { + if (link(src, dst)) perror_msg("link '%s'"); + return; + } else { + int fdin, i; + + fdin = xopen(src, O_RDONLY); + for (i=2 ; i; i--) { + fdout = open(dst, O_RDWR|O_CREAT|O_TRUNC, srcst->st_mode); + if (fdout>=0 || !(toys.optflags & FLAG_f)) break; + unlink(dst); + } + if (fdout<0) perror_exit("%s", dst); + xsendfile(fdin, fdout); + close(fdin); + } + + // Inability to set these isn't fatal, some require root access. + // Can't do fchmod() etc here because -p works on mkdir, too. + + if (toys.optflags & (FLAG_p|FLAG_a)) { + int mask = umask(0); + struct utimbuf ut; + + (void) fchown(fdout,srcst->st_uid, srcst->st_gid); + ut.actime = srcst->st_atime; + ut.modtime = srcst->st_mtime; + utime(dst, &ut); + umask(mask); + } + xclose(fdout); } // Callback from dirtree_read() for each file/directory under a source dir. int cp_node(struct dirtree *node) { - char *path = dirtree_path(node, 0); // TODO: use openat() instead - char *s = path+strlen(path); - struct dirtree *n; - - // Find appropriate chunk of path for destination. - - n = node; - if (!TT.destisdir) n = n->parent; - for (;;n = n->parent) { - while (s!=path) { - if (*(--s)=='/') break; - } - if (!n) break; - } - if (s != path) s++; - - s = xmsprintf("%s/%s", TT.destname, s); - cp_file(path, s, &(node->st)); - free(s); - free(path); // redo this whole darn function. - - return 0; + char *path = dirtree_path(node, 0); // TODO: use openat() instead + char *s = path+strlen(path); + struct dirtree *n; + + // Find appropriate chunk of path for destination. + + n = node; + if (!TT.destisdir) n = n->parent; + for (;;n = n->parent) { + while (s!=path) if (*(--s)=='/') break; + if (!n) break; + } + if (s != path) s++; + + s = xmsprintf("%s/%s", TT.destname, s); + cp_file(path, s, &(node->st)); + free(s); + free(path); // redo this whole darn function. + + return 0; } void cp_main(void) { - char *dpath = NULL; - struct stat st, std; - int i; + char *dpath = NULL; + struct stat st, std; + int i; - // Identify destination + // Identify destination - if (!stat(TT.destname, &std) && S_ISDIR(std.st_mode)) TT.destisdir++; - else if (toys.optc>1) error_exit("'%s' not directory", TT.destname); + if (!stat(TT.destname, &std) && S_ISDIR(std.st_mode)) TT.destisdir++; + else if (toys.optc>1) error_exit("'%s' not directory", TT.destname); // TODO: This is too early: we haven't created it yet if we need to - if (toys.optflags & (FLAG_R|FLAG_r|FLAG_a)) - dpath = realpath(TT.destname = toys.optargs[--toys.optc], NULL); + if (toys.optflags & (FLAG_R|FLAG_r|FLAG_a)) + dpath = realpath(TT.destname = toys.optargs[--toys.optc], NULL); - // Loop through sources + // Loop through sources - for (i=0; i * @@ -9,83 +7,83 @@ USE_DATE(NEWTOY(date, "r:u", TOYFLAG_BIN)) config DATE - bool "date" - default y - help - usage: date [-u] [-r file] [+format] | mmddhhmm[[cc]yy] + bool "date" + default y + help + usage: date [-u] [-r file] [+format] | mmddhhmm[[cc]yy] - Set/get the current date/time + Set/get the current date/time */ #define FOR_date #include "toys.h" GLOBALS( - char *file; + char *file; ) void date_main(void) { - const char *format_string = "%a %b %e %H:%M:%S %Z %Y"; - time_t now = time(NULL); - struct tm tm; - - if (TT.file) { - struct stat st; - - xstat(TT.file, &st); - now = st.st_mtim.tv_sec; - } - ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm); - - // Display the date? - if (!toys.optargs[0] || toys.optargs[0][0] == '+') { - if (toys.optargs[0]) format_string = toys.optargs[0]+1; - if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) - perror_msg("bad format `%s'", format_string); - - puts(toybuf); - - // Set the date - } else { - struct timeval tv; - char *s = *toys.optargs; - int len = strlen(s); - - if (len < 8 || len > 12 || (len & 1)) error_msg("bad date `%s'", s); - - // Date format: mmddhhmm[[cc]yy] - memset(&tm, 0, sizeof(tm)); - len = sscanf(s, "%2u%2u%2u%2u", &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, - &tm.tm_min); - tm.tm_mon--; - - // If year specified, overwrite one we fetched earlier - if (len > 8) { - sscanf(s, "%u", &tm.tm_year); - if (len == 12) tm.tm_year -= 1900; - /* 69-99 = 1969-1999, 0 - 68 = 2000-2068 */ - else if (tm.tm_year < 69) tm.tm_year += 100; - } - - if (toys.optflags & FLAG_u) { - // Get the UTC version of a struct tm - char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0; - setenv("TZ", "UTC", 1); - tzset(); - tv.tv_sec = mktime(&tm); - if (CFG_TOYBOX_FREE) { - if (tz) setenv("TZ", tz, 1); - else unsetenv("TZ"); - tzset(); - } - } else tv.tv_sec = mktime(&tm); - - if (tv.tv_sec == (time_t)-1) error_msg("bad `%s'", toys.optargs[0]); - tv.tv_usec = 0; - if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) - perror_msg("bad format `%s'", format_string); - puts(toybuf); - if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date"); + const char *format_string = "%a %b %e %H:%M:%S %Z %Y"; + time_t now = time(NULL); + struct tm tm; + + if (TT.file) { + struct stat st; + + xstat(TT.file, &st); + now = st.st_mtim.tv_sec; + } + ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm); + + // Display the date? + if (!toys.optargs[0] || toys.optargs[0][0] == '+') { + if (toys.optargs[0]) format_string = toys.optargs[0]+1; + if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) + perror_msg("bad format `%s'", format_string); + + puts(toybuf); + + // Set the date + } else { + struct timeval tv; + char *s = *toys.optargs; + int len = strlen(s); + + if (len < 8 || len > 12 || (len & 1)) error_msg("bad date `%s'", s); + + // Date format: mmddhhmm[[cc]yy] + memset(&tm, 0, sizeof(tm)); + len = sscanf(s, "%2u%2u%2u%2u", &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, + &tm.tm_min); + tm.tm_mon--; + + // If year specified, overwrite one we fetched earlier + if (len > 8) { + sscanf(s, "%u", &tm.tm_year); + if (len == 12) tm.tm_year -= 1900; + /* 69-99 = 1969-1999, 0 - 68 = 2000-2068 */ + else if (tm.tm_year < 69) tm.tm_year += 100; } + + if (toys.optflags & FLAG_u) { + // Get the UTC version of a struct tm + char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0; + setenv("TZ", "UTC", 1); + tzset(); + tv.tv_sec = mktime(&tm); + if (CFG_TOYBOX_FREE) { + if (tz) setenv("TZ", tz, 1); + else unsetenv("TZ"); + tzset(); + } + } else tv.tv_sec = mktime(&tm); + + if (tv.tv_sec == (time_t)-1) error_msg("bad `%s'", toys.optargs[0]); + tv.tv_usec = 0; + if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) + perror_msg("bad format `%s'", format_string); + puts(toybuf); + if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date"); + } } diff --git a/toys/posix/df.c b/toys/posix/df.c index 66e86b3b..5641ff34 100644 --- a/toys/posix/df.c +++ b/toys/posix/df.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * df.c - report free disk space. +/* df.c - report free disk space. * * Copyright 2006 Rob Landley * @@ -9,156 +7,155 @@ USE_DF(NEWTOY(df, "Pkt*a", TOYFLAG_USR|TOYFLAG_SBIN)) config DF - bool "df (disk free)" - default y - help - usage: df [-t type] [FILESYSTEM ...] + bool "df (disk free)" + default y + help + usage: df [-t type] [FILESYSTEM ...] - The "disk free" command, df shows total/used/available disk space for - each filesystem listed on the command line, or all currently mounted - filesystems. + The "disk free" command, df shows total/used/available disk space for + each filesystem listed on the command line, or all currently mounted + filesystems. - -t type - Display only filesystems of this type. + -t type Display only filesystems of this type. config DF_PEDANTIC - bool "options -P and -k" - default y - depends on DF - help - usage: df [-Pk] + bool "options -P and -k" + default y + depends on DF + help + usage: df [-Pk] - -P The SUSv3 "Pedantic" option + -P The SUSv3 "Pedantic" option - Provides a slightly less useful output format dictated by - the Single Unix Specification version 3, and sets the - units to 512 bytes instead of the default 1024 bytes. + Provides a slightly less useful output format dictated by + the Single Unix Specification version 3, and sets the + units to 512 bytes instead of the default 1024 bytes. - -k Sets units back to 1024 bytes (the default without -P) + -k Sets units back to 1024 bytes (the default without -P) */ #define FOR_df #include "toys.h" GLOBALS( - struct arg_list *fstype; + struct arg_list *fstype; - long units; + long units; ) static void show_mt(struct mtab_list *mt) { - int len; - long long size, used, avail, percent, block; - char *device; - - // Return if it wasn't found (should never happen, but with /etc/mtab...) - if (!mt) return; - - // If we have -t, skip other filesystem types - if (TT.fstype) { - struct arg_list *al; - - for (al = TT.fstype; al; al = al->next) { - if (!strcmp(mt->type, al->arg)) break; - } - if (!al) return; - } - - // If we don't have -a, skip synthetic filesystems - if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return; - - // Figure out how much total/used/free space this filesystem has, - // forcing 64-bit math because filesystems are big now. - block = mt->statvfs.f_bsize ? mt->statvfs.f_bsize : 1; - size = (block * mt->statvfs.f_blocks) / TT.units; - used = (block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree)) / TT.units; - avail = (block * (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree)) - / TT.units; - if (!(used+avail)) percent = 0; - else { - percent = (used*100)/(used+avail); - if (used*100 != percent*(used+avail)) percent++; - } - - device = *mt->device == '/' ? realpath(mt->device, NULL) : NULL; - if (!device) device = mt->device; - - // Figure out appropriate spacing - len = 25 - strlen(device); - if (len < 1) len = 1; - if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { - xprintf("%s %lld %lld %lld %lld%% %s\n", device, size, used, avail, - percent, mt->dir); - } else { - xprintf("%s% *lld % 10lld % 9lld % 3lld%% %s\n", device, len, - size, used, avail, percent, mt->dir); - } - - if (device != mt->device) free(device); + int len; + long long size, used, avail, percent, block; + char *device; + + // Return if it wasn't found (should never happen, but with /etc/mtab...) + if (!mt) return; + + // If we have -t, skip other filesystem types + if (TT.fstype) { + struct arg_list *al; + + for (al = TT.fstype; al; al = al->next) + if (!strcmp(mt->type, al->arg)) break; + + if (!al) return; + } + + // If we don't have -a, skip synthetic filesystems + if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return; + + // Figure out how much total/used/free space this filesystem has, + // forcing 64-bit math because filesystems are big now. + block = mt->statvfs.f_bsize ? mt->statvfs.f_bsize : 1; + size = (block * mt->statvfs.f_blocks) / TT.units; + used = (block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree)) / TT.units; + avail = (block * (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree)) + / TT.units; + if (!(used+avail)) percent = 0; + else { + percent = (used*100)/(used+avail); + if (used*100 != percent*(used+avail)) percent++; + } + + device = *mt->device == '/' ? realpath(mt->device, NULL) : NULL; + if (!device) device = mt->device; + + // Figure out appropriate spacing + len = 25 - strlen(device); + if (len < 1) len = 1; + if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { + xprintf("%s %lld %lld %lld %lld%% %s\n", device, size, used, avail, + percent, mt->dir); + } else { + xprintf("%s% *lld % 10lld % 9lld % 3lld%% %s\n", device, len, + size, used, avail, percent, mt->dir); + } + + if (device != mt->device) free(device); } void df_main(void) { - struct mtab_list *mt, *mt2, *mtlist; - - // Handle -P and -k - TT.units = 1024; - if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { - // Units are 512 bytes if you select "pedantic" without "kilobytes". - if ((toys.optflags&(FLAG_P|FLAG_k)) == FLAG_P) TT.units = 512; - printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n", - TT.units); - } else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on"); - - mtlist = getmountlist(1); - - // If we have a list of filesystems on the command line, loop through them. - if (*toys.optargs) { - char **next; - - for(next = toys.optargs; *next; next++) { - struct stat st; - - // Stat it (complain if we can't). - if(stat(*next, &st)) { - perror_msg("`%s'", *next); - toys.exitval = 1; - continue; - } - - // Find and display this filesystem. Use _last_ hit in case of - // -- bind mounts. - mt2 = NULL; - for (mt = mtlist; mt; mt = mt->next) { - if (st.st_dev == mt->stat.st_dev) { - mt2 = mt; - break; - } - } - show_mt(mt2); - } - } else { - // Get and loop through mount list. - - for (mt = mtlist; mt; mt = mt->next) { - struct mtab_list *mt2, *mt3; - - if (!mt->stat.st_dev) continue; - - // Filter out overmounts. - mt3 = mt; - for (mt2 = mt->next; mt2; mt2 = mt2->next) { - if (mt->stat.st_dev == mt2->stat.st_dev) { - // For --bind mounts, take last match - if (!strcmp(mt->device, mt2->device)) mt3 = mt2; - // Filter out overmounts - mt2->stat.st_dev = 0; - } - } - show_mt(mt3); - } - } - - if (CFG_TOYBOX_FREE) llist_traverse(mtlist, free); + struct mtab_list *mt, *mt2, *mtlist; + + // Handle -P and -k + TT.units = 1024; + if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { + // Units are 512 bytes if you select "pedantic" without "kilobytes". + if ((toys.optflags&(FLAG_P|FLAG_k)) == FLAG_P) TT.units = 512; + printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n", + TT.units); + } else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on"); + + mtlist = getmountlist(1); + + // If we have a list of filesystems on the command line, loop through them. + if (*toys.optargs) { + char **next; + + for(next = toys.optargs; *next; next++) { + struct stat st; + + // Stat it (complain if we can't). + if(stat(*next, &st)) { + perror_msg("`%s'", *next); + toys.exitval = 1; + continue; + } + + // Find and display this filesystem. Use _last_ hit in case of + // -- bind mounts. + mt2 = NULL; + for (mt = mtlist; mt; mt = mt->next) { + if (st.st_dev == mt->stat.st_dev) { + mt2 = mt; + break; + } + } + show_mt(mt2); + } + } else { + // Get and loop through mount list. + + for (mt = mtlist; mt; mt = mt->next) { + struct mtab_list *mt2, *mt3; + + if (!mt->stat.st_dev) continue; + + // Filter out overmounts. + mt3 = mt; + for (mt2 = mt->next; mt2; mt2 = mt2->next) { + if (mt->stat.st_dev == mt2->stat.st_dev) { + // For --bind mounts, take last match + if (!strcmp(mt->device, mt2->device)) mt3 = mt2; + // Filter out overmounts + mt2->stat.st_dev = 0; + } + } + show_mt(mt3); + } + } + + if (CFG_TOYBOX_FREE) llist_traverse(mtlist, free); } diff --git a/toys/posix/dirname.c b/toys/posix/dirname.c index 5dc60181..06470ad8 100644 --- a/toys/posix/dirname.c +++ b/toys/posix/dirname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * dirname.c - show directory portion of path +/* dirname.c - show directory portion of path * * Copyright 2011 Rob Landley * @@ -9,17 +7,17 @@ USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config DIRNAME - bool "dirname" - default y - help - usage: dirname PATH + bool "dirname" + default y + help + usage: dirname PATH - Show directory portion of path. + Show directory portion of path. */ #include "toys.h" void dirname_main(void) { - puts(dirname(*toys.optargs)); + puts(dirname(*toys.optargs)); } diff --git a/toys/posix/du.c b/toys/posix/du.c index 8013810c..68cf286d 100644 --- a/toys/posix/du.c +++ b/toys/posix/du.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * du.c - disk usage program. +/* du.c - disk usage program. * * Copyright 2012 Ashwini Kumar * @@ -9,45 +7,45 @@ USE_DU(NEWTOY(du, "d#<0hmlcaHkLsx", TOYFLAG_USR|TOYFLAG_BIN)) config DU - bool "du" - default y - help - usage: du [-d N] [-askxHLlmc] [file...] - - Estimate file space usage (default in unit of 512 blocks). - -a Show all file sizes - -H Follow symlinks on cmdline - -L Follow all symlinks - -k Show size in units of 1024. - -s Show only the total Size for each file specified - -x Estimate size only on the same device - -c Print total size of all arguments - -d N Limit output to directories (and files with -a) of depth < N - -l Count sizes many times if hard linked - -h Sizes in human readable format (e.g., 1K 243M 2G ) - -m Sizes in megabytes + bool "du" + default y + help + usage: du [-d N] [-askxHLlmc] [file...] + + Estimate file space usage (default in unit of 512 blocks). + -a Show all file sizes + -H Follow symlinks on cmdline + -L Follow all symlinks + -k Show size in units of 1024. + -s Show only the total Size for each file specified + -x Estimate size only on the same device + -c Print total size of all arguments + -d N Limit output to directories (and files with -a) of depth < N + -l Count sizes many times if hard linked + -h Sizes in human readable format (e.g., 1K 243M 2G ) + -m Sizes in megabytes */ #define FOR_du #include "toys.h" GLOBALS( - long maxdepth; - long depth; - long *dirsum; - long total; - dev_t st_dev; - struct arg_list *inodes; + long maxdepth; + long depth; + long *dirsum; + long total; + dev_t st_dev; + struct arg_list *inodes; ) typedef struct node_size { - struct dirtree *node; - long size; + struct dirtree *node; + long size; }node_size; typedef struct inode_ent { - ino_t ino; - dev_t dev; + ino_t ino; + dev_t dev; }inode_ent_t; /* @@ -56,18 +54,18 @@ typedef struct inode_ent { char *make_pathproper(char *str) { - char *path = str; - switch(strlen(str)) { - case 1: - if(str[0] == '.') path = xstrdup("./"); - break; - case 2: - if(str[0] == '.' && str[1] == '.') path = xstrdup("../"); - break; - default: - break; - } - return path; + char *path = str; + switch(strlen(str)) { + case 1: + if(str[0] == '.') path = xstrdup("./"); + break; + case 2: + if(str[0] == '.' && str[1] == '.') path = xstrdup("../"); + break; + default: + break; + } + return path; } /* @@ -75,38 +73,38 @@ char *make_pathproper(char *str) */ void print(long size, char* name) { - unsigned long long tempsize = (unsigned long long)size * 512; - unsigned long unit = 512; - char *sizestr = NULL; - if(TT.depth > TT.maxdepth) return; - if(toys.optflags & FLAG_h) unit = 0; - if(toys.optflags & FLAG_k) unit = 1024; - if(toys.optflags & FLAG_m) unit = 1024*1024; - sizestr = make_human_readable(tempsize, unit); //make human readable string, depending upon unit size. - xprintf("%s\t%s\n",sizestr, name); - free(sizestr); + unsigned long long tempsize = (unsigned long long)size * 512; + unsigned long unit = 512; + char *sizestr = NULL; + if(TT.depth > TT.maxdepth) return; + if(toys.optflags & FLAG_h) unit = 0; + if(toys.optflags & FLAG_k) unit = 1024; + if(toys.optflags & FLAG_m) unit = 1024*1024; + sizestr = make_human_readable(tempsize, unit); //make human readable string, depending upon unit size. + xprintf("%s\t%s\n",sizestr, name); + free(sizestr); } /* - * free the inodes which are stored for hard link reference + * free the inodes which are stored for hard link reference */ void free_inodes(void *data) { - void *arg = ((struct arg_list*)data)->arg; - if(arg) free(arg); - free(data); + void *arg = ((struct arg_list*)data)->arg; + if(arg) free(arg); + free(data); } /* * allocate and add a node to the list */ static void llist_add_inode(struct arg_list **old, void *data) -{ - struct arg_list *new = xmalloc(sizeof(struct arg_list)); +{ + struct arg_list *new = xmalloc(sizeof(struct arg_list)); - new->arg = (char*)data; - new->next = *old; - *old = new; + new->arg = (char*)data; + new->next = *old; + *old = new; } /* @@ -114,14 +112,14 @@ static void llist_add_inode(struct arg_list **old, void *data) */ int is_inode_present(struct stat *st) { - struct arg_list *temparg = NULL; - inode_ent_t *ent = NULL; - if(!TT.inodes) return 0; - for(temparg = TT.inodes; temparg; temparg = (struct arg_list *)temparg->next) { - ent = (inode_ent_t*)temparg->arg; - if(ent && ent->ino == st->st_ino && ent->dev == st->st_dev) return 1; - } - return 0; + struct arg_list *temparg = NULL; + inode_ent_t *ent = NULL; + if(!TT.inodes) return 0; + for(temparg = TT.inodes; temparg; temparg = (struct arg_list *)temparg->next) { + ent = (inode_ent_t*)temparg->arg; + if(ent && ent->ino == st->st_ino && ent->dev == st->st_dev) return 1; + } + return 0; } /* @@ -129,66 +127,66 @@ int is_inode_present(struct stat *st) */ int do_du(struct dirtree *node) { - inode_ent_t *ino_details = NULL; - node_size *nd = NULL; - if(!dirtree_notdotdot(node)) return 0; - if((toys.optflags & FLAG_x) && (TT.st_dev != node->st.st_dev)) //if file not on same device, don't count size - return DIRTREE_RECURSE; - - if(!(toys.optflags & FLAG_l) && node->st.st_nlink > 1 && !node->extra) { //keeping reference for hard links - if(is_inode_present(&node->st)) return DIRTREE_RECURSE; - ino_details = xzalloc(sizeof(inode_ent_t)); - ino_details->ino = node->st.st_ino; - ino_details->dev = node->st.st_dev; - llist_add_inode(&TT.inodes, (void*)ino_details); - } + inode_ent_t *ino_details = NULL; + node_size *nd = NULL; + if(!dirtree_notdotdot(node)) return 0; + if((toys.optflags & FLAG_x) && (TT.st_dev != node->st.st_dev)) //if file not on same device, don't count size + return DIRTREE_RECURSE; - if(S_ISDIR(node->st.st_mode)) { - if(!(node->extra && (long)((node_size*)(node->extra))->node == (long)node)) { - nd = xzalloc(sizeof(node_size)); - nd->node = node; - nd->size = 0; - TT.dirsum = (long*)&(nd->size); - node->extra = (long)nd; - *TT.dirsum = 0; - TT.depth++; - return (DIRTREE_RECURSE|DIRTREE_COMEAGAIN | ((toys.optflags & FLAG_L) ? DIRTREE_SYMFOLLOW : 0)); //DIRTREE_COMEAGAIN to comeback and print the entry. - } - else if(node->extra) { //extra is set for a returning DIR entry. - long offset = 0; - nd = (node_size*)node->extra; - offset = nd->size; - nd->size += node->st.st_blocks; - TT.depth--; - if(!(toys.optflags & FLAG_s)) - print(*TT.dirsum, dirtree_path(node, NULL)); - if((node->parent) && (node->parent->extra)) { - /* when returning from internal directory, get the saved size of the parent and continue from there */ - nd = (node_size*)node->parent->extra; - TT.dirsum = (long*)&(nd->size); - *TT.dirsum += offset; - *TT.dirsum += node->st.st_blocks; - return DIRTREE_RECURSE; - } - else if(!node->parent) { - /*if node has no parent, it means it is the top in the tree, stop recursing here */ - TT.total += *TT.dirsum; - if((toys.optflags & FLAG_s)) - print(*TT.dirsum, dirtree_path(node, NULL)); - return 0; - } - } + if(!(toys.optflags & FLAG_l) && node->st.st_nlink > 1 && !node->extra) { //keeping reference for hard links + if(is_inode_present(&node->st)) return DIRTREE_RECURSE; + ino_details = xzalloc(sizeof(inode_ent_t)); + ino_details->ino = node->st.st_ino; + ino_details->dev = node->st.st_dev; + llist_add_inode(&TT.inodes, (void*)ino_details); + } + + if(S_ISDIR(node->st.st_mode)) { + if(!(node->extra && (long)((node_size*)(node->extra))->node == (long)node)) { + nd = xzalloc(sizeof(node_size)); + nd->node = node; + nd->size = 0; + TT.dirsum = (long*)&(nd->size); + node->extra = (long)nd; + *TT.dirsum = 0; + TT.depth++; + return (DIRTREE_RECURSE|DIRTREE_COMEAGAIN | ((toys.optflags & FLAG_L) ? DIRTREE_SYMFOLLOW : 0)); //DIRTREE_COMEAGAIN to comeback and print the entry. } - else if(!(node->parent)) { - /* this is the file specified on cmdline */ - TT.total += node->st.st_blocks; - print(node->st.st_blocks, dirtree_path(node, NULL)); + else if(node->extra) { //extra is set for a returning DIR entry. + long offset = 0; + nd = (node_size*)node->extra; + offset = nd->size; + nd->size += node->st.st_blocks; + TT.depth--; + if(!(toys.optflags & FLAG_s)) + print(*TT.dirsum, dirtree_path(node, NULL)); + if((node->parent) && (node->parent->extra)) { + /* when returning from internal directory, get the saved size of the parent and continue from there */ + nd = (node_size*)node->parent->extra; + TT.dirsum = (long*)&(nd->size); + *TT.dirsum += offset; + *TT.dirsum += node->st.st_blocks; + return DIRTREE_RECURSE; + } + else if(!node->parent) { + /*if node has no parent, it means it is the top in the tree, stop recursing here */ + TT.total += *TT.dirsum; + if((toys.optflags & FLAG_s)) + print(*TT.dirsum, dirtree_path(node, NULL)); return 0; + } } - if(TT.dirsum) *TT.dirsum += node->st.st_blocks; - if(toys.optflags & FLAG_a && !(toys.optflags & FLAG_s)) - print(node->st.st_blocks, dirtree_path(node, NULL)); - return DIRTREE_RECURSE; + } + else if(!(node->parent)) { + /* this is the file specified on cmdline */ + TT.total += node->st.st_blocks; + print(node->st.st_blocks, dirtree_path(node, NULL)); + return 0; + } + if(TT.dirsum) *TT.dirsum += node->st.st_blocks; + if(toys.optflags & FLAG_a && !(toys.optflags & FLAG_s)) + print(node->st.st_blocks, dirtree_path(node, NULL)); + return DIRTREE_RECURSE; } /* @@ -196,22 +194,22 @@ int do_du(struct dirtree *node) */ void du_main(void) { - int symfollow = toys.optflags & (FLAG_H | FLAG_L); - TT.total = 0; - TT.inodes = NULL; - - if(!(toys.optflags & FLAG_d)) TT.maxdepth = INT_MAX; - if(toys.optc == 0) toys.optargs[0] = "./"; - while(*toys.optargs) { - TT.depth = 0; - char *path = make_pathproper(*toys.optargs); - struct dirtree *root = dirtree_add_node(AT_FDCWD, path, symfollow); //create a node - if(root) { - TT.st_dev = root->st.st_dev; - handle_callback(root, do_du); //this will recurse thru the DIR children. - } - toys.optargs++; + int symfollow = toys.optflags & (FLAG_H | FLAG_L); + TT.total = 0; + TT.inodes = NULL; + + if(!(toys.optflags & FLAG_d)) TT.maxdepth = INT_MAX; + if(toys.optc == 0) toys.optargs[0] = "./"; + while(*toys.optargs) { + TT.depth = 0; + char *path = make_pathproper(*toys.optargs); + struct dirtree *root = dirtree_add_node(AT_FDCWD, path, symfollow); //create a node + if(root) { + TT.st_dev = root->st.st_dev; + handle_callback(root, do_du); //this will recurse thru the DIR children. } - if(TT.inodes) llist_traverse(TT.inodes, free_inodes); //free the stored nodes - if(toys.optflags & FLAG_c) print(TT.total, "total"); + toys.optargs++; + } + if(TT.inodes) llist_traverse(TT.inodes, free_inodes); //free the stored nodes + if(toys.optflags & FLAG_c) print(TT.total, "total"); } diff --git a/toys/posix/echo.c b/toys/posix/echo.c index 1bf4d399..28284bfb 100644 --- a/toys/posix/echo.c +++ b/toys/posix/echo.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * echo.c - echo supporting -n and -e. +/* echo.c - echo supporting -n and -e. * * Copyright 2007 Rob Landley * @@ -9,27 +7,27 @@ USE_ECHO(NEWTOY(echo, "^?en", TOYFLAG_BIN)) config ECHO - bool "echo" - default y - help - usage: echo [-ne] [args...] + bool "echo" + default y + help + usage: echo [-ne] [args...] - Write each argument to stdout, with one space between each, followed - by a newline. + Write each argument to stdout, with one space between each, followed + by a newline. - -n No trailing newline. - -e Process the following escape sequences: - \\ backslash - \0NNN octal values (1 to 3 digits) - \a alert (beep/flash) - \b backspace - \c stop output here (avoids trailing newline) - \f form feed - \n newline - \r carriage return - \t horizontal tab - \v vertical tab - \xHH hexadecimal values (1 to 2 digits) + -n No trailing newline. + -e Process the following escape sequences: + \\ backslash + \0NNN octal values (1 to 3 digits) + \a alert (beep/flash) + \b backspace + \c stop output here (avoids trailing newline) + \f form feed + \n newline + \r carriage return + \t horizontal tab + \v vertical tab + \xHH hexadecimal values (1 to 2 digits) */ #define FOR_echo @@ -37,58 +35,56 @@ config ECHO void echo_main(void) { - int i = 0, out; - char *arg, *from = "\\abfnrtv", *to = "\\\a\b\f\n\r\t\v", *c; + int i = 0, out; + char *arg, *from = "\\abfnrtv", *to = "\\\a\b\f\n\r\t\v", *c; - for (;;) { - arg = toys.optargs[i]; - if (!arg) break; - if (i++) xputc(' '); + for (;;) { + arg = toys.optargs[i]; + if (!arg) break; + if (i++) xputc(' '); - // Should we output arg verbatim? + // Should we output arg verbatim? - if (!(toys.optflags&FLAG_e)) { - xprintf("%s", arg); - continue; - } + if (!(toys.optflags & FLAG_e)) { + xprintf("%s", arg); + continue; + } - // Handle -e + // Handle -e - for (c=arg;;) { - if (!(out = *(c++))) break; + for (c=arg;;) { + if (!(out = *(c++))) break; - // handle \escapes - if (out == '\\' && *c) { - int n = 0, slash = *(c++); - char *found = strchr(from, slash); - if (found) out = to[found-from]; - else if (slash == 'c') goto done; - else if (slash == '0') { - out = 0; - while (*c>='0' && *c<='7' && n++<3) - out = (out*8)+*(c++)-'0'; - } else if (slash == 'x') { - out = 0; - while (n++<2) { - if (*c>='0' && *c<='9') - out = (out*16)+*(c++)-'0'; - else { - int temp = tolower(*c); - if (temp>='a' && temp<='f') { - out = (out*16)+temp-'a'+10; - c++; - } else break; - } - } - // Slash in front of unknown character, print literal. - } else c--; - } - xputc(out); - } - } + // handle \escapes + if (out == '\\' && *c) { + int n = 0, slash = *(c++); + char *found = strchr(from, slash); + if (found) out = to[found-from]; + else if (slash == 'c') goto done; + else if (slash == '0') { + out = 0; + while (*c>='0' && *c<='7' && n++<3) out = (out*8)+*(c++)-'0'; + } else if (slash == 'x') { + out = 0; + while (n++<2) { + if (*c>='0' && *c<='9') out = (out*16)+*(c++)-'0'; + else { + int temp = tolower(*c); + if (temp>='a' && temp<='f') { + out = (out*16)+temp-'a'+10; + c++; + } else break; + } + } + // Slash in front of unknown character, print literal. + } else c--; + } + xputc(out); + } + } - // Output "\n" if no -n - if (!(toys.optflags&FLAG_n)) xputc('\n'); + // Output "\n" if no -n + if (!(toys.optflags&FLAG_n)) xputc('\n'); done: - xflush(); + xflush(); } diff --git a/toys/posix/env.c b/toys/posix/env.c index 32272799..8f7ccf1f 100644 --- a/toys/posix/env.c +++ b/toys/posix/env.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * env.c - Set the environment for command invocation. +/* env.c - Set the environment for command invocation. * * Copyright 2012 Tryn Mirell * @@ -9,14 +7,14 @@ USE_ENV(NEWTOY(env, "^i", TOYFLAG_USR|TOYFLAG_BIN)) config ENV - bool "env" - default y - help - usage: env [-i] [NAME=VALUE...] [command [option...]] + bool "env" + default y + help + usage: env [-i] [NAME=VALUE...] [command [option...]] - Set the environment for command invocation. + Set the environment for command invocation. - -i Clear existing environment. + -i Clear existing environment. */ #include "toys.h" @@ -25,29 +23,29 @@ extern char **environ; void env_main(void) { - char **ev; - char **command = NULL; - char *del = "="; - - if (toys.optflags) clearenv(); - - for (ev = toys.optargs; *ev != NULL; ev++) { - char *env, *val = NULL; - - env = strtok(*ev, del); - - if (env) val = strtok(NULL, del); - - if (val) setenv(env, val, 1); - else { - command = ev; - break; - } + char **ev; + char **command = NULL; + char *del = "="; + + if (toys.optflags) clearenv(); + + for (ev = toys.optargs; *ev != NULL; ev++) { + char *env, *val = NULL; + + env = strtok(*ev, del); + + if (env) val = strtok(NULL, del); + + if (val) setenv(env, val, 1); + else { + command = ev; + break; } - - if (!command) { - char **ep; - for (ep = environ; *ep; ep++) xputs(*ep); - return; - } else xexec(command); + } + + if (!command) { + char **ep; + for (ep = environ; *ep; ep++) xputs(*ep); + return; + } else xexec(command); } diff --git a/toys/posix/false.c b/toys/posix/false.c index 7208ea7a..73458bea 100644 --- a/toys/posix/false.c +++ b/toys/posix/false.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * false.c - Return nonzero. +/* false.c - Return nonzero. * * Copyright 2007 Rob Landley * @@ -9,15 +7,15 @@ USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN)) config FALSE - bool "false" - default y - help - Return nonzero. + bool "false" + default y + help + Return nonzero. */ #include "toys.h" void false_main(void) { - toys.exitval = 1; + toys.exitval = 1; } diff --git a/toys/posix/head.c b/toys/posix/head.c index 77978f74..ba7b7385 100644 --- a/toys/posix/head.c +++ b/toys/posix/head.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * head.c - copy first lines from input to stdout. +/* head.c - copy first lines from input to stdout. * * Copyright 2006 Timothy Elliott * @@ -9,52 +7,51 @@ USE_HEAD(NEWTOY(head, "n#<0=10", TOYFLAG_BIN)) config HEAD - bool "head" - default y - help - usage: head [-n number] [file...] + bool "head" + default y + help + usage: head [-n number] [file...] - Copy first lines from files to stdout. If no files listed, copy from - stdin. Filename "-" is a synonym for stdin. + Copy first lines from files to stdout. If no files listed, copy from + stdin. Filename "-" is a synonym for stdin. - -n Number of lines to copy. + -n Number of lines to copy. */ #define FOR_head #include "toys.h" GLOBALS( - long lines; - int file_no; + long lines; + int file_no; ) static void do_head(int fd, char *name) { - int i, len, lines=TT.lines, size=sizeof(toybuf); - - if (toys.optc > 1) { - // Print an extra newline for all but the first file - if (TT.file_no++) xprintf("\n"); - xprintf("==> %s <==\n", name); - xflush(); - } - - while (lines) { - len = read(fd, toybuf, size); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - - for(i=0; i 1) { + // Print an extra newline for all but the first file + if (TT.file_no++) xprintf("\n"); + xprintf("==> %s <==\n", name); + xflush(); + } + + while (lines) { + len = read(fd, toybuf, size); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + + for(i=0; ipw_uid; - gid = egid = pw->pw_gid; - } - - i = toys.optflags & FLAG_r; - pw = xgetpwuid(i ? uid : euid); - if (flags & FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1); - - grp = xgetgrgid(i ? gid : egid); - if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1); - - if (!(flags & FLAG_G)) { - showid("uid=", pw->pw_uid, pw->pw_name); - showid(" gid=", grp->gr_gid, grp->gr_name); - - if (!i) { - if (uid != euid) { - pw = xgetpwuid(euid); - showid(" euid=", pw->pw_uid, pw->pw_name); - } - if (gid != egid) { - grp = xgetgrgid(egid); - showid(" egid=", grp->gr_gid, grp->gr_name); - } - } - - showid(" groups=", grp->gr_gid, grp->gr_name); - } - - - groups = (gid_t *)toybuf; - if (0 >= (ngroups = getgroups(sizeof(toybuf)/sizeof(gid_t), groups))) - perror_exit(0); - - for (i = 0; i < ngroups; i++) { - xputc(' '); - if (!(grp = getgrgid(groups[i]))) perror_msg(0); - else if (flags & FLAG_G) - s_or_u(grp->gr_name, grp->gr_gid, 0); - else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name); - } - xputc('\n'); + int flags = toys.optflags, i, ngroups; + struct passwd *pw; + struct group *grp; + uid_t uid = getuid(), euid = geteuid(); + gid_t gid = getgid(), egid = getegid(), *groups; + + // check if a username is given + if (*toys.optargs) { + if (!(pw = getpwnam(*toys.optargs))) + error_exit("no such user '%s'", *toys.optargs); + uid = euid = pw->pw_uid; + gid = egid = pw->pw_gid; + } + + i = toys.optflags & FLAG_r; + pw = xgetpwuid(i ? uid : euid); + if (flags & FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1); + + grp = xgetgrgid(i ? gid : egid); + if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1); + + if (!(flags & FLAG_G)) { + showid("uid=", pw->pw_uid, pw->pw_name); + showid(" gid=", grp->gr_gid, grp->gr_name); + + if (!i) { + if (uid != euid) { + pw = xgetpwuid(euid); + showid(" euid=", pw->pw_uid, pw->pw_name); + } + if (gid != egid) { + grp = xgetgrgid(egid); + showid(" egid=", grp->gr_gid, grp->gr_name); + } + } + + showid(" groups=", grp->gr_gid, grp->gr_name); + } + + groups = (gid_t *)toybuf; + if (0 >= (ngroups = getgroups(sizeof(toybuf)/sizeof(gid_t), groups))) + perror_exit(0); + + for (i = 0; i < ngroups; i++) { + xputc(' '); + if (!(grp = getgrgid(groups[i]))) perror_msg(0); + else if (flags & FLAG_G) s_or_u(grp->gr_name, grp->gr_gid, 0); + else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name); + } + xputc('\n'); } diff --git a/toys/posix/kill.c b/toys/posix/kill.c index 7810b899..2d1606b4 100644 --- a/toys/posix/kill.c +++ b/toys/posix/kill.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * kill.c - a program to send signals to processes +/* kill.c - a program to send signals to processes * * Copyright 2012 Daniel Walter * @@ -9,65 +7,64 @@ USE_KILL(NEWTOY(kill, "?s: l", TOYFLAG_BIN)) config KILL - bool "kill" - default y - help - usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] pid... - - Send a signal to a process + bool "kill" + default y + help + usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] pid... + Send a signal to a process */ #define FOR_kill #include "toys.h" GLOBALS( - char *signame; + char *signame; ) void kill_main(void) { - int signum; - char *tmp, **args = toys.optargs; - pid_t pid; + int signum; + char *tmp, **args = toys.optargs; + pid_t pid; - // list signal(s) - if (toys.optflags & FLAG_l) { - if (*args) { - int signum = sig_to_num(*args); - char *s = NULL; + // list signal(s) + if (toys.optflags & FLAG_l) { + if (*args) { + int signum = sig_to_num(*args); + char *s = NULL; - if (signum>=0) s = num_to_sig(signum&127); - puts(s ? s : "UNKNOWN"); - } else sig_to_num(NULL); - return; - } + if (signum>=0) s = num_to_sig(signum&127); + puts(s ? s : "UNKNOWN"); + } else sig_to_num(NULL); + return; + } - // signal must come before pids, so "kill -9 -1" isn't confusing. + // signal must come before pids, so "kill -9 -1" isn't confusing. - if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1; - if (TT.signame) { - char *arg; - int i = strtol(TT.signame, &arg, 10); - if (!*arg) arg = num_to_sig(i); - else arg = TT.signame; + if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1; + if (TT.signame) { + char *arg; + int i = strtol(TT.signame, &arg, 10); + if (!*arg) arg = num_to_sig(i); + else arg = TT.signame; - if (!arg || -1 == (signum = sig_to_num(arg))) - error_exit("Unknown signal '%s'", arg); - } else signum = SIGTERM; + if (!arg || -1 == (signum = sig_to_num(arg))) + error_exit("Unknown signal '%s'", arg); + } else signum = SIGTERM; - if (!*args) { - toys.exithelp++; - error_exit("missing argument"); - } + if (!*args) { + toys.exithelp++; + error_exit("missing argument"); + } - while (*args) { - char *arg = *(args++); + while (*args) { + char *arg = *(args++); - pid = strtol(arg, &tmp, 10); - if (*tmp || kill(pid, signum) < 0) { - error_msg("unknown pid '%s'", arg); - toys.exitval = EXIT_FAILURE; - } - } + pid = strtol(arg, &tmp, 10); + if (*tmp || kill(pid, signum) < 0) { + error_msg("unknown pid '%s'", arg); + toys.exitval = EXIT_FAILURE; + } + } } diff --git a/toys/posix/link.c b/toys/posix/link.c index 69a9a60f..38d2cf05 100644 --- a/toys/posix/link.c +++ b/toys/posix/link.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * link.c - hardlink a file +/* link.c - hardlink a file * * Copyright 2011 Rob Landley * @@ -9,19 +7,19 @@ USE_LINK(NEWTOY(link, "<2>2", TOYFLAG_USR|TOYFLAG_BIN)) config LINK - bool "link" - default y - help - usage: link FILE NEWLINK + bool "link" + default y + help + usage: link FILE NEWLINK - Create hardlink to a file. + Create hardlink to a file. */ #include "toys.h" void link_main(void) { - if (link(toys.optargs[0], toys.optargs[1])) - perror_exit("couldn't link '%s' to '%s'", toys.optargs[1], - toys.optargs[0]); + if (link(toys.optargs[0], toys.optargs[1])) + perror_exit("couldn't link '%s' to '%s'", toys.optargs[1], + toys.optargs[0]); } diff --git a/toys/posix/ln.c b/toys/posix/ln.c index a83df7f6..bde77269 100644 --- a/toys/posix/ln.c +++ b/toys/posix/ln.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * ln.c - Create filesystem links +/* ln.c - Create filesystem links * * Copyright 2012 Andre Renaud * @@ -9,17 +7,17 @@ USE_LN(NEWTOY(ln, "<1nfs", TOYFLAG_BIN)) config LN - bool "ln" - default y - help - usage: ln [-sf] [FROM...] TO + bool "ln" + default y + help + usage: ln [-sf] [FROM...] TO - Create a link between FROM and TO. - With only one argument, create link in current directory. + Create a link between FROM and TO. + With only one argument, create link in current directory. - -s Create a symbolic link - -f Force the creation of the link, even if TO already exists - -n Symlink at destination treated as file + -s Create a symbolic link + -f Force the creation of the link, even if TO already exists + -n Symlink at destination treated as file */ #define FOR_ln @@ -27,41 +25,41 @@ config LN void ln_main(void) { - char *dest = toys.optargs[--toys.optc], *new; - struct stat buf; - int i; + char *dest = toys.optargs[--toys.optc], *new; + struct stat buf; + int i; - // With one argument, create link in current directory. - if (!toys.optc) { - toys.optc++; - dest="."; - } + // With one argument, create link in current directory. + if (!toys.optc) { + toys.optc++; + dest="."; + } - // Is destination a directory? - if (((toys.optflags&FLAG_n) ? lstat : stat)(dest, &buf) - || !S_ISDIR(buf.st_mode)) - { - if (toys.optc>1) error_exit("'%s' not a directory"); - buf.st_mode = 0; - } + // Is destination a directory? + if (((toys.optflags&FLAG_n) ? lstat : stat)(dest, &buf) + || !S_ISDIR(buf.st_mode)) + { + if (toys.optc>1) error_exit("'%s' not a directory"); + buf.st_mode = 0; + } - for (i=0; i * @@ -9,19 +7,19 @@ USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_BIN)) config LOGNAME - bool "logname" - default y - help - usage: logname + bool "logname" + default y + help + usage: logname - Prints the calling user's name or an error when this cannot be - determined. + Prints the calling user's name or an error when this cannot be + determined. */ #include "toys.h" void logname_main(void) { - if (getlogin_r(toybuf, sizeof(toybuf))) error_exit("no login name"); - xputs(toybuf); + if (getlogin_r(toybuf, sizeof(toybuf))) error_exit("no login name"); + xputs(toybuf); } diff --git a/toys/posix/ls.c b/toys/posix/ls.c index 6492fb9e..201c7e24 100644 --- a/toys/posix/ls.c +++ b/toys/posix/ls.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * ls.c - list files +/* ls.c - list files * * Copyright 2012 Andre Renaud * Copyright 2012 Rob Landley @@ -11,43 +9,43 @@ USE_LS(NEWTOY(ls, "goACFHLRSacdfiklmnpqrstux1", TOYFLAG_BIN)) config LS - bool "ls" - default y - help - usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...] - list files - - what to show: - -a all files including .hidden - -c use ctime for timestamps - -d directory, not contents - -i inode number - -k block sizes in kilobytes - -p put a '/' after directory names - -q unprintable chars as '?' - -s size (in blocks) - -u use access time for timestamps - -A list all files except . and .. - -H follow command line symlinks - -L follow symlinks - -R recursively list files in subdirectories - -F append file type indicator (/=dir, *=exe, @=symlink, |=FIFO) - - output formats: - -1 list one file per line - -C columns (sorted vertically) - -g like -l but no owner - -l long (show full details for each file) - -m comma separated - -n like -l but numeric uid/gid - -o like -l but no group - -x columns (sorted horizontally) - - sorting (default is alphabetical): - -f unsorted - -r reverse - -t timestamp - -S size + bool "ls" + default y + help + usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...] + list files + + what to show: + -a all files including .hidden + -c use ctime for timestamps + -d directory, not contents + -i inode number + -k block sizes in kilobytes + -p put a '/' after directory names + -q unprintable chars as '?' + -s size (in blocks) + -u use access time for timestamps + -A list all files except . and .. + -H follow command line symlinks + -L follow symlinks + -R recursively list files in subdirectories + -F append file type indicator (/=dir, *=exe, @=symlink, |=FIFO) + + output formats: + -1 list one file per line + -C columns (sorted vertically) + -g like -l but no owner + -l long (show full details for each file) + -m comma separated + -n like -l but numeric uid/gid + -o like -l but no group + -x columns (sorted horizontally) + + sorting (default is alphabetical): + -f unsorted + -r reverse + -t timestamp + -S size */ #define FOR_ls @@ -58,156 +56,156 @@ config LS // ls -lR starts .: then ./subdir: GLOBALS( - struct dirtree *files; + struct dirtree *files; - unsigned screen_width; - int nl_title; + unsigned screen_width; + int nl_title; - // group and user can make overlapping use of the utoa() buf, so move it - char uid_buf[12]; + // group and user can make overlapping use of the utoa() buf, so move it + char uid_buf[12]; ) void dlist_to_dirtree(struct dirtree *parent) { - // Turn double_list into dirtree - struct dirtree *dt = parent->child; - if (dt) { - dt->parent->next = NULL; - while (dt) { - dt->parent = parent; - dt = dt->next; - } + // Turn double_list into dirtree + struct dirtree *dt = parent->child; + if (dt) { + dt->parent->next = NULL; + while (dt) { + dt->parent = parent; + dt = dt->next; } + } } static char endtype(struct stat *st) { - mode_t mode = st->st_mode; - if ((toys.optflags&(FLAG_F|FLAG_p)) && S_ISDIR(mode)) return '/'; - if (toys.optflags & FLAG_F) { - if (S_ISLNK(mode)) return '@'; - if (S_ISREG(mode) && (mode&0111)) return '*'; - if (S_ISFIFO(mode)) return '|'; - if (S_ISSOCK(mode)) return '='; - } - return 0; + mode_t mode = st->st_mode; + if ((toys.optflags&(FLAG_F|FLAG_p)) && S_ISDIR(mode)) return '/'; + if (toys.optflags & FLAG_F) { + if (S_ISLNK(mode)) return '@'; + if (S_ISREG(mode) && (mode&0111)) return '*'; + if (S_ISFIFO(mode)) return '|'; + if (S_ISSOCK(mode)) return '='; + } + return 0; } static char *getusername(uid_t uid) { - struct passwd *pw = getpwuid(uid); - utoa_to_buf(uid, TT.uid_buf, 12); - return pw ? pw->pw_name : TT.uid_buf; + struct passwd *pw = getpwuid(uid); + utoa_to_buf(uid, TT.uid_buf, 12); + return pw ? pw->pw_name : TT.uid_buf; } static char *getgroupname(gid_t gid) { - struct group *gr = getgrgid(gid); - return gr ? gr->gr_name : utoa(gid); + struct group *gr = getgrgid(gid); + return gr ? gr->gr_name : utoa(gid); } // Figure out size of printable entry fields for display indent/wrap static void entrylen(struct dirtree *dt, unsigned *len) { - struct stat *st = &(dt->st); - unsigned flags = toys.optflags; - - *len = strlen(dt->name); - if (endtype(st)) ++*len; - if (flags & FLAG_m) ++*len; - - if (flags & FLAG_i) *len += (len[1] = numlen(st->st_ino)); - if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { - unsigned fn = flags & FLAG_n; - len[2] = numlen(st->st_nlink); - len[3] = strlen(fn ? utoa(st->st_uid) : getusername(st->st_uid)); - len[4] = strlen(fn ? utoa(st->st_gid) : getgroupname(st->st_gid)); - len[5] = numlen(st->st_size); - } - if (flags & FLAG_s) *len += (len[6] = numlen(st->st_blocks)); + struct stat *st = &(dt->st); + unsigned flags = toys.optflags; + + *len = strlen(dt->name); + if (endtype(st)) ++*len; + if (flags & FLAG_m) ++*len; + + if (flags & FLAG_i) *len += (len[1] = numlen(st->st_ino)); + if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { + unsigned fn = flags & FLAG_n; + len[2] = numlen(st->st_nlink); + len[3] = strlen(fn ? utoa(st->st_uid) : getusername(st->st_uid)); + len[4] = strlen(fn ? utoa(st->st_gid) : getgroupname(st->st_gid)); + len[5] = numlen(st->st_size); + } + if (flags & FLAG_s) *len += (len[6] = numlen(st->st_blocks)); } static int compare(void *a, void *b) { - struct dirtree *dta = *(struct dirtree **)a; - struct dirtree *dtb = *(struct dirtree **)b; - int ret = 0, reverse = (toys.optflags & FLAG_r) ? -1 : 1; - - if (toys.optflags & FLAG_S) { - if (dta->st.st_size > dtb->st.st_size) ret = -1; - else if (dta->st.st_size < dtb->st.st_size) ret = 1; - } - if (toys.optflags & FLAG_t) { - if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1; - else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1; - } - if (!ret) ret = strcmp(dta->name, dtb->name); - return ret * reverse; + struct dirtree *dta = *(struct dirtree **)a; + struct dirtree *dtb = *(struct dirtree **)b; + int ret = 0, reverse = (toys.optflags & FLAG_r) ? -1 : 1; + + if (toys.optflags & FLAG_S) { + if (dta->st.st_size > dtb->st.st_size) ret = -1; + else if (dta->st.st_size < dtb->st.st_size) ret = 1; + } + if (toys.optflags & FLAG_t) { + if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1; + else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1; + } + if (!ret) ret = strcmp(dta->name, dtb->name); + return ret * reverse; } // callback from dirtree_recurse() determining how to handle this entry. static int filter(struct dirtree *new) { - int flags = toys.optflags; + int flags = toys.optflags; - // Special case to handle enormous dirs without running out of memory. - if (flags == (FLAG_1|FLAG_f)) { - xprintf("%s\n", new->name); - return 0; - } + // Special case to handle enormous dirs without running out of memory. + if (flags == (FLAG_1|FLAG_f)) { + xprintf("%s\n", new->name); + return 0; + } - if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime; - if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime; - if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2; + if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime; + if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime; + if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2; - if (flags & (FLAG_a|FLAG_f)) return DIRTREE_SAVE; - if (!(flags & FLAG_A) && new->name[0]=='.') return 0; + if (flags & (FLAG_a|FLAG_f)) return DIRTREE_SAVE; + if (!(flags & FLAG_A) && new->name[0]=='.') return 0; - return dirtree_notdotdot(new) & DIRTREE_SAVE; + return dirtree_notdotdot(new) & DIRTREE_SAVE; } // For column view, calculate horizontal position (for padding) and return // index of next entry to display. static unsigned long next_column(unsigned long ul, unsigned long dtlen, - unsigned columns, unsigned *xpos) + unsigned columns, unsigned *xpos) { - unsigned long transition; - unsigned height, widecols; + unsigned long transition; + unsigned height, widecols; - // Horizontal sort is easy - if (!(toys.optflags & FLAG_C)) { - *xpos = ul % columns; - return ul; - } + // Horizontal sort is easy + if (!(toys.optflags & FLAG_C)) { + *xpos = ul % columns; + return ul; + } - // vertical sort + // vertical sort - // For -x, calculate height of display, rounded up - height = (dtlen+columns-1)/columns; + // For -x, calculate height of display, rounded up + height = (dtlen+columns-1)/columns; - // Sanity check: does wrapping render this column count impossible - // due to the right edge wrapping eating a whole row? - if (height*columns - dtlen >= height) { - *xpos = columns; - return 0; - } + // Sanity check: does wrapping render this column count impossible + // due to the right edge wrapping eating a whole row? + if (height*columns - dtlen >= height) { + *xpos = columns; + return 0; + } - // Uneven rounding goes along right edge - widecols = dtlen % height; - if (!widecols) widecols = height; - transition = widecols * columns; - if (ul < transition) { - *xpos = ul % columns; - return (*xpos*height) + (ul/columns); - } + // Uneven rounding goes along right edge + widecols = dtlen % height; + if (!widecols) widecols = height; + transition = widecols * columns; + if (ul < transition) { + *xpos = ul % columns; + return (*xpos*height) + (ul/columns); + } - ul -= transition; - *xpos = ul % (columns-1); + ul -= transition; + *xpos = ul % (columns-1); - return (*xpos*height) + widecols + (ul/(columns-1)); + return (*xpos*height) + widecols + (ul/(columns-1)); } // Display a list of dirtree entries, according to current format @@ -215,250 +213,247 @@ static unsigned long next_column(unsigned long ul, unsigned long dtlen, static void listfiles(int dirfd, struct dirtree *indir) { - struct dirtree *dt, **sort = 0; - unsigned long dtlen = 0, ul = 0; - unsigned width, flags = toys.optflags, totals[7], len[7], - *colsizes = (unsigned *)(toybuf+260), columns = (sizeof(toybuf)-260)/4; - - memset(totals, 0, sizeof(totals)); - - // Silently descend into single directory listed by itself on command line. - // In this case only show dirname/total header when given -R. - if (!indir->parent) { - if (!(dt = indir->child)) return; - if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) { - dt->extra = 1; - listfiles(open(dt->name, 0), dt); - return; - } - } else { - // Read directory contents. We dup() the fd because this will close it. - indir->data = dup(dirfd); - dirtree_recurse(indir, filter, (flags&FLAG_L)); + struct dirtree *dt, **sort = 0; + unsigned long dtlen = 0, ul = 0; + unsigned width, flags = toys.optflags, totals[7], len[7], + *colsizes = (unsigned *)(toybuf+260), columns = (sizeof(toybuf)-260)/4; + + memset(totals, 0, sizeof(totals)); + + // Silently descend into single directory listed by itself on command line. + // In this case only show dirname/total header when given -R. + if (!indir->parent) { + if (!(dt = indir->child)) return; + if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) { + dt->extra = 1; + listfiles(open(dt->name, 0), dt); + return; } - - // Copy linked list to array and sort it. Directories go in array because - // we visit them in sorted order. - - for (;;) { - for (dt = indir->child; dt; dt = dt->next) { - if (sort) sort[dtlen] = dt; - dtlen++; + } else { + // Read directory contents. We dup() the fd because this will close it. + indir->data = dup(dirfd); + dirtree_recurse(indir, filter, (flags&FLAG_L)); + } + + // Copy linked list to array and sort it. Directories go in array because + // we visit them in sorted order. + + for (;;) { + for (dt = indir->child; dt; dt = dt->next) { + if (sort) sort[dtlen] = dt; + dtlen++; + } + if (sort) break; + sort = xmalloc(dtlen * sizeof(void *)); + dtlen = 0; + continue; + } + + // Label directory if not top of tree, or if -R + if (indir->parent && (!indir->extra || (flags & FLAG_R))) + { + char *path = dirtree_path(indir, 0); + + if (TT.nl_title++) xputc('\n'); + xprintf("%s:\n", path); + free(path); + } + + if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare); + + // Find largest entry in each field for display alignment + if (flags & (FLAG_C|FLAG_x)) { + + // columns can't be more than toybuf can hold, or more than files, + // or > 1/2 screen width (one char filename, one space). + if (columns > TT.screen_width/2) columns = TT.screen_width/2; + if (columns > dtlen) columns = dtlen; + + // Try to fit as many columns as we can, dropping down by one each time + for (;columns > 1; columns--) { + unsigned c, totlen = columns; + + memset(colsizes, 0, columns*sizeof(unsigned)); + for (ul=0; ul colsizes[c]) { + totlen += *len-colsizes[c]; + colsizes[c] = *len; + if (totlen > TT.screen_width) break; } - if (sort) break; - sort = xmalloc(dtlen * sizeof(void *)); - dtlen = 0; - continue; + } + // If it fit, stop here + if (ul == dtlen) break; } + } else if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) { + unsigned long blocks = 0; - // Label directory if not top of tree, or if -R - if (indir->parent && (!indir->extra || (flags & FLAG_R))) + for (ul = 0; ul totals[width]) totals[width] = len[width]; + blocks += sort[ul]->st.st_blocks; } - if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare); + if (indir->parent) xprintf("total %lu\n", blocks); + } - // Find largest entry in each field for display alignment - if (flags & (FLAG_C|FLAG_x)) { + // Loop through again to produce output. + memset(toybuf, ' ', 256); + width = 0; + for (ul = 0; ulst); + mode_t mode = st->st_mode; + char et = endtype(st); + + // Skip directories at the top of the tree when -d isn't set + if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue; + TT.nl_title=1; + + // Handle padding and wrapping for display purposes + entrylen(sort[next], len); + if (ul) { + if (flags & FLAG_m) xputc(','); + if (flags & (FLAG_C|FLAG_x)) { + if (!curcol) xputc('\n'); + } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) { + xputc('\n'); + width = 0; + } else { + xputc(' '); + width++; + } + } + width += *len; - // columns can't be more than toybuf can hold, or more than files, - // or > 1/2 screen width (one char filename, one space). - if (columns > TT.screen_width/2) columns = TT.screen_width/2; - if (columns > dtlen) columns = dtlen; - - // Try to fit as many columns as we can, dropping down by one each time - for (;columns > 1; columns--) { - unsigned c, totlen = columns; - - memset(colsizes, 0, columns*sizeof(unsigned)); - for (ul=0; ul colsizes[c]) { - totlen += *len-colsizes[c]; - colsizes[c] = *len; - if (totlen > TT.screen_width) break; - } - } - // If it fit, stop here - if (ul == dtlen) break; - } - } else if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) { - unsigned long blocks = 0; - - for (ul = 0; ul totals[width]) totals[width] = len[width]; - blocks += sort[ul]->st.st_blocks; - } + if (flags & FLAG_i) xprintf("% *lu ", len[1], (unsigned long)st->st_ino); + if (flags & FLAG_s) xprintf("% *lu ", len[6], (unsigned long)st->st_blocks); - if (indir->parent) xprintf("total %lu\n", blocks); + if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { + struct tm *tm; + char perm[11], thyme[64], c, d, *usr, *upad, *grp, *grpad; + int i, bit; + + perm[10]=0; + for (i=0; i<9; i++) { + bit = mode & (1<st_mtime)); + strftime(thyme, sizeof(thyme), "%F %H:%M", tm); + + if (flags&FLAG_o) grp = grpad = toybuf+256; + else { + grp = (flags&FLAG_n) ? utoa(st->st_gid) : getgroupname(st->st_gid); + grpad = toybuf+256-(totals[4]-len[4]); + } + + if (flags&FLAG_g) usr = upad = toybuf+256; + else { + upad = toybuf+255-(totals[3]-len[3]); + if (flags&FLAG_n) { + usr = TT.uid_buf; + utoa_to_buf(st->st_uid, TT.uid_buf, 12); + } else usr = getusername(st->st_uid); + } + + // Coerce the st types into something we know we can print. + xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1, + (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1, + (int64_t)st->st_size, thyme); } - // Loop through again to produce output. - memset(toybuf, ' ', 256); - width = 0; - for (ul = 0; ulst); - mode_t mode = st->st_mode; - char et = endtype(st); - - // Skip directories at the top of the tree when -d isn't set - if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue; - TT.nl_title=1; - - // Handle padding and wrapping for display purposes - entrylen(sort[next], len); - if (ul) { - if (flags & FLAG_m) xputc(','); - if (flags & (FLAG_C|FLAG_x)) { - if (!curcol) xputc('\n'); - } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) { - xputc('\n'); - width = 0; - } else { - xputc(' '); - width++; - } - } - width += *len; - - if (flags & FLAG_i) - xprintf("% *lu ", len[1], (unsigned long)st->st_ino); - if (flags & FLAG_s) - xprintf("% *lu ", len[6], (unsigned long)st->st_blocks); - - if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { - struct tm *tm; - char perm[11], thyme[64], c, d, *usr, *upad, *grp, *grpad; - int i, bit; - - perm[10]=0; - for (i=0; i<9; i++) { - bit = mode & (1<st_mtime)); - strftime(thyme, sizeof(thyme), "%F %H:%M", tm); - - if (flags&FLAG_o) grp = grpad = toybuf+256; - else { - grp = (flags&FLAG_n) ? utoa(st->st_gid) - : getgroupname(st->st_gid); - grpad = toybuf+256-(totals[4]-len[4]); - } - - if (flags&FLAG_g) usr = upad = toybuf+256; - else { - upad = toybuf+255-(totals[3]-len[3]); - if (flags&FLAG_n) { - usr = TT.uid_buf; - utoa_to_buf(st->st_uid, TT.uid_buf, 12); - } else usr = getusername(st->st_uid); - } - - // Coerce the st types into something we know we can print. - xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1, - (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1, - (int64_t)st->st_size, thyme); - } + if (flags & FLAG_q) { + char *p; + for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?'); + } else xprintf("%s", sort[next]->name); + if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) + xprintf(" -> %s", sort[next]->symlink); - if (flags & FLAG_q) { - char *p; - for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?'); - } else xprintf("%s", sort[next]->name); - if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) - xprintf(" -> %s", sort[next]->symlink); + if (et) xputc(et); - if (et) xputc(et); - - // Pad columns - if (flags & (FLAG_C|FLAG_x)) { - curcol = colsizes[curcol] - *len; - if (curcol >= 0) xprintf("%s", toybuf+255-curcol); - } + // Pad columns + if (flags & (FLAG_C|FLAG_x)) { + curcol = colsizes[curcol] - *len; + if (curcol >= 0) xprintf("%s", toybuf+255-curcol); } + } - if (width) xputc('\n'); + if (width) xputc('\n'); - // Free directory entries, recursing first if necessary. + // Free directory entries, recursing first if necessary. - for (ul = 0; ulst.st_mode) - || !dirtree_notdotdot(sort[ul])) continue; + for (ul = 0; ulst.st_mode) + || !dirtree_notdotdot(sort[ul])) continue; - // Recurse into dirs if at top of the tree or given -R - if (!indir->parent || (flags & FLAG_R)) - listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); - } - free(sort); - if (dirfd != AT_FDCWD) close(indir->data); + // Recurse into dirs if at top of the tree or given -R + if (!indir->parent || (flags & FLAG_R)) + listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); + } + free(sort); + if (dirfd != AT_FDCWD) close(indir->data); } void ls_main(void) { - char **s, *noargs[] = {".", 0}; - struct dirtree *dt; - - // Do we have an implied -1 - if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g))) - toys.optflags |= FLAG_1; - else { - TT.screen_width = 80; - terminal_size(&TT.screen_width, NULL); + char **s, *noargs[] = {".", 0}; + struct dirtree *dt; + + // Do we have an implied -1 + if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g))) + toys.optflags |= FLAG_1; + else { + TT.screen_width = 80; + terminal_size(&TT.screen_width, NULL); + } + // The optflags parsing infrastructure should really do this for us, + // but currently it has "switch off when this is set", so "-dR" and "-Rd" + // behave differently + if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; + + // Iterate through command line arguments, collecting directories and files. + // Non-absolute paths are relative to current directory. + TT.files = dirtree_add_node(0, 0, 0); + for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { + dt = dirtree_add_node(AT_FDCWD, *s, + (toys.optflags & (FLAG_L|FLAG_H|FLAG_l))^FLAG_l); + + if (!dt) { + toys.exitval = 1; + continue; } - // The optflags parsing infrastructure should really do this for us, - // but currently it has "switch off when this is set", so "-dR" and "-Rd" - // behave differently - if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; - - // Iterate through command line arguments, collecting directories and files. - // Non-absolute paths are relative to current directory. - TT.files = dirtree_add_node(0, 0, 0); - for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { - dt = dirtree_add_node(AT_FDCWD, *s, - (toys.optflags & (FLAG_L|FLAG_H|FLAG_l))^FLAG_l); - - if (!dt) { - toys.exitval = 1; - continue; - } - // Typecast means double_list->prev temporarirly goes in dirtree->parent - dlist_add_nomalloc((struct double_list **)&TT.files->child, - (struct double_list *)dt); - } + // Typecast means double_list->prev temporarirly goes in dirtree->parent + dlist_add_nomalloc((struct double_list **)&TT.files->child, + (struct double_list *)dt); + } - // Turn double_list into dirtree - dlist_to_dirtree(TT.files); + // Turn double_list into dirtree + dlist_to_dirtree(TT.files); - // Display the files we collected - listfiles(AT_FDCWD, TT.files); + // Display the files we collected + listfiles(AT_FDCWD, TT.files); - if (CFG_TOYBOX_FREE) free(TT.files); + if (CFG_TOYBOX_FREE) free(TT.files); } diff --git a/toys/posix/mkdir.c b/toys/posix/mkdir.c index e4e591d7..33fb8326 100644 --- a/toys/posix/mkdir.c +++ b/toys/posix/mkdir.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mkdir.c - Make directories +/* mkdir.c - Make directories * * Copyright 2012 Georgi Chorbadzhiyski * @@ -11,65 +9,65 @@ USE_MKDIR(NEWTOY(mkdir, "<1p", TOYFLAG_BIN)) config MKDIR - bool "mkdir" - default y - help - usage: mkdir [-p] [dirname...] - Create one or more directories. + bool "mkdir" + default y + help + usage: mkdir [-p] [dirname...] + Create one or more directories. - -p make parent directories as needed. + -p make parent directories as needed. */ #define FOR_mkdir #include "toys.h" GLOBALS( - long mode; + long mode; ) static int do_mkdir(char *dir) { - struct stat buf; - char *s; + struct stat buf; + char *s; - // mkdir -p one/two/three is not an error if the path already exists, - // but is if "three" is a file. The others we dereference and catch - // not-a-directory along the way, but the last one we must explicitly - // test for. Might as well do it up front. + // mkdir -p one/two/three is not an error if the path already exists, + // but is if "three" is a file. The others we dereference and catch + // not-a-directory along the way, but the last one we must explicitly + // test for. Might as well do it up front. - if (!stat(dir, &buf) && !S_ISDIR(buf.st_mode)) { - errno = EEXIST; - return 1; - } + if (!stat(dir, &buf) && !S_ISDIR(buf.st_mode)) { + errno = EEXIST; + return 1; + } - for (s=dir; ; s++) { - char save=0; + for (s=dir; ; s++) { + char save=0; - // Skip leading / of absolute paths. - if (s!=dir && *s == '/' && toys.optflags) { - save = *s; - *s = 0; - } else if (*s) continue; + // Skip leading / of absolute paths. + if (s!=dir && *s == '/' && toys.optflags) { + save = *s; + *s = 0; + } else if (*s) continue; - if (mkdir(dir, TT.mode)<0 && (!toys.optflags || errno != EEXIST)) - return 1; + if (mkdir(dir, TT.mode)<0 && (!toys.optflags || errno != EEXIST)) + return 1; - if (!(*s = save)) break; - } + if (!(*s = save)) break; + } - return 0; + return 0; } void mkdir_main(void) { - char **s; + char **s; - TT.mode = 0777; + TT.mode = 0777; - for (s=toys.optargs; *s; s++) { - if (do_mkdir(*s)) { - perror_msg("cannot create directory '%s'", *s); - toys.exitval = 1; - } - } + for (s=toys.optargs; *s; s++) { + if (do_mkdir(*s)) { + perror_msg("cannot create directory '%s'", *s); + toys.exitval = 1; + } + } } diff --git a/toys/posix/mkfifo.c b/toys/posix/mkfifo.c index 44775788..44fbc994 100644 --- a/toys/posix/mkfifo.c +++ b/toys/posix/mkfifo.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * mkfifo.c - Create FIFOs (named pipes) +/* mkfifo.c - Create FIFOs (named pipes) * * Copyright 2012 Georgi Chorbadzhiyski * @@ -11,35 +9,35 @@ USE_MKFIFO(NEWTOY(mkfifo, "<1m:", TOYFLAG_BIN)) config MKFIFO - bool "mkfifo" - default y - help - usage: mkfifo [fifo_name...] + bool "mkfifo" + default y + help + usage: mkfifo [fifo_name...] - Create FIFOs (named pipes). + Create FIFOs (named pipes). */ #define FOR_mkfifo #include "toys.h" GLOBALS( - char *m_string; - mode_t mode; + char *m_string; + mode_t mode; ) void mkfifo_main(void) { - char **s; - - TT.mode = 0666; - if (toys.optflags & FLAG_m) { - TT.mode = string_to_mode(TT.m_string, 0); - } - - for (s = toys.optargs; *s; s++) { - if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) { - perror_msg("cannot create fifo '%s'", *s); - toys.exitval = 1; - } - } + char **s; + + TT.mode = 0666; + if (toys.optflags & FLAG_m) { + TT.mode = string_to_mode(TT.m_string, 0); + } + + for (s = toys.optargs; *s; s++) { + if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) { + perror_msg("cannot create fifo '%s'", *s); + toys.exitval = 1; + } + } } diff --git a/toys/posix/nice.c b/toys/posix/nice.c index d45429f8..4b587ee6 100644 --- a/toys/posix/nice.c +++ b/toys/posix/nice.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * nice.c - Run a program at a different niceness level. +/* nice.c - Run a program at a different niceness level. * * Copyright 2010 Rob Landley * @@ -9,32 +7,32 @@ USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_USR|TOYFLAG_BIN)) config NICE - bool "nice" - default y - help - usage: nice [-n PRIORITY] command [args...] + bool "nice" + default y + help + usage: nice [-n PRIORITY] command [args...] - Run a command line at an increased or decreased scheduling priority. + Run a command line at an increased or decreased scheduling priority. - Higher numbers make a program yield more CPU time, from -20 (highest - priority) to 19 (lowest). By default processes inherit their parent's - niceness (usually 0). By default this command adds 10 to the parent's - priority. Only root can set a negative niceness level. + Higher numbers make a program yield more CPU time, from -20 (highest + priority) to 19 (lowest). By default processes inherit their parent's + niceness (usually 0). By default this command adds 10 to the parent's + priority. Only root can set a negative niceness level. */ #define FOR_nice #include "toys.h" GLOBALS( - long priority; + long priority; ) void nice_main(void) { - if (!toys.optflags) TT.priority = 10; + if (!toys.optflags) TT.priority = 10; - errno = 0; - if (nice(TT.priority)==-1 && errno) perror_exit("Can't set priority"); + errno = 0; + if (nice(TT.priority)==-1 && errno) perror_exit("Can't set priority"); - xexec(toys.optargs); + xexec(toys.optargs); } diff --git a/toys/posix/nohup.c b/toys/posix/nohup.c index e11fb094..b936a093 100644 --- a/toys/posix/nohup.c +++ b/toys/posix/nohup.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * nohup.c - run commandline with SIGHUP blocked. +/* nohup.c - run commandline with SIGHUP blocked. * * Copyright 2011 Rob Landley * @@ -9,34 +7,34 @@ USE_NOHUP(NEWTOY(nohup, "<1", TOYFLAG_USR|TOYFLAG_BIN)) config NOHUP - bool "nohup" - default y - help - usage: nohup COMMAND [ARGS...] + bool "nohup" + default y + help + usage: nohup COMMAND [ARGS...] - Run a command that survives the end of its terminal. - If stdin is a tty, redirect from /dev/null - If stdout is a tty, redirect to file "nohup.out" + Run a command that survives the end of its terminal. + If stdin is a tty, redirect from /dev/null + If stdout is a tty, redirect to file "nohup.out" */ #include "toys.h" void nohup_main(void) { - signal(SIGHUP, SIG_IGN); - if (isatty(1)) { - close(1); - if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY, - S_IRUSR|S_IWUSR )) - { - char *temp = getenv("HOME"); - temp = xmsprintf("%s/%s", temp ? temp : "", "nohup.out"); - xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, S_IRUSR|S_IWUSR); - } - } - if (isatty(0)) { - close(0); - open("/dev/null", O_RDONLY); - } - xexec(toys.optargs); + signal(SIGHUP, SIG_IGN); + if (isatty(1)) { + close(1); + if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY, + S_IRUSR|S_IWUSR )) + { + char *temp = getenv("HOME"); + temp = xmsprintf("%s/%s", temp ? temp : "", "nohup.out"); + xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, S_IRUSR|S_IWUSR); + } + } + if (isatty(0)) { + close(0); + open("/dev/null", O_RDONLY); + } + xexec(toys.optargs); } diff --git a/toys/posix/od.c b/toys/posix/od.c index ef420b87..948a99e1 100644 --- a/toys/posix/od.c +++ b/toys/posix/od.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * od.c - Provide octal/hex dumps of data +/* od.c - Provide octal/hex dumps of data * * Copyright 2012 Andre Renaud * Copyright 2012 Rob Landley @@ -10,253 +8,253 @@ USE_OD(NEWTOY(od, "j#vN#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN)) config OD - bool "od" - default y - help - usage: od [-bdosxv] [-j #] [-N #] [-A doxn] [-t arg] + bool "od" + default y + help + usage: od [-bdosxv] [-j #] [-N #] [-A doxn] [-t arg] - -A Address base (decimal, octal, hexdecimal, none) - -t output type(s) a (ascii) c (char) d (decimal) foux + -A Address base (decimal, octal, hexdecimal, none) + -t output type(s) a (ascii) c (char) d (decimal) foux */ #define FOR_od #include "toys.h" GLOBALS( - struct arg_list *output_base; - char *address_base; - long max_count; - long jump_bytes; - - unsigned types, leftover, star, address_idx; - char *buf; - uint64_t bufs[4]; // force 64-bit alignment - off_t pos; + struct arg_list *output_base; + char *address_base; + long max_count; + long jump_bytes; + + unsigned types, leftover, star, address_idx; + char *buf; + uint64_t bufs[4]; // force 64-bit alignment + off_t pos; ) static char *ascii = "nulsohstxetxeotenqackbel bs ht nl vt ff cr so si" - "dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp"; + "dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp"; struct odtype { - int type; - int size; + int type; + int size; }; static void od_outline(void) { - unsigned flags = toys.optflags; - char *abases[] = {"", "%07d", "%07o", "%06x"}; - struct odtype *types = (struct odtype *)toybuf, *t; - int i, len; - - if (TT.leftover<16) memset(TT.buf+TT.leftover, 0, 16-TT.leftover); - - // Handle duplciate lines as * - if (!(flags&FLAG_v) && TT.jump_bytes != TT.pos && TT.leftover - && !memcmp(TT.bufs, TT.bufs + 2, 16)) - { - if (!TT.star) { - xputs("*"); - TT.star++; - } - - // Print line position - } else { - TT.star = 0; - - xprintf(abases[TT.address_idx], TT.pos); - if (!TT.leftover) { - if (TT.address_idx) xputc('\n'); - return; - } - } - - TT.pos += len = TT.leftover; - TT.leftover = 0; - if (TT.star) return; - - // For each output type, print one line - - for (i=0; itype < 2) { - char c = TT.buf[j++]; - pad += 4; - - if (!t->type) { - c &= 127; - if (c<=32) sprintf(buf, "%.3s", ascii+(3*c)); - else if (c==127) strcpy(buf, "del"); - else sprintf(buf, "%c", c); - } else { - char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c); - if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]); - else if (c < 32 || c >= 127) sprintf(buf, "%03o", c); - else { - // TODO: this should be UTF8 aware. - sprintf(buf, "%c", c); - } - } - } else if (CFG_TOYBOX_FLOAT && t->type == 6) { - long double ld; - union {float f; double d; long double ld;} fdl; - - memcpy(&fdl, TT.buf+j, t->size); - j += t->size; - if (sizeof(float) == t->size) { - ld = fdl.f; - pad += (throw = 8)+7; - } else if (sizeof(double) == t->size) { - ld = fdl.d; - pad += (throw = 17)+8; - } else if (sizeof(long double) == t->size) { - ld = fdl.ld; - pad += (throw = 21)+9; - } else error_exit("bad -tf '%d'", t->size); - - sprintf(buf, "%.*Le", throw, ld); - // Integer types - } else { - unsigned long long ll = 0, or; - char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"}, - *class = c[t->type-2]; - - // Work out width of field - if (t->size == 8) { - or = -1LL; - if (t->type == 2) or >>= 1; - } else or = (1LL<<(8*t->size))-1; - throw = sprintf(buf, class, 0, or); - - // Accumulate integer based on size argument - for (k=0; k < t->size; k++) { - or = TT.buf[j++]; - ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k)); - } - - // Handle negative values - if (t->type == 2) { - or = sizeof(or) - t->size; - throw++; - if (or && (ll & (1l<<((8*t->size)-1)))) - ll |= ((or<<(8*or))-1) << (8*t->size); - } - - sprintf(buf, class, throw, ll); - pad += throw+1; - } - xprintf("%*s", pad, buf); - pad = 0; - } - xputc('\n'); - } - - // buffer toggle for "same as last time" check. - TT.buf = (char *)((TT.buf == (char *)TT.bufs) ? TT.bufs+2 : TT.bufs); + unsigned flags = toys.optflags; + char *abases[] = {"", "%07d", "%07o", "%06x"}; + struct odtype *types = (struct odtype *)toybuf, *t; + int i, len; + + if (TT.leftover<16) memset(TT.buf+TT.leftover, 0, 16-TT.leftover); + + // Handle duplciate lines as * + if (!(flags&FLAG_v) && TT.jump_bytes != TT.pos && TT.leftover + && !memcmp(TT.bufs, TT.bufs + 2, 16)) + { + if (!TT.star) { + xputs("*"); + TT.star++; + } + + // Print line position + } else { + TT.star = 0; + + xprintf(abases[TT.address_idx], TT.pos); + if (!TT.leftover) { + if (TT.address_idx) xputc('\n'); + return; + } + } + + TT.pos += len = TT.leftover; + TT.leftover = 0; + if (TT.star) return; + + // For each output type, print one line + + for (i=0; itype < 2) { + char c = TT.buf[j++]; + pad += 4; + + if (!t->type) { + c &= 127; + if (c<=32) sprintf(buf, "%.3s", ascii+(3*c)); + else if (c==127) strcpy(buf, "del"); + else sprintf(buf, "%c", c); + } else { + char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c); + if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]); + else if (c < 32 || c >= 127) sprintf(buf, "%03o", c); + else { + // TODO: this should be UTF8 aware. + sprintf(buf, "%c", c); + } + } + } else if (CFG_TOYBOX_FLOAT && t->type == 6) { + long double ld; + union {float f; double d; long double ld;} fdl; + + memcpy(&fdl, TT.buf+j, t->size); + j += t->size; + if (sizeof(float) == t->size) { + ld = fdl.f; + pad += (throw = 8)+7; + } else if (sizeof(double) == t->size) { + ld = fdl.d; + pad += (throw = 17)+8; + } else if (sizeof(long double) == t->size) { + ld = fdl.ld; + pad += (throw = 21)+9; + } else error_exit("bad -tf '%d'", t->size); + + sprintf(buf, "%.*Le", throw, ld); + // Integer types + } else { + unsigned long long ll = 0, or; + char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"}, + *class = c[t->type-2]; + + // Work out width of field + if (t->size == 8) { + or = -1LL; + if (t->type == 2) or >>= 1; + } else or = (1LL<<(8*t->size))-1; + throw = sprintf(buf, class, 0, or); + + // Accumulate integer based on size argument + for (k=0; k < t->size; k++) { + or = TT.buf[j++]; + ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k)); + } + + // Handle negative values + if (t->type == 2) { + or = sizeof(or) - t->size; + throw++; + if (or && (ll & (1l<<((8*t->size)-1)))) + ll |= ((or<<(8*or))-1) << (8*t->size); + } + + sprintf(buf, class, throw, ll); + pad += throw+1; + } + xprintf("%*s", pad, buf); + pad = 0; + } + xputc('\n'); + } + + // buffer toggle for "same as last time" check. + TT.buf = (char *)((TT.buf == (char *)TT.bufs) ? TT.bufs+2 : TT.bufs); } static void do_od(int fd, char *name) { - // Skip input, possibly more than one entire file. - if (TT.jump_bytes < TT.pos) { - off_t off = lskip(fd, TT.jump_bytes); - if (off > 0) TT.pos += off; - if (TT.jump_bytes < TT.pos) return; - } - - for(;;) { - char *buf = TT.buf + TT.leftover; - int len = 16 - TT.leftover; - - if (toys.optflags & FLAG_N) { - if (!TT.max_count) break; - if (TT.max_count < len) len = TT.max_count; - } - - len = readall(fd, buf, len); - if (len < 0) { - perror_msg("%s", name); - break; - } - if (TT.max_count) TT.max_count -= len; - TT.leftover += len; - if (TT.leftover < 16) break; - - od_outline(); - } + // Skip input, possibly more than one entire file. + if (TT.jump_bytes < TT.pos) { + off_t off = lskip(fd, TT.jump_bytes); + if (off > 0) TT.pos += off; + if (TT.jump_bytes < TT.pos) return; + } + + for(;;) { + char *buf = TT.buf + TT.leftover; + int len = 16 - TT.leftover; + + if (toys.optflags & FLAG_N) { + if (!TT.max_count) break; + if (TT.max_count < len) len = TT.max_count; + } + + len = readall(fd, buf, len); + if (len < 0) { + perror_msg("%s", name); + break; + } + if (TT.max_count) TT.max_count -= len; + TT.leftover += len; + if (TT.leftover < 16) break; + + od_outline(); + } } static void append_base(char *base) { - char *s = base; - struct odtype *types = (struct odtype *)toybuf; - int type; - - for (;;) { - int size = 1; - - if (!*s) return; - if (TT.types >= sizeof(toybuf)/sizeof(struct odtype)) break; - if (-1 == (type = stridx("acduox"USE_TOYBOX_FLOAT("f"), *(s++)))) break; - - if (isdigit(*s)) { - size = strtol(s, &s, 10); - if (type < 2 && size != 1) break; - if (CFG_TOYBOX_FLOAT && type == 6 && size == sizeof(long double)); - else if (size < 0 || size > 8) break; - } else if (CFG_TOYBOX_FLOAT && type == 6) { - int sizes[] = {sizeof(float), sizeof(double), sizeof(long double)}; - if (-1 == (size = stridx("FDL", *s))) size = sizeof(double); - else { - s++; - size = sizes[size]; - } - } else if (type > 1) { - if (-1 == (size = stridx("CSIL", *s))) size = 4; - else { - s++; - size = 1 << size; - } - } - - types[TT.types].type = type; - types[TT.types].size = size; - TT.types++; - } - - error_exit("bad -t %s", base); + char *s = base; + struct odtype *types = (struct odtype *)toybuf; + int type; + + for (;;) { + int size = 1; + + if (!*s) return; + if (TT.types >= sizeof(toybuf)/sizeof(struct odtype)) break; + if (-1 == (type = stridx("acduox"USE_TOYBOX_FLOAT("f"), *(s++)))) break; + + if (isdigit(*s)) { + size = strtol(s, &s, 10); + if (type < 2 && size != 1) break; + if (CFG_TOYBOX_FLOAT && type == 6 && size == sizeof(long double)); + else if (size < 0 || size > 8) break; + } else if (CFG_TOYBOX_FLOAT && type == 6) { + int sizes[] = {sizeof(float), sizeof(double), sizeof(long double)}; + if (-1 == (size = stridx("FDL", *s))) size = sizeof(double); + else { + s++; + size = sizes[size]; + } + } else if (type > 1) { + if (-1 == (size = stridx("CSIL", *s))) size = 4; + else { + s++; + size = 1 << size; + } + } + + types[TT.types].type = type; + types[TT.types].size = size; + TT.types++; + } + + error_exit("bad -t %s", base); } void od_main(void) { - struct arg_list *arg; + struct arg_list *arg; - TT.buf = (char *)TT.bufs; + TT.buf = (char *)TT.bufs; - if (!TT.address_base) TT.address_idx = 2; - else if (0>(TT.address_idx = stridx("ndox", *TT.address_base))) - error_exit("bad -A '%c'", *TT.address_base); + if (!TT.address_base) TT.address_idx = 2; + else if (0>(TT.address_idx = stridx("ndox", *TT.address_base))) + error_exit("bad -A '%c'", *TT.address_base); - // Collect -t entries + // Collect -t entries - for (arg = TT.output_base; arg; arg = arg->next) append_base(arg->arg); - if (toys.optflags & FLAG_b) append_base("o1"); - if (toys.optflags & FLAG_d) append_base("u2"); - if (toys.optflags & FLAG_o) append_base("o2"); - if (toys.optflags & FLAG_s) append_base("d2"); - if (toys.optflags & FLAG_x) append_base("x2"); - if (!TT.output_base) append_base("o2"); + for (arg = TT.output_base; arg; arg = arg->next) append_base(arg->arg); + if (toys.optflags & FLAG_b) append_base("o1"); + if (toys.optflags & FLAG_d) append_base("u2"); + if (toys.optflags & FLAG_o) append_base("o2"); + if (toys.optflags & FLAG_s) append_base("d2"); + if (toys.optflags & FLAG_x) append_base("x2"); + if (!TT.output_base) append_base("o2"); - loopfiles(toys.optargs, do_od); + loopfiles(toys.optargs, do_od); - if (TT.leftover) od_outline(); - od_outline(); + if (TT.leftover) od_outline(); + od_outline(); } diff --git a/toys/posix/patch.c b/toys/posix/patch.c index 40d7cbcf..12e4b8c3 100644 --- a/toys/posix/patch.c +++ b/toys/posix/patch.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * patch.c - Apply a "universal" diff. +/* patch.c - Apply a "universal" diff. * * Copyright 2007 Rob Landley * @@ -24,39 +22,39 @@ USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"ulp#i:R", TOYFLAG_USR|TOYFLAG_BIN)) config PATCH - bool "patch" - default y - help - usage: patch [-i file] [-p depth] [-Ru] + bool "patch" + default y + help + usage: patch [-i file] [-p depth] [-Ru] - Apply a unified diff to one or more files. + Apply a unified diff to one or more files. - -i Input file (defaults=stdin) - -l Loose match (ignore whitespace) - -p Number of '/' to strip from start of file paths (default=all) - -R Reverse patch. - -u Ignored (only handles "unified" diffs) + -i Input file (defaults=stdin) + -l Loose match (ignore whitespace) + -p Number of '/' to strip from start of file paths (default=all) + -R Reverse patch. + -u Ignored (only handles "unified" diffs) - This version of patch only handles unified diffs, and only modifies - a file when all all hunks to that file apply. Patch prints failed - hunks to stderr, and exits with nonzero status if any hunks fail. + This version of patch only handles unified diffs, and only modifies + a file when all all hunks to that file apply. Patch prints failed + hunks to stderr, and exits with nonzero status if any hunks fail. - A file compared against /dev/null (or with a date <= the epoch) is - created/deleted as appropriate. + A file compared against /dev/null (or with a date <= the epoch) is + created/deleted as appropriate. */ #define FOR_patch #include "toys.h" GLOBALS( - char *infile; - long prefix; - - struct double_list *current_hunk; - long oldline, oldlen, newline, newlen; - long linenum; - int context, state, filein, fileout, filepatch, hunknum; - char *tempname; + char *infile; + long prefix; + + struct double_list *current_hunk; + long oldline, oldlen, newline, newlen; + long linenum; + int context, state, filein, fileout, filepatch, hunknum; + char *tempname; ) // Dispose of a line of input, either by writing it out or discarding it. @@ -70,59 +68,59 @@ GLOBALS( static void do_line(void *data) { - struct double_list *dlist = (struct double_list *)data; + struct double_list *dlist = (struct double_list *)data; - if (TT.state>1 && *dlist->data != TT.state) { - char *s = dlist->data+(TT.state>3 ? 1 : 0); - int i = TT.state == 2 ? 2 : TT.fileout; + if (TT.state>1 && *dlist->data != TT.state) { + char *s = dlist->data+(TT.state>3 ? 1 : 0); + int i = TT.state == 2 ? 2 : TT.fileout; - xwrite(i, s, strlen(s)); - xwrite(i, "\n", 1); - } + xwrite(i, s, strlen(s)); + xwrite(i, "\n", 1); + } - if (PATCH_DEBUG) fprintf(stderr, "DO %d: %s\n", TT.state, dlist->data); + if (PATCH_DEBUG) fprintf(stderr, "DO %d: %s\n", TT.state, dlist->data); - free(dlist->data); - free(data); + free(dlist->data); + free(data); } static void finish_oldfile(void) { - if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); - TT.fileout = TT.filein = -1; + if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); + TT.fileout = TT.filein = -1; } static void fail_hunk(void) { - if (!TT.current_hunk) return; - TT.current_hunk->prev->next = 0; + if (!TT.current_hunk) return; + TT.current_hunk->prev->next = 0; - fprintf(stderr, "Hunk %d FAILED %ld/%ld.\n", - TT.hunknum, TT.oldline, TT.newline); - toys.exitval = 1; + fprintf(stderr, "Hunk %d FAILED %ld/%ld.\n", + TT.hunknum, TT.oldline, TT.newline); + toys.exitval = 1; - // If we got to this point, we've seeked to the end. Discard changes to - // this file and advance to next file. + // If we got to this point, we've seeked to the end. Discard changes to + // this file and advance to next file. - TT.state = 2; - llist_traverse(TT.current_hunk, do_line); - TT.current_hunk = NULL; - delete_tempfile(TT.filein, TT.fileout, &TT.tempname); - TT.state = 0; + TT.state = 2; + llist_traverse(TT.current_hunk, do_line); + TT.current_hunk = NULL; + delete_tempfile(TT.filein, TT.fileout, &TT.tempname); + TT.state = 0; } -// Compare ignoring whitespace. Just returns +// Compare ignoring whitespace. Just returns static int loosecmp(char *aa, char *bb) { - int a = 0, b = 0; - - for (;;) { - while (isspace(aa[a])) a++; - while (isspace(bb[b])) b++; - if (aa[a] != bb[b]) return 1; - if (!aa[a]) return 0; - a++, b++; - } + int a = 0, b = 0; + + for (;;) { + while (isspace(aa[a])) a++; + while (isspace(bb[b])) b++; + if (aa[a] != bb[b]) return 1; + if (!aa[a]) return 0; + a++, b++; + } } // Given a hunk of a unified diff, make the appropriate change to the file. @@ -134,116 +132,114 @@ static int loosecmp(char *aa, char *bb) static int apply_one_hunk(void) { - struct double_list *plist, *buf = NULL, *check; - int matcheof = 0, reverse = toys.optflags & FLAG_R, backwarn = 0; - int (*lcmp)(char *aa, char *bb); - - lcmp = (toys.optflags & FLAG_l) ? (void *)loosecmp : (void *)strcmp; - - // Break doubly linked list so we can use singly linked traversal function. - TT.current_hunk->prev->next = NULL; - - // Match EOF if there aren't as many ending context lines as beginning - for (plist = TT.current_hunk; plist; plist = plist->next) { - if (plist->data[0]==' ') matcheof++; - else matcheof = 0; - if (PATCH_DEBUG) fprintf(stderr, "HUNK:%s\n", plist->data); - } - matcheof = matcheof < TT.context; - - if (PATCH_DEBUG) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N'); - - // Loop through input data searching for this hunk. Match all context - // lines and all lines to be removed until we've found the end of a - // complete hunk. - plist = TT.current_hunk; - buf = NULL; - if (TT.context) for (;;) { - char *data = get_line(TT.filein); - - TT.linenum++; - - // Figure out which line of hunk to compare with next. (Skip lines - // of the hunk we'd be adding.) - while (plist && *plist->data == "+-"[reverse]) { - if (data && !lcmp(data, plist->data+1)) { - if (!backwarn) backwarn = TT.linenum; - } - plist = plist->next; - } - - // Is this EOF? - if (!data) { - if (PATCH_DEBUG) fprintf(stderr, "INEOF\n"); - - // Does this hunk need to match EOF? - if (!plist && matcheof) break; - - if (backwarn) - fprintf(stderr, "Possibly reversed hunk %d at %ld\n", - TT.hunknum, TT.linenum); - - // File ended before we found a place for this hunk. - fail_hunk(); - goto done; - } else if (PATCH_DEBUG) fprintf(stderr, "IN: %s\n", data); - check = dlist_add(&buf, data); - - // Compare this line with next expected line of hunk. - - // A match can fail because the next line doesn't match, or because - // we hit the end of a hunk that needed EOF, and this isn't EOF. - - // If match failed, flush first line of buffered data and - // recheck buffered data for a new match until we find one or run - // out of buffer. - - for (;;) { - if (!plist || lcmp(check->data, plist->data+1)) { - // Match failed. Write out first line of buffered data and - // recheck remaining buffered data for a new match. - - if (PATCH_DEBUG) - fprintf(stderr, "NOT: %s\n", plist->data); - - TT.state = 3; - check = llist_pop(&buf); - check->prev->next = buf; - buf->prev = check->prev; - do_line(check); - plist = TT.current_hunk; - - // If we've reached the end of the buffer without confirming a - // match, read more lines. - if (check==buf) { - buf = 0; - break; - } - check = buf; - } else { - if (PATCH_DEBUG) - fprintf(stderr, "MAYBE: %s\n", plist->data); - // This line matches. Advance plist, detect successful match. - plist = plist->next; - if (!plist && !matcheof) goto out; - check = check->next; - if (check == buf) break; - } - } - } + struct double_list *plist, *buf = NULL, *check; + int matcheof = 0, reverse = toys.optflags & FLAG_R, backwarn = 0; + int (*lcmp)(char *aa, char *bb); + + lcmp = (toys.optflags & FLAG_l) ? (void *)loosecmp : (void *)strcmp; + + // Break doubly linked list so we can use singly linked traversal function. + TT.current_hunk->prev->next = NULL; + + // Match EOF if there aren't as many ending context lines as beginning + for (plist = TT.current_hunk; plist; plist = plist->next) { + if (plist->data[0]==' ') matcheof++; + else matcheof = 0; + if (PATCH_DEBUG) fprintf(stderr, "HUNK:%s\n", plist->data); + } + matcheof = matcheof < TT.context; + + if (PATCH_DEBUG) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N'); + + // Loop through input data searching for this hunk. Match all context + // lines and all lines to be removed until we've found the end of a + // complete hunk. + plist = TT.current_hunk; + buf = NULL; + if (TT.context) for (;;) { + char *data = get_line(TT.filein); + + TT.linenum++; + + // Figure out which line of hunk to compare with next. (Skip lines + // of the hunk we'd be adding.) + while (plist && *plist->data == "+-"[reverse]) { + if (data && !lcmp(data, plist->data+1)) { + if (!backwarn) backwarn = TT.linenum; + } + plist = plist->next; + } + + // Is this EOF? + if (!data) { + if (PATCH_DEBUG) fprintf(stderr, "INEOF\n"); + + // Does this hunk need to match EOF? + if (!plist && matcheof) break; + + if (backwarn) + fprintf(stderr, "Possibly reversed hunk %d at %ld\n", + TT.hunknum, TT.linenum); + + // File ended before we found a place for this hunk. + fail_hunk(); + goto done; + } else if (PATCH_DEBUG) fprintf(stderr, "IN: %s\n", data); + check = dlist_add(&buf, data); + + // Compare this line with next expected line of hunk. + + // A match can fail because the next line doesn't match, or because + // we hit the end of a hunk that needed EOF, and this isn't EOF. + + // If match failed, flush first line of buffered data and + // recheck buffered data for a new match until we find one or run + // out of buffer. + + for (;;) { + if (!plist || lcmp(check->data, plist->data+1)) { + // Match failed. Write out first line of buffered data and + // recheck remaining buffered data for a new match. + + if (PATCH_DEBUG) fprintf(stderr, "NOT: %s\n", plist->data); + + TT.state = 3; + check = llist_pop(&buf); + check->prev->next = buf; + buf->prev = check->prev; + do_line(check); + plist = TT.current_hunk; + + // If we've reached the end of the buffer without confirming a + // match, read more lines. + if (check==buf) { + buf = 0; + break; + } + check = buf; + } else { + if (PATCH_DEBUG) fprintf(stderr, "MAYBE: %s\n", plist->data); + // This line matches. Advance plist, detect successful match. + plist = plist->next; + if (!plist && !matcheof) goto out; + check = check->next; + if (check == buf) break; + } + } + } out: - // We have a match. Emit changed data. - TT.state = "-+"[reverse]; - llist_traverse(TT.current_hunk, do_line); - TT.current_hunk = NULL; - TT.state = 1; + // We have a match. Emit changed data. + TT.state = "-+"[reverse]; + llist_traverse(TT.current_hunk, do_line); + TT.current_hunk = NULL; + TT.state = 1; done: - if (buf) { - buf->prev->next = NULL; - llist_traverse(buf, do_line); - } + if (buf) { + buf->prev->next = NULL; + llist_traverse(buf, do_line); + } - return TT.state; + return TT.state; } // Read a patch file and find hunks, opening/creating/deleting files. @@ -256,172 +252,170 @@ done: void patch_main(void) { - int reverse = toys.optflags&FLAG_R, state = 0, patchlinenum = 0, - strip = 0; - char *oldname = NULL, *newname = NULL; - - if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY); - TT.filein = TT.fileout = -1; - - // Loop through the lines in the patch - for (;;) { - char *patchline; - - patchline = get_line(TT.filepatch); - if (!patchline) break; - - // Other versions of patch accept damaged patches, - // so we need to also. - if (strip || !patchlinenum++) { - int len = strlen(patchline); - if (patchline[len-1] == '\r') { - if (!strip) fprintf(stderr, "Removing DOS newlines\n"); - strip = 1; - patchline[len-1]=0; - } - } - if (!*patchline) { - free(patchline); - patchline = xstrdup(" "); - } - - // Are we assembling a hunk? - if (state >= 2) { - if (*patchline==' ' || *patchline=='+' || *patchline=='-') { - dlist_add(&TT.current_hunk, patchline); - - if (*patchline != '+') TT.oldlen--; - if (*patchline != '-') TT.newlen--; - - // Context line? - if (*patchline==' ' && state==2) TT.context++; - else state=3; - - // If we've consumed all expected hunk lines, apply the hunk. - - if (!TT.oldlen && !TT.newlen) state = apply_one_hunk(); - continue; - } - fail_hunk(); - state = 0; - continue; - } - - // Open a new file? - if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) { - char *s, **name = &oldname; - int i; - - if (*patchline == '+') { - name = &newname; - state = 1; - } - - free(*name); - finish_oldfile(); - - // Trim date from end of filename (if any). We don't care. - for (s = patchline+4; *s && *s!='\t'; s++) - if (*s=='\\' && s[1]) s++; - i = atoi(s); - if (i>1900 && i<=1970) - *name = xstrdup("/dev/null"); - else { - *s = 0; - *name = xstrdup(patchline+4); - } - - // We defer actually opening the file because svn produces broken - // patches that don't signal they want to create a new file the - // way the patch man page says, so you have to read the first hunk - // and _guess_. - - // Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@ - // but a missing ,value means the value is 1. - } else if (state == 1 && !strncmp("@@ -", patchline, 4)) { - int i; - char *s = patchline+4; - - // Read oldline[,oldlen] +newline[,newlen] - - TT.oldlen = TT.newlen = 1; - TT.oldline = strtol(s, &s, 10); - if (*s == ',') TT.oldlen=strtol(s+1, &s, 10); - TT.newline = strtol(s+2, &s, 10); - if (*s == ',') TT.newlen = strtol(s+1, &s, 10); - - TT.context = 0; - state = 2; - - // If this is the first hunk, open the file. - if (TT.filein == -1) { - int oldsum, newsum, del = 0; - char *name; - - oldsum = TT.oldline + TT.oldlen; - newsum = TT.newline + TT.newlen; - - name = reverse ? oldname : newname; - - // We're deleting oldname if new file is /dev/null (before -p) - // or if new hunk is empty (zero context) after patching - if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) - { - name = reverse ? newname : oldname; - del++; - } - - // handle -p path truncation. - for (i = 0, s = name; *s;) { - if ((toys.optflags & FLAG_p) && TT.prefix == i) break; - if (*s++ != '/') continue; - while (*s == '/') s++; - name = s; - i++; - } - - if (del) { - printf("removing %s\n", name); - xunlink(name); - state = 0; - // If we've got a file to open, do so. - } else if (!(toys.optflags & FLAG_p) || i <= TT.prefix) { - // If the old file was null, we're creating a new one. - if ((!strcmp(oldname, "/dev/null") || !oldsum) - && access(name, F_OK)) - { - printf("creating %s\n", name); - s = strrchr(name, '/'); - if (s) { - *s = 0; - xmkpath(name, -1); - *s = '/'; - } - TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666); - } else { - printf("patching %s\n", name); - TT.filein = xopen(name, O_RDWR); - } - TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); - TT.linenum = 0; - TT.hunknum = 0; - } - } - - TT.hunknum++; - - continue; - } - - // If we didn't continue above, discard this line. - free(patchline); - } - - finish_oldfile(); - - if (CFG_TOYBOX_FREE) { - close(TT.filepatch); - free(oldname); - free(newname); - } + int reverse = toys.optflags&FLAG_R, state = 0, patchlinenum = 0, + strip = 0; + char *oldname = NULL, *newname = NULL; + + if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY); + TT.filein = TT.fileout = -1; + + // Loop through the lines in the patch + for (;;) { + char *patchline; + + patchline = get_line(TT.filepatch); + if (!patchline) break; + + // Other versions of patch accept damaged patches, + // so we need to also. + if (strip || !patchlinenum++) { + int len = strlen(patchline); + if (patchline[len-1] == '\r') { + if (!strip) fprintf(stderr, "Removing DOS newlines\n"); + strip = 1; + patchline[len-1]=0; + } + } + if (!*patchline) { + free(patchline); + patchline = xstrdup(" "); + } + + // Are we assembling a hunk? + if (state >= 2) { + if (*patchline==' ' || *patchline=='+' || *patchline=='-') { + dlist_add(&TT.current_hunk, patchline); + + if (*patchline != '+') TT.oldlen--; + if (*patchline != '-') TT.newlen--; + + // Context line? + if (*patchline==' ' && state==2) TT.context++; + else state=3; + + // If we've consumed all expected hunk lines, apply the hunk. + + if (!TT.oldlen && !TT.newlen) state = apply_one_hunk(); + continue; + } + fail_hunk(); + state = 0; + continue; + } + + // Open a new file? + if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) { + char *s, **name = &oldname; + int i; + + if (*patchline == '+') { + name = &newname; + state = 1; + } + + free(*name); + finish_oldfile(); + + // Trim date from end of filename (if any). We don't care. + for (s = patchline+4; *s && *s!='\t'; s++) + if (*s=='\\' && s[1]) s++; + i = atoi(s); + if (i>1900 && i<=1970) *name = xstrdup("/dev/null"); + else { + *s = 0; + *name = xstrdup(patchline+4); + } + + // We defer actually opening the file because svn produces broken + // patches that don't signal they want to create a new file the + // way the patch man page says, so you have to read the first hunk + // and _guess_. + + // Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@ + // but a missing ,value means the value is 1. + } else if (state == 1 && !strncmp("@@ -", patchline, 4)) { + int i; + char *s = patchline+4; + + // Read oldline[,oldlen] +newline[,newlen] + + TT.oldlen = TT.newlen = 1; + TT.oldline = strtol(s, &s, 10); + if (*s == ',') TT.oldlen=strtol(s+1, &s, 10); + TT.newline = strtol(s+2, &s, 10); + if (*s == ',') TT.newlen = strtol(s+1, &s, 10); + + TT.context = 0; + state = 2; + + // If this is the first hunk, open the file. + if (TT.filein == -1) { + int oldsum, newsum, del = 0; + char *name; + + oldsum = TT.oldline + TT.oldlen; + newsum = TT.newline + TT.newlen; + + name = reverse ? oldname : newname; + + // We're deleting oldname if new file is /dev/null (before -p) + // or if new hunk is empty (zero context) after patching + if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) + { + name = reverse ? newname : oldname; + del++; + } + + // handle -p path truncation. + for (i = 0, s = name; *s;) { + if ((toys.optflags & FLAG_p) && TT.prefix == i) break; + if (*s++ != '/') continue; + while (*s == '/') s++; + name = s; + i++; + } + + if (del) { + printf("removing %s\n", name); + xunlink(name); + state = 0; + // If we've got a file to open, do so. + } else if (!(toys.optflags & FLAG_p) || i <= TT.prefix) { + // If the old file was null, we're creating a new one. + if ((!strcmp(oldname, "/dev/null") || !oldsum) && access(name, F_OK)) + { + printf("creating %s\n", name); + s = strrchr(name, '/'); + if (s) { + *s = 0; + xmkpath(name, -1); + *s = '/'; + } + TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666); + } else { + printf("patching %s\n", name); + TT.filein = xopen(name, O_RDWR); + } + TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); + TT.linenum = 0; + TT.hunknum = 0; + } + } + + TT.hunknum++; + + continue; + } + + // If we didn't continue above, discard this line. + free(patchline); + } + + finish_oldfile(); + + if (CFG_TOYBOX_FREE) { + close(TT.filepatch); + free(oldname); + free(newname); + } } diff --git a/toys/posix/pwd.c b/toys/posix/pwd.c index d5a3bb69..f70f9098 100644 --- a/toys/posix/pwd.c +++ b/toys/posix/pwd.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * pwd.c - Print working directory. +/* pwd.c - Print working directory. * * Copyright 2006 Rob Landley * @@ -11,20 +9,20 @@ USE_PWD(NEWTOY(pwd, NULL, TOYFLAG_BIN)) config PWD - bool "pwd" - default y - help - usage: pwd + bool "pwd" + default y + help + usage: pwd - The print working directory command prints the current directory. + The print working directory command prints the current directory. */ #include "toys.h" void pwd_main(void) { - char *pwd = xgetcwd(); + char *pwd = xgetcwd(); - xprintf("%s\n", pwd); - if (CFG_TOYBOX_FREE) free(pwd); + xprintf("%s\n", pwd); + if (CFG_TOYBOX_FREE) free(pwd); } diff --git a/toys/posix/rmdir.c b/toys/posix/rmdir.c index be93cb69..289b0156 100644 --- a/toys/posix/rmdir.c +++ b/toys/posix/rmdir.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * rmdir.c - remove directory/path +/* rmdir.c - remove directory/path * * Copyright 2008 Rob Landley * @@ -9,35 +7,35 @@ USE_RMDIR(NEWTOY(rmdir, "<1p", TOYFLAG_BIN)) config RMDIR - bool "rmdir" - default y - help - usage: rmdir [-p] [dirname...] - Remove one or more directories. + bool "rmdir" + default y + help + usage: rmdir [-p] [dirname...] + Remove one or more directories. - -p Remove path. + -p Remove path. */ #include "toys.h" static void do_rmdir(char *name) { - for (;;) { - char *temp; - - if (rmdir(name)) { - perror_msg("%s",name); - return; - } - if (!toys.optflags) return; - if (!(temp=strrchr(name,'/'))) return; - *temp=0; - } + for (;;) { + char *temp; + + if (rmdir(name)) { + perror_msg("%s",name); + return; + } + if (!toys.optflags) return; + if (!(temp=strrchr(name,'/'))) return; + *temp=0; + } } void rmdir_main(void) { - char **s; + char **s; - for (s=toys.optargs; *s; s++) do_rmdir(*s); + for (s=toys.optargs; *s; s++) do_rmdir(*s); } diff --git a/toys/posix/sed.c b/toys/posix/sed.c index a3ba9e38..15099cc6 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -1,21 +1,24 @@ -/* vi: set sw=4 ts=4: +/* sed.c - Stream editor. * - * sed.c - Stream editor. - * - * Copyright 2008 Rob Landley + * Copyright 2012 Rob Landley * * See http://opengroup.org/onlinepubs/9699919799/utilities/sed.c USE_SED(NEWTOY(sed, "irne*", TOYFLAG_BIN)) config SED - bool "sed" - default n - help - usage: sed [-irn] {command | [-e command]...} [FILE...] + bool "sed" + default n + help + usage: sed [-irn] {command | [-e command]...} [FILE...] + + Stream EDitor, transforms text by appling script of command to each line + of input. - Stream EDitor, transforms text by appling commands to each line - of input. + -e Add expression to the command script (if no -e, use first argument) + -i Modify file in place + -n No default output (p commands only) + -r Use extended regular expression syntex */ #define FOR_sed @@ -23,40 +26,106 @@ config SED #include "lib/xregcomp.h" GLOBALS( - struct arg_list *commands; + struct arg_list *scripts; + struct double_list *commands; + + void *parsed; ) +// Digested version of what sed commands can actually tell use to do. + + struct sed_command { - // Doubly linked list of commands. - struct sed_command *next, *prev; + // double_list compatibility (easier to create in-order) + struct sed_command *next, *prev; - // Regexes for s/match/data/ and /match_begin/,/match_end/command - regex_t *match, *match_begin, *match_end; + // data string for (saicytb) + char c, *data; + // Regexes for s/match/data/ and /begin/,/end/command + regex_t *match, *begin, *end; + // For numeric ranges ala 10,20command + long lstart, lstop; + // Which match to replace, 0 for all. s and w commands can write to a file + int which, outfd; +}; - // For numeric ranges ala 10,20command - int first_line, last_line; +// Space. Space. Gotta get past space. Spaaaaaaaace! (But not newline.) +void spaceorb(char **s) +{ + while (**s == ' ' || **s == '\t') *s++; +} - // Which match to replace, 0 for all. - int which; +void parse_scripts(void) +{ + struct sed_command *commands = 0; + struct arg_list *script; + int which = 0; + long l; - // s and w commands can write to a file. Slight optimization: we use 0 - // instead of -1 to mean no file here, because even when there's no stdin - // our input file would take fd 0. - int outfd; + for (script = TT.scripts; *script; script = script->next) { + char *str = script->arg, *s; + struct sed_command *cmd; - // Data string for (saicytb) - char *data; + which++; + for (i=1;;) { + if (!*str) break; - // Which command letter is this? - char command; -}; + cmd = xzalloc(sizeof(struct sed_command)); + + // Identify prefix + for (;;) { + long l; + + spaceorb(&str); + if (*str == '$') { + l = -1; + str++; + } else if (isdigit(*str)) l = strtol(str, &str, 10); + else if (!cmd->lstart) break; + else goto parse_fail; + + spaceorb(&str); + if (!cmd->lstart) { + if (!l) goto parse_fail; + cmd->lstart = l; + if (*str != ',') break; + str++; + continue; + } + cmd->lstop = l; + break; + } else if (*str == '/') { + printf("regex\n"); + } + l = stridx("{bcdDgGhHlnNpPstwxyrqia= \t#:}", *str); + if (l == -1) goto parse_fail; + + + } + } + + return; + +parse_fail: + error_exit("bad expression %d@%d: %s", which, i, script->arg+i); +} void sed_main(void) { - struct arg_list *test; + char **files=toys.optargs; + + // If no -e, use first argument + if (!TT.scripts) { + if (!*files) error_exit("Need script"); + (TT.scripts=xzalloc(sizeof(struct arg_list)))->arg=*(files++); + } + - for (test = TT.commands; test; test = test->next) - dprintf(2,"command=%s\n",test->arg); + { + struct arg_list *test; - printf("Hello world\n"); + for (test = TT.commands; test; test = test->next) + dprintf(2,"command=%s\n",test->arg); + while (*files) dprintf(2,"file=%s\n", *(files++)); + } } diff --git a/toys/posix/sh.c b/toys/posix/sh.c index 44c39119..30900b30 100644 --- a/toys/posix/sh.c +++ b/toys/posix/sh.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sh.c - toybox shell +/* sh.c - toybox shell * * Copyright 2006 Rob Landley * @@ -30,157 +28,157 @@ USE_SH(NEWTOY(sh, "c:i", TOYFLAG_BIN)) USE_SH(OLDTOY(toysh, sh, "c:i", TOYFLAG_BIN)) config SH - bool "sh (toysh)" - default n - help - usage: sh [-c command] [script] + bool "sh (toysh)" + default n + help + usage: sh [-c command] [script] - Command shell. Runs a shell script, or reads input interactively - and responds to it. + Command shell. Runs a shell script, or reads input interactively + and responds to it. - -c command line to execute + -c command line to execute config SH_TTY - bool "Interactive shell (terminal control)" - default n - depends on SH - help - Add terminal control to toysh. This is necessary for interactive use, - so the shell isn't killed by CTRL-C. + bool "Interactive shell (terminal control)" + default n + depends on SH + help + Add terminal control to toysh. This is necessary for interactive use, + so the shell isn't killed by CTRL-C. config SH_PROFILE - bool "Profile support" - default n - depends on SH_TTY - help - Read /etc/profile and ~/.profile when running interactively. + bool "Profile support" + default n + depends on SH_TTY + help + Read /etc/profile and ~/.profile when running interactively. - Also enables the built-in command "source". + Also enables the built-in command "source". config SH_JOBCTL - bool "Job Control (fg, bg, jobs)" - default n - depends on SH_TTY - help - Add job control to toysh. This lets toysh handle CTRL-Z, and enables - the built-in commands "fg", "bg", and "jobs". + bool "Job Control (fg, bg, jobs)" + default n + depends on SH_TTY + help + Add job control to toysh. This lets toysh handle CTRL-Z, and enables + the built-in commands "fg", "bg", and "jobs". - With pipe support, enable use of "&" to run background processes. + With pipe support, enable use of "&" to run background processes. config SH_FLOWCTL - bool "Flow control (if, while, for, functions)" - default n - depends on SH - help - Add flow control to toysh. This enables the if/then/else/fi, - while/do/done, and for/do/done constructs. + bool "Flow control (if, while, for, functions)" + default n + depends on SH + help + Add flow control to toysh. This enables the if/then/else/fi, + while/do/done, and for/do/done constructs. - With pipe support, this enables the ability to define functions - using the "function name" or "name()" syntax, plus curly brackets - "{ }" to group commands. + With pipe support, this enables the ability to define functions + using the "function name" or "name()" syntax, plus curly brackets + "{ }" to group commands. config SH_QUOTES - bool "Smarter argument parsing (quotes)" - default n - depends on SH - help - Add support for parsing "" and '' style quotes to the toysh command - parser, with lets arguments have spaces in them. + bool "Smarter argument parsing (quotes)" + default n + depends on SH + help + Add support for parsing "" and '' style quotes to the toysh command + parser, with lets arguments have spaces in them. config SH_WILDCARDS - bool "Wildcards ( ?*{,} )" - default n - depends on SH_QUOTES - help - Expand wildcards in argument names, ala "ls -l *.t?z" and - "rm subdir/{one,two,three}.txt". + bool "Wildcards ( ?*{,} )" + default n + depends on SH_QUOTES + help + Expand wildcards in argument names, ala "ls -l *.t?z" and + "rm subdir/{one,two,three}.txt". config SH_PROCARGS - bool "Executable arguments ( `` and $() )" - default n - depends on SH_QUOTES - help - Add support for executing arguments contianing $() and ``, using - the output of the command as the new argument value(s). + bool "Executable arguments ( `` and $() )" + default n + depends on SH_QUOTES + help + Add support for executing arguments contianing $() and ``, using + the output of the command as the new argument value(s). - (Bash calls this "command substitution".) + (Bash calls this "command substitution".) config SH_ENVVARS - bool "Environment variable support" - default n - depends on SH_QUOTES - help - Substitute environment variable values for $VARNAME or ${VARNAME}, - and enable the built-in command "export". + bool "Environment variable support" + default n + depends on SH_QUOTES + help + Substitute environment variable values for $VARNAME or ${VARNAME}, + and enable the built-in command "export". config SH_LOCALS - bool "Local variables" - default n - depends on SH_ENVVARS - help - Support for local variables, fancy prompts ($PS1), the "set" command, - and $?. + bool "Local variables" + default n + depends on SH_ENVVARS + help + Support for local variables, fancy prompts ($PS1), the "set" command, + and $?. config SH_ARRAYS - bool "Array variables" - default n - depends on SH_LOCALS - help - Support for ${blah[blah]} style array variables. + bool "Array variables" + default n + depends on SH_LOCALS + help + Support for ${blah[blah]} style array variables. config SH_PIPES - bool "Pipes and redirects ( | > >> < << & && | || () ; )" - default n - depends on SH - help - Support multiple commands on the same command line. This includes - | pipes, > >> < redirects, << here documents, || && conditional - execution, () subshells, ; sequential execution, and (with job - control) & background processes. + bool "Pipes and redirects ( | > >> < << & && | || () ; )" + default n + depends on SH + help + Support multiple commands on the same command line. This includes + | pipes, > >> < redirects, << here documents, || && conditional + execution, () subshells, ; sequential execution, and (with job + control) & background processes. config SH_BUILTINS - bool "Builtin commands" - default n - depends on SH - help - Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set, - unset, read, alias. + bool "Builtin commands" + default n + depends on SH + help + Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set, + unset, read, alias. config EXIT - bool - default n - depends on SH - help - usage: exit [status] + bool + default n + depends on SH + help + usage: exit [status] - Exit shell. If no return value supplied on command line, use value - of most recent command, or 0 if none. + Exit shell. If no return value supplied on command line, use value + of most recent command, or 0 if none. config CD - bool - default n - depends on SH - help - usage: cd [path] + bool + default n + depends on SH + help + usage: cd [path] - Change current directory. With no arguments, go to $HOME. + Change current directory. With no arguments, go to $HOME. config CD_P - bool # "-P support for cd" - default n - depends on SH - help - usage: cd [-PL] - - -P Physical path: resolve symlinks in path. - -L Cancel previous -P and restore default behavior. + bool # "-P support for cd" + default n + depends on SH + help + usage: cd [-PL] + + -P Physical path: resolve symlinks in path. + -L Cancel previous -P and restore default behavior. */ #define FOR_sh #include "toys.h" GLOBALS( - char *command; + char *command; ) // A single executable, its arguments, and other information we know about it. @@ -195,20 +193,20 @@ GLOBALS( // What we know about a single process. struct command { - struct command *next; - int flags; // exit, suspend, && || - int pid; // pid (or exit code) - int argc; - char *argv[0]; + struct command *next; + int flags; // exit, suspend, && || + int pid; // pid (or exit code) + int argc; + char *argv[0]; }; // A collection of processes piped into/waiting on each other. struct pipeline { - struct pipeline *next; - int job_id; - struct command *cmd; - char *cmdline; // Unparsed line for display purposes - int cmdlinelen; // How long is cmdline? + struct pipeline *next; + int job_id; + struct command *cmd; + char *cmdline; // Unparsed line for display purposes + int cmdlinelen; // How long is cmdline? }; // Parse one word from the command line, appending one or more argv[] entries @@ -217,23 +215,23 @@ struct pipeline { // hit an ending token. static char *parse_word(char *start, struct command **cmd) { - char *end; + char *end; - // Detect end of line (and truncate line at comment) - if (CFG_SH_PIPES && strchr("><&|(;", *start)) return 0; + // Detect end of line (and truncate line at comment) + if (CFG_SH_PIPES && strchr("><&|(;", *start)) return 0; - // Grab next word. (Add dequote and envvar logic here) - end = start; - while (*end && !isspace(*end)) end++; - (*cmd)->argv[(*cmd)->argc++] = xstrndup(start, end-start); + // Grab next word. (Add dequote and envvar logic here) + end = start; + while (*end && !isspace(*end)) end++; + (*cmd)->argv[(*cmd)->argc++] = xstrndup(start, end-start); - // Allocate more space if there's no room for NULL terminator. + // Allocate more space if there's no room for NULL terminator. - if (!((*cmd)->argc & 7)) - *cmd=xrealloc(*cmd, - sizeof(struct command) + ((*cmd)->argc+8)*sizeof(char *)); - (*cmd)->argv[(*cmd)->argc] = 0; - return end; + if (!((*cmd)->argc & 7)) + *cmd=xrealloc(*cmd, + sizeof(struct command) + ((*cmd)->argc+8)*sizeof(char *)); + (*cmd)->argv[(*cmd)->argc] = 0; + return end; } // Parse a line of text into a pipeline. @@ -241,149 +239,149 @@ static char *parse_word(char *start, struct command **cmd) static char *parse_pipeline(char *cmdline, struct pipeline *line) { - struct command **cmd = &(line->cmd); - char *start = line->cmdline = cmdline; - - if (!cmdline) return 0; - - if (CFG_SH_JOBCTL) line->cmdline = cmdline; - - // Parse command into argv[] - for (;;) { - char *end; - - // Skip leading whitespace and detect end of line. - while (isspace(*start)) start++; - if (!*start || *start=='#') { - if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; - return 0; - } - - // Allocate next command structure if necessary - if (!*cmd) *cmd = xzalloc(sizeof(struct command)+8*sizeof(char *)); - - // Parse next argument and add the results to argv[] - end = parse_word(start, cmd); - - // If we hit the end of this command, how did it end? - if (!end) { - if (CFG_SH_PIPES && *start) { - if (*start==';') { - start++; - break; - } - // handle | & < > >> << || && - } - break; - } - start = end; - } - - if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; - - return start; + struct command **cmd = &(line->cmd); + char *start = line->cmdline = cmdline; + + if (!cmdline) return 0; + + if (CFG_SH_JOBCTL) line->cmdline = cmdline; + + // Parse command into argv[] + for (;;) { + char *end; + + // Skip leading whitespace and detect end of line. + while (isspace(*start)) start++; + if (!*start || *start=='#') { + if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; + return 0; + } + + // Allocate next command structure if necessary + if (!*cmd) *cmd = xzalloc(sizeof(struct command)+8*sizeof(char *)); + + // Parse next argument and add the results to argv[] + end = parse_word(start, cmd); + + // If we hit the end of this command, how did it end? + if (!end) { + if (CFG_SH_PIPES && *start) { + if (*start==';') { + start++; + break; + } + // handle | & < > >> << || && + } + break; + } + start = end; + } + + if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline; + + return start; } // Execute the commands in a pipeline static void run_pipeline(struct pipeline *line) { - struct toy_list *tl; - struct command *cmd = line->cmd; - if (!cmd || !cmd->argc) return; - - tl = toy_find(cmd->argv[0]); - // Is this command a builtin that should run in this process? - if (tl && (tl->flags & TOYFLAG_NOFORK)) { - struct toy_context temp; - - // This fakes lots of what toybox_main() does. - memcpy(&temp, &toys, sizeof(struct toy_context)); - memset(&toys, 0, sizeof(struct toy_context)); - toy_init(tl, cmd->argv); - tl->toy_main(); - cmd->pid = toys.exitval; - free(toys.optargs); - if (toys.old_umask) umask(toys.old_umask); - memcpy(&toys, &temp, sizeof(struct toy_context)); - } else { - int status; - - cmd->pid = vfork(); - if (!cmd->pid) xexec(cmd->argv); - else waitpid(cmd->pid, &status, 0); - - if (CFG_SH_FLOWCTL || CFG_SH_PIPES) { - if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status); - if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status); - } - } - - return; + struct toy_list *tl; + struct command *cmd = line->cmd; + if (!cmd || !cmd->argc) return; + + tl = toy_find(cmd->argv[0]); + // Is this command a builtin that should run in this process? + if (tl && (tl->flags & TOYFLAG_NOFORK)) { + struct toy_context temp; + + // This fakes lots of what toybox_main() does. + memcpy(&temp, &toys, sizeof(struct toy_context)); + memset(&toys, 0, sizeof(struct toy_context)); + toy_init(tl, cmd->argv); + tl->toy_main(); + cmd->pid = toys.exitval; + free(toys.optargs); + if (toys.old_umask) umask(toys.old_umask); + memcpy(&toys, &temp, sizeof(struct toy_context)); + } else { + int status; + + cmd->pid = vfork(); + if (!cmd->pid) xexec(cmd->argv); + else waitpid(cmd->pid, &status, 0); + + if (CFG_SH_FLOWCTL || CFG_SH_PIPES) { + if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status); + if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status); + } + } + + return; } // Free the contents of a command structure static void free_cmd(void *data) { - struct command *cmd=(struct command *)data; + struct command *cmd=(struct command *)data; - while(cmd->argc) free(cmd->argv[--cmd->argc]); + while(cmd->argc) free(cmd->argv[--cmd->argc]); } // Parse a command line and do what it says to do. static void handle(char *command) { - struct pipeline line; - char *start = command; + struct pipeline line; + char *start = command; - // Loop through commands in this line + // Loop through commands in this line - for (;;) { + for (;;) { - // Parse a group of connected commands + // Parse a group of connected commands - memset(&line,0,sizeof(struct pipeline)); - start = parse_pipeline(start, &line); - if (!line.cmd) break; + memset(&line,0,sizeof(struct pipeline)); + start = parse_pipeline(start, &line); + if (!line.cmd) break; - // Run those commands + // Run those commands - run_pipeline(&line); - llist_traverse(line.cmd, free_cmd); - } + run_pipeline(&line); + llist_traverse(line.cmd, free_cmd); + } } void cd_main(void) { - char *dest = *toys.optargs ? *toys.optargs : getenv("HOME"); - xchdir(dest); + char *dest = *toys.optargs ? *toys.optargs : getenv("HOME"); + xchdir(dest); } void exit_main(void) { - exit(*toys.optargs ? atoi(*toys.optargs) : 0); + exit(*toys.optargs ? atoi(*toys.optargs) : 0); } void sh_main(void) { - FILE *f; - - // Set up signal handlers and grab control of this tty. - if (CFG_SH_TTY) { - if (isatty(0)) toys.optflags |= 1; - } - f = *toys.optargs ? xfopen(*toys.optargs, "r") : NULL; - if (TT.command) handle(TT.command); - else { - size_t cmdlen = 0; - for (;;) { - char *command = 0; - if (!f) xputc('$'); - if (1 > getline(&command, &cmdlen, f ? f : stdin)) break; - handle(command); - free(command); - } - } - - toys.exitval = 1; + FILE *f; + + // Set up signal handlers and grab control of this tty. + if (CFG_SH_TTY) { + if (isatty(0)) toys.optflags |= 1; + } + f = *toys.optargs ? xfopen(*toys.optargs, "r") : NULL; + if (TT.command) handle(TT.command); + else { + size_t cmdlen = 0; + for (;;) { + char *command = 0; + if (!f) xputc('$'); + if (1 > getline(&command, &cmdlen, f ? f : stdin)) break; + handle(command); + free(command); + } + } + + toys.exitval = 1; } diff --git a/toys/posix/sleep.c b/toys/posix/sleep.c index c544e0ac..a83f1e56 100644 --- a/toys/posix/sleep.c +++ b/toys/posix/sleep.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sleep.c - Wait for a number of seconds. +/* sleep.c - Wait for a number of seconds. * * Copyright 2007 Rob Landley * Copyright 2012 Georgi Chorbadzhiyski @@ -10,20 +8,20 @@ USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN)) config SLEEP - bool "sleep" - default y - help - usage: sleep SECONDS + bool "sleep" + default y + help + usage: sleep SECONDS - Wait before exiting. + Wait before exiting. config SLEEP_FLOAT - bool - default y - depends on SLEEP && TOYBOX_FLOAT - help - The delay can be a decimal fraction. An optional suffix can be "m" - (minutes), "h" (hours), "d" (days), or "s" (seconds, the default). + bool + default y + depends on SLEEP && TOYBOX_FLOAT + help + The delay can be a decimal fraction. An optional suffix can be "m" + (minutes), "h" (hours), "d" (days), or "s" (seconds, the default). */ #include "toys.h" @@ -31,21 +29,21 @@ config SLEEP_FLOAT void sleep_main(void) { - if (!CFG_TOYBOX_FLOAT) toys.exitval = sleep(atol(*toys.optargs)); - else { - char *arg; - double d = strtod(*toys.optargs, &arg); - struct timespec tv; - - // Parse suffix - if (*arg) { - int ismhd[]={1,60,3600,86400}; - char *smhd = "smhd", *c = strchr(smhd, *arg); - if (!c) error_exit("Unknown suffix '%c'", *arg); - d *= ismhd[c-smhd]; - } - - tv.tv_nsec=1000000000*(d-(tv.tv_sec = (unsigned long)d)); - toys.exitval = !!nanosleep(&tv, NULL); - } + if (!CFG_TOYBOX_FLOAT) toys.exitval = sleep(atol(*toys.optargs)); + else { + char *arg; + double d = strtod(*toys.optargs, &arg); + struct timespec tv; + + // Parse suffix + if (*arg) { + int ismhd[]={1,60,3600,86400}; + char *smhd = "smhd", *c = strchr(smhd, *arg); + if (!c) error_exit("Unknown suffix '%c'", *arg); + d *= ismhd[c-smhd]; + } + + tv.tv_nsec=1000000000*(d-(tv.tv_sec = (unsigned long)d)); + toys.exitval = !!nanosleep(&tv, NULL); + } } diff --git a/toys/posix/sort.c b/toys/posix/sort.c index 8f26f5d3..41b020b9 100644 --- a/toys/posix/sort.c +++ b/toys/posix/sort.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * sort.c - put input lines into order +/* sort.c - put input lines into order * * Copyright 2004, 2008 Rob Landley * @@ -9,54 +7,54 @@ USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")USE_SORT_BIG("S:T:m" "o:k*t:xbMcszdfi") "run", TOYFLAG_USR|TOYFLAG_BIN)) config SORT - bool "sort" - default y - help - usage: sort [-run] [FILE...] + bool "sort" + default y + help + usage: sort [-run] [FILE...] - Sort all lines of text from input files (or stdin) to stdout. + Sort all lines of text from input files (or stdin) to stdout. - -r reverse - -u unique lines only - -n numeric order (instead of alphabetical) + -r reverse + -u unique lines only + -n numeric order (instead of alphabetical) config SORT_BIG - bool "SuSv3 options (Support -ktcsbdfiozM)" - default y - depends on SORT - help - usage: sort [-bcdfiMsz] [-k#[,#[x]] [-t X]] [-o FILE] - - -b ignore leading blanks (or trailing blanks in second part of key) - -c check whether input is sorted - -d dictionary order (use alphanumeric and whitespace chars only) - -f force uppercase (case insensitive sort) - -i ignore nonprinting characters - -M month sort (jan, feb, etc). - -x Hexadecimal numerical sort - -s skip fallback sort (only sort with keys) - -z zero (null) terminated input - -k sort by "key" (see below) - -t use a key separator other than whitespace - -o output to FILE instead of stdout - - Sorting by key looks at a subset of the words on each line. -k2 - uses the second word to the end of the line, -k2,2 looks at only - the second word, -k2,4 looks from the start of the second to the end - of the fourth word. Specifying multiple keys uses the later keys as - tie breakers, in order. A type specifier appended to a sort key - (such as -2,2n) applies only to sorting that key. + bool "SuSv3 options (Support -ktcsbdfiozM)" + default y + depends on SORT + help + usage: sort [-bcdfiMsz] [-k#[,#[x]] [-t X]] [-o FILE] + + -b ignore leading blanks (or trailing blanks in second part of key) + -c check whether input is sorted + -d dictionary order (use alphanumeric and whitespace chars only) + -f force uppercase (case insensitive sort) + -i ignore nonprinting characters + -M month sort (jan, feb, etc). + -x Hexadecimal numerical sort + -s skip fallback sort (only sort with keys) + -z zero (null) terminated input + -k sort by "key" (see below) + -t use a key separator other than whitespace + -o output to FILE instead of stdout + + Sorting by key looks at a subset of the words on each line. -k2 + uses the second word to the end of the line, -k2,2 looks at only + the second word, -k2,4 looks from the start of the second to the end + of the fourth word. Specifying multiple keys uses the later keys as + tie breakers, in order. A type specifier appended to a sort key + (such as -2,2n) applies only to sorting that key. config SORT_FLOAT - bool "Floating point (-g)" - default y - depends on SORT_BIG - help - usage: sort [-g] + bool "Floating point (-g)" + default y + depends on SORT_BIG + help + usage: sort [-g] - This version of sort requires floating point. + This version of sort requires floating point. - -g general numeric sort (double precision with nan and inf) + -g general numeric sort (double precision with nan and inf) */ @@ -64,14 +62,14 @@ config SORT_FLOAT #include "toys.h" GLOBALS( - char *key_separator; - struct arg_list *raw_keys; - char *outfile; - char *ignore1, ignore2; // GNU compatability NOPs for -S and -T. - - void *key_list; - int linecount; - char **lines; + char *key_separator; + struct arg_list *raw_keys; + char *outfile; + char *ignore1, ignore2; // GNU compatability NOPs for -S and -T. + + void *key_list; + int linecount; + char **lines; ) // The sort types are n, g, and M. @@ -83,321 +81,320 @@ GLOBALS( struct sort_key { - struct sort_key *next_key; // linked list - unsigned range[4]; // start word, start char, end word, end char - int flags; + struct sort_key *next_key; // linked list + unsigned range[4]; // start word, start char, end word, end char + int flags; }; // Copy of the part of this string corresponding to a key/flags. static char *get_key_data(char *str, struct sort_key *key, int flags) { - int start=0, end, len, i, j; + int start=0, end, len, i, j; - // Special case whole string, so we don't have to make a copy + // Special case whole string, so we don't have to make a copy - if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3] - && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str; + if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3] + && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str; - // Find start of key on first pass, end on second pass + // Find start of key on first pass, end on second pass - len = strlen(str); - for (j=0; j<2; j++) { - if (!key->range[2*j]) end=len; + len = strlen(str); + for (j=0; j<2; j++) { + if (!key->range[2*j]) end=len; - // Loop through fields - else { - end=0; - for (i=1; i < key->range[2*j]+j; i++) { + // Loop through fields + else { + end=0; + for (i=1; i < key->range[2*j]+j; i++) { - // Skip leading blanks - if (str[end] && !TT.key_separator) - while (isspace(str[end])) end++; + // Skip leading blanks + if (str[end] && !TT.key_separator) + while (isspace(str[end])) end++; - // Skip body of key - for (; str[end]; end++) { - if (TT.key_separator) { - if (str[end]==*TT.key_separator) break; - } else if (isspace(str[end])) break; - } - } + // Skip body of key + for (; str[end]; end++) { + if (TT.key_separator) { + if (str[end]==*TT.key_separator) break; + } else if (isspace(str[end])) break; } - if (!j) start=end; - } - - // Key with explicit separator starts after the separator - if (TT.key_separator && str[start]==*TT.key_separator) start++; - - // Strip leading and trailing whitespace if necessary - if (flags&FLAG_b) while (isspace(str[start])) start++; - if (flags&FLAG_bb) while (end>start && isspace(str[end-1])) end--; - - // Handle offsets on start and end - if (key->range[3]) { - end += key->range[3]-1; - if (end>len) end=len; - } - if (key->range[1]) { - start += key->range[1]-1; - if (start>len) start=len; - } - - // Make the copy - if (endstart && isspace(str[end-1])) end--; + + // Handle offsets on start and end + if (key->range[3]) { + end += key->range[3]-1; + if (end>len) end=len; + } + if (key->range[1]) { + start += key->range[1]-1; + if (start>len) start=len; + } + + // Make the copy + if (endnext_key); - return *pkey = xzalloc(sizeof(struct sort_key)); + while (*pkey) pkey = &((*pkey)->next_key); + return *pkey = xzalloc(sizeof(struct sort_key)); } // Perform actual comparison static int compare_values(int flags, char *x, char *y) { - int ff = flags & (FLAG_n|FLAG_g|FLAG_M|FLAG_x); - - // Ascii sort - if (!ff) return strcmp(x, y); + int ff = flags & (FLAG_n|FLAG_g|FLAG_M|FLAG_x); - if (CFG_SORT_FLOAT && ff == FLAG_g) { - char *xx,*yy; - double dx = strtod(x,&xx), dy = strtod(y,&yy); - int xinf, yinf; + // Ascii sort + if (!ff) return strcmp(x, y); - // not numbers < NaN < -infinity < numbers < +infinity + if (CFG_SORT_FLOAT && ff == FLAG_g) { + char *xx,*yy; + double dx = strtod(x,&xx), dy = strtod(y,&yy); + int xinf, yinf; - if (x==xx) return y==yy ? 0 : -1; - if (y==yy) return 1; + // not numbers < NaN < -infinity < numbers < +infinity - // Check for isnan - if (dx!=dx) return (dy!=dy) ? 0 : -1; - if (dy!=dy) return 1; + if (x==xx) return y==yy ? 0 : -1; + if (y==yy) return 1; - // Check for infinity. (Could underflow, but avoids needing libm.) - xinf = (1.0/dx == 0.0); - yinf = (1.0/dy == 0.0); - if (xinf) { - if(dx<0) return (yinf && dy<0) ? 0 : -1; - return (yinf && dy>0) ? 0 : 1; - } - if (yinf) return dy<0 ? 1 : -1; - - return dx>dy ? 1 : (dxdy ? 1 : (dx0) ? 0 : 1; } + if (yinf) return dy<0 ? 1 : -1; + + return dx>dy ? 1 : (dxdy ? 1 : (dxnext_key) - { - flags = key->flags ? key->flags : toys.optflags; + int flags = toys.optflags, retval = 0; + char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg; + struct sort_key *key; - // Chop out and modify key chunks, handling -dfib + if (CFG_SORT_BIG) { + for (key=(struct sort_key *)TT.key_list; !retval && key; + key = key->next_key) + { + flags = key->flags ? key->flags : toys.optflags; - x = get_key_data(xx, key, flags); - y = get_key_data(yy, key, flags); + // Chop out and modify key chunks, handling -dfib - retval = compare_values(flags, x, y); + x = get_key_data(xx, key, flags); + y = get_key_data(yy, key, flags); - // Free the copies get_key_data() made. + retval = compare_values(flags, x, y); - if (x != xx) free(x); - if (y != yy) free(y); + // Free the copies get_key_data() made. - if (retval) break; - } - } else retval = compare_values(flags, xx, yy); + if (x != xx) free(x); + if (y != yy) free(y); - // Perform fallback sort if necessary - if (!retval && !(CFG_SORT_BIG && (toys.optflags&FLAG_s))) { - retval = strcmp(xx, yy); - flags = toys.optflags; + if (retval) break; } + } else retval = compare_values(flags, xx, yy); + + // Perform fallback sort if necessary + if (!retval && !(CFG_SORT_BIG && (toys.optflags&FLAG_s))) { + retval = strcmp(xx, yy); + flags = toys.optflags; + } - return retval * ((flags&FLAG_r) ? -1 : 1); + return retval * ((flags&FLAG_r) ? -1 : 1); } // Callback from loopfiles to handle input files. static void sort_read(int fd, char *name) { - // Read each line from file, appending to a big array. - - for (;;) { - char * line = (CFG_SORT_BIG && (toys.optflags&FLAG_z)) - ? get_rawline(fd, NULL, 0) : get_line(fd); - - if (!line) break; - - // handle -c here so we don't allocate more memory than necessary. - if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) { - int j = (toys.optflags&FLAG_u) ? -1 : 0; - - if (TT.lines && compare_keys((void *)&TT.lines, &line)>j) - error_exit("%s: Check line %d\n", name, TT.linecount); - free(TT.lines); - TT.lines = (char **)line; - } else { - if (!(TT.linecount&63)) - TT.lines = xrealloc(TT.lines, sizeof(char *)*(TT.linecount+64)); - TT.lines[TT.linecount] = line; - } - TT.linecount++; + // Read each line from file, appending to a big array. + + for (;;) { + char * line = (CFG_SORT_BIG && (toys.optflags&FLAG_z)) + ? get_rawline(fd, NULL, 0) : get_line(fd); + + if (!line) break; + + // handle -c here so we don't allocate more memory than necessary. + if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) { + int j = (toys.optflags&FLAG_u) ? -1 : 0; + + if (TT.lines && compare_keys((void *)&TT.lines, &line)>j) + error_exit("%s: Check line %d\n", name, TT.linecount); + free(TT.lines); + TT.lines = (char **)line; + } else { + if (!(TT.linecount&63)) + TT.lines = xrealloc(TT.lines, sizeof(char *)*(TT.linecount+64)); + TT.lines[TT.linecount] = line; } + TT.linecount++; + } } void sort_main(void) { - int idx, fd = 1; - - // Open output file if necessary. - if (CFG_SORT_BIG && TT.outfile) - fd = xcreate(TT.outfile, O_CREAT|O_TRUNC|O_WRONLY, 0666); - - // Parse -k sort keys. - if (CFG_SORT_BIG && TT.raw_keys) { - struct arg_list *arg; - - for (arg = TT.raw_keys; arg; arg = arg->next) { - struct sort_key *key = add_key(); - char *temp; - int flag; - - idx = 0; - temp = arg->arg; - while (*temp) { - // Start of range - key->range[2*idx] = (unsigned)strtol(temp, &temp, 10); - if (*temp=='.') - key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10); - - // Handle flags appended to a key type. - for (;*temp;temp++) { - char *temp2, *optlist; - - // Note that a second comma becomes an "Unknown key" error. - - if (*temp==',' && !idx++) { - temp++; - break; - } - - // Which flag is this? - - optlist = toys.which->options; - temp2 = strchr(optlist, *temp); - flag = (1<<(optlist-temp2+strlen(optlist)-1)); - - // Was it a flag that can apply to a key? - - if (!temp2 || flag>FLAG_b - || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z))) - { - error_exit("Unknown key option."); - } - // b after , means strip _trailing_ space, not leading. - if (idx && flag==FLAG_b) flag = FLAG_bb; - key->flags |= flag; - } - } + int idx, fd = 1; + + // Open output file if necessary. + if (CFG_SORT_BIG && TT.outfile) + fd = xcreate(TT.outfile, O_CREAT|O_TRUNC|O_WRONLY, 0666); + + // Parse -k sort keys. + if (CFG_SORT_BIG && TT.raw_keys) { + struct arg_list *arg; + + for (arg = TT.raw_keys; arg; arg = arg->next) { + struct sort_key *key = add_key(); + char *temp; + int flag; + + idx = 0; + temp = arg->arg; + while (*temp) { + // Start of range + key->range[2*idx] = (unsigned)strtol(temp, &temp, 10); + if (*temp=='.') + key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10); + + // Handle flags appended to a key type. + for (;*temp;temp++) { + char *temp2, *optlist; + + // Note that a second comma becomes an "Unknown key" error. + + if (*temp==',' && !idx++) { + temp++; + break; + } + + // Which flag is this? + + optlist = toys.which->options; + temp2 = strchr(optlist, *temp); + flag = (1<<(optlist-temp2+strlen(optlist)-1)); + + // Was it a flag that can apply to a key? + + if (!temp2 || flag>FLAG_b + || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z))) + { + error_exit("Unknown key option."); + } + // b after , means strip _trailing_ space, not leading. + if (idx && flag==FLAG_b) flag = FLAG_bb; + key->flags |= flag; } + } } + } - // global b flag strips both leading and trailing spaces - if (toys.optflags&FLAG_b) toys.optflags |= FLAG_bb; + // global b flag strips both leading and trailing spaces + if (toys.optflags&FLAG_b) toys.optflags |= FLAG_bb; - // If no keys, perform alphabetic sort over the whole line. - if (CFG_SORT_BIG && !TT.key_list) add_key()->range[0] = 1; + // If no keys, perform alphabetic sort over the whole line. + if (CFG_SORT_BIG && !TT.key_list) add_key()->range[0] = 1; - // Open input files and read data, populating TT.lines[TT.linecount] - loopfiles(toys.optargs, sort_read); + // Open input files and read data, populating TT.lines[TT.linecount] + loopfiles(toys.optargs, sort_read); - // The compare (-c) logic was handled in sort_read(), - // so if we got here, we're done. - if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) goto exit_now; + // The compare (-c) logic was handled in sort_read(), + // so if we got here, we're done. + if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) goto exit_now; - // Perform the actual sort - qsort(TT.lines, TT.linecount, sizeof(char *), compare_keys); + // Perform the actual sort + qsort(TT.lines, TT.linecount, sizeof(char *), compare_keys); - // handle unique (-u) - if (toys.optflags&FLAG_u) { - int jdx; + // handle unique (-u) + if (toys.optflags&FLAG_u) { + int jdx; - for (jdx=0, idx=1; idx * @@ -9,62 +7,62 @@ USE_TAIL(NEWTOY(tail, "fc-n-", TOYFLAG_BIN)) config TAIL - bool "tail" - default y - help - usage: tail [-n|c number] [-f] [file...] + bool "tail" + default y + help + usage: tail [-n|c number] [-f] [file...] - Copy last lines from files to stdout. If no files listed, copy from - stdin. Filename "-" is a synonym for stdin. + Copy last lines from files to stdout. If no files listed, copy from + stdin. Filename "-" is a synonym for stdin. - -n output the last X lines (default 10), +X counts from start. - -c output the last X bytes, +X counts from start - -f follow file, waiting for more data to be appended + -n output the last X lines (default 10), +X counts from start. + -c output the last X bytes, +X counts from start + -f follow file, waiting for more data to be appended config TAIL_SEEK - bool "tail seek support" - default y - depends on TAIL - help - This version uses lseek, which is faster on large files. + bool "tail seek support" + default y + depends on TAIL + help + This version uses lseek, which is faster on large files. */ #define FOR_tail #include "toys.h" GLOBALS( - long lines; - long bytes; + long lines; + long bytes; - int file_no; + int file_no; ) struct line_list { - struct line_list *next, *prev; - char *data; - int len; + struct line_list *next, *prev; + char *data; + int len; }; static struct line_list *get_chunk(int fd, int len) { - struct line_list *line = xmalloc(sizeof(struct line_list)+len); + struct line_list *line = xmalloc(sizeof(struct line_list)+len); - line->data = ((char *)line) + sizeof(struct line_list); - line->len = readall(fd, line->data, len); + line->data = ((char *)line) + sizeof(struct line_list); + line->len = readall(fd, line->data, len); - if (line->len < 1) { - free(line); - return 0; - } + if (line->len < 1) { + free(line); + return 0; + } - return line; + return line; } static void dump_chunk(void *ptr) { - struct line_list *list = ptr; - xwrite(1, list->data, list->len); - free(list); + struct line_list *list = ptr; + xwrite(1, list->data, list->len); + free(list); } // Reading through very large files is slow. Using lseek can speed things @@ -72,156 +70,156 @@ static void dump_chunk(void *ptr) // Note: bytes and lines are negative here. static int try_lseek(int fd, long bytes, long lines) { - struct line_list *list = 0, *temp; - int flag = 0, chunk = sizeof(toybuf); - ssize_t pos = lseek(fd, 0, SEEK_END); - - // If lseek() doesn't work on this stream, return now. - if (pos<0) return 0; - - // Seek to the right spot, output data from there. - if (bytes) { - if (lseek(fd, bytes, SEEK_END)<0) lseek(fd, 0, SEEK_SET); - xsendfile(fd, 1); - return 1; - } - - // Read from end to find enough lines, then output them. - - bytes = pos; - while (lines && pos) { - int offset; - - // Read in next chunk from end of file - if (chunk>pos) chunk = pos; - pos -= chunk; - if (pos != lseek(fd, pos, SEEK_SET)) { - perror_msg("seek failed"); - break; - } - if (!(temp = get_chunk(fd, chunk))) break; - if (list) list->next = temp; - list = temp; - - // Count newlines in this chunk. - offset = list->len; - while (offset--) { - // If the last line ends with a newline, that one doesn't count. - if (!flag) { - flag++; - - continue; - } - - // Start outputting data right after newline - if (list->data[offset] == '\n' && !++lines) { - offset++; - list->data += offset; - list->len -= offset; - - break; - } - } - } - - // Output stored data - llist_traverse(list, dump_chunk); - - // In case of -f - lseek(fd, bytes, SEEK_SET); - return 1; + struct line_list *list = 0, *temp; + int flag = 0, chunk = sizeof(toybuf); + ssize_t pos = lseek(fd, 0, SEEK_END); + + // If lseek() doesn't work on this stream, return now. + if (pos<0) return 0; + + // Seek to the right spot, output data from there. + if (bytes) { + if (lseek(fd, bytes, SEEK_END)<0) lseek(fd, 0, SEEK_SET); + xsendfile(fd, 1); + return 1; + } + + // Read from end to find enough lines, then output them. + + bytes = pos; + while (lines && pos) { + int offset; + + // Read in next chunk from end of file + if (chunk>pos) chunk = pos; + pos -= chunk; + if (pos != lseek(fd, pos, SEEK_SET)) { + perror_msg("seek failed"); + break; + } + if (!(temp = get_chunk(fd, chunk))) break; + if (list) list->next = temp; + list = temp; + + // Count newlines in this chunk. + offset = list->len; + while (offset--) { + // If the last line ends with a newline, that one doesn't count. + if (!flag) { + flag++; + + continue; + } + + // Start outputting data right after newline + if (list->data[offset] == '\n' && !++lines) { + offset++; + list->data += offset; + list->len -= offset; + + break; + } + } + } + + // Output stored data + llist_traverse(list, dump_chunk); + + // In case of -f + lseek(fd, bytes, SEEK_SET); + return 1; } // Called for each file listed on command line, and/or stdin static void do_tail(int fd, char *name) { - long bytes = TT.bytes, lines = TT.lines; - - if (toys.optc > 1) { - if (TT.file_no++) xputc('\n'); - xprintf("==> %s <==\n", name); - } - - // Are we measuring from the end of the file? - - if (bytes<0 || lines<0) { - struct line_list *list = 0, *new; - - // The slow codepath is always needed, and can handle all input, - // so make lseek support optional. - if (CFG_TAIL_SEEK && try_lseek(fd, bytes, lines)); - - // Read data until we run out, keep a trailing buffer - else for (;;) { - int len, count; - char *try; - - if (!(new = get_chunk(fd, sizeof(toybuf)))) break; - // append in order - dlist_add_nomalloc((struct double_list **)&list, - (struct double_list *)new); - - // Measure new chunk, discarding extra data from buffer - len = new->len; - try = new->data; - for (count=0; countdata++); - if (!(--list->len)) { - struct line_list *next = list->next; - list->prev->next = next; - list->next->prev = list->prev; - free(list); - list = next; - } - if (c == '\n') break; - } while (lines); - } - } - - // Output/free the buffer. - llist_traverse(list, dump_chunk); - - // Measuring from the beginning of the file. - } else for (;;) { - int len, offset = 0; - - // Error while reading does not exit. Error writing does. - len = read(fd, toybuf, sizeof(toybuf)); - if (len<1) break; - while (bytes > 1 || lines > 1) { - bytes--; - if (toybuf[offset++] == '\n') lines--; - if (offset >= len) break; - } - if (offset 1) { + if (TT.file_no++) xputc('\n'); + xprintf("==> %s <==\n", name); + } + + // Are we measuring from the end of the file? + + if (bytes<0 || lines<0) { + struct line_list *list = 0, *new; + + // The slow codepath is always needed, and can handle all input, + // so make lseek support optional. + if (CFG_TAIL_SEEK && try_lseek(fd, bytes, lines)); + + // Read data until we run out, keep a trailing buffer + else for (;;) { + int len, count; + char *try; + + if (!(new = get_chunk(fd, sizeof(toybuf)))) break; + // append in order + dlist_add_nomalloc((struct double_list **)&list, + (struct double_list *)new); + + // Measure new chunk, discarding extra data from buffer + len = new->len; + try = new->data; + for (count=0; countdata++); + if (!(--list->len)) { + struct line_list *next = list->next; + list->prev->next = next; + list->next->prev = list->prev; + free(list); + list = next; + } + if (c == '\n') break; + } while (lines); + } + } + + // Output/free the buffer. + llist_traverse(list, dump_chunk); + + // Measuring from the beginning of the file. + } else for (;;) { + int len, offset = 0; + + // Error while reading does not exit. Error writing does. + len = read(fd, toybuf, sizeof(toybuf)); + if (len<1) break; + while (bytes > 1 || lines > 1) { + bytes--; + if (toybuf[offset++] == '\n') lines--; + if (offset >= len) break; + } + if (offset * @@ -9,66 +7,65 @@ USE_TEE(NEWTOY(tee, "ia", TOYFLAG_BIN)) config TEE - bool "tee" - default y - help - usage: tee [-ai] [file...] + bool "tee" + default y + help + usage: tee [-ai] [file...] - Copy stdin to each listed file, and also to stdout. - Filename "-" is a synonym for stdout. + Copy stdin to each listed file, and also to stdout. + Filename "-" is a synonym for stdout. - -a append to files. - -i ignore SIGINT. + -a append to files. + -i ignore SIGINT. */ #define FOR_tee #include "toys.h" GLOBALS( - void *outputs; + void *outputs; ) struct fd_list { - struct fd_list *next; - int fd; + struct fd_list *next; + int fd; }; // Open each output file, saving filehandles to a linked list. static void do_tee_open(int fd, char *name) { - struct fd_list *temp; + struct fd_list *temp; - temp = xmalloc(sizeof(struct fd_list)); - temp->next = TT.outputs; - temp->fd = fd; - TT.outputs = temp; + temp = xmalloc(sizeof(struct fd_list)); + temp->next = TT.outputs; + temp->fd = fd; + TT.outputs = temp; } void tee_main(void) { - if (toys.optflags & FLAG_i) signal(SIGINT, SIG_IGN); + if (toys.optflags & FLAG_i) signal(SIGINT, SIG_IGN); - // Open output files - loopfiles_rw(toys.optargs, - O_RDWR|O_CREAT|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), - 0666, 0, do_tee_open); + // Open output files + loopfiles_rw(toys.optargs, + O_RDWR|O_CREAT|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), + 0666, 0, do_tee_open); - for (;;) { - struct fd_list *fdl; - int len; + for (;;) { + struct fd_list *fdl; + int len; - // Read data from stdin - len = xread(0, toybuf, sizeof(toybuf)); - if (len<1) break; + // Read data from stdin + len = xread(0, toybuf, sizeof(toybuf)); + if (len<1) break; - // Write data to each output file, plus stdout. - fdl = TT.outputs; - for (;;) { - if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1; - if (!fdl) break; - fdl = fdl->next; - } + // Write data to each output file, plus stdout. + fdl = TT.outputs; + for (;;) { + if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1; + if (!fdl) break; + fdl = fdl->next; } - + } } diff --git a/toys/posix/true.c b/toys/posix/true.c index e2e7ea62..09e551c3 100644 --- a/toys/posix/true.c +++ b/toys/posix/true.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * true.c - Return zero. +/* true.c - Return zero. * * Copyright 2007 Rob Landley * @@ -9,15 +7,15 @@ USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN)) config TRUE - bool "true" - default y - help - Return zero. + bool "true" + default y + help + Return zero. */ #include "toys.h" void true_main(void) { - return; + return; } diff --git a/toys/posix/tty.c b/toys/posix/tty.c index 661e919a..578c9aff 100644 --- a/toys/posix/tty.c +++ b/toys/posix/tty.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * tty.c - Show stdin's terminal name +/* tty.c - Show stdin's terminal name * * Copyright 2011 Rob Landley * @@ -9,24 +7,24 @@ USE_TTY(NEWTOY(tty, "s", TOYFLAG_USR|TOYFLAG_BIN)) config TTY - bool "tty" - default y - help - Show filename of terminal connected to stdin. + bool "tty" + default y + help + Show filename of terminal connected to stdin. - Prints "not a tty" and exits with nonzero status if no terminal - is connected to stdin. + Prints "not a tty" and exits with nonzero status if no terminal + is connected to stdin. - -s silent mode + -s silent mode */ #include "toys.h" void tty_main(void) { - char *tty = ttyname(0); + char *tty = ttyname(0); - if (!toys.optflags) puts(tty ? tty : "not a tty"); + if (!toys.optflags) puts(tty ? tty : "not a tty"); - toys.exitval = !tty; + toys.exitval = !tty; } diff --git a/toys/posix/uname.c b/toys/posix/uname.c index fcc92a08..2c1a0504 100644 --- a/toys/posix/uname.c +++ b/toys/posix/uname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * uname.c - return system name +/* uname.c - return system name * * Copyright 2008 Rob Landley * @@ -9,19 +7,19 @@ USE_UNAME(NEWTOY(uname, "amvrns", TOYFLAG_BIN)) config UNAME - bool "uname" - default y - help - usage: uname [-asnrvmpio] + bool "uname" + default y + help + usage: uname [-asnrvmpio] - Print system information. + Print system information. - -s System name - -n Network (domain) name - -r Release number - -v Version (build date) - -m Machine (hardware) name - -a All of the above + -s System name + -n Network (domain) name + -r Release number + -v Version (build date) + -m Machine (hardware) name + -a All of the above */ #define FOR_uname @@ -42,34 +40,34 @@ config UNAME void uname_main(void) { - int i, flags = toys.optflags, needspace=0; + int i, flags = toys.optflags, needspace=0; - uname((void *)toybuf); + uname((void *)toybuf); - if (!flags) flags = FLAG_s; - for (i=0; i<5; i++) { - char *c = toybuf+(65*i); + if (!flags) flags = FLAG_s; + for (i=0; i<5; i++) { + char *c = toybuf+(65*i); - if (flags & ((1< * @@ -9,116 +7,113 @@ USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_BIN)) config UNIQ - bool "uniq" - default y - help - usage: uniq [-cduiz] [-w maxchars] [-f fields] [-s char] [input_file [output_file]] - - Report or filter out repeated lines in a file - - -c show counts before each line - -d show only lines that are repeated - -u show only lines that are unique - -i ignore case when comparing lines - -z lines end with \0 not \n - -w compare maximum X chars per line - -f ignore first X fields - -s ignore first X chars + bool "uniq" + default y + help + usage: uniq [-cduiz] [-w maxchars] [-f fields] [-s char] [input_file [output_file]] + + Report or filter out repeated lines in a file + + -c show counts before each line + -d show only lines that are repeated + -u show only lines that are unique + -i ignore case when comparing lines + -z lines end with \0 not \n + -w compare maximum X chars per line + -f ignore first X fields + -s ignore first X chars */ #define FOR_uniq #include "toys.h" GLOBALS( - long maxchars; - long nchars; - long nfields; - long repeats; + long maxchars; + long nchars; + long nfields; + long repeats; ) static char *skip(char *str) { - long nchars = TT.nchars, nfields; - - // Skip fields first - for (nfields = TT.nfields; nfields; str++) { - while (*str && isspace(*str)) str++; - while (*str && !isspace(*str)) str++; - nfields--; - } - // Skip chars - while (*str && nchars--) str++; - - return str; + long nchars = TT.nchars, nfields; + + // Skip fields first + for (nfields = TT.nfields; nfields; str++) { + while (*str && isspace(*str)) str++; + while (*str && !isspace(*str)) str++; + nfields--; + } + // Skip chars + while (*str && nchars--) str++; + + return str; } static void print_line(FILE *f, char *line) { - if (toys.optflags & (TT.repeats ? FLAG_u : FLAG_d)) return; - if (toys.optflags & FLAG_c) fprintf(f, "%7lu ", TT.repeats + 1); - fputs(line, f); - if (toys.optflags & FLAG_z) fputc(0, f); + if (toys.optflags & (TT.repeats ? FLAG_u : FLAG_d)) return; + if (toys.optflags & FLAG_c) fprintf(f, "%7lu ", TT.repeats + 1); + fputs(line, f); + if (toys.optflags & FLAG_z) fputc(0, f); } void uniq_main(void) { - FILE *infile = stdin, *outfile = stdout; - char *thisline = NULL, *prevline = NULL, *tmpline, eol = '\n'; - size_t thissize, prevsize = 0, tmpsize; - - if (toys.optc >= 1) infile = xfopen(toys.optargs[0], "r"); - if (toys.optc >= 2) outfile = xfopen(toys.optargs[1], "w"); - - if (toys.optflags & FLAG_z) eol = 0; - - // If first line can't be read - if (getdelim(&prevline, &prevsize, eol, infile) < 0) - return; - - while (getdelim(&thisline, &thissize, eol, infile) > 0) { - int diff; - char *t1, *t2; - - // If requested get the chosen fields + character offsets. - if (TT.nfields || TT.nchars) { - t1 = skip(thisline); - t2 = skip(prevline); - } else { - t1 = thisline; - t2 = prevline; - } - - if (TT.maxchars == 0) { - diff = !(toys.optflags & FLAG_i) - ? strcmp(t1, t2) - : strcasecmp(t1, t2); - } else { - diff = !(toys.optflags & FLAG_i) - ? strncmp(t1, t2, TT.maxchars) - : strncasecmp(t1, t2, TT.maxchars); - } - - if (diff == 0) { // same - TT.repeats++; - } else { - print_line(outfile, prevline); - - TT.repeats = 0; - - tmpline = prevline; - prevline = thisline; - thisline = tmpline; - - tmpsize = prevsize; - prevsize = thissize; - thissize = tmpsize; - } - } - - print_line(outfile, prevline); - - if (CFG_TOYBOX_FREE) { - free(prevline); - free(thisline); - } + FILE *infile = stdin, *outfile = stdout; + char *thisline = NULL, *prevline = NULL, *tmpline, eol = '\n'; + size_t thissize, prevsize = 0, tmpsize; + + if (toys.optc >= 1) infile = xfopen(toys.optargs[0], "r"); + if (toys.optc >= 2) outfile = xfopen(toys.optargs[1], "w"); + + if (toys.optflags & FLAG_z) eol = 0; + + // If first line can't be read + if (getdelim(&prevline, &prevsize, eol, infile) < 0) + return; + + while (getdelim(&thisline, &thissize, eol, infile) > 0) { + int diff; + char *t1, *t2; + + // If requested get the chosen fields + character offsets. + if (TT.nfields || TT.nchars) { + t1 = skip(thisline); + t2 = skip(prevline); + } else { + t1 = thisline; + t2 = prevline; + } + + if (TT.maxchars == 0) { + diff = !(toys.optflags & FLAG_i) ? strcmp(t1, t2) : strcasecmp(t1, t2); + } else { + diff = !(toys.optflags & FLAG_i) ? strncmp(t1, t2, TT.maxchars) + : strncasecmp(t1, t2, TT.maxchars); + } + + if (diff == 0) { // same + TT.repeats++; + } else { + print_line(outfile, prevline); + + TT.repeats = 0; + + tmpline = prevline; + prevline = thisline; + thisline = tmpline; + + tmpsize = prevsize; + prevsize = thissize; + thissize = tmpsize; + } + } + + print_line(outfile, prevline); + + if (CFG_TOYBOX_FREE) { + free(prevline); + free(thisline); + } } diff --git a/toys/posix/unlink.c b/toys/posix/unlink.c index 19660c5d..4faef9dc 100644 --- a/toys/posix/unlink.c +++ b/toys/posix/unlink.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * unlink.c - delete one file +/* unlink.c - delete one file * * Copyright 2011 Rob Landley * @@ -9,18 +7,18 @@ USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN)) config UNLINK - bool "unlink" - default y - help - usage: unlink FILE + bool "unlink" + default y + help + usage: unlink FILE - Deletes one file. + Deletes one file. */ #include "toys.h" void unlink_main(void) { - if (unlink(*toys.optargs)) - perror_exit("Couldn't unlink `%s'", *toys.optargs); + if (unlink(*toys.optargs)) + perror_exit("Couldn't unlink `%s'", *toys.optargs); } diff --git a/toys/posix/wc.c b/toys/posix/wc.c index 3896b73a..19ba4b8b 100644 --- a/toys/posix/wc.c +++ b/toys/posix/wc.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * wc.c - Word count +/* wc.c - Word count * * Copyright 2011 Rob Landley * @@ -9,90 +7,88 @@ USE_WC(NEWTOY(wc, "mcwl", TOYFLAG_USR|TOYFLAG_BIN)) config WC - bool "wc" - default y - help - usage: wc -lwcm [FILE...] + bool "wc" + default y + help + usage: wc -lwcm [FILE...] - Count lines, words, and characters in input. + Count lines, words, and characters in input. - -l show lines - -w show words - -c show bytes - -m show characters + -l show lines + -w show words + -c show bytes + -m show characters - By default outputs lines, words, bytes, and filename for each - argument (or from stdin if none). Displays only either bytes - or characters. + By default outputs lines, words, bytes, and filename for each + argument (or from stdin if none). Displays only either bytes + or characters. */ #define FOR_wc #include "toys.h" GLOBALS( - unsigned long totals[3]; + unsigned long totals[3]; ) static void show_lengths(unsigned long *lengths, char *name) { - int i, nospace = 1; - for (i=0; i<3; i++) { - if (!toys.optflags || (toys.optflags&(1<>1; - loopfiles(toys.optargs, do_wc); - if (toys.optc>1) show_lengths(TT.totals, "total"); + setlocale(LC_ALL, ""); + toys.optflags |= (toys.optflags&8)>>1; + loopfiles(toys.optargs, do_wc); + if (toys.optc>1) show_lengths(TT.totals, "total"); } diff --git a/toys/posix/who.c b/toys/posix/who.c index 5f888d71..d09a9325 100644 --- a/toys/posix/who.c +++ b/toys/posix/who.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * who.c - display who is on the system +/* who.c - display who is on the system * * Copyright 2012 ProFUSION Embedded Systems * @@ -11,36 +9,35 @@ USE_WHO(NEWTOY(who, NULL, TOYFLAG_BIN)) config WHO - bool "who" - default n - help - usage: who - - Print logged user information on system + bool "who" + default n + help + usage: who + Print logged user information on system */ #include "toys.h" void who_main(void) { - struct utmpx *entry; - - setutxent(); + struct utmpx *entry; - while ((entry = getutxent())) { - if (entry->ut_type == USER_PROCESS) { - time_t time; - int time_size; - char * times; + setutxent(); - time = entry->ut_tv.tv_sec; - times = ctime(&time); - time_size = strlen(times) - 2; - printf("%s\t%s\t%*.*s\t(%s)\n", entry->ut_user, entry->ut_line, time_size, time_size, ctime(&time), entry->ut_host); + while ((entry = getutxent())) { + if (entry->ut_type == USER_PROCESS) { + time_t time; + int time_size; + char * times; - } + time = entry->ut_tv.tv_sec; + times = ctime(&time); + time_size = strlen(times) - 2; + printf("%s\t%s\t%*.*s\t(%s)\n", entry->ut_user, entry->ut_line, + time_size, time_size, ctime(&time), entry->ut_host); } + } - endutxent(); + endutxent(); } diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c index 8f19d07f..18b70f2e 100644 --- a/toys/posix/xargs.c +++ b/toys/posix/xargs.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * xargs.c - Run command with arguments taken from stdin. +/* xargs.c - Run command with arguments taken from stdin. * * Copyright 2011 Rob Landley * @@ -9,42 +7,42 @@ USE_XARGS(NEWTOY(xargs, "^I:E:L#ptxrn#<1s#0", TOYFLAG_USR|TOYFLAG_BIN)) config XARGS - bool "xargs" - default y - help - usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND... - - Run command line one or more times, appending arguments from stdin. - - If command exits with 255, don't launch another even if arguments remain. - - -s Size in bytes per command line - -n Max number of arguments per command - -0 Each argument is NULL terminated, no whitespace or quote processing - #-p Prompt for y/n from tty before running each command - #-t Trace, print command line to stderr - #-x Exit if can't fit everything in one command - #-r Don't run command with empty input - #-L Max number of lines of input per command - -E stop at line matching string + bool "xargs" + default y + help + usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND... + + Run command line one or more times, appending arguments from stdin. + + If command exits with 255, don't launch another even if arguments remain. + + -s Size in bytes per command line + -n Max number of arguments per command + -0 Each argument is NULL terminated, no whitespace or quote processing + #-p Prompt for y/n from tty before running each command + #-t Trace, print command line to stderr + #-x Exit if can't fit everything in one command + #-r Don't run command with empty input + #-L Max number of lines of input per command + -E stop at line matching string */ #define FOR_xargs #include "toys.h" GLOBALS( - long max_bytes; - long max_entries; - long L; - char *eofstr; - char *I; - - long entries, bytes; - char delim; + long max_bytes; + long max_entries; + long L; + char *eofstr; + char *I; + + long entries, bytes; + char delim; ) // If out==NULL count TT.bytes and TT.entries, stopping at max. -// Otherwise, fill out out[] +// Otherwise, fill out out[] // Returning NULL means need more data. // Returning char * means hit data limits, start of data left over @@ -53,135 +51,135 @@ GLOBALS( static char *handle_entries(char *data, char **entry) { - if (TT.delim) { - char *s = data; - - // Chop up whitespace delimited string into args - while (*s) { - char *save; - - while (isspace(*s)) { - if (entry) *s = 0; - s++; - } - - if (TT.max_entries && TT.entries >= TT.max_entries) - return *s ? s : (char *)1; - - if (!*s) break; - save = s; - - for (;;) { - if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save; - if (!*s || isspace(*s)) break; - s++; - } - if (TT.eofstr) { - int len = s-save; - if (len == strlen(TT.eofstr) && !strncmp(save, TT.eofstr, len)) - return (char *)2; - } - if (entry) entry[TT.entries] = save; - ++TT.entries; - } - - // -0 support - } else { - TT.bytes += strlen(data)+1; - if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data; - if (TT.max_entries && TT.entries >= TT.max_entries) - return (char *)1; - if (entry) entry[TT.entries] = data; - TT.entries++; - } - - return NULL; + if (TT.delim) { + char *s = data; + + // Chop up whitespace delimited string into args + while (*s) { + char *save; + + while (isspace(*s)) { + if (entry) *s = 0; + s++; + } + + if (TT.max_entries && TT.entries >= TT.max_entries) + return *s ? s : (char *)1; + + if (!*s) break; + save = s; + + for (;;) { + if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save; + if (!*s || isspace(*s)) break; + s++; + } + if (TT.eofstr) { + int len = s-save; + if (len == strlen(TT.eofstr) && !strncmp(save, TT.eofstr, len)) + return (char *)2; + } + if (entry) entry[TT.entries] = save; + ++TT.entries; + } + + // -0 support + } else { + TT.bytes += strlen(data)+1; + if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data; + if (TT.max_entries && TT.entries >= TT.max_entries) + return (char *)1; + if (entry) entry[TT.entries] = data; + TT.entries++; + } + + return NULL; } void xargs_main(void) { - struct double_list *dlist = NULL; - int entries, bytes, done = 0, status; - char *data = NULL; - - if (!(toys.optflags & FLAG_0)) TT.delim = '\n'; - - // If no optargs, call echo. - if (!toys.optc) { - free(toys.optargs); - *(toys.optargs = xzalloc(2*sizeof(char *)))="echo"; - toys.optc = 1; - } - - for (entries = 0, bytes = -1; entries < toys.optc; entries++, bytes++) - bytes += strlen(toys.optargs[entries]); - - // Loop through exec chunks. - while (data || !done) { - char **out; - - TT.entries = 0; - TT.bytes = bytes; - - // Loop reading input - for (;;) { - - // Read line - if (!data) { - ssize_t l = 0; - l = getdelim(&data, (size_t *)&l, TT.delim, stdin); - - if (l<0) { - data = 0; - done++; - break; - } - } - dlist_add(&dlist, data); - - // Count data used - data = handle_entries(data, NULL); - if (!data) continue; - if (data == (char *)2) done++; - if ((long)data <= 2) data = 0; - else data = xstrdup(data); - - break; - } - - // Accumulate cally thing - - if (data && !TT.entries) error_exit("argument too long"); - out = xzalloc((entries+TT.entries+1)*sizeof(char *)); - - if (dlist) { - struct double_list *dtemp; - - // Fill out command line to exec - memcpy(out, toys.optargs, entries*sizeof(char *)); - TT.entries = 0; - TT.bytes = bytes; - dlist->prev->next = 0; - for (dtemp = dlist; dtemp; dtemp = dtemp->next) - handle_entries(dtemp->data, out+entries); - } - pid_t pid=fork(); - if (!pid) { - xclose(0); - open("/dev/null", O_RDONLY); - xexec(out); - } - waitpid(pid, &status, 0); - status = WEXITSTATUS(status); - - // Abritrary number of execs, can't just leak memory each time... - while (dlist) { - struct double_list *dtemp = dlist->next; - - free(dlist->data); - free(dlist); - dlist = dtemp; - } - free(out); - } + struct double_list *dlist = NULL; + int entries, bytes, done = 0, status; + char *data = NULL; + + if (!(toys.optflags & FLAG_0)) TT.delim = '\n'; + + // If no optargs, call echo. + if (!toys.optc) { + free(toys.optargs); + *(toys.optargs = xzalloc(2*sizeof(char *)))="echo"; + toys.optc = 1; + } + + for (entries = 0, bytes = -1; entries < toys.optc; entries++, bytes++) + bytes += strlen(toys.optargs[entries]); + + // Loop through exec chunks. + while (data || !done) { + char **out; + + TT.entries = 0; + TT.bytes = bytes; + + // Loop reading input + for (;;) { + + // Read line + if (!data) { + ssize_t l = 0; + l = getdelim(&data, (size_t *)&l, TT.delim, stdin); + + if (l<0) { + data = 0; + done++; + break; + } + } + dlist_add(&dlist, data); + + // Count data used + data = handle_entries(data, NULL); + if (!data) continue; + if (data == (char *)2) done++; + if ((long)data <= 2) data = 0; + else data = xstrdup(data); + + break; + } + + // Accumulate cally thing + + if (data && !TT.entries) error_exit("argument too long"); + out = xzalloc((entries+TT.entries+1)*sizeof(char *)); + + if (dlist) { + struct double_list *dtemp; + + // Fill out command line to exec + memcpy(out, toys.optargs, entries*sizeof(char *)); + TT.entries = 0; + TT.bytes = bytes; + dlist->prev->next = 0; + for (dtemp = dlist; dtemp; dtemp = dtemp->next) + handle_entries(dtemp->data, out+entries); + } + pid_t pid=fork(); + if (!pid) { + xclose(0); + open("/dev/null", O_RDONLY); + xexec(out); + } + waitpid(pid, &status, 0); + status = WEXITSTATUS(status); + + // Abritrary number of execs, can't just leak memory each time... + while (dlist) { + struct double_list *dtemp = dlist->next; + + free(dlist->data); + free(dlist); + dlist = dtemp; + } + free(out); + } } diff --git a/www/code.html b/www/code.html index 4f0843dc..75483564 100644 --- a/www/code.html +++ b/www/code.html @@ -13,11 +13,8 @@ This helps code auditing and thus reduces bugs. That said, sometimes being more explicit is preferable to being clever enough to outsmart yourself: don't be so terse your code is unreadable.

-

Toybox source is formatted to be read with 4-space tab stops. Each file -starts with a special comment telling vi to set the tab stop to 4. Note that -one of the bugs in Ubuntu 7.10 broke vi's ability to parse these comments; you -must either rebuild vim from source, or go ":ts=4" yourself each time you load -the file.

+

Toybox source uses two spaces per indentation level, and wraps at 80 +columns.

Gotos are allowed for error handling, and for breaking out of nested loops. In general, a goto should only jump forward (not back), and @@ -31,7 +28,7 @@ to spot as overrides to the normal flow of control, which they are.

Toybox is configured using the Kconfig language pioneered by the Linux kernel, and adopted by many other projects (uClibc, OpenEmbedded, etc). This generates a ".config" file containing the selected options, which -controls which features to enable when building toybox.

+controls which features are included when compiling toybox.

Each configuration option has a default value. The defaults indicate the "maximum sane configuration", I.E. if the feature defaults to "n" then it diff --git a/www/design.html b/www/design.html index 5adae0a9..ce5fc55b 100644 --- a/www/design.html +++ b/www/design.html @@ -71,7 +71,7 @@ but it's just as true that a loop which stays in L1 cache is many times faster than a loop that has to wait for a DRAM fetch on each iteration. Don't worry about whether "&" is faster than "%" until your executable loop stays in L1 cache and the data access is fetching cache lines intelligently. (To -understand DRAM, L1, and L2 cache, read Hannibal's marvelous ram guid at Ars +understand DRAM, L1, and L2 cache, read Hannibal's marvelous ram guide at Ars Technica: part one, part two, @@ -277,7 +277,7 @@ messages produced by perror_exit() and friends can be expected to be localized by libc. Our error functions also prepend the command name, which non-english speakers can presumably recognize already.

-

An enventual goal is UTF-8 support, although it isn't a priority for the +

An enventual goal is UTF-8 support, although it isn't a priority for the first pass of each command. (All commands should at least be 8-bit clean.)

Locale support isn't currently a goal; that's a presentation layer issue, -- cgit v1.2.3