- 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
This commit is contained in:
Bernhard Reutner-Fischer 2006-08-28 23:31:54 +00:00
parent 6ce8dae1d5
commit 73561cc75a
20 changed files with 1164 additions and 1285 deletions

View File

@ -278,6 +278,7 @@ endif # CONFIG_FEATURE_FULL_LIBBUSYBOX
APPLET_SRC:=$(APPLET_SRC-y) APPLET_SRC:=$(APPLET_SRC-y)
APPLETS_DEFINE:=$(APPLETS_DEFINE-y) APPLETS_DEFINE:=$(APPLETS_DEFINE-y)
else # CONFIG_BUILD_AT_ONCE else # CONFIG_BUILD_AT_ONCE
APPLET_SRC:=
# no --combine, build archives out of the individual .o # no --combine, build archives out of the individual .o
# This was the old way the binary was built. # This was the old way the binary was built.
libbusybox-obj:=archival/libunarchive/libunarchive.a \ libbusybox-obj:=archival/libunarchive/libunarchive.a \

View File

@ -14,49 +14,55 @@
int catv_main(int argc, char **argv) int catv_main(int argc, char **argv)
{ {
int retval = EXIT_SUCCESS, fd, flags; int retval = EXIT_SUCCESS, fd;
unsigned long flags;
flags = bb_getopt_ulflags(argc, argv, "etv"); flags = bb_getopt_ulflags(argc, argv, "etv");
flags ^= 4; #define CATV_OPT_e (1<<0)
#define CATV_OPT_t (1<<1)
// Loop through files. #define CATV_OPT_v (1<<2)
flags ^= CATV_OPT_v;
argv += optind; argv += optind;
do { do {
// Read from stdin if there's nothing else to do. /* Read from stdin if there's nothing else to do. */
fd = 0; fd = 0;
if (*argv && 0>(fd = xopen(*argv, O_RDONLY))) retval = EXIT_FAILURE; if (*argv && 0 > (fd = xopen(*argv, O_RDONLY)))
else for(;;) { retval = EXIT_FAILURE;
else for (;;) {
int i, res; int i, res;
res = read(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1)); res = read(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1));
if (res < 0) retval = EXIT_FAILURE; if (res < 0)
if (res <1) break; retval = EXIT_FAILURE;
for (i=0; i<res; i++) { if (res < 1)
char c=bb_common_bufsiz1[i]; break;
for (i = 0; i < res; i++) {
char c = bb_common_bufsiz1[i];
if (c > 126 && (flags & 4)) { if (c > 126 && (flags & CATV_OPT_v)) {
if (c == 127) { if (c == 127) {
printf("^?"); bb_printf("^?");
continue; continue;
} else { } else {
printf("M-"); bb_printf("M-");
c -= 128; c -= 128;
} }
} }
if (c < 32) { if (c < 32) {
if (c == 10) { if (c == 10) {
if (flags & 1) putchar('$'); if (flags & CATV_OPT_e)
} else if (flags & (c==9 ? 2 : 4)) { putchar('$');
printf("^%c", c+'@'); } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) {
bb_printf("^%c", c+'@');
continue; continue;
} }
} }
putchar(c); putchar(c);
} }
} }
if (ENABLE_FEATURE_CLEAN_UP && fd) close(fd); if (ENABLE_FEATURE_CLEAN_UP && fd)
close(fd);
} while (*++argv); } while (*++argv);
return retval; return retval;

View File

