aboutsummaryrefslogtreecommitdiff
path: root/toys/posix
diff options
context:
space:
mode:
Diffstat (limited to 'toys/posix')
-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
45 files changed, 3533 insertions, 3582 deletions
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);
+ }
}