diff options
author | Rob Landley <rob@landley.net> | 2012-11-13 17:14:08 -0600 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2012-11-13 17:14:08 -0600 |
commit | 7aa651a6a4496d848f86de9b1e6b3a003256a01f (patch) | |
tree | 6995fb4b7cc2e90a6706b0239ebaf95d9dbab530 | |
parent | 571b0706cce45716126776d0ad0f6ac65f4586e3 (diff) | |
download | toybox-7aa651a6a4496d848f86de9b1e6b3a003256a01f.tar.gz |
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.
117 files changed, 7996 insertions, 8245 deletions
@@ -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 <rob@landley.net> */ @@ -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<<i; - } else if (*options == '[') { // TODO - } else if (-1 != (idx = stridx("|^ ", *options))) - new->flags |= 1<<idx; - // bounds checking - else if (-1 != (idx = stridx("<>=", *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<<i; + } else if (*options == '[') { // TODO + } else if (-1 != (idx = stridx("|^ ", *options))) new->flags |= 1<<idx; + // bounds checking + else if (-1 != (idx = stridx("<>=", *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.optc<gof.minargs) { - error_exit("Need%s %d argument%s", letters[!!(gof.minargs-1)], - gof.minargs, letters[!(gof.minargs-1)]); - } - if (toys.optc>gof.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.optc<gof.minargs) + error_exit("Need%s %d argument%s", letters[!!(gof.minargs-1)], + gof.minargs, letters[!(gof.minargs-1)]); + if (toys.optc>gof.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<<bd->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<<bits_wanted)-1); - - return bits; + 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<<bd->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<<bits_wanted)-1); + + return bits; } /* Read block header at start of a new compressed data block. Consists of: @@ -139,156 +137,153 @@ static unsigned int get_bits(struct bunzip_data *bd, char bits_wanted) static int read_block_header(struct bunzip_data *bd, struct bwdata *bw) { - 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; ii<bd->groupCount; ii++) bd->mtfSymbol[ii] = ii; - for (ii=0; ii<bd->nSelectors; 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; jj<bd->groupCount; 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; ii<bd->groupCount; ii++) bd->mtfSymbol[ii] = ii; + for (ii=0; ii<bd->nSelectors; 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; jj<bd->groupCount; 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; i<THREADS; i++) - bd->bwdata[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; i<THREADS; i++) + bd->bwdata[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; j<THREADS; j++) free(bd->bwdata[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; j<THREADS; j++) free(bd->bwdata[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 <rob@landley.net> @@ -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 <rob@landley.net> @@ -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; } @@ -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<len) { - int i = read(fd, buf+count, len-count); - if (!i) break; - if (i<0) return i; - count += i; - } + while (count<len) { + int i = read(fd, buf+count, len-count); + if (!i) break; + if (i<0) return i; + count += i; + } - return count; + return count; } // Keep writing until done or EOF ssize_t writeall(int fd, void *buf, size_t len) { - size_t count = 0; - while (count<len) { - int i = write(fd, buf+count, len-count); - if (i<1) return i; - count += i; - } + size_t count = 0; + while (count<len) { + int i = write(fd, buf+count, len-count); + if (i<1) return i; + count += i; + } - return count; + return count; } // Die if there's an error other than EOF. size_t xread(int fd, void *buf, size_t len) { - ssize_t ret = read(fd, buf, len); - if (ret < 0) perror_exit("xread"); + ssize_t ret = read(fd, buf, len); + if (ret < 0) perror_exit("xread"); - return ret; + return ret; } void xreadall(int fd, void *buf, size_t len) { - if (len != readall(fd, buf, len)) perror_exit("xreadall"); + if (len != readall(fd, buf, len)) perror_exit("xreadall"); } // There's no xwriteall(), just xwrite(). When we read, there may or may not @@ -273,51 +272,51 @@ void xreadall(int fd, void *buf, size_t len) void xwrite(int fd, void *buf, size_t len) { - if (len != writeall(fd, buf, len)) perror_exit("xwrite"); + if (len != writeall(fd, buf, len)) perror_exit("xwrite"); } // Die if lseek fails, probably due to being called on a pipe. off_t xlseek(int fd, off_t offset, int whence) { - offset = lseek(fd, offset, whence); - if (offset<0) perror_exit("lseek"); + offset = lseek(fd, offset, whence); + if (offset<0) perror_exit("lseek"); - return offset; + return offset; } off_t lskip(int fd, off_t offset) { - off_t and = lseek(fd, offset, SEEK_CUR); + off_t and = lseek(fd, offset, SEEK_CUR); - 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; + 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<size) { - buf[len]=0; - return buf; - } - } + if (len<0) { + free(buf); + return 0; + } + if (len<size) { + buf[len]=0; + return buf; + } + } } /* @@ -628,24 +627,24 @@ char *xreadlink(char *name) // Read contents of file as a single freshly allocated nul-terminated string. char *readfile(char *name) { - off_t len; - int fd; - char *buf; + off_t len; + int fd; + char *buf; - fd = open(name, O_RDONLY); - if (fd == -1) return 0; - len = fdlength(fd); - buf = xmalloc(len+1); - buf[readall(fd, buf, len)] = 0; + fd = open(name, O_RDONLY); + if (fd == -1) return 0; + len = fdlength(fd); + buf = xmalloc(len+1); + buf[readall(fd, buf, len)] = 0; - return buf; + return buf; } char *xreadfile(char *name) { - char *buf = readfile(name); - if (!buf) perror_exit("xreadfile %s", name); - return buf; + char *buf = readfile(name); + if (!buf) perror_exit("xreadfile %s", name); + return buf; } */ @@ -654,33 +653,33 @@ char *xreadfile(char *name) // exists and is this executable. void xpidfile(char *name) { - char pidfile[256], spid[32]; - int i, fd; - pid_t pid; - - sprintf(pidfile, "/var/run/%s.pid", name); - // Try three times to open the sucker. - for (i=0; i<3; i++) { - fd = open(pidfile, O_CREAT|O_EXCL, 0644); - if (fd != -1) break; + char pidfile[256], spid[32]; + int i, fd; + pid_t pid; + + sprintf(pidfile, "/var/run/%s.pid", name); + // Try three times to open the sucker. + for (i=0; i<3; i++) { + fd = open(pidfile, O_CREAT|O_EXCL, 0644); + if (fd != -1) break; - // If it already existed, read it. Loop for race condition. - fd = open(pidfile, O_RDONLY); - if (fd == -1) continue; + // If it already existed, read it. Loop for race condition. + fd = open(pidfile, O_RDONLY); + if (fd == -1) continue; - // Is the old program still there? - spid[xread(fd, spid, sizeof(spid)-1)] = 0; - close(fd); - pid = atoi(spid); - if (pid < 1 || kill(pid, 0) == ESRCH) unlink(pidfile); + // Is the old program still there? + spid[xread(fd, spid, sizeof(spid)-1)] = 0; + close(fd); + pid = atoi(spid); + if (pid < 1 || kill(pid, 0) == ESRCH) unlink(pidfile); - // An else with more sanity checking might be nice here. - } + // An else with more sanity checking might be nice here. + } - if (i == 3) error_exit("xpidfile %s", name); + if (i == 3) error_exit("xpidfile %s", name); - xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid())); - close(fd); + xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid())); + close(fd); } // Iterate through an array of files, opening each one and calling a function @@ -691,157 +690,157 @@ void xpidfile(char *name) // Note: read only filehandles are automatically closed when function() // returns, but writeable filehandles must be close by function() void loopfiles_rw(char **argv, int flags, int permissions, int failok, - void (*function)(int fd, char *name)) + void (*function)(int fd, char *name)) { - int fd; + int fd; - // If no arguments, read from stdin. - if (!*argv) function(flags ? 1 : 0, "-"); - else do { - // Filename "-" means read from stdin. - // Inability to open a file prints a warning, but doesn't exit. + // If no arguments, read from stdin. + if (!*argv) function(flags ? 1 : 0, "-"); + else do { + // Filename "-" means read from stdin. + // Inability to open a file prints a warning, but doesn't exit. - 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); + 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<sizeof(signames)/sizeof(struct signame); i++) - if (signames[i].num == sig) return signames[i].name; - return NULL; + for (i=0; i<sizeof(signames)/sizeof(struct signame); i++) + if (signames[i].num == sig) return signames[i].name; + return NULL; } // premute mode bits based on posix mode strings. mode_t string_to_mode(char *modestr, mode_t mode) { - char *whos = "ogua", *hows = "=+-", *whats = "xwrstX", *whys = "ogu"; - char *s, *str = modestr; - - // Handle octal mode - if (isdigit(*str)) { - mode = strtol(str, &s, 8); - if (*s || (mode & ~(07777))) goto barf; - - return mode; - } - - // Gaze into the bin of permission... - for (;;) { - int i, j, dowho, dohow, dowhat, amask; - - dowho = dohow = dowhat = amask = 0; - - // Find the who, how, and what stanzas, in that order - while (*str && (s = strchr(whos, *str))) { - dowho |= 1<<(s-whos); - str++; - } - // If who isn't specified, like "a" but honoring umask. - if (!dowho) { - dowho = 8; - umask(amask=umask(0)); - } - if (!*str || !(s = strchr(hows, *str))) goto barf; - dohow = *(str++); - - if (!dohow) goto barf; - while (*str && (s = strchr(whats, *str))) { - dowhat |= 1<<(s-whats); - str++; - } - - // Convert X to x for directory or if already executable somewhere - if ((dowhat&32) && (S_ISDIR(mode) || (mode&0111))) dowhat |= 1; - - // Copy mode from another category? - if (!dowhat && *str && (s = strchr(whys, *str))) { - dowhat = (mode>>(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<<i)))) bit++; - } else if (dowhat & 16) bit++; - } else { - if (!(dowho&(8|(1<<i)))) continue; - if (dowhat&(1<<j)) bit++; - } - - // When selection active, modify bit - - if (dohow == '=' || (bit && dohow == '-')) - mode &= ~where; - if (bit && dohow != '-') mode |= where; - } - } - - if (!*str) break; - } - return mode; + char *whos = "ogua", *hows = "=+-", *whats = "xwrstX", *whys = "ogu"; + char *s, *str = modestr; + + // Handle octal mode + if (isdigit(*str)) { + mode = strtol(str, &s, 8); + if (*s || (mode & ~(07777))) goto barf; + + return mode; + } + + // Gaze into the bin of permission... + for (;;) { + int i, j, dowho, dohow, dowhat, amask; + + dowho = dohow = dowhat = amask = 0; + + // Find the who, how, and what stanzas, in that order + while (*str && (s = strchr(whos, *str))) { + dowho |= 1<<(s-whos); + str++; + } + // If who isn't specified, like "a" but honoring umask. + if (!dowho) { + dowho = 8; + umask(amask=umask(0)); + } + if (!*str || !(s = strchr(hows, *str))) goto barf; + dohow = *(str++); + + if (!dohow) goto barf; + while (*str && (s = strchr(whats, *str))) { + dowhat |= 1<<(s-whats); + str++; + } + + // Convert X to x for directory or if already executable somewhere + if ((dowhat&32) && (S_ISDIR(mode) || (mode&0111))) dowhat |= 1; + + // Copy mode from another category? + if (!dowhat && *str && (s = strchr(whys, *str))) { + dowhat = (mode>>(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<<i)))) bit++; + } else if (dowhat & 16) bit++; + } else { + if (!(dowho&(8|(1<<i)))) continue; + if (dowhat&(1<<j)) bit++; + } + + // When selection active, modify bit + + if (dohow == '=' || (bit && dohow == '-')) mode &= ~where; + if (bit && dohow != '-') mode |= where; + } + } + + if (!*str) break; + } + return mode; barf: - error_exit("bad mode '%s'", modestr); + error_exit("bad mode '%s'", modestr); } char* make_human_readable(unsigned long long size, unsigned long unit) { - unsigned int frac = 0; - if(unit) { - size = (size/(unit)) + (size%(unit)?1:0); - return xmsprintf("%llu", size); + unsigned int frac = 0; + if(unit) { + size = (size/(unit)) + (size%(unit)?1:0); + return xmsprintf("%llu", size); + } + 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++; } - 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 } @@ -1,4 +1,3 @@ -/* vi: set ts=4 :*/ /* lib.h - header file for lib directory * * Copyright 2006 Rob Landley <rob@landley.net> @@ -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 <ak.ashwini@gmail.com> */ @@ -7,136 +6,131 @@ #include "toys.h" #include <time.h> - 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 <rob@landley.net> @@ -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 <rob@landley.net> * @@ -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); + } } @@ -1,4 +1,3 @@ -/* vi: set ts=4 :*/ /* Toybox infrastructure. * * Copyright 2006 Rob Landley <rob@landley.net> @@ -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 (middle<bottom || middle>top) 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 (middle<bottom || middle>top) 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; i<ARRAY_LEN(toy_list); i++) { - int fl = toy_list[i].flags; - if (fl & TOYMASK_LOCATION) { - if (toys.argv[1]) { - int j; - for (j=0; toy_paths[j]; j++) - if (fl & (1<<j)) len += printf("%s", toy_paths[j]); - } - len += printf("%s ",toy_list[i].name); - if (len>65) { - 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; i<ARRAY_LEN(toy_list); i++) { + int fl = toy_list[i].flags; + if (fl & TOYMASK_LOCATION) { + if (toys.argv[1]) { + int j; + for (j=0; toy_paths[j]; j++) + if (fl & (1<<j)) len += printf("%s", toy_paths[j]); + } + len += printf("%s ",toy_list[i].name); + if (len>65) { + 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 <rob@landley.net> @@ -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; i<TOY_LIST_LEN; i++) { - int fl = toy_list[i].flags; - if (fl & TOYMASK_LOCATION) { - if (argc>1) { - int j; - for (j=0; toy_paths[j]; j++) - if (fl & (1<<j)) len += printf("%s", toy_paths[j]); - } - len += printf("%s\n",toy_list[i].name); - } - } - return 0; + // Output list of applets. + for (i=1; i<TOY_LIST_LEN; i++) { + int fl = toy_list[i].flags; + if (fl & TOYMASK_LOCATION) { + if (argc>1) { + int j; + for (j=0; toy_paths[j]; j++) + if (fl & (1<<j)) len += printf("%s", toy_paths[j]); + } + len += printf("%s\n",toy_list[i].name); + } + } + return 0; } diff --git a/scripts/test/basename.test b/scripts/test/basename.test index bd48f4af..2f7a2ec3 100755 --- a/scripts/test/basename.test +++ b/scripts/test/basename.test @@ -7,7 +7,7 @@ # Removal of extra /'s testing "basename /-only" "basename ///////" "/\n" "" "" testing "basename trailing /" "basename a//////" "a\n" "" "" -testing "basename combined" "basename /////a///b///c///d/////" "d\n" "" "" +testing "basename combined" "basename /////a///b///c///d/////" "d\n" "" "" # Standard suffix behavior. testing "basename suffix" "basename a/b/c/d.suffix .suffix" "d\n" "" "" diff --git a/scripts/test/cat.test b/scripts/test/cat.test index 583c4e82..7b4066ac 100755 --- a/scripts/test/cat.test +++ b/scripts/test/cat.test @@ -6,7 +6,7 @@ testing "cat" "cat && echo yes" "oneyes\n" "" "one" testing "cat file1" \ - "cat /bin/cat > 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 index 9afa4508..a0075384 100644..100755 --- 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" @@ -1,4 +1,3 @@ -/* vi: set ts=4 :*/ /* Toybox infrastructure. * * Copyright 2006 Rob Landley <rob@landley.net> @@ -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 <rob@landley.net> */ @@ -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 <rob@landley.net> * @@ -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 <sys/klog.h> 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<size; ) { - if (last=='\n' && data[i]=='<') i += 3; - else xputc(last = data[i++]); - } - if (last!='\n') xputc('\n'); - if (CFG_TOYBOX_FREE) free(data); - } + // 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<size; ) { + if (last=='\n' && data[i]=='<') i += 3; + else xputc(last = data[i++]); + } + if (last!='\n') xputc('\n'); + if (CFG_TOYBOX_FREE) free(data); + } } diff --git a/toys/lsb/hostname.c b/toys/lsb/hostname.c index ca436833..23467fb3 100644 --- a/toys/lsb/hostname.c +++ b/toys/lsb/hostname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * hostname.c - Get/Set the hostname +/* hostname.c - Get/Set the hostname * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> * @@ -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 <aheck@gmx.de> * @@ -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 <rob@landley.net> * @@ -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 <eliedebrauwer@gmail.com> * @@ -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 <eliedebrauwer@gmail.com> * @@ -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 <ak.ashwini@gmail.com> * Modified 2012 Jason Kyungwan Han <asura321@gmail.com> @@ -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] <account name> - - update user’s authentication tokens. Default : current user + bool "passwd" + default y + help + usage: passwd [-a ALGO] [-d] [-l] [-u] <account name> - -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 <time.h> 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; i<salt_length; i++) - salt[i] = inttoc(random_number_generator(randfd)); - salt[salt_length+1] = '\0'; - xclose(randfd); - - return 0; +{ + 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; i<salt_length; i++) + salt[i] = inttoc(random_number_generator(randfd)); + salt[salt_length+1] = '\0'; + xclose(randfd); + + return 0; } static int str_check(char *s, char *p) { - if((strcasestr(s, p) != NULL) || (strcasestr(p, s) != NULL)) - return 1; - return 0; + if((strcasestr(s, p) != NULL) || (strcasestr(p, s) != NULL)) + return 1; + return 0; } static void strength_check(char *newp, char *oldp, char *user) { - char *msg = NULL; - if(strlen(newp) < 6) { //Min passwd len - msg = "too short"; - xprintf("BAD PASSWORD: %s\n",msg); - } - if(!newp[0]) - return; //passwd is empty - - if(str_check(newp, user)) { - msg = "user based password"; - xprintf("BAD PASSWORD: %s\n",msg); - } - - if(oldp[0] && str_check(newp, oldp)) { - msg = "based on old passwd"; - xprintf("BAD PASSWORD: %s\n",msg); - } + char *msg = NULL; + if(strlen(newp) < 6) { //Min passwd len + msg = "too short"; + xprintf("BAD PASSWORD: %s\n",msg); + } + if(!newp[0]) + return; //passwd is empty + + if(str_check(newp, user)) { + msg = "user based password"; + xprintf("BAD PASSWORD: %s\n",msg); + } + + if(oldp[0] && str_check(newp, oldp)) { + msg = "based on old passwd"; + xprintf("BAD PASSWORD: %s\n",msg); + } } static int verify_passwd(char * pwd) -{ - char * pass; +{ + char * pass; - if (!pwd) return 1; - if (pwd[0] == '!' || pwd[0] == '*') return 1; + if (!pwd) return 1; + if (pwd[0] == '!' || pwd[0] == '*') return 1; - pass = crypt(toybuf, pwd); - if (pass != NULL && strcmp(pass, pwd)==0) - return 0; + pass = crypt(toybuf, pwd); + if (pass != NULL && strcmp(pass, pwd)==0) + return 0; - return 1; + return 1; } static char *new_password(char *oldp, char *user) { - char *newp = NULL; - - if(read_password(toybuf, sizeof(toybuf), "New password:")) - return NULL; //may be due to Ctrl-C + char *newp = NULL; - newp = xstrdup(toybuf); - strength_check(newp, oldp, user); - if(read_password(toybuf, sizeof(toybuf), "Retype password:")) { - free(newp); - return NULL; //may be due to Ctrl-C - } + if(read_password(toybuf, sizeof(toybuf), "New password:")) + return NULL; //may be due to Ctrl-C - if(strcmp(newp, toybuf) == 0) - return newp; - else error_msg("Passwords do not match.\n"); - /*Failure Case */ + newp = xstrdup(toybuf); + strength_check(newp, oldp, user); + if(read_password(toybuf, sizeof(toybuf), "Retype password:")) { free(newp); - return NULL; + return NULL; //may be due to Ctrl-C + } + + if(strcmp(newp, toybuf) == 0) + return newp; + else error_msg("Passwords do not match.\n"); + /*Failure Case */ + free(newp); + return NULL; } void passwd_main(void) { - 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; + 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 <aheck@gmx.de> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> 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 <rob@landley.net> * @@ -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<len; i++) { - char c=toybuf[i]; + len = read(fd, toybuf, sizeof(toybuf)); + if (len < 0) toys.exitval = EXIT_FAILURE; + if (len < 1) break; + for (i=0; i<len; i++) { + char c=toybuf[i]; - 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); - } - } + 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 <rob@landley.net> 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 <danders@amltd.com> 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 <rob@landley.net> 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 <rob@landley.net> 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 <rob@landley.net> @@ -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 <eliedebrauwer@gmail.com> 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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <eliedebrauwer@gmail.com> 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 <eliedebrauwer@gmail.com> * @@ -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(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; - buff[i] = 0; + 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(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; + buff[i] = 0; } void handle_nologin(void) { - int fd = open("/etc/nologin", O_RDONLY); - int size; - if (fd == -1) return; - - size = readall(fd, toybuf,sizeof(toybuf)-1); - toybuf[size] = 0; - if (!size) puts("System closed for routine maintenance\n"); - else puts(toybuf); - - close(fd); - fflush(stdout); - exit(EXIT_FAILURE); + int fd = open("/etc/nologin", O_RDONLY); + int size; + if (fd == -1) return; + + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + if (!size) puts("System closed for routine maintenance\n"); + else puts(toybuf); + + close(fd); + fflush(stdout); + exit(EXIT_FAILURE); } void handle_motd(void) { - int fd = open("/etc/motd", O_RDONLY); - int size; - if (fd == -1) return; + int fd = open("/etc/motd", O_RDONLY); + int size; + if (fd == -1) return; - size = readall(fd, toybuf,sizeof(toybuf)-1); - toybuf[size] = 0; - puts(toybuf); + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + puts(toybuf); - close(fd); - fflush(stdout); + close(fd); + fflush(stdout); } int change_identity(const struct passwd *pwd) { - if (initgroups(pwd->pw_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 <eliedebrauwer@gmail.com> 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 <rob@landley.net> * Copyright 2005 Frank Sorenson <frank@tuxrocks.com> @@ -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-conf<len;) { - int field; - char *end2; - - line++; - // find end of this line - for(end = pos; end-conf<len && *end!='\n'; end++); - - // Three fields: regex, uid:gid, mode - for (field = 3; field; field--) { - // Skip whitespace - while (pos<end && isspace(*pos)) pos++; - if (pos==end || *pos=='#') break; - for (end2 = pos; - end2<end && !isspace(*end2) && *end2!='#'; end2++); - switch(field) { - // Regex to match this device - case 3: - { - char *regex = strndup(pos, end2-pos); - regex_t match; - regmatch_t off; - int result; - - // Is this it? - xregcomp(&match, regex, REG_EXTENDED); - result=regexec(&match, device_name, 1, &off, 0); - regfree(&match); - free(regex); - - // If not this device, skip rest of line - if (result || off.rm_so - || off.rm_eo!=strlen(device_name)) - goto end_line; - - break; - } - // uid:gid - case 2: - { - char *s2; - - // Find : - for(s = pos; s<end2 && *s!=':'; s++); - if (s==end2) goto end_line; - - // Parse UID - uid = strtoul(pos,&s2,10); - if (s!=s2) { - struct passwd *pass; - char *str = strndup(pos, s-pos); - pass = getpwnam(str); - free(str); - if (!pass) goto end_line; - uid = pass->pw_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-conf<len;) { + int field; + char *end2; + + line++; + // find end of this line + for(end = pos; end-conf<len && *end!='\n'; end++); + + // Three fields: regex, uid:gid, mode + for (field = 3; field; field--) { + // Skip whitespace + while (pos<end && isspace(*pos)) pos++; + if (pos==end || *pos=='#') break; + for (end2 = pos; + end2<end && !isspace(*end2) && *end2!='#'; end2++); + switch(field) { + // Regex to match this device + case 3: + { + char *regex = strndup(pos, end2-pos); + regex_t match; + regmatch_t off; + int result; + + // Is this it? + xregcomp(&match, regex, REG_EXTENDED); + result=regexec(&match, device_name, 1, &off, 0); + regfree(&match); + free(regex); + + // If not this device, skip rest of line + if (result || off.rm_so + || off.rm_eo!=strlen(device_name)) + goto end_line; + + break; + } + // uid:gid + case 2: + { + char *s2; + + // Find : + for(s = pos; s<end2 && *s!=':'; s++); + if (s==end2) goto end_line; + + // Parse UID + uid = strtoul(pos,&s2,10); + if (s!=s2) { + struct passwd *pass; + char *str = strndup(pos, s-pos); + pass = getpwnam(str); + free(str); + if (!pass) goto end_line; + uid = pass->pw_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 <rob@landley.net> @@ -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<dblocks; i++) blocklist[i] = i; - // Singly indirect index blocks - if (dblocks > 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<dblocks; i++) blocklist[i] = i; + // Singly indirect index blocks + if (dblocks > 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<<temp) break; - if (temp==4) error_exit("bad blocksize"); - sb->log_block_size = sb->log_frag_size = SWAP_LE32(temp); + for (temp = 0; temp < 4; temp++) if (TT.blocksize == 1024<<temp) break; + if (temp==4) error_exit("bad blocksize"); + sb->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<group) j*=i; - if (j==group) return 1; - } - return 0; + 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<group) j*=i; + if (j==group) return 1; + } + return 0; } - + // Number of blocks used in group by optional superblock/group list backup. static int group_superblock_overhead(uint32_t group) { - int used; + int used; - if (!is_sb_group(group)) return 0; + if (!is_sb_group(group)) return 0; - // How many blocks does the group descriptor table take up? - used = TT.groups * sizeof(struct ext2_group); - used += TT.blocksize - 1; - used /= TT.blocksize; - // Plus the superblock itself. - used++; - // And a corner case. - if (!group && TT.blocksize == 1024) used++; + // How many blocks does the group descriptor table take up? + used = TT.groups * sizeof(struct ext2_group); + used += TT.blocksize - 1; + used /= TT.blocksize; + // Plus the superblock itself. + used++; + // And a corner case. + if (!group && TT.blocksize == 1024) used++; - return used; + return used; } // Number of blocks used in group to store superblock/group/inode list static int group_overhead(uint32_t group) { - // Return superblock backup overhead (if any), plus block/inode - // allocation bitmaps, plus inode tables. - return group_superblock_overhead(group) + 2 + get_inodespg(TT.inodespg) - / (TT.blocksize/sizeof(struct ext2_inode)); + // Return superblock backup overhead (if any), plus block/inode + // allocation bitmaps, plus inode tables. + return group_superblock_overhead(group) + 2 + get_inodespg(TT.inodespg) + / (TT.blocksize/sizeof(struct ext2_inode)); } // In bitmap "array" set "len" bits starting at position "start" (from 0). static void bits_set(char *array, int start, int len) { - while(len) { - if ((start&7) || len<8) { - array[start/8]|=(1<<(start&7)); - start++; - len--; - } else { - array[start/8]=255; - start+=8; - len-=8; - } - } + while(len) { + if ((start&7) || len<8) { + array[start/8]|=(1<<(start&7)); + start++; + len--; + } else { + array[start/8]=255; + start+=8; + len-=8; + } + } } // Seek past len bytes (to maintain sparse file), or write zeroes if output // not seekable static void put_zeroes(int len) { - 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; - } - } + 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.groups; i++) temp += group_overhead(i); - - if (TT.blocks) { - if (TT.blocks < temp) error_exit("Not enough space.\n"); - break; - } - if (temp <= TT.groups * TT.blockbits) { - TT.blocks = temp; - break; - } - TT.groups++; - } - TT.freeblocks = TT.blocks - temp; - - // Now we know all the TT data, initialize superblock structure. - - init_superblock(&TT.sb); - - // Start writing. Skip the first 1k to avoid the boot sector (if any). - put_zeroes(1024); - - // Loop through block groups, write out each one. - dtiblk = dtbblk = usedblocks = usedinodes = 0; - for (i=0; i<TT.groups; i++) { - struct ext2_inode *in = (struct ext2_inode *)toybuf; - uint32_t start, itable, used, end; - int j, slot; - - // Where does this group end? - end = TT.blockbits; - if ((i+1)*TT.blockbits > 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<TT.groups; j++) { - - // Figure out what sector this group starts in. - used = group_superblock_overhead(j); - - // Find next array slot in this block (flush block if full). - slot = j % (TT.blocksize/sizeof(struct ext2_group)); - if (!slot) { - if (j) xwrite(TT.fsfd, bg, TT.blocksize); - memset(bg, 0, TT.blocksize); - } - - // How many free inodes in this group? - temp = TT.inodespg; - if (!i) temp -= INODES_RESERVED; - if (temp > 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<TT.inodespg; j++) { - slot = j % (TT.blocksize/sizeof(struct ext2_inode)); - if (!slot) { - if (j) xwrite(TT.fsfd, in, TT.blocksize); - memset(in, 0, TT.blocksize); - } - if (!i && j<INODES_RESERVED) { - // Write root inode - if (j == 2) fill_inode(in+slot, dtb); - } else if (dti) { - fill_inode(in+slot, dti); - dti = treenext(dti); - } - } - xwrite(TT.fsfd, in, TT.blocksize); - - while (dtb) { - // TODO write index data block - // TODO write root directory data block - // TODO write directory data block - // TODO write file data block - put_zeroes(TT.blocksize); - start++; - if (start == end) break; - } - // Write data blocks (TODO) - put_zeroes((end-start) * TT.blocksize); - } + 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.groups; i++) temp += group_overhead(i); + + if (TT.blocks) { + if (TT.blocks < temp) error_exit("Not enough space.\n"); + break; + } + if (temp <= TT.groups * TT.blockbits) { + TT.blocks = temp; + break; + } + TT.groups++; + } + TT.freeblocks = TT.blocks - temp; + + // Now we know all the TT data, initialize superblock structure. + + init_superblock(&TT.sb); + + // Start writing. Skip the first 1k to avoid the boot sector (if any). + put_zeroes(1024); + + // Loop through block groups, write out each one. + dtiblk = dtbblk = usedblocks = usedinodes = 0; + for (i=0; i<TT.groups; i++) { + struct ext2_inode *in = (struct ext2_inode *)toybuf; + uint32_t start, itable, used, end; + int j, slot; + + // Where does this group end? + end = TT.blockbits; + if ((i+1)*TT.blockbits > 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<TT.groups; j++) { + + // Figure out what sector this group starts in. + used = group_superblock_overhead(j); + + // Find next array slot in this block (flush block if full). + slot = j % (TT.blocksize/sizeof(struct ext2_group)); + if (!slot) { + if (j) xwrite(TT.fsfd, bg, TT.blocksize); + memset(bg, 0, TT.blocksize); + } + + // How many free inodes in this group? + temp = TT.inodespg; + if (!i) temp -= INODES_RESERVED; + if (temp > 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<TT.inodespg; j++) { + slot = j % (TT.blocksize/sizeof(struct ext2_inode)); + if (!slot) { + if (j) xwrite(TT.fsfd, in, TT.blocksize); + memset(in, 0, TT.blocksize); + } + if (!i && j<INODES_RESERVED) { + // Write root inode + if (j == 2) fill_inode(in+slot, dtb); + } else if (dti) { + fill_inode(in+slot, dti); + dti = treenext(dti); + } + } + xwrite(TT.fsfd, in, TT.blocksize); + + while (dtb) { + // TODO write index data block + // TODO write root directory data block + // TODO write directory data block + // TODO write file data block + put_zeroes(TT.blocksize); + start++; + if (start == end) break; + } + // Write data blocks (TODO) + put_zeroes((end-start) * TT.blocksize); + } } diff --git a/toys/other/mkswap.c b/toys/other/mkswap.c index 1e96c196..ff864244 100644 --- a/toys/other/mkswap.c +++ b/toys/other/mkswap.c @@ -1,40 +1,38 @@ -/* vi: set sw=4 ts=4: - * - * mkswap.c - Format swap device. +/* mkswap.c - Format swap device. * * Copyright 2009 Rob Landley <rob@landley.net> 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 <andre@bluewatersys.com> - * 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 <eliedebrauwer@gmail.com> 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 <rob@landley.net> * * 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; i<pollcount; i++) { - if (pollfds[i].revents & POLLIN) { - int len = read(pollfds[i].fd, toybuf, sizeof(toybuf)); - if (len<1) goto dohupnow; - xwrite(i ? pollfds[0].fd : 1, toybuf, len); - } else if (pollfds[i].revents & POLLHUP) { + 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; i<pollcount; i++) { + if (pollfds[i].revents & POLLIN) { + int len = read(pollfds[i].fd, toybuf, sizeof(toybuf)); + if (len<1) goto dohupnow; + xwrite(i ? pollfds[0].fd : 1, toybuf, len); + } else if (pollfds[i].revents & POLLHUP) { dohupnow: - // Close half-connection. This is needed for things like - // "echo GET / | netcat landley.net 80" - if (i) { - shutdown(pollfds[0].fd, SHUT_WR); - pollcount--; - set_alarm(TT.quit_delay); - } else goto cleanup; - } - } - } + // Close half-connection. This is needed for things like + // "echo GET / | netcat landley.net 80" + if (i) { + shutdown(pollfds[0].fd, SHUT_WR); + pollcount--; + set_alarm(TT.quit_delay); + } else goto cleanup; + } + } + } cleanup: - if (CFG_TOYBOX_FREE) { - close(pollfds[0].fd); - close(sockfd); - } + if (CFG_TOYBOX_FREE) { + close(pollfds[0].fd); + close(sockfd); + } } diff --git a/toys/other/oneit.c b/toys/other/oneit.c index 8bb482da..5bf4e941 100644 --- a/toys/other/oneit.c +++ b/toys/other/oneit.c @@ -1,27 +1,25 @@ -/* vi: set sw=4 ts=4: - * - * oneit.c - tiny init replacement to launch a single child process. +/* oneit.c - tiny init replacement to launch a single child process. * * Copyright 2005, 2007 by Rob Landley <rob@landley.net>. 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 <sys/reboot.h> 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 <georgi@unixsol.org> 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 <rob@landley.net> 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 <andre@bluewatersys.com> 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 <eliedebrauwer@gmail.com> 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 <rob@landley.net> 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 <eliedebrauwer@gmail.com> 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 <eliedebrauwer@gmail.com> 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 <sys/vfs.h> 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 <rob@landley.net> 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 <eliedebrauwer@gmail.com> 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<k; j++) { - unsigned long digit = *(--s) - '0'; - - if (digit > 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<k; j++) { + unsigned long digit = *(--s) - '0'; + + if (digit > 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 <rob@landley.net> 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 <rob@landley.net> 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<<i)) - f |= flags[i]; + for (i=0; flags[i]; i++) if (toys.optflags & (1<<i)) f |= flags[i]; - if(unshare(f)) perror_exit("failed"); + if(unshare(f)) perror_exit("failed"); - xexec(toys.optargs); + xexec(toys.optargs); } diff --git a/toys/other/uptime.c b/toys/other/uptime.c index dfd62b6c..f4ce5e46 100644 --- a/toys/other/uptime.c +++ b/toys/other/uptime.c @@ -1,50 +1,45 @@ -/* vi: set sw=4 ts=4: - * - * uptime.c - Tell how long the system has been running. +/* uptime.c - Tell how long the system has been running. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> 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 <eliedebrauwer@gmail.com> 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 <sandeep.jack2756@gmail.com>, Kyungwan Han <asura321@gmail.com> * @@ -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 <eliedebrauwer@gmail.com> 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 <gmshastri@gmail.com> 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 <rob@landley.net> 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 <georgi@unixsol.org> 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 <rob@landley.net> 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 <tryn@mirell.org> * @@ -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 <rob@landley.net> * @@ -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 : mday<len) { - pat = "%2d "; - mday++; - } - buf += sprintf(buf, pat, mday); - } - buf++; - } - - return buf; + 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 : mday<len) { + pat = "%2d "; + mday++; + } + buf += sprintf(buf, pat, mday); + } + buf++; + } + + return buf; } void xcheckrange(long val, long low, long high) { - char *err = "%ld %s than %ld"; + char *err = "%ld %s than %ld"; - if (val < low) error_exit(err, val, "less", low); - if (val > 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 <rob@landley.net> * @@ -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 <georgi@unixsol.org> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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<len; i++) crc=cksum(crc, toybuf[i]); - } - - // CRC the length - - llen2 = llen; - if (!(toys.optflags&1)) { - while (llen) { - crc = cksum(crc, llen); - llen >>= 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<len; i++) crc=cksum(crc, toybuf[i]); + } + + // CRC the length + + llen2 = llen; + if (!(toys.optflags&1)) { + while (llen) { + crc = cksum(crc, llen); + llen >>= 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 <tle@holymonkey.com> * @@ -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<min_len; i++) { - if (toybuf[i] != buf2[i]) { - toys.exitval = 1; - if (toys.optflags & FLAG_l) - printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]); - else { - if (!(toys.optflags & FLAG_s)) { - printf("%s %s differ: char %ld, line %ld\n", - TT.name, name, byte_no, line_no); - toys.exitval++; - } - goto out; - } - } - byte_no++; - if (toybuf[i] == '\n') line_no++; - } - if (len1 != len2) { - if (!(toys.optflags & FLAG_s)) { - fprintf(stderr, "cmp: EOF on %s\n", - len1 < len2 ? TT.name : name); - } - toys.exitval = 1; - break; - } - if (len1 < 1) break; - } + min_len = len1 < len2 ? len1 : len2; + for (i=0; i<min_len; i++) { + if (toybuf[i] != buf2[i]) { + toys.exitval = 1; + if (toys.optflags & FLAG_l) + printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]); + else { + if (!(toys.optflags & FLAG_s)) { + printf("%s %s differ: char %ld, line %ld\n", + TT.name, name, byte_no, line_no); + toys.exitval++; + } + goto out; + } + } + byte_no++; + if (toybuf[i] == '\n') line_no++; + } + if (len1 != len2) { + if (!(toys.optflags & FLAG_s)) + fprintf(stderr, "cmp: EOF on %s\n", len1 < len2 ? TT.name : name); + toys.exitval = 1; + break; + } + if (len1 < 1) break; + } out: - if (CFG_TOYBOX_FREE) close(TT.fd); + if (CFG_TOYBOX_FREE) close(TT.fd); } void cmp_main(void) { - loopfiles_rw(toys.optargs, O_RDONLY, 0, toys.optflags&FLAG_s, do_cmp); + loopfiles_rw(toys.optargs, O_RDONLY, 0, toys.optflags&FLAG_s, do_cmp); } diff --git a/toys/posix/comm.c b/toys/posix/comm.c index 477d5160..bbdcccef 100644 --- a/toys/posix/comm.c +++ b/toys/posix/comm.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * comm.c - select or reject lines common to two files +/* comm.c - select or reject lines common to two files * * Copyright 2012 Ilya Kuzmich <ikv@safe-mail.net> * @@ -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 <rob@landley.net> +/* Copyright 2008 Rob Landley <rob@landley.net> * * 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<toys.optc; i++) { - char *dst, *src = toys.optargs[i]; + for (i=0; i<toys.optc; i++) { + char *dst, *src = toys.optargs[i]; - // Skip src==dest (TODO check inodes to catch "cp blah ./blah"). + // Skip src==dest (TODO check inodes to catch "cp blah ./blah"). - if (!strncmp(src, TT.destname)) continue; + if (!strncmp(src, TT.destname)) continue; - // Skip nonexistent sources. + // Skip nonexistent sources. - TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a); - if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st) - || (st.st_dev = dst.st_dev && st.st_ino == dst.dst_ino)) - { + TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a); + if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st) + || (st.st_dev = dst.st_dev && st.st_ino == dst.dst_ino)) + { objection: - perror_msg("bad '%s'", src); - toys.exitval = 1; - continue; - } - - // Copy directory or file. - - if (TT.destisdir) { - char *s; - - // Catch "cp -R .. ." and friends that would go on forever - if (dpath && (s = realpath(src, NULL)) { - int i = strlen(s); - i = (!strncmp(s, dst, i) && (!s[i] || s[i]=='/')); - free(s); - - if (i) goto objection; - } - - // Create destination filename within directory - dst = strrchr(src, '/'); - if (dst) dst++; - else dst=src; - dst = xmsprintf("%s/%s", TT.destname, dst); - } else dst = TT.destname; - - if (S_ISDIR(st.st_mode)) { - if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) { - cp_file(src, dst, &st); - - TT.keep_symlinks++; - dirtree_read(src, cp_node); - } else error_msg("Skipped dir '%s'", src); - } else cp_file(src, dst, &st); - if (TT.destisdir) free(dst); - } - - if (CFG_TOYBOX_FREE) free(dpath); - return; + perror_msg("bad '%s'", src); + toys.exitval = 1; + continue; + } + + // Copy directory or file. + + if (TT.destisdir) { + char *s; + + // Catch "cp -R .. ." and friends that would go on forever + if (dpath && (s = realpath(src, NULL)) { + int i = strlen(s); + i = (!strncmp(s, dst, i) && (!s[i] || s[i]=='/')); + free(s); + + if (i) goto objection; + } + + // Create destination filename within directory + dst = strrchr(src, '/'); + if (dst) dst++; + else dst=src; + dst = xmsprintf("%s/%s", TT.destname, dst); + } else dst = TT.destname; + + if (S_ISDIR(st.st_mode)) { + if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) { + cp_file(src, dst, &st); + + TT.keep_symlinks++; + dirtree_read(src, cp_node); + } else error_msg("Skipped dir '%s'", src); + } else cp_file(src, dst, &st); + if (TT.destisdir) free(dst); + } + + if (CFG_TOYBOX_FREE) free(dpath); + return; } diff --git a/toys/posix/date.c b/toys/posix/date.c index 9beaaa1a..68751043 100644 --- a/toys/posix/date.c +++ b/toys/posix/date.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * date.c - set/get the date +/* date.c - set/get the date * * Copyright 2012 Andre Renaud <andre@bluewatersys.com> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <ak.ashwini@gmail.com> * @@ -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 <rob@landley.net> * @@ -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 <tryn@mirell.org> * @@ -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 <rob@landley.net> * @@ -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 <tle@holymonkey.com> * @@ -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<len;) - if (toybuf[i++] == '\n' && !--lines) break; - - xwrite(1, toybuf, i); - } + 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<len;) if (toybuf[i++] == '\n' && !--lines) break; + + xwrite(1, toybuf, i); + } } void head_main(void) { - loopfiles(toys.optargs, do_head); + loopfiles(toys.optargs, do_head); } diff --git a/toys/posix/id.c b/toys/posix/id.c index 523d4f3a..0cdd2b0c 100644 --- a/toys/posix/id.c +++ b/toys/posix/id.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * id.c - print real and effective user and group IDs +/* id.c - print real and effective user and group IDs * * Copyright 2012 Sony Network Entertainment, Inc. * @@ -11,18 +9,18 @@ USE_ID(NEWTOY(id, "nGgru", TOYFLAG_BIN)) config ID - bool "id" - default y - help - usage: id [-nGgru] - - Print user and group ID. - - -n print names instead of numeric IDs (to be used with -Ggu) - -G Show only the group IDs - -g Show only the effective group ID - -r Show real ID instead of effective ID - -u Show only the effective user ID + bool "id" + default y + help + usage: id [-nGgru] + + Print user and group ID. + + -n print names instead of numeric IDs (to be used with -Ggu) + -G Show only the group IDs + -g Show only the effective group ID + -r Show real ID instead of effective ID + -u Show only the effective user ID */ #define FOR_id @@ -30,85 +28,83 @@ config ID static void s_or_u(char *s, unsigned u, int done) { - if (toys.optflags & FLAG_n) printf("%s", s); - else printf("%u", u); - if (done) { - xputc('\n'); - exit(0); - } + if (toys.optflags & FLAG_n) printf("%s", s); + else printf("%u", u); + if (done) { + xputc('\n'); + exit(0); + } } static void showid(char *header, unsigned u, char *s) { - printf("%s%u(%s)", header, u, s); + printf("%s%u(%s)", header, u, s); } struct passwd *xgetpwuid(uid_t uid) { - struct passwd *pwd = getpwuid(uid); - if (!pwd) error_exit(NULL); - return pwd; + struct passwd *pwd = getpwuid(uid); + if (!pwd) error_exit(NULL); + return pwd; } struct group *xgetgrgid(gid_t gid) { - struct group *group = getgrgid(gid); - if (!group) error_exit(NULL); - return group; + struct group *group = getgrgid(gid); + if (!group) error_exit(NULL); + return group; } void id_main(void) { - 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'); + 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 <d.walter@0x90.at> * @@ -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 <rob@landley.net> * @@ -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 <andre@bluewatersys.com> * @@ -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<toys.optc; i++) { - int rc; - char *try = toys.optargs[i]; + for (i=0; i<toys.optc; i++) { + int rc; + char *try = toys.optargs[i]; - if (S_ISDIR(buf.st_mode)) { - new = strrchr(try, '/'); - if (!new) new = try; - new = xmsprintf("%s/%s", dest, new); - } else new = dest; - /* Silently unlink the existing target. If it doesn't exist, - * then we just move on */ - if (toys.optflags & FLAG_f) unlink(new); + if (S_ISDIR(buf.st_mode)) { + new = strrchr(try, '/'); + if (!new) new = try; + new = xmsprintf("%s/%s", dest, new); + } else new = dest; + /* Silently unlink the existing target. If it doesn't exist, + * then we just move on */ + if (toys.optflags & FLAG_f) unlink(new); - rc = (toys.optflags & FLAG_s) ? symlink(try, new) : link(try, new); - if (rc) - perror_exit("cannot create %s link from '%s' to '%s'", - (toys.optflags & FLAG_s) ? "symbolic" : "hard", try, new); - if (new != dest) free(new); - } + rc = (toys.optflags & FLAG_s) ? symlink(try, new) : link(try, new); + if (rc) + perror_exit("cannot create %s link from '%s' to '%s'", + (toys.optflags & FLAG_s) ? "symbolic" : "hard", try, new); + if (new != dest) free(new); + } } diff --git a/toys/posix/logname.c b/toys/posix/logname.c index 6ebdb329..b638ea2f 100644 --- a/toys/posix/logname.c +++ b/toys/posix/logname.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * logname.c - Print user's login name. +/* logname.c - Print user's login name. * * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> * @@ -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 <andre@bluewatersys.com> * Copyright 2012 Rob Landley <rob@landley.net> @@ -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<dtlen; ul++) { + entrylen(sort[next_column(ul, dtlen, columns, &c)], len); + if (c == columns) break; + // Does this put us over budget? + if (*len > 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<dtlen; ul++) { - char *path = dirtree_path(indir, 0); - - if (TT.nl_title++) xputc('\n'); - xprintf("%s:\n", path); - free(path); + entrylen(sort[ul], len); + for (width=0; width<6; width++) + if (len[width] > 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; ul<dtlen; ul++) { + unsigned curcol; + unsigned long next = next_column(ul, dtlen, columns, &curcol); + struct stat *st = &(sort[next]->st); + 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<dtlen; ul++) { - entrylen(sort[next_column(ul, dtlen, columns, &c)], len); - if (c == columns) break; - // Does this put us over budget? - if (*len > 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<dtlen; ul++) - { - entrylen(sort[ul], len); - for (width=0; width<6; width++) - if (len[width] > 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<<i); + c = i%3; + if (!c && (mode & (1<<((d=i/3)+9)))) { + c = "tss"[d]; + if (!bit) c &= ~0x20; + } else c = bit ? "xwr"[c] : '-'; + perm[9-i] = c; + } + + if (S_ISDIR(mode)) c = 'd'; + else if (S_ISBLK(mode)) c = 'b'; + else if (S_ISCHR(mode)) c = 'c'; + else if (S_ISLNK(mode)) c = 'l'; + else if (S_ISFIFO(mode)) c = 'p'; + else if (S_ISSOCK(mode)) c = 's'; + else c = '-'; + *perm = c; + + tm = localtime(&(st->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; ul<dtlen; ul++) { - unsigned curcol; - unsigned long next = next_column(ul, dtlen, columns, &curcol); - struct stat *st = &(sort[next]->st); - 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<<i); - c = i%3; - if (!c && (mode & (1<<((d=i/3)+9)))) { - c = "tss"[d]; - if (!bit) c &= ~0x20; - } else c = bit ? "xwr"[c] : '-'; - perm[9-i] = c; - } - - if (S_ISDIR(mode)) c = 'd'; - else if (S_ISBLK(mode)) c = 'b'; - else if (S_ISCHR(mode)) c = 'c'; - else if (S_ISLNK(mode)) c = 'l'; - else if (S_ISFIFO(mode)) c = 'p'; - else if (S_ISSOCK(mode)) c = 's'; - else c = '-'; - *perm = c; - - tm = localtime(&(st->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; ul<dtlen; free(sort[ul++])) { - if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode) - || !dirtree_notdotdot(sort[ul])) continue; + for (ul = 0; ul<dtlen; free(sort[ul++])) { + if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.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 <georgi@unixsol.org> * @@ -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 <georgi@unixsol.org> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <andre@bluewatersys.com> * Copyright 2012 Rob Landley <rob@landley.net> @@ -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; i<TT.types; i++) { - int j = 0, pad = i ? 8 : 0; - char buf[128]; - - t = types+i; - while (j<len) { - unsigned k; - int throw = 0; - - // Handle ascii - if (t->type < 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; i<TT.types; i++) { + int j = 0, pad = i ? 8 : 0; + char buf[128]; + + t = types+i; + while (j<len) { + unsigned k; + int throw = 0; + + // Handle ascii + if (t->type < 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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> + * Copyright 2012 Rob Landley <rob@landley.net> * * 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 <rob@landley.net> * @@ -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 <rob@landley.net> * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> @@ -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 <rob@landley.net> * @@ -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 (end<start) end=start; - str = xstrndup(str+start, end-start); - - // Handle -d - if (flags&FLAG_d) { - for (start = end = 0; str[end]; end++) - if (isspace(str[end]) || isalnum(str[end])) str[start++] = str[end]; - str[start] = 0; - } - - // Handle -i - if (flags&FLAG_i) { - for (start = end = 0; str[end]; end++) - if (isprint(str[end])) str[start++] = str[end]; - str[start] = 0; + } } - - // Handle -f - if (flags*FLAG_f) for(i=0; str[i]; i++) str[i] = toupper(str[i]); - - return str; + 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 (end<start) end=start; + str = xstrndup(str+start, end-start); + + // Handle -d + if (flags&FLAG_d) { + for (start = end = 0; str[end]; end++) + if (isspace(str[end]) || isalnum(str[end])) str[start++] = str[end]; + str[start] = 0; + } + + // Handle -i + if (flags&FLAG_i) { + for (start = end = 0; str[end]; end++) + if (isprint(str[end])) str[start++] = str[end]; + str[start] = 0; + } + + // Handle -f + if (flags*FLAG_f) for(i=0; str[i]; i++) str[i] = toupper(str[i]); + + return str; } // append a sort_key to key_list. static struct sort_key *add_key(void) { - void **stupid_compiler = &TT.key_list; - struct sort_key **pkey = (struct sort_key **)stupid_compiler; + void **stupid_compiler = &TT.key_list; + struct sort_key **pkey = (struct sort_key **)stupid_compiler; - while (*pkey) pkey = &((*pkey)->next_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 : (dx<dy ? -1 : 0); - } else if (CFG_SORT_BIG && ff == FLAG_M) { - struct tm thyme; - int dx; - char *xx,*yy; - - xx = strptime(x,"%b",&thyme); - dx = thyme.tm_mon; - yy = strptime(y,"%b",&thyme); - if (!xx) return !yy ? 0 : -1; - else if (!yy) return 1; - else return dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon; - - } else if (CFG_SORT_BIG && ff == FLAG_x) { - return strtol(x, NULL, 16)-strtol(y, NULL, 16); - // This has to be ff == FLAG_n - } else { - // Full floating point version of -n - if (CFG_SORT_FLOAT) { - double dx = atof(x), dy = atof(y); + // Check for isnan + if (dx!=dx) return (dy!=dy) ? 0 : -1; + if (dy!=dy) return 1; - return dx>dy ? 1 : (dx<dy ? -1 : 0); - // Integer version of -n for tiny systems - } else return atoi(x)-atoi(y); + // 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 : (dx<dy ? -1 : 0); + } else if (CFG_SORT_BIG && ff == FLAG_M) { + struct tm thyme; + int dx; + char *xx,*yy; + + xx = strptime(x,"%b",&thyme); + dx = thyme.tm_mon; + yy = strptime(y,"%b",&thyme); + if (!xx) return !yy ? 0 : -1; + else if (!yy) return 1; + else return dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon; + + } else if (CFG_SORT_BIG && ff == FLAG_x) { + return strtol(x, NULL, 16)-strtol(y, NULL, 16); + // This has to be ff == FLAG_n + } else { + // Full floating point version of -n + if (CFG_SORT_FLOAT) { + double dx = atof(x), dy = atof(y); + + return dx>dy ? 1 : (dx<dy ? -1 : 0); + // Integer version of -n for tiny systems + } else return atoi(x)-atoi(y); + } } - // Callback from qsort(): Iterate through key_list and perform comparisons. static int compare_keys(const void *xarg, const void *yarg) { - int flags = toys.optflags, retval = 0; - char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg; - struct sort_key *key; - - 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; + 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<TT.linecount; idx++) { - if (!compare_keys(&TT.lines[jdx], &TT.lines[idx])) - free(TT.lines[idx]); - else TT.lines[++jdx] = TT.lines[idx]; - } - if (TT.linecount) TT.linecount = jdx+1; + for (jdx=0, idx=1; idx<TT.linecount; idx++) { + if (!compare_keys(&TT.lines[jdx], &TT.lines[idx])) + free(TT.lines[idx]); + else TT.lines[++jdx] = TT.lines[idx]; } + if (TT.linecount) TT.linecount = jdx+1; + } - // Output result - for (idx = 0; idx<TT.linecount; idx++) { - char *s = TT.lines[idx]; - xwrite(fd, s, strlen(s)); - if (CFG_TOYBOX_FREE) free(s); - xwrite(fd, "\n", 1); - } + // Output result + for (idx = 0; idx<TT.linecount; idx++) { + char *s = TT.lines[idx]; + xwrite(fd, s, strlen(s)); + if (CFG_TOYBOX_FREE) free(s); + xwrite(fd, "\n", 1); + } exit_now: - if (CFG_TOYBOX_FREE) { - if (fd != 1) close(fd); - free(TT.lines); - } + if (CFG_TOYBOX_FREE) { + if (fd != 1) close(fd); + free(TT.lines); + } } diff --git a/toys/posix/tail.c b/toys/posix/tail.c index d0711c0c..bdbbfb30 100644 --- a/toys/posix/tail.c +++ b/toys/posix/tail.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * tail.c - copy last lines from input to stdout. +/* tail.c - copy last lines from input to stdout. * * Copyright 2012 Timothy Elliott <tle@holymonkey.com> * @@ -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; count<len; count++) { - if ((toys.optflags & FLAG_c) && bytes) { - bytes++; - continue; - } - - if (lines) { - if(try[count] != '\n' && count != len-1) continue; - if (lines<0) { - if (!++lines) ++lines; - continue; - } - } - - // Time to discard data; given that bytes and lines were - // nonzero coming in, we can't discard too much if we're - // measuring right. - do { - char c = *(list->data++); - 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<len) xwrite(1, toybuf+offset, len-offset); - } - - // -f support: cache name/descriptor + 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; count<len; count++) { + if ((toys.optflags & FLAG_c) && bytes) { + bytes++; + continue; + } + + if (lines) { + if(try[count] != '\n' && count != len-1) continue; + if (lines<0) { + if (!++lines) ++lines; + continue; + } + } + + // Time to discard data; given that bytes and lines were + // nonzero coming in, we can't discard too much if we're + // measuring right. + do { + char c = *(list->data++); + 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<len) xwrite(1, toybuf+offset, len-offset); + } + + // -f support: cache name/descriptor } void tail_main(void) { - // if nothing specified, default -n to -10 - if (!(toys.optflags&(FLAG_n|FLAG_c))) TT.lines = -10; + // if nothing specified, default -n to -10 + if (!(toys.optflags&(FLAG_n|FLAG_c))) TT.lines = -10; - loopfiles(toys.optargs, do_tail); + loopfiles(toys.optargs, do_tail); - // do -f stuff + // do -f stuff } diff --git a/toys/posix/tee.c b/toys/posix/tee.c index e6342f4c..03885109 100644 --- a/toys/posix/tee.c +++ b/toys/posix/tee.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * tee.c - cat to multiple outputs. +/* tee.c - cat to multiple outputs. * * Copyright 2008 Rob Landley <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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<<i)|FLAG_a)) { - int len = strlen(c); + if (flags & ((1<<i)|FLAG_a)) { + int len = strlen(c); - // This problem originates in autoconf, so of course the solution - // is horribly ugly. + // This problem originates in autoconf, so of course the solution + // is horribly ugly. #ifdef GROSS - if (i==4 && !strcmp(c,"x86_64")) { - printf(GROSS); - continue; - } + if (i==4 && !strcmp(c,"x86_64")) { + printf(GROSS); + continue; + } #endif - if (needspace++) { - // We can't decrement on the first entry, because - // needspace would be 0 - *(--c)=' '; - len++; - } - xwrite(1, c, len); - } - } - putchar('\n'); + if (needspace++) { + // We can't decrement on the first entry, because + // needspace would be 0 + *(--c)=' '; + len++; + } + xwrite(1, c, len); + } + } + putchar('\n'); } diff --git a/toys/posix/uniq.c b/toys/posix/uniq.c index f42b7293..bd41d4af 100644 --- a/toys/posix/uniq.c +++ b/toys/posix/uniq.c @@ -1,6 +1,4 @@ -/* vi: set sw=4 ts=4: - * - * uniq.c - report or filter out repeated lines in a file +/* uniq.c - report or filter out repeated lines in a file * * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org> * @@ -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 <rob@landley.net> * @@ -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 <rob@landley.net> * @@ -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<<i))) { - xprintf(" %ld"+nospace, lengths[i]); - nospace = 0; - } - TT.totals[i] += lengths[i]; - } - if (*toys.optargs) xprintf(" %s", name); - xputc('\n'); + int i, nospace = 1; + for (i=0; i<3; i++) { + if (!toys.optflags || (toys.optflags&(1<<i))) { + xprintf(" %ld"+nospace, lengths[i]); + nospace = 0; + } + TT.totals[i] += lengths[i]; + } + if (*toys.optargs) xprintf(" %s", name); + xputc('\n'); } static void do_wc(int fd, char *name) { - int i, len, clen=1, space; - wchar_t wchar; - unsigned long word=0, lengths[]={0,0,0}; + int i, len, clen=1, space; + wchar_t wchar; + unsigned long word=0, lengths[]={0,0,0}; - for (;;) { - len = read(fd, toybuf, sizeof(toybuf)); - if (len<0) { - perror_msg("%s",name); - toys.exitval = EXIT_FAILURE; - } - if (len<1) break; - for (i=0; i<len; i+=clen) { - if(toys.optflags&8) { - clen = mbrtowc(&wchar, toybuf+i, len-i, 0); - if(clen==(size_t)(-1)) { - if(i!=len-1) { - clen = 1; - continue; - } - else break; - } - if(clen==(size_t)(-2)) break; - if(clen==0) clen=1; - space = iswspace(wchar); - } - else space = isspace(toybuf[i]); + for (;;) { + len = read(fd, toybuf, sizeof(toybuf)); + if (len<0) { + perror_msg("%s",name); + toys.exitval = EXIT_FAILURE; + } + if (len<1) break; + for (i=0; i<len; i+=clen) { + if(toys.optflags&8) { + clen = mbrtowc(&wchar, toybuf+i, len-i, 0); + if(clen==(size_t)(-1)) { + if(i!=len-1) { + clen = 1; + continue; + } else break; + } + if(clen==(size_t)(-2)) break; + if(clen==0) clen=1; + space = iswspace(wchar); + } else space = isspace(toybuf[i]); - if (toybuf[i]==10) lengths[0]++; - if (space) word=0; - else { - if (!word) lengths[1]++; - word=1; - } - lengths[2]++; - } - } + if (toybuf[i]==10) lengths[0]++; + if (space) word=0; + else { + if (!word) lengths[1]++; + word=1; + } + lengths[2]++; + } + } - show_lengths(lengths, name); + show_lengths(lengths, name); } void wc_main(void) { - setlocale(LC_ALL, ""); - toys.optflags |= (toys.optflags&8)>>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 <rob@landley.net> * @@ -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.</p> -<p>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.</p> +<p>Toybox source uses two spaces per indentation level, and wraps at 80 +columns.</p> <p>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.</p> <p>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.</p> +controls which features are included when compiling toybox.</p> <p>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: <a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part1-2.html>part one</a>, <a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part2-1.html>part two</a>, @@ -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.</p> -<p>An enventual goal is UTF-8 support, although it isn't a priority for the +<p>An enventual goal is <a href=http://yarchive.net/comp/linux/utf8.html>UTF-8</a> support, although it isn't a priority for the first pass of each command. (All commands should at least be 8-bit clean.)</p> <p>Locale support isn't currently a goal; that's a presentation layer issue, |