@ -3,12 +3,13 @@
* cksum - calculate the CRC32 checksum of a file * cksum - calculate the CRC32 checksum of a file
* *
* Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms
* *
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */
#include "busybox.h" #include "busybox.h"
int cksum_main(int argc, char **argv) { int cksum_main(int argc, char **argv)
{
uint32_t *crc32_table = crc32_filltable(1); uint32_t *crc32_table = crc32_filltable(1);
@ -17,36 +18,36 @@ int cksum_main(int argc, char **argv) {
long length, filesize; long length, filesize;
int bytes_read; int bytes_read;
char *cp; char *cp;
RESERVE_CONFIG_BUFFER(buf, BUFSIZ);
int inp_stdin = (argc == optind) ? 1 : 0; int inp_stdin = (argc == optind) ? 1 : 0;
do { do {
fp = bb_wfopen_input((inp_stdin) ? bb_msg_standard_input : *++argv); fp = bb_wfopen_input((inp_stdin) ? bb_msg_standard_input : *++argv);
crc = 0; crc = 0;
length = 0; length = 0;
while ((bytes_read = fread(buf, 1, BUFSIZ, fp)) > 0) { while ((bytes_read = fread(bb_common_bufsiz1, 1, BUFSIZ, fp)) > 0) {
cp = buf; cp = bb_common_bufsiz1;
length += bytes_read; length += bytes_read;
while (bytes_read--) while (bytes_read--)
crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL]; crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL];
} }
filesize = length; filesize = length;
for (; length; length >>= 8) for (; length; length >>= 8)
crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL]; crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL];
crc ^= 0xffffffffL; crc ^= 0xffffffffL;
if (inp_stdin) { if (inp_stdin) {
printf("%"PRIu32" %li\n", crc, filesize); bb_printf("%" PRIu32 " %li\n", crc, filesize);
break; break;
} }
printf("%"PRIu32" %li %s\n", crc, filesize, *argv); bb_printf("%" PRIu32 " %li %s\n", crc, filesize, *argv);
fclose(fp); fclose(fp);
} while (*(argv+1)); } while (*(argv + 1));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -23,7 +23,7 @@
#include "busybox.h" #include "busybox.h"
static FILE *cmp_xfopen_input(const char *filename) static FILE *cmp_xfopen_input(const char * const filename)
{ {
FILE *fp; FILE *fp;
@ -40,32 +40,28 @@ static const char fmt_differ[] = "%s %s differ: char %d, line %d\n";
static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n"; static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n";
static const char opt_chars[] = "sl"; static const char opt_chars[] = "sl";
#define CMP_OPT_s (1<<0)
enum { #define CMP_OPT_l (1<<1)
OPT_s = 1,
OPT_l = 2
};
int cmp_main(int argc, char **argv) int cmp_main(int argc, char **argv)
{ {
FILE *fp1, *fp2, *outfile = stdout; FILE *fp1, *fp2, *outfile = stdout;
const char *filename1, *filename2; const char *filename1, *filename2 = "-";
const char *fmt; const char *fmt;
int c1, c2, char_pos, line_pos; int c1, c2, char_pos = 0, line_pos = 1;
int opt_flags; unsigned opt;
int exit_val = 0; int retval = 0;
bb_default_error_retval = 2; /* 1 is returned if files are different. */ bb_default_error_retval = 2; /* 1 is returned if files are different. */
opt_flags = bb_getopt_ulflags(argc, argv, opt_chars); opt = bb_getopt_ulflags(argc, argv, opt_chars);
if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) { if ((opt & (CMP_OPT_s|CMP_OPT_l))
|| (((unsigned int)(--argc - optind)) > 1))
bb_show_usage(); bb_show_usage();
}
fp1 = cmp_xfopen_input(filename1 = *(argv += optind)); fp1 = cmp_xfopen_input(filename1 = *(argv += optind));
filename2 = "-";
if (*++argv) { if (*++argv) {
filename2 = *argv; filename2 = *argv;
} }
@ -79,19 +75,17 @@ int cmp_main(int argc, char **argv)
return 0; return 0;
} }
fmt = fmt_differ; if (opt & CMP_OPT_l)
if (opt_flags == OPT_l) {
fmt = fmt_l_opt; fmt = fmt_l_opt;
} else
fmt = fmt_differ;
char_pos = 0;
line_pos = 1;
do { do {
c1 = getc(fp1); c1 = getc(fp1);
c2 = getc(fp2); c2 = getc(fp2);
++char_pos; ++char_pos;
if (c1 != c2) { /* Remember -- a read error may have occurred. */ if (c1 != c2) { /* Remember: a read error may have occurred. */
exit_val = 1; /* But assume the files are different for now. */ retval = 1; /* But assume the files are different for now. */
if (c2 == EOF) { if (c2 == EOF) {
/* We know that fp1 isn't at EOF or in an error state. But to /* We know that fp1 isn't at EOF or in an error state. But to
* save space below, things are setup to expect an EOF in fp1 * save space below, things are setup to expect an EOF in fp1
@ -109,13 +103,14 @@ int cmp_main(int argc, char **argv)
* make sure we fflush before writing to stderr. */ * make sure we fflush before writing to stderr. */
xfflush_stdout(); xfflush_stdout();
} }
if (opt_flags != OPT_s) { if (!opt & CMP_OPT_s) {
if (opt_flags == OPT_l) { if (opt & CMP_OPT_l) {
line_pos = c1; /* line_pos is unused in the -l case. */ line_pos = c1; /* line_pos is unused in the -l case. */
} }
bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2); bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
if (opt_flags) { /* This must be -l since not -s. */ if (opt) { /* This must be -l since not -s. */
/* If we encountered and EOF, the while check will catch it. */ /* If we encountered an EOF,
* the while check will catch it. */
continue; continue;
} }
} }
@ -129,5 +124,5 @@ int cmp_main(int argc, char **argv)
xferror(fp1, filename1); xferror(fp1, filename1);
xferror(fp2, filename2); xferror(fp2, filename2);
bb_fflush_stdout_and_exit(exit_val); bb_fflush_stdout_and_exit(retval);
} }

View File

@ -4,28 +4,24 @@
* *
* Copyright (C) 1999,2000,2001 by Lineo, inc. * Copyright (C) 1999,2000,2001 by Lineo, inc.
* Written by Mark Whitley <markw@codepoet.org> * Written by Mark Whitley <markw@codepoet.org>
* debloated by Bernhard Fischer
* *
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include "busybox.h" #include "busybox.h"
/* option vars */ /* option vars */
static const char optstring[] = "b:c:f:d:sn"; static const char *const optstring = "b:c:f:d:sn";
#define OPT_BYTE_FLGS 1
#define OPT_CHAR_FLGS 2 #define CUT_OPT_BYTE_FLGS (1<<0)
#define OPT_FIELDS_FLGS 4 #define CUT_OPT_CHAR_FLGS (1<<1)
#define OPT_DELIM_FLGS 8 #define CUT_OPT_FIELDS_FLGS (1<<2)
#define OPT_SUPRESS_FLGS 16 #define CUT_OPT_DELIM_FLGS (1<<3)
static char part; /* (b)yte, (c)har, (f)ields */ #define CUT_OPT_SUPPRESS_FLGS (1<<4)
static unsigned int supress_non_delimited_lines; static unsigned long opt;
static char delim = '\t'; /* delimiter, default is tab */
static char delim = '\t'; /* delimiter, default is tab */
struct cut_list { struct cut_list {
int startpos; int startpos;
@ -38,295 +34,268 @@ enum {
NON_RANGE = -1 NON_RANGE = -1
}; };
static struct cut_list *cut_lists = NULL; /* growable array holding a series of lists */ /* growable array holding a series of lists */
static unsigned int nlists = 0; /* number of elements in above list */ static struct cut_list *cut_lists;
static unsigned int nlists; /* number of elements in above list */
static int cmpfunc(const void *a, const void *b) static int cmpfunc(const void *a, const void *b)
{ {
struct cut_list *la = (struct cut_list *)a; return (((struct cut_list *) a)->startpos -
struct cut_list *lb = (struct cut_list *)b; ((struct cut_list *) b)->startpos);
if (la->startpos > lb->startpos)
return 1;
if (la->startpos < lb->startpos)
return -1;
return 0;
}
/*
* parse_lists() - parses a list and puts values into startpos and endpos.
* valid list formats: N, N-, N-M, -M
* more than one list can be separated by commas
*/
static void parse_lists(char *lists)
{
char *ltok = NULL;
char *ntok = NULL;
char *junk;
int s = 0, e = 0;
/* take apart the lists, one by one (they are separated with commas */
while ((ltok = strsep(&lists, ",")) != NULL) {
/* it's actually legal to pass an empty list */
if (strlen(ltok) == 0)
continue;
/* get the start pos */
ntok = strsep(&ltok, "-");
if (ntok == NULL) {
fprintf(stderr, "Help ntok is null for starting position! What do I do?\n");
} else if (strlen(ntok) == 0) {
s = BOL;
} else {
s = strtoul(ntok, &junk, 10);
if(*junk != '\0' || s < 0)
bb_error_msg_and_die("invalid byte or field list");
/* account for the fact that arrays are zero based, while the user
* expects the first char on the line to be char # 1 */
if (s != 0)
s--;
}
/* get the end pos */
ntok = strsep(&ltok, "-");
if (ntok == NULL) {
e = NON_RANGE;
} else if (strlen(ntok) == 0) {
e = EOL;
} else {
e = strtoul(ntok, &junk, 10);
if(*junk != '\0' || e < 0)
bb_error_msg_and_die("invalid byte or field list");
/* if the user specified and end position of 0, that means "til the
* end of the line */
if (e == 0)
e = INT_MAX;
e--; /* again, arrays are zero based, lines are 1 based */
if (e == s)
e = NON_RANGE;
}
/* if there's something left to tokenize, the user past an invalid list */
if (ltok)
bb_error_msg_and_die("invalid byte or field list");
/* add the new list */
cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
cut_lists[nlists-1].startpos = s;
cut_lists[nlists-1].endpos = e;
}
/* make sure we got some cut positions out of all that */
if (nlists == 0)
bb_error_msg_and_die("missing list of positions");
/* now that the lists are parsed, we need to sort them to make life easier
* on us when it comes time to print the chars / fields / lines */
qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
} }
static void cut_file(FILE * file)
static void cut_line_by_chars(const char *line)
{
int c, l;
/* set up a list so we can keep track of what's been printed */
char *printed = xzalloc(strlen(line));
/* print the chars specified in each cut list */
for (c = 0; c < nlists; c++) {
l = cut_lists[c].startpos;
while (l < strlen(line)) {
if (!printed[l]) {
putchar(line[l]);
printed[l] = 'X';
}
l++;
if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos)
break;
}
}
putchar('\n'); /* cuz we were handed a chomped line */
free(printed);
}
static void cut_line_by_fields(char *line)
{
int c, f;
int ndelim = -1; /* zero-based / one-based problem */
int nfields_printed = 0;
char *field = NULL;
char d[2] = { delim, 0 };
char *printed;
/* test the easy case first: does this line contain any delimiters? */
if (strchr(line, delim) == NULL) {
if (!supress_non_delimited_lines)
puts(line);
return;
}
/* set up a list so we can keep track of what's been printed */
printed = xzalloc(strlen(line));
/* process each list on this line, for as long as we've got a line to process */
for (c = 0; c < nlists && line; c++) {
f = cut_lists[c].startpos;
do {
/* find the field we're looking for */
while (line && ndelim < f) {
field = strsep(&line, d);
ndelim++;
}
/* we found it, and it hasn't been printed yet */
if (field && ndelim == f && !printed[ndelim]) {
/* if this isn't our first time through, we need to print the
* delimiter after the last field that was printed */
if (nfields_printed > 0)
putchar(delim);
fputs(field, stdout);
printed[ndelim] = 'X';
nfields_printed++;
}
f++;
/* keep going as long as we have a line to work with, this is a
* list, and we're not at the end of that list */
} while (line && cut_lists[c].endpos != NON_RANGE && f <= cut_lists[c].endpos);
}
/* if we printed anything at all, we need to finish it with a newline cuz
* we were handed a chomped line */
putchar('\n');
free(printed);
}
static void cut_file_by_lines(const char *line, unsigned int linenum)
{
static int c = 0;
static int l = -1;
/* I can't initialize this above cuz the "initializer isn't
* constant" *sigh* */
if (l == -1)
l = cut_lists[c].startpos;
/* get out if we have no more lists to process or if the lines are lower
* than what we're interested in */
if (c >= nlists || linenum < l)
return;
/* if the line we're looking for is lower than the one we were passed, it
* means we displayed it already, so move on */
while (l < linenum) {
l++;
/* move on to the next list if we're at the end of this one */
if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) {
c++;
/* get out if there's no more lists to process */
if (c >= nlists)
return;
l = cut_lists[c].startpos;
/* get out if the current line is lower than the one we just became
* interested in */
if (linenum < l)
return;
}
}
/* If we made it here, it means we've found the line we're looking for, so print it */
puts(line);
}
/*
* snippy-snip
*/
static void cut_file(FILE *file)
{ {
char *line = NULL; char *line = NULL;
unsigned int linenum = 0; /* keep these zero-based to be consistent */ unsigned int linenum = 0; /* keep these zero-based to be consistent */
/* go through every line in the file */ /* go through every line in the file */
while ((line = bb_get_chomped_line_from_file(file)) != NULL) { while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
/* set up a list so we can keep track of what's been printed */
char * printed = xzalloc(strlen(line) * sizeof(char));
char * orig_line = line;
unsigned int cl_pos = 0;
int spos;
/* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS))) if ((opt & (CUT_OPT_CHAR_FLGS | CUT_OPT_BYTE_FLGS))) {
cut_line_by_chars(line); /* print the chars specified in each cut list */
for (; cl_pos < nlists; cl_pos++) {
spos = cut_lists[cl_pos].startpos;
while (spos < strlen(line)) {
if (!printed[spos]) {
printed[spos] = 'X';
putchar(line[spos]);
}
spos++;
if (spos > cut_lists[cl_pos].endpos
|| cut_lists[cl_pos].endpos == NON_RANGE)
break;
}
}
} else if (delim == '\n') { /* cut by lines */
spos = cut_lists[cl_pos].startpos;
/* cut based on fields */ /* get out if we have no more lists to process or if the lines
else { * are lower than what we're interested in */
if (delim == '\n') if (linenum < spos || cl_pos >= nlists)
cut_file_by_lines(line, linenum); goto next_line;
else
cut_line_by_fields(line); /* if the line we're looking for is lower than the one we were
* passed, it means we displayed it already, so move on */
while (spos < linenum) {
spos++;
/* go to the next list if we're at the end of this one */
if (spos > cut_lists[cl_pos].endpos
|| cut_lists[cl_pos].endpos == NON_RANGE) {
cl_pos++;
/* get out if there's no more lists to process */
if (cl_pos >= nlists)
goto next_line;
spos = cut_lists[cl_pos].startpos;
/* get out if the current line is lower than the one
* we just became interested in */
if (linenum < spos)
goto next_line;
}
}
/* If we made it here, it means we've found the line we're
* looking for, so print it */
puts(line);
goto next_line;
} else { /* cut by fields */
int ndelim = -1; /* zero-based / one-based problem */
int nfields_printed = 0;
char *field = NULL;
const char delimiter[2] = { delim, 0 };
/* does this line contain any delimiters? */
if (strchr(line, delim) == NULL) {
if (!(opt & CUT_OPT_SUPPRESS_FLGS))
puts(line);
goto next_line;
}
/* process each list on this line, for as long as we've got
* a line to process */
for (; cl_pos < nlists && line; cl_pos++) {
spos = cut_lists[cl_pos].startpos;
do {
/* find the field we're looking for */
while (line && ndelim < spos) {
field = strsep(&line, delimiter);
ndelim++;
}
/* we found it, and it hasn't been printed yet */
if (field && ndelim == spos && !printed[ndelim]) {
/* if this isn't our first time through, we need to
* print the delimiter after the last field that was
* printed */
if (nfields_printed > 0)
putchar(delim);
fputs(field, stdout);
printed[ndelim] = 'X';
nfields_printed++; /* shouldn't overflow.. */
}
spos++;
/* keep going as long as we have a line to work with,
* this is a list, and we're not at the end of that
* list */
} while (spos <= cut_lists[cl_pos].endpos && line
&& cut_lists[cl_pos].endpos != NON_RANGE);
}
} }
/* if we printed anything at all, we need to finish it with a
* newline cuz we were handed a chomped line */
putchar('\n');
next_line:
linenum++; linenum++;
free(line); free(printed);
free(orig_line);
} }
} }
static int getval(char *ntok)
{
char *junk;
int i = strtoul(ntok, &junk, 10);
if (*junk != '\0' || i < 0)
bb_error_msg_and_die("invalid byte or field list");
return i;
}
static const char * const _op_on_field = " only when operating on fields";
int cut_main(int argc, char **argv) int cut_main(int argc, char **argv)
{ {
unsigned long opt; char *sopt, *ltok;
char *sopt, *sdopt;
bb_opt_complementally = "b--bcf:c--bcf:f--bcf"; bb_opt_complementally = "b--bcf:c--bcf:f--bcf";
opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt); opt =
part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS); bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &ltok);
if(part == 0) if (!(opt & (CUT_OPT_BYTE_FLGS | CUT_OPT_CHAR_FLGS | CUT_OPT_FIELDS_FLGS)))
bb_error_msg_and_die("you must specify a list of bytes, characters, or fields"); bb_error_msg_and_die
if(opt & BB_GETOPT_ERROR) ("expected a list of bytes, characters, or fields");
if (opt & BB_GETOPT_ERROR)
bb_error_msg_and_die("only one type of list may be specified"); bb_error_msg_and_die("only one type of list may be specified");
parse_lists(sopt);
if((opt & (OPT_DELIM_FLGS))) { if ((opt & (CUT_OPT_DELIM_FLGS))) {
if (strlen(sdopt) > 1) { if (strlen(ltok) > 1) {
bb_error_msg_and_die("the delimiter must be a single character"); bb_error_msg_and_die("the delimiter must be a single character");
} }
delim = sdopt[0]; delim = ltok[0];
} }
supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS;
/* non-field (char or byte) cutting has some special handling */ /* non-field (char or byte) cutting has some special handling */
if (part != OPT_FIELDS_FLGS) { if (!(opt & CUT_OPT_FIELDS_FLGS)) {
if (supress_non_delimited_lines) { if (opt & CUT_OPT_SUPPRESS_FLGS) {
bb_error_msg_and_die("suppressing non-delimited lines makes sense" bb_error_msg_and_die
" only when operating on fields"); ("suppressing non-delimited lines makes sense%s",
_op_on_field);
} }
if (delim != '\t') { if (delim != '\t') {
bb_error_msg_and_die("a delimiter may be specified only when operating on fields"); bb_error_msg_and_die
("a delimiter may be specified%s", _op_on_field);
} }
} }
/*
* parse list and put values into startpos and endpos.
* valid list formats: N, N-, N-M, -M
* more than one list can be separated by commas
*/
{
char *ntok;
int s = 0, e = 0;
/* take apart the lists, one by one (they are separated with commas */
while ((ltok = strsep(&sopt, ",")) != NULL) {
/* it's actually legal to pass an empty list */
if (strlen(ltok) == 0)
continue;
/* get the start pos */
ntok = strsep(&ltok, "-");
if (ntok == NULL) {
bb_error_msg
("internal error: ntok is null for start pos!?\n");
} else if (strlen(ntok) == 0) {
s = BOL;
} else {
s = getval(ntok);
/* account for the fact that arrays are zero based, while
* the user expects the first char on the line to be char #1 */
if (s != 0)
s--;
}
/* get the end pos */
ntok = strsep(&ltok, "-");
if (ntok == NULL) {
e = NON_RANGE;
} else if (strlen(ntok) == 0) {
e = EOL;
} else {
e = getval(ntok);
/* if the user specified and end position of 0, that means "til the
* end of the line */
if (e == 0)
e = EOL;
e--; /* again, arrays are zero based, lines are 1 based */
if (e == s)
e = NON_RANGE;
}
/* if there's something left to tokenize, the user passed
* an invalid list */
if (ltok)
bb_error_msg_and_die("invalid byte or field list");
/* add the new list */
cut_lists =
xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
cut_lists[nlists - 1].startpos = s;
cut_lists[nlists - 1].endpos = e;
}
/* make sure we got some cut positions out of all that */
if (nlists == 0)
bb_error_msg_and_die("missing list of positions");
/* now that the lists are parsed, we need to sort them to make life
* easier on us when it comes time to print the chars / fields / lines
*/
qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
}
/* argv[(optind)..(argc-1)] should be names of file to process. If no /* argv[(optind)..(argc-1)] should be names of file to process. If no
* files were specified or '-' was specified, take input from stdin. * files were specified or '-' was specified, take input from stdin.
* Otherwise, we process all the files specified. */ * Otherwise, we process all the files specified. */
if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { if (argv[optind] == NULL
|| (argv[optind][0] == '-' && argv[optind][1] == '\0')) {
cut_file(stdin); cut_file(stdin);
} } else {
else {
int i;
FILE *file; FILE *file;
for (i = optind; i < argc; i++) {
file = bb_wfopen(argv[i], "r"); for (; optind < argc; optind++) {
if(file) { file = bb_wfopen(argv[optind], "r");
if (file) {
cut_file(file); cut_file(file);
fclose(file); fclose(file);
} }
} }
} }
if (ENABLE_FEATURE_CLEAN_UP)
free(cut_lists);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -5,14 +5,17 @@
* by Matthew Grant <grantma@anathoth.gen.nz> * by Matthew Grant <grantma@anathoth.gen.nz>
* *
* iso-format handling added by Robert Griebl <griebl@gmx.de> * iso-format handling added by Robert Griebl <griebl@gmx.de>
* bugfixes and cleanup by Bernhard Fischer
* *
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/ */
#include "busybox.h"
/* This 'date' command supports only 2 time setting formats, /* This 'date' command supports only 2 time setting formats,
all the GNU strftime stuff (its in libc, lets use it), all the GNU strftime stuff (its in libc, lets use it),
setting time using UTC and displaying int, as well as setting time using UTC and displaying it, as well as
an RFC 822 complient date output for shell scripting an RFC 2822 compliant date output for shell scripting
mail commands */ mail commands */
/* Input parsing code is always bulky - used heavy duty libc stuff as /* Input parsing code is always bulky - used heavy duty libc stuff as
@ -20,13 +23,6 @@
/* Default input handling to save surprising some people */ /* Default input handling to save surprising some people */
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include "busybox.h"
#define DATE_OPT_RFC2822 0x01 #define DATE_OPT_RFC2822 0x01
#define DATE_OPT_SET 0x02 #define DATE_OPT_SET 0x02
@ -36,119 +32,45 @@
#define DATE_OPT_TIMESPEC 0x20 #define DATE_OPT_TIMESPEC 0x20
#define DATE_OPT_HINT 0x40 #define DATE_OPT_HINT 0x40
static void maybe_set_utc(int opt)
static struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
{ {
int nr; if ((opt & DATE_OPT_UTC) && putenv("TZ=UTC0") != 0)
char *cp; bb_error_msg_and_die(bb_msg_memory_exhausted);
nr = sscanf(t_string, "%2d%2d%2d%2d%d", &(tm_time->tm_mon),
&(tm_time->tm_mday), &(tm_time->tm_hour), &(tm_time->tm_min),
&(tm_time->tm_year));
if (nr < 4 || nr > 5) {
bb_error_msg_and_die(bb_msg_invalid_date, t_string);
}
cp = strchr(t_string, '.');
if (cp) {
nr = sscanf(cp + 1, "%2d", &(tm_time->tm_sec));
if (nr != 1) {
bb_error_msg_and_die(bb_msg_invalid_date, t_string);
}
}
/* correct for century - minor Y2K problem here? */
if (tm_time->tm_year >= 1900) {
tm_time->tm_year -= 1900;
}
/* adjust date */
tm_time->tm_mon -= 1;
return (tm_time);
}
/* The new stuff for LRP */
static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
{
struct tm t;
/* Parse input and assign appropriately to tm_time */
if (t = *tm_time, sscanf(t_string, "%d:%d:%d", &t.tm_hour, &t.tm_min,
&t.tm_sec) == 3) {
/* no adjustments needed */
} else if (t = *tm_time, sscanf(t_string, "%d:%d", &t.tm_hour,
&t.tm_min) == 2) {
/* no adjustments needed */
} else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d:%d", &t.tm_mon,
&t.tm_mday, &t.tm_hour,
&t.tm_min, &t.tm_sec) == 5) {
/* Adjust dates from 1-12 to 0-11 */
t.tm_mon -= 1;
} else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d", &t.tm_mon,
&t.tm_mday,
&t.tm_hour, &t.tm_min) == 4) {
/* Adjust dates from 1-12 to 0-11 */
t.tm_mon -= 1;
} else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d:%d", &t.tm_year,
&t.tm_mon, &t.tm_mday,
&t.tm_hour, &t.tm_min,
&t.tm_sec) == 6) {
t.tm_year -= 1900; /* Adjust years */
t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
} else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d", &t.tm_year,
&t.tm_mon, &t.tm_mday,
&t.tm_hour, &t.tm_min) == 5) {
t.tm_year -= 1900; /* Adjust years */
t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
} else {
bb_error_msg_and_die(bb_msg_invalid_date, t_string);
}
*tm_time = t;
return (tm_time);
} }
int date_main(int argc, char **argv) int date_main(int argc, char **argv)
{ {
time_t tm;
struct tm tm_time;
unsigned long opt;
int ifmt = -1;
char *date_str = NULL; char *date_str = NULL;
char *date_fmt = NULL; char *date_fmt = NULL;
int set_time;
int utc;
time_t tm;
unsigned long opt;
struct tm tm_time;
char *filename = NULL; char *filename = NULL;
int ifmt = 0;
char *isofmt_arg; char *isofmt_arg;
char *hintfmt_arg; char *hintfmt_arg;
bb_opt_complementally = "?:d--s:s--d"; bb_opt_complementally = "?:d--s:s--d"
USE_FEATURE_DATE_ISOFMT(":R--I:I--R");
opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:" opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:"
USE_FEATURE_DATE_ISOFMT("I::D:"), USE_FEATURE_DATE_ISOFMT("I::D:"),
&date_str, &date_str, &filename &date_str, &date_str, &filename
USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg)); USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg));
set_time = opt & DATE_OPT_SET; maybe_set_utc(opt);
utc = opt & DATE_OPT_UTC;
if (utc && putenv("TZ=UTC0") != 0) {
bb_error_msg_and_die(bb_msg_memory_exhausted);
}
if(ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) { if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) {
if (!isofmt_arg) { if (!isofmt_arg) {
ifmt = 1; ifmt = 0; /* default is date */
} else { } else {
char *isoformats[]={"date","hours","minutes","seconds"}; const char * const isoformats[] =
for(ifmt = 4; ifmt;) {"date", "hours", "minutes", "seconds"};
if(!strcmp(isofmt_arg,isoformats[--ifmt]))
for (ifmt = 0; ifmt < 4; ifmt++)
if (!strcmp(isofmt_arg, isoformats[ifmt])) {
break; break;
} }
if (!ifmt) { if (ifmt == 4) /* parse error */
bb_show_usage(); bb_show_usage();
} }
} }
@ -156,18 +78,19 @@ int date_main(int argc, char **argv)
if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) { if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) {
date_fmt = &argv[optind][1]; /* Skip over the '+' */ date_fmt = &argv[optind][1]; /* Skip over the '+' */
} else if (date_str == NULL) { } else if (date_str == NULL) {
set_time = 1; opt |= DATE_OPT_SET;
date_str = argv[optind]; date_str = argv[optind];
} }
/* Now we have parsed all the information except the date format /* Now we have parsed all the information except the date format
which depends on whether the clock is being set or read */ which depends on whether the clock is being set or read */
if(filename) { if (filename) {
struct stat statbuf; struct stat statbuf;
xstat(filename,&statbuf); xstat(filename, &statbuf);
tm=statbuf.st_mtime; tm = statbuf.st_mtime;
} else time(&tm); } else
time(&tm);
memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
/* Zero out fields - take her back to midnight! */ /* Zero out fields - take her back to midnight! */
if (date_str != NULL) { if (date_str != NULL) {
@ -179,9 +102,64 @@ int date_main(int argc, char **argv)
if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) { if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) {
strptime(date_str, hintfmt_arg, &tm_time); strptime(date_str, hintfmt_arg, &tm_time);
} else if (strchr(date_str, ':') != NULL) { } else if (strchr(date_str, ':') != NULL) {
date_conv_ftime(&tm_time, date_str); /* Parse input and assign appropriately to tm_time */
if (sscanf(date_str, "%d:%d:%d", &tm_time.tm_hour, &tm_time.tm_min,
&tm_time.tm_sec) == 3) {
/* no adjustments needed */
} else if (sscanf(date_str, "%d:%d", &tm_time.tm_hour,
&tm_time.tm_min) == 2) {
/* no adjustments needed */
} else if (sscanf(date_str, "%d.%d-%d:%d:%d", &tm_time.tm_mon,
&tm_time.tm_mday, &tm_time.tm_hour,
&tm_time.tm_min, &tm_time.tm_sec) == 5) {
/* Adjust dates from 1-12 to 0-11 */
tm_time.tm_mon -= 1;
} else if (sscanf(date_str, "%d.%d-%d:%d", &tm_time.tm_mon,
&tm_time.tm_mday,
&tm_time.tm_hour, &tm_time.tm_min) == 4) {
/* Adjust dates from 1-12 to 0-11 */
tm_time.tm_mon -= 1;
} else if (sscanf(date_str, "%d.%d.%d-%d:%d:%d", &tm_time.tm_year,
&tm_time.tm_mon, &tm_time.tm_mday,
&tm_time.tm_hour, &tm_time.tm_min,
&tm_time.tm_sec) == 6) {
tm_time.tm_year -= 1900; /* Adjust years */
tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
} else if (sscanf(date_str, "%d.%d.%d-%d:%d", &tm_time.tm_year,
&tm_time.tm_mon, &tm_time.tm_mday,
&tm_time.tm_hour, &tm_time.tm_min) == 5) {
tm_time.tm_year -= 1900; /* Adjust years */
tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
} else {
bb_error_msg_and_die(bb_msg_invalid_date, date_str);
}
} else { } else {
date_conv_time(&tm_time, date_str); int nr;
char *cp;
nr = sscanf(date_str, "%2d%2d%2d%2d%d", &tm_time.tm_mon,
&tm_time.tm_mday, &tm_time.tm_hour, &tm_time.tm_min,
&tm_time.tm_year);
if (nr < 4 || nr > 5) {
bb_error_msg_and_die(bb_msg_invalid_date, date_str);
}
cp = strchr(date_str, '.');
if (cp) {
nr = sscanf(cp + 1, "%2d", &tm_time.tm_sec);
if (nr != 1) {
bb_error_msg_and_die(bb_msg_invalid_date, date_str);
}
}
/* correct for century - minor Y2K problem here? */
if (tm_time.tm_year >= 1900) {
tm_time.tm_year -= 1900;
}
/* adjust date */
tm_time.tm_mon -= 1;
} }
/* Correct any day of week and day of year etc. fields */ /* Correct any day of week and day of year etc. fields */
@ -190,12 +168,10 @@ int date_main(int argc, char **argv)
if (tm < 0) { if (tm < 0) {
bb_error_msg_and_die(bb_msg_invalid_date, date_str); bb_error_msg_and_die(bb_msg_invalid_date, date_str);
} }
if (utc && putenv("TZ=UTC0") != 0) { maybe_set_utc(opt);
bb_error_msg_and_die(bb_msg_memory_exhausted);
}
/* if setting time, set it */ /* if setting time, set it */
if (set_time && stime(&tm) < 0) { if ((opt & DATE_OPT_SET) && stime(&tm) < 0) {
bb_perror_msg("cannot set date"); bb_perror_msg("cannot set date");
} }
} }
@ -203,33 +179,43 @@ int date_main(int argc, char **argv)
/* Display output */ /* Display output */
/* Deal with format string */ /* Deal with format string */
if (date_fmt == NULL) { if (date_fmt == NULL) {
/* Start with the default case */ int i;
date_fmt = xzalloc(32);
date_fmt = (opt & DATE_OPT_RFC2822 ? if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) {
(utc ? "%a, %d %b %Y %H:%M:%S GMT" : strcpy(date_fmt, "%Y-%m-%d");
"%a, %d %b %Y %H:%M:%S %z") : if (ifmt > 0) {
"%a %b %e %H:%M:%S %Z %Y"); i = 8;
date_fmt[i++] = 'T';
if (ENABLE_FEATURE_DATE_ISOFMT) { date_fmt[i++] = '%';
if (ifmt == 4) date_fmt[i++] = 'H';
date_fmt = utc ? "%Y-%m-%dT%H:%M:%SZ" : "%Y-%m-%dT%H:%M:%S%z"; if (ifmt > 1) {
else if (ifmt == 3) date_fmt[i++] = ':';
date_fmt = utc ? "%Y-%m-%dT%H:%MZ" : "%Y-%m-%dT%H:%M%z"; date_fmt[i++] = '%';
else if (ifmt == 2) date_fmt[i++] = 'M';
date_fmt = utc ? "%Y-%m-%dT%HZ" : "%Y-%m-%dT%H%z"; }
else if (ifmt == 1) if (ifmt > 2) {
date_fmt = "%Y-%m-%d"; date_fmt[i++] = ':';
} date_fmt[i++] = '%';
date_fmt[i++] = 'S';
}
format_utc:
date_fmt[i++] = '%';
date_fmt[i] = (opt & DATE_OPT_UTC) ? 'Z' : 'z';
}
} else if (opt & DATE_OPT_RFC2822) {
strcpy(date_fmt, "%a, %d %b %Y %H:%M:%S ");
i = 22;
goto format_utc;
} else /* default case */
date_fmt = "%a %b %e %H:%M:%S %Z %Y";
} }
if (*date_fmt == '\0') { if (*date_fmt == '\0') {
/* With no format string, just print a blank line */ /* With no format string, just print a blank line */
*bb_common_bufsiz1 = 0;
*bb_common_bufsiz1=0;
} else { } else {
/* Handle special conversions */ /* Handle special conversions */
if (strncmp(date_fmt, "%f", 2) == 0) { if (strncmp(date_fmt, "%f", 2) == 0) {

View File

@ -9,6 +9,7 @@
*/ */
#include "busybox.h" #include "busybox.h"
#include <signal.h> /* For FEATURE_DD_SIGNAL_HANDLING */
static const struct suffix_mult dd_suffixes[] = { static const struct suffix_mult dd_suffixes[] = {
{ "c", 1 }, { "c", 1 },
@ -23,72 +24,72 @@ static const struct suffix_mult dd_suffixes[] = {
{ NULL, 0 } { NULL, 0 }
}; };
static size_t out_full; static size_t out_full, out_part, in_full, in_part;
static size_t out_part;
static size_t in_full;
static size_t in_part;
static void dd_output_status(int cur_signal) static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
{ {
fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n", bb_fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
(long)in_full, (long)in_part, (long)in_full, (long)in_part,
(long)out_full, (long)out_part); (long)out_full, (long)out_part);
} }
int dd_main(int argc, char **argv) int dd_main(int argc, char **argv)
{ {
#define sync_flag (1<<0)
#define noerror (1<<1)
#define trunc_flag (1<<2)
#define twobufs_flag (1<<3)
int flags = trunc_flag;
size_t count = -1, oc = 0, ibs = 512, obs = 512; size_t count = -1, oc = 0, ibs = 512, obs = 512;
ssize_t n; ssize_t n;
off_t seek = 0, skip = 0; off_t seek = 0, skip = 0;
int sync_flag = FALSE, noerror = FALSE, trunc_flag = TRUE, twobufs_flag = 0, int oflag, ifd, ofd;
oflag, ifd, ofd, i;
const char *infile = NULL, *outfile = NULL; const char *infile = NULL, *outfile = NULL;
char *ibuf, *obuf; char *ibuf, *obuf;
if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) {
{
struct sigaction sa; struct sigaction sa;
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.sa_handler = dd_output_status; sa.sa_handler = dd_output_status;
sa.sa_flags = SA_RESTART; sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, 0); sigaction(SIGUSR1, &sa, 0);
} }
for (i = 1; i < argc; i++) { for (n = 1; n < argc; n++) {
if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[i], 4)) { if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[n], 4)) {
ibs = bb_xparse_number(argv[i]+4, dd_suffixes); ibs = bb_xparse_number(argv[n]+4, dd_suffixes);
twobufs_flag++; flags |= twobufs_flag;
} else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[i], 4)) { } else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[n], 4)) {
obs = bb_xparse_number(argv[i]+4, dd_suffixes); obs = bb_xparse_number(argv[n]+4, dd_suffixes);
twobufs_flag++; flags |= twobufs_flag;
} else if (!strncmp("bs=", argv[i], 3)) { } else if (!strncmp("bs=", argv[n], 3))
ibs = obs = bb_xparse_number(argv[i]+3, dd_suffixes); ibs = obs = bb_xparse_number(argv[n]+3, dd_suffixes);
} else if (!strncmp("count=", argv[i], 6)) else if (!strncmp("count=", argv[n], 6))
count = bb_xparse_number(argv[i]+6, dd_suffixes); count = bb_xparse_number(argv[n]+6, dd_suffixes);
else if (!strncmp("seek=", argv[i], 5)) else if (!strncmp("seek=", argv[n], 5))
seek = bb_xparse_number(argv[i]+5, dd_suffixes); seek = bb_xparse_number(argv[n]+5, dd_suffixes);
else if (!strncmp("skip=", argv[i], 5)) else if (!strncmp("skip=", argv[n], 5))
skip = bb_xparse_number(argv[i]+5, dd_suffixes); skip = bb_xparse_number(argv[n]+5, dd_suffixes);
else if (!strncmp("if=", argv[i], 3)) else if (!strncmp("if=", argv[n], 3))
infile = argv[i]+3; infile = argv[n]+3;
else if (!strncmp("of=", argv[i], 3)) else if (!strncmp("of=", argv[n], 3))
outfile = argv[i]+3; outfile = argv[n]+3;
else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[i], 5)) { else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[n], 5)) {
ibuf = argv[i]+5; ibuf = argv[n]+5;
while (1) { while (1) {
if (!strncmp("notrunc", ibuf, 7)) { if (!strncmp("notrunc", ibuf, 7)) {
trunc_flag = FALSE; flags ^= trunc_flag;
ibuf += 7; ibuf += 7;
} else if (!strncmp("sync", ibuf, 4)) { } else if (!strncmp("sync", ibuf, 4)) {
sync_flag = TRUE; flags |= sync_flag;
ibuf += 4; ibuf += 4;
} else if (!strncmp("noerror", ibuf, 7)) { } else if (!strncmp("noerror", ibuf, 7)) {
noerror = TRUE; flags |= noerror;
ibuf += 7; ibuf += 7;
} else { } else {
bb_error_msg_and_die(bb_msg_invalid_arg, argv[i]+5, "conv"); bb_error_msg_and_die(bb_msg_invalid_arg, argv[n]+5, "conv");
} }
if (ibuf[0] == '\0') break; if (ibuf[0] == '\0') break;
if (ibuf[0] == ',') ibuf++; if (ibuf[0] == ',') ibuf++;
@ -98,12 +99,14 @@ int dd_main(int argc, char **argv)
} }
ibuf = xmalloc(ibs); ibuf = xmalloc(ibs);
if (twobufs_flag) obuf = xmalloc(obs); if (flags & twobufs_flag)
else obuf = ibuf; obuf = xmalloc(obs);
else
obuf = ibuf;
if (infile != NULL) { if (infile != NULL)
ifd = xopen(infile, O_RDONLY); ifd = xopen(infile, O_RDONLY);
} else { else {
ifd = STDIN_FILENO; ifd = STDIN_FILENO;
infile = bb_msg_standard_input; infile = bb_msg_standard_input;
} }
@ -111,20 +114,18 @@ int dd_main(int argc, char **argv)
if (outfile != NULL) { if (outfile != NULL) {
oflag = O_WRONLY | O_CREAT; oflag = O_WRONLY | O_CREAT;
if (!seek && trunc_flag) { if (!seek && (flags & trunc_flag))
oflag |= O_TRUNC; oflag |= O_TRUNC;
}
ofd = xopen3(outfile, oflag, 0666); ofd = xopen3(outfile, oflag, 0666);
if (seek && trunc_flag) { if (seek && (flags & trunc_flag)) {
if (ftruncate(ofd, seek * obs) < 0) { if (ftruncate(ofd, seek * obs) < 0) {
struct stat st; struct stat st;
if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) || if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) ||
S_ISDIR (st.st_mode)) { S_ISDIR(st.st_mode))
bb_perror_msg_and_die("%s", outfile); goto die_outfile;
}
} }
} }
} else { } else {
@ -145,44 +146,42 @@ int dd_main(int argc, char **argv)
} }
if (seek) { if (seek) {
if (lseek(ofd, seek * obs, SEEK_CUR) < 0) { if (lseek(ofd, seek * obs, SEEK_CUR) < 0)
bb_perror_msg_and_die("%s", outfile); goto die_outfile;
}
} }
while (in_full + in_part != count) { while (in_full + in_part != count) {
if (noerror) { if (flags & noerror) {
/* Pre-zero the buffer when doing the noerror thing */ /* Pre-zero the buffer when doing the noerror thing */
memset(ibuf, '\0', ibs); memset(ibuf, '\0', ibs);
} }
n = safe_read(ifd, ibuf, ibs); n = safe_read(ifd, ibuf, ibs);
if (n == 0) { if (n == 0)
break; break;
}
if (n < 0) { if (n < 0) {
if (noerror) { if (flags & noerror) {
n = ibs; n = ibs;
bb_perror_msg("%s", infile); bb_perror_msg("%s", infile);
} else { } else
bb_perror_msg_and_die("%s", infile); bb_perror_msg_and_die("%s", infile);
}
} }
if ((size_t)n == ibs) { if ((size_t)n == ibs)
in_full++; in_full++;
} else { else {
in_part++; in_part++;
if (sync_flag) { if (sync_flag) {
memset(ibuf + n, '\0', ibs - n); memset(ibuf + n, '\0', ibs - n);
n = ibs; n = ibs;
} }
} }
if (twobufs_flag) { if (flags & twobufs_flag) {
char *tmp = ibuf; char *tmp = ibuf;
while (n) { while (n) {
size_t d = obs - oc; size_t d = obs - oc;
if (d > n) d = n; if (d > n)
d = n;
memcpy(obuf + oc, tmp, d); memcpy(obuf + oc, tmp, d);
n -= d; n -= d;
tmp += d; tmp += d;
@ -195,8 +194,10 @@ int dd_main(int argc, char **argv)
} }
} else { } else {
xwrite(ofd, ibuf, n); xwrite(ofd, ibuf, n);
if (n == ibs) out_full++; if (n == ibs)
else out_part++; out_full++;
else
out_part++;
} }
} }
@ -209,6 +210,7 @@ int dd_main(int argc, char **argv)
} }
if (close (ofd) < 0) { if (close (ofd) < 0) {
die_outfile:
bb_perror_msg_and_die("%s", outfile); bb_perror_msg_and_die("%s", outfile);
} }

View File

@ -23,11 +23,6 @@
* 4) Fixed busybox bug #1284 involving long overflow with human_readable. * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
*/ */
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "busybox.h" #include "busybox.h"
#ifdef CONFIG_FEATURE_HUMAN_READABLE #ifdef CONFIG_FEATURE_HUMAN_READABLE
@ -57,7 +52,7 @@ static int one_file_system;
static dev_t dir_dev; static dev_t dir_dev;
static void print(long size, char *filename) static void print(long size, const char * const filename)
{ {
/* TODO - May not want to defer error checking here. */ /* TODO - May not want to defer error checking here. */
#ifdef CONFIG_FEATURE_HUMAN_READABLE #ifdef CONFIG_FEATURE_HUMAN_READABLE
@ -73,7 +68,7 @@ static void print(long size, char *filename)
} }
/* tiny recursive du */ /* tiny recursive du */
static long du(char *filename) static long du(const char * const filename)
{ {
struct stat statbuf; struct stat statbuf;
long sum; long sum;

View File

@ -37,11 +37,13 @@ typedef enum valtype TYPE;
#if ENABLE_EXPR_MATH_SUPPORT_64 #if ENABLE_EXPR_MATH_SUPPORT_64
typedef int64_t arith_t; typedef int64_t arith_t;
#define PF_REZ "ll" #define PF_REZ "ll"
#define PF_REZ_TYPE (long long) #define PF_REZ_TYPE (long long)
#define STRTOL(s, e, b) strtoll(s, e, b) #define STRTOL(s, e, b) strtoll(s, e, b)
#else #else
typedef long arith_t; typedef long arith_t;
#define PF_REZ "l" #define PF_REZ "l"
#define PF_REZ_TYPE (long) #define PF_REZ_TYPE (long)
#define STRTOL(s, e, b) strtol(s, e, b) #define STRTOL(s, e, b) strtol(s, e, b)
@ -49,8 +51,8 @@ typedef long arith_t;
/* A value is.... */ /* A value is.... */
struct valinfo { struct valinfo {
TYPE type; /* Which kind. */ TYPE type; /* Which kind. */
union { /* The value itself. */ union { /* The value itself. */
arith_t i; arith_t i;
char *s; char *s;
} u; } u;
@ -60,17 +62,17 @@ typedef struct valinfo VALUE;
/* The arguments given to the program, minus the program name. */ /* The arguments given to the program, minus the program name. */
static char **args; static char **args;
static VALUE *docolon (VALUE *sv, VALUE *pv); static VALUE *docolon(VALUE * sv, VALUE * pv);
static VALUE *eval (void); static VALUE *eval(void);
static VALUE *int_value (arith_t i); static VALUE *int_value(arith_t i);
static VALUE *str_value (char *s); static VALUE *str_value(char *s);
static int nextarg (char *str); static int nextarg(char *str);
static int null (VALUE *v); static int null(VALUE * v);
static int toarith (VALUE *v); static int toarith(VALUE * v);
static void freev (VALUE *v); static void freev(VALUE * v);
static void tostring (VALUE *v); static void tostring(VALUE * v);
int expr_main (int argc, char **argv) int expr_main(int argc, char **argv)
{ {
VALUE *v; VALUE *v;
@ -80,25 +82,25 @@ int expr_main (int argc, char **argv)
args = argv + 1; args = argv + 1;
v = eval (); v = eval();
if (*args) if (*args)
bb_error_msg_and_die ("syntax error"); bb_error_msg_and_die("syntax error");
if (v->type == integer) if (v->type == integer)
printf ("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); bb_printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
else else
puts (v->u.s); puts(v->u.s);
exit (null (v)); exit(null(v));
} }
/* Return a VALUE for I. */ /* Return a VALUE for I. */
static VALUE *int_value (arith_t i) static VALUE *int_value(arith_t i)
{ {
VALUE *v; VALUE *v;
v = xmalloc (sizeof(VALUE)); v = xmalloc(sizeof(VALUE));
v->type = integer; v->type = integer;
v->u.i = i; v->u.i = i;
return v; return v;
@ -106,7 +108,7 @@ static VALUE *int_value (arith_t i)
/* Return a VALUE for S. */ /* Return a VALUE for S. */
static VALUE *str_value (char *s) static VALUE *str_value(char *s)
{ {
VALUE *v; VALUE *v;
@ -118,28 +120,26 @@ static VALUE *str_value (char *s)
/* Free VALUE V, including structure components. */ /* Free VALUE V, including structure components. */
static void freev (VALUE *v) static void freev(VALUE * v)
{ {
if (v->type == string) if (v->type == string)
free (v->u.s); free(v->u.s);
free (v); free(v);
} }
/* Return nonzero if V is a null-string or zero-number. */ /* Return nonzero if V is a null-string or zero-number. */
static int null (VALUE *v) static int null(VALUE * v)
{ {
switch (v->type) { if (v->type == integer)
case integer: return v->u.i == 0;
return v->u.i == 0; else /* string: */
default: /* string: */ return v->u.s[0] == '\0' || strcmp(v->u.s, "0") == 0;
return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
}
} }
/* Coerce V to a string value (can't fail). */ /* Coerce V to a string value (can't fail). */
static void tostring (VALUE *v) static void tostring(VALUE * v)
{ {
if (v->type == integer) { if (v->type == integer) {
v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i); v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
@ -149,9 +149,9 @@ static void tostring (VALUE *v)
/* Coerce V to an integer value. Return 1 on success, 0 on failure. */ /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
static int toarith (VALUE *v) static int toarith(VALUE * v)
{ {
if(v->type == string) { if (v->type == string) {
arith_t i; arith_t i;
char *e; char *e;
@ -160,7 +160,7 @@ static int toarith (VALUE *v)
i = STRTOL(v->u.s, &e, 10); i = STRTOL(v->u.s, &e, 10);
if ((v->u.s == e) || *e) if ((v->u.s == e) || *e)
return 0; return 0;
free (v->u.s); free(v->u.s);
v->u.i = i; v->u.i = i;
v->type = integer; v->type = integer;
} }
@ -170,221 +170,207 @@ static int toarith (VALUE *v)
/* Return nonzero if the next token matches STR exactly. /* Return nonzero if the next token matches STR exactly.
STR must not be NULL. */ STR must not be NULL. */
static int static int nextarg(char *str)
nextarg (char *str)
{ {
if (*args == NULL) if (*args == NULL)
return 0; return 0;
return strcmp (*args, str) == 0; return strcmp(*args, str) == 0;
} }
/* The comparison operator handling functions. */ /* The comparison operator handling functions. */
static int cmp_common (VALUE *l, VALUE *r, int op) static int cmp_common(VALUE * l, VALUE * r, int op)
{ {
int cmpval; int cmpval;
if (l->type == string || r->type == string) { if (l->type == string || r->type == string) {
tostring (l); tostring(l);
tostring (r); tostring(r);
cmpval = strcmp (l->u.s, r->u.s); cmpval = strcmp(l->u.s, r->u.s);
} } else
else
cmpval = l->u.i - r->u.i; cmpval = l->u.i - r->u.i;
switch(op) { if (op == '<')
case '<': return cmpval < 0;
return cmpval < 0; else if (op == ('L' + 'E'))
case ('L'+'E'): return cmpval <= 0;
return cmpval <= 0; else if (op == '=')
case '=': return cmpval == 0;
return cmpval == 0; else if (op == '!')
case '!': return cmpval != 0;
return cmpval != 0; else if (op == '>')
case '>': return cmpval > 0;
return cmpval > 0; else /* >= */
default: /* >= */ return cmpval >= 0;
return cmpval >= 0;
}
} }
/* The arithmetic operator handling functions. */ /* The arithmetic operator handling functions. */
static arith_t arithmetic_common (VALUE *l, VALUE *r, int op) static arith_t arithmetic_common(VALUE * l, VALUE * r, int op)
{ {
arith_t li, ri; arith_t li, ri;
if (!toarith (l) || !toarith (r)) if (!toarith(l) || !toarith(r))
bb_error_msg_and_die ("non-numeric argument"); bb_error_msg_and_die("non-numeric argument");
li = l->u.i; li = l->u.i;
ri = r->u.i; ri = r->u.i;
if((op == '/' || op == '%') && ri == 0) if ((op == '/' || op == '%') && ri == 0)
bb_error_msg_and_die ( "division by zero"); bb_error_msg_and_die("division by zero");
switch(op) { if (op == '+')
case '+':
return li + ri; return li + ri;
case '-': else if (op == '-')
return li - ri; return li - ri;
case '*': else if (op == '*')
return li * ri; return li * ri;
case '/': else if (op == '/')
return li / ri; return li / ri;
default: else
return li % ri; return li % ri;
}
} }
/* Do the : operator. /* Do the : operator.
SV is the VALUE for the lhs (the string), SV is the VALUE for the lhs (the string),
PV is the VALUE for the rhs (the pattern). */ PV is the VALUE for the rhs (the pattern). */
static VALUE *docolon (VALUE *sv, VALUE *pv) static VALUE *docolon(VALUE * sv, VALUE * pv)
{ {
VALUE *v; VALUE *v;
regex_t re_buffer; regex_t re_buffer;
const int NMATCH = 2; const int NMATCH = 2;
regmatch_t re_regs[NMATCH]; regmatch_t re_regs[NMATCH];
tostring (sv); tostring(sv);
tostring (pv); tostring(pv);
if (pv->u.s[0] == '^') { if (pv->u.s[0] == '^') {
fprintf (stderr, "\ fprintf(stderr, "\
warning: unportable BRE: `%s': using `^' as the first character\n\ warning: unportable BRE: `%s': using `^' as the first character\n\
of a basic regular expression is not portable; it is being ignored", of a basic regular expression is not portable; it is being ignored", pv->u.s);
pv->u.s);
} }
memset (&re_buffer, 0, sizeof (re_buffer)); memset(&re_buffer, 0, sizeof(re_buffer));
memset (re_regs, 0, sizeof (*re_regs)); memset(re_regs, 0, sizeof(*re_regs));
if( regcomp (&re_buffer, pv->u.s, 0) != 0 ) if (regcomp(&re_buffer, pv->u.s, 0) != 0)
bb_error_msg_and_die("Invalid regular expression"); bb_error_msg_and_die("Invalid regular expression");
/* expr uses an anchored pattern match, so check that there was a /* expr uses an anchored pattern match, so check that there was a
* match and that the match starts at offset 0. */ * match and that the match starts at offset 0. */
if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
re_regs[0].rm_so == 0) { re_regs[0].rm_so == 0) {
/* Were \(...\) used? */ /* Were \(...\) used? */
if (re_buffer.re_nsub > 0) { if (re_buffer.re_nsub > 0) {
sv->u.s[re_regs[1].rm_eo] = '\0'; sv->u.s[re_regs[1].rm_eo] = '\0';
v = str_value (sv->u.s + re_regs[1].rm_so); v = str_value(sv->u.s + re_regs[1].rm_so);
} } else
else v = int_value(re_regs[0].rm_eo);
v = int_value (re_regs[0].rm_eo); } else {
}
else {
/* Match failed -- return the right kind of null. */ /* Match failed -- return the right kind of null. */
if (re_buffer.re_nsub > 0) if (re_buffer.re_nsub > 0)
v = str_value (""); v = str_value("");
else else
v = int_value (0); v = int_value(0);
} }
return v; return v;
} }
/* Handle bare operands and ( expr ) syntax. */ /* Handle bare operands and ( expr ) syntax. */
static VALUE *eval7 (void) static VALUE *eval7(void)
{ {
VALUE *v; VALUE *v;
if (!*args) if (!*args)
bb_error_msg_and_die ( "syntax error"); bb_error_msg_and_die("syntax error");
if (nextarg ("(")) { if (nextarg("(")) {
args++; args++;
v = eval (); v = eval();
if (!nextarg (")")) if (!nextarg(")"))
bb_error_msg_and_die ( "syntax error"); bb_error_msg_and_die("syntax error");
args++; args++;
return v; return v;
} }
if (nextarg (")")) if (nextarg(")"))
bb_error_msg_and_die ( "syntax error"); bb_error_msg_and_die("syntax error");
return str_value (*args++); return str_value(*args++);
} }
/* Handle match, substr, index, length, and quote keywords. */ /* Handle match, substr, index, length, and quote keywords. */
static VALUE *eval6 (void) static VALUE *eval6(void)
{ {
VALUE *l, *r, *v, *i1, *i2; VALUE *l, *r, *v, *i1, *i2;
if (nextarg ("quote")) { if (nextarg("quote")) {
args++; args++;
if (!*args) if (!*args)
bb_error_msg_and_die ( "syntax error"); bb_error_msg_and_die("syntax error");
return str_value (*args++); return str_value(*args++);
} } else if (nextarg("length")) {
else if (nextarg ("length")) {
args++; args++;
r = eval6 (); r = eval6();
tostring (r); tostring(r);
v = int_value (strlen (r->u.s)); v = int_value(strlen(r->u.s));
freev (r); freev(r);
return v; return v;
} } else if (nextarg("match")) {
else if (nextarg ("match")) {
args++; args++;
l = eval6 (); l = eval6();
r = eval6 (); r = eval6();
v = docolon (l, r); v = docolon(l, r);
freev (l); freev(l);
freev (r); freev(r);
return v; return v;
} } else if (nextarg("index")) {
else if (nextarg ("index")) {
args++; args++;
l = eval6 (); l = eval6();
r = eval6 (); r = eval6();
tostring (l); tostring(l);
tostring (r); tostring(r);
v = int_value (strcspn (l->u.s, r->u.s) + 1); v = int_value(strcspn(l->u.s, r->u.s) + 1);
if (v->u.i == (arith_t) strlen (l->u.s) + 1) if (v->u.i == (arith_t) strlen(l->u.s) + 1)
v->u.i = 0; v->u.i = 0;
freev (l); freev(l);
freev (r); freev(r);
return v; return v;
} } else if (nextarg("substr")) {
else if (nextarg ("substr")) {
args++; args++;
l = eval6 (); l = eval6();
i1 = eval6 (); i1 = eval6();
i2 = eval6 (); i2 = eval6();
tostring (l); tostring(l);
if (!toarith (i1) || !toarith (i2) if (!toarith(i1) || !toarith(i2)
|| i1->u.i > (arith_t) strlen (l->u.s) || i1->u.i > (arith_t) strlen(l->u.s)
|| i1->u.i <= 0 || i2->u.i <= 0) || i1->u.i <= 0 || i2->u.i <= 0)
v = str_value (""); v = str_value("");
else { else {
v = xmalloc (sizeof(VALUE)); v = xmalloc(sizeof(VALUE));
v->type = string; v->type = string;
v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
} }
freev (l); freev(l);
freev (i1); freev(i1);
freev (i2); freev(i2);
return v; return v;
} } else
else return eval7();
return eval7 ();
} }
/* Handle : operator (pattern matching). /* Handle : operator (pattern matching).
Calls docolon to do the real work. */ Calls docolon to do the real work. */
static VALUE *eval5 (void) static VALUE *eval5(void)
{ {
VALUE *l, *r, *v; VALUE *l, *r, *v;
l = eval6 (); l = eval6();
while (nextarg (":")) { while (nextarg(":")) {
args++; args++;
r = eval6 (); r = eval6();
v = docolon (l, r); v = docolon(l, r);
freev (l); freev(l);
freev (r); freev(r);
l = v; l = v;
} }
return l; return l;
@ -392,128 +378,126 @@ static VALUE *eval5 (void)
/* Handle *, /, % operators. */ /* Handle *, /, % operators. */
static VALUE *eval4 (void) static VALUE *eval4(void)
{ {
VALUE *l, *r; VALUE *l, *r;
int op; int op;
arith_t val; arith_t val;
l = eval5 (); l = eval5();
while (1) { while (1) {
if (nextarg ("*")) if (nextarg("*"))
op = '*'; op = '*';
else if (nextarg ("/")) else if (nextarg("/"))
op = '/'; op = '/';
else if (nextarg ("%")) else if (nextarg("%"))
op = '%'; op = '%';
else else
return l; return l;
args++; args++;
r = eval5 (); r = eval5();
val = arithmetic_common (l, r, op); val = arithmetic_common(l, r, op);
freev (l); freev(l);
freev (r); freev(r);
l = int_value (val); l = int_value(val);
} }
} }
/* Handle +, - operators. */ /* Handle +, - operators. */
static VALUE *eval3 (void) static VALUE *eval3(void)
{ {
VALUE *l, *r; VALUE *l, *r;
int op; int op;
arith_t val; arith_t val;
l = eval4 (); l = eval4();
while (1) { while (1) {
if (nextarg ("+")) if (nextarg("+"))
op = '+'; op = '+';
else if (nextarg ("-")) else if (nextarg("-"))
op = '-'; op = '-';
else else
return l; return l;
args++; args++;
r = eval4 (); r = eval4();
val = arithmetic_common (l, r, op); val = arithmetic_common(l, r, op);
freev (l); freev(l);
freev (r); freev(r);
l = int_value (val); l = int_value(val);
} }
} }
/* Handle comparisons. */ /* Handle comparisons. */
static VALUE *eval2 (void) static VALUE *eval2(void)
{ {
VALUE *l, *r; VALUE *l, *r;
int op; int op;
arith_t val; arith_t val;
l = eval3 (); l = eval3();
while (1) { while (1) {
if (nextarg ("<")) if (nextarg("<"))
op = '<'; op = '<';
else if (nextarg ("<=")) else if (nextarg("<="))
op = 'L'+'E'; op = 'L' + 'E';
else if (nextarg ("=") || nextarg ("==")) else if (nextarg("=") || nextarg("=="))
op = '='; op = '=';
else if (nextarg ("!=")) else if (nextarg("!="))
op = '!'; op = '!';
else if (nextarg (">=")) else if (nextarg(">="))
op = 'G'+'E'; op = 'G' + 'E';
else if (nextarg (">")) else if (nextarg(">"))
op = '>'; op = '>';
else else
return l; return l;
args++; args++;
r = eval3 (); r = eval3();
toarith (l); toarith(l);
toarith (r); toarith(r);
val = cmp_common (l, r, op); val = cmp_common(l, r, op);
freev (l); freev(l);
freev (r); freev(r);
l = int_value (val); l = int_value(val);
} }
} }
/* Handle &. */ /* Handle &. */
static VALUE *eval1 (void) static VALUE *eval1(void)
{ {
VALUE *l, *r; VALUE *l, *r;
l = eval2 (); l = eval2();
while (nextarg ("&")) { while (nextarg("&")) {
args++; args++;
r = eval2 (); r = eval2();
if (null (l) || null (r)) { if (null(l) || null(r)) {
freev (l); freev(l);
freev (r); freev(r);
l = int_value (0); l = int_value(0);
} } else
else freev(r);
freev (r);
} }
return l; return l;
} }
/* Handle |. */ /* Handle |. */
static VALUE *eval (void) static VALUE *eval(void)
{ {
VALUE *l, *r; VALUE *l, *r;
l = eval1 (); l = eval1();
while (nextarg ("|")) { while (nextarg("|")) {
args++; args++;
r = eval1 (); r = eval1();
if (null (l)) { if (null(l)) {
freev (l); freev(l);
l = r; l = r;
} } else
else freev(r);
freev (r);
} }
return l; return l;
} }

View File

@ -13,12 +13,6 @@
* Licensed under the GPL v2, see the file LICENSE in this tarball. * Licensed under the GPL v2, see the file LICENSE in this tarball.
*/ */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "busybox.h" #include "busybox.h"
/* 1 if any of the files read were the standard input */ /* 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)
int checksum = 0; /* The checksum mod 2^16. */ int checksum = 0; /* The checksum mod 2^16. */
uintmax_t total_bytes = 0; /* The number of bytes. */ uintmax_t total_bytes = 0; /* The number of bytes. */
int ch; /* Each character read. */ int ch; /* Each character read. */
int ret = 0;
if (IS_STDIN(file)) { if (IS_STDIN(file)) {
fp = stdin; fp = stdin;
have_read_stdin = 1; have_read_stdin++;
} else { } else {
fp = bb_wfopen(file, "r"); fp = bb_wfopen(file, "r");
if (fp == NULL) if (fp == NULL)
return 0; goto out;
} }
while ((ch = getc(fp)) != EOF) { while ((ch = getc(fp)) != EOF) {
@ -58,21 +53,21 @@ static int bsd_sum_file(const char *file, int print_name)
if (ferror(fp)) { if (ferror(fp)) {
bb_perror_msg(file); bb_perror_msg(file);
bb_fclose_nonstdin(fp); bb_fclose_nonstdin(fp);
return 0; goto out;
} }
if (bb_fclose_nonstdin(fp) == EOF) { if (bb_fclose_nonstdin(fp) == EOF) {
bb_perror_msg(file); bb_perror_msg(file);
return 0; goto out;
} }
ret++;
printf("%05d %5ju ", checksum, (total_bytes+1023)/1024); printf("%05d %5ju ", checksum, (total_bytes+1023)/1024);
if (print_name > 1) if (print_name > 1)
puts(file); puts(file);
else else
printf("\n"); printf("\n");
out:
return 1; return ret;
} }
/* Calculate and print the checksum and the size in 512-byte blocks /* Calculate and print the checksum and the size in 512-byte blocks

View File

@ -42,15 +42,6 @@ static const struct suffix_mult tail_suffixes[] = {
static int status; static int status;
static void tail_xprint_header(const char *fmt, const char *filename)
{
/* If we get an output error, there is really no sense in continuing. */
if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
bb_perror_nomsg_and_die();
}
}
/* len should probably be size_t */
static void tail_xbb_full_write(const char *buf, size_t len) static void tail_xbb_full_write(const char *buf, size_t len)
{ {
/* If we get a write error, there is really no sense in continuing. */ /* If we get a write error, there is really no sense in continuing. */
@ -58,6 +49,20 @@ static void tail_xbb_full_write(const char *buf, size_t len)
bb_perror_nomsg_and_die(); bb_perror_nomsg_and_die();
} }
static void tail_xprint_header(const char *fmt, const char *filename)
{
#if defined __GLIBC__
if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
bb_perror_nomsg_and_die();
}
#else
int hdr_len = strlen(fmt) + strlen(filename);
char *hdr = xzalloc(hdr_len);
sprintf(hdr, filename, filename);
tail_xbb_full_write(hdr, hdr_len);
#endif
}
static ssize_t tail_read(int fd, char *buf, size_t count) static ssize_t tail_read(int fd, char *buf, size_t count)
{ {
ssize_t r; ssize_t r;

View File

@ -11,6 +11,7 @@
/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */ /* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
#include "busybox.h" #include "busybox.h"
#include <signal.h>
int tee_main(int argc, char **argv) int tee_main(int argc, char **argv)
{ {
@ -37,7 +38,7 @@ int tee_main(int argc, char **argv)
/* gnu tee ignores SIGPIPE in case one of the output files is a pipe /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
* that doesn't consume all its input. Good idea... */ * that doesn't consume all its input. Good idea... */
signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/ signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/
/* Allocate an array of FILE *'s, with one extra for a sentinal. */ /* Allocate an array of FILE *'s, with one extra for a sentinal. */
p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2)); p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2));

View File

@ -3,6 +3,7 @@
* Mini watch implementation for busybox * Mini watch implementation for busybox
* *
* Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de> * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de>
* Copyrigjt (C) Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
* *
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/ */
@ -10,14 +11,9 @@
/* BB_AUDIT SUSv3 N/A */ /* BB_AUDIT SUSv3 N/A */
/* BB_AUDIT GNU defects -- only option -n is supported. */ /* BB_AUDIT GNU defects -- only option -n is supported. */
/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
*
* Removed dependency on date_main(), added proper error checking, and
* reduced size.
*/
#include "busybox.h" #include "busybox.h"
int watch_main(int argc, char **argv) int watch_main(int argc, char **argv)
{ {
int width, len; int width, len;
@ -26,19 +22,18 @@ int watch_main(int argc, char **argv)
if (argc < 2) bb_show_usage(); if (argc < 2) bb_show_usage();
get_terminal_width_height(1, &width, 0); get_terminal_width_height(STDOUT_FILENO, &width, 0);
header = xzalloc(width--); header = xzalloc(width--);
/* don't use getopt, because it permutes the arguments */ /* don't use getopt, because it permutes the arguments */
++argv; ++argv;
if ((argc > 3) && !strcmp(*argv, "-n")) { if ((argc > 3) && argv[0][0] == '-' && argv[0][1] == 'n') {
period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX); period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
argv += 2; argv += 2;
} }
watched_argv = argv; watched_argv = argv;
/* create header */ /* create header */
len = snprintf(header, width, "Every %ds:", period); len = snprintf(header, width, "Every %ds:", period);
while (*argv && len<width) while (*argv && len<width)
snprintf(header+len, width-len, " %s", *(argv++)); snprintf(header+len, width-len, " %s", *(argv++));
@ -50,11 +45,13 @@ int watch_main(int argc, char **argv)
time(&t); time(&t);
thyme = ctime(&t); thyme = ctime(&t);
len = strlen(thyme); len = strlen(thyme);
if (len < width) header[width-len] = 0; if (len < width)
header[width-len] = 0;
printf("\033[H\033[J%s %s\n", header, thyme); bb_printf("\033[H\033[J%s %s\n", header, thyme);
waitpid(xspawn(watched_argv),0,0); waitpid(xspawn(watched_argv),0,0);
sleep(period); sleep(period);
} }
if (ENABLE_FEATURE_CLEAN_UP)
free(header);
} }

View File

@ -60,10 +60,6 @@
#define PATH_MAX 256 #define PATH_MAX 256
#endif #endif
#ifdef DMALLOC
#include <dmalloc.h>
#endif
/* Some useful definitions */ /* Some useful definitions */
#undef FALSE #undef FALSE
#define FALSE ((int) 0) #define FALSE ((int) 0)
@ -211,7 +207,9 @@ extern int bb_fprintf(FILE * __restrict stream, const char * __restrict format,
extern int bb_printf(const char * __restrict format, ...) extern int bb_printf(const char * __restrict format, ...)
__attribute__ ((format (printf, 1, 2))); __attribute__ ((format (printf, 1, 2)));
//#warning rename to xferror_filename? #if ENABLE_NITPICK
#warning rename to xferror_filename?
#endif
extern void xferror(FILE *fp, const char *fn); extern void xferror(FILE *fp, const char *fn);
extern void xferror_stdout(void); extern void xferror_stdout(void);
extern void xfflush_stdout(void); extern void xfflush_stdout(void);
@ -265,7 +263,9 @@ extern long bb_xgetlarg_bnd_sfx(const char *arg, int base,
extern long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes); extern long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes);
//#warning pitchable now? #if ENABLE_NITPICK
#warning pitchable now?
#endif
extern unsigned long bb_xparse_number(const char *numstr, extern unsigned long bb_xparse_number(const char *numstr,
const struct suffix_mult *suffixes); const struct suffix_mult *suffixes);
@ -330,7 +330,9 @@ char *concat_path_file(const char *path, const char *filename);
char *concat_subpath_file(const char *path, const char *filename); char *concat_subpath_file(const char *path, const char *filename);
char *last_char_is(const char *s, int c); char *last_char_is(const char *s, int c);
//#warning yuk! #if ENABLE_NITPICK
#warning yuk!
#endif
char *fgets_str(FILE *file, const char *terminating_string); char *fgets_str(FILE *file, const char *terminating_string);
extern int uncompress(int fd_in, int fd_out); extern int uncompress(int fd_in, int fd_out);
@ -344,7 +346,9 @@ extern int xconnect(struct sockaddr_in *s_addr);
extern unsigned short bb_lookup_port(const char *port, const char *protocol, unsigned short default_port); extern unsigned short bb_lookup_port(const char *port, const char *protocol, unsigned short default_port);
extern void bb_lookup_host(struct sockaddr_in *s_in, const char *host); extern void bb_lookup_host(struct sockaddr_in *s_in, const char *host);
//#warning wrap this? #if ENABLE_NITPICK
#warning wrap this?
#endif
char *dirname (char *path); char *dirname (char *path);
int bb_make_directory (char *path, long mode, int flags); int bb_make_directory (char *path, long mode, int flags);
@ -456,8 +460,10 @@ extern int bb_default_error_retval;
# define FB_0 "/dev/fb0" # define FB_0 "/dev/fb0"
#endif #endif
//#warning put these in .o files
#if ENABLE_NITPICK
#warning put these in .o files
#endif
/* The following devices are the same on devfs and non-devfs systems. */ /* The following devices are the same on devfs and non-devfs systems. */
#define CURRENT_TTY "/dev/tty" #define CURRENT_TTY "/dev/tty"
#define CONSOLE_DEV "/dev/console" #define CONSOLE_DEV "/dev/console"
@ -581,4 +587,8 @@ extern const char BB_BANNER[];
#undef isupper #undef isupper
#undef isxdigit #undef isxdigit
#ifdef DMALLOC
#include <dmalloc.h>
#endif
#endif /* __LIBBUSYBOX_H__ */ #endif /* __LIBBUSYBOX_H__ */

View File

@ -10,8 +10,6 @@
#define ARCHIVE_NOPRESERVE_OWN 32 #define ARCHIVE_NOPRESERVE_OWN 32
#define ARCHIVE_NOPRESERVE_PERM 64 #define ARCHIVE_NOPRESERVE_PERM 64
#include <sys/types.h>
#include <stdio.h>
#include "libbb.h" #include "libbb.h"
typedef struct file_headers_s { typedef struct file_headers_s {

View File

@ -1426,12 +1426,12 @@ USE_FEATURE_DATE_ISOFMT( \
#define ipcrm_trivial_usage \ #define ipcrm_trivial_usage \
"[-[MQS] key] [-[mqs] id]" "[-[MQS] key] [-[mqs] id]"
#define ipcrm_full_usage \ #define ipcrm_full_usage \
"The upper-case options MQS are used to remove a shared memory\n" \ "The upper-case options MQS are used to remove a shared memory segment by a\n" \
"segment by an shmkey value. The lower-case options mqs are used\n" \ "segment by a shmkey value. The lower-case options mqs are used\n" \
"to remove a segment by shmid value.\n" \ "to remove a segment by shmid value.\n" \
"\t-m | -M\tRemove the memory segment after the last detach\n" \ "\t-[mM]\tRemove the memory segment after the last detach\n" \
"\t-q | -Q\tRemove the message queue\n" \ "\t-[qQ]\tRemove the message queue\n" \
"\t-s | -S\tRemove the semaphore" "\t-[sS]\tRemove the semaphore"
#define ipcs_trivial_usage \ #define ipcs_trivial_usage \
"[[-smq] -i shmid] | [[-asmq] [-tclup]]" "[[-smq] -i shmid] | [[-asmq] [-tclup]]"

View File

@ -16,8 +16,12 @@
* succeeded. */ * succeeded. */
#ifndef DMALLOC #ifndef DMALLOC
/* dmalloc provides variants of these that do abort() on failure.
* Since dmalloc's prototypes overwrite the impls here as they are
* included after these prototypes in libbb.h, all is well.
*/
#ifdef L_xmalloc #ifdef L_xmalloc
// Die if we can't allocate size bytes of memory. /* Die if we can't allocate size bytes of memory. */
void *xmalloc(size_t size) void *xmalloc(size_t size)
{ {
void *ptr = malloc(size); void *ptr = malloc(size);
@ -28,9 +32,9 @@ void *xmalloc(size_t size)
#endif #endif
#ifdef L_xrealloc #ifdef L_xrealloc
// Die if we can't resize previously allocated memory. (This returns a pointer /* Die if we can't resize previously allocated memory. (This returns a pointer
// to the new memory, which may or may not be the same as the old memory. * to the new memory, which may or may not be the same as the old memory.
// It'll copy the contents to a new chunk and free the old one if necessary.) * It'll copy the contents to a new chunk and free the old one if necessary.) */
void *xrealloc(void *ptr, size_t size) void *xrealloc(void *ptr, size_t size)
{ {
ptr = realloc(ptr, size); ptr = realloc(ptr, size);
@ -39,9 +43,11 @@ void *xrealloc(void *ptr, size_t size)
return ptr; return ptr;
} }
#endif #endif
#endif /* DMALLOC */
#ifdef L_xzalloc #ifdef L_xzalloc
// Die if we can't allocate and zero size bytes of memory. /* Die if we can't allocate and zero size bytes of memory. */
void *xzalloc(size_t size) void *xzalloc(size_t size)
{ {
void *ptr = xmalloc(size); void *ptr = xmalloc(size);
@ -50,10 +56,8 @@ void *xzalloc(size_t size)
} }
#endif #endif
#endif /* DMALLOC */
#ifdef L_xstrdup #ifdef L_xstrdup
// Die if we can't copy a string to freshly allocated memory. /* Die if we can't copy a string to freshly allocated memory. */
char * xstrdup(const char *s) char * xstrdup(const char *s)
{ {
char *t; char *t;
@ -71,8 +75,9 @@ char * xstrdup(const char *s)
#endif #endif
#ifdef L_xstrndup #ifdef L_xstrndup
// Die if we can't allocate n+1 bytes (space for the null terminator) and copy /* Die if we can't allocate n+1 bytes (space for the null terminator) and copy
// the (possibly truncated to length n) string into it. * the (possibly truncated to length n) string into it.
*/
char * xstrndup(const char *s, int n) char * xstrndup(const char *s, int n)
{ {
char *t; char *t;
@ -87,8 +92,9 @@ char * xstrndup(const char *s, int n)
#endif #endif
#ifdef L_xfopen #ifdef L_xfopen
// Die if we can't open a file and return a FILE * to it. /* Die if we can't open a file and return a FILE * to it.
// Notice we haven't got xfread(), This is for use with fscanf() and friends. * Notice we haven't got xfread(), This is for use with fscanf() and friends.
*/
FILE *xfopen(const char *path, const char *mode) FILE *xfopen(const char *path, const char *mode)
{ {
FILE *fp; FILE *fp;
@ -99,7 +105,7 @@ FILE *xfopen(const char *path, const char *mode)
#endif #endif
#ifdef L_xopen #ifdef L_xopen
// Die if we can't open an existing file and return an fd. /* Die if we can't open an existing file and return an fd. */
int xopen(const char *pathname, int flags) int xopen(const char *pathname, int flags)
{ {
if (ENABLE_DEBUG && (flags && O_CREAT)) if (ENABLE_DEBUG && (flags && O_CREAT))
@ -110,7 +116,7 @@ int xopen(const char *pathname, int flags)
#endif #endif
#ifdef L_xopen3 #ifdef L_xopen3
// Die if we can't open a new file and return an fd. /* Die if we can't open a new file and return an fd. */
int xopen3(const char *pathname, int flags, int mode) int xopen3(const char *pathname, int flags, int mode)
{ {
int ret; int ret;
@ -124,7 +130,7 @@ int xopen3(const char *pathname, int flags, int mode)
#endif #endif
#ifdef L_xread #ifdef L_xread
// Die with an error message if we can't read the entire buffer. /* Die with an error message if we can't read the entire buffer. */
void xread(int fd, void *buf, size_t count) void xread(int fd, void *buf, size_t count)
{ {
while (count) { while (count) {
@ -139,7 +145,7 @@ void xread(int fd, void *buf, size_t count)
#endif #endif
#ifdef L_xwrite #ifdef L_xwrite
// Die with an error message if we can't write the entire buffer. /* Die with an error message if we can't write the entire buffer. */
void xwrite(int fd, void *buf, size_t count) void xwrite(int fd, void *buf, size_t count)
{ {
while (count) { while (count) {
@ -154,7 +160,7 @@ void xwrite(int fd, void *buf, size_t count)
#endif #endif
#ifdef L_xlseek #ifdef L_xlseek
// Die with an error message if we can't lseek to the right spot. /* Die with an error message if we can't lseek to the right spot. */
void xlseek(int fd, off_t offset, int whence) void xlseek(int fd, off_t offset, int whence)
{ {
if (offset != lseek(fd, offset, whence)) bb_error_msg_and_die("lseek"); 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)
#endif #endif
#ifdef L_xread_char #ifdef L_xread_char
// Die with an error message if we can't read one character. /* Die with an error message if we can't read one character. */
unsigned char xread_char(int fd) unsigned char xread_char(int fd)
{ {
char tmp; char tmp;
@ -174,7 +180,7 @@ unsigned char xread_char(int fd)
#endif #endif
#ifdef L_xferror #ifdef L_xferror
// Die with supplied error message if this FILE * has ferror set. /* Die with supplied error message if this FILE * has ferror set. */
void xferror(FILE *fp, const char *fn) void xferror(FILE *fp, const char *fn)
{ {
if (ferror(fp)) { if (ferror(fp)) {
@ -184,7 +190,7 @@ void xferror(FILE *fp, const char *fn)
#endif #endif
#ifdef L_xferror_stdout #ifdef L_xferror_stdout
// Die with an error message if stdout has ferror set. /* Die with an error message if stdout has ferror set. */
void xferror_stdout(void) void xferror_stdout(void)
{ {
xferror(stdout, bb_msg_standard_output); xferror(stdout, bb_msg_standard_output);
@ -192,7 +198,7 @@ void xferror_stdout(void)
#endif #endif
#ifdef L_xfflush_stdout #ifdef L_xfflush_stdout
// Die with an error message if we have trouble flushing stdout. /* Die with an error message if we have trouble flushing stdout. */
void xfflush_stdout(void) void xfflush_stdout(void)
{ {
if (fflush(stdout)) { if (fflush(stdout)) {
@ -202,24 +208,25 @@ void xfflush_stdout(void)
#endif #endif
#ifdef L_spawn #ifdef L_spawn
// This does a fork/exec in one call, using vfork(). Return PID of new child, /* This does a fork/exec in one call, using vfork(). Return PID of new child,
// -1 for failure. Runs argv[0], searching path if that has no / in it. * -1 for failure. Runs argv[0], searching path if that has no / in it.
*/
pid_t spawn(char **argv) pid_t spawn(char **argv)
{ {
static int failed; static int failed;
pid_t pid; pid_t pid;
void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0; void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0;
// Be nice to nommu machines. /* Be nice to nommu machines. */
failed = 0; failed = 0;
pid = vfork(); pid = vfork();
if (pid < 0) return pid; if (pid < 0) return pid;
if (!pid) { if (!pid) {
execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv); execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);
// We're sharing a stack with blocked parent, let parent know we failed /* We're sharing a stack with blocked parent, let parent know we failed
// and then exit to unblock parent (but don't run atexit() stuff, which * and then exit to unblock parent (but don't run atexit() stuff, which
// would screw up parent.) would screw up parent.) */
failed = -1; failed = -1;
_exit(0); _exit(0);
@ -229,7 +236,7 @@ pid_t spawn(char **argv)
#endif #endif
#ifdef L_xspawn #ifdef L_xspawn
// Die with an error message if we can't spawn a child process. /* Die with an error message if we can't spawn a child process. */
pid_t xspawn(char **argv) pid_t xspawn(char **argv)
{ {
pid_t pid = spawn(argv); pid_t pid = spawn(argv);
@ -239,7 +246,7 @@ pid_t xspawn(char **argv)
#endif #endif
#ifdef L_wait4 #ifdef L_wait4
// Wait for the specified child PID to exit, returning child's error return. /* Wait for the specified child PID to exit, returning child's error return. */
int wait4pid(int pid) int wait4pid(int pid)
{ {
int status; int status;
@ -252,9 +259,9 @@ int wait4pid(int pid)
#endif #endif
#ifdef L_itoa #ifdef L_itoa
// Convert unsigned integer to ascii, writing into supplied buffer. A /* Convert unsigned integer to ascii, writing into supplied buffer. A
// truncated result is always null terminated (unless buflen is 0), and * truncated result is always null terminated (unless buflen is 0), and
// contains the first few digits of the result ala strncpy. * contains the first few digits of the result ala strncpy. */
void utoa_to_buf(unsigned n, char *buf, unsigned buflen) void utoa_to_buf(unsigned n, char *buf, unsigned buflen)
{ {
int i, out = 0; int i, out = 0;
@ -272,7 +279,7 @@ void utoa_to_buf(unsigned n, char *buf, unsigned buflen)
} }
} }
// Convert signed integer to ascii, like utoa_to_buf() /* Convert signed integer to ascii, like utoa_to_buf() */
void itoa_to_buf(int n, char *buf, unsigned buflen) void itoa_to_buf(int n, char *buf, unsigned buflen)
{ {
if (buflen && n<0) { if (buflen && n<0) {
@ -283,16 +290,16 @@ void itoa_to_buf(int n, char *buf, unsigned buflen)
utoa_to_buf((unsigned)n, buf, buflen); utoa_to_buf((unsigned)n, buf, buflen);
} }
// The following two functions use a static buffer, so calling either one a /* The following two functions use a static buffer, so calling either one a
// second time will overwrite previous results. * second time will overwrite previous results.
// *
// The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes. * The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
// Int should always be 32 bits on any remotely Unix-like system, see * Int should always be 32 bits on any remotely Unix-like system, see
// http://www.unix.org/whitepapers/64bit.html for the reasons why. * http://www.unix.org/whitepapers/64bit.html for the reasons why.
*/
static char local_buf[12]; static char local_buf[12];
// Convert unsigned integer to ascii using a static buffer (returned). /* Convert unsigned integer to ascii using a static buffer (returned). */
char *utoa(unsigned n) char *utoa(unsigned n)
{ {
utoa_to_buf(n, local_buf, sizeof(local_buf)); utoa_to_buf(n, local_buf, sizeof(local_buf));
@ -300,7 +307,7 @@ char *utoa(unsigned n)
return local_buf; return local_buf;
} }
// Convert signed integer to ascii using a static buffer (returned). /* Convert signed integer to ascii using a static buffer (returned). */
char *itoa(int n) char *itoa(int n)
{ {
itoa_to_buf(n, local_buf, sizeof(local_buf)); itoa_to_buf(n, local_buf, sizeof(local_buf));
@ -310,15 +317,15 @@ char *itoa(int n)
#endif #endif
#ifdef L_setuid #ifdef L_setuid
// Die with an error message if we can't set gid. (Because resource limits may /* Die with an error message if we can't set gid. (Because resource limits may
// limit this user to a given number of processes, and if that fills up the * limit this user to a given number of processes, and if that fills up the
// setgid() will fail and we'll _still_be_root_, which is bad.) * setgid() will fail and we'll _still_be_root_, which is bad.) */
void xsetgid(gid_t gid) void xsetgid(gid_t gid)
{ {
if (setgid(gid)) bb_error_msg_and_die("setgid"); if (setgid(gid)) bb_error_msg_and_die("setgid");
} }
// Die with an error message if we cant' set uid. (See xsetgid() for why.) /* Die with an error message if we cant' set uid. (See xsetgid() for why.) */
void xsetuid(uid_t uid) void xsetuid(uid_t uid)
{ {
if (setuid(uid)) bb_error_msg_and_die("setuid"); if (setuid(uid)) bb_error_msg_and_die("setuid");
@ -326,31 +333,31 @@ void xsetuid(uid_t uid)
#endif #endif
#ifdef L_fdlength #ifdef L_fdlength
// Return how long the file at fd is, if there's any way to determine it. /* Return how long the file at fd is, if there's any way to determine it. */
off_t fdlength(int fd) off_t fdlength(int fd)
{ {
off_t bottom = 0, top = 0, pos; off_t bottom = 0, top = 0, pos;
long size; long size;
// If the ioctl works for this, return it. /* If the ioctl works for this, return it. */
if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512; if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
// If not, do a binary search for the last location we can read. (Some /* If not, do a binary search for the last location we can read. (Some
// block devices don't do BLKGETSIZE right.) * block devices don't do BLKGETSIZE right.) */
do { do {
char temp; char temp;
pos = bottom + (top - bottom) / 2;; pos = bottom + (top - bottom) / 2;;
// If we can read from the current location, it's bigger. /* If we can read from the current location, it's bigger. */
if (lseek(fd, pos, 0)>=0 && safe_read(fd, &temp, 1)==1) { if (lseek(fd, pos, 0)>=0 && safe_read(fd, &temp, 1)==1) {
if (bottom == top) bottom = top = (top+1) * 2; if (bottom == top) bottom = top = (top+1) * 2;
else bottom = pos; else bottom = pos;
// If we can't, it's smaller. /* If we can't, it's smaller. */
} else { } else {
if (bottom == top) { if (bottom == top) {
@ -366,8 +373,8 @@ off_t fdlength(int fd)
#endif #endif
#ifdef L_xasprintf #ifdef L_xasprintf
// Die with an error message if we can't malloc() enough space and do an /* Die with an error message if we can't malloc() enough space and do an
// sprintf() into that space. * sprintf() into that space. */
char *xasprintf(const char *format, ...) char *xasprintf(const char *format, ...)
{ {
va_list p; va_list p;
@ -396,8 +403,8 @@ char *xasprintf(const char *format, ...)
#endif #endif
#ifdef L_xprint_and_close_file #ifdef L_xprint_and_close_file
// Die with an error message if we can't copy an entire FILE * to stdout, then /* Die with an error message if we can't copy an entire FILE * to stdout, then
// close that file. * close that file. */
void xprint_and_close_file(FILE *file) void xprint_and_close_file(FILE *file)
{ {
// copyfd outputs error messages for us. // copyfd outputs error messages for us.
@ -408,7 +415,7 @@ void xprint_and_close_file(FILE *file)
#endif #endif
#ifdef L_xchdir #ifdef L_xchdir
// Die if we can't chdir to a new path. /* Die if we can't chdir to a new path. */
void xchdir(const char *path) void xchdir(const char *path)
{ {
if (chdir(path)) if (chdir(path))
@ -417,7 +424,7 @@ void xchdir(const char *path)
#endif #endif
#ifdef L_warn_opendir #ifdef L_warn_opendir
// Print a warning message if opendir() fails, but don't die. /* Print a warning message if opendir() fails, but don't die. */
DIR *warn_opendir(const char *path) DIR *warn_opendir(const char *path)
{ {
DIR *dp; DIR *dp;
@ -431,7 +438,7 @@ DIR *warn_opendir(const char *path)
#endif #endif
#ifdef L_xopendir #ifdef L_xopendir
// Die with an error message if opendir() fails. /* Die with an error message if opendir() fails. */
DIR *xopendir(const char *path) DIR *xopendir(const char *path)
{ {
DIR *dp; DIR *dp;
@ -444,7 +451,7 @@ DIR *xopendir(const char *path)
#ifdef L_xdaemon #ifdef L_xdaemon
#ifndef BB_NOMMU #ifndef BB_NOMMU
// Die with an error message if we can't daemonize. /* Die with an error message if we can't daemonize. */
void xdaemon(int nochdir, int noclose) void xdaemon(int nochdir, int noclose)
{ {
if (daemon(nochdir, noclose)) bb_perror_msg_and_die("daemon"); if (daemon(nochdir, noclose)) bb_perror_msg_and_die("daemon");
@ -453,7 +460,7 @@ void xdaemon(int nochdir, int noclose)
#endif #endif
#ifdef L_xsocket #ifdef L_xsocket
// Die with an error message if we can't open a new socket. /* Die with an error message if we can't open a new socket. */
int xsocket(int domain, int type, int protocol) int xsocket(int domain, int type, int protocol)
{ {
int r = socket(domain, type, protocol); int r = socket(domain, type, protocol);
@ -465,7 +472,7 @@ int xsocket(int domain, int type, int protocol)
#endif #endif
#ifdef L_xbind #ifdef L_xbind
// Die with an error message if we can't bind a socket to an address. /* Die with an error message if we can't bind a socket to an address. */
void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
{ {
if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind"); 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)
#endif #endif
#ifdef L_xlisten #ifdef L_xlisten
// Die with an error message if we can't listen for connections on a socket. /* Die with an error message if we can't listen for connections on a socket. */
void xlisten(int s, int backlog) void xlisten(int s, int backlog)
{ {
if (listen(s, backlog)) bb_perror_msg_and_die("listen"); if (listen(s, backlog)) bb_perror_msg_and_die("listen");

View File

@ -49,6 +49,7 @@ find $srcdir/../ \
-e '\<algorithic\>' \ -e '\<algorithic\>' \
-e '\<deamon\>' \ -e '\<deamon\>' \
-e '\<derefernce\>' \ -e '\<derefernce\>' \
-e '\<acomadate\>' \
| sed -e "s:^$srcdir/\.\./::g" > src.typos | sed -e "s:^$srcdir/\.\./::g" > src.typos
testing "Common typos" "cat src.typos" "" "" "" testing "Common typos" "cat src.typos" "" "" ""
rm -f src.typos rm -f src.typos

View File

@ -1,56 +1,22 @@
/* vi: set sw=4 ts=4: */ /* vi: set sw=4 ts=4: */
/* /*
* ipcrm.c -- utility to allow removal of IPC objects and data structures. * ipcrm.c - utility to allow removal of IPC objects and data structures.
* *
* 01 Sept 2004 - Rodney Radford <rradford@mindspring.com> * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
* Adapted for busybox from util-linux-2.12a. * Adapted for busybox from util-linux-2.12a.
* *
* This program is free software; you can redistribute it and/or modify * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* --- Pre-busybox history from util-linux-2.12a ------------------------
*
* 1999-04-02 frank zago
* - can now remove several id's in the same call
*
* 1999-02-22 Arkadiusz Miÿkiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
*
* Original author - krishna balasubramanian 1993
*/ */
#include <stdio.h> #include "busybox.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h> /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
#include <sys/msg.h> #include <sys/msg.h>
#include <sys/sem.h> #include <sys/sem.h>
/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
/* for getopt */
#include <unistd.h>
/* for tolower and isupper */
#include <ctype.h>
#include "busybox.h"
#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) #if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */ /* union semun is defined by including <sys/sem.h> */
#else #else
@ -63,164 +29,149 @@ union semun {
}; };
#endif #endif
#ifndef CONFIG_IPCRM_DROP_LEGACY
typedef enum type_id { typedef enum type_id {
SHM, SHM,
SEM, SEM,
MSG MSG
} type_id; } type_id;
static int static int remove_ids(type_id type, int argc, char **argv)
remove_ids(type_id type, int argc, char **argv) { {
int id; int id;
int ret = 0; /* for gcc */ int ret = 0; /* silence gcc */
char *end; char *end;
int nb_errors = 0; int nb_errors = 0;
union semun arg; union semun arg;
arg.val = 0; arg.val = 0;
while(argc) { while (argc) {
id = strtoul(argv[0], &end, 10); id = strtoul(argv[0], &end, 10);
if (*end != 0) { if (*end != 0) {
bb_printf ("invalid id: %s\n", argv[0]); bb_error_msg("invalid id: %s", argv[0]);
nb_errors ++; nb_errors++;
} else { } else {
switch(type) { if (type == SEM)
case SEM: ret = semctl(id, 0, IPC_RMID, arg);
ret = semctl (id, 0, IPC_RMID, arg); else if (type == MSG)
break; ret = msgctl(id, IPC_RMID, NULL);
else if (type == SHM)
case MSG: ret = shmctl(id, IPC_RMID, NULL);
ret = msgctl (id, IPC_RMID, NULL);
break;
case SHM:
ret = shmctl (id, IPC_RMID, NULL);
break;
}
if (ret) { if (ret) {
bb_printf ("cannot remove id %s (%s)\n", bb_perror_msg("cannot remove id %s", argv[0]);
argv[0], strerror(errno)); nb_errors++;
nb_errors ++;
} }
} }
argc--; argc--;
argv++; argv++;
} }
return(nb_errors); return (nb_errors);
}
static int deprecated_main(int argc, char **argv)
{
if (argc < 3) {
bb_show_usage();
bb_fflush_stdout_and_exit(1);
}
if (!strcmp(argv[1], "shm")) {
if (remove_ids(SHM, argc-2, &argv[2]))
bb_fflush_stdout_and_exit(1);
}
else if (!strcmp(argv[1], "msg")) {
if (remove_ids(MSG, argc-2, &argv[2]))
bb_fflush_stdout_and_exit(1);
}
else if (!strcmp(argv[1], "sem")) {
if (remove_ids(SEM, argc-2, &argv[2]))
bb_fflush_stdout_and_exit(1);
}
else {
bb_printf ("unknown resource type: %s\n", argv[1]);
bb_show_usage();
bb_fflush_stdout_and_exit(1);
}
bb_printf ("resource(s) deleted\n");
return 0;
} }
#endif /* #ifndef CONFIG_IPCRM_DROP_LEGACY */
int ipcrm_main(int argc, char **argv) int ipcrm_main(int argc, char **argv)
{ {
int c; int c;
int error = 0; int error = 0;
char *prog = argv[0];
/* if the command is executed without parameters, do nothing */ /* if the command is executed without parameters, do nothing */
if (argc == 1) if (argc == 1)
return 0; return 0;
#ifndef CONFIG_IPCRM_DROP_LEGACY
/* check to see if the command is being invoked in the old way if so /* check to see if the command is being invoked in the old way if so
then run the old code */ then run the old code. Valid commands are msg, shm, sem. */
if (strcmp(argv[1], "shm") == 0 || {
strcmp(argv[1], "msg") == 0 || type_id what = 0; /* silence gcc */
strcmp(argv[1], "sem") == 0) char w;
return deprecated_main(argc, argv);
if ((((w=argv[1][0]) == 'm' && argv[1][1] == 's' && argv[1][2] == 'g')
|| (argv[1][0] == 's'
&& ((w=argv[1][1]) == 'h' || w == 'e')
&& argv[1][2] == 'm'))
&& argv[1][3] == '\0') {
if (argc < 3)
bb_show_usage();
if (w == 'h')
what = SHM;
else if (w == 'm')
what = MSG;
else if (w == 'e')
what = SEM;
if (remove_ids(what, argc-2, &argv[2]))
bb_fflush_stdout_and_exit(1);
bb_printf("resource(s) deleted\n");
return 0;
}
}
#endif /* #ifndef CONFIG_IPCRM_DROP_LEGACY */
/* process new syntax to conform with SYSV ipcrm */ /* process new syntax to conform with SYSV ipcrm */
while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) { while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) {
int result; int result;
int id = 0; int id = 0;
int iskey = isupper(c); int iskey = (isupper)(c);
/* needed to delete semaphores */ /* needed to delete semaphores */
union semun arg; union semun arg;
arg.val = 0; arg.val = 0;
if ((c == '?') || (c == 'h')) if ((c == '?') || (c == 'h')) {
{
bb_show_usage(); bb_show_usage();
return 0;
} }
/* we don't need case information any more */ /* we don't need case information any more */
c = tolower(c); c = tolower(c);
/* make sure the option is in range */ /* make sure the option is in range: allowed are q, m, s */
if (c != 'q' && c != 'm' && c != 's') { if (c != 'q' && c != 'm' && c != 's') {
bb_show_usage(); bb_show_usage();
error++;
return error;
} }
if (iskey) { if (iskey) {
/* keys are in hex or decimal */ /* keys are in hex or decimal */
key_t key = strtoul(optarg, NULL, 0); key_t key = strtoul(optarg, NULL, 0);
if (key == IPC_PRIVATE) { if (key == IPC_PRIVATE) {
error++; error++;
bb_fprintf(stderr, "%s: illegal key (%s)\n", bb_error_msg("illegal key (%s)", optarg);
prog, optarg);
continue; continue;
} }
/* convert key to id */ /* convert key to id */
id = ((c == 'q') ? msgget(key, 0) : id = ((c == 'q') ? msgget(key, 0) :
(c == 'm') ? shmget(key, 0, 0) : (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
semget(key, 0, 0));
if (id < 0) { if (id < 0) {
char *errmsg; char *errmsg;
const char * const what = "key";
error++; error++;
switch(errno) { switch (errno) {
case EACCES: case EACCES:
errmsg = "permission denied for key"; errmsg = "permission denied for";
break; break;
case EIDRM: case EIDRM:
errmsg = "already removed key"; errmsg = "already removed";
break; break;
case ENOENT: case ENOENT:
errmsg = "invalid key"; errmsg = "invalid";
break; break;
default: default:
errmsg = "unknown error in key"; errmsg = "unknown error in";
break; break;
} }
bb_fprintf(stderr, "%s: %s (%s)\n", bb_error_msg("%s %s (%s)", errmsg, what, optarg);
prog, errmsg, optarg);
continue; continue;
} }
} else { } else {
@ -229,37 +180,30 @@ int ipcrm_main(int argc, char **argv)
} }
result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) : result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
(c == 'm') ? shmctl(id, IPC_RMID, NULL) : (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
semctl(id, 0, IPC_RMID, arg)); semctl(id, 0, IPC_RMID, arg));
if (result < 0) { if (result) {
char *errmsg; char *errmsg;
const char * const what = iskey ? "key" : "id";
error++; error++;
switch(errno) { switch (errno) {
case EACCES: case EACCES:
case EPERM: case EPERM:
errmsg = iskey errmsg = "permission denied for";
? "permission denied for key"
: "permission denied for id";
break; break;
case EINVAL: case EINVAL:
errmsg = iskey errmsg = "invalid";
? "invalid key"
: "invalid id";
break; break;
case EIDRM: case EIDRM:
errmsg = iskey errmsg = "already removed";
? "already removed key"
: "already removed id";
break; break;
default: default:
errmsg = iskey errmsg = "unknown error in";
? "unknown error in key"
: "unknown error in id";
break; break;
} }
bb_fprintf(stderr, "%s: %s (%s)\n", bb_error_msg("%s %s (%s)", errmsg, what, optarg);
prog, errmsg, optarg);
continue; continue;
} }
} }

View File

@ -8,9 +8,7 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/ */
#include <stdio.h> #include "busybox.h"
#include <stdlib.h>
#include <getopt.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#include <pwd.h> #include <pwd.h>
@ -25,15 +23,15 @@
#include <sys/msg.h> #include <sys/msg.h>
#include <sys/shm.h> #include <sys/shm.h>
#include "busybox.h"
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
/* SHM_DEST and SHM_LOCKED are defined in kernel headers, /* SHM_DEST and SHM_LOCKED are defined in kernel headers,
but inside #ifdef __KERNEL__ ... #endif */ but inside #ifdef __KERNEL__ ... #endif */
#ifndef SHM_DEST #ifndef SHM_DEST
/* shm_mode upper byte flags */ /* shm_mode upper byte flags */
#define SHM_DEST 01000 /* segment will be destroyed on last detach */ #define SHM_DEST 01000 /* segment will be destroyed on last detach */
#define SHM_LOCKED 02000 /* segment will not be swapped */ #define SHM_LOCKED 02000 /* segment will not be swapped */
#endif #endif
/* For older kernels the same holds for the defines below */ /* For older kernels the same holds for the defines below */
@ -46,12 +44,12 @@
#define SHM_STAT 13 #define SHM_STAT 13
#define SHM_INFO 14 #define SHM_INFO 14
struct shm_info { struct shm_info {
int used_ids; int used_ids;
ulong shm_tot; /* total allocated shm */ ulong shm_tot; /* total allocated shm */
ulong shm_rss; /* total resident shm */ ulong shm_rss; /* total resident shm */
ulong shm_swp; /* total swapped shm */ ulong shm_swp; /* total swapped shm */
ulong swap_attempts; ulong swap_attempts;
ulong swap_successes; ulong swap_successes;
}; };
#endif #endif
@ -98,12 +96,14 @@ union semun {
#define TIME 4 #define TIME 4
#define PID 5 #define PID 5
static char format;
static void print_perms (int id, struct ipc_perm *ipcp) { static void print_perms(int id, struct ipc_perm *ipcp)
{
struct passwd *pw; struct passwd *pw;
struct group *gr; struct group *gr;
bb_printf ("%-10d %-10o", id, ipcp->mode & 0777); bb_printf("%-10d %-10o", id, ipcp->mode & 0777);
if ((pw = getpwuid(ipcp->cuid))) if ((pw = getpwuid(ipcp->cuid)))
bb_printf(" %-10s", pw->pw_name); bb_printf(" %-10s", pw->pw_name);
@ -125,7 +125,7 @@ static void print_perms (int id, struct ipc_perm *ipcp) {
} }
static void do_shm (char format) static void do_shm(void)
{ {
int maxid, shmid, id; int maxid, shmid, id;
struct shmid_ds shmseg; struct shmid_ds shmseg;
@ -134,127 +134,125 @@ static void do_shm (char format)
struct ipc_perm *ipcp = &shmseg.shm_perm; struct ipc_perm *ipcp = &shmseg.shm_perm;
struct passwd *pw; struct passwd *pw;
maxid = shmctl (0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info); maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
if (maxid < 0) { if (maxid < 0) {
bb_printf ("kernel not configured for shared memory\n"); bb_printf("kernel not configured for shared memory\n");
return; return;
} }
switch (format) { switch (format) {
case LIMITS: case LIMITS:
bb_printf ("------ Shared Memory Limits --------\n"); bb_printf("------ Shared Memory Limits --------\n");
if ((shmctl (0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0 ) if ((shmctl(0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0)
return; return;
/* glibc 2.1.3 and all earlier libc's have ints as fields /* glibc 2.1.3 and all earlier libc's have ints as fields
of struct shminfo; glibc 2.1.91 has unsigned long; ach */ of struct shminfo; glibc 2.1.91 has unsigned long; ach */
bb_printf ("max number of segments = %lu\n" bb_printf("max number of segments = %lu\n"
"max seg size (kbytes) = %lu\n" "max seg size (kbytes) = %lu\n"
"max total shared memory (pages) = %lu\n" "max total shared memory (pages) = %lu\n"
"min seg size (bytes) = %lu\n", "min seg size (bytes) = %lu\n",
(unsigned long) shminfo.shmmni, (unsigned long) shminfo.shmmni,
(unsigned long) (shminfo.shmmax >> 10), (unsigned long) (shminfo.shmmax >> 10),
(unsigned long) shminfo.shmall, (unsigned long) shminfo.shmall,
(unsigned long) shminfo.shmmin); (unsigned long) shminfo.shmmin);
return; return;
case STATUS: case STATUS:
bb_printf ("------ Shared Memory Status --------\n" bb_printf("------ Shared Memory Status --------\n"
"segments allocated %d\n" "segments allocated %d\n"
"pages allocated %ld\n" "pages allocated %ld\n"
"pages resident %ld\n" "pages resident %ld\n"
"pages swapped %ld\n" "pages swapped %ld\n"
"Swap performance: %ld attempts\t %ld successes\n", "Swap performance: %ld attempts\t %ld successes\n",
shm_info.used_ids, shm_info.used_ids,
shm_info.shm_tot, shm_info.shm_tot,
shm_info.shm_rss, shm_info.shm_rss,
shm_info.shm_swp, shm_info.shm_swp,
shm_info.swap_attempts, shm_info.swap_successes); shm_info.swap_attempts, shm_info.swap_successes);
return; return;
case CREATOR: case CREATOR:
bb_printf ("------ Shared Memory Segment Creators/Owners --------\n" bb_printf("------ Shared Memory Segment Creators/Owners --------\n"
"%-10s %-10s %-10s %-10s %-10s %-10s\n", "%-10s %-10s %-10s %-10s %-10s %-10s\n",
"shmid","perms","cuid","cgid","uid","gid"); "shmid", "perms", "cuid", "cgid", "uid", "gid");
break; break;
case TIME: case TIME:
bb_printf ("------ Shared Memory Attach/Detach/Change Times --------\n" bb_printf("------ Shared Memory Attach/Detach/Change Times --------\n"
"%-10s %-10s %-20s %-20s %-20s\n", "%-10s %-10s %-20s %-20s %-20s\n",
"shmid","owner","attached","detached","changed"); "shmid", "owner", "attached", "detached", "changed");
break; break;
case PID: case PID:
bb_printf ("------ Shared Memory Creator/Last-op --------\n" bb_printf("------ Shared Memory Creator/Last-op --------\n"
"%-10s %-10s %-10s %-10s\n", "%-10s %-10s %-10s %-10s\n",
"shmid","owner","cpid","lpid"); "shmid", "owner", "cpid", "lpid");
break; break;
default: default:
bb_printf ("------ Shared Memory Segments --------\n" bb_printf("------ Shared Memory Segments --------\n"
"%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n", "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
"key","shmid","owner","perms","bytes","nattch","status"); "key", "shmid", "owner", "perms", "bytes", "nattch",
"status");
break; break;
} }
for (id = 0; id <= maxid; id++) { for (id = 0; id <= maxid; id++) {
shmid = shmctl (id, SHM_STAT, &shmseg); shmid = shmctl(id, SHM_STAT, &shmseg);
if (shmid < 0) if (shmid < 0)
continue; continue;
if (format == CREATOR) { if (format == CREATOR) {
print_perms (shmid, ipcp); print_perms(shmid, ipcp);
continue; continue;
} }
pw = getpwuid(ipcp->uid); pw = getpwuid(ipcp->uid);
switch (format) { switch (format) {
case TIME: case TIME:
if (pw) if (pw)
bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); bb_printf("%-10d %-10.10s", shmid, pw->pw_name);
else else
bb_printf ("%-10d %-10d", shmid, ipcp->uid); bb_printf("%-10d %-10d", shmid, ipcp->uid);
/* ctime uses static buffer: use separate calls */ /* ctime uses static buffer: use separate calls */
bb_printf(" %-20.16s", shmseg.shm_atime bb_printf(" %-20.16s", shmseg.shm_atime
? ctime(&shmseg.shm_atime) + 4 : "Not set"); ? ctime(&shmseg.shm_atime) + 4 : "Not set");
bb_printf(" %-20.16s", shmseg.shm_dtime bb_printf(" %-20.16s", shmseg.shm_dtime
? ctime(&shmseg.shm_dtime) + 4 : "Not set"); ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
bb_printf(" %-20.16s\n", shmseg.shm_ctime bb_printf(" %-20.16s\n", shmseg.shm_ctime
? ctime(&shmseg.shm_ctime) + 4 : "Not set"); ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
break; break;
case PID: case PID:
if (pw) if (pw)
bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); bb_printf("%-10d %-10.10s", shmid, pw->pw_name);
else else
bb_printf ("%-10d %-10d", shmid, ipcp->uid); bb_printf("%-10d %-10d", shmid, ipcp->uid);
bb_printf (" %-10d %-10d\n", bb_printf(" %-10d %-10d\n", shmseg.shm_cpid, shmseg.shm_lpid);
shmseg.shm_cpid, shmseg.shm_lpid);
break; break;
default: default:
bb_printf("0x%08x ",ipcp->KEY ); bb_printf("0x%08x ", ipcp->KEY);
if (pw) if (pw)
bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); bb_printf("%-10d %-10.10s", shmid, pw->pw_name);
else else
bb_printf ("%-10d %-10d", shmid, ipcp->uid); bb_printf("%-10d %-10d", shmid, ipcp->uid);
bb_printf ("%-10o %-10lu %-10ld %-6s %-6s\n", bb_printf("%-10o %-10lu %-10ld %-6s %-6s\n", ipcp->mode & 0777,
ipcp->mode & 0777, /*
/* * earlier: int, Austin has size_t
* earlier: int, Austin has size_t */
*/ (unsigned long) shmseg.shm_segsz,
(unsigned long) shmseg.shm_segsz, /*
/* * glibc-2.1.3 and earlier has unsigned short;
* glibc-2.1.3 and earlier has unsigned short; * Austin has shmatt_t
* Austin has shmatt_t */
*/ (long) shmseg.shm_nattch,
(long) shmseg.shm_nattch, ipcp->mode & SHM_DEST ? "dest" : " ",
ipcp->mode & SHM_DEST ? "dest" : " ", ipcp->mode & SHM_LOCKED ? "locked" : " ");
ipcp->mode & SHM_LOCKED ? "locked" : " ");
break; break;
} }
} }
return;
} }
static void do_sem (char format) static void do_sem(void)
{ {
int maxid, semid, id; int maxid, semid, id;
struct semid_ds semary; struct semid_ds semary;
@ -263,107 +261,104 @@ static void do_sem (char format)
struct passwd *pw; struct passwd *pw;
union semun arg; union semun arg;
arg.array = (ushort *) (void *) &seminfo; arg.array = (ushort *) (void *) &seminfo;
maxid = semctl (0, 0, SEM_INFO, arg); maxid = semctl(0, 0, SEM_INFO, arg);
if (maxid < 0) { if (maxid < 0) {
bb_printf ("kernel not configured for semaphores\n"); bb_printf("kernel not configured for semaphores\n");
return; return;
} }
switch (format) { switch (format) {
case LIMITS: case LIMITS:
bb_printf ("------ Semaphore Limits --------\n"); bb_printf("------ Semaphore Limits --------\n");
arg.array = (ushort *) (void *) &seminfo; /* damn union */ arg.array = (ushort *) (void *) &seminfo; /* damn union */
if ((semctl (0, 0, IPC_INFO, arg)) < 0 ) if ((semctl(0, 0, IPC_INFO, arg)) < 0)
return; return;
bb_printf ("max number of arrays = %d\n" bb_printf("max number of arrays = %d\n"
"max semaphores per array = %d\n" "max semaphores per array = %d\n"
"max semaphores system wide = %d\n" "max semaphores system wide = %d\n"
"max ops per semop call = %d\n" "max ops per semop call = %d\n"
"semaphore max value = %d\n", "semaphore max value = %d\n",
seminfo.semmni, seminfo.semmni,
seminfo.semmsl, seminfo.semmsl,
seminfo.semmns, seminfo.semmns, seminfo.semopm, seminfo.semvmx);
seminfo.semopm,
seminfo.semvmx);
return; return;
case STATUS: case STATUS:
bb_printf ("------ Semaphore Status --------\n" bb_printf("------ Semaphore Status --------\n"
"used arrays = %d\n" "used arrays = %d\n"
"allocated semaphores = %d\n", "allocated semaphores = %d\n",
seminfo.semusz, seminfo.semusz, seminfo.semaem);
seminfo.semaem);
return; return;
case CREATOR: case CREATOR:
bb_printf ("------ Semaphore Arrays Creators/Owners --------\n" bb_printf("------ Semaphore Arrays Creators/Owners --------\n"
"%-10s %-10s %-10s %-10s %-10s %-10s\n", "%-10s %-10s %-10s %-10s %-10s %-10s\n",
"semid","perms","cuid","cgid","uid","gid"); "semid", "perms", "cuid", "cgid", "uid", "gid");
break; break;
case TIME: case TIME:
bb_printf ("------ Shared Memory Operation/Change Times --------\n" bb_printf("------ Shared Memory Operation/Change Times --------\n"
"%-8s %-10s %-26.24s %-26.24s\n", "%-8s %-10s %-26.24s %-26.24s\n",
"shmid","owner","last-op","last-changed"); "shmid", "owner", "last-op", "last-changed");
break; break;
case PID: case PID:
break; break;
default: default:
bb_printf ("------ Semaphore Arrays --------\n" bb_printf("------ Semaphore Arrays --------\n"
"%-10s %-10s %-10s %-10s %-10s\n", "%-10s %-10s %-10s %-10s %-10s\n",
"key","semid","owner","perms","nsems"); "key", "semid", "owner", "perms", "nsems");
break; break;
} }
for (id = 0; id <= maxid; id++) { for (id = 0; id <= maxid; id++) {
arg.buf = (struct semid_ds *) &semary; arg.buf = (struct semid_ds *) &semary;
semid = semctl (id, 0, SEM_STAT, arg); semid = semctl(id, 0, SEM_STAT, arg);
if (semid < 0) if (semid < 0)
continue; continue;
if (format == CREATOR) { if (format == CREATOR) {
print_perms (semid, ipcp); print_perms(semid, ipcp);
continue; continue;
} }
pw = getpwuid(ipcp->uid); pw = getpwuid(ipcp->uid);
switch (format) { switch (format) {
case TIME: case TIME:
if (pw) if (pw)
bb_printf ("%-8d %-10.10s", semid, pw->pw_name); bb_printf("%-8d %-10.10s", semid, pw->pw_name);
else else
bb_printf ("%-8d %-10d", semid, ipcp->uid); bb_printf("%-8d %-10d", semid, ipcp->uid);
bb_printf (" %-26.24s", semary.sem_otime /* ctime uses static buffer: use separate calls */
? ctime(&semary.sem_otime) : "Not set"); bb_printf(" %-26.24s", semary.sem_otime
bb_printf (" %-26.24s\n", semary.sem_ctime ? ctime(&semary.sem_otime) : "Not set");
? ctime(&semary.sem_ctime) : "Not set"); bb_printf(" %-26.24s\n", semary.sem_ctime
? ctime(&semary.sem_ctime) : "Not set");
break; break;
case PID: case PID:
break; break;
default: default:
bb_printf("0x%08x ", ipcp->KEY); bb_printf("0x%08x ", ipcp->KEY);
if (pw) if (pw)
bb_printf ("%-10d %-10.9s", semid, pw->pw_name); bb_printf("%-10d %-10.9s", semid, pw->pw_name);
else else
bb_printf ("%-10d %-9d", semid, ipcp->uid); bb_printf("%-10d %-9d", semid, ipcp->uid);
bb_printf ("%-10o %-10ld\n", bb_printf("%-10o %-10ld\n", ipcp->mode & 0777,
ipcp->mode & 0777, /*
/* * glibc-2.1.3 and earlier has unsigned short;
* glibc-2.1.3 and earlier has unsigned short; * glibc-2.1.91 has variation between
* glibc-2.1.91 has variation between * unsigned short and unsigned long
* unsigned short and unsigned long * Austin prescribes unsigned short.
* Austin prescribes unsigned short. */
*/ (long) semary.sem_nsems);
(long) semary.sem_nsems);
break; break;
} }
} }
} }
static void do_msg (char format) static void do_msg(void)
{ {
int maxid, msqid, id; int maxid, msqid, id;
struct msqid_ds msgque; struct msqid_ds msgque;
@ -371,178 +366,165 @@ static void do_msg (char format)
struct ipc_perm *ipcp = &msgque.msg_perm; struct ipc_perm *ipcp = &msgque.msg_perm;
struct passwd *pw; struct passwd *pw;
maxid = msgctl (0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo); maxid = msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
if (maxid < 0) { if (maxid < 0) {
bb_printf ("kernel not configured for message queues\n"); bb_printf("kernel not configured for message queues\n");
return; return;
} }
switch (format) { switch (format) {
case LIMITS: case LIMITS:
if ((msgctl (0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0 ) if ((msgctl(0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0)
return; return;
bb_printf ("------ Messages: Limits --------\n" bb_printf("------ Messages: Limits --------\n"
"max queues system wide = %d\n" "max queues system wide = %d\n"
"max size of message (bytes) = %d\n" "max size of message (bytes) = %d\n"
"default max size of queue (bytes) = %d\n", "default max size of queue (bytes) = %d\n",
msginfo.msgmni, msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb);
msginfo.msgmax,
msginfo.msgmnb);
return; return;
case STATUS: case STATUS:
bb_printf ("------ Messages: Status --------\n" bb_printf("------ Messages: Status --------\n"
"allocated queues = %d\n" "allocated queues = %d\n"
"used headers = %d\n" "used headers = %d\n"
"used space = %d bytes\n", "used space = %d bytes\n",
msginfo.msgpool, msginfo.msgpool, msginfo.msgmap, msginfo.msgtql);
msginfo.msgmap,
msginfo.msgtql);
return; return;
case CREATOR: case CREATOR:
bb_printf ("------ Message Queues: Creators/Owners --------\n" bb_printf("------ Message Queues: Creators/Owners --------\n"
"%-10s %-10s %-10s %-10s %-10s %-10s\n", "%-10s %-10s %-10s %-10s %-10s %-10s\n",
"msqid","perms","cuid","cgid","uid","gid"); "msqid", "perms", "cuid", "cgid", "uid", "gid");
break; break;
case TIME: case TIME:
bb_printf ("------ Message Queues Send/Recv/Change Times --------\n" bb_printf("------ Message Queues Send/Recv/Change Times --------\n"
"%-8s %-10s %-20s %-20s %-20s\n", "%-8s %-10s %-20s %-20s %-20s\n",
"msqid","owner","send","recv","change"); "msqid", "owner", "send", "recv", "change");
break; break;
case PID: case PID:
bb_printf ("------ Message Queues PIDs --------\n" bb_printf("------ Message Queues PIDs --------\n"
"%-10s %-10s %-10s %-10s\n", "%-10s %-10s %-10s %-10s\n",
"msqid","owner","lspid","lrpid"); "msqid", "owner", "lspid", "lrpid");
break; break;
default: default:
bb_printf ("------ Message Queues --------\n" bb_printf("------ Message Queues --------\n"
"%-10s %-10s %-10s %-10s %-12s %-12s\n", "%-10s %-10s %-10s %-10s %-12s %-12s\n",
"key","msqid","owner","perms","used-bytes","messages"); "key", "msqid", "owner", "perms", "used-bytes", "messages");
break; break;
} }
for (id = 0; id <= maxid; id++) { for (id = 0; id <= maxid; id++) {
msqid = msgctl (id, MSG_STAT, &msgque); msqid = msgctl(id, MSG_STAT, &msgque);
if (msqid < 0) if (msqid < 0)
continue; continue;
if (format == CREATOR) { if (format == CREATOR) {
print_perms (msqid, ipcp); print_perms(msqid, ipcp);
continue; continue;
} }
pw = getpwuid(ipcp->uid); pw = getpwuid(ipcp->uid);
switch (format) { switch (format) {
case TIME: case TIME:
if (pw) if (pw)
bb_printf ("%-8d %-10.10s", msqid, pw->pw_name); bb_printf("%-8d %-10.10s", msqid, pw->pw_name);
else else
bb_printf ("%-8d %-10d", msqid, ipcp->uid); bb_printf("%-8d %-10d", msqid, ipcp->uid);
bb_printf (" %-20.16s", msgque.msg_stime bb_printf(" %-20.16s", msgque.msg_stime
? ctime(&msgque.msg_stime) + 4 : "Not set"); ? ctime(&msgque.msg_stime) + 4 : "Not set");
bb_printf (" %-20.16s", msgque.msg_rtime bb_printf(" %-20.16s", msgque.msg_rtime
? ctime(&msgque.msg_rtime) + 4 : "Not set"); ? ctime(&msgque.msg_rtime) + 4 : "Not set");
bb_printf (" %-20.16s\n", msgque.msg_ctime bb_printf(" %-20.16s\n", msgque.msg_ctime
? ctime(&msgque.msg_ctime) + 4 : "Not set"); ? ctime(&msgque.msg_ctime) + 4 : "Not set");
break; break;
case PID: case PID:
if (pw) if (pw)
bb_printf ("%-8d %-10.10s", msqid, pw->pw_name); bb_printf("%-8d %-10.10s", msqid, pw->pw_name);
else else
bb_printf ("%-8d %-10d", msqid, ipcp->uid); bb_printf("%-8d %-10d", msqid, ipcp->uid);
bb_printf (" %5d %5d\n", bb_printf(" %5d %5d\n", msgque.msg_lspid, msgque.msg_lrpid);
msgque.msg_lspid, msgque.msg_lrpid);
break; break;
default: default:
bb_printf( "0x%08x ",ipcp->KEY ); bb_printf("0x%08x ", ipcp->KEY);
if (pw) if (pw)
bb_printf ("%-10d %-10.10s", msqid, pw->pw_name); bb_printf("%-10d %-10.10s", msqid, pw->pw_name);
else else
bb_printf ("%-10d %-10d", msqid, ipcp->uid); bb_printf("%-10d %-10d", msqid, ipcp->uid);
bb_printf (" %-10o %-12ld %-12ld\n", bb_printf(" %-10o %-12ld %-12ld\n", ipcp->mode & 0777,
ipcp->mode & 0777, /*
/* * glibc-2.1.3 and earlier has unsigned short;
* glibc-2.1.3 and earlier has unsigned short; * glibc-2.1.91 has variation between
* glibc-2.1.91 has variation between * unsigned short, unsigned long
* unsigned short, unsigned long * Austin has msgqnum_t
* Austin has msgqnum_t */
*/ (long) msgque.msg_cbytes, (long) msgque.msg_qnum);
(long) msgque.msg_cbytes,
(long) msgque.msg_qnum);
break; break;
} }
} }
return;
} }
static void print_shm (int shmid) static void print_shm(int shmid)
{ {
struct shmid_ds shmds; struct shmid_ds shmds;
struct ipc_perm *ipcp = &shmds.shm_perm; struct ipc_perm *ipcp = &shmds.shm_perm;
if (shmctl (shmid, IPC_STAT, &shmds) == -1) { if (shmctl(shmid, IPC_STAT, &shmds) == -1) {
perror ("shmctl "); bb_perror_msg("shmctl");
return; return;
} }
bb_printf ("\nShared memory Segment shmid=%d\n" bb_printf("\nShared memory Segment shmid=%d\n"
"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n" "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
"mode=%#o\taccess_perms=%#o\n" "mode=%#o\taccess_perms=%#o\n"
"bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n" "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n",
"att_time=%-26.24s\n" shmid,
"det_time=%-26.24s\n" ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
"change_time=%-26.24s\n" ipcp->mode, ipcp->mode & 0777,
"\n", (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
shmid, (long) shmds.shm_nattch);
ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, bb_printf("att_time=%-26.24s\n",
ipcp->mode, ipcp->mode & 0777, shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set");
(long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid, bb_printf("det_time=%-26.24s\n",
(long) shmds.shm_nattch, shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set");
shmds.shm_atime ? ctime (&shmds.shm_atime) : "Not set", bb_printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime));
shmds.shm_dtime ? ctime (&shmds.shm_dtime) : "Not set",
ctime (&shmds.shm_ctime));
return;
} }
static void print_msg (int msqid) static void print_msg(int msqid)
{ {
struct msqid_ds buf; struct msqid_ds buf;
struct ipc_perm *ipcp = &buf.msg_perm; struct ipc_perm *ipcp = &buf.msg_perm;
if (msgctl (msqid, IPC_STAT, &buf) == -1) { if (msgctl(msqid, IPC_STAT, &buf) == -1) {
perror ("msgctl "); bb_perror_msg("msgctl");
return; return;
} }
bb_printf ("\nMessage Queue msqid=%d\n" bb_printf("\nMessage Queue msqid=%d\n"
"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n" "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
"cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n" "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n",
"send_time=%-26.24s\n" msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
"rcv_time=%-26.24s\n" /*
"change_time=%-26.24s\n" * glibc-2.1.3 and earlier has unsigned short;
"\n", * glibc-2.1.91 has variation between
msqid, * unsigned short, unsigned long
ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode, * Austin has msgqnum_t (for msg_qbytes)
/* */
* glibc-2.1.3 and earlier has unsigned short; (long) buf.msg_cbytes, (long) buf.msg_qbytes,
* glibc-2.1.91 has variation between (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);
* unsigned short, unsigned long
* Austin has msgqnum_t (for msg_qbytes) bb_printf("send_time=%-26.24s\n",
*/ buf.msg_stime ? ctime(&buf.msg_stime) : "Not set");
(long) buf.msg_cbytes, (long) buf.msg_qbytes, bb_printf("rcv_time=%-26.24s\n",
(long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid, buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set");
buf.msg_stime ? ctime (&buf.msg_stime) : "Not set", bb_printf("change_time=%-26.24s\n\n",
buf.msg_rtime ? ctime (&buf.msg_rtime) : "Not set", buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set");
buf.msg_ctime ? ctime (&buf.msg_ctime) : "Not set");
return;
} }
static void print_sem (int semid) static void print_sem(int semid)
{ {
struct semid_ds semds; struct semid_ds semds;
struct ipc_perm *ipcp = &semds.sem_perm; struct ipc_perm *ipcp = &semds.sem_perm;
@ -550,66 +532,69 @@ static void print_sem (int semid)
unsigned int i; unsigned int i;
arg.buf = &semds; arg.buf = &semds;
if (semctl (semid, 0, IPC_STAT, arg) < 0) { if (semctl(semid, 0, IPC_STAT, arg)) {
perror ("semctl "); bb_perror_msg("semctl");
return; return;
} }
bb_printf ("\nSemaphore Array semid=%d\n" bb_printf("\nSemaphore Array semid=%d\n"
"uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n" "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
"mode=%#o, access_perms=%#o\n" "mode=%#o, access_perms=%#o\n"
"nsems = %ld\n" "nsems = %ld\n"
"otime = %-26.24s\n" "otime = %-26.24s\n",
"ctime = %-26.24s\n" semid,
"%-10s %-10s %-10s %-10s %-10s\n", ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
semid, ipcp->mode, ipcp->mode & 0777,
ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, (long) semds.sem_nsems,
ipcp->mode, ipcp->mode & 0777, semds.sem_otime ? ctime(&semds.sem_otime) : "Not set");
(long) semds.sem_nsems, bb_printf("ctime = %-26.24s\n"
semds.sem_otime ? ctime (&semds.sem_otime) : "Not set", "%-10s %-10s %-10s %-10s %-10s\n",
ctime (&semds.sem_ctime), ctime(&semds.sem_ctime),
"semnum","value","ncount","zcount","pid"); "semnum", "value", "ncount", "zcount", "pid");
arg.val = 0; arg.val = 0;
for (i=0; i < semds.sem_nsems; i++) { for (i = 0; i < semds.sem_nsems; i++) {
int val, ncnt, zcnt, pid; int val, ncnt, zcnt, pid;
val = semctl (semid, i, GETVAL, arg);
ncnt = semctl (semid, i, GETNCNT, arg); val = semctl(semid, i, GETVAL, arg);
zcnt = semctl (semid, i, GETZCNT, arg); ncnt = semctl(semid, i, GETNCNT, arg);
pid = semctl (semid, i, GETPID, arg); zcnt = semctl(semid, i, GETZCNT, arg);
pid = semctl(semid, i, GETPID, arg);
if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) { if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) {
perror ("semctl "); bb_perror_msg_and_die("semctl");
bb_fflush_stdout_and_exit (1);
} }
bb_printf ("%-10d %-10d %-10d %-10d %-10d\n", bb_printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
i, val, ncnt, zcnt, pid);
} }
bb_printf ("\n"); bb_printf("\n");
return;
} }
int ipcs_main (int argc, char **argv) { int ipcs_main(int argc, char **argv)
int opt, msg = 0, sem = 0, shm = 0, id=0, print=0; {
char format = 0; int opt, id = 0;
char options[] = "atclupsmqi:ih?"; unsigned flags = 0;
#define flag_print (1<<0)
#define flag_msg (1<<1)
#define flag_sem (1<<2)
#define flag_shm (1<<3)
const char *const options = "atclupsmqi:ih?";
while ((opt = getopt (argc, argv, options)) != -1) { while ((opt = getopt(argc, argv, options)) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
id = atoi (optarg); id = atoi(optarg);
print = 1; flags |= flag_print;
break; break;
case 'a': case 'a':
msg = shm = sem = 1; flags |= flag_msg | flag_sem | flag_shm;
break; break;
case 'q': case 'q':
msg = 1; flags |= flag_msg;
break; break;
case 's': case 's':
sem = 1; flags |= flag_sem;
break; break;
case 'm': case 'm':
shm = 1; flags |= flag_shm;
break; break;
case 't': case 't':
format = TIME; format = TIME;
@ -629,43 +614,40 @@ int ipcs_main (int argc, char **argv) {
case 'h': case 'h':
case '?': case '?':
bb_show_usage(); bb_show_usage();
bb_fflush_stdout_and_exit (0);
} }
} }
if (print) { if (flags & flag_print) {
if (shm) { if (flags & flag_shm) {
print_shm (id); print_shm(id);
bb_fflush_stdout_and_exit (0); bb_fflush_stdout_and_exit(0);
} }
if (sem) { if (flags & flag_sem) {
print_sem (id); print_sem(id);
bb_fflush_stdout_and_exit (0); bb_fflush_stdout_and_exit(0);
} }
if (msg) { if (flags & flag_msg) {
print_msg (id); print_msg(id);
bb_fflush_stdout_and_exit (0); bb_fflush_stdout_and_exit(0);
} }
bb_show_usage(); bb_show_usage();
bb_fflush_stdout_and_exit (0);
} }
if ( !shm && !msg && !sem) if (!(flags & (flag_shm | flag_msg | flag_sem)))
msg = sem = shm = 1; flags |= flag_msg | flag_shm | flag_sem;
bb_printf ("\n"); bb_printf("\n");
if (shm) { if (flags & flag_shm) {
do_shm (format); do_shm();
bb_printf ("\n"); bb_printf("\n");
} }
if (sem) { if (flags & flag_sem) {
do_sem (format); do_sem();
bb_printf ("\n"); bb_printf("\n");
} }
if (msg) { if (flags & flag_msg) {
do_msg (format); do_msg();
bb_printf ("\n"); bb_printf("\n");
} }
return 0; return EXIT_SUCCESS;
} }