aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2006-08-28 23:31:54 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2006-08-28 23:31:54 +0000
commit73561cc75ac31e63bcab4b4ebfaf738e4ca225e6 (patch)
tree2a57564b8917a983365c765d4daa83032d9f0a17
parent6ce8dae1d5a201156a83201de6c49cdcc4c8df3e (diff)
downloadbusybox-w32-73561cc75ac31e63bcab4b4ebfaf738e4ca225e6.tar.gz
busybox-w32-73561cc75ac31e63bcab4b4ebfaf738e4ca225e6.tar.bz2
busybox-w32-73561cc75ac31e63bcab4b4ebfaf738e4ca225e6.zip
- pull from busybox_scratch: r15829:15850
Various fixes, cleanups and shrinkage: saves 952 Bytes: text data bss dec hex filename 1087742 15853 790632 1894227 1ce753 ../busybox/busybox.old 1086790 15853 790632 1893275 1ce39b busybox via: # scripts/bloat-o-meter ../busybox/busybox_unstripped.old busybox_unstripped function old new delta ipcrm_main 756 822 +66 getval - 61 +61 maybe_set_utc - 40 +40 udhcpc_main 2896 2912 +16 md5_hash_block 428 437 +9 opt 8 16 +8 qgravechar 106 110 +4 make_bitmap 292 295 +3 inflate_unzip 2056 2059 +3 add_partition 1412 1414 +2 __parsespent 156 158 +2 qrealloc 41 42 +1 format - 1 +1 catv_main 313 314 +1 watch_main 293 292 -1 varunset 81 80 -1 part 1 - -1 check_if_skip 837 836 -1 start_stop_daemon_main 840 837 -3 create_lost_and_found 175 172 -3 supress_non_delimited_lines 4 - -4 static.l 4 - -4 static.c 5 1 -4 bsd_sum_file 237 233 -4 eval2 338 332 -6 arithmetic_common 166 158 -8 cmpfunc 22 5 -17 cksum_main 294 275 -19 cmp_main 465 439 -26 dd_main 1535 1508 -27 rmmod_main 376 333 -43 cut_file 727 644 -83 ipcs_main 3809 3721 -88 cut_main 722 614 -108 date_main 1443 1263 -180 remove_ids 222 - -222 ------------------------------------------------------------------------------ (add/remove: 3/4 grow/shrink: 11/18 up/down: 217/-853) Total: -636 bytes
-rw-r--r--Makefile1
-rw-r--r--coreutils/catv.c44
-rw-r--r--coreutils/cksum.c31
-rw-r--r--coreutils/cmp.c47
-rw-r--r--coreutils/cut.c479
-rw-r--r--coreutils/date.c260
-rw-r--r--coreutils/dd.c128
-rw-r--r--coreutils/du.c9
-rw-r--r--coreutils/expr.c406
-rw-r--r--coreutils/sum.c21
-rw-r--r--coreutils/tail.c21
-rw-r--r--coreutils/tee.c3
-rw-r--r--coreutils/watch.c21
-rw-r--r--include/libbb.h28
-rw-r--r--include/unarchive.h2
-rw-r--r--include/usage.h10
-rw-r--r--libbb/xfuncs.c133
-rwxr-xr-xtestsuite/all_sourcecode.tests1
-rw-r--r--util-linux/ipcrm.c216
-rw-r--r--util-linux/ipcs.c584
20 files changed, 1162 insertions, 1283 deletions
diff --git a/Makefile b/Makefile
index 82e002603..cc223478b 100644
--- a/Makefile
+++ b/Makefile
@@ -278,6 +278,7 @@ endif # CONFIG_FEATURE_FULL_LIBBUSYBOX
278APPLET_SRC:=$(APPLET_SRC-y) 278APPLET_SRC:=$(APPLET_SRC-y)
279APPLETS_DEFINE:=$(APPLETS_DEFINE-y) 279APPLETS_DEFINE:=$(APPLETS_DEFINE-y)
280else # CONFIG_BUILD_AT_ONCE 280else # CONFIG_BUILD_AT_ONCE
281APPLET_SRC:=
281# no --combine, build archives out of the individual .o 282# no --combine, build archives out of the individual .o
282# This was the old way the binary was built. 283# This was the old way the binary was built.
283libbusybox-obj:=archival/libunarchive/libunarchive.a \ 284libbusybox-obj:=archival/libunarchive/libunarchive.a \
diff --git a/coreutils/catv.c b/coreutils/catv.c
index e18203915..f8229c20e 100644
--- a/coreutils/catv.c
+++ b/coreutils/catv.c
@@ -14,49 +14,55 @@
14 14
15int catv_main(int argc, char **argv) 15int catv_main(int argc, char **argv)
16{ 16{
17 int retval = EXIT_SUCCESS, fd, flags; 17 int retval = EXIT_SUCCESS, fd;
18 unsigned long flags;
18 19
19 flags = bb_getopt_ulflags(argc, argv, "etv"); 20 flags = bb_getopt_ulflags(argc, argv, "etv");
20 flags ^= 4; 21#define CATV_OPT_e (1<<0)
21 22#define CATV_OPT_t (1<<1)
22 // Loop through files. 23#define CATV_OPT_v (1<<2)
24 flags ^= CATV_OPT_v;
23 25
24 argv += optind; 26 argv += optind;
25 do { 27 do {
26 // Read from stdin if there's nothing else to do. 28 /* Read from stdin if there's nothing else to do. */
27
28 fd = 0; 29 fd = 0;
29 if (*argv && 0>(fd = xopen(*argv, O_RDONLY))) retval = EXIT_FAILURE; 30 if (*argv && 0 > (fd = xopen(*argv, O_RDONLY)))
30 else for(;;) { 31 retval = EXIT_FAILURE;
32 else for (;;) {
31 int i, res; 33 int i, res;
32 34
33 res = read(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1)); 35 res = read(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1));
34 if (res < 0) retval = EXIT_FAILURE; 36 if (res < 0)
35 if (res <1) break; 37 retval = EXIT_FAILURE;
36 for (i=0; i<res; i++) { 38 if (res < 1)
37 char c=bb_common_bufsiz1[i]; 39 break;
40 for (i = 0; i < res; i++) {
41 char c = bb_common_bufsiz1[i];
38 42
39 if (c > 126 && (flags & 4)) { 43 if (c > 126 && (flags & CATV_OPT_v)) {
40 if (c == 127) { 44 if (c == 127) {
41 printf("^?"); 45 bb_printf("^?");
42 continue; 46 continue;
43 } else { 47 } else {
44 printf("M-"); 48 bb_printf("M-");
45 c -= 128; 49 c -= 128;
46 } 50 }
47 } 51 }
48 if (c < 32) { 52 if (c < 32) {
49 if (c == 10) { 53 if (c == 10) {
50 if (flags & 1) putchar('$'); 54 if (flags & CATV_OPT_e)
51 } else if (flags & (c==9 ? 2 : 4)) { 55 putchar('$');
52 printf("^%c", c+'@'); 56 } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) {
57 bb_printf("^%c", c+'@');
53 continue; 58 continue;
54 } 59 }
55 } 60 }
56 putchar(c); 61 putchar(c);
57 } 62 }
58 } 63 }
59 if (ENABLE_FEATURE_CLEAN_UP && fd) close(fd); 64 if (ENABLE_FEATURE_CLEAN_UP && fd)
65 close(fd);
60 } while (*++argv); 66 } while (*++argv);
61 67
62 return retval; 68 return retval;
diff --git a/coreutils/cksum.c b/coreutils/cksum.c
index 5849ddab2..9a45fd656 100644
--- a/coreutils/cksum.c
+++ b/coreutils/cksum.c
@@ -3,12 +3,13 @@
3 * cksum - calculate the CRC32 checksum of a file 3 * cksum - calculate the CRC32 checksum of a file
4 * 4 *
5 * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms 5 * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms
6 * 6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */
8 8
9#include "busybox.h" 9#include "busybox.h"
10 10
11int cksum_main(int argc, char **argv) { 11int cksum_main(int argc, char **argv)
12{
12 13
13 uint32_t *crc32_table = crc32_filltable(1); 14 uint32_t *crc32_table = crc32_filltable(1);
14 15
@@ -17,36 +18,36 @@ int cksum_main(int argc, char **argv) {
17 long length, filesize; 18 long length, filesize;
18 int bytes_read; 19 int bytes_read;
19 char *cp; 20 char *cp;
20 RESERVE_CONFIG_BUFFER(buf, BUFSIZ); 21
21 int inp_stdin = (argc == optind) ? 1 : 0; 22 int inp_stdin = (argc == optind) ? 1 : 0;
22 23
23 do { 24 do {
24 fp = bb_wfopen_input((inp_stdin) ? bb_msg_standard_input : *++argv); 25 fp = bb_wfopen_input((inp_stdin) ? bb_msg_standard_input : *++argv);
25 26
26 crc = 0; 27 crc = 0;
27 length = 0; 28 length = 0;
28 29
29 while ((bytes_read = fread(buf, 1, BUFSIZ, fp)) > 0) { 30 while ((bytes_read = fread(bb_common_bufsiz1, 1, BUFSIZ, fp)) > 0) {
30 cp = buf; 31 cp = bb_common_bufsiz1;
31 length += bytes_read; 32 length += bytes_read;
32 while (bytes_read--) 33 while (bytes_read--)
33 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL]; 34 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL];
34 } 35 }
35 36
36 filesize = length; 37 filesize = length;
37 38
38 for (; length; length >>= 8) 39 for (; length; length >>= 8)
39 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL]; 40 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL];
40 crc ^= 0xffffffffL; 41 crc ^= 0xffffffffL;
41 42
42 if (inp_stdin) { 43 if (inp_stdin) {
43 printf("%"PRIu32" %li\n", crc, filesize); 44 bb_printf("%" PRIu32 " %li\n", crc, filesize);
44 break; 45 break;
45 } 46 }
46 47
47 printf("%"PRIu32" %li %s\n", crc, filesize, *argv); 48 bb_printf("%" PRIu32 " %li %s\n", crc, filesize, *argv);
48 fclose(fp); 49 fclose(fp);
49 } while (*(argv+1)); 50 } while (*(argv + 1));
50 51
51 return EXIT_SUCCESS; 52 return EXIT_SUCCESS;
52} 53}
diff --git a/coreutils/cmp.c b/coreutils/cmp.c
index a569eb3fe..ae3f50279 100644
--- a/coreutils/cmp.c
+++ b/coreutils/cmp.c
@@ -23,7 +23,7 @@
23 23
24#include "busybox.h" 24#include "busybox.h"
25 25
26static FILE *cmp_xfopen_input(const char *filename) 26static FILE *cmp_xfopen_input(const char * const filename)
27{ 27{
28 FILE *fp; 28 FILE *fp;
29 29
@@ -40,32 +40,28 @@ static const char fmt_differ[] = "%s %s differ: char %d, line %d\n";
40static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n"; 40static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n";
41 41
42static const char opt_chars[] = "sl"; 42static const char opt_chars[] = "sl";
43 43#define CMP_OPT_s (1<<0)
44enum { 44#define CMP_OPT_l (1<<1)
45 OPT_s = 1,
46 OPT_l = 2
47};
48 45
49int cmp_main(int argc, char **argv) 46int cmp_main(int argc, char **argv)
50{ 47{
51 FILE *fp1, *fp2, *outfile = stdout; 48 FILE *fp1, *fp2, *outfile = stdout;
52 const char *filename1, *filename2; 49 const char *filename1, *filename2 = "-";
53 const char *fmt; 50 const char *fmt;
54 int c1, c2, char_pos, line_pos; 51 int c1, c2, char_pos = 0, line_pos = 1;
55 int opt_flags; 52 unsigned opt;
56 int exit_val = 0; 53 int retval = 0;
57 54
58 bb_default_error_retval = 2; /* 1 is returned if files are different. */ 55 bb_default_error_retval = 2; /* 1 is returned if files are different. */
59 56
60 opt_flags = bb_getopt_ulflags(argc, argv, opt_chars); 57 opt = bb_getopt_ulflags(argc, argv, opt_chars);
61 58
62 if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) { 59 if ((opt & (CMP_OPT_s|CMP_OPT_l))
60 || (((unsigned int)(--argc - optind)) > 1))
63 bb_show_usage(); 61 bb_show_usage();
64 }
65 62
66 fp1 = cmp_xfopen_input(filename1 = *(argv += optind)); 63 fp1 = cmp_xfopen_input(filename1 = *(argv += optind));
67 64
68 filename2 = "-";
69 if (*++argv) { 65 if (*++argv) {
70 filename2 = *argv; 66 filename2 = *argv;
71 } 67 }
@@ -79,19 +75,17 @@ int cmp_main(int argc, char **argv)
79 return 0; 75 return 0;
80 } 76 }
81 77
82 fmt = fmt_differ; 78 if (opt & CMP_OPT_l)
83 if (opt_flags == OPT_l) {
84 fmt = fmt_l_opt; 79 fmt = fmt_l_opt;
85 } 80 else
81 fmt = fmt_differ;
86 82
87 char_pos = 0;
88 line_pos = 1;
89 do { 83 do {
90 c1 = getc(fp1); 84 c1 = getc(fp1);
91 c2 = getc(fp2); 85 c2 = getc(fp2);
92 ++char_pos; 86 ++char_pos;
93 if (c1 != c2) { /* Remember -- a read error may have occurred. */ 87 if (c1 != c2) { /* Remember: a read error may have occurred. */
94 exit_val = 1; /* But assume the files are different for now. */ 88 retval = 1; /* But assume the files are different for now. */
95 if (c2 == EOF) { 89 if (c2 == EOF) {
96 /* We know that fp1 isn't at EOF or in an error state. But to 90 /* We know that fp1 isn't at EOF or in an error state. But to
97 * save space below, things are setup to expect an EOF in fp1 91 * save space below, things are setup to expect an EOF in fp1
@@ -109,13 +103,14 @@ int cmp_main(int argc, char **argv)
109 * make sure we fflush before writing to stderr. */ 103 * make sure we fflush before writing to stderr. */
110 xfflush_stdout(); 104 xfflush_stdout();
111 } 105 }
112 if (opt_flags != OPT_s) { 106 if (!opt & CMP_OPT_s) {
113 if (opt_flags == OPT_l) { 107 if (opt & CMP_OPT_l) {
114 line_pos = c1; /* line_pos is unused in the -l case. */ 108 line_pos = c1; /* line_pos is unused in the -l case. */
115 } 109 }
116 bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2); 110 bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
117 if (opt_flags) { /* This must be -l since not -s. */ 111 if (opt) { /* This must be -l since not -s. */
118 /* If we encountered and EOF, the while check will catch it. */ 112 /* If we encountered an EOF,
113 * the while check will catch it. */
119 continue; 114 continue;
120 } 115 }
121 } 116 }
@@ -129,5 +124,5 @@ int cmp_main(int argc, char **argv)
129 xferror(fp1, filename1); 124 xferror(fp1, filename1);
130 xferror(fp2, filename2); 125 xferror(fp2, filename2);
131 126
132 bb_fflush_stdout_and_exit(exit_val); 127 bb_fflush_stdout_and_exit(retval);
133} 128}
diff --git a/coreutils/cut.c b/coreutils/cut.c
index 1b80e7e73..d88a891b0 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -4,28 +4,24 @@
4 * 4 *
5 * Copyright (C) 1999,2000,2001 by Lineo, inc. 5 * Copyright (C) 1999,2000,2001 by Lineo, inc.
6 * Written by Mark Whitley <markw@codepoet.org> 6 * Written by Mark Whitley <markw@codepoet.org>
7 * debloated by Bernhard Fischer
7 * 8 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */ 10 */
10 11
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <string.h>
15#include <limits.h>
16#include "busybox.h" 12#include "busybox.h"
17 13
18
19/* option vars */ 14/* option vars */
20static const char optstring[] = "b:c:f:d:sn"; 15static const char *const optstring = "b:c:f:d:sn";
21#define OPT_BYTE_FLGS 1 16
22#define OPT_CHAR_FLGS 2 17#define CUT_OPT_BYTE_FLGS (1<<0)
23#define OPT_FIELDS_FLGS 4 18#define CUT_OPT_CHAR_FLGS (1<<1)
24#define OPT_DELIM_FLGS 8 19#define CUT_OPT_FIELDS_FLGS (1<<2)
25#define OPT_SUPRESS_FLGS 16 20#define CUT_OPT_DELIM_FLGS (1<<3)
26static char part; /* (b)yte, (c)har, (f)ields */ 21#define CUT_OPT_SUPPRESS_FLGS (1<<4)
27static unsigned int supress_non_delimited_lines; 22static unsigned long opt;
28static char delim = '\t'; /* delimiter, default is tab */ 23
24static char delim = '\t'; /* delimiter, default is tab */
29 25
30struct cut_list { 26struct cut_list {
31 int startpos; 27 int startpos;
@@ -38,295 +34,268 @@ enum {
38 NON_RANGE = -1 34 NON_RANGE = -1
39}; 35};
40 36
41static struct cut_list *cut_lists = NULL; /* growable array holding a series of lists */ 37/* growable array holding a series of lists */
42static unsigned int nlists = 0; /* number of elements in above list */ 38static struct cut_list *cut_lists;
39static unsigned int nlists; /* number of elements in above list */
43 40
44 41
45static int cmpfunc(const void *a, const void *b) 42static int cmpfunc(const void *a, const void *b)
46{ 43{
47 struct cut_list *la = (struct cut_list *)a; 44 return (((struct cut_list *) a)->startpos -
48 struct cut_list *lb = (struct cut_list *)b; 45 ((struct cut_list *) b)->startpos);
49
50 if (la->startpos > lb->startpos)
51 return 1;
52 if (la->startpos < lb->startpos)
53 return -1;
54 return 0;
55}
56 46
47}
57 48
58/* 49static void cut_file(FILE * file)
59 * parse_lists() - parses a list and puts values into startpos and endpos.
60 * valid list formats: N, N-, N-M, -M
61 * more than one list can be separated by commas
62 */
63static void parse_lists(char *lists)
64{ 50{
65 char *ltok = NULL; 51 char *line = NULL;
66 char *ntok = NULL; 52 unsigned int linenum = 0; /* keep these zero-based to be consistent */
67 char *junk;
68 int s = 0, e = 0;
69
70 /* take apart the lists, one by one (they are separated with commas */
71 while ((ltok = strsep(&lists, ",")) != NULL) {
72
73 /* it's actually legal to pass an empty list */
74 if (strlen(ltok) == 0)
75 continue;
76
77 /* get the start pos */
78 ntok = strsep(&ltok, "-");
79 if (ntok == NULL) {
80 fprintf(stderr, "Help ntok is null for starting position! What do I do?\n");
81 } else if (strlen(ntok) == 0) {
82 s = BOL;
83 } else {
84 s = strtoul(ntok, &junk, 10);
85 if(*junk != '\0' || s < 0)
86 bb_error_msg_and_die("invalid byte or field list");
87
88 /* account for the fact that arrays are zero based, while the user
89 * expects the first char on the line to be char # 1 */
90 if (s != 0)
91 s--;
92 }
93
94 /* get the end pos */
95 ntok = strsep(&ltok, "-");
96 if (ntok == NULL) {
97 e = NON_RANGE;
98 } else if (strlen(ntok) == 0) {
99 e = EOL;
100 } else {
101 e = strtoul(ntok, &junk, 10);
102 if(*junk != '\0' || e < 0)
103 bb_error_msg_and_die("invalid byte or field list");
104 /* if the user specified and end position of 0, that means "til the
105 * end of the line */
106 if (e == 0)
107 e = INT_MAX;
108 e--; /* again, arrays are zero based, lines are 1 based */
109 if (e == s)
110 e = NON_RANGE;
111 }
112
113 /* if there's something left to tokenize, the user past an invalid list */
114 if (ltok)
115 bb_error_msg_and_die("invalid byte or field list");
116
117 /* add the new list */
118 cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
119 cut_lists[nlists-1].startpos = s;
120 cut_lists[nlists-1].endpos = e;
121 }
122
123 /* make sure we got some cut positions out of all that */
124 if (nlists == 0)
125 bb_error_msg_and_die("missing list of positions");
126
127 /* now that the lists are parsed, we need to sort them to make life easier
128 * on us when it comes time to print the chars / fields / lines */
129 qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
130 53
131} 54 /* go through every line in the file */
55 while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
132 56
57 /* set up a list so we can keep track of what's been printed */
58 char * printed = xzalloc(strlen(line) * sizeof(char));
59 char * orig_line = line;
60 unsigned int cl_pos = 0;
61 int spos;
133 62
134static void cut_line_by_chars(const char *line) 63 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
135{ 64 if ((opt & (CUT_OPT_CHAR_FLGS | CUT_OPT_BYTE_FLGS))) {
136 int c, l; 65 /* print the chars specified in each cut list */
137 /* set up a list so we can keep track of what's been printed */ 66 for (; cl_pos < nlists; cl_pos++) {
138 char *printed = xzalloc(strlen(line)); 67 spos = cut_lists[cl_pos].startpos;
139 68 while (spos < strlen(line)) {
140 /* print the chars specified in each cut list */ 69 if (!printed[spos]) {
141 for (c = 0; c < nlists; c++) { 70 printed[spos] = 'X';
142 l = cut_lists[c].startpos; 71 putchar(line[spos]);
143 while (l < strlen(line)) { 72 }
144 if (!printed[l]) { 73 spos++;
145 putchar(line[l]); 74 if (spos > cut_lists[cl_pos].endpos
146 printed[l] = 'X'; 75 || cut_lists[cl_pos].endpos == NON_RANGE)
76 break;
77 }
78 }
79 } else if (delim == '\n') { /* cut by lines */
80 spos = cut_lists[cl_pos].startpos;
81
82 /* get out if we have no more lists to process or if the lines
83 * are lower than what we're interested in */
84 if (linenum < spos || cl_pos >= nlists)
85 goto next_line;
86
87 /* if the line we're looking for is lower than the one we were
88 * passed, it means we displayed it already, so move on */
89 while (spos < linenum) {
90 spos++;
91 /* go to the next list if we're at the end of this one */
92 if (spos > cut_lists[cl_pos].endpos
93 || cut_lists[cl_pos].endpos == NON_RANGE) {
94 cl_pos++;
95 /* get out if there's no more lists to process */
96 if (cl_pos >= nlists)
97 goto next_line;
98 spos = cut_lists[cl_pos].startpos;
99 /* get out if the current line is lower than the one
100 * we just became interested in */
101 if (linenum < spos)
102 goto next_line;
103 }
147 } 104 }
148 l++;
149 if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos)
150 break;
151 }
152 }
153 putchar('\n'); /* cuz we were handed a chomped line */
154 free(printed);
155}
156
157 105
158static void cut_line_by_fields(char *line) 106 /* If we made it here, it means we've found the line we're
159{ 107 * looking for, so print it */
160 int c, f;
161 int ndelim = -1; /* zero-based / one-based problem */
162 int nfields_printed = 0;
163 char *field = NULL;
164 char d[2] = { delim, 0 };
165 char *printed;
166
167 /* test the easy case first: does this line contain any delimiters? */
168 if (strchr(line, delim) == NULL) {
169 if (!supress_non_delimited_lines)
170 puts(line); 108 puts(line);
171 return; 109 goto next_line;
172 } 110 } else { /* cut by fields */
173 111 int ndelim = -1; /* zero-based / one-based problem */
174 /* set up a list so we can keep track of what's been printed */ 112 int nfields_printed = 0;
175 printed = xzalloc(strlen(line)); 113 char *field = NULL;
176 114 const char delimiter[2] = { delim, 0 };
177 /* process each list on this line, for as long as we've got a line to process */ 115
178 for (c = 0; c < nlists && line; c++) { 116 /* does this line contain any delimiters? */
179 f = cut_lists[c].startpos; 117 if (strchr(line, delim) == NULL) {
180 do { 118 if (!(opt & CUT_OPT_SUPPRESS_FLGS))
181 119 puts(line);
182 /* find the field we're looking for */ 120 goto next_line;
183 while (line && ndelim < f) {
184 field = strsep(&line, d);
185 ndelim++;
186 } 121 }
187 122
188 /* we found it, and it hasn't been printed yet */ 123 /* process each list on this line, for as long as we've got
189 if (field && ndelim == f && !printed[ndelim]) { 124 * a line to process */
190 /* if this isn't our first time through, we need to print the 125 for (; cl_pos < nlists && line; cl_pos++) {
191 * delimiter after the last field that was printed */ 126 spos = cut_lists[cl_pos].startpos;
192 if (nfields_printed > 0) 127 do {
193 putchar(delim); 128
194 fputs(field, stdout); 129 /* find the field we're looking for */
195 printed[ndelim] = 'X'; 130 while (line && ndelim < spos) {
196 nfields_printed++; 131 field = strsep(&line, delimiter);
132 ndelim++;
133 }
134
135 /* we found it, and it hasn't been printed yet */
136 if (field && ndelim == spos && !printed[ndelim]) {
137 /* if this isn't our first time through, we need to
138 * print the delimiter after the last field that was
139 * printed */
140 if (nfields_printed > 0)
141 putchar(delim);
142 fputs(field, stdout);
143 printed[ndelim] = 'X';
144 nfields_printed++; /* shouldn't overflow.. */
145 }
146
147 spos++;
148
149 /* keep going as long as we have a line to work with,
150 * this is a list, and we're not at the end of that
151 * list */
152 } while (spos <= cut_lists[cl_pos].endpos && line
153 && cut_lists[cl_pos].endpos != NON_RANGE);
197 } 154 }
198
199 f++;
200
201 /* keep going as long as we have a line to work with, this is a
202 * list, and we're not at the end of that list */
203 } while (line && cut_lists[c].endpos != NON_RANGE && f <= cut_lists[c].endpos);
204 }
205
206 /* if we printed anything at all, we need to finish it with a newline cuz
207 * we were handed a chomped line */
208 putchar('\n');
209
210 free(printed);
211}
212
213
214static void cut_file_by_lines(const char *line, unsigned int linenum)
215{
216 static int c = 0;
217 static int l = -1;
218
219 /* I can't initialize this above cuz the "initializer isn't
220 * constant" *sigh* */
221 if (l == -1)
222 l = cut_lists[c].startpos;
223
224 /* get out if we have no more lists to process or if the lines are lower
225 * than what we're interested in */
226 if (c >= nlists || linenum < l)
227 return;
228
229 /* if the line we're looking for is lower than the one we were passed, it
230 * means we displayed it already, so move on */
231 while (l < linenum) {
232 l++;
233 /* move on to the next list if we're at the end of this one */
234 if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) {
235 c++;
236 /* get out if there's no more lists to process */
237 if (c >= nlists)
238 return;
239 l = cut_lists[c].startpos;
240 /* get out if the current line is lower than the one we just became
241 * interested in */
242 if (linenum < l)
243 return;
244 } 155 }
156 /* if we printed anything at all, we need to finish it with a
157 * newline cuz we were handed a chomped line */
158 putchar('\n');
159 next_line:
160 linenum++;
161 free(printed);
162 free(orig_line);
245 } 163 }
246
247 /* If we made it here, it means we've found the line we're looking for, so print it */
248 puts(line);
249} 164}
250 165
251 166static int getval(char *ntok)
252/*
253 * snippy-snip
254 */
255static void cut_file(FILE *file)
256{ 167{
257 char *line = NULL; 168 char *junk;
258 unsigned int linenum = 0; /* keep these zero-based to be consistent */ 169 int i = strtoul(ntok, &junk, 10);
259
260 /* go through every line in the file */
261 while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
262
263 /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
264 if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS)))
265 cut_line_by_chars(line);
266
267 /* cut based on fields */
268 else {
269 if (delim == '\n')
270 cut_file_by_lines(line, linenum);
271 else
272 cut_line_by_fields(line);
273 }
274 170
275 linenum++; 171 if (*junk != '\0' || i < 0)
276 free(line); 172 bb_error_msg_and_die("invalid byte or field list");
277 } 173 return i;
278} 174}
279 175
176static const char * const _op_on_field = " only when operating on fields";
280 177
281int cut_main(int argc, char **argv) 178int cut_main(int argc, char **argv)
282{ 179{
283 unsigned long opt; 180 char *sopt, *ltok;
284 char *sopt, *sdopt;
285 181
286 bb_opt_complementally = "b--bcf:c--bcf:f--bcf"; 182 bb_opt_complementally = "b--bcf:c--bcf:f--bcf";
287 opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt); 183 opt =
288 part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS); 184 bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &ltok);
289 if(part == 0) 185 if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS)))
290 bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); 186 bb_error_msg_and_die
291 if(opt & BB_GETOPT_ERROR) 187 ("expected a list of bytes, characters, or fields");
188 if (opt & BB_GETOPT_ERROR)
292 bb_error_msg_and_die("only one type of list may be specified"); 189 bb_error_msg_and_die("only one type of list may be specified");
293 parse_lists(sopt); 190
294 if((opt & (OPT_DELIM_FLGS))) { 191 if ((opt & (CUT_OPT_DELIM_FLGS))) {
295 if (strlen(sdopt) > 1) { 192 if (strlen(ltok) > 1) {
296 bb_error_msg_and_die("the delimiter must be a single character"); 193 bb_error_msg_and_die("the delimiter must be a single character");
297 } 194 }
298 delim = sdopt[0]; 195 delim = ltok[0];
299 } 196 }
300 supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS;
301 197
302 /* non-field (char or byte) cutting has some special handling */ 198 /* non-field (char or byte) cutting has some special handling */
303 if (part != OPT_FIELDS_FLGS) { 199 if (!(opt & CUT_OPT_FIELDS_FLGS)) {
304 if (supress_non_delimited_lines) { 200 if (opt & CUT_OPT_SUPPRESS_FLGS) {
305 bb_error_msg_and_die("suppressing non-delimited lines makes sense" 201 bb_error_msg_and_die
306 " only when operating on fields"); 202 ("suppressing non-delimited lines makes sense%s",
203 _op_on_field);
307 } 204 }
308 if (delim != '\t') { 205 if (delim != '\t') {
309 bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); 206 bb_error_msg_and_die
207 ("a delimiter may be specified%s", _op_on_field);
310 } 208 }
311 } 209 }
312 210
211 /*
212 * parse list and put values into startpos and endpos.
213 * valid list formats: N, N-, N-M, -M
214 * more than one list can be separated by commas
215 */
216 {
217 char *ntok;
218 int s = 0, e = 0;
219
220 /* take apart the lists, one by one (they are separated with commas */
221 while ((ltok = strsep(&sopt, ",")) != NULL) {
222
223 /* it's actually legal to pass an empty list */
224 if (strlen(ltok) == 0)
225 continue;
226
227 /* get the start pos */
228 ntok = strsep(&ltok, "-");
229 if (ntok == NULL) {
230 bb_error_msg
231 ("internal error: ntok is null for start pos!?\n");
232 } else if (strlen(ntok) == 0) {
233 s = BOL;
234 } else {
235 s = getval(ntok);
236 /* account for the fact that arrays are zero based, while
237 * the user expects the first char on the line to be char #1 */
238 if (s != 0)
239 s--;
240 }
241
242 /* get the end pos */
243 ntok = strsep(&ltok, "-");
244 if (ntok == NULL) {
245 e = NON_RANGE;
246 } else if (strlen(ntok) == 0) {
247 e = EOL;
248 } else {
249 e = getval(ntok);
250 /* if the user specified and end position of 0, that means "til the
251 * end of the line */
252 if (e == 0)
253 e = EOL;
254 e--; /* again, arrays are zero based, lines are 1 based */
255 if (e == s)
256 e = NON_RANGE;
257 }
258
259 /* if there's something left to tokenize, the user passed
260 * an invalid list */
261 if (ltok)
262 bb_error_msg_and_die("invalid byte or field list");
263
264 /* add the new list */
265 cut_lists =
266 xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
267 cut_lists[nlists - 1].startpos = s;
268 cut_lists[nlists - 1].endpos = e;
269 }
270
271 /* make sure we got some cut positions out of all that */
272 if (nlists == 0)
273 bb_error_msg_and_die("missing list of positions");
274
275 /* now that the lists are parsed, we need to sort them to make life
276 * easier on us when it comes time to print the chars / fields / lines
277 */
278 qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
279 }
280
313 /* argv[(optind)..(argc-1)] should be names of file to process. If no 281 /* argv[(optind)..(argc-1)] should be names of file to process. If no
314 * files were specified or '-' was specified, take input from stdin. 282 * files were specified or '-' was specified, take input from stdin.
315 * Otherwise, we process all the files specified. */ 283 * Otherwise, we process all the files specified. */
316 if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { 284 if (argv[optind] == NULL
285 || (argv[optind][0] == '-' && argv[optind][1] == '\0')) {
317 cut_file(stdin); 286 cut_file(stdin);
318 } 287 } else {
319 else {
320 int i;
321 FILE *file; 288 FILE *file;
322 for (i = optind; i < argc; i++) { 289
323 file = bb_wfopen(argv[i], "r"); 290 for (; optind < argc; optind++) {
324 if(file) { 291 file = bb_wfopen(argv[optind], "r");
292 if (file) {
325 cut_file(file); 293 cut_file(file);
326 fclose(file); 294 fclose(file);
327 } 295 }
328 } 296 }
329 } 297 }
330 298 if (ENABLE_FEATURE_CLEAN_UP)
299 free(cut_lists);
331 return EXIT_SUCCESS; 300 return EXIT_SUCCESS;
332} 301}
diff --git a/coreutils/date.c b/coreutils/date.c
index f08392ec2..2a82e0413 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -5,14 +5,17 @@
5 * by Matthew Grant <grantma@anathoth.gen.nz> 5 * by Matthew Grant <grantma@anathoth.gen.nz>
6 * 6 *
7 * iso-format handling added by Robert Griebl <griebl@gmx.de> 7 * iso-format handling added by Robert Griebl <griebl@gmx.de>
8 * bugfixes and cleanup by Bernhard Fischer
8 * 9 *
9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
10*/ 11*/
11 12
13#include "busybox.h"
14
12/* This 'date' command supports only 2 time setting formats, 15/* This 'date' command supports only 2 time setting formats,
13 all the GNU strftime stuff (its in libc, lets use it), 16 all the GNU strftime stuff (its in libc, lets use it),
14 setting time using UTC and displaying int, as well as 17 setting time using UTC and displaying it, as well as
15 an RFC 822 complient date output for shell scripting 18 an RFC 2822 compliant date output for shell scripting
16 mail commands */ 19 mail commands */
17 20
18/* Input parsing code is always bulky - used heavy duty libc stuff as 21/* Input parsing code is always bulky - used heavy duty libc stuff as
@@ -20,13 +23,6 @@
20 23
21/* Default input handling to save surprising some people */ 24/* Default input handling to save surprising some people */
22 25
23#include <stdlib.h>
24#include <errno.h>
25#include <unistd.h>
26#include <time.h>
27#include <stdio.h>
28#include <string.h>
29#include "busybox.h"
30 26
31#define DATE_OPT_RFC2822 0x01 27#define DATE_OPT_RFC2822 0x01
32#define DATE_OPT_SET 0x02 28#define DATE_OPT_SET 0x02
@@ -36,119 +32,45 @@
36#define DATE_OPT_TIMESPEC 0x20 32#define DATE_OPT_TIMESPEC 0x20
37#define DATE_OPT_HINT 0x40 33#define DATE_OPT_HINT 0x40
38 34
39 35static void maybe_set_utc(int opt)
40static struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
41{
42 int nr;
43 char *cp;
44
45 nr = sscanf(t_string, "%2d%2d%2d%2d%d", &(tm_time->tm_mon),
46 &(tm_time->tm_mday), &(tm_time->tm_hour), &(tm_time->tm_min),
47 &(tm_time->tm_year));
48
49 if (nr < 4 || nr > 5) {
50 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
51 }
52
53 cp = strchr(t_string, '.');
54 if (cp) {
55 nr = sscanf(cp + 1, "%2d", &(tm_time->tm_sec));
56 if (nr != 1) {
57 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
58 }
59 }
60
61 /* correct for century - minor Y2K problem here? */
62 if (tm_time->tm_year >= 1900) {
63 tm_time->tm_year -= 1900;
64 }
65 /* adjust date */
66 tm_time->tm_mon -= 1;
67
68 return (tm_time);
69
70}
71
72
73/* The new stuff for LRP */
74
75static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
76{ 36{
77 struct tm t; 37 if ((opt & DATE_OPT_UTC) && putenv("TZ=UTC0") != 0)
78 38 bb_error_msg_and_die(bb_msg_memory_exhausted);
79 /* Parse input and assign appropriately to tm_time */
80
81 if (t = *tm_time, sscanf(t_string, "%d:%d:%d", &t.tm_hour, &t.tm_min,
82 &t.tm_sec) == 3) {
83 /* no adjustments needed */
84 } else if (t = *tm_time, sscanf(t_string, "%d:%d", &t.tm_hour,
85 &t.tm_min) == 2) {
86 /* no adjustments needed */
87 } else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d:%d", &t.tm_mon,
88 &t.tm_mday, &t.tm_hour,
89 &t.tm_min, &t.tm_sec) == 5) {
90 /* Adjust dates from 1-12 to 0-11 */
91 t.tm_mon -= 1;
92 } else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d", &t.tm_mon,
93 &t.tm_mday,
94 &t.tm_hour, &t.tm_min) == 4) {
95 /* Adjust dates from 1-12 to 0-11 */
96 t.tm_mon -= 1;
97 } else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d:%d", &t.tm_year,
98 &t.tm_mon, &t.tm_mday,
99 &t.tm_hour, &t.tm_min,
100 &t.tm_sec) == 6) {
101 t.tm_year -= 1900; /* Adjust years */
102 t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
103 } else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d", &t.tm_year,
104 &t.tm_mon, &t.tm_mday,
105 &t.tm_hour, &t.tm_min) == 5) {
106 t.tm_year -= 1900; /* Adjust years */
107 t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
108 } else {
109 bb_error_msg_and_die(bb_msg_invalid_date, t_string);
110 }
111 *tm_time = t;
112 return (tm_time);
113} 39}
114 40
115int date_main(int argc, char **argv) 41int date_main(int argc, char **argv)
116{ 42{
117 char *date_str = NULL;
118 char *date_fmt = NULL;
119 int set_time;
120 int utc;
121 time_t tm; 43 time_t tm;
122 unsigned long opt;
123 struct tm tm_time; 44 struct tm tm_time;
45 unsigned long opt;
46 int ifmt = -1;
47 char *date_str = NULL;
48 char *date_fmt = NULL;
124 char *filename = NULL; 49 char *filename = NULL;
125
126 int ifmt = 0;
127 char *isofmt_arg; 50 char *isofmt_arg;
128 char *hintfmt_arg; 51 char *hintfmt_arg;
129 52
130 bb_opt_complementally = "?:d--s:s--d"; 53 bb_opt_complementally = "?:d--s:s--d"
54 USE_FEATURE_DATE_ISOFMT(":R--I:I--R");
131 opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:" 55 opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:"
132 USE_FEATURE_DATE_ISOFMT("I::D:"), 56 USE_FEATURE_DATE_ISOFMT("I::D:"),
133 &date_str, &date_str, &filename 57 &date_str, &date_str, &filename
134 USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg)); 58 USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg));
135 set_time = opt & DATE_OPT_SET; 59 maybe_set_utc(opt);
136 utc = opt & DATE_OPT_UTC;
137 if (utc && putenv("TZ=UTC0") != 0) {
138 bb_error_msg_and_die(bb_msg_memory_exhausted);
139 }
140 60
141 if(ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) { 61 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) {
142 if (!isofmt_arg) { 62 if (!isofmt_arg) {
143 ifmt = 1; 63 ifmt = 0; /* default is date */
144 } else { 64 } else {
145 char *isoformats[]={"date","hours","minutes","seconds"}; 65 const char * const isoformats[] =
146 for(ifmt = 4; ifmt;) 66 {"date", "hours", "minutes", "seconds"};
147 if(!strcmp(isofmt_arg,isoformats[--ifmt])) 67
68 for (ifmt = 0; ifmt < 4; ifmt++)
69 if (!strcmp(isofmt_arg, isoformats[ifmt])) {
148 break; 70 break;
149 } 71 }
150 if (!ifmt) { 72 if (ifmt == 4) /* parse error */
151 bb_show_usage(); 73 bb_show_usage();
152 } 74 }
153 } 75 }
154 76
@@ -156,18 +78,19 @@ int date_main(int argc, char **argv)
156 if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) { 78 if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) {
157 date_fmt = &argv[optind][1]; /* Skip over the '+' */ 79 date_fmt = &argv[optind][1]; /* Skip over the '+' */
158 } else if (date_str == NULL) { 80 } else if (date_str == NULL) {
159 set_time = 1; 81 opt |= DATE_OPT_SET;
160 date_str = argv[optind]; 82 date_str = argv[optind];
161 } 83 }
162 84
163 /* Now we have parsed all the information except the date format 85 /* Now we have parsed all the information except the date format
164 which depends on whether the clock is being set or read */ 86 which depends on whether the clock is being set or read */
165 87
166 if(filename) { 88 if (filename) {
167 struct stat statbuf; 89 struct stat statbuf;
168 xstat(filename,&statbuf); 90 xstat(filename, &statbuf);
169 tm=statbuf.st_mtime; 91 tm = statbuf.st_mtime;
170 } else time(&tm); 92 } else
93 time(&tm);
171 memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); 94 memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
172 /* Zero out fields - take her back to midnight! */ 95 /* Zero out fields - take her back to midnight! */
173 if (date_str != NULL) { 96 if (date_str != NULL) {
@@ -179,9 +102,64 @@ int date_main(int argc, char **argv)
179 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) { 102 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) {
180 strptime(date_str, hintfmt_arg, &tm_time); 103 strptime(date_str, hintfmt_arg, &tm_time);
181 } else if (strchr(date_str, ':') != NULL) { 104 } else if (strchr(date_str, ':') != NULL) {
182 date_conv_ftime(&tm_time, date_str); 105 /* Parse input and assign appropriately to tm_time */
106
107 if (sscanf(date_str, "%d:%d:%d", &tm_time.tm_hour, &tm_time.tm_min,
108 &tm_time.tm_sec) == 3) {
109 /* no adjustments needed */
110 } else if (sscanf(date_str, "%d:%d", &tm_time.tm_hour,
111 &tm_time.tm_min) == 2) {
112 /* no adjustments needed */
113 } else if (sscanf(date_str, "%d.%d-%d:%d:%d", &tm_time.tm_mon,
114 &tm_time.tm_mday, &tm_time.tm_hour,
115 &tm_time.tm_min, &tm_time.tm_sec) == 5) {
116 /* Adjust dates from 1-12 to 0-11 */
117 tm_time.tm_mon -= 1;
118 } else if (sscanf(date_str, "%d.%d-%d:%d", &tm_time.tm_mon,
119 &tm_time.tm_mday,
120 &tm_time.tm_hour, &tm_time.tm_min) == 4) {
121 /* Adjust dates from 1-12 to 0-11 */
122 tm_time.tm_mon -= 1;
123 } else if (sscanf(date_str, "%d.%d.%d-%d:%d:%d", &tm_time.tm_year,
124 &tm_time.tm_mon, &tm_time.tm_mday,
125 &tm_time.tm_hour, &tm_time.tm_min,
126 &tm_time.tm_sec) == 6) {
127 tm_time.tm_year -= 1900; /* Adjust years */
128 tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
129 } else if (sscanf(date_str, "%d.%d.%d-%d:%d", &tm_time.tm_year,
130 &tm_time.tm_mon, &tm_time.tm_mday,
131 &tm_time.tm_hour, &tm_time.tm_min) == 5) {
132 tm_time.tm_year -= 1900; /* Adjust years */
133 tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
134 } else {
135 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
136 }
183 } else { 137 } else {
184 date_conv_time(&tm_time, date_str); 138 int nr;
139 char *cp;
140
141 nr = sscanf(date_str, "%2d%2d%2d%2d%d", &tm_time.tm_mon,
142 &tm_time.tm_mday, &tm_time.tm_hour, &tm_time.tm_min,
143 &tm_time.tm_year);
144
145 if (nr < 4 || nr > 5) {
146 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
147 }
148
149 cp = strchr(date_str, '.');
150 if (cp) {
151 nr = sscanf(cp + 1, "%2d", &tm_time.tm_sec);
152 if (nr != 1) {
153 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
154 }
155 }
156
157 /* correct for century - minor Y2K problem here? */
158 if (tm_time.tm_year >= 1900) {
159 tm_time.tm_year -= 1900;
160 }
161 /* adjust date */
162 tm_time.tm_mon -= 1;
185 } 163 }
186 164
187 /* Correct any day of week and day of year etc. fields */ 165 /* Correct any day of week and day of year etc. fields */
@@ -190,12 +168,10 @@ int date_main(int argc, char **argv)
190 if (tm < 0) { 168 if (tm < 0) {
191 bb_error_msg_and_die(bb_msg_invalid_date, date_str); 169 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
192 } 170 }
193 if (utc && putenv("TZ=UTC0") != 0) { 171 maybe_set_utc(opt);
194 bb_error_msg_and_die(bb_msg_memory_exhausted);
195 }
196 172
197 /* if setting time, set it */ 173 /* if setting time, set it */
198 if (set_time && stime(&tm) < 0) { 174 if ((opt & DATE_OPT_SET) && stime(&tm) < 0) {
199 bb_perror_msg("cannot set date"); 175 bb_perror_msg("cannot set date");
200 } 176 }
201 } 177 }
@@ -203,33 +179,43 @@ int date_main(int argc, char **argv)
203 /* Display output */ 179 /* Display output */
204 180
205 /* Deal with format string */ 181 /* Deal with format string */
182
206 if (date_fmt == NULL) { 183 if (date_fmt == NULL) {
207 /* Start with the default case */ 184 int i;
208 185 date_fmt = xzalloc(32);
209 date_fmt = (opt & DATE_OPT_RFC2822 ? 186 if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) {
210 (utc ? "%a, %d %b %Y %H:%M:%S GMT" : 187 strcpy(date_fmt, "%Y-%m-%d");
211 "%a, %d %b %Y %H:%M:%S %z") : 188 if (ifmt > 0) {
212 "%a %b %e %H:%M:%S %Z %Y"); 189 i = 8;
213 190 date_fmt[i++] = 'T';
214 if (ENABLE_FEATURE_DATE_ISOFMT) { 191 date_fmt[i++] = '%';
215 if (ifmt == 4) 192 date_fmt[i++] = 'H';
216 date_fmt = utc ? "%Y-%m-%dT%H:%M:%SZ" : "%Y-%m-%dT%H:%M:%S%z"; 193 if (ifmt > 1) {
217 else if (ifmt == 3) 194 date_fmt[i++] = ':';
218 date_fmt = utc ? "%Y-%m-%dT%H:%MZ" : "%Y-%m-%dT%H:%M%z"; 195 date_fmt[i++] = '%';
219 else if (ifmt == 2) 196 date_fmt[i++] = 'M';
220 date_fmt = utc ? "%Y-%m-%dT%HZ" : "%Y-%m-%dT%H%z"; 197 }
221 else if (ifmt == 1) 198 if (ifmt > 2) {
222 date_fmt = "%Y-%m-%d"; 199 date_fmt[i++] = ':';
223 } 200 date_fmt[i++] = '%';
201 date_fmt[i++] = 'S';
202 }
203format_utc:
204 date_fmt[i++] = '%';
205 date_fmt[i] = (opt & DATE_OPT_UTC) ? 'Z' : 'z';
206 }
207 } else if (opt & DATE_OPT_RFC2822) {
208 strcpy(date_fmt, "%a, %d %b %Y %H:%M:%S ");
209 i = 22;
210 goto format_utc;
211 } else /* default case */
212 date_fmt = "%a %b %e %H:%M:%S %Z %Y";
224 } 213 }
225
226 if (*date_fmt == '\0') {
227 214
215 if (*date_fmt == '\0') {
228 /* With no format string, just print a blank line */ 216 /* With no format string, just print a blank line */
229 217 *bb_common_bufsiz1 = 0;
230 *bb_common_bufsiz1=0;
231 } else { 218 } else {
232
233 /* Handle special conversions */ 219 /* Handle special conversions */
234 220
235 if (strncmp(date_fmt, "%f", 2) == 0) { 221 if (strncmp(date_fmt, "%f", 2) == 0) {
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 052cd2902..a9536a584 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include "busybox.h" 11#include "busybox.h"
12#include <signal.h> /* For FEATURE_DD_SIGNAL_HANDLING */
12 13
13static const struct suffix_mult dd_suffixes[] = { 14static const struct suffix_mult dd_suffixes[] = {
14 { "c", 1 }, 15 { "c", 1 },
@@ -23,72 +24,72 @@ static const struct suffix_mult dd_suffixes[] = {
23 { NULL, 0 } 24 { NULL, 0 }
24}; 25};
25 26
26static size_t out_full; 27static size_t out_full, out_part, in_full, in_part;
27static size_t out_part;
28static size_t in_full;
29static size_t in_part;
30 28
31static void dd_output_status(int cur_signal) 29static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
32{ 30{
33 fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n", 31 bb_fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
34 (long)in_full, (long)in_part, 32 (long)in_full, (long)in_part,
35 (long)out_full, (long)out_part); 33 (long)out_full, (long)out_part);
36} 34}
37 35
38int dd_main(int argc, char **argv) 36int dd_main(int argc, char **argv)
39{ 37{
38#define sync_flag (1<<0)
39#define noerror (1<<1)
40#define trunc_flag (1<<2)
41#define twobufs_flag (1<<3)
42 int flags = trunc_flag;
40 size_t count = -1, oc = 0, ibs = 512, obs = 512; 43 size_t count = -1, oc = 0, ibs = 512, obs = 512;
41 ssize_t n; 44 ssize_t n;
42 off_t seek = 0, skip = 0; 45 off_t seek = 0, skip = 0;
43 int sync_flag = FALSE, noerror = FALSE, trunc_flag = TRUE, twobufs_flag = 0, 46 int oflag, ifd, ofd;
44 oflag, ifd, ofd, i;
45 const char *infile = NULL, *outfile = NULL; 47 const char *infile = NULL, *outfile = NULL;
46 char *ibuf, *obuf; 48 char *ibuf, *obuf;
47 49
48 if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) 50 if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) {
49 {
50 struct sigaction sa; 51 struct sigaction sa;
51 52
52 memset(&sa, 0, sizeof(sa)); 53 memset(&sa, 0, sizeof(sa));
53 sa.sa_handler = dd_output_status; 54 sa.sa_handler = dd_output_status;
54 sa.sa_flags = SA_RESTART; 55 sa.sa_flags = SA_RESTART;
55 sigemptyset(&sa.sa_mask); 56 sigemptyset(&sa.sa_mask);
56 sigaction(SIGUSR1, &sa, 0); 57 sigaction(SIGUSR1, &sa, 0);
57 } 58 }
58 59
59 for (i = 1; i < argc; i++) { 60 for (n = 1; n < argc; n++) {
60 if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[i], 4)) { 61 if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[n], 4)) {
61 ibs = bb_xparse_number(argv[i]+4, dd_suffixes); 62 ibs = bb_xparse_number(argv[n]+4, dd_suffixes);
62 twobufs_flag++; 63 flags |= twobufs_flag;
63 } else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[i], 4)) { 64 } else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[n], 4)) {
64 obs = bb_xparse_number(argv[i]+4, dd_suffixes); 65 obs = bb_xparse_number(argv[n]+4, dd_suffixes);
65 twobufs_flag++; 66 flags |= twobufs_flag;
66 } else if (!strncmp("bs=", argv[i], 3)) { 67 } else if (!strncmp("bs=", argv[n], 3))
67 ibs = obs = bb_xparse_number(argv[i]+3, dd_suffixes); 68 ibs = obs = bb_xparse_number(argv[n]+3, dd_suffixes);
68 } else if (!strncmp("count=", argv[i], 6)) 69 else if (!strncmp("count=", argv[n], 6))
69 count = bb_xparse_number(argv[i]+6, dd_suffixes); 70 count = bb_xparse_number(argv[n]+6, dd_suffixes);
70 else if (!strncmp("seek=", argv[i], 5)) 71 else if (!strncmp("seek=", argv[n], 5))
71 seek = bb_xparse_number(argv[i]+5, dd_suffixes); 72 seek = bb_xparse_number(argv[n]+5, dd_suffixes);
72 else if (!strncmp("skip=", argv[i], 5)) 73 else if (!strncmp("skip=", argv[n], 5))
73 skip = bb_xparse_number(argv[i]+5, dd_suffixes); 74 skip = bb_xparse_number(argv[n]+5, dd_suffixes);
74 else if (!strncmp("if=", argv[i], 3)) 75 else if (!strncmp("if=", argv[n], 3))
75 infile = argv[i]+3; 76 infile = argv[n]+3;
76 else if (!strncmp("of=", argv[i], 3)) 77 else if (!strncmp("of=", argv[n], 3))
77 outfile = argv[i]+3; 78 outfile = argv[n]+3;
78 else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[i], 5)) { 79 else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[n], 5)) {
79 ibuf = argv[i]+5; 80 ibuf = argv[n]+5;
80 while (1) { 81 while (1) {
81 if (!strncmp("notrunc", ibuf, 7)) { 82 if (!strncmp("notrunc", ibuf, 7)) {
82 trunc_flag = FALSE; 83 flags ^= trunc_flag;
83 ibuf += 7; 84 ibuf += 7;
84 } else if (!strncmp("sync", ibuf, 4)) { 85 } else if (!strncmp("sync", ibuf, 4)) {
85 sync_flag = TRUE; 86 flags |= sync_flag;
86 ibuf += 4; 87 ibuf += 4;
87 } else if (!strncmp("noerror", ibuf, 7)) { 88 } else if (!strncmp("noerror", ibuf, 7)) {
88 noerror = TRUE; 89 flags |= noerror;
89 ibuf += 7; 90 ibuf += 7;
90 } else { 91 } else {
91 bb_error_msg_and_die(bb_msg_invalid_arg, argv[i]+5, "conv"); 92 bb_error_msg_and_die(bb_msg_invalid_arg, argv[n]+5, "conv");
92 } 93 }
93 if (ibuf[0] == '\0') break; 94 if (ibuf[0] == '\0') break;
94 if (ibuf[0] == ',') ibuf++; 95 if (ibuf[0] == ',') ibuf++;
@@ -98,12 +99,14 @@ int dd_main(int argc, char **argv)
98 } 99 }
99 ibuf = xmalloc(ibs); 100 ibuf = xmalloc(ibs);
100 101
101 if (twobufs_flag) obuf = xmalloc(obs); 102 if (flags & twobufs_flag)
102 else obuf = ibuf; 103 obuf = xmalloc(obs);
104 else
105 obuf = ibuf;
103 106
104 if (infile != NULL) { 107 if (infile != NULL)
105 ifd = xopen(infile, O_RDONLY); 108 ifd = xopen(infile, O_RDONLY);
106 } else { 109 else {
107 ifd = STDIN_FILENO; 110 ifd = STDIN_FILENO;
108 infile = bb_msg_standard_input; 111 infile = bb_msg_standard_input;
109 } 112 }
@@ -111,20 +114,18 @@ int dd_main(int argc, char **argv)
111 if (outfile != NULL) { 114 if (outfile != NULL) {
112 oflag = O_WRONLY | O_CREAT; 115 oflag = O_WRONLY | O_CREAT;
113 116
114 if (!seek && trunc_flag) { 117 if (!seek && (flags & trunc_flag))
115 oflag |= O_TRUNC; 118 oflag |= O_TRUNC;
116 }
117 119
118 ofd = xopen3(outfile, oflag, 0666); 120 ofd = xopen3(outfile, oflag, 0666);
119 121
120 if (seek && trunc_flag) { 122 if (seek && (flags & trunc_flag)) {
121 if (ftruncate(ofd, seek * obs) < 0) { 123 if (ftruncate(ofd, seek * obs) < 0) {
122 struct stat st; 124 struct stat st;
123 125
124 if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) || 126 if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) ||
125 S_ISDIR (st.st_mode)) { 127 S_ISDIR(st.st_mode))
126 bb_perror_msg_and_die("%s", outfile); 128 goto die_outfile;
127 }
128 } 129 }
129 } 130 }
130 } else { 131 } else {
@@ -145,44 +146,42 @@ int dd_main(int argc, char **argv)
145 } 146 }
146 147
147 if (seek) { 148 if (seek) {
148 if (lseek(ofd, seek * obs, SEEK_CUR) < 0) { 149 if (lseek(ofd, seek * obs, SEEK_CUR) < 0)
149 bb_perror_msg_and_die("%s", outfile); 150 goto die_outfile;
150 }
151 } 151 }
152 152
153 while (in_full + in_part != count) { 153 while (in_full + in_part != count) {
154 if (noerror) { 154 if (flags & noerror) {
155 /* Pre-zero the buffer when doing the noerror thing */ 155 /* Pre-zero the buffer when doing the noerror thing */
156 memset(ibuf, '\0', ibs); 156 memset(ibuf, '\0', ibs);
157 } 157 }
158 158
159 n = safe_read(ifd, ibuf, ibs); 159 n = safe_read(ifd, ibuf, ibs);
160 if (n == 0) { 160 if (n == 0)
161 break; 161 break;
162 }
163 if (n < 0) { 162 if (n < 0) {
164 if (noerror) { 163 if (flags & noerror) {
165 n = ibs; 164 n = ibs;
166 bb_perror_msg("%s", infile); 165 bb_perror_msg("%s", infile);
167 } else { 166 } else
168 bb_perror_msg_and_die("%s", infile); 167 bb_perror_msg_and_die("%s", infile);
169 }
170 } 168 }
171 if ((size_t)n == ibs) { 169 if ((size_t)n == ibs)
172 in_full++; 170 in_full++;
173 } else { 171 else {
174 in_part++; 172 in_part++;
175 if (sync_flag) { 173 if (sync_flag) {
176 memset(ibuf + n, '\0', ibs - n); 174 memset(ibuf + n, '\0', ibs - n);
177 n = ibs; 175 n = ibs;
178 } 176 }
179 } 177 }
180 if (twobufs_flag) { 178 if (flags & twobufs_flag) {
181 char *tmp = ibuf; 179 char *tmp = ibuf;
182 while (n) { 180 while (n) {
183 size_t d = obs - oc; 181 size_t d = obs - oc;
184 182
185 if (d > n) d = n; 183 if (d > n)
184 d = n;
186 memcpy(obuf + oc, tmp, d); 185 memcpy(obuf + oc, tmp, d);
187 n -= d; 186 n -= d;
188 tmp += d; 187 tmp += d;
@@ -195,8 +194,10 @@ int dd_main(int argc, char **argv)
195 } 194 }
196 } else { 195 } else {
197 xwrite(ofd, ibuf, n); 196 xwrite(ofd, ibuf, n);
198 if (n == ibs) out_full++; 197 if (n == ibs)
199 else out_part++; 198 out_full++;
199 else
200 out_part++;
200 } 201 }
201 } 202 }
202 203
@@ -209,6 +210,7 @@ int dd_main(int argc, char **argv)
209 } 210 }
210 211
211 if (close (ofd) < 0) { 212 if (close (ofd) < 0) {
213die_outfile:
212 bb_perror_msg_and_die("%s", outfile); 214 bb_perror_msg_and_die("%s", outfile);
213 } 215 }
214 216
diff --git a/coreutils/du.c b/coreutils/du.c
index 29427c779..3cc935553 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -23,11 +23,6 @@
23 * 4) Fixed busybox bug #1284 involving long overflow with human_readable. 23 * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
24 */ 24 */
25 25
26#include <stdlib.h>
27#include <limits.h>
28#include <unistd.h>
29#include <dirent.h>
30#include <sys/stat.h>
31#include "busybox.h" 26#include "busybox.h"
32 27
33#ifdef CONFIG_FEATURE_HUMAN_READABLE 28#ifdef CONFIG_FEATURE_HUMAN_READABLE
@@ -57,7 +52,7 @@ static int one_file_system;
57static dev_t dir_dev; 52static dev_t dir_dev;
58 53
59 54
60static void print(long size, char *filename) 55static void print(long size, const char * const filename)
61{ 56{
62 /* TODO - May not want to defer error checking here. */ 57 /* TODO - May not want to defer error checking here. */
63#ifdef CONFIG_FEATURE_HUMAN_READABLE 58#ifdef CONFIG_FEATURE_HUMAN_READABLE
@@ -73,7 +68,7 @@ static void print(long size, char *filename)
73} 68}
74 69
75/* tiny recursive du */ 70/* tiny recursive du */
76static long du(char *filename) 71static long du(const char * const filename)
77{ 72{
78 struct stat statbuf; 73 struct stat statbuf;
79 long sum; 74 long sum;
diff --git a/coreutils/expr.c b/coreutils/expr.c
index 0a1baa19d..e7fdc5f1e 100644
--- a/coreutils/expr.c
+++ b/coreutils/expr.c
@@ -37,11 +37,13 @@ typedef enum valtype TYPE;
37 37
38#if ENABLE_EXPR_MATH_SUPPORT_64 38#if ENABLE_EXPR_MATH_SUPPORT_64
39typedef int64_t arith_t; 39typedef int64_t arith_t;
40
40#define PF_REZ "ll" 41#define PF_REZ "ll"
41#define PF_REZ_TYPE (long long) 42#define PF_REZ_TYPE (long long)
42#define STRTOL(s, e, b) strtoll(s, e, b) 43#define STRTOL(s, e, b) strtoll(s, e, b)
43#else 44#else
44typedef long arith_t; 45typedef long arith_t;
46
45#define PF_REZ "l" 47#define PF_REZ "l"
46#define PF_REZ_TYPE (long) 48#define PF_REZ_TYPE (long)
47#define STRTOL(s, e, b) strtol(s, e, b) 49#define STRTOL(s, e, b) strtol(s, e, b)
@@ -49,8 +51,8 @@ typedef long arith_t;
49 51
50/* A value is.... */ 52/* A value is.... */
51struct valinfo { 53struct valinfo {
52 TYPE type; /* Which kind. */ 54 TYPE type; /* Which kind. */
53 union { /* The value itself. */ 55 union { /* The value itself. */
54 arith_t i; 56 arith_t i;
55 char *s; 57 char *s;
56 } u; 58 } u;
@@ -60,17 +62,17 @@ typedef struct valinfo VALUE;
60/* The arguments given to the program, minus the program name. */ 62/* The arguments given to the program, minus the program name. */
61static char **args; 63static char **args;
62 64
63static VALUE *docolon (VALUE *sv, VALUE *pv); 65static VALUE *docolon(VALUE * sv, VALUE * pv);
64static VALUE *eval (void); 66static VALUE *eval(void);
65static VALUE *int_value (arith_t i); 67static VALUE *int_value(arith_t i);
66static VALUE *str_value (char *s); 68static VALUE *str_value(char *s);
67static int nextarg (char *str); 69static int nextarg(char *str);
68static int null (VALUE *v); 70static int null(VALUE * v);
69static int toarith (VALUE *v); 71static int toarith(VALUE * v);
70static void freev (VALUE *v); 72static void freev(VALUE * v);
71static void tostring (VALUE *v); 73static void tostring(VALUE * v);
72 74
73int expr_main (int argc, char **argv) 75int expr_main(int argc, char **argv)
74{ 76{
75 VALUE *v; 77 VALUE *v;
76 78
@@ -80,25 +82,25 @@ int expr_main (int argc, char **argv)
80 82
81 args = argv + 1; 83 args = argv + 1;
82 84
83 v = eval (); 85 v = eval();
84 if (*args) 86 if (*args)
85 bb_error_msg_and_die ("syntax error"); 87 bb_error_msg_and_die("syntax error");
86 88
87 if (v->type == integer) 89 if (v->type == integer)
88 printf ("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); 90 bb_printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
89 else 91 else
90 puts (v->u.s); 92 puts(v->u.s);
91 93
92 exit (null (v)); 94 exit(null(v));
93} 95}
94 96
95/* Return a VALUE for I. */ 97/* Return a VALUE for I. */
96 98
97static VALUE *int_value (arith_t i) 99static VALUE *int_value(arith_t i)
98{ 100{
99 VALUE *v; 101 VALUE *v;
100 102
101 v = xmalloc (sizeof(VALUE)); 103 v = xmalloc(sizeof(VALUE));
102 v->type = integer; 104 v->type = integer;
103 v->u.i = i; 105 v->u.i = i;
104 return v; 106 return v;
@@ -106,7 +108,7 @@ static VALUE *int_value (arith_t i)
106 108
107/* Return a VALUE for S. */ 109/* Return a VALUE for S. */
108 110
109static VALUE *str_value (char *s) 111static VALUE *str_value(char *s)
110{ 112{
111 VALUE *v; 113 VALUE *v;
112 114
@@ -118,28 +120,26 @@ static VALUE *str_value (char *s)
118 120
119/* Free VALUE V, including structure components. */ 121/* Free VALUE V, including structure components. */
120 122
121static void freev (VALUE *v) 123static void freev(VALUE * v)
122{ 124{
123 if (v->type == string) 125 if (v->type == string)
124 free (v->u.s); 126 free(v->u.s);
125 free (v); 127 free(v);
126} 128}
127 129
128/* Return nonzero if V is a null-string or zero-number. */ 130/* Return nonzero if V is a null-string or zero-number. */
129 131
130static int null (VALUE *v) 132static int null(VALUE * v)
131{ 133{
132 switch (v->type) { 134 if (v->type == integer)
133 case integer: 135 return v->u.i == 0;
134 return v->u.i == 0; 136 else /* string: */
135 default: /* string: */ 137 return v->u.s[0] == '\0' || strcmp(v->u.s, "0") == 0;
136 return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
137 }
138} 138}
139 139
140/* Coerce V to a string value (can't fail). */ 140/* Coerce V to a string value (can't fail). */
141 141
142static void tostring (VALUE *v) 142static void tostring(VALUE * v)
143{ 143{
144 if (v->type == integer) { 144 if (v->type == integer) {
145 v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i); 145 v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
@@ -149,9 +149,9 @@ static void tostring (VALUE *v)
149 149
150/* Coerce V to an integer value. Return 1 on success, 0 on failure. */ 150/* Coerce V to an integer value. Return 1 on success, 0 on failure. */
151 151
152static int toarith (VALUE *v) 152static int toarith(VALUE * v)
153{ 153{
154 if(v->type == string) { 154 if (v->type == string) {
155 arith_t i; 155 arith_t i;
156 char *e; 156 char *e;
157 157
@@ -160,7 +160,7 @@ static int toarith (VALUE *v)
160 i = STRTOL(v->u.s, &e, 10); 160 i = STRTOL(v->u.s, &e, 10);
161 if ((v->u.s == e) || *e) 161 if ((v->u.s == e) || *e)
162 return 0; 162 return 0;
163 free (v->u.s); 163 free(v->u.s);
164 v->u.i = i; 164 v->u.i = i;
165 v->type = integer; 165 v->type = integer;
166 } 166 }
@@ -170,221 +170,207 @@ static int toarith (VALUE *v)
170/* Return nonzero if the next token matches STR exactly. 170/* Return nonzero if the next token matches STR exactly.
171 STR must not be NULL. */ 171 STR must not be NULL. */
172 172
173static int 173static int nextarg(char *str)
174nextarg (char *str)
175{ 174{
176 if (*args == NULL) 175 if (*args == NULL)
177 return 0; 176 return 0;
178 return strcmp (*args, str) == 0; 177 return strcmp(*args, str) == 0;
179} 178}
180 179
181/* The comparison operator handling functions. */ 180/* The comparison operator handling functions. */
182 181
183static int cmp_common (VALUE *l, VALUE *r, int op) 182static int cmp_common(VALUE * l, VALUE * r, int op)
184{ 183{
185 int cmpval; 184 int cmpval;
186 185
187 if (l->type == string || r->type == string) { 186 if (l->type == string || r->type == string) {
188 tostring (l); 187 tostring(l);
189 tostring (r); 188 tostring(r);
190 cmpval = strcmp (l->u.s, r->u.s); 189 cmpval = strcmp(l->u.s, r->u.s);
191 } 190 } else
192 else
193 cmpval = l->u.i - r->u.i; 191 cmpval = l->u.i - r->u.i;
194 switch(op) { 192 if (op == '<')
195 case '<': 193 return cmpval < 0;
196 return cmpval < 0; 194 else if (op == ('L' + 'E'))
197 case ('L'+'E'): 195 return cmpval <= 0;
198 return cmpval <= 0; 196 else if (op == '=')
199 case '=': 197 return cmpval == 0;
200 return cmpval == 0; 198 else if (op == '!')
201 case '!': 199 return cmpval != 0;
202 return cmpval != 0; 200 else if (op == '>')
203 case '>': 201 return cmpval > 0;
204 return cmpval > 0; 202 else /* >= */
205 default: /* >= */ 203 return cmpval >= 0;
206 return cmpval >= 0;
207 }
208} 204}
209 205
210/* The arithmetic operator handling functions. */ 206/* The arithmetic operator handling functions. */
211 207
212static arith_t arithmetic_common (VALUE *l, VALUE *r, int op) 208static arith_t arithmetic_common(VALUE * l, VALUE * r, int op)
213{ 209{
214 arith_t li, ri; 210 arith_t li, ri;
215 211
216 if (!toarith (l) || !toarith (r)) 212 if (!toarith(l) || !toarith(r))
217 bb_error_msg_and_die ("non-numeric argument"); 213 bb_error_msg_and_die("non-numeric argument");
218 li = l->u.i; 214 li = l->u.i;
219 ri = r->u.i; 215 ri = r->u.i;
220 if((op == '/' || op == '%') && ri == 0) 216 if ((op == '/' || op == '%') && ri == 0)
221 bb_error_msg_and_die ( "division by zero"); 217 bb_error_msg_and_die("division by zero");
222 switch(op) { 218 if (op == '+')
223 case '+':
224 return li + ri; 219 return li + ri;
225 case '-': 220 else if (op == '-')
226 return li - ri; 221 return li - ri;
227 case '*': 222 else if (op == '*')
228 return li * ri; 223 return li * ri;
229 case '/': 224 else if (op == '/')
230 return li / ri; 225 return li / ri;
231 default: 226 else
232 return li % ri; 227 return li % ri;
233 }
234} 228}
235 229
236/* Do the : operator. 230/* Do the : operator.
237 SV is the VALUE for the lhs (the string), 231 SV is the VALUE for the lhs (the string),
238 PV is the VALUE for the rhs (the pattern). */ 232 PV is the VALUE for the rhs (the pattern). */
239 233
240static VALUE *docolon (VALUE *sv, VALUE *pv) 234static VALUE *docolon(VALUE * sv, VALUE * pv)
241{ 235{
242 VALUE *v; 236 VALUE *v;
243 regex_t re_buffer; 237 regex_t re_buffer;
244 const int NMATCH = 2; 238 const int NMATCH = 2;
245 regmatch_t re_regs[NMATCH]; 239 regmatch_t re_regs[NMATCH];
246 240
247 tostring (sv); 241 tostring(sv);
248 tostring (pv); 242 tostring(pv);
249 243
250 if (pv->u.s[0] == '^') { 244 if (pv->u.s[0] == '^') {
251 fprintf (stderr, "\ 245 fprintf(stderr, "\
252warning: unportable BRE: `%s': using `^' as the first character\n\ 246warning: unportable BRE: `%s': using `^' as the first character\n\
253of a basic regular expression is not portable; it is being ignored", 247of a basic regular expression is not portable; it is being ignored", pv->u.s);
254 pv->u.s);
255 } 248 }
256 249
257 memset (&re_buffer, 0, sizeof (re_buffer)); 250 memset(&re_buffer, 0, sizeof(re_buffer));
258 memset (re_regs, 0, sizeof (*re_regs)); 251 memset(re_regs, 0, sizeof(*re_regs));
259 if( regcomp (&re_buffer, pv->u.s, 0) != 0 ) 252 if (regcomp(&re_buffer, pv->u.s, 0) != 0)
260 bb_error_msg_and_die("Invalid regular expression"); 253 bb_error_msg_and_die("Invalid regular expression");
261 254
262 /* expr uses an anchored pattern match, so check that there was a 255 /* expr uses an anchored pattern match, so check that there was a
263 * match and that the match starts at offset 0. */ 256 * match and that the match starts at offset 0. */
264 if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && 257 if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
265 re_regs[0].rm_so == 0) { 258 re_regs[0].rm_so == 0) {
266 /* Were \(...\) used? */ 259 /* Were \(...\) used? */
267 if (re_buffer.re_nsub > 0) { 260 if (re_buffer.re_nsub > 0) {
268 sv->u.s[re_regs[1].rm_eo] = '\0'; 261 sv->u.s[re_regs[1].rm_eo] = '\0';
269 v = str_value (sv->u.s + re_regs[1].rm_so); 262 v = str_value(sv->u.s + re_regs[1].rm_so);
270 } 263 } else
271 else 264 v = int_value(re_regs[0].rm_eo);
272 v = int_value (re_regs[0].rm_eo); 265 } else {
273 }
274 else {
275 /* Match failed -- return the right kind of null. */ 266 /* Match failed -- return the right kind of null. */
276 if (re_buffer.re_nsub > 0) 267 if (re_buffer.re_nsub > 0)
277 v = str_value (""); 268 v = str_value("");
278 else 269 else
279 v = int_value (0); 270 v = int_value(0);
280 } 271 }
281 return v; 272 return v;
282} 273}
283 274
284/* Handle bare operands and ( expr ) syntax. */ 275/* Handle bare operands and ( expr ) syntax. */
285 276
286static VALUE *eval7 (void) 277static VALUE *eval7(void)
287{ 278{
288 VALUE *v; 279 VALUE *v;
289 280
290 if (!*args) 281 if (!*args)
291 bb_error_msg_and_die ( "syntax error"); 282 bb_error_msg_and_die("syntax error");
292 283
293 if (nextarg ("(")) { 284 if (nextarg("(")) {
294 args++; 285 args++;
295 v = eval (); 286 v = eval();
296 if (!nextarg (")")) 287 if (!nextarg(")"))
297 bb_error_msg_and_die ( "syntax error"); 288 bb_error_msg_and_die("syntax error");
298 args++; 289 args++;
299 return v; 290 return v;
300 } 291 }
301 292
302 if (nextarg (")")) 293 if (nextarg(")"))
303 bb_error_msg_and_die ( "syntax error"); 294 bb_error_msg_and_die("syntax error");
304 295
305 return str_value (*args++); 296 return str_value(*args++);
306} 297}
307 298
308/* Handle match, substr, index, length, and quote keywords. */ 299/* Handle match, substr, index, length, and quote keywords. */
309 300
310static VALUE *eval6 (void) 301static VALUE *eval6(void)
311{ 302{
312 VALUE *l, *r, *v, *i1, *i2; 303 VALUE *l, *r, *v, *i1, *i2;
313 304
314 if (nextarg ("quote")) { 305 if (nextarg("quote")) {
315 args++; 306 args++;
316 if (!*args) 307 if (!*args)
317 bb_error_msg_and_die ( "syntax error"); 308 bb_error_msg_and_die("syntax error");
318 return str_value (*args++); 309 return str_value(*args++);
319 } 310 } else if (nextarg("length")) {
320 else if (nextarg ("length")) {
321 args++; 311 args++;
322 r = eval6 (); 312 r = eval6();
323 tostring (r); 313 tostring(r);
324 v = int_value (strlen (r->u.s)); 314 v = int_value(strlen(r->u.s));
325 freev (r); 315 freev(r);
326 return v; 316 return v;
327 } 317 } else if (nextarg("match")) {
328 else if (nextarg ("match")) {
329 args++; 318 args++;
330 l = eval6 (); 319 l = eval6();
331 r = eval6 (); 320 r = eval6();
332 v = docolon (l, r); 321 v = docolon(l, r);
333 freev (l); 322 freev(l);
334 freev (r); 323 freev(r);
335 return v; 324 return v;
336 } 325 } else if (nextarg("index")) {
337 else if (nextarg ("index")) {
338 args++; 326 args++;
339 l = eval6 (); 327 l = eval6();
340 r = eval6 (); 328 r = eval6();
341 tostring (l); 329 tostring(l);
342 tostring (r); 330 tostring(r);
343 v = int_value (strcspn (l->u.s, r->u.s) + 1); 331 v = int_value(strcspn(l->u.s, r->u.s) + 1);
344 if (v->u.i == (arith_t) strlen (l->u.s) + 1) 332 if (v->u.i == (arith_t) strlen(l->u.s) + 1)
345 v->u.i = 0; 333 v->u.i = 0;
346 freev (l); 334 freev(l);
347 freev (r); 335 freev(r);
348 return v; 336 return v;
349 } 337 } else if (nextarg("substr")) {
350 else if (nextarg ("substr")) {
351 args++; 338 args++;
352 l = eval6 (); 339 l = eval6();
353 i1 = eval6 (); 340 i1 = eval6();
354 i2 = eval6 (); 341 i2 = eval6();
355 tostring (l); 342 tostring(l);
356 if (!toarith (i1) || !toarith (i2) 343 if (!toarith(i1) || !toarith(i2)
357 || i1->u.i > (arith_t) strlen (l->u.s) 344 || i1->u.i > (arith_t) strlen(l->u.s)
358 || i1->u.i <= 0 || i2->u.i <= 0) 345 || i1->u.i <= 0 || i2->u.i <= 0)
359 v = str_value (""); 346 v = str_value("");
360 else { 347 else {
361 v = xmalloc (sizeof(VALUE)); 348 v = xmalloc(sizeof(VALUE));
362 v->type = string; 349 v->type = string;
363 v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); 350 v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
364 } 351 }
365 freev (l); 352 freev(l);
366 freev (i1); 353 freev(i1);
367 freev (i2); 354 freev(i2);
368 return v; 355 return v;
369 } 356 } else
370 else 357 return eval7();
371 return eval7 ();
372} 358}
373 359
374/* Handle : operator (pattern matching). 360/* Handle : operator (pattern matching).
375 Calls docolon to do the real work. */ 361 Calls docolon to do the real work. */
376 362
377static VALUE *eval5 (void) 363static VALUE *eval5(void)
378{ 364{
379 VALUE *l, *r, *v; 365 VALUE *l, *r, *v;
380 366
381 l = eval6 (); 367 l = eval6();
382 while (nextarg (":")) { 368 while (nextarg(":")) {
383 args++; 369 args++;
384 r = eval6 (); 370 r = eval6();
385 v = docolon (l, r); 371 v = docolon(l, r);
386 freev (l); 372 freev(l);
387 freev (r); 373 freev(r);
388 l = v; 374 l = v;
389 } 375 }
390 return l; 376 return l;
@@ -392,128 +378,126 @@ static VALUE *eval5 (void)
392 378
393/* Handle *, /, % operators. */ 379/* Handle *, /, % operators. */
394 380
395static VALUE *eval4 (void) 381static VALUE *eval4(void)
396{ 382{
397 VALUE *l, *r; 383 VALUE *l, *r;
398 int op; 384 int op;
399 arith_t val; 385 arith_t val;
400 386
401 l = eval5 (); 387 l = eval5();
402 while (1) { 388 while (1) {
403 if (nextarg ("*")) 389 if (nextarg("*"))
404 op = '*'; 390 op = '*';
405 else if (nextarg ("/")) 391 else if (nextarg("/"))
406 op = '/'; 392 op = '/';
407 else if (nextarg ("%")) 393 else if (nextarg("%"))
408 op = '%'; 394 op = '%';
409 else 395 else
410 return l; 396 return l;
411 args++; 397 args++;
412 r = eval5 (); 398 r = eval5();
413 val = arithmetic_common (l, r, op); 399 val = arithmetic_common(l, r, op);
414 freev (l); 400 freev(l);
415 freev (r); 401 freev(r);
416 l = int_value (val); 402 l = int_value(val);
417 } 403 }
418} 404}
419 405
420/* Handle +, - operators. */ 406/* Handle +, - operators. */
421 407
422static VALUE *eval3 (void) 408static VALUE *eval3(void)
423{ 409{
424 VALUE *l, *r; 410 VALUE *l, *r;
425 int op; 411 int op;
426 arith_t val; 412 arith_t val;
427 413
428 l = eval4 (); 414 l = eval4();
429 while (1) { 415 while (1) {
430 if (nextarg ("+")) 416 if (nextarg("+"))
431 op = '+'; 417 op = '+';
432 else if (nextarg ("-")) 418 else if (nextarg("-"))
433 op = '-'; 419 op = '-';
434 else 420 else
435 return l; 421 return l;
436 args++; 422 args++;
437 r = eval4 (); 423 r = eval4();
438 val = arithmetic_common (l, r, op); 424 val = arithmetic_common(l, r, op);
439 freev (l); 425 freev(l);
440 freev (r); 426 freev(r);
441 l = int_value (val); 427 l = int_value(val);
442 } 428 }
443} 429}
444 430
445/* Handle comparisons. */ 431/* Handle comparisons. */
446 432
447static VALUE *eval2 (void) 433static VALUE *eval2(void)
448{ 434{
449 VALUE *l, *r; 435 VALUE *l, *r;
450 int op; 436 int op;
451 arith_t val; 437 arith_t val;
452 438
453 l = eval3 (); 439 l = eval3();
454 while (1) { 440 while (1) {
455 if (nextarg ("<")) 441 if (nextarg("<"))
456 op = '<'; 442 op = '<';
457 else if (nextarg ("<=")) 443 else if (nextarg("<="))
458 op = 'L'+'E'; 444 op = 'L' + 'E';
459 else if (nextarg ("=") || nextarg ("==")) 445 else if (nextarg("=") || nextarg("=="))
460 op = '='; 446 op = '=';
461 else if (nextarg ("!=")) 447 else if (nextarg("!="))
462 op = '!'; 448 op = '!';
463 else if (nextarg (">=")) 449 else if (nextarg(">="))
464 op = 'G'+'E'; 450 op = 'G' + 'E';
465 else if (nextarg (">")) 451 else if (nextarg(">"))
466 op = '>'; 452 op = '>';
467 else 453 else
468 return l; 454 return l;
469 args++; 455 args++;
470 r = eval3 (); 456 r = eval3();
471 toarith (l); 457 toarith(l);
472 toarith (r); 458 toarith(r);
473 val = cmp_common (l, r, op); 459 val = cmp_common(l, r, op);
474 freev (l); 460 freev(l);
475 freev (r); 461 freev(r);
476 l = int_value (val); 462 l = int_value(val);
477 } 463 }
478} 464}
479 465
480/* Handle &. */ 466/* Handle &. */
481 467
482static VALUE *eval1 (void) 468static VALUE *eval1(void)
483{ 469{
484 VALUE *l, *r; 470 VALUE *l, *r;
485 471
486 l = eval2 (); 472 l = eval2();
487 while (nextarg ("&")) { 473 while (nextarg("&")) {
488 args++; 474 args++;
489 r = eval2 (); 475 r = eval2();
490 if (null (l) || null (r)) { 476 if (null(l) || null(r)) {
491 freev (l); 477 freev(l);
492 freev (r); 478 freev(r);
493 l = int_value (0); 479 l = int_value(0);
494 } 480 } else
495 else 481 freev(r);
496 freev (r);
497 } 482 }
498 return l; 483 return l;
499} 484}
500 485
501/* Handle |. */ 486/* Handle |. */
502 487
503static VALUE *eval (void) 488static VALUE *eval(void)
504{ 489{
505 VALUE *l, *r; 490 VALUE *l, *r;
506 491
507 l = eval1 (); 492 l = eval1();
508 while (nextarg ("|")) { 493 while (nextarg("|")) {
509 args++; 494 args++;
510 r = eval1 (); 495 r = eval1();
511 if (null (l)) { 496 if (null(l)) {
512 freev (l); 497 freev(l);
513 l = r; 498 l = r;
514 } 499 } else
515 else 500 freev(r);
516 freev (r);
517 } 501 }
518 return l; 502 return l;
519} 503}
diff --git a/coreutils/sum.c b/coreutils/sum.c
index 2edd92036..d6a76dbbc 100644
--- a/coreutils/sum.c
+++ b/coreutils/sum.c
@@ -13,12 +13,6 @@
13 * Licensed under the GPL v2, see the file LICENSE in this tarball. 13 * Licensed under the GPL v2, see the file LICENSE in this tarball.
14 */ 14 */
15 15
16#include <stdio.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20#include <unistd.h>
21
22#include "busybox.h" 16#include "busybox.h"
23 17
24/* 1 if any of the files read were the standard input */ 18/* 1 if any of the files read were the standard input */
@@ -38,14 +32,15 @@ static int bsd_sum_file(const char *file, int print_name)
38 int checksum = 0; /* The checksum mod 2^16. */ 32 int checksum = 0; /* The checksum mod 2^16. */
39 uintmax_t total_bytes = 0; /* The number of bytes. */ 33 uintmax_t total_bytes = 0; /* The number of bytes. */
40 int ch; /* Each character read. */ 34 int ch; /* Each character read. */
35 int ret = 0;
41 36
42 if (IS_STDIN(file)) { 37 if (IS_STDIN(file)) {
43 fp = stdin; 38 fp = stdin;
44 have_read_stdin = 1; 39 have_read_stdin++;
45 } else { 40 } else {
46 fp = bb_wfopen(file, "r"); 41 fp = bb_wfopen(file, "r");
47 if (fp == NULL) 42 if (fp == NULL)
48 return 0; 43 goto out;
49 } 44 }
50 45
51 while ((ch = getc(fp)) != EOF) { 46 while ((ch = getc(fp)) != EOF) {
@@ -58,21 +53,21 @@ static int bsd_sum_file(const char *file, int print_name)
58 if (ferror(fp)) { 53 if (ferror(fp)) {
59 bb_perror_msg(file); 54 bb_perror_msg(file);
60 bb_fclose_nonstdin(fp); 55 bb_fclose_nonstdin(fp);
61 return 0; 56 goto out;
62 } 57 }
63 58
64 if (bb_fclose_nonstdin(fp) == EOF) { 59 if (bb_fclose_nonstdin(fp) == EOF) {
65 bb_perror_msg(file); 60 bb_perror_msg(file);
66 return 0; 61 goto out;
67 } 62 }
68 63 ret++;
69 printf("%05d %5ju ", checksum, (total_bytes+1023)/1024); 64 printf("%05d %5ju ", checksum, (total_bytes+1023)/1024);
70 if (print_name > 1) 65 if (print_name > 1)
71 puts(file); 66 puts(file);
72 else 67 else
73 printf("\n"); 68 printf("\n");
74 69out:
75 return 1; 70 return ret;
76} 71}
77 72
78/* Calculate and print the checksum and the size in 512-byte blocks 73/* Calculate and print the checksum and the size in 512-byte blocks
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 80a66fbf5..49f1bcd6a 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -42,20 +42,25 @@ static const struct suffix_mult tail_suffixes[] = {
42 42
43static int status; 43static int status;
44 44
45static void tail_xprint_header(const char *fmt, const char *filename) 45static void tail_xbb_full_write(const char *buf, size_t len)
46{ 46{
47 /* If we get an output error, there is really no sense in continuing. */ 47 /* If we get a write error, there is really no sense in continuing. */
48 if (dprintf(STDOUT_FILENO, fmt, filename) < 0) { 48 if (full_write(STDOUT_FILENO, buf, len) < 0)
49 bb_perror_nomsg_and_die(); 49 bb_perror_nomsg_and_die();
50 }
51} 50}
52 51
53/* len should probably be size_t */ 52static void tail_xprint_header(const char *fmt, const char *filename)
54static void tail_xbb_full_write(const char *buf, size_t len)
55{ 53{
56 /* If we get a write error, there is really no sense in continuing. */ 54#if defined __GLIBC__
57 if (full_write(STDOUT_FILENO, buf, len) < 0) 55 if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
58 bb_perror_nomsg_and_die(); 56 bb_perror_nomsg_and_die();
57 }
58#else
59 int hdr_len = strlen(fmt) + strlen(filename);
60 char *hdr = xzalloc(hdr_len);
61 sprintf(hdr, filename, filename);
62 tail_xbb_full_write(hdr, hdr_len);
63#endif
59} 64}
60 65
61static ssize_t tail_read(int fd, char *buf, size_t count) 66static ssize_t tail_read(int fd, char *buf, size_t count)
diff --git a/coreutils/tee.c b/coreutils/tee.c
index 4d0e6ff85..1f59f0361 100644
--- a/coreutils/tee.c
+++ b/coreutils/tee.c
@@ -11,6 +11,7 @@
11/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */ 11/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
12 12
13#include "busybox.h" 13#include "busybox.h"
14#include <signal.h>
14 15
15int tee_main(int argc, char **argv) 16int tee_main(int argc, char **argv)
16{ 17{
@@ -37,7 +38,7 @@ int tee_main(int argc, char **argv)
37 38
38 /* gnu tee ignores SIGPIPE in case one of the output files is a pipe 39 /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
39 * that doesn't consume all its input. Good idea... */ 40 * that doesn't consume all its input. Good idea... */
40 signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/ 41 signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/
41 42
42 /* Allocate an array of FILE *'s, with one extra for a sentinal. */ 43 /* Allocate an array of FILE *'s, with one extra for a sentinal. */
43 p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2)); 44 p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2));
diff --git a/coreutils/watch.c b/coreutils/watch.c
index c8b16b908..7b9c6698a 100644
--- a/coreutils/watch.c
+++ b/coreutils/watch.c
@@ -3,6 +3,7 @@
3 * Mini watch implementation for busybox 3 * Mini watch implementation for busybox
4 * 4 *
5 * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de> 5 * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de>
6 * Copyrigjt (C) Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
6 * 7 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */ 9 */
@@ -10,14 +11,9 @@
10/* BB_AUDIT SUSv3 N/A */ 11/* BB_AUDIT SUSv3 N/A */
11/* BB_AUDIT GNU defects -- only option -n is supported. */ 12/* BB_AUDIT GNU defects -- only option -n is supported. */
12 13
13/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
14 *
15 * Removed dependency on date_main(), added proper error checking, and
16 * reduced size.
17 */
18
19#include "busybox.h" 14#include "busybox.h"
20 15
16
21int watch_main(int argc, char **argv) 17int watch_main(int argc, char **argv)
22{ 18{
23 int width, len; 19 int width, len;
@@ -26,19 +22,18 @@ int watch_main(int argc, char **argv)
26 22
27 if (argc < 2) bb_show_usage(); 23 if (argc < 2) bb_show_usage();
28 24
29 get_terminal_width_height(1, &width, 0); 25 get_terminal_width_height(STDOUT_FILENO, &width, 0);
30 header = xzalloc(width--); 26 header = xzalloc(width--);
31 27
32 /* don't use getopt, because it permutes the arguments */ 28 /* don't use getopt, because it permutes the arguments */
33 ++argv; 29 ++argv;
34 if ((argc > 3) && !strcmp(*argv, "-n")) { 30 if ((argc > 3) && argv[0][0] == '-' && argv[0][1] == 'n') {
35 period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX); 31 period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
36 argv += 2; 32 argv += 2;
37 } 33 }
38 watched_argv = argv; 34 watched_argv = argv;
39 35
40 /* create header */ 36 /* create header */
41
42 len = snprintf(header, width, "Every %ds:", period); 37 len = snprintf(header, width, "Every %ds:", period);
43 while (*argv && len<width) 38 while (*argv && len<width)
44 snprintf(header+len, width-len, " %s", *(argv++)); 39 snprintf(header+len, width-len, " %s", *(argv++));
@@ -50,11 +45,13 @@ int watch_main(int argc, char **argv)
50 time(&t); 45 time(&t);
51 thyme = ctime(&t); 46 thyme = ctime(&t);
52 len = strlen(thyme); 47 len = strlen(thyme);
53 if (len < width) header[width-len] = 0; 48 if (len < width)
54 49 header[width-len] = 0;
55 printf("\033[H\033[J%s %s\n", header, thyme); 50 bb_printf("\033[H\033[J%s %s\n", header, thyme);
56 51
57 waitpid(xspawn(watched_argv),0,0); 52 waitpid(xspawn(watched_argv),0,0);
58 sleep(period); 53 sleep(period);
59 } 54 }
55 if (ENABLE_FEATURE_CLEAN_UP)
56 free(header);
60} 57}
diff --git a/include/libbb.h b/include/libbb.h
index 3c563a96f..b94586165 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -60,10 +60,6 @@
60#define PATH_MAX 256 60#define PATH_MAX 256
61#endif 61#endif
62 62
63#ifdef DMALLOC
64#include <dmalloc.h>
65#endif
66
67/* Some useful definitions */ 63/* Some useful definitions */
68#undef FALSE 64#undef FALSE
69#define FALSE ((int) 0) 65#define FALSE ((int) 0)
@@ -211,7 +207,9 @@ extern int bb_fprintf(FILE * __restrict stream, const char * __restrict format,
211extern int bb_printf(const char * __restrict format, ...) 207extern int bb_printf(const char * __restrict format, ...)
212 __attribute__ ((format (printf, 1, 2))); 208 __attribute__ ((format (printf, 1, 2)));
213 209
214//#warning rename to xferror_filename? 210#if ENABLE_NITPICK
211#warning rename to xferror_filename?
212#endif
215extern void xferror(FILE *fp, const char *fn); 213extern void xferror(FILE *fp, const char *fn);
216extern void xferror_stdout(void); 214extern void xferror_stdout(void);
217extern void xfflush_stdout(void); 215extern void xfflush_stdout(void);
@@ -265,7 +263,9 @@ extern long bb_xgetlarg_bnd_sfx(const char *arg, int base,
265extern long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes); 263extern long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes);
266 264
267 265
268//#warning pitchable now? 266#if ENABLE_NITPICK
267#warning pitchable now?
268#endif
269extern unsigned long bb_xparse_number(const char *numstr, 269extern unsigned long bb_xparse_number(const char *numstr,
270 const struct suffix_mult *suffixes); 270 const struct suffix_mult *suffixes);
271 271
@@ -330,7 +330,9 @@ char *concat_path_file(const char *path, const char *filename);
330char *concat_subpath_file(const char *path, const char *filename); 330char *concat_subpath_file(const char *path, const char *filename);
331char *last_char_is(const char *s, int c); 331char *last_char_is(const char *s, int c);
332 332
333//#warning yuk! 333#if ENABLE_NITPICK
334#warning yuk!
335#endif
334char *fgets_str(FILE *file, const char *terminating_string); 336char *fgets_str(FILE *file, const char *terminating_string);
335 337
336extern int uncompress(int fd_in, int fd_out); 338extern int uncompress(int fd_in, int fd_out);
@@ -344,7 +346,9 @@ extern int xconnect(struct sockaddr_in *s_addr);
344extern unsigned short bb_lookup_port(const char *port, const char *protocol, unsigned short default_port); 346extern unsigned short bb_lookup_port(const char *port, const char *protocol, unsigned short default_port);
345extern void bb_lookup_host(struct sockaddr_in *s_in, const char *host); 347extern void bb_lookup_host(struct sockaddr_in *s_in, const char *host);
346 348
347//#warning wrap this? 349#if ENABLE_NITPICK
350#warning wrap this?
351#endif
348char *dirname (char *path); 352char *dirname (char *path);
349 353
350int bb_make_directory (char *path, long mode, int flags); 354int bb_make_directory (char *path, long mode, int flags);
@@ -456,8 +460,10 @@ extern int bb_default_error_retval;
456# define FB_0 "/dev/fb0" 460# define FB_0 "/dev/fb0"
457#endif 461#endif
458 462
459//#warning put these in .o files
460 463
464#if ENABLE_NITPICK
465#warning put these in .o files
466#endif
461/* The following devices are the same on devfs and non-devfs systems. */ 467/* The following devices are the same on devfs and non-devfs systems. */
462#define CURRENT_TTY "/dev/tty" 468#define CURRENT_TTY "/dev/tty"
463#define CONSOLE_DEV "/dev/console" 469#define CONSOLE_DEV "/dev/console"
@@ -581,4 +587,8 @@ extern const char BB_BANNER[];
581#undef isupper 587#undef isupper
582#undef isxdigit 588#undef isxdigit
583 589
590#ifdef DMALLOC
591#include <dmalloc.h>
592#endif
593
584#endif /* __LIBBUSYBOX_H__ */ 594#endif /* __LIBBUSYBOX_H__ */
diff --git a/include/unarchive.h b/include/unarchive.h
index 05ab0c16a..1dbbc009d 100644
--- a/include/unarchive.h
+++ b/include/unarchive.h
@@ -10,8 +10,6 @@
10#define ARCHIVE_NOPRESERVE_OWN 32 10#define ARCHIVE_NOPRESERVE_OWN 32
11#define ARCHIVE_NOPRESERVE_PERM 64 11#define ARCHIVE_NOPRESERVE_PERM 64
12 12
13#include <sys/types.h>
14#include <stdio.h>
15#include "libbb.h" 13#include "libbb.h"
16 14
17typedef struct file_headers_s { 15typedef struct file_headers_s {
diff --git a/include/usage.h b/include/usage.h
index ced9f68c7..0f95708c5 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -1426,12 +1426,12 @@ USE_FEATURE_DATE_ISOFMT( \
1426#define ipcrm_trivial_usage \ 1426#define ipcrm_trivial_usage \
1427 "[-[MQS] key] [-[mqs] id]" 1427 "[-[MQS] key] [-[mqs] id]"
1428#define ipcrm_full_usage \ 1428#define ipcrm_full_usage \
1429 "The upper-case options MQS are used to remove a shared memory\n" \ 1429 "The upper-case options MQS are used to remove a shared memory segment by a\n" \
1430 "segment by an shmkey value. The lower-case options mqs are used\n" \ 1430 "segment by a shmkey value. The lower-case options mqs are used\n" \
1431 "to remove a segment by shmid value.\n" \ 1431 "to remove a segment by shmid value.\n" \
1432 "\t-m | -M\tRemove the memory segment after the last detach\n" \ 1432 "\t-[mM]\tRemove the memory segment after the last detach\n" \
1433 "\t-q | -Q\tRemove the message queue\n" \ 1433 "\t-[qQ]\tRemove the message queue\n" \
1434 "\t-s | -S\tRemove the semaphore" 1434 "\t-[sS]\tRemove the semaphore"
1435 1435
1436#define ipcs_trivial_usage \ 1436#define ipcs_trivial_usage \
1437 "[[-smq] -i shmid] | [[-asmq] [-tclup]]" 1437 "[[-smq] -i shmid] | [[-asmq] [-tclup]]"
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 4d81fdc28..b2b53a712 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -16,8 +16,12 @@
16 * succeeded. */ 16 * succeeded. */
17 17
18#ifndef DMALLOC 18#ifndef DMALLOC
19/* dmalloc provides variants of these that do abort() on failure.
20 * Since dmalloc's prototypes overwrite the impls here as they are
21 * included after these prototypes in libbb.h, all is well.
22 */
19#ifdef L_xmalloc 23#ifdef L_xmalloc
20// Die if we can't allocate size bytes of memory. 24/* Die if we can't allocate size bytes of memory. */
21void *xmalloc(size_t size) 25void *xmalloc(size_t size)
22{ 26{
23 void *ptr = malloc(size); 27 void *ptr = malloc(size);
@@ -28,9 +32,9 @@ void *xmalloc(size_t size)
28#endif 32#endif
29 33
30#ifdef L_xrealloc 34#ifdef L_xrealloc
31// Die if we can't resize previously allocated memory. (This returns a pointer 35/* Die if we can't resize previously allocated memory. (This returns a pointer
32// to the new memory, which may or may not be the same as the old memory. 36 * to the new memory, which may or may not be the same as the old memory.
33// It'll copy the contents to a new chunk and free the old one if necessary.) 37 * It'll copy the contents to a new chunk and free the old one if necessary.) */
34void *xrealloc(void *ptr, size_t size) 38void *xrealloc(void *ptr, size_t size)
35{ 39{
36 ptr = realloc(ptr, size); 40 ptr = realloc(ptr, size);
@@ -39,9 +43,11 @@ void *xrealloc(void *ptr, size_t size)
39 return ptr; 43 return ptr;
40} 44}
41#endif 45#endif
46#endif /* DMALLOC */
47
42 48
43#ifdef L_xzalloc 49#ifdef L_xzalloc
44// Die if we can't allocate and zero size bytes of memory. 50/* Die if we can't allocate and zero size bytes of memory. */
45void *xzalloc(size_t size) 51void *xzalloc(size_t size)
46{ 52{
47 void *ptr = xmalloc(size); 53 void *ptr = xmalloc(size);
@@ -50,10 +56,8 @@ void *xzalloc(size_t size)
50} 56}
51#endif 57#endif
52 58
53#endif /* DMALLOC */
54
55#ifdef L_xstrdup 59#ifdef L_xstrdup
56// Die if we can't copy a string to freshly allocated memory. 60/* Die if we can't copy a string to freshly allocated memory. */
57char * xstrdup(const char *s) 61char * xstrdup(const char *s)
58{ 62{
59 char *t; 63 char *t;
@@ -71,8 +75,9 @@ char * xstrdup(const char *s)
71#endif 75#endif
72 76
73#ifdef L_xstrndup 77#ifdef L_xstrndup
74// Die if we can't allocate n+1 bytes (space for the null terminator) and copy 78/* Die if we can't allocate n+1 bytes (space for the null terminator) and copy
75// the (possibly truncated to length n) string into it. 79 * the (possibly truncated to length n) string into it.
80 */
76char * xstrndup(const char *s, int n) 81char * xstrndup(const char *s, int n)
77{ 82{
78 char *t; 83 char *t;
@@ -87,8 +92,9 @@ char * xstrndup(const char *s, int n)
87#endif 92#endif
88 93
89#ifdef L_xfopen 94#ifdef L_xfopen
90// Die if we can't open a file and return a FILE * to it. 95/* Die if we can't open a file and return a FILE * to it.
91// Notice we haven't got xfread(), This is for use with fscanf() and friends. 96 * Notice we haven't got xfread(), This is for use with fscanf() and friends.
97 */
92FILE *xfopen(const char *path, const char *mode) 98FILE *xfopen(const char *path, const char *mode)
93{ 99{
94 FILE *fp; 100 FILE *fp;
@@ -99,7 +105,7 @@ FILE *xfopen(const char *path, const char *mode)
99#endif 105#endif
100 106
101#ifdef L_xopen 107#ifdef L_xopen
102// Die if we can't open an existing file and return an fd. 108/* Die if we can't open an existing file and return an fd. */
103int xopen(const char *pathname, int flags) 109int xopen(const char *pathname, int flags)
104{ 110{
105 if (ENABLE_DEBUG && (flags && O_CREAT)) 111 if (ENABLE_DEBUG && (flags && O_CREAT))
@@ -110,7 +116,7 @@ int xopen(const char *pathname, int flags)
110#endif 116#endif
111 117
112#ifdef L_xopen3 118#ifdef L_xopen3
113// Die if we can't open a new file and return an fd. 119/* Die if we can't open a new file and return an fd. */
114int xopen3(const char *pathname, int flags, int mode) 120int xopen3(const char *pathname, int flags, int mode)
115{ 121{
116 int ret; 122 int ret;
@@ -124,7 +130,7 @@ int xopen3(const char *pathname, int flags, int mode)
124#endif 130#endif
125 131
126#ifdef L_xread 132#ifdef L_xread
127// Die with an error message if we can't read the entire buffer. 133/* Die with an error message if we can't read the entire buffer. */
128void xread(int fd, void *buf, size_t count) 134void xread(int fd, void *buf, size_t count)
129{ 135{
130 while (count) { 136 while (count) {
@@ -139,7 +145,7 @@ void xread(int fd, void *buf, size_t count)
139#endif 145#endif
140 146
141#ifdef L_xwrite 147#ifdef L_xwrite
142// Die with an error message if we can't write the entire buffer. 148/* Die with an error message if we can't write the entire buffer. */
143void xwrite(int fd, void *buf, size_t count) 149void xwrite(int fd, void *buf, size_t count)
144{ 150{
145 while (count) { 151 while (count) {
@@ -154,7 +160,7 @@ void xwrite(int fd, void *buf, size_t count)
154#endif 160#endif
155 161
156#ifdef L_xlseek 162#ifdef L_xlseek
157// Die with an error message if we can't lseek to the right spot. 163/* Die with an error message if we can't lseek to the right spot. */
158void xlseek(int fd, off_t offset, int whence) 164void xlseek(int fd, off_t offset, int whence)
159{ 165{
160 if (offset != lseek(fd, offset, whence)) bb_error_msg_and_die("lseek"); 166 if (offset != lseek(fd, offset, whence)) bb_error_msg_and_die("lseek");
@@ -162,7 +168,7 @@ void xlseek(int fd, off_t offset, int whence)
162#endif 168#endif
163 169
164#ifdef L_xread_char 170#ifdef L_xread_char
165// Die with an error message if we can't read one character. 171/* Die with an error message if we can't read one character. */
166unsigned char xread_char(int fd) 172unsigned char xread_char(int fd)
167{ 173{
168 char tmp; 174 char tmp;
@@ -174,7 +180,7 @@ unsigned char xread_char(int fd)
174#endif 180#endif
175 181
176#ifdef L_xferror 182#ifdef L_xferror
177// Die with supplied error message if this FILE * has ferror set. 183/* Die with supplied error message if this FILE * has ferror set. */
178void xferror(FILE *fp, const char *fn) 184void xferror(FILE *fp, const char *fn)
179{ 185{
180 if (ferror(fp)) { 186 if (ferror(fp)) {
@@ -184,7 +190,7 @@ void xferror(FILE *fp, const char *fn)
184#endif 190#endif
185 191
186#ifdef L_xferror_stdout 192#ifdef L_xferror_stdout
187// Die with an error message if stdout has ferror set. 193/* Die with an error message if stdout has ferror set. */
188void xferror_stdout(void) 194void xferror_stdout(void)
189{ 195{
190 xferror(stdout, bb_msg_standard_output); 196 xferror(stdout, bb_msg_standard_output);
@@ -192,7 +198,7 @@ void xferror_stdout(void)
192#endif 198#endif
193 199
194#ifdef L_xfflush_stdout 200#ifdef L_xfflush_stdout
195// Die with an error message if we have trouble flushing stdout. 201/* Die with an error message if we have trouble flushing stdout. */
196void xfflush_stdout(void) 202void xfflush_stdout(void)
197{ 203{
198 if (fflush(stdout)) { 204 if (fflush(stdout)) {
@@ -202,24 +208,25 @@ void xfflush_stdout(void)
202#endif 208#endif
203 209
204#ifdef L_spawn 210#ifdef L_spawn
205// This does a fork/exec in one call, using vfork(). Return PID of new child, 211/* This does a fork/exec in one call, using vfork(). Return PID of new child,
206// -1 for failure. Runs argv[0], searching path if that has no / in it. 212 * -1 for failure. Runs argv[0], searching path if that has no / in it.
213 */
207pid_t spawn(char **argv) 214pid_t spawn(char **argv)
208{ 215{
209 static int failed; 216 static int failed;
210 pid_t pid; 217 pid_t pid;
211 void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0; 218 void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0;
212 219
213 // Be nice to nommu machines. 220 /* Be nice to nommu machines. */
214 failed = 0; 221 failed = 0;
215 pid = vfork(); 222 pid = vfork();
216 if (pid < 0) return pid; 223 if (pid < 0) return pid;
217 if (!pid) { 224 if (!pid) {
218 execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv); 225 execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);
219 226
220 // We're sharing a stack with blocked parent, let parent know we failed 227 /* We're sharing a stack with blocked parent, let parent know we failed
221 // and then exit to unblock parent (but don't run atexit() stuff, which 228 * and then exit to unblock parent (but don't run atexit() stuff, which
222 // would screw up parent.) 229 would screw up parent.) */
223 230
224 failed = -1; 231 failed = -1;
225 _exit(0); 232 _exit(0);
@@ -229,7 +236,7 @@ pid_t spawn(char **argv)
229#endif 236#endif
230 237
231#ifdef L_xspawn 238#ifdef L_xspawn
232// Die with an error message if we can't spawn a child process. 239/* Die with an error message if we can't spawn a child process. */
233pid_t xspawn(char **argv) 240pid_t xspawn(char **argv)
234{ 241{
235 pid_t pid = spawn(argv); 242 pid_t pid = spawn(argv);
@@ -239,7 +246,7 @@ pid_t xspawn(char **argv)
239#endif 246#endif
240 247
241#ifdef L_wait4 248#ifdef L_wait4
242// Wait for the specified child PID to exit, returning child's error return. 249/* Wait for the specified child PID to exit, returning child's error return. */
243int wait4pid(int pid) 250int wait4pid(int pid)
244{ 251{
245 int status; 252 int status;
@@ -252,9 +259,9 @@ int wait4pid(int pid)
252#endif 259#endif
253 260
254#ifdef L_itoa 261#ifdef L_itoa
255// Convert unsigned integer to ascii, writing into supplied buffer. A 262/* Convert unsigned integer to ascii, writing into supplied buffer. A
256// truncated result is always null terminated (unless buflen is 0), and 263 * truncated result is always null terminated (unless buflen is 0), and
257// contains the first few digits of the result ala strncpy. 264 * contains the first few digits of the result ala strncpy. */
258void utoa_to_buf(unsigned n, char *buf, unsigned buflen) 265void utoa_to_buf(unsigned n, char *buf, unsigned buflen)
259{ 266{
260 int i, out = 0; 267 int i, out = 0;
@@ -272,7 +279,7 @@ void utoa_to_buf(unsigned n, char *buf, unsigned buflen)
272 } 279 }
273} 280}
274 281
275// Convert signed integer to ascii, like utoa_to_buf() 282/* Convert signed integer to ascii, like utoa_to_buf() */
276void itoa_to_buf(int n, char *buf, unsigned buflen) 283void itoa_to_buf(int n, char *buf, unsigned buflen)
277{ 284{
278 if (buflen && n<0) { 285 if (buflen && n<0) {
@@ -283,16 +290,16 @@ void itoa_to_buf(int n, char *buf, unsigned buflen)
283 utoa_to_buf((unsigned)n, buf, buflen); 290 utoa_to_buf((unsigned)n, buf, buflen);
284} 291}
285 292
286// The following two functions use a static buffer, so calling either one a 293/* The following two functions use a static buffer, so calling either one a
287// second time will overwrite previous results. 294 * second time will overwrite previous results.
288// 295 *
289// The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes. 296 * The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
290// Int should always be 32 bits on any remotely Unix-like system, see 297 * Int should always be 32 bits on any remotely Unix-like system, see
291// http://www.unix.org/whitepapers/64bit.html for the reasons why. 298 * http://www.unix.org/whitepapers/64bit.html for the reasons why.
292 299*/
293static char local_buf[12]; 300static char local_buf[12];
294 301
295// Convert unsigned integer to ascii using a static buffer (returned). 302/* Convert unsigned integer to ascii using a static buffer (returned). */
296char *utoa(unsigned n) 303char *utoa(unsigned n)
297{ 304{
298 utoa_to_buf(n, local_buf, sizeof(local_buf)); 305 utoa_to_buf(n, local_buf, sizeof(local_buf));
@@ -300,7 +307,7 @@ char *utoa(unsigned n)
300 return local_buf; 307 return local_buf;
301} 308}
302 309
303// Convert signed integer to ascii using a static buffer (returned). 310/* Convert signed integer to ascii using a static buffer (returned). */
304char *itoa(int n) 311char *itoa(int n)
305{ 312{
306 itoa_to_buf(n, local_buf, sizeof(local_buf)); 313 itoa_to_buf(n, local_buf, sizeof(local_buf));
@@ -310,15 +317,15 @@ char *itoa(int n)
310#endif 317#endif
311 318
312#ifdef L_setuid 319#ifdef L_setuid
313// Die with an error message if we can't set gid. (Because resource limits may 320/* Die with an error message if we can't set gid. (Because resource limits may
314// limit this user to a given number of processes, and if that fills up the 321 * limit this user to a given number of processes, and if that fills up the
315// setgid() will fail and we'll _still_be_root_, which is bad.) 322 * setgid() will fail and we'll _still_be_root_, which is bad.) */
316void xsetgid(gid_t gid) 323void xsetgid(gid_t gid)
317{ 324{
318 if (setgid(gid)) bb_error_msg_and_die("setgid"); 325 if (setgid(gid)) bb_error_msg_and_die("setgid");
319} 326}
320 327
321// Die with an error message if we cant' set uid. (See xsetgid() for why.) 328/* Die with an error message if we cant' set uid. (See xsetgid() for why.) */
322void xsetuid(uid_t uid) 329void xsetuid(uid_t uid)
323{ 330{
324 if (setuid(uid)) bb_error_msg_and_die("setuid"); 331 if (setuid(uid)) bb_error_msg_and_die("setuid");
@@ -326,31 +333,31 @@ void xsetuid(uid_t uid)
326#endif 333#endif
327 334
328#ifdef L_fdlength 335#ifdef L_fdlength
329// Return how long the file at fd is, if there's any way to determine it. 336/* Return how long the file at fd is, if there's any way to determine it. */
330off_t fdlength(int fd) 337off_t fdlength(int fd)
331{ 338{
332 off_t bottom = 0, top = 0, pos; 339 off_t bottom = 0, top = 0, pos;
333 long size; 340 long size;
334 341
335 // If the ioctl works for this, return it. 342 /* If the ioctl works for this, return it. */
336 343
337 if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512; 344 if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
338 345
339 // If not, do a binary search for the last location we can read. (Some 346 /* If not, do a binary search for the last location we can read. (Some
340 // block devices don't do BLKGETSIZE right.) 347 * block devices don't do BLKGETSIZE right.) */
341 348
342 do { 349 do {
343 char temp; 350 char temp;
344 351
345 pos = bottom + (top - bottom) / 2;; 352 pos = bottom + (top - bottom) / 2;;
346 353
347 // If we can read from the current location, it's bigger. 354 /* If we can read from the current location, it's bigger. */
348 355
349 if (lseek(fd, pos, 0)>=0 && safe_read(fd, &temp, 1)==1) { 356 if (lseek(fd, pos, 0)>=0 && safe_read(fd, &temp, 1)==1) {
350 if (bottom == top) bottom = top = (top+1) * 2; 357 if (bottom == top) bottom = top = (top+1) * 2;
351 else bottom = pos; 358 else bottom = pos;
352 359
353 // If we can't, it's smaller. 360 /* If we can't, it's smaller. */
354 361
355 } else { 362 } else {
356 if (bottom == top) { 363 if (bottom == top) {
@@ -366,8 +373,8 @@ off_t fdlength(int fd)
366#endif 373#endif
367 374
368#ifdef L_xasprintf 375#ifdef L_xasprintf
369// Die with an error message if we can't malloc() enough space and do an 376/* Die with an error message if we can't malloc() enough space and do an
370// sprintf() into that space. 377 * sprintf() into that space. */
371char *xasprintf(const char *format, ...) 378char *xasprintf(const char *format, ...)
372{ 379{
373 va_list p; 380 va_list p;
@@ -396,8 +403,8 @@ char *xasprintf(const char *format, ...)
396#endif 403#endif
397 404
398#ifdef L_xprint_and_close_file 405#ifdef L_xprint_and_close_file
399// Die with an error message if we can't copy an entire FILE * to stdout, then 406/* Die with an error message if we can't copy an entire FILE * to stdout, then
400// close that file. 407 * close that file. */
401void xprint_and_close_file(FILE *file) 408void xprint_and_close_file(FILE *file)
402{ 409{
403 // copyfd outputs error messages for us. 410 // copyfd outputs error messages for us.
@@ -408,7 +415,7 @@ void xprint_and_close_file(FILE *file)
408#endif 415#endif
409 416
410#ifdef L_xchdir 417#ifdef L_xchdir
411// Die if we can't chdir to a new path. 418/* Die if we can't chdir to a new path. */
412void xchdir(const char *path) 419void xchdir(const char *path)
413{ 420{
414 if (chdir(path)) 421 if (chdir(path))
@@ -417,7 +424,7 @@ void xchdir(const char *path)
417#endif 424#endif
418 425
419#ifdef L_warn_opendir 426#ifdef L_warn_opendir
420// Print a warning message if opendir() fails, but don't die. 427/* Print a warning message if opendir() fails, but don't die. */
421DIR *warn_opendir(const char *path) 428DIR *warn_opendir(const char *path)
422{ 429{
423 DIR *dp; 430 DIR *dp;
@@ -431,7 +438,7 @@ DIR *warn_opendir(const char *path)
431#endif 438#endif
432 439
433#ifdef L_xopendir 440#ifdef L_xopendir
434// Die with an error message if opendir() fails. 441/* Die with an error message if opendir() fails. */
435DIR *xopendir(const char *path) 442DIR *xopendir(const char *path)
436{ 443{
437 DIR *dp; 444 DIR *dp;
@@ -444,7 +451,7 @@ DIR *xopendir(const char *path)
444 451
445#ifdef L_xdaemon 452#ifdef L_xdaemon
446#ifndef BB_NOMMU 453#ifndef BB_NOMMU
447// Die with an error message if we can't daemonize. 454/* Die with an error message if we can't daemonize. */
448void xdaemon(int nochdir, int noclose) 455void xdaemon(int nochdir, int noclose)
449{ 456{
450 if (daemon(nochdir, noclose)) bb_perror_msg_and_die("daemon"); 457 if (daemon(nochdir, noclose)) bb_perror_msg_and_die("daemon");
@@ -453,7 +460,7 @@ void xdaemon(int nochdir, int noclose)
453#endif 460#endif
454 461
455#ifdef L_xsocket 462#ifdef L_xsocket
456// Die with an error message if we can't open a new socket. 463/* Die with an error message if we can't open a new socket. */
457int xsocket(int domain, int type, int protocol) 464int xsocket(int domain, int type, int protocol)
458{ 465{
459 int r = socket(domain, type, protocol); 466 int r = socket(domain, type, protocol);
@@ -465,7 +472,7 @@ int xsocket(int domain, int type, int protocol)
465#endif 472#endif
466 473
467#ifdef L_xbind 474#ifdef L_xbind
468// Die with an error message if we can't bind a socket to an address. 475/* Die with an error message if we can't bind a socket to an address. */
469void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) 476void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
470{ 477{
471 if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind"); 478 if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
@@ -473,7 +480,7 @@ void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
473#endif 480#endif
474 481
475#ifdef L_xlisten 482#ifdef L_xlisten
476// Die with an error message if we can't listen for connections on a socket. 483/* Die with an error message if we can't listen for connections on a socket. */
477void xlisten(int s, int backlog) 484void xlisten(int s, int backlog)
478{ 485{
479 if (listen(s, backlog)) bb_perror_msg_and_die("listen"); 486 if (listen(s, backlog)) bb_perror_msg_and_die("listen");
diff --git a/testsuite/all_sourcecode.tests b/testsuite/all_sourcecode.tests
index 42360eb31..c115878fe 100755
--- a/testsuite/all_sourcecode.tests
+++ b/testsuite/all_sourcecode.tests
@@ -49,6 +49,7 @@ find $srcdir/../ \
49 -e '\<algorithic\>' \ 49 -e '\<algorithic\>' \
50 -e '\<deamon\>' \ 50 -e '\<deamon\>' \
51 -e '\<derefernce\>' \ 51 -e '\<derefernce\>' \
52 -e '\<acomadate\>' \
52 | sed -e "s:^$srcdir/\.\./::g" > src.typos 53 | sed -e "s:^$srcdir/\.\./::g" > src.typos
53testing "Common typos" "cat src.typos" "" "" "" 54testing "Common typos" "cat src.typos" "" "" ""
54rm -f src.typos 55rm -f src.typos
diff --git a/util-linux/ipcrm.c b/util-linux/ipcrm.c
index 2e164b8b3..735a8955b 100644
--- a/util-linux/ipcrm.c
+++ b/util-linux/ipcrm.c
@@ -1,56 +1,22 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * ipcrm.c -- utility to allow removal of IPC objects and data structures. 3 * ipcrm.c - utility to allow removal of IPC objects and data structures.
4 * 4 *
5 * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com> 5 * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
6 * Adapted for busybox from util-linux-2.12a. 6 * Adapted for busybox from util-linux-2.12a.
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * --- Pre-busybox history from util-linux-2.12a ------------------------
23 *
24 * 1999-04-02 frank zago
25 * - can now remove several id's in the same call
26 *
27 * 1999-02-22 Arkadiusz Miÿkiewicz <misiek@pld.ORG.PL>
28 * - added Native Language Support
29 *
30 * Original author - krishna balasubramanian 1993
31 */ 9 */
32 10
33#include <stdio.h> 11#include "busybox.h"
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37 12
38#include <sys/types.h> 13/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
14/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
39#include <sys/ipc.h> 15#include <sys/ipc.h>
40#include <sys/shm.h> 16#include <sys/shm.h>
41#include <sys/msg.h> 17#include <sys/msg.h>
42#include <sys/sem.h> 18#include <sys/sem.h>
43 19
44/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
45/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
46/* for getopt */
47#include <unistd.h>
48
49/* for tolower and isupper */
50#include <ctype.h>
51
52#include "busybox.h"
53
54#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) 20#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
55/* union semun is defined by including <sys/sem.h> */ 21/* union semun is defined by including <sys/sem.h> */
56#else 22#else
@@ -63,164 +29,149 @@ union semun {
63}; 29};
64#endif 30#endif
65 31
32#ifndef CONFIG_IPCRM_DROP_LEGACY
33
66typedef enum type_id { 34typedef enum type_id {
67 SHM, 35 SHM,
68 SEM, 36 SEM,
69 MSG 37 MSG
70} type_id; 38} type_id;
71 39
72static int 40static int remove_ids(type_id type, int argc, char **argv)
73remove_ids(type_id type, int argc, char **argv) { 41{
74 int id; 42 int id;
75 int ret = 0; /* for gcc */ 43 int ret = 0; /* silence gcc */
76 char *end; 44 char *end;
77 int nb_errors = 0; 45 int nb_errors = 0;
78 union semun arg; 46 union semun arg;
79 47
80 arg.val = 0; 48 arg.val = 0;
81 49
82 while(argc) { 50 while (argc) {
83 51
84 id = strtoul(argv[0], &end, 10); 52 id = strtoul(argv[0], &end, 10);
85 53
86 if (*end != 0) { 54 if (*end != 0) {
87 bb_printf ("invalid id: %s\n", argv[0]); 55 bb_error_msg("invalid id: %s", argv[0]);
88 nb_errors ++; 56 nb_errors++;
89 } else { 57 } else {
90 switch(type) { 58 if (type == SEM)
91 case SEM: 59 ret = semctl(id, 0, IPC_RMID, arg);
92 ret = semctl (id, 0, IPC_RMID, arg); 60 else if (type == MSG)
93 break; 61 ret = msgctl(id, IPC_RMID, NULL);
94 62 else if (type == SHM)
95 case MSG: 63 ret = shmctl(id, IPC_RMID, NULL);
96 ret = msgctl (id, IPC_RMID, NULL);
97 break;
98
99 case SHM:
100 ret = shmctl (id, IPC_RMID, NULL);
101 break;
102 }
103 64
104 if (ret) { 65 if (ret) {
105 bb_printf ("cannot remove id %s (%s)\n", 66 bb_perror_msg("cannot remove id %s", argv[0]);
106 argv[0], strerror(errno)); 67 nb_errors++;
107 nb_errors ++;
108 } 68 }
109 } 69 }
110 argc--; 70 argc--;
111 argv++; 71 argv++;
112 } 72 }
113 73
114 return(nb_errors); 74 return (nb_errors);
115}
116
117static int deprecated_main(int argc, char **argv)
118{
119 if (argc < 3) {
120 bb_show_usage();
121 bb_fflush_stdout_and_exit(1);
122 }
123
124 if (!strcmp(argv[1], "shm")) {
125 if (remove_ids(SHM, argc-2, &argv[2]))
126 bb_fflush_stdout_and_exit(1);
127 }
128 else if (!strcmp(argv[1], "msg")) {
129 if (remove_ids(MSG, argc-2, &argv[2]))
130 bb_fflush_stdout_and_exit(1);
131 }
132 else if (!strcmp(argv[1], "sem")) {
133 if (remove_ids(SEM, argc-2, &argv[2]))
134 bb_fflush_stdout_and_exit(1);
135 }
136 else {
137 bb_printf ("unknown resource type: %s\n", argv[1]);
138 bb_show_usage();
139 bb_fflush_stdout_and_exit(1);
140 }
141
142 bb_printf ("resource(s) deleted\n");
143 return 0;
144} 75}
76#endif /* #ifndef CONFIG_IPCRM_DROP_LEGACY */
145 77
146 78
147int ipcrm_main(int argc, char **argv) 79int ipcrm_main(int argc, char **argv)
148{ 80{
149 int c; 81 int c;
150 int error = 0; 82 int error = 0;
151 char *prog = argv[0];
152 83
153 /* if the command is executed without parameters, do nothing */ 84 /* if the command is executed without parameters, do nothing */
154 if (argc == 1) 85 if (argc == 1)
155 return 0; 86 return 0;
156 87#ifndef CONFIG_IPCRM_DROP_LEGACY
157 /* check to see if the command is being invoked in the old way if so 88 /* check to see if the command is being invoked in the old way if so
158 then run the old code */ 89 then run the old code. Valid commands are msg, shm, sem. */
159 if (strcmp(argv[1], "shm") == 0 || 90 {
160 strcmp(argv[1], "msg") == 0 || 91 type_id what = 0; /* silence gcc */
161 strcmp(argv[1], "sem") == 0) 92 char w;
162 return deprecated_main(argc, argv); 93
94 if ((((w=argv[1][0]) == 'm' && argv[1][1] == 's' && argv[1][2] == 'g')
95 || (argv[1][0] == 's'
96 && ((w=argv[1][1]) == 'h' || w == 'e')
97 && argv[1][2] == 'm'))
98 && argv[1][3] == '\0') {
99
100 if (argc < 3)
101 bb_show_usage();
102
103 if (w == 'h')
104 what = SHM;
105 else if (w == 'm')
106 what = MSG;
107 else if (w == 'e')
108 what = SEM;
109
110 if (remove_ids(what, argc-2, &argv[2]))
111 bb_fflush_stdout_and_exit(1);
112 bb_printf("resource(s) deleted\n");
113 return 0;
114 }
115 }
116#endif /* #ifndef CONFIG_IPCRM_DROP_LEGACY */
163 117
164 /* process new syntax to conform with SYSV ipcrm */ 118 /* process new syntax to conform with SYSV ipcrm */
165 while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) { 119 while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) {
166 int result; 120 int result;
167 int id = 0; 121 int id = 0;
168 int iskey = isupper(c); 122 int iskey = (isupper)(c);
169 123
170 /* needed to delete semaphores */ 124 /* needed to delete semaphores */
171 union semun arg; 125 union semun arg;
126
172 arg.val = 0; 127 arg.val = 0;
173 128
174 if ((c == '?') || (c == 'h')) 129 if ((c == '?') || (c == 'h')) {
175 {
176 bb_show_usage(); 130 bb_show_usage();
177 return 0;
178 } 131 }
179 132
180 /* we don't need case information any more */ 133 /* we don't need case information any more */
181 c = tolower(c); 134 c = tolower(c);
182 135
183 /* make sure the option is in range */ 136 /* make sure the option is in range: allowed are q, m, s */
184 if (c != 'q' && c != 'm' && c != 's') { 137 if (c != 'q' && c != 'm' && c != 's') {
185 bb_show_usage(); 138 bb_show_usage();
186 error++;
187 return error;
188 } 139 }
189 140
190 if (iskey) { 141 if (iskey) {
191 /* keys are in hex or decimal */ 142 /* keys are in hex or decimal */
192 key_t key = strtoul(optarg, NULL, 0); 143 key_t key = strtoul(optarg, NULL, 0);
144
193 if (key == IPC_PRIVATE) { 145 if (key == IPC_PRIVATE) {
194 error++; 146 error++;
195 bb_fprintf(stderr, "%s: illegal key (%s)\n", 147 bb_error_msg("illegal key (%s)", optarg);
196 prog, optarg);
197 continue; 148 continue;
198 } 149 }
199 150
200 /* convert key to id */ 151 /* convert key to id */
201 id = ((c == 'q') ? msgget(key, 0) : 152 id = ((c == 'q') ? msgget(key, 0) :
202 (c == 'm') ? shmget(key, 0, 0) : 153 (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
203 semget(key, 0, 0));
204 154
205 if (id < 0) { 155 if (id < 0) {
206 char *errmsg; 156 char *errmsg;
157 const char * const what = "key";
158
207 error++; 159 error++;
208 switch(errno) { 160 switch (errno) {
209 case EACCES: 161 case EACCES:
210 errmsg = "permission denied for key"; 162 errmsg = "permission denied for";
211 break; 163 break;
212 case EIDRM: 164 case EIDRM:
213 errmsg = "already removed key"; 165 errmsg = "already removed";
214 break; 166 break;
215 case ENOENT: 167 case ENOENT:
216 errmsg = "invalid key"; 168 errmsg = "invalid";
217 break; 169 break;
218 default: 170 default:
219 errmsg = "unknown error in key"; 171 errmsg = "unknown error in";
220 break; 172 break;
221 } 173 }
222 bb_fprintf(stderr, "%s: %s (%s)\n", 174 bb_error_msg("%s %s (%s)", errmsg, what, optarg);
223 prog, errmsg, optarg);
224 continue; 175 continue;
225 } 176 }
226 } else { 177 } else {
@@ -229,37 +180,30 @@ int ipcrm_main(int argc, char **argv)
229 } 180 }
230 181
231 result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) : 182 result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
232 (c == 'm') ? shmctl(id, IPC_RMID, NULL) : 183 (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
233 semctl(id, 0, IPC_RMID, arg)); 184 semctl(id, 0, IPC_RMID, arg));
234 185
235 if (result < 0) { 186 if (result) {
236 char *errmsg; 187 char *errmsg;
188 const char * const what = iskey ? "key" : "id";
189
237 error++; 190 error++;
238 switch(errno) { 191 switch (errno) {
239 case EACCES: 192 case EACCES:
240 case EPERM: 193 case EPERM:
241 errmsg = iskey 194 errmsg = "permission denied for";
242 ? "permission denied for key"
243 : "permission denied for id";
244 break; 195 break;
245 case EINVAL: 196 case EINVAL:
246 errmsg = iskey 197 errmsg = "invalid";
247 ? "invalid key"
248 : "invalid id";
249 break; 198 break;
250 case EIDRM: 199 case EIDRM:
251 errmsg = iskey 200 errmsg = "already removed";
252 ? "already removed key"
253 : "already removed id";
254 break; 201 break;
255 default: 202 default:
256 errmsg = iskey 203 errmsg = "unknown error in";
257 ? "unknown error in key"
258 : "unknown error in id";
259 break; 204 break;
260 } 205 }
261 bb_fprintf(stderr, "%s: %s (%s)\n", 206 bb_error_msg("%s %s (%s)", errmsg, what, optarg);
262 prog, errmsg, optarg);
263 continue; 207 continue;
264 } 208 }
265 } 209 }
diff --git a/util-linux/ipcs.c b/util-linux/ipcs.c
index fbc75cbee..c7c837669 100644
--- a/util-linux/ipcs.c
+++ b/util-linux/ipcs.c
@@ -8,9 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */ 9 */
10 10
11#include <stdio.h> 11#include "busybox.h"
12#include <stdlib.h>
13#include <getopt.h>
14#include <errno.h> 12#include <errno.h>
15#include <time.h> 13#include <time.h>
16#include <pwd.h> 14#include <pwd.h>
@@ -25,15 +23,15 @@
25#include <sys/msg.h> 23#include <sys/msg.h>
26#include <sys/shm.h> 24#include <sys/shm.h>
27 25
28#include "busybox.h" 26
29 27
30/*-------------------------------------------------------------------*/ 28/*-------------------------------------------------------------------*/
31/* SHM_DEST and SHM_LOCKED are defined in kernel headers, 29/* SHM_DEST and SHM_LOCKED are defined in kernel headers,
32 but inside #ifdef __KERNEL__ ... #endif */ 30 but inside #ifdef __KERNEL__ ... #endif */
33#ifndef SHM_DEST 31#ifndef SHM_DEST
34/* shm_mode upper byte flags */ 32/* shm_mode upper byte flags */
35#define SHM_DEST 01000 /* segment will be destroyed on last detach */ 33#define SHM_DEST 01000 /* segment will be destroyed on last detach */
36#define SHM_LOCKED 02000 /* segment will not be swapped */ 34#define SHM_LOCKED 02000 /* segment will not be swapped */
37#endif 35#endif
38 36
39/* For older kernels the same holds for the defines below */ 37/* For older kernels the same holds for the defines below */
@@ -46,12 +44,12 @@
46#define SHM_STAT 13 44#define SHM_STAT 13
47#define SHM_INFO 14 45#define SHM_INFO 14
48struct shm_info { 46struct shm_info {
49 int used_ids; 47 int used_ids;
50 ulong shm_tot; /* total allocated shm */ 48 ulong shm_tot; /* total allocated shm */
51 ulong shm_rss; /* total resident shm */ 49 ulong shm_rss; /* total resident shm */
52 ulong shm_swp; /* total swapped shm */ 50 ulong shm_swp; /* total swapped shm */
53 ulong swap_attempts; 51 ulong swap_attempts;
54 ulong swap_successes; 52 ulong swap_successes;
55}; 53};
56#endif 54#endif
57 55
@@ -98,12 +96,14 @@ union semun {
98#define TIME 4 96#define TIME 4
99#define PID 5 97#define PID 5
100 98
99static char format;
101 100
102static void print_perms (int id, struct ipc_perm *ipcp) { 101static void print_perms(int id, struct ipc_perm *ipcp)
102{
103 struct passwd *pw; 103 struct passwd *pw;
104 struct group *gr; 104 struct group *gr;
105 105
106 bb_printf ("%-10d %-10o", id, ipcp->mode & 0777); 106 bb_printf("%-10d %-10o", id, ipcp->mode & 0777);
107 107
108 if ((pw = getpwuid(ipcp->cuid))) 108 if ((pw = getpwuid(ipcp->cuid)))
109 bb_printf(" %-10s", pw->pw_name); 109 bb_printf(" %-10s", pw->pw_name);
@@ -125,7 +125,7 @@ static void print_perms (int id, struct ipc_perm *ipcp) {
125} 125}
126 126
127 127
128static void do_shm (char format) 128static void do_shm(void)
129{ 129{
130 int maxid, shmid, id; 130 int maxid, shmid, id;
131 struct shmid_ds shmseg; 131 struct shmid_ds shmseg;
@@ -134,127 +134,125 @@ static void do_shm (char format)
134 struct ipc_perm *ipcp = &shmseg.shm_perm; 134 struct ipc_perm *ipcp = &shmseg.shm_perm;
135 struct passwd *pw; 135 struct passwd *pw;
136 136
137 maxid = shmctl (0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info); 137 maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
138 if (maxid < 0) { 138 if (maxid < 0) {
139 bb_printf ("kernel not configured for shared memory\n"); 139 bb_printf("kernel not configured for shared memory\n");
140 return; 140 return;
141 } 141 }
142 142
143 switch (format) { 143 switch (format) {
144 case LIMITS: 144 case LIMITS:
145 bb_printf ("------ Shared Memory Limits --------\n"); 145 bb_printf("------ Shared Memory Limits --------\n");
146 if ((shmctl (0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0 ) 146 if ((shmctl(0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0)
147 return; 147 return;
148 /* glibc 2.1.3 and all earlier libc's have ints as fields 148 /* glibc 2.1.3 and all earlier libc's have ints as fields
149 of struct shminfo; glibc 2.1.91 has unsigned long; ach */ 149 of struct shminfo; glibc 2.1.91 has unsigned long; ach */
150 bb_printf ("max number of segments = %lu\n" 150 bb_printf("max number of segments = %lu\n"
151 "max seg size (kbytes) = %lu\n" 151 "max seg size (kbytes) = %lu\n"
152 "max total shared memory (pages) = %lu\n" 152 "max total shared memory (pages) = %lu\n"
153 "min seg size (bytes) = %lu\n", 153 "min seg size (bytes) = %lu\n",
154 (unsigned long) shminfo.shmmni, 154 (unsigned long) shminfo.shmmni,
155 (unsigned long) (shminfo.shmmax >> 10), 155 (unsigned long) (shminfo.shmmax >> 10),
156 (unsigned long) shminfo.shmall, 156 (unsigned long) shminfo.shmall,
157 (unsigned long) shminfo.shmmin); 157 (unsigned long) shminfo.shmmin);
158 return; 158 return;
159 159
160 case STATUS: 160 case STATUS:
161 bb_printf ("------ Shared Memory Status --------\n" 161 bb_printf("------ Shared Memory Status --------\n"
162 "segments allocated %d\n" 162 "segments allocated %d\n"
163 "pages allocated %ld\n" 163 "pages allocated %ld\n"
164 "pages resident %ld\n" 164 "pages resident %ld\n"
165 "pages swapped %ld\n" 165 "pages swapped %ld\n"
166 "Swap performance: %ld attempts\t %ld successes\n", 166 "Swap performance: %ld attempts\t %ld successes\n",
167 shm_info.used_ids, 167 shm_info.used_ids,
168 shm_info.shm_tot, 168 shm_info.shm_tot,
169 shm_info.shm_rss, 169 shm_info.shm_rss,
170 shm_info.shm_swp, 170 shm_info.shm_swp,
171 shm_info.swap_attempts, shm_info.swap_successes); 171 shm_info.swap_attempts, shm_info.swap_successes);
172 return; 172 return;
173 173
174 case CREATOR: 174 case CREATOR:
175 bb_printf ("------ Shared Memory Segment Creators/Owners --------\n" 175 bb_printf("------ Shared Memory Segment Creators/Owners --------\n"
176 "%-10s %-10s %-10s %-10s %-10s %-10s\n", 176 "%-10s %-10s %-10s %-10s %-10s %-10s\n",
177 "shmid","perms","cuid","cgid","uid","gid"); 177 "shmid", "perms", "cuid", "cgid", "uid", "gid");
178 break; 178 break;
179 179
180 case TIME: 180 case TIME:
181 bb_printf ("------ Shared Memory Attach/Detach/Change Times --------\n" 181 bb_printf("------ Shared Memory Attach/Detach/Change Times --------\n"
182 "%-10s %-10s %-20s %-20s %-20s\n", 182 "%-10s %-10s %-20s %-20s %-20s\n",
183 "shmid","owner","attached","detached","changed"); 183 "shmid", "owner", "attached", "detached", "changed");
184 break; 184 break;
185 185
186 case PID: 186 case PID:
187 bb_printf ("------ Shared Memory Creator/Last-op --------\n" 187 bb_printf("------ Shared Memory Creator/Last-op --------\n"
188 "%-10s %-10s %-10s %-10s\n", 188 "%-10s %-10s %-10s %-10s\n",
189 "shmid","owner","cpid","lpid"); 189 "shmid", "owner", "cpid", "lpid");
190 break; 190 break;
191 191
192 default: 192 default:
193 bb_printf ("------ Shared Memory Segments --------\n" 193 bb_printf("------ Shared Memory Segments --------\n"
194 "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n", 194 "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
195 "key","shmid","owner","perms","bytes","nattch","status"); 195 "key", "shmid", "owner", "perms", "bytes", "nattch",
196 "status");
196 break; 197 break;
197 } 198 }
198 199
199 for (id = 0; id <= maxid; id++) { 200 for (id = 0; id <= maxid; id++) {
200 shmid = shmctl (id, SHM_STAT, &shmseg); 201 shmid = shmctl(id, SHM_STAT, &shmseg);
201 if (shmid < 0) 202 if (shmid < 0)
202 continue; 203 continue;
203 if (format == CREATOR) { 204 if (format == CREATOR) {
204 print_perms (shmid, ipcp); 205 print_perms(shmid, ipcp);
205 continue; 206 continue;
206 } 207 }
207 pw = getpwuid(ipcp->uid); 208 pw = getpwuid(ipcp->uid);
208 switch (format) { 209 switch (format) {
209 case TIME: 210 case TIME:
210 if (pw) 211 if (pw)
211 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); 212 bb_printf("%-10d %-10.10s", shmid, pw->pw_name);
212 else 213 else
213 bb_printf ("%-10d %-10d", shmid, ipcp->uid); 214 bb_printf("%-10d %-10d", shmid, ipcp->uid);
214 /* ctime uses static buffer: use separate calls */ 215 /* ctime uses static buffer: use separate calls */
215 bb_printf(" %-20.16s", shmseg.shm_atime 216 bb_printf(" %-20.16s", shmseg.shm_atime
216 ? ctime(&shmseg.shm_atime) + 4 : "Not set"); 217 ? ctime(&shmseg.shm_atime) + 4 : "Not set");
217 bb_printf(" %-20.16s", shmseg.shm_dtime 218 bb_printf(" %-20.16s", shmseg.shm_dtime
218 ? ctime(&shmseg.shm_dtime) + 4 : "Not set"); 219 ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
219 bb_printf(" %-20.16s\n", shmseg.shm_ctime 220 bb_printf(" %-20.16s\n", shmseg.shm_ctime
220 ? ctime(&shmseg.shm_ctime) + 4 : "Not set"); 221 ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
221 break; 222 break;
222 case PID: 223 case PID:
223 if (pw) 224 if (pw)
224 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); 225 bb_printf("%-10d %-10.10s", shmid, pw->pw_name);
225 else 226 else
226 bb_printf ("%-10d %-10d", shmid, ipcp->uid); 227 bb_printf("%-10d %-10d", shmid, ipcp->uid);
227 bb_printf (" %-10d %-10d\n", 228 bb_printf(" %-10d %-10d\n", shmseg.shm_cpid, shmseg.shm_lpid);
228 shmseg.shm_cpid, shmseg.shm_lpid);
229 break; 229 break;
230 230
231 default: 231 default:
232 bb_printf("0x%08x ",ipcp->KEY ); 232 bb_printf("0x%08x ", ipcp->KEY);
233 if (pw) 233 if (pw)
234 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); 234 bb_printf("%-10d %-10.10s", shmid, pw->pw_name);
235 else 235 else
236 bb_printf ("%-10d %-10d", shmid, ipcp->uid); 236 bb_printf("%-10d %-10d", shmid, ipcp->uid);
237 bb_printf ("%-10o %-10lu %-10ld %-6s %-6s\n", 237 bb_printf("%-10o %-10lu %-10ld %-6s %-6s\n", ipcp->mode & 0777,
238 ipcp->mode & 0777, 238 /*
239 /* 239 * earlier: int, Austin has size_t
240 * earlier: int, Austin has size_t 240 */
241 */ 241 (unsigned long) shmseg.shm_segsz,
242 (unsigned long) shmseg.shm_segsz, 242 /*
243 /* 243 * glibc-2.1.3 and earlier has unsigned short;
244 * glibc-2.1.3 and earlier has unsigned short; 244 * Austin has shmatt_t
245 * Austin has shmatt_t 245 */
246 */ 246 (long) shmseg.shm_nattch,
247 (long) shmseg.shm_nattch, 247 ipcp->mode & SHM_DEST ? "dest" : " ",
248 ipcp->mode & SHM_DEST ? "dest" : " ", 248 ipcp->mode & SHM_LOCKED ? "locked" : " ");
249 ipcp->mode & SHM_LOCKED ? "locked" : " ");
250 break; 249 break;
251 } 250 }
252 } 251 }
253 return;
254} 252}
255 253
256 254
257static void do_sem (char format) 255static void do_sem(void)
258{ 256{
259 int maxid, semid, id; 257 int maxid, semid, id;
260 struct semid_ds semary; 258 struct semid_ds semary;
@@ -263,107 +261,104 @@ static void do_sem (char format)
263 struct passwd *pw; 261 struct passwd *pw;
264 union semun arg; 262 union semun arg;
265 263
266 arg.array = (ushort *) (void *) &seminfo; 264 arg.array = (ushort *) (void *) &seminfo;
267 maxid = semctl (0, 0, SEM_INFO, arg); 265 maxid = semctl(0, 0, SEM_INFO, arg);
268 if (maxid < 0) { 266 if (maxid < 0) {
269 bb_printf ("kernel not configured for semaphores\n"); 267 bb_printf("kernel not configured for semaphores\n");
270 return; 268 return;
271 } 269 }
272 270
273 switch (format) { 271 switch (format) {
274 case LIMITS: 272 case LIMITS:
275 bb_printf ("------ Semaphore Limits --------\n"); 273 bb_printf("------ Semaphore Limits --------\n");
276 arg.array = (ushort *) (void *) &seminfo; /* damn union */ 274 arg.array = (ushort *) (void *) &seminfo; /* damn union */
277 if ((semctl (0, 0, IPC_INFO, arg)) < 0 ) 275 if ((semctl(0, 0, IPC_INFO, arg)) < 0)
278 return; 276 return;
279 bb_printf ("max number of arrays = %d\n" 277 bb_printf("max number of arrays = %d\n"
280 "max semaphores per array = %d\n" 278 "max semaphores per array = %d\n"
281 "max semaphores system wide = %d\n" 279 "max semaphores system wide = %d\n"
282 "max ops per semop call = %d\n" 280 "max ops per semop call = %d\n"
283 "semaphore max value = %d\n", 281 "semaphore max value = %d\n",
284 seminfo.semmni, 282 seminfo.semmni,
285 seminfo.semmsl, 283 seminfo.semmsl,
286 seminfo.semmns, 284 seminfo.semmns, seminfo.semopm, seminfo.semvmx);
287 seminfo.semopm,
288 seminfo.semvmx);
289 return; 285 return;
290 286
291 case STATUS: 287 case STATUS:
292 bb_printf ("------ Semaphore Status --------\n" 288 bb_printf("------ Semaphore Status --------\n"
293 "used arrays = %d\n" 289 "used arrays = %d\n"
294 "allocated semaphores = %d\n", 290 "allocated semaphores = %d\n",
295 seminfo.semusz, 291 seminfo.semusz, seminfo.semaem);
296 seminfo.semaem);
297 return; 292 return;
298 293
299 case CREATOR: 294 case CREATOR:
300 bb_printf ("------ Semaphore Arrays Creators/Owners --------\n" 295 bb_printf("------ Semaphore Arrays Creators/Owners --------\n"
301 "%-10s %-10s %-10s %-10s %-10s %-10s\n", 296 "%-10s %-10s %-10s %-10s %-10s %-10s\n",
302 "semid","perms","cuid","cgid","uid","gid"); 297 "semid", "perms", "cuid", "cgid", "uid", "gid");
303 break; 298 break;
304 299
305 case TIME: 300 case TIME:
306 bb_printf ("------ Shared Memory Operation/Change Times --------\n" 301 bb_printf("------ Shared Memory Operation/Change Times --------\n"
307 "%-8s %-10s %-26.24s %-26.24s\n", 302 "%-8s %-10s %-26.24s %-26.24s\n",
308 "shmid","owner","last-op","last-changed"); 303 "shmid", "owner", "last-op", "last-changed");
309 break; 304 break;
310 305
311 case PID: 306 case PID:
312 break; 307 break;
313 308
314 default: 309 default:
315 bb_printf ("------ Semaphore Arrays --------\n" 310 bb_printf("------ Semaphore Arrays --------\n"
316 "%-10s %-10s %-10s %-10s %-10s\n", 311 "%-10s %-10s %-10s %-10s %-10s\n",
317 "key","semid","owner","perms","nsems"); 312 "key", "semid", "owner", "perms", "nsems");
318 break; 313 break;
319 } 314 }
320 315
321 for (id = 0; id <= maxid; id++) { 316 for (id = 0; id <= maxid; id++) {
322 arg.buf = (struct semid_ds *) &semary; 317 arg.buf = (struct semid_ds *) &semary;
323 semid = semctl (id, 0, SEM_STAT, arg); 318 semid = semctl(id, 0, SEM_STAT, arg);
324 if (semid < 0) 319 if (semid < 0)
325 continue; 320 continue;
326 if (format == CREATOR) { 321 if (format == CREATOR) {
327 print_perms (semid, ipcp); 322 print_perms(semid, ipcp);
328 continue; 323 continue;
329 } 324 }
330 pw = getpwuid(ipcp->uid); 325 pw = getpwuid(ipcp->uid);
331 switch (format) { 326 switch (format) {
332 case TIME: 327 case TIME:
333 if (pw) 328 if (pw)
334 bb_printf ("%-8d %-10.10s", semid, pw->pw_name); 329 bb_printf("%-8d %-10.10s", semid, pw->pw_name);
335 else 330 else
336 bb_printf ("%-8d %-10d", semid, ipcp->uid); 331 bb_printf("%-8d %-10d", semid, ipcp->uid);
337 bb_printf (" %-26.24s", semary.sem_otime 332 /* ctime uses static buffer: use separate calls */
338 ? ctime(&semary.sem_otime) : "Not set"); 333 bb_printf(" %-26.24s", semary.sem_otime
339 bb_printf (" %-26.24s\n", semary.sem_ctime 334 ? ctime(&semary.sem_otime) : "Not set");
340 ? ctime(&semary.sem_ctime) : "Not set"); 335 bb_printf(" %-26.24s\n", semary.sem_ctime
336 ? ctime(&semary.sem_ctime) : "Not set");
341 break; 337 break;
342 case PID: 338 case PID:
343 break; 339 break;
344 340
345 default: 341 default:
346 bb_printf("0x%08x ", ipcp->KEY); 342 bb_printf("0x%08x ", ipcp->KEY);
347 if (pw) 343 if (pw)
348 bb_printf ("%-10d %-10.9s", semid, pw->pw_name); 344 bb_printf("%-10d %-10.9s", semid, pw->pw_name);
349 else 345 else
350 bb_printf ("%-10d %-9d", semid, ipcp->uid); 346 bb_printf("%-10d %-9d", semid, ipcp->uid);
351 bb_printf ("%-10o %-10ld\n", 347 bb_printf("%-10o %-10ld\n", ipcp->mode & 0777,
352 ipcp->mode & 0777, 348 /*
353 /* 349 * glibc-2.1.3 and earlier has unsigned short;
354 * glibc-2.1.3 and earlier has unsigned short; 350 * glibc-2.1.91 has variation between
355 * glibc-2.1.91 has variation between 351 * unsigned short and unsigned long
356 * unsigned short and unsigned long 352 * Austin prescribes unsigned short.
357 * Austin prescribes unsigned short. 353 */
358 */ 354 (long) semary.sem_nsems);
359 (long) semary.sem_nsems);
360 break; 355 break;
361 } 356 }
362 } 357 }
363} 358}
364 359
365 360
366static void do_msg (char format) 361static void do_msg(void)
367{ 362{
368 int maxid, msqid, id; 363 int maxid, msqid, id;
369 struct msqid_ds msgque; 364 struct msqid_ds msgque;
@@ -371,178 +366,165 @@ static void do_msg (char format)
371 struct ipc_perm *ipcp = &msgque.msg_perm; 366 struct ipc_perm *ipcp = &msgque.msg_perm;
372 struct passwd *pw; 367 struct passwd *pw;
373 368
374 maxid = msgctl (0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo); 369 maxid = msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
375 if (maxid < 0) { 370 if (maxid < 0) {
376 bb_printf ("kernel not configured for message queues\n"); 371 bb_printf("kernel not configured for message queues\n");
377 return; 372 return;
378 } 373 }
379 374
380 switch (format) { 375 switch (format) {
381 case LIMITS: 376 case LIMITS:
382 if ((msgctl (0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0 ) 377 if ((msgctl(0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0)
383 return; 378 return;
384 bb_printf ("------ Messages: Limits --------\n" 379 bb_printf("------ Messages: Limits --------\n"
385 "max queues system wide = %d\n" 380 "max queues system wide = %d\n"
386 "max size of message (bytes) = %d\n" 381 "max size of message (bytes) = %d\n"
387 "default max size of queue (bytes) = %d\n", 382 "default max size of queue (bytes) = %d\n",
388 msginfo.msgmni, 383 msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb);
389 msginfo.msgmax,
390 msginfo.msgmnb);
391 return; 384 return;
392 385
393 case STATUS: 386 case STATUS:
394 bb_printf ("------ Messages: Status --------\n" 387 bb_printf("------ Messages: Status --------\n"
395 "allocated queues = %d\n" 388 "allocated queues = %d\n"
396 "used headers = %d\n" 389 "used headers = %d\n"
397 "used space = %d bytes\n", 390 "used space = %d bytes\n",
398 msginfo.msgpool, 391 msginfo.msgpool, msginfo.msgmap, msginfo.msgtql);
399 msginfo.msgmap,
400 msginfo.msgtql);
401 return; 392 return;
402 393
403 case CREATOR: 394 case CREATOR:
404 bb_printf ("------ Message Queues: Creators/Owners --------\n" 395 bb_printf("------ Message Queues: Creators/Owners --------\n"
405 "%-10s %-10s %-10s %-10s %-10s %-10s\n", 396 "%-10s %-10s %-10s %-10s %-10s %-10s\n",
406 "msqid","perms","cuid","cgid","uid","gid"); 397 "msqid", "perms", "cuid", "cgid", "uid", "gid");
407 break; 398 break;
408 399
409 case TIME: 400 case TIME:
410 bb_printf ("------ Message Queues Send/Recv/Change Times --------\n" 401 bb_printf("------ Message Queues Send/Recv/Change Times --------\n"
411 "%-8s %-10s %-20s %-20s %-20s\n", 402 "%-8s %-10s %-20s %-20s %-20s\n",
412 "msqid","owner","send","recv","change"); 403 "msqid", "owner", "send", "recv", "change");
413 break; 404 break;
414 405
415 case PID: 406 case PID:
416 bb_printf ("------ Message Queues PIDs --------\n" 407 bb_printf("------ Message Queues PIDs --------\n"
417 "%-10s %-10s %-10s %-10s\n", 408 "%-10s %-10s %-10s %-10s\n",
418 "msqid","owner","lspid","lrpid"); 409 "msqid", "owner", "lspid", "lrpid");
419 break; 410 break;
420 411
421 default: 412 default:
422 bb_printf ("------ Message Queues --------\n" 413 bb_printf("------ Message Queues --------\n"
423 "%-10s %-10s %-10s %-10s %-12s %-12s\n", 414 "%-10s %-10s %-10s %-10s %-12s %-12s\n",
424 "key","msqid","owner","perms","used-bytes","messages"); 415 "key", "msqid", "owner", "perms", "used-bytes", "messages");
425 break; 416 break;
426 } 417 }
427 418
428 for (id = 0; id <= maxid; id++) { 419 for (id = 0; id <= maxid; id++) {
429 msqid = msgctl (id, MSG_STAT, &msgque); 420 msqid = msgctl(id, MSG_STAT, &msgque);
430 if (msqid < 0) 421 if (msqid < 0)
431 continue; 422 continue;
432 if (format == CREATOR) { 423 if (format == CREATOR) {
433 print_perms (msqid, ipcp); 424 print_perms(msqid, ipcp);
434 continue; 425 continue;
435 } 426 }
436 pw = getpwuid(ipcp->uid); 427 pw = getpwuid(ipcp->uid);
437 switch (format) { 428 switch (format) {
438 case TIME: 429 case TIME:
439 if (pw) 430 if (pw)
440 bb_printf ("%-8d %-10.10s", msqid, pw->pw_name); 431 bb_printf("%-8d %-10.10s", msqid, pw->pw_name);
441 else 432 else
442 bb_printf ("%-8d %-10d", msqid, ipcp->uid); 433 bb_printf("%-8d %-10d", msqid, ipcp->uid);
443 bb_printf (" %-20.16s", msgque.msg_stime 434 bb_printf(" %-20.16s", msgque.msg_stime
444 ? ctime(&msgque.msg_stime) + 4 : "Not set"); 435 ? ctime(&msgque.msg_stime) + 4 : "Not set");
445 bb_printf (" %-20.16s", msgque.msg_rtime 436 bb_printf(" %-20.16s", msgque.msg_rtime
446 ? ctime(&msgque.msg_rtime) + 4 : "Not set"); 437 ? ctime(&msgque.msg_rtime) + 4 : "Not set");
447 bb_printf (" %-20.16s\n", msgque.msg_ctime 438 bb_printf(" %-20.16s\n", msgque.msg_ctime
448 ? ctime(&msgque.msg_ctime) + 4 : "Not set"); 439 ? ctime(&msgque.msg_ctime) + 4 : "Not set");
449 break; 440 break;
450 case PID: 441 case PID:
451 if (pw) 442 if (pw)
452 bb_printf ("%-8d %-10.10s", msqid, pw->pw_name); 443 bb_printf("%-8d %-10.10s", msqid, pw->pw_name);
453 else 444 else
454 bb_printf ("%-8d %-10d", msqid, ipcp->uid); 445 bb_printf("%-8d %-10d", msqid, ipcp->uid);
455 bb_printf (" %5d %5d\n", 446 bb_printf(" %5d %5d\n", msgque.msg_lspid, msgque.msg_lrpid);
456 msgque.msg_lspid, msgque.msg_lrpid);
457 break; 447 break;
458 448
459 default: 449 default:
460 bb_printf( "0x%08x ",ipcp->KEY ); 450 bb_printf("0x%08x ", ipcp->KEY);
461 if (pw) 451 if (pw)
462 bb_printf ("%-10d %-10.10s", msqid, pw->pw_name); 452 bb_printf("%-10d %-10.10s", msqid, pw->pw_name);
463 else 453 else
464 bb_printf ("%-10d %-10d", msqid, ipcp->uid); 454 bb_printf("%-10d %-10d", msqid, ipcp->uid);
465 bb_printf (" %-10o %-12ld %-12ld\n", 455 bb_printf(" %-10o %-12ld %-12ld\n", ipcp->mode & 0777,
466 ipcp->mode & 0777, 456 /*
467 /* 457 * glibc-2.1.3 and earlier has unsigned short;
468 * glibc-2.1.3 and earlier has unsigned short; 458 * glibc-2.1.91 has variation between
469 * glibc-2.1.91 has variation between 459 * unsigned short, unsigned long
470 * unsigned short, unsigned long 460 * Austin has msgqnum_t
471 * Austin has msgqnum_t 461 */
472 */ 462 (long) msgque.msg_cbytes, (long) msgque.msg_qnum);
473 (long) msgque.msg_cbytes,
474 (long) msgque.msg_qnum);
475 break; 463 break;
476 } 464 }
477 } 465 }
478 return;
479} 466}
480 467
481 468
482static void print_shm (int shmid) 469static void print_shm(int shmid)
483{ 470{
484 struct shmid_ds shmds; 471 struct shmid_ds shmds;
485 struct ipc_perm *ipcp = &shmds.shm_perm; 472 struct ipc_perm *ipcp = &shmds.shm_perm;
486 473
487 if (shmctl (shmid, IPC_STAT, &shmds) == -1) { 474 if (shmctl(shmid, IPC_STAT, &shmds) == -1) {
488 perror ("shmctl "); 475 bb_perror_msg("shmctl");
489 return; 476 return;
490 } 477 }
491 478
492 bb_printf ("\nShared memory Segment shmid=%d\n" 479 bb_printf("\nShared memory Segment shmid=%d\n"
493 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n" 480 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
494 "mode=%#o\taccess_perms=%#o\n" 481 "mode=%#o\taccess_perms=%#o\n"
495 "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n" 482 "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n",
496 "att_time=%-26.24s\n" 483 shmid,
497 "det_time=%-26.24s\n" 484 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
498 "change_time=%-26.24s\n" 485 ipcp->mode, ipcp->mode & 0777,
499 "\n", 486 (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
500 shmid, 487 (long) shmds.shm_nattch);
501 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, 488 bb_printf("att_time=%-26.24s\n",
502 ipcp->mode, ipcp->mode & 0777, 489 shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set");
503 (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid, 490 bb_printf("det_time=%-26.24s\n",
504 (long) shmds.shm_nattch, 491 shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set");
505 shmds.shm_atime ? ctime (&shmds.shm_atime) : "Not set", 492 bb_printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime));
506 shmds.shm_dtime ? ctime (&shmds.shm_dtime) : "Not set",
507 ctime (&shmds.shm_ctime));
508 return;
509} 493}
510 494
511 495
512static void print_msg (int msqid) 496static void print_msg(int msqid)
513{ 497{
514 struct msqid_ds buf; 498 struct msqid_ds buf;
515 struct ipc_perm *ipcp = &buf.msg_perm; 499 struct ipc_perm *ipcp = &buf.msg_perm;
516 500
517 if (msgctl (msqid, IPC_STAT, &buf) == -1) { 501 if (msgctl(msqid, IPC_STAT, &buf) == -1) {
518 perror ("msgctl "); 502 bb_perror_msg("msgctl");
519 return; 503 return;
520 } 504 }
521 505
522 bb_printf ("\nMessage Queue msqid=%d\n" 506 bb_printf("\nMessage Queue msqid=%d\n"
523 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n" 507 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
524 "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n" 508 "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n",
525 "send_time=%-26.24s\n" 509 msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
526 "rcv_time=%-26.24s\n" 510 /*
527 "change_time=%-26.24s\n" 511 * glibc-2.1.3 and earlier has unsigned short;
528 "\n", 512 * glibc-2.1.91 has variation between
529 msqid, 513 * unsigned short, unsigned long
530 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode, 514 * Austin has msgqnum_t (for msg_qbytes)
531 /* 515 */
532 * glibc-2.1.3 and earlier has unsigned short; 516 (long) buf.msg_cbytes, (long) buf.msg_qbytes,
533 * glibc-2.1.91 has variation between 517 (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);
534 * unsigned short, unsigned long 518
535 * Austin has msgqnum_t (for msg_qbytes) 519 bb_printf("send_time=%-26.24s\n",
536 */ 520 buf.msg_stime ? ctime(&buf.msg_stime) : "Not set");
537 (long) buf.msg_cbytes, (long) buf.msg_qbytes, 521 bb_printf("rcv_time=%-26.24s\n",
538 (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid, 522 buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set");
539 buf.msg_stime ? ctime (&buf.msg_stime) : "Not set", 523 bb_printf("change_time=%-26.24s\n\n",
540 buf.msg_rtime ? ctime (&buf.msg_rtime) : "Not set", 524 buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set");
541 buf.msg_ctime ? ctime (&buf.msg_ctime) : "Not set");
542 return;
543} 525}
544 526
545static void print_sem (int semid) 527static void print_sem(int semid)
546{ 528{
547 struct semid_ds semds; 529 struct semid_ds semds;
548 struct ipc_perm *ipcp = &semds.sem_perm; 530 struct ipc_perm *ipcp = &semds.sem_perm;
@@ -550,66 +532,69 @@ static void print_sem (int semid)
550 unsigned int i; 532 unsigned int i;
551 533
552 arg.buf = &semds; 534 arg.buf = &semds;
553 if (semctl (semid, 0, IPC_STAT, arg) < 0) { 535 if (semctl(semid, 0, IPC_STAT, arg)) {
554 perror ("semctl "); 536 bb_perror_msg("semctl");
555 return; 537 return;
556 } 538 }
557 539
558 bb_printf ("\nSemaphore Array semid=%d\n" 540 bb_printf("\nSemaphore Array semid=%d\n"
559 "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n" 541 "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
560 "mode=%#o, access_perms=%#o\n" 542 "mode=%#o, access_perms=%#o\n"
561 "nsems = %ld\n" 543 "nsems = %ld\n"
562 "otime = %-26.24s\n" 544 "otime = %-26.24s\n",
563 "ctime = %-26.24s\n" 545 semid,
564 "%-10s %-10s %-10s %-10s %-10s\n", 546 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
565 semid, 547 ipcp->mode, ipcp->mode & 0777,
566 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, 548 (long) semds.sem_nsems,
567 ipcp->mode, ipcp->mode & 0777, 549 semds.sem_otime ? ctime(&semds.sem_otime) : "Not set");
568 (long) semds.sem_nsems, 550 bb_printf("ctime = %-26.24s\n"
569 semds.sem_otime ? ctime (&semds.sem_otime) : "Not set", 551 "%-10s %-10s %-10s %-10s %-10s\n",
570 ctime (&semds.sem_ctime), 552 ctime(&semds.sem_ctime),
571 "semnum","value","ncount","zcount","pid"); 553 "semnum", "value", "ncount", "zcount", "pid");
572 554
573 arg.val = 0; 555 arg.val = 0;
574 for (i=0; i < semds.sem_nsems; i++) { 556 for (i = 0; i < semds.sem_nsems; i++) {
575 int val, ncnt, zcnt, pid; 557 int val, ncnt, zcnt, pid;
576 val = semctl (semid, i, GETVAL, arg); 558
577 ncnt = semctl (semid, i, GETNCNT, arg); 559 val = semctl(semid, i, GETVAL, arg);
578 zcnt = semctl (semid, i, GETZCNT, arg); 560 ncnt = semctl(semid, i, GETNCNT, arg);
579 pid = semctl (semid, i, GETPID, arg); 561 zcnt = semctl(semid, i, GETZCNT, arg);
562 pid = semctl(semid, i, GETPID, arg);
580 if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) { 563 if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) {
581 perror ("semctl "); 564 bb_perror_msg_and_die("semctl");
582 bb_fflush_stdout_and_exit (1);
583 } 565 }
584 bb_printf ("%-10d %-10d %-10d %-10d %-10d\n", 566 bb_printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
585 i, val, ncnt, zcnt, pid);
586 } 567 }
587 bb_printf ("\n"); 568 bb_printf("\n");
588 return;
589} 569}
590 570
591int ipcs_main (int argc, char **argv) { 571int ipcs_main(int argc, char **argv)
592 int opt, msg = 0, sem = 0, shm = 0, id=0, print=0; 572{
593 char format = 0; 573 int opt, id = 0;
594 char options[] = "atclupsmqi:ih?"; 574 unsigned flags = 0;
595 575#define flag_print (1<<0)
596 while ((opt = getopt (argc, argv, options)) != -1) { 576#define flag_msg (1<<1)
577#define flag_sem (1<<2)
578#define flag_shm (1<<3)
579 const char *const options = "atclupsmqi:ih?";
580
581 while ((opt = getopt(argc, argv, options)) != -1) {
597 switch (opt) { 582 switch (opt) {
598 case 'i': 583 case 'i':
599 id = atoi (optarg); 584 id = atoi(optarg);
600 print = 1; 585 flags |= flag_print;
601 break; 586 break;
602 case 'a': 587 case 'a':
603 msg = shm = sem = 1; 588 flags |= flag_msg | flag_sem | flag_shm;
604 break; 589 break;
605 case 'q': 590 case 'q':
606 msg = 1; 591 flags |= flag_msg;
607 break; 592 break;
608 case 's': 593 case 's':
609 sem = 1; 594 flags |= flag_sem;
610 break; 595 break;
611 case 'm': 596 case 'm':
612 shm = 1; 597 flags |= flag_shm;
613 break; 598 break;
614 case 't': 599 case 't':
615 format = TIME; 600 format = TIME;
@@ -629,43 +614,40 @@ int ipcs_main (int argc, char **argv) {
629 case 'h': 614 case 'h':
630 case '?': 615 case '?':
631 bb_show_usage(); 616 bb_show_usage();
632 bb_fflush_stdout_and_exit (0);
633 } 617 }
634 } 618 }
635 619
636 if (print) { 620 if (flags & flag_print) {
637 if (shm) { 621 if (flags & flag_shm) {
638 print_shm (id); 622 print_shm(id);
639 bb_fflush_stdout_and_exit (0); 623 bb_fflush_stdout_and_exit(0);
640 } 624 }
641 if (sem) { 625 if (flags & flag_sem) {
642 print_sem (id); 626 print_sem(id);
643 bb_fflush_stdout_and_exit (0); 627 bb_fflush_stdout_and_exit(0);
644 } 628 }
645 if (msg) { 629 if (flags & flag_msg) {
646 print_msg (id); 630 print_msg(id);
647 bb_fflush_stdout_and_exit (0); 631 bb_fflush_stdout_and_exit(0);
648 } 632 }
649 bb_show_usage(); 633 bb_show_usage();
650 bb_fflush_stdout_and_exit (0);
651 } 634 }
652 635
653 if ( !shm && !msg && !sem) 636 if (!(flags & (flag_shm | flag_msg | flag_sem)))
654 msg = sem = shm = 1; 637 flags |= flag_msg | flag_shm | flag_sem;
655 bb_printf ("\n"); 638 bb_printf("\n");
656 639
657 if (shm) { 640 if (flags & flag_shm) {
658 do_shm (format); 641 do_shm();
659 bb_printf ("\n"); 642 bb_printf("\n");
660 } 643 }
661 if (sem) { 644 if (flags & flag_sem) {
662 do_sem (format); 645 do_sem();
663 bb_printf ("\n"); 646 bb_printf("\n");
664 } 647 }
665 if (msg) { 648 if (flags & flag_msg) {
666 do_msg (format); 649 do_msg();
667 bb_printf ("\n"); 650 bb_printf("\n");
668 } 651 }
669 return 0; 652 return EXIT_SUCCESS;
670} 653}
671