aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/args.c633
-rw-r--r--lib/bunzip.c1039
-rw-r--r--lib/dirtree.c206
-rw-r--r--lib/getmountlist.c47
-rw-r--r--lib/lib.c1217
-rw-r--r--lib/lib.h43
-rw-r--r--lib/llist.c51
-rw-r--r--lib/password.c238
-rw-r--r--lib/portability.c93
-rw-r--r--lib/xregcomp.c17
-rw-r--r--main.c169
-rwxr-xr-xscripts/config2help.sh4
-rw-r--r--scripts/install.c31
-rwxr-xr-xscripts/test/basename.test2
-rwxr-xr-xscripts/test/cat.test2
-rwxr-xr-xscripts/test/cp.test2
-rwxr-xr-x[-rw-r--r--]scripts/test/dirname.test2
-rwxr-xr-xscripts/test/xargs.test2
-rw-r--r--toys.h25
-rw-r--r--toys/e2fs.h196
-rw-r--r--toys/lsb/dmesg.c69
-rw-r--r--toys/lsb/hostname.c31
-rw-r--r--toys/lsb/killall.c79
-rw-r--r--toys/lsb/md5sum.c7
-rw-r--r--toys/lsb/mknod.c47
-rw-r--r--toys/lsb/mktemp.c54
-rw-r--r--toys/lsb/passwd.c389
-rw-r--r--toys/lsb/pidof.c27
-rw-r--r--toys/lsb/seq.c58
-rw-r--r--toys/lsb/sync.c16
-rw-r--r--toys/other/bzcat.c18
-rw-r--r--toys/other/catv.c82
-rw-r--r--toys/other/chroot.c21
-rw-r--r--toys/other/chvt.c48
-rw-r--r--toys/other/clear.c14
-rw-r--r--toys/other/count.c36
-rw-r--r--toys/other/dos2unix.c72
-rw-r--r--toys/other/free.c76
-rw-r--r--toys/other/hello.c52
-rw-r--r--toys/other/help.c44
-rw-r--r--toys/other/insmod.c53
-rw-r--r--toys/other/login.c286
-rw-r--r--toys/other/lsmod.c48
-rw-r--r--toys/other/mdev.c346
-rw-r--r--toys/other/mke2fs.c1014
-rw-r--r--toys/other/mkswap.c42
-rw-r--r--toys/other/modinfo.c119
-rw-r--r--toys/other/mountpoint.c77
-rw-r--r--toys/other/netcat.c355
-rw-r--r--toys/other/oneit.c45
-rw-r--r--toys/other/printenv.c55
-rw-r--r--toys/other/readlink.c46
-rw-r--r--toys/other/realpath.c29
-rw-r--r--toys/other/rmmod.c57
-rw-r--r--toys/other/setsid.c29
-rw-r--r--toys/other/swapoff.c17
-rw-r--r--toys/other/swapon.c26
-rw-r--r--toys/other/switch_root.c130
-rw-r--r--toys/other/tac.c68
-rw-r--r--toys/other/taskset.c144
-rw-r--r--toys/other/truncate.c43
-rw-r--r--toys/other/unshare.c46
-rw-r--r--toys/other/uptime.c67
-rw-r--r--toys/other/usleep.c26
-rw-r--r--toys/other/vconfig.c193
-rw-r--r--toys/other/vmstat.c317
-rw-r--r--toys/other/w.c35
-rw-r--r--toys/other/which.c81
-rw-r--r--toys/other/whoami.c28
-rw-r--r--toys/other/yes.c32
-rw-r--r--toys/posix/basename.c50
-rw-r--r--toys/posix/cal.c206
-rw-r--r--toys/posix/cat.c40
-rw-r--r--toys/posix/chgrp.c174
-rw-r--r--toys/posix/chmod.c68
-rw-r--r--toys/posix/cksum.c107
-rw-r--r--toys/posix/cmp.c110
-rw-r--r--toys/posix/comm.c105
-rw-r--r--toys/posix/cp.c354
-rw-r--r--toys/posix/date.c138
-rw-r--r--toys/posix/df.c263
-rw-r--r--toys/posix/dirname.c16
-rw-r--r--toys/posix/du.c282
-rw-r--r--toys/posix/echo.c132
-rw-r--r--toys/posix/env.c64
-rw-r--r--toys/posix/false.c14
-rw-r--r--toys/posix/head.c67
-rw-r--r--toys/posix/id.c156
-rw-r--r--toys/posix/kill.c87
-rw-r--r--toys/posix/link.c20
-rw-r--r--toys/posix/ln.c86
-rw-r--r--toys/posix/logname.c20
-rw-r--r--toys/posix/ls.c705
-rw-r--r--toys/posix/mkdir.c78
-rw-r--r--toys/posix/mkfifo.c44
-rw-r--r--toys/posix/nice.c32
-rw-r--r--toys/posix/nohup.c50
-rw-r--r--toys/posix/od.c434
-rw-r--r--toys/posix/patch.c664
-rw-r--r--toys/posix/pwd.c20
-rw-r--r--toys/posix/rmdir.c42
-rw-r--r--toys/posix/sed.c133
-rw-r--r--toys/posix/sh.c484
-rw-r--r--toys/posix/sleep.c60
-rw-r--r--toys/posix/sort.c591
-rw-r--r--toys/posix/tail.c348
-rw-r--r--toys/posix/tee.c73
-rw-r--r--toys/posix/true.c14
-rw-r--r--toys/posix/tty.c24
-rw-r--r--toys/posix/uname.c72
-rw-r--r--toys/posix/uniq.c189
-rw-r--r--toys/posix/unlink.c18
-rw-r--r--toys/posix/wc.c126
-rw-r--r--toys/posix/who.c43
-rw-r--r--toys/posix/xargs.c312
-rw-r--r--www/code.html9
-rw-r--r--www/design.html4
117 files changed, 7996 insertions, 8245 deletions
diff --git a/lib/args.c b/lib/args.c
index 2f6132ab..b7119651 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -1,5 +1,4 @@
-/* vi: set sw=4 ts=4 :
- * args.c - Command line argument parsing.
+/* args.c - Command line argument parsing.
*
* Copyright 2006 Rob Landley <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;
}
diff --git a/lib/lib.c b/lib/lib.c
index 2c2ea63e..06828a40 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -1,4 +1,3 @@
-/* vi: set sw=4 ts=4 :*/
/* lib.c - reusable stuff.
*
* Functions with the x prefix are wrappers for library functions. They either
@@ -14,257 +13,257 @@
// Strcpy with size checking: exit if there's not enough space for the string.
void xstrcpy(char *dest, char *src, size_t size)
{
- if (strlen(src)+1 > size) error_exit("xstrcpy");
- strcpy(dest, src);
+ if (strlen(src)+1 > size) error_exit("xstrcpy");
+ strcpy(dest, src);
}
void verror_msg(char *msg, int err, va_list va)
{
- char *s = ": %s";
+ char *s = ": %s";
- fprintf(stderr, "%s: ", toys.which->name);
- if (msg) vfprintf(stderr, msg, va);
- else s+=2;
- if (err) fprintf(stderr, s, strerror(err));
- putc('\n', stderr);
+ fprintf(stderr, "%s: ", toys.which->name);
+ if (msg) vfprintf(stderr, msg, va);
+ else s+=2;
+ if (err) fprintf(stderr, s, strerror(err));
+ putc('\n', stderr);
}
void error_msg(char *msg, ...)
{
- va_list va;
+ va_list va;
- va_start(va, msg);
- verror_msg(msg, 0, va);
- va_end(va);
+ va_start(va, msg);
+ verror_msg(msg, 0, va);
+ va_end(va);
}
void perror_msg(char *msg, ...)
{
- va_list va;
+ va_list va;
- va_start(va, msg);
- verror_msg(msg, errno, va);
- va_end(va);
+ va_start(va, msg);
+ verror_msg(msg, errno, va);
+ va_end(va);
}
// Die with an error message.
void error_exit(char *msg, ...)
{
- va_list va;
+ va_list va;
- if (CFG_HELP && toys.exithelp) {
- *toys.optargs=*toys.argv;
- USE_HELP(help_main();) // dear gcc: shut up.
- fprintf(stderr,"\n");
- }
+ if (CFG_HELP && toys.exithelp) {
+ *toys.optargs=*toys.argv;
+ USE_HELP(help_main();) // dear gcc: shut up.
+ fprintf(stderr,"\n");
+ }
- va_start(va, msg);
- verror_msg(msg, 0, va);
- va_end(va);
+ va_start(va, msg);
+ verror_msg(msg, 0, va);
+ va_end(va);
- exit(!toys.exitval ? 1 : toys.exitval);
+ exit(!toys.exitval ? 1 : toys.exitval);
}
// Die with an error message and strerror(errno)
void perror_exit(char *msg, ...)
{
- va_list va;
+ va_list va;
- va_start(va, msg);
- verror_msg(msg, errno, va);
- va_end(va);
+ va_start(va, msg);
+ verror_msg(msg, errno, va);
+ va_end(va);
- exit(!toys.exitval ? 1 : toys.exitval);
+ exit(!toys.exitval ? 1 : toys.exitval);
}
// Die unless we can allocate memory.
void *xmalloc(size_t size)
{
- void *ret = malloc(size);
- if (!ret) error_exit("xmalloc");
+ void *ret = malloc(size);
+ if (!ret) error_exit("xmalloc");
- return ret;
+ return ret;
}
// Die unless we can allocate prezeroed memory.
void *xzalloc(size_t size)
{
- void *ret = xmalloc(size);
- memset(ret, 0, size);
- return ret;
+ void *ret = xmalloc(size);
+ memset(ret, 0, size);
+ return ret;
}
// Die unless we can change the size of an existing allocation, possibly
// moving it. (Notice different arguments from libc function.)
void *xrealloc(void *ptr, size_t size)
{
- ptr = realloc(ptr, size);
- if (!ptr) error_exit("xrealloc");
+ ptr = realloc(ptr, size);
+ if (!ptr) error_exit("xrealloc");
- return ptr;
+ return ptr;
}
// Die unless we can allocate a copy of this many bytes of string.
char *xstrndup(char *s, size_t n)
{
- char *ret = xmalloc(++n);
- strncpy(ret, s, n);
- ret[--n]=0;
+ char *ret = xmalloc(++n);
+ strncpy(ret, s, n);
+ ret[--n]=0;
- return ret;
+ return ret;
}
// Die unless we can allocate a copy of this string.
char *xstrdup(char *s)
{
- return xstrndup(s, strlen(s));
+ return xstrndup(s, strlen(s));
}
// Die unless we can allocate enough space to sprintf() into.
char *xmsprintf(char *format, ...)
{
- va_list va, va2;
- int len;
- char *ret;
+ va_list va, va2;
+ int len;
+ char *ret;
- va_start(va, format);
- va_copy(va2, va);
+ va_start(va, format);
+ va_copy(va2, va);
- // How long is it?
- len = vsnprintf(0, 0, format, va);
- len++;
- va_end(va);
+ // How long is it?
+ len = vsnprintf(0, 0, format, va);
+ len++;
+ va_end(va);
- // Allocate and do the sprintf()
- ret = xmalloc(len);
- vsnprintf(ret, len, format, va2);
- va_end(va2);
+ // Allocate and do the sprintf()
+ ret = xmalloc(len);
+ vsnprintf(ret, len, format, va2);
+ va_end(va2);
- return ret;
+ return ret;
}
void xprintf(char *format, ...)
{
- va_list va;
- va_start(va, format);
+ va_list va;
+ va_start(va, format);
- vprintf(format, va);
- if (ferror(stdout)) perror_exit("write");
+ vprintf(format, va);
+ if (ferror(stdout)) perror_exit("write");
}
void xputs(char *s)
{
- if (EOF == puts(s)) perror_exit("write");
+ if (EOF == puts(s)) perror_exit("write");
}
void xputc(char c)
{
- if (EOF == fputc(c, stdout) || fflush(stdout)) perror_exit("write");
+ if (EOF == fputc(c, stdout) || fflush(stdout)) perror_exit("write");
}
void xflush(void)
{
- if (fflush(stdout)) perror_exit("write");;
+ if (fflush(stdout)) perror_exit("write");;
}
// Die unless we can exec argv[] (or run builtin command). Note that anything
// with a path isn't a builtin, so /bin/sh won't match the builtin sh.
void xexec(char **argv)
{
- toy_exec(argv);
- execvp(argv[0], argv);
+ toy_exec(argv);
+ execvp(argv[0], argv);
- perror_exit("exec %s", argv[0]);
+ perror_exit("exec %s", argv[0]);
}
void xaccess(char *path, int flags)
{
- if (access(path, flags)) perror_exit("Can't access '%s'", path);
+ if (access(path, flags)) perror_exit("Can't access '%s'", path);
}
// Die unless we can delete a file. (File must exist to be deleted.)
void xunlink(char *path)
{
- if (unlink(path)) perror_exit("unlink '%s'", path);
+ if (unlink(path)) perror_exit("unlink '%s'", path);
}
// Die unless we can open/create a file, returning file descriptor.
int xcreate(char *path, int flags, int mode)
{
- int fd = open(path, flags, mode);
- if (fd == -1) perror_exit("%s", path);
- return fd;
+ int fd = open(path, flags, mode);
+ if (fd == -1) perror_exit("%s", path);
+ return fd;
}
// Die unless we can open a file, returning file descriptor.
int xopen(char *path, int flags)
{
- return xcreate(path, flags, 0);
+ return xcreate(path, flags, 0);
}
void xclose(int fd)
{
- if (close(fd)) perror_exit("xclose");
+ if (close(fd)) perror_exit("xclose");
}
int xdup(int fd)
{
- if (fd != -1) {
- fd = dup(fd);
- if (fd == -1) perror_exit("xdup");
- }
- return fd;
+ if (fd != -1) {
+ fd = dup(fd);
+ if (fd == -1) perror_exit("xdup");
+ }
+ return fd;
}
// Die unless we can open/create a file, returning FILE *.
FILE *xfopen(char *path, char *mode)
{
- FILE *f = fopen(path, mode);
- if (!f) perror_exit("No file %s", path);
- return f;
+ FILE *f = fopen(path, mode);
+ if (!f) perror_exit("No file %s", path);
+ return f;
}
// Keep reading until full or EOF
ssize_t readall(int fd, void *buf, size_t len)
{
- size_t count = 0;
+ size_t count = 0;
- while (count<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
}
diff --git a/lib/lib.h b/lib/lib.h
index d81e2d94..2b452566 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -1,4 +1,3 @@
-/* vi: set ts=4 :*/
/* lib.h - header file for lib directory
*
* Copyright 2006 Rob Landley <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);
+ }
}
diff --git a/main.c b/main.c
index 8bd0feef..c705d645 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,3 @@
-/* vi: set ts=4 :*/
/* Toybox infrastructure.
*
* Copyright 2006 Rob Landley <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"
diff --git a/toys.h b/toys.h
index eb7c67f6..72670cd7 100644
--- a/toys.h
+++ b/toys.h
@@ -1,4 +1,3 @@
-/* vi: set ts=4 :*/
/* Toybox infrastructure.
*
* Copyright 2006 Rob Landley <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,