aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/bb_cat.c33
-rw-r--r--libbb/correct_password.c8
-rw-r--r--libbb/getopt32.c10
-rw-r--r--libbb/isqrt.c60
-rw-r--r--libbb/loop.c49
-rw-r--r--libbb/print_numbered_lines.c29
-rw-r--r--libbb/recursive_action.c46
-rw-r--r--libbb/securetty.c26
-rw-r--r--libbb/vfork_daemon_rexec.c28
10 files changed, 219 insertions, 71 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index fc9371db1..0d7dd2a2c 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -77,6 +77,7 @@ lib-y += safe_gethostname.o
77lib-y += safe_poll.o 77lib-y += safe_poll.o
78lib-y += safe_strncpy.o 78lib-y += safe_strncpy.o
79lib-y += safe_write.o 79lib-y += safe_write.o
80lib-y += securetty.o
80lib-y += setup_environment.o 81lib-y += setup_environment.o
81lib-y += simplify_path.o 82lib-y += simplify_path.o
82lib-y += single_argv.o 83lib-y += single_argv.o
diff --git a/libbb/bb_cat.c b/libbb/bb_cat.c
new file mode 100644
index 000000000..0a4a350fb
--- /dev/null
+++ b/libbb/bb_cat.c
@@ -0,0 +1,33 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//kbuild:lib-y += bb_cat.o
8
9#include "libbb.h"
10
11int FAST_FUNC bb_cat(char **argv)
12{
13 int fd;
14 int retval = EXIT_SUCCESS;
15
16 if (!*argv)
17 argv = (char**) &bb_argv_dash;
18
19 do {
20 fd = open_or_warn_stdin(*argv);
21 if (fd >= 0) {
22 /* This is not a xfunc - never exits */
23 off_t r = bb_copyfd_eof(fd, STDOUT_FILENO);
24 if (fd != STDIN_FILENO)
25 close(fd);
26 if (r >= 0)
27 continue;
28 }
29 retval = EXIT_FAILURE;
30 } while (*++argv);
31
32 return retval;
33}
diff --git a/libbb/correct_password.c b/libbb/correct_password.c
index 513c93028..f4635a5bc 100644
--- a/libbb/correct_password.c
+++ b/libbb/correct_password.c
@@ -63,7 +63,7 @@ static const char *get_passwd(const struct passwd *pw, char buffer[SHADOW_BUFSIZ
63} 63}
64 64
65/* 65/*
66 * Return 1 if PW has an empty password. 66 * Return CHECKPASS_PW_HAS_EMPTY_PASSWORD if PW has an empty password.
67 * Return 1 if the user gives the correct password for entry PW, 67 * Return 1 if the user gives the correct password for entry PW,
68 * 0 if not. 68 * 0 if not.
69 * NULL pw means "just fake it for login with bad username" 69 * NULL pw means "just fake it for login with bad username"
@@ -77,7 +77,7 @@ int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext)
77 77
78 pw_pass = get_passwd(pw, buffer); 78 pw_pass = get_passwd(pw, buffer);
79 if (!pw_pass[0]) { /* empty password field? */ 79 if (!pw_pass[0]) { /* empty password field? */
80 return 1; 80 return CHECKPASS_PW_HAS_EMPTY_PASSWORD;
81 } 81 }
82 82
83 encrypted = pw_encrypt(plaintext, /*salt:*/ pw_pass, 1); 83 encrypted = pw_encrypt(plaintext, /*salt:*/ pw_pass, 1);
@@ -88,7 +88,7 @@ int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext)
88 88
89 89
90/* Ask the user for a password. 90/* Ask the user for a password.
91 * Return 1 without asking if PW has an empty password. 91 * Return CHECKPASS_PW_HAS_EMPTY_PASSWORD without asking if PW has an empty password.
92 * Return -1 on EOF, error while reading input, or timeout. 92 * Return -1 on EOF, error while reading input, or timeout.
93 * Return 1 if the user gives the correct password for entry PW, 93 * Return 1 if the user gives the correct password for entry PW,
94 * 0 if not. 94 * 0 if not.
@@ -105,7 +105,7 @@ int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw,
105 105
106 pw_pass = get_passwd(pw, buffer); 106 pw_pass = get_passwd(pw, buffer);
107 if (!pw_pass[0]) /* empty password field? */ 107 if (!pw_pass[0]) /* empty password field? */
108 return 1; 108 return CHECKPASS_PW_HAS_EMPTY_PASSWORD;
109 109
110 plaintext = bb_ask(STDIN_FILENO, timeout, prompt); 110 plaintext = bb_ask(STDIN_FILENO, timeout, prompt);
111 if (!plaintext) { 111 if (!plaintext) {
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 03fca3493..b87b83538 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -128,7 +128,7 @@ const char *opt_complementary
128 "abc" If groups of two or more chars are specified, the first char 128 "abc" If groups of two or more chars are specified, the first char
129 is the main option and the other chars are secondary options. 129 is the main option and the other chars are secondary options.
130 Their flags will be turned on if the main option is found even 130 Their flags will be turned on if the main option is found even
131 if they are not specifed on the command line. For example: 131 if they are not specified on the command line. For example:
132 132
133 opt_complementary = "abc"; 133 opt_complementary = "abc";
134 flags = getopt32(argv, "abcd") 134 flags = getopt32(argv, "abcd")
@@ -576,13 +576,7 @@ getopt32(char **argv, const char *applet_opts, ...)
576 * run_nofork_applet() does this, but we might end up here 576 * run_nofork_applet() does this, but we might end up here
577 * also via gunzip_main() -> gzip_main(). Play safe. 577 * also via gunzip_main() -> gzip_main(). Play safe.
578 */ 578 */
579#if defined(__GLIBC__) || ENABLE_PLATFORM_MINGW32 579 GETOPT_RESET();
580 optind = 0;
581#else /* BSD style */
582 optind = 1;
583 /* optreset = 1; */
584#endif
585 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
586 580
587 /* Note: just "getopt() <= 0" will not work well for 581 /* Note: just "getopt() <= 0" will not work well for
588 * "fake" short options, like this one: 582 * "fake" short options, like this one:
diff --git a/libbb/isqrt.c b/libbb/isqrt.c
new file mode 100644
index 000000000..817b7d036
--- /dev/null
+++ b/libbb/isqrt.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7//kbuild:lib-y += isqrt.o
8
9#ifndef ISQRT_TEST
10# include "libbb.h"
11#else
12/* gcc -DISQRT_TEST -Wall -O2 isqrt.c -oisqrt && ./isqrt $((RANDOM*RANDOM)) */
13# include <stdlib.h>
14# include <stdio.h>
15# include <time.h>
16# define FAST_FUNC /* nothing */
17#endif
18
19/* Returns such x that x+1 > sqrt(N) */
20unsigned long FAST_FUNC isqrt(unsigned long long N)
21{
22 unsigned long x;
23 unsigned shift;
24#define LL_WIDTH_BITS (unsigned)(sizeof(N)*8)
25
26 shift = LL_WIDTH_BITS - 2;
27 x = 0;
28 do {
29 x = (x << 1) + 1;
30 if ((unsigned long long)x * x > (N >> shift))
31 x--; /* whoops, that +1 was too much */
32 shift -= 2;
33 } while ((int)shift >= 0);
34 return x;
35}
36
37#ifdef ISQRT_TEST
38int main(int argc, char **argv)
39{
40 unsigned long long n = argv[1] ? strtoull(argv[1], NULL, 0) : time(NULL);
41 for (;;) {
42 unsigned long h;
43 n--;
44 h = isqrt(n);
45 if (!(n & 0xffff))
46 printf("isqrt(%llx)=%lx\n", n, h);
47 if ((unsigned long long)h * h > n) {
48 printf("BAD1: isqrt(%llx)=%lx\n", n, h);
49 return 1;
50 }
51 h++;
52 if ((unsigned long long)h * h != 0 /* this can overflow to 0 - not a bug */
53 && (unsigned long long)h * h <= n)
54 {
55 printf("BAD2: isqrt(%llx)=%lx\n", n, h);
56 return 1;
57 }
58 }
59}
60#endif
diff --git a/libbb/loop.c b/libbb/loop.c
index d30b378d7..f0d4296ae 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -78,22 +78,24 @@ int FAST_FUNC del_loop(const char *device)
78 return rc; 78 return rc;
79} 79}
80 80
81/* Returns 0 if mounted RW, 1 if mounted read-only, <0 for error. 81/* Returns opened fd to the loop device, <0 on error.
82 *device is loop device to use, or if *device==NULL finds a loop device to 82 * *device is loop device to use, or if *device==NULL finds a loop device to
83 mount it on and sets *device to a strdup of that loop device name. This 83 * mount it on and sets *device to a strdup of that loop device name. This
84 search will re-use an existing loop device already bound to that 84 * search will re-use an existing loop device already bound to that
85 file/offset if it finds one. 85 * file/offset if it finds one.
86 */ 86 */
87int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, int ro) 87int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, unsigned flags)
88{ 88{
89 char dev[LOOP_NAMESIZE]; 89 char dev[LOOP_NAMESIZE];
90 char *try; 90 char *try;
91 bb_loop_info loopinfo; 91 bb_loop_info loopinfo;
92 struct stat statbuf; 92 struct stat statbuf;
93 int i, dfd, ffd, mode, rc = -1; 93 int i, dfd, ffd, mode, rc;
94
95 rc = dfd = -1;
94 96
95 /* Open the file. Barf if this doesn't work. */ 97 /* Open the file. Barf if this doesn't work. */
96 mode = ro ? O_RDONLY : O_RDWR; 98 mode = (flags & BB_LO_FLAGS_READ_ONLY) ? O_RDONLY : O_RDWR;
97 open_ffd: 99 open_ffd:
98 ffd = open(file, mode); 100 ffd = open(file, mode);
99 if (ffd < 0) { 101 if (ffd < 0) {
@@ -144,20 +146,35 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
144 146
145 /* If device is free, claim it. */ 147 /* If device is free, claim it. */
146 if (rc && errno == ENXIO) { 148 if (rc && errno == ENXIO) {
147 memset(&loopinfo, 0, sizeof(loopinfo));
148 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
149 loopinfo.lo_offset = offset;
150 /* Associate free loop device with file. */ 149 /* Associate free loop device with file. */
151 if (ioctl(dfd, LOOP_SET_FD, ffd) == 0) { 150 if (ioctl(dfd, LOOP_SET_FD, ffd) == 0) {
152 if (ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo) == 0) 151 memset(&loopinfo, 0, sizeof(loopinfo));
153 rc = 0; 152 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
154 else 153 loopinfo.lo_offset = offset;
154 /*
155 * Used by mount to set LO_FLAGS_AUTOCLEAR.
156 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file.
157 * Note that closing LO_FLAGS_AUTOCLEARed dfd before mount
158 * is wrong (would free the loop device!)
159 */
160 loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY);
161 rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
162 if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) {
163 /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */
164 /* (this code path is not tested) */
165 loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR;
166 rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
167 }
168 if (rc != 0) {
155 ioctl(dfd, LOOP_CLR_FD, 0); 169 ioctl(dfd, LOOP_CLR_FD, 0);
170 }
156 } 171 }
157 } else { 172 } else {
158 rc = -1; 173 rc = -1;
159 } 174 }
160 close(dfd); 175 if (rc != 0) {
176 close(dfd);
177 }
161 try_again: 178 try_again:
162 if (*device) break; 179 if (*device) break;
163 } 180 }
@@ -165,7 +182,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
165 if (rc == 0) { 182 if (rc == 0) {
166 if (!*device) 183 if (!*device)
167 *device = xstrdup(dev); 184 *device = xstrdup(dev);
168 return (mode == O_RDONLY); /* 1:ro, 0:rw */ 185 return dfd;
169 } 186 }
170 return rc; 187 return rc;
171} 188}
diff --git a/libbb/print_numbered_lines.c b/libbb/print_numbered_lines.c
new file mode 100644
index 000000000..702aed1ea
--- /dev/null
+++ b/libbb/print_numbered_lines.c
@@ -0,0 +1,29 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//kbuild:lib-y += print_numbered_lines.o
8
9#include "libbb.h"
10
11void FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filename)
12{
13 FILE *fp = fopen_or_warn_stdin(filename);
14 unsigned N = ns->start;
15 char *line;
16
17 while ((line = xmalloc_fgetline(fp)) != NULL) {
18 if (ns->all
19 || (ns->nonempty && line[0])
20 ) {
21 printf("%*u%s%s\n", ns->width, N, ns->sep, line);
22 N += ns->inc;
23 } else if (ns->empty_str)
24 fputs(ns->empty_str, stdout);
25 free(line);
26 }
27
28 fclose(fp);
29}
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c
index b5cf7c0ab..8f2b8b932 100644
--- a/libbb/recursive_action.c
+++ b/libbb/recursive_action.c
@@ -30,24 +30,37 @@ static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM,
30 return TRUE; 30 return TRUE;
31} 31}
32 32
33/* fileAction return value of 0 on any file in directory will make 33/* fileName is (l)stat'ed (depending on ACTION_FOLLOWLINKS[_L0]).
34 * recursive_action() return 0, but it doesn't stop directory traversal 34 *
35 * If it is a file: fileAction in run on it, its return value is returned.
36 *
37 * In case we are in a recursive invocation (see below):
38 * normally, fileAction should return 1 (TRUE) to indicate that
39 * everything is okay and processing should continue.
40 * fileAction return value of 0 (FALSE) on any file in directory will make
41 * recursive_action() also return 0, but it doesn't stop directory traversal
35 * (fileAction/dirAction will be called on each file). 42 * (fileAction/dirAction will be called on each file).
36 * 43 *
37 * If !ACTION_RECURSE, dirAction is called on the directory and its 44 * [TODO: maybe introduce -1 to mean "stop traversal NOW and return"]
45 *
46 * If it is a directory:
47 *
48 * If !ACTION_RECURSE, dirAction is called and its
38 * return value is returned from recursive_action(). No recursion. 49 * return value is returned from recursive_action(). No recursion.
39 * 50 *
40 * If ACTION_RECURSE, recursive_action() is called on each directory. 51 * If ACTION_RECURSE, directory is opened, and recursive_action() is called
52 * on each file/subdirectory.
41 * If any one of these calls returns 0, current recursive_action() returns 0. 53 * If any one of these calls returns 0, current recursive_action() returns 0.
42 * 54 *
55 * If !ACTION_DEPTHFIRST, dirAction is called before recurse.
56 * Return value of 0 (FALSE) is an error: prevents recursion,
57 * the warning is printed (unless ACTION_QUIET) and recursive_action() returns 0.
58 * Return value of 2 (SKIP) prevents recursion, instead recursive_action()
59 * returns 1 (TRUE, no error).
60 *
43 * If ACTION_DEPTHFIRST, dirAction is called after recurse. 61 * If ACTION_DEPTHFIRST, dirAction is called after recurse.
44 * If it returns 0, the warning is printed and recursive_action() returns 0. 62 * If it returns 0, the warning is printed and recursive_action() returns 0.
45 * 63 *
46 * If !ACTION_DEPTHFIRST, dirAction is called before we recurse.
47 * Return value of 0 (FALSE) or 2 (SKIP) prevents recursion
48 * into that directory, instead recursive_action() returns 0 (if FALSE)
49 * or 1 (if SKIP)
50 *
51 * ACTION_FOLLOWLINKS mainly controls handling of links to dirs. 64 * ACTION_FOLLOWLINKS mainly controls handling of links to dirs.
52 * 0: lstat(statbuf). Calls fileAction on link name even if points to dir. 65 * 0: lstat(statbuf). Calls fileAction on link name even if points to dir.
53 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir. 66 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir.
@@ -105,7 +118,7 @@ int FAST_FUNC recursive_action(const char *fileName,
105 118
106 if (!(flags & ACTION_DEPTHFIRST)) { 119 if (!(flags & ACTION_DEPTHFIRST)) {
107 status = dirAction(fileName, &statbuf, userData, depth); 120 status = dirAction(fileName, &statbuf, userData, depth);
108 if (!status) 121 if (status == FALSE)
109 goto done_nak_warn; 122 goto done_nak_warn;
110 if (status == SKIP) 123 if (status == SKIP)
111 return TRUE; 124 return TRUE;
@@ -121,24 +134,23 @@ int FAST_FUNC recursive_action(const char *fileName,
121 status = TRUE; 134 status = TRUE;
122 while ((next = readdir(dir)) != NULL) { 135 while ((next = readdir(dir)) != NULL) {
123 char *nextFile; 136 char *nextFile;
137 int s;
124 138
125 nextFile = concat_subpath_file(fileName, next->d_name); 139 nextFile = concat_subpath_file(fileName, next->d_name);
126 if (nextFile == NULL) 140 if (nextFile == NULL)
127 continue; 141 continue;
142
128 /* process every file (NB: ACTION_RECURSE is set in flags) */ 143 /* process every file (NB: ACTION_RECURSE is set in flags) */
129 if (!recursive_action(nextFile, flags, fileAction, dirAction, 144 s = recursive_action(nextFile, flags, fileAction, dirAction,
130 userData, depth + 1)) 145 userData, depth + 1);
146 if (s == FALSE)
131 status = FALSE; 147 status = FALSE;
132// s = recursive_action(nextFile, flags, fileAction, dirAction,
133// userData, depth + 1);
134 free(nextFile); 148 free(nextFile);
135//#define RECURSE_RESULT_ABORT 3 149//#define RECURSE_RESULT_ABORT -1
136// if (s == RECURSE_RESULT_ABORT) { 150// if (s == RECURSE_RESULT_ABORT) {
137// closedir(dir); 151// closedir(dir);
138// return s; 152// return s;
139// } 153// }
140// if (s == FALSE)
141// status = FALSE;
142 } 154 }
143 closedir(dir); 155 closedir(dir);
144 156
diff --git a/libbb/securetty.c b/libbb/securetty.c
new file mode 100644
index 000000000..21354e2fa
--- /dev/null
+++ b/libbb/securetty.c
@@ -0,0 +1,26 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * /etc/securetty checking.
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7#include "libbb.h"
8
9#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
10int FAST_FUNC is_tty_secure(const char *short_tty)
11{
12 char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */
13 parser_t *parser = config_open2("/etc/securetty", fopen_for_read);
14 while (config_read(parser, &buf, 1, 1, "# \t", PARSE_NORMAL)) {
15 if (strcmp(buf, short_tty) == 0)
16 break;
17 buf = NULL;
18 }
19 config_close(parser);
20 /* buf != NULL here if config file was not found, empty
21 * or line was found which equals short_tty.
22 * In all these cases, we report "this tty is secure".
23 */
24 return buf != NULL;
25}
26#endif
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index a6d260a40..9ab49d0a1 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -123,28 +123,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
123 123
124 /* In case getopt() or getopt32() was already called: 124 /* In case getopt() or getopt32() was already called:
125 * reset the libc getopt() function, which keeps internal state. 125 * reset the libc getopt() function, which keeps internal state.
126 *
127 * BSD-derived getopt() functions require that optind be set to 1 in
128 * order to reset getopt() state. This used to be generally accepted
129 * way of resetting getopt(). However, glibc's getopt()
130 * has additional getopt() state beyond optind, and requires that
131 * optind be set to zero to reset its state. So the unfortunate state of
132 * affairs is that BSD-derived versions of getopt() misbehave if
133 * optind is set to 0 in order to reset getopt(), and glibc's getopt()
134 * will core dump if optind is set 1 in order to reset getopt().
135 *
136 * More modern versions of BSD require that optreset be set to 1 in
137 * order to reset getopt(). Sigh. Standards, anyone?
138 */ 126 */
139#ifdef __GLIBC__ 127 GETOPT_RESET();
140 optind = 0;
141#else /* BSD style */
142 optind = 1;
143 /* optreset = 1; */
144#endif
145 /* optarg = NULL; opterr = 1; optopt = 63; - do we need this too? */
146 /* (values above are what they initialized to in glibc and uclibc) */
147 /* option_mask32 = 0; - not needed, no applet depends on it being 0 */
148 128
149 argc = 1; 129 argc = 1;
150 while (argv[argc]) 130 while (argv[argc])
@@ -169,11 +149,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
169 restore_nofork_data(&old); 149 restore_nofork_data(&old);
170 150
171 /* Other globals can be simply reset to defaults */ 151 /* Other globals can be simply reset to defaults */
172#ifdef __GLIBC__ 152 GETOPT_RESET();
173 optind = 0;
174#else /* BSD style */
175 optind = 1;
176#endif
177 153
178 return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ 154 return rc & 0xff; /* don't confuse people with "exitcodes" >255 */
179} 155}