aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-22 15:41:00 +0000
committerRon Yorston <rmy@pobox.com>2012-03-22 15:41:00 +0000
commit1118c95535ea51961437089fc3dece5ab4ea7e1b (patch)
tree1515bd2376a6d6c5123791662307ce2ed90cdf36 /libbb
parent0d8b2c4a929ea9d3ac37499319fe0d8e7941a0c2 (diff)
parent066f39956641300c1e5c6bfe6c11a115cea3e2cf (diff)
downloadbusybox-w32-1118c95535ea51961437089fc3dece5ab4ea7e1b.tar.gz
busybox-w32-1118c95535ea51961437089fc3dece5ab4ea7e1b.tar.bz2
busybox-w32-1118c95535ea51961437089fc3dece5ab4ea7e1b.zip
Merge commit '066f39956641300c1e5c6bfe6c11a115cea3e2cf' into merge
Conflicts: procps/ps.c
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Kbuild.src4
-rw-r--r--libbb/appletlib.c15
-rw-r--r--libbb/get_line_from_file.c42
-rw-r--r--libbb/parse_config.c140
-rw-r--r--libbb/platform.c29
-rw-r--r--libbb/procps.c44
6 files changed, 163 insertions, 111 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index d110a3265..fcab184e0 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -57,9 +57,7 @@ lib-y += hash_md5_sha.o
57#lib-y += hash_md5prime.o 57#lib-y += hash_md5prime.o
58lib-y += messages.o 58lib-y += messages.o
59lib-y += mode_string.o 59lib-y += mode_string.o
60lib-y += obscure.o
61lib-y += parse_mode.o 60lib-y += parse_mode.o
62lib-y += parse_config.o
63lib-y += perror_msg.o 61lib-y += perror_msg.o
64lib-y += perror_nomsg.o 62lib-y += perror_nomsg.o
65lib-y += perror_nomsg_and_die.o 63lib-y += perror_nomsg_and_die.o
@@ -138,7 +136,7 @@ lib-$(CONFIG_ADDUSER) += update_passwd.o
138lib-$(CONFIG_DELGROUP) += update_passwd.o 136lib-$(CONFIG_DELGROUP) += update_passwd.o
139lib-$(CONFIG_DELUSER) += update_passwd.o 137lib-$(CONFIG_DELUSER) += update_passwd.o
140 138
141lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o 139lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o
142lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o 140lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
143lib-$(CONFIG_CRYPTPW) += pw_encrypt.o 141lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
144lib-$(CONFIG_SULOGIN) += pw_encrypt.o 142lib-$(CONFIG_SULOGIN) += pw_encrypt.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index d4025b9c7..b824b4775 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -34,17 +34,6 @@
34# include <malloc.h> /* for mallopt */ 34# include <malloc.h> /* for mallopt */
35#endif 35#endif
36 36
37/* Try to pull in PAGE_SIZE */
38#ifdef __linux__
39# include <sys/user.h>
40#endif
41#ifdef __GNU__ /* Hurd */
42# include <mach/vm_param.h>
43#endif
44#ifndef PAGE_SIZE
45# define PAGE_SIZE (4*1024) /* guess */
46#endif
47
48 37
49/* Declare <applet>_main() */ 38/* Declare <applet>_main() */
50#define PROTOTYPES 39#define PROTOTYPES
@@ -788,13 +777,13 @@ int main(int argc UNUSED_PARAM, char **argv)
788 * to keep before releasing to the OS 777 * to keep before releasing to the OS
789 * Default is way too big: 256k 778 * Default is way too big: 256k
790 */ 779 */
791 mallopt(M_TRIM_THRESHOLD, 2 * PAGE_SIZE); 780 mallopt(M_TRIM_THRESHOLD, 8 * 1024);
792#endif 781#endif
793#ifdef M_MMAP_THRESHOLD 782#ifdef M_MMAP_THRESHOLD
794 /* M_MMAP_THRESHOLD is the request size threshold for using mmap() 783 /* M_MMAP_THRESHOLD is the request size threshold for using mmap()
795 * Default is too big: 256k 784 * Default is too big: 256k
796 */ 785 */
797 mallopt(M_MMAP_THRESHOLD, 8 * PAGE_SIZE - 256); 786 mallopt(M_MMAP_THRESHOLD, 32 * 1024 - 256);
798#endif 787#endif
799 788
800#if !BB_MMU 789#if !BB_MMU
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c
index 9be10687b..a98dd35eb 100644
--- a/libbb/get_line_from_file.c
+++ b/libbb/get_line_from_file.c
@@ -11,45 +11,24 @@
11 11
12#include "libbb.h" 12#include "libbb.h"
13 13
14/* This function reads an entire line from a text file, up to a newline 14char* FAST_FUNC bb_get_chunk_from_file(FILE *file, int *end)
15 * or NUL byte, inclusive. It returns a malloc'ed char * which
16 * must be free'ed by the caller. If end is NULL '\n' isn't considered
17 * end of line. If end isn't NULL, length of the chunk is stored in it.
18 * If lineno is not NULL, *lineno is incremented for each line,
19 * and also trailing '\' is recognized as line continuation.
20 *
21 * Returns NULL if EOF/error. */
22char* FAST_FUNC bb_get_chunk_with_continuation(FILE *file, int *end, int *lineno)
23{ 15{
24 int ch; 16 int ch;
25 int idx = 0; 17 unsigned idx = 0;
26 char *linebuf = NULL; 18 char *linebuf = NULL;
27 int linebufsz = 0;
28 19
29 while ((ch = getc(file)) != EOF) { 20 while ((ch = getc(file)) != EOF) {
30 /* grow the line buffer as necessary */ 21 /* grow the line buffer as necessary */
31 if (idx >= linebufsz) { 22 if (!(idx & 0xff))
32 linebufsz += 256; 23 linebuf = xrealloc(linebuf, idx + 0x100);
33 linebuf = xrealloc(linebuf, linebufsz);
34 }
35 linebuf[idx++] = (char) ch; 24 linebuf[idx++] = (char) ch;
36 if (!ch) 25 if (ch == '\0')
26 break;
27 if (end && ch == '\n')
37 break; 28 break;
38 if (end && ch == '\n') {
39 if (lineno == NULL)
40 break;
41 (*lineno)++;
42 if (idx < 2 || linebuf[idx-2] != '\\')
43 break;
44 idx -= 2;
45 }
46 } 29 }
47 if (end) { 30 if (end)
48 *end = idx; 31 *end = idx;
49 /* handle corner case when the file is not ended with '\n' */
50 if (ch == EOF && lineno != NULL)
51 (*lineno)++;
52 }
53 if (linebuf) { 32 if (linebuf) {
54 // huh, does fgets discard prior data on error like this? 33 // huh, does fgets discard prior data on error like this?
55 // I don't think so.... 34 // I don't think so....
@@ -63,11 +42,6 @@ char* FAST_FUNC bb_get_chunk_with_continuation(FILE *file, int *end, int *lineno
63 return linebuf; 42 return linebuf;
64} 43}
65 44
66char* FAST_FUNC bb_get_chunk_from_file(FILE *file, int *end)
67{
68 return bb_get_chunk_with_continuation(file, end, NULL);
69}
70
71/* Get line, including trailing \n if any */ 45/* Get line, including trailing \n if any */
72char* FAST_FUNC xmalloc_fgets(FILE *file) 46char* FAST_FUNC xmalloc_fgets(FILE *file)
73{ 47{
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index 4b0236028..cf5ba4deb 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -8,11 +8,27 @@
8 * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later. 8 * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later.
9 */ 9 */
10 10
11/* 11/* Uncomment to enable test applet */
12////config:config PARSE
13////config: bool "Uniform config file parser debugging applet: parse"
14////config: default n
15////config: help
16////config: Typical usage of parse API:
17////config: char *t[3];
18////config: parser_t *p = config_open(filename);
19////config: while (config_read(p, t, 3, 0, delimiters, flags)) { // 1..3 tokens
20////config: bb_error_msg("TOKENS: '%s''%s''%s'", t[0], t[1], t[2]);
21////config: }
22////config: config_close(p);
23
24////applet:IF_PARSE(APPLET(parse, BB_DIR_USR_BIN, BB_SUID_DROP))
25
26//kbuild:lib-y += parse_config.o
27
12//usage:#define parse_trivial_usage 28//usage:#define parse_trivial_usage
13//usage: "[-n MAXTOKENS] [-m MINTOKENS] [-d DELIMS] [-f FLAGS] FILE..." 29//usage: "[-x] [-n MAXTOKENS] [-m MINTOKENS] [-d DELIMS] [-f FLAGS] FILE..."
14//usage:#define parse_full_usage "" 30//usage:#define parse_full_usage "\n\n"
15*/ 31//usage: " -x Suppress output (for benchmarking)"
16 32
17#include "libbb.h" 33#include "libbb.h"
18 34
@@ -21,52 +37,34 @@ int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
21int parse_main(int argc UNUSED_PARAM, char **argv) 37int parse_main(int argc UNUSED_PARAM, char **argv)
22{ 38{
23 const char *delims = "# \t"; 39 const char *delims = "# \t";
40 char **t;
24 unsigned flags = PARSE_NORMAL; 41 unsigned flags = PARSE_NORMAL;
25 int mintokens = 0, ntokens = 128; 42 int mintokens = 0, ntokens = 128;
43 unsigned noout;
26 44
27 opt_complementary = "-1:n+:m+:f+"; 45 opt_complementary = "-1:n+:m+:f+";
28 getopt32(argv, "n:m:d:f:", &ntokens, &mintokens, &delims, &flags); 46 noout = 1 & getopt32(argv, "xn:m:d:f:", &ntokens, &mintokens, &delims, &flags);
29 //argc -= optind; 47 //argc -= optind;
30 argv += optind; 48 argv += optind;
49
50 t = xmalloc(sizeof(t[0]) * ntokens);
31 while (*argv) { 51 while (*argv) {
52 int n;
32 parser_t *p = config_open(*argv); 53 parser_t *p = config_open(*argv);
33 if (p) { 54 while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) != 0) {
34 int n; 55 if (!noout) {
35 char **t = xmalloc(sizeof(char *) * ntokens);
36 while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) != 0) {
37 for (int i = 0; i < n; ++i) 56 for (int i = 0; i < n; ++i)
38 printf("[%s]", t[i]); 57 printf("[%s]", t[i]);
39 puts(""); 58 puts("");
40 } 59 }
41 config_close(p);
42 } 60 }
61 config_close(p);
43 argv++; 62 argv++;
44 } 63 }
45 return EXIT_SUCCESS; 64 return EXIT_SUCCESS;
46} 65}
47#endif 66#endif
48 67
49/*
50
51Typical usage:
52
53----- CUT -----
54 char *t[3]; // tokens placeholder
55 parser_t *p = config_open(filename);
56 if (p) {
57 // parse line-by-line
58 while (config_read(p, t, 3, 0, delimiters, flags)) { // 1..3 tokens
59 // use tokens
60 bb_error_msg("TOKENS: [%s][%s][%s]", t[0], t[1], t[2]);
61 }
62 ...
63 // free parser
64 config_close(p);
65 }
66----- CUT -----
67
68*/
69
70parser_t* FAST_FUNC config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path)) 68parser_t* FAST_FUNC config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path))
71{ 69{
72 FILE* fp; 70 FILE* fp;
@@ -85,25 +83,58 @@ parser_t* FAST_FUNC config_open(const char *filename)
85 return config_open2(filename, fopen_or_warn_stdin); 83 return config_open2(filename, fopen_or_warn_stdin);
86} 84}
87 85
88static void config_free_data(parser_t *parser)
89{
90 free(parser->line);
91 parser->line = NULL;
92 if (PARSE_KEEP_COPY) { /* compile-time constant */
93 free(parser->data);
94 parser->data = NULL;
95 }
96}
97
98void FAST_FUNC config_close(parser_t *parser) 86void FAST_FUNC config_close(parser_t *parser)
99{ 87{
100 if (parser) { 88 if (parser) {
101 config_free_data(parser); 89 if (PARSE_KEEP_COPY) /* compile-time constant */
90 free(parser->data);
102 fclose(parser->fp); 91 fclose(parser->fp);
92 free(parser->line);
93 free(parser->nline);
103 free(parser); 94 free(parser);
104 } 95 }
105} 96}
106 97
98/* This function reads an entire line from a text file,
99 * up to a newline, exclusive.
100 * Trailing '\' is recognized as line continuation.
101 * Returns -1 if EOF/error.
102 */
103static int get_line_with_continuation(parser_t *parser)
104{
105 ssize_t len, nlen;
106 char *line;
107
108 len = getline(&parser->line, &parser->line_alloc, parser->fp);
109 if (len <= 0)
110 return len;
111
112 line = parser->line;
113 for (;;) {
114 parser->lineno++;
115 if (line[len - 1] == '\n')
116 len--;
117 if (len == 0 || line[len - 1] != '\\')
118 break;
119 len--;
120
121 nlen = getline(&parser->nline, &parser->nline_alloc, parser->fp);
122 if (nlen <= 0)
123 break;
124
125 if (parser->line_alloc < len + nlen + 1) {
126 parser->line_alloc = len + nlen + 1;
127 line = parser->line = xrealloc(line, parser->line_alloc);
128 }
129 memcpy(&line[len], parser->nline, nlen);
130 len += nlen;
131 }
132
133 line[len] = '\0';
134 return len;
135}
136
137
107/* 138/*
1080. If parser is NULL return 0. 1390. If parser is NULL return 0.
1091. Read a line from config file. If nothing to read then return 0. 1401. Read a line from config file. If nothing to read then return 0.
@@ -132,27 +163,22 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
132{ 163{
133 char *line; 164 char *line;
134 int ntokens, mintokens; 165 int ntokens, mintokens;
135 int t, len; 166 int t;
167
168 if (!parser)
169 return 0;
136 170
137 ntokens = (uint8_t)flags; 171 ntokens = (uint8_t)flags;
138 mintokens = (uint8_t)(flags >> 8); 172 mintokens = (uint8_t)(flags >> 8);
139 173
140 if (parser == NULL) 174 again:
141 return 0;
142
143again:
144 memset(tokens, 0, sizeof(tokens[0]) * ntokens); 175 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
145 config_free_data(parser);
146 176
147 /* Read one line (handling continuations with backslash) */ 177 /* Read one line (handling continuations with backslash) */
148 line = bb_get_chunk_with_continuation(parser->fp, &len, &parser->lineno); 178 if (get_line_with_continuation(parser) < 0)
149 if (line == NULL)
150 return 0; 179 return 0;
151 parser->line = line;
152 180
153 /* Strip trailing line-feed if any */ 181 line = parser->line;
154 if (len && line[len-1] == '\n')
155 line[len-1] = '\0';
156 182
157 /* Skip token in the start of line? */ 183 /* Skip token in the start of line? */
158 if (flags & PARSE_TRIM) 184 if (flags & PARSE_TRIM)
@@ -161,8 +187,10 @@ again:
161 if (line[0] == '\0' || line[0] == delims[0]) 187 if (line[0] == '\0' || line[0] == delims[0])
162 goto again; 188 goto again;
163 189
164 if (flags & PARSE_KEEP_COPY) 190 if (flags & PARSE_KEEP_COPY) {
191 free(parser->data);
165 parser->data = xstrdup(line); 192 parser->data = xstrdup(line);
193 }
166 194
167 /* Tokenize the line */ 195 /* Tokenize the line */
168 t = 0; 196 t = 0;
@@ -208,8 +236,6 @@ again:
208 parser->lineno, t, mintokens); 236 parser->lineno, t, mintokens);
209 if (flags & PARSE_MIN_DIE) 237 if (flags & PARSE_MIN_DIE)
210 xfunc_die(); 238 xfunc_die();
211 if (flags & PARSE_KEEP_COPY)
212 free(parser->data);
213 goto again; 239 goto again;
214 } 240 }
215 241
diff --git a/libbb/platform.c b/libbb/platform.c
index c594dcb4a..3cb41347f 100644
--- a/libbb/platform.c
+++ b/libbb/platform.c
@@ -158,3 +158,32 @@ char* FAST_FUNC stpcpy(char *p, const char *to_add)
158 return p; 158 return p;
159} 159}
160#endif 160#endif
161
162#ifndef HAVE_GETLINE
163ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream)
164{
165 int ch;
166 char *line = *lineptr;
167 size_t alloced = *n;
168 size_t len = 0;
169
170 do {
171 ch = fgetc(stream);
172 if (ch == EOF)
173 break;
174 if (len + 1 >= alloced) {
175 alloced += alloced/4 + 64;
176 line = xrealloc(line, alloced);
177 }
178 line[len++] = ch;
179 } while (ch != '\n');
180
181 if (len == 0)
182 return -1;
183
184 line[len] = '\0';
185 *lineptr = line;
186 *n = alloced;
187 return len;
188}
189#endif
diff --git a/libbb/procps.c b/libbb/procps.c
index 58772d4e9..b5582edfa 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -358,7 +358,14 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
358 sp->gid = sb.st_gid; 358 sp->gid = sb.st_gid;
359 } 359 }
360 360
361 if (flags & PSSCAN_STAT) { 361 /* These are all retrieved from proc/NN/stat in one go: */
362 if (flags & (PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
363 | PSSCAN_COMM | PSSCAN_STATE
364 | PSSCAN_VSZ | PSSCAN_RSS
365 | PSSCAN_STIME | PSSCAN_UTIME | PSSCAN_START_TIME
366 | PSSCAN_TTY | PSSCAN_NICE
367 | PSSCAN_CPU)
368 ) {
362 char *cp, *comm1; 369 char *cp, *comm1;
363 int tty; 370 int tty;
364#if !ENABLE_FEATURE_FAST_TOP 371#if !ENABLE_FEATURE_FAST_TOP
@@ -562,18 +569,47 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
562void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) 569void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
563{ 570{
564 int sz; 571 int sz;
565 char filename[sizeof("/proc//cmdline") + sizeof(int)*3]; 572 char filename[sizeof("/proc/%u/cmdline") + sizeof(int)*3];
566 573
567 sprintf(filename, "/proc/%u/cmdline", pid); 574 sprintf(filename, "/proc/%u/cmdline", pid);
568 sz = open_read_close(filename, buf, col - 1); 575 sz = open_read_close(filename, buf, col - 1);
569 if (sz > 0) { 576 if (sz > 0) {
577 const char *base;
578 int comm_len;
579
570 buf[sz] = '\0'; 580 buf[sz] = '\0';
571 while (--sz >= 0 && buf[sz] == '\0') 581 while (--sz >= 0 && buf[sz] == '\0')
572 continue; 582 continue;
573 do { 583 base = bb_basename(buf); /* before we replace argv0's NUL with space */
584 while (sz >= 0) {
574 if ((unsigned char)(buf[sz]) < ' ') 585 if ((unsigned char)(buf[sz]) < ' ')
575 buf[sz] = ' '; 586 buf[sz] = ' ';
576 } while (--sz >= 0); 587 sz--;
588 }
589
590 /* If comm differs from argv0, prepend "{comm} ".
591 * It allows to see thread names set by prctl(PR_SET_NAME).
592 */
593 if (base[0] == '-') /* "-sh" (login shell)? */
594 base++;
595 comm_len = strlen(comm);
596 /* Why compare up to comm_len, not COMM_LEN-1?
597 * Well, some processes rewrite argv, and use _spaces_ there
598 * while rewriting. (KDE is observed to do it).
599 * I prefer to still treat argv0 "process foo bar"
600 * as 'equal' to comm "process".
601 */
602 if (strncmp(base, comm, comm_len) != 0) {
603 comm_len += 3;
604 if (col > comm_len)
605 memmove(buf + comm_len, buf, col - comm_len);
606 snprintf(buf, col, "{%s}", comm);
607 if (col <= comm_len)
608 return;
609 buf[comm_len - 1] = ' ';
610 buf[col - 1] = '\0';
611 }
612
577 } else { 613 } else {
578 snprintf(buf, col, "[%s]", comm); 614 snprintf(buf, col, "[%s]", comm);
579 } 615 }