busybox: squashed commit of merging cm-12.1
With fixes to LOCAL_C_INCLUDES for libsepol in M and fixed
some missing includes to enable building for 64 bit devices
Conflicts:
Android.mk
android/libc/arch-x86/syscalls/swapoff.S
android/libc/arch-x86/syscalls/swapon.S
android/libc/arch-x86/syscalls/sysinfo.S
android/librpc/pmap_rmt.c
android/reboot.c
include-full/copy-current.sh
include-minimal/copy-current.sh
include/platform.h
networking/interface.c
networking/nslookup.c
Change-Id: If6092fa87f3d21190db1af4f70daa150eb462660
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 61eec26..a6468f1 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -27,8 +27,6 @@
lib-y += copy_file.o
lib-y += copyfd.o
lib-y += crc32.o
-lib-y += create_icmp6_socket.o
-lib-y += create_icmp_socket.o
lib-y += default_error_retval.o
lib-y += device_open.o
lib-y += dump.o
@@ -146,7 +144,7 @@
lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o
lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
-lib-$(CONFIG_SULOGIN) += pw_encrypt.o
+lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o
lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o
lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o
lib-$(CONFIG_LOGIN) += pw_encrypt.o correct_password.o
diff --git a/libbb/android.c b/libbb/android.c
deleted file mode 100644
index 8f2c3c4..0000000
--- a/libbb/android.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Android/bionic glue.
- *
- * Copyright (C) 2010 by Dylan Simon <dylan@dylex.net>
- *
- * Licensed under GPLv2, see file LICENSE in this tarball for details.
- */
-
-#include <stdlib.h>
-#include "libbb.h"
-
-/* declared in stdlib.h */
-int clearenv()
-{
- environ = NULL;
- return 0;
-}
-
-/* bionic/stubs.c:ttyname not implemented anyway */
-int ttyname_r(int fd, char *name, size_t namesize)
-{
- char *t = ttyname(fd);
- if (!t)
- return -1;
- strncpy(name, ttyname(fd), namesize);
- return 0;
-}
-
-/* no /etc/shells anyway */
-char *getusershell() { return NULL; }
-void setusershell() {}
-void endusershell() {}
-
-struct mntent *getmntent_r(FILE *fp, struct mntent *mnt, char *buf, int buflen)
-{
- char *tokp = NULL, *s;
-
- do {
- if (!fgets(buf, buflen, fp))
- return NULL;
- tokp = 0;
- s = strtok_r(buf, " \t\n", &tokp);
- } while (!s || *s == '#');
-
- mnt->mnt_fsname = s;
- mnt->mnt_freq = mnt->mnt_passno = 0;
- if (!(mnt->mnt_dir = strtok_r(NULL, " \t\n", &tokp)))
- return NULL;
- if (!(mnt->mnt_type = strtok_r(NULL, " \t\n", &tokp)))
- return NULL;
- if (!(mnt->mnt_opts = strtok_r(NULL, " \t\n", &tokp)))
- mnt->mnt_opts = "";
- else if ((s = strtok_r(NULL, " \t\n", &tokp)))
- {
- mnt->mnt_freq = atoi(s);
- if ((s = strtok_r(NULL, " \t\n", &tokp)))
- mnt->mnt_passno = atoi(s);
- }
-
- return mnt;
-}
-
-/* override definition in bionic/stubs.c */
-struct mntent *getmntent(FILE *fp)
-{
- static struct mntent mnt;
- static char buf[256];
- return getmntent_r(fp, &mnt, buf, 256);
-}
-
-/* not used anyway */
-int addmntent(FILE *fp, const struct mntent *mnt)
-{
- errno = ENOENT;
- return 1;
-}
-
-const char *hasmntopt(const struct mntent *mnt, const char *opt)
-{
- const char *o = mnt->mnt_opts;
- size_t l = strlen(opt);
-
- while ((o = strstr(o, opt)) &&
- ((o > mnt->mnt_opts && o[-1] != ',') ||
- (o[l] != 0 && o[l] != ',' && o[l] != '=')));
- return o;
-}
-
-/* declared in grp.h, but not necessary */
-#if !ENABLE_USE_BB_PWD_GRP
-int setpwent() { return 0; }
-void setgrent() {}
-void endgrent() {}
-#endif
-
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index fc1847a..5e4f4a9 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -29,7 +29,7 @@
#include "busybox.h"
#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
- || defined(__APPLE__) \
+ || defined(__APPLE__) \
)
# include <malloc.h> /* for mallopt */
#endif
@@ -750,7 +750,7 @@
//TODO: just compare applet_no with APPLET_NO_test
if (!ENABLE_TEST || strcmp(applet_name, "test") != 0) {
/* If you want "foo --help" to return 0: */
- /*xfunc_error_retval = 0;*/
+ xfunc_error_retval = 0;
bb_show_usage();
}
}
diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c
index fe2b506..77c1bcd 100644
--- a/libbb/bb_askpass.c
+++ b/libbb/bb_askpass.c
@@ -65,7 +65,9 @@
i = 0;
while (1) {
int r = read(fd, &ret[i], 1);
- if (r < 0) {
+ if ((i == 0 && r == 0) /* EOF (^D) with no password */
+ || r < 0
+ ) {
/* read is interrupted by timeout or ^C */
ret = NULL;
break;
diff --git a/libbb/bb_pwd.c b/libbb/bb_pwd.c
index 4829b72..d5e651c 100644
--- a/libbb/bb_pwd.c
+++ b/libbb/bb_pwd.c
@@ -15,9 +15,31 @@
* pointers to static data (getpwuid)
*/
-struct passwd* FAST_FUNC xgetpwnam(const char *name)
+struct passwd* FAST_FUNC safegetpwnam(const char *name)
{
struct passwd *pw = getpwnam(name);
+#ifdef __BIONIC__
+ if (pw && !pw->pw_passwd) {
+ pw->pw_passwd = "";
+ }
+#endif
+ return pw;
+}
+
+struct passwd* FAST_FUNC safegetpwuid(uid_t uid)
+{
+ struct passwd *pw = getpwuid(uid);
+#ifdef __BIONIC__
+ if (pw && !pw->pw_passwd) {
+ pw->pw_passwd = "";
+ }
+#endif
+ return pw;
+}
+
+struct passwd* FAST_FUNC xgetpwnam(const char *name)
+{
+ struct passwd *pw = safegetpwnam(name);
if (!pw)
bb_error_msg_and_die("unknown user %s", name);
return pw;
@@ -31,10 +53,9 @@
return gr;
}
-
struct passwd* FAST_FUNC xgetpwuid(uid_t uid)
{
- struct passwd *pw = getpwuid(uid);
+ struct passwd *pw = safegetpwuid(uid);
if (!pw)
bb_error_msg_and_die("unknown uid %u", (unsigned)uid);
return pw;
@@ -110,3 +131,51 @@
return xname2id(s);
return r;
}
+
+/* Experimental "mallocing" API.
+ * The goal is nice: "we want to support a case when "guests" group is very large"
+ * but the code is butt-ugly.
+ */
+#if 0
+static char *find_latest(char last, char *cp)
+{
+ if (!cp)
+ return last;
+ cp += strlen(cp) + 1;
+ if (last < cp)
+ last = cp;
+ return last;
+}
+
+struct group* FAST_FUNC xmalloc_getgrnam(const char *name)
+{
+ struct {
+ struct group gr;
+ // May still be not enough!
+ char buf[64*1024 - sizeof(struct group) - 16];
+ } *s;
+ struct group *grp;
+ int r;
+ char *last;
+ char **gr_mem;
+
+ s = xmalloc(sizeof(*s));
+ r = getgrnam_r(name, &s->gr, s->buf, sizeof(s->buf), &grp);
+ if (!grp) {
+ free(s);
+ return grp;
+ }
+ last = find_latest(s->buf, grp->gr_name);
+ last = find_latest(last, grp->gr_passwd);
+ gr_mem = grp->gr_mem;
+ while (*gr_mem)
+ last = find_latest(last, *gr_mem++);
+ gr_mem++; /* points past NULL */
+ if (last < (char*)gr_mem)
+ last = (char*)gr_mem;
+//FIXME: what if we get not only truncated, but also moved here?
+// grp->gr_name pointer and friends are invalid now!!!
+ s = xrealloc(s, last - (char*)s);
+ return grp;
+}
+#endif
diff --git a/libbb/correct_password.c b/libbb/correct_password.c
index 7cabd33..acadf39 100644
--- a/libbb/correct_password.c
+++ b/libbb/correct_password.c
@@ -31,12 +31,15 @@
#include "libbb.h"
/* Ask the user for a password.
+ * Return 1 without asking if PW has an empty password.
+ * Return -1 on EOF, error while reading input, or timeout.
* Return 1 if the user gives the correct password for entry PW,
- * 0 if not. Return 1 without asking if PW has an empty password.
+ * 0 if not.
*
- * NULL pw means "just fake it for login with bad username" */
-
-int FAST_FUNC correct_password(const struct passwd *pw)
+ * NULL pw means "just fake it for login with bad username"
+ */
+int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw,
+ int timeout, const char *prompt)
{
char *unencrypted, *encrypted;
const char *correct;
@@ -65,13 +68,19 @@
return 1;
fake_it:
- unencrypted = bb_ask_stdin("Password: ");
+ unencrypted = bb_ask(STDIN_FILENO, timeout, prompt);
if (!unencrypted) {
- return 0;
+ /* EOF (such as ^D) or error (such as ^C) or timeout */
+ return -1;
}
encrypted = pw_encrypt(unencrypted, correct, 1);
r = (strcmp(encrypted, correct) == 0);
free(encrypted);
- memset(unencrypted, 0, strlen(unencrypted));
+ nuke_str(unencrypted);
return r;
}
+
+int FAST_FUNC ask_and_check_password(const struct passwd *pw)
+{
+ return ask_and_check_password_extended(pw, 0, "Password: ");
+}
diff --git a/libbb/create_icmp6_socket.c b/libbb/create_icmp6_socket.c
deleted file mode 100644
index bdee7a0..0000000
--- a/libbb/create_icmp6_socket.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Utility routines.
- *
- * create raw socket for icmp (IPv6 version) protocol
- * and drop root privileges if running setuid
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-#include "libbb.h"
-
-#if ENABLE_FEATURE_IPV6
-int FAST_FUNC create_icmp6_socket(void)
-{
- int sock;
-#if 0
- struct protoent *proto;
- proto = getprotobyname("ipv6-icmp");
- /* if getprotobyname failed, just silently force
- * proto->p_proto to have the correct value for "ipv6-icmp" */
- sock = socket(AF_INET6, SOCK_RAW,
- (proto ? proto->p_proto : IPPROTO_ICMPV6));
-#else
- sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-#endif
- if (sock < 0) {
- if (errno == EPERM)
- bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
- bb_perror_msg_and_die("%s", bb_msg_can_not_create_raw_socket);
- }
-
- /* drop root privs if running setuid */
- xsetuid(getuid());
-
- return sock;
-}
-#endif
diff --git a/libbb/create_icmp_socket.c b/libbb/create_icmp_socket.c
deleted file mode 100644
index 65eea3b..0000000
--- a/libbb/create_icmp_socket.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Utility routines.
- *
- * create raw socket for icmp protocol
- * and drop root privileges if running setuid
- *
- * Licensed under GPLv2, see file LICENSE in this source tree.
- */
-
-#include "libbb.h"
-
-int FAST_FUNC create_icmp_socket(void)
-{
- int sock;
-#if 0
- struct protoent *proto;
- proto = getprotobyname("icmp");
- /* if getprotobyname failed, just silently force
- * proto->p_proto to have the correct value for "icmp" */
- sock = socket(AF_INET, SOCK_RAW,
- (proto ? proto->p_proto : 1)); /* 1 == ICMP */
-#else
- sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */
-#endif
- if (sock < 0) {
- if (errno == EPERM)
- bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
- bb_perror_msg_and_die("%s", bb_msg_can_not_create_raw_socket);
- }
-
- /* drop root privs if running setuid */
- xsetuid(getuid());
-
- return sock;
-}
diff --git a/libbb/dump.c b/libbb/dump.c
index 91efe41..b465c5d 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -333,7 +333,7 @@
return;
}
}
- if (fseek(stdin, dumper->pub.dump_skip, SEEK_SET)) {
+ if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) {
bb_simple_perror_msg_and_die(fname);
}
dumper->address += dumper->pub.dump_skip;
diff --git a/libbb/endofname.c b/libbb/endofname.c
new file mode 100644
index 0000000..305f093
--- /dev/null
+++ b/libbb/endofname.c
@@ -0,0 +1,26 @@
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2013 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-y += endofname.o
+
+#include "libbb.h"
+
+#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
+#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
+
+const char* FAST_FUNC
+endofname(const char *name)
+{
+ if (!is_name(*name))
+ return name;
+ while (*++name) {
+ if (!is_in_name(*name))
+ break;
+ }
+ return name;
+}
diff --git a/libbb/fclose_nonstdin.c b/libbb/fclose_nonstdin.c
index 5ce9d5b..1b14413 100644
--- a/libbb/fclose_nonstdin.c
+++ b/libbb/fclose_nonstdin.c
@@ -18,7 +18,8 @@
{
/* Some more paranoid applets want ferror() check too */
int r = ferror(f); /* NB: does NOT set errno! */
- if (r) errno = EIO; /* so we'll help it */
+ if (r)
+ errno = EIO; /* so we'll help it */
if (f != stdin)
return (r | fclose(f)); /* fclose does set errno on error */
return r;
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index b4d955e..3f743ac 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -84,7 +84,7 @@
if (swap_needed)
t = bb_bswap_64(t);
/* wbuffer is suitably aligned for this */
- *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
+ *(bb__aliased_uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
}
ctx->process_block(ctx);
if (remaining >= 8)
@@ -883,10 +883,10 @@
uint64_t t;
t = ctx->total64[0] << 3;
t = SWAP_BE64(t);
- *(uint64_t *) (&ctx->wbuffer[128 - 8]) = t;
+ *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 8]) = t;
t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61);
t = SWAP_BE64(t);
- *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
+ *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
}
sha512_process_block128(ctx);
if (remaining >= 16)
diff --git a/libbb/human_readable.c b/libbb/human_readable.c
index 8b22b0c..0b2eb77 100644
--- a/libbb/human_readable.c
+++ b/libbb/human_readable.c
@@ -94,7 +94,7 @@
/* Convert unsigned long long value into compact 5-char representation.
* String is not terminated (buf[5] is untouched) */
-void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale)
+char* FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale)
{
const char *fmt;
char c;
@@ -145,12 +145,13 @@
buf[3] = "0123456789"[v];
buf[4] = scale[idx]; /* typically scale = " kmgt..." */
}
+ return buf + 5;
}
/* Convert unsigned long long value into compact 4-char
* representation. Examples: "1234", "1.2k", " 27M", "123T"
* String is not terminated (buf[4] is untouched) */
-void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale)
+char* FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale)
{
const char *fmt;
char c;
@@ -194,4 +195,5 @@
buf[2] = "0123456789"[v];
buf[3] = scale[idx]; /* typically scale = " kmgt..." */
}
+ return buf + 4;
}
diff --git a/libbb/in_ether.c b/libbb/in_ether.c
new file mode 100644
index 0000000..1de383b
--- /dev/null
+++ b/libbb/in_ether.c
@@ -0,0 +1,59 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ */
+
+//kbuild:lib-$(CONFIG_ARP) += in_ether.o
+//kbuild:lib-$(CONFIG_IFCONFIG) += in_ether.o
+//kbuild:lib-$(CONFIG_IFENSLAVE) += in_ether.o
+
+#include "libbb.h"
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+
+/* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr.
+ * Return nonzero on error.
+ */
+int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap)
+{
+ char *ptr;
+ int i, j;
+ unsigned char val;
+ unsigned char c;
+
+ sap->sa_family = ARPHRD_ETHER;
+ ptr = (char *) sap->sa_data;
+
+ i = ETH_ALEN;
+ goto first;
+ do {
+ /* We might get a semicolon here */
+ if (*bufp == ':')
+ bufp++;
+ first:
+ j = val = 0;
+ do {
+ c = *bufp;
+ if (((unsigned char)(c - '0')) <= 9) {
+ c -= '0';
+ } else if ((unsigned char)((c|0x20) - 'a') <= 5) {
+ c = (unsigned char)((c|0x20) - 'a') + 10;
+ } else {
+ if (j && (c == ':' || c == '\0'))
+ /* One-digit byte: __:X:__ */
+ break;
+ return -1;
+ }
+ ++bufp;
+ val <<= 4;
+ val += c;
+ j ^= 1;
+ } while (j);
+
+ *ptr++ = val;
+
+ } while (--i);
+
+ /* Error if we aren't at end of string */
+ return *bufp;
+}
diff --git a/libbb/inet_common.c b/libbb/inet_common.c
index 0f4fca1..b3e0802 100644
--- a/libbb/inet_common.c
+++ b/libbb/inet_common.c
@@ -175,8 +175,7 @@
return -1;
}
memcpy(sin6, ai->ai_addr, sizeof(*sin6));
- if (ai)
- freeaddrinfo(ai);
+ freeaddrinfo(ai);
return 0;
}
diff --git a/libbb/inode_hash.c b/libbb/inode_hash.c
index 715535e..377ecbc 100644
--- a/libbb/inode_hash.c
+++ b/libbb/inode_hash.c
@@ -71,7 +71,7 @@
/* Clear statbuf hash table */
void FAST_FUNC reset_ino_dev_hashtable(void)
{
- int i;
+ unsigned i;
ino_dev_hashtable_bucket_t *bucket;
for (i = 0; ino_dev_hashtable && i < HASH_SIZE; i++) {
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 0da625f..f897e96 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -38,6 +38,14 @@
* and the \] escape to signal the end of such a sequence. Example:
*
* PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
+ *
+ * Unicode in PS1 is not fully supported: prompt length calulation is wrong,
+ * resulting in line wrap problems with long (multi-line) input.
+ *
+ * Multi-line PS1 (e.g. PS1="\n[\w]\n$ ") has problems with history
+ * browsing: up/down arrows result in scrolling.
+ * It stems from simplistic "cmdedit_y = cmdedit_prmt_len / cmdedit_termw"
+ * calculation of how many lines the prompt takes.
*/
#include "libbb.h"
#include "unicode.h"
@@ -133,9 +141,6 @@
CHAR_T *command_ps;
const char *cmdedit_prompt;
-#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
- int num_ok_lines; /* = 1; */
-#endif
#if ENABLE_USERNAME_OR_HOMEDIR
char *user_buf;
@@ -172,7 +177,6 @@
#define command_len (S.command_len )
#define command_ps (S.command_ps )
#define cmdedit_prompt (S.cmdedit_prompt )
-#define num_ok_lines (S.num_ok_lines )
#define user_buf (S.user_buf )
#define home_pwd_buf (S.home_pwd_buf )
#define matches (S.matches )
@@ -185,8 +189,8 @@
(*(struct lineedit_statics**)&lineedit_ptr_to_statics) = xzalloc(sizeof(S)); \
barrier(); \
cmdedit_termw = 80; \
- IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines = 1;) \
IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \
+ IF_FEATURE_EDITING_VI(delptr = delbuf;) \
} while (0)
static void deinit_S(void)
@@ -1251,14 +1255,16 @@
{
line_input_t *n = xzalloc(sizeof(*n));
n->flags = flags;
+#if MAX_HISTORY > 0
n->max_history = MAX_HISTORY;
+#endif
return n;
}
#if MAX_HISTORY > 0
-unsigned size_from_HISTFILESIZE(const char *hp)
+unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp)
{
int size = MAX_HISTORY;
if (hp) {
@@ -1313,6 +1319,17 @@
return 0;
}
+/* Lists command history. Used by shell 'history' builtins */
+void FAST_FUNC show_history(const line_input_t *st)
+{
+ unsigned i;
+
+ if (!st)
+ return;
+ for (i = 0; i < st->cnt_history; i++)
+ printf("%4d %s\n", i, st->history[i]);
+}
+
# if ENABLE_FEATURE_EDITING_SAVEHISTORY
/* We try to ensure that concurrent additions to the history
* do not overwrite each other.
@@ -1532,7 +1549,6 @@
# if ENABLE_FEATURE_EDITING_SAVEHISTORY && !ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
save_history(str);
# endif
- IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
}
#else /* MAX_HISTORY == 0 */
@@ -1754,43 +1770,84 @@
#define ask_terminal() ((void)0)
#endif
+/* Called just once at read_line_input() init time */
#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
static void parse_and_put_prompt(const char *prmt_ptr)
{
+ const char *p;
cmdedit_prompt = prmt_ptr;
- cmdedit_prmt_len = strlen(prmt_ptr);
+ p = strrchr(prmt_ptr, '\n');
+ cmdedit_prmt_len = unicode_strwidth(p ? p+1 : prmt_ptr);
put_prompt();
}
#else
static void parse_and_put_prompt(const char *prmt_ptr)
{
- int prmt_len = 0;
- size_t cur_prmt_len = 0;
- char flg_not_length = '[';
+ int prmt_size = 0;
char *prmt_mem_ptr = xzalloc(1);
- char *cwd_buf = xrealloc_getcwd_or_warn(NULL);
+# if ENABLE_USERNAME_OR_HOMEDIR
+ char *cwd_buf = NULL;
+# endif
+ char flg_not_length = '[';
char cbuf[2];
- char c;
- char *pbuf;
- cmdedit_prmt_len = 0;
-
- if (!cwd_buf) {
- cwd_buf = (char *)bb_msg_unknown;
- }
+ /*cmdedit_prmt_len = 0; - already is */
cbuf[1] = '\0'; /* never changes */
while (*prmt_ptr) {
+ char timebuf[sizeof("HH:MM:SS")];
char *free_me = NULL;
+ char *pbuf;
+ char c;
pbuf = cbuf;
c = *prmt_ptr++;
if (c == '\\') {
- const char *cp = prmt_ptr;
+ const char *cp;
int l;
-
- c = bb_process_escape_sequence(&prmt_ptr);
+/*
+ * Supported via bb_process_escape_sequence:
+ * \a ASCII bell character (07)
+ * \e ASCII escape character (033)
+ * \n newline
+ * \r carriage return
+ * \\ backslash
+ * \nnn char with octal code nnn
+ * Supported:
+ * \$ if the effective UID is 0, a #, otherwise a $
+ * \w current working directory, with $HOME abbreviated with a tilde
+ * Note: we do not support $PROMPT_DIRTRIM=n feature
+ * \W basename of the current working directory, with $HOME abbreviated with a tilde
+ * \h hostname up to the first '.'
+ * \H hostname
+ * \u username
+ * \[ begin a sequence of non-printing characters
+ * \] end a sequence of non-printing characters
+ * \T current time in 12-hour HH:MM:SS format
+ * \@ current time in 12-hour am/pm format
+ * \A current time in 24-hour HH:MM format
+ * \t current time in 24-hour HH:MM:SS format
+ * (all of the above work as \A)
+ * Not supported:
+ * \! history number of this command
+ * \# command number of this command
+ * \j number of jobs currently managed by the shell
+ * \l basename of the shell's terminal device name
+ * \s name of the shell, the basename of $0 (the portion following the final slash)
+ * \V release of bash, version + patch level (e.g., 2.00.0)
+ * \d date in "Weekday Month Date" format (e.g., "Tue May 26")
+ * \D{format}
+ * format is passed to strftime(3).
+ * An empty format results in a locale-specific time representation.
+ * The braces are required.
+ * Mishandled by bb_process_escape_sequence:
+ * \v version of bash (e.g., 2.00)
+ */
+ cp = prmt_ptr;
+ c = *cp;
+ if (c != 't') /* don't treat \t as tab */
+ c = bb_process_escape_sequence(&prmt_ptr);
if (prmt_ptr == cp) {
if (*cp == '\0')
break;
@@ -1802,39 +1859,54 @@
pbuf = user_buf ? user_buf : (char*)"";
break;
# endif
+ case 'H':
case 'h':
pbuf = free_me = safe_gethostname();
- *strchrnul(pbuf, '.') = '\0';
+ if (c == 'h')
+ strchrnul(pbuf, '.')[0] = '\0';
break;
case '$':
c = (geteuid() == 0 ? '#' : '$');
break;
+ case 'T': /* 12-hour HH:MM:SS format */
+ case '@': /* 12-hour am/pm format */
+ case 'A': /* 24-hour HH:MM format */
+ case 't': /* 24-hour HH:MM:SS format */
+ /* We show all of them as 24-hour HH:MM */
+ strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0';
+ pbuf = timebuf;
+ break;
# if ENABLE_USERNAME_OR_HOMEDIR
- case 'w':
- /* /home/user[/something] -> ~[/something] */
- pbuf = cwd_buf;
- l = strlen(home_pwd_buf);
- if (l != 0
- && strncmp(home_pwd_buf, cwd_buf, l) == 0
- && (cwd_buf[l]=='/' || cwd_buf[l]=='\0')
- && strlen(cwd_buf + l) < PATH_MAX
- ) {
- pbuf = free_me = xasprintf("~%s", cwd_buf + l);
+ case 'w': /* current dir */
+ case 'W': /* basename of cur dir */
+ if (!cwd_buf) {
+ cwd_buf = xrealloc_getcwd_or_warn(NULL);
+ if (!cwd_buf)
+ cwd_buf = (char *)bb_msg_unknown;
+ else {
+ /* /home/user[/something] -> ~[/something] */
+ l = strlen(home_pwd_buf);
+ if (l != 0
+ && strncmp(home_pwd_buf, cwd_buf, l) == 0
+ && (cwd_buf[l] == '/' || cwd_buf[l] == '\0')
+ ) {
+ cwd_buf[0] = '~';
+ overlapping_strcpy(cwd_buf + 1, cwd_buf + l);
+ }
+ }
}
+ pbuf = cwd_buf;
+ if (c == 'w')
+ break;
+ cp = strrchr(pbuf, '/');
+ if (cp)
+ pbuf = (char*)cp + 1;
break;
# endif
- case 'W':
- pbuf = cwd_buf;
- cp = strrchr(pbuf, '/');
- if (cp != NULL && cp != pbuf)
- pbuf += (cp-pbuf) + 1;
- break;
- case '!':
- pbuf = free_me = xasprintf("%d", num_ok_lines);
- break;
- case 'e': case 'E': /* \e \E = \033 */
- c = '\033';
- break;
+// bb_process_escape_sequence does this now:
+// case 'e': case 'E': /* \e \E = \033 */
+// c = '\033';
+// break;
case 'x': case 'X': {
char buf2[4];
for (l = 0; l < 3;) {
@@ -1856,7 +1928,8 @@
}
case '[': case ']':
if (c == flg_not_length) {
- flg_not_length = (flg_not_length == '[' ? ']' : '[');
+ /* Toggle '['/']' hex 5b/5d */
+ flg_not_length ^= 6;
continue;
}
break;
@@ -1864,16 +1937,29 @@
} /* if */
} /* if */
cbuf[0] = c;
- cur_prmt_len = strlen(pbuf);
- prmt_len += cur_prmt_len;
- if (flg_not_length != ']')
- cmdedit_prmt_len += cur_prmt_len;
- prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
+ {
+ int n = strlen(pbuf);
+ prmt_size += n;
+ if (c == '\n')
+ cmdedit_prmt_len = 0;
+ else if (flg_not_length != ']') {
+#if 0 /*ENABLE_UNICODE_SUPPORT*/
+/* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */
+/* FIXME */
+ cmdedit_prmt_len += unicode_strwidth(pbuf);
+#else
+ cmdedit_prmt_len += n;
+#endif
+ }
+ }
+ prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf);
free(free_me);
} /* while */
+# if ENABLE_USERNAME_OR_HOMEDIR
if (cwd_buf != (char *)bb_msg_unknown)
free(cwd_buf);
+# endif
cmdedit_prompt = prmt_mem_ptr;
put_prompt();
}
@@ -1935,7 +2021,15 @@
S.sent_ESC_br6n = 0;
if (cursor == 0) { /* otherwise it may be bogus */
int col = ((ic >> 32) & 0x7fff) - 1;
- if (col > (int) cmdedit_prmt_len) {
+ /*
+ * Is col > cmdedit_prmt_len?
+ * If yes (terminal says cursor is farther to the right
+ * of where we think it should be),
+ * the prompt wasn't printed starting at col 1,
+ * there was additional text before it.
+ */
+ if ((int)(col - cmdedit_prmt_len) > 0) {
+ /* Fix our understanding of current x position */
cmdedit_x += (col - cmdedit_prmt_len);
while (cmdedit_x >= cmdedit_termw) {
cmdedit_x -= cmdedit_termw;
@@ -2026,6 +2120,7 @@
char read_key_buffer[KEYCODE_BUFFER_SIZE];
const char *matched_history_line;
const char *saved_prompt;
+ unsigned saved_prmt_len;
int32_t ic;
matched_history_line = NULL;
@@ -2034,6 +2129,7 @@
/* Save and replace the prompt */
saved_prompt = cmdedit_prompt;
+ saved_prmt_len = cmdedit_prmt_len;
goto set_prompt;
while (1) {
@@ -2109,7 +2205,7 @@
free((char*)cmdedit_prompt);
set_prompt:
cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
- cmdedit_prmt_len = strlen(cmdedit_prompt);
+ cmdedit_prmt_len = unicode_strwidth(cmdedit_prompt);
goto do_redraw;
}
}
@@ -2131,7 +2227,7 @@
free((char*)cmdedit_prompt);
cmdedit_prompt = saved_prompt;
- cmdedit_prmt_len = strlen(cmdedit_prompt);
+ cmdedit_prmt_len = saved_prmt_len;
redraw(cmdedit_y, command_len - cursor);
return ic;
@@ -2699,8 +2795,9 @@
free(command_ps);
#endif
- if (command_len > 0)
+ if (command_len > 0) {
remember_in_history(command);
+ }
if (break_out > 0) {
command[command_len++] = '\n';
diff --git a/libbb/login.c b/libbb/login.c
index 8a82c6a..8f080b7 100644
--- a/libbb/login.c
+++ b/libbb/login.c
@@ -16,7 +16,6 @@
#define LOGIN " login: "
static const char fmtstr_d[] ALIGN1 = "%A, %d %B %Y";
-static const char fmtstr_t[] ALIGN1 = "%H:%M:%S";
void FAST_FUNC print_login_issue(const char *issue_file, const char *tty)
{
@@ -73,7 +72,7 @@
strftime(buf, sizeof(buf), fmtstr_d, localtime(&t));
break;
case 't':
- strftime(buf, sizeof(buf), fmtstr_t, localtime(&t));
+ strftime_HHMMSS(buf, sizeof(buf), &t);
break;
case 'l':
outbuf = tty;
diff --git a/libbb/messages.c b/libbb/messages.c
index fad82c9..1ce84cf 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -40,7 +40,11 @@
/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
* but I want to save a few bytes here. Check libbb.h before changing! */
const char bb_PATH_root_path[] ALIGN1 =
+#ifdef __BIONIC__
+ "PATH=/sbin" BB_ADDITIONAL_PATH; /* platform.h */
+#else
"PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH;
+#endif
const int const_int_1 = 1;
diff --git a/libbb/nuke_str.c b/libbb/nuke_str.c
new file mode 100644
index 0000000..56b808b
--- /dev/null
+++ b/libbb/nuke_str.c
@@ -0,0 +1,21 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2008 Denys Vlasenko
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-y += nuke_str.o
+
+#include "libbb.h"
+
+void FAST_FUNC nuke_str(char *str)
+{
+ if (str) {
+ while (*str)
+ *str++ = 0;
+ /* or: memset(str, 0, strlen(str)); - not as small as above */
+ }
+}
diff --git a/libbb/platform.c b/libbb/platform.c
index 2bf34f5..5fcd448 100644
--- a/libbb/platform.c
+++ b/libbb/platform.c
@@ -28,14 +28,16 @@
r = vsnprintf(buf, 128, format, p);
va_end(p);
+ /* Note: can't use xstrdup/xmalloc, they call vasprintf (us) on failure! */
+
if (r < 128) {
va_end(p2);
- *string_ptr = xstrdup(buf);
- return r;
+ *string_ptr = strdup(buf);
+ return (*string_ptr ? r : -1);
}
- *string_ptr = xmalloc(r+1);
- r = vsnprintf(*string_ptr, r+1, format, p2);
+ *string_ptr = malloc(r+1);
+ r = (*string_ptr ? vsnprintf(*string_ptr, r+1, format, p2) : -1);
va_end(p2);
return r;
@@ -84,6 +86,9 @@
#endif
#ifndef HAVE_MKDTEMP
+#ifdef __BIONIC__
+#define mktemp(s) bb_mktemp(s)
+#endif
/* This is now actually part of POSIX.1, but was only added in 2008 */
char* FAST_FUNC mkdtemp(char *template)
{
diff --git a/libbb/printable.c b/libbb/printable.c
index f6ada49..9a42343 100644
--- a/libbb/printable.c
+++ b/libbb/printable.c
@@ -32,3 +32,27 @@
}
fputc(ch, file);
}
+
+void FAST_FUNC visible(unsigned ch, char *buf, int flags)
+{
+ if (ch == '\t' && !(flags & VISIBLE_SHOW_TABS)) {
+ goto raw;
+ }
+ if (ch == '\n') {
+ if (flags & VISIBLE_ENDLINE)
+ *buf++ = '$';
+ } else {
+ if (ch >= 128) {
+ ch -= 128;
+ *buf++ = 'M';
+ *buf++ = '-';
+ }
+ if (ch < 32 || ch == 127) {
+ *buf++ = '^';
+ ch ^= 0x40;
+ }
+ }
+ raw:
+ *buf++ = ch;
+ *buf = '\0';
+}
diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c
index c8e02dd..35326a5 100644
--- a/libbb/pw_encrypt_des.c
+++ b/libbb/pw_encrypt_des.c
@@ -598,7 +598,7 @@
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
*/
uint32_t l, r, *kl, *kr;
- uint32_t f = f; /* silence gcc */
+ static uint32_t f; /* silence gcc */
uint32_t r48l, r48r;
int round;
diff --git a/libbb/pw_encrypt_md5.c b/libbb/pw_encrypt_md5.c
index 889e09c..1e52eca 100644
--- a/libbb/pw_encrypt_md5.c
+++ b/libbb/pw_encrypt_md5.c
@@ -86,7 +86,7 @@
/* Get the length of the salt including "$1$" */
sl = 3;
- while (salt[sl] && salt[sl] != '$' && sl < (3 + 8))
+ while (sl < (3 + 8) && salt[sl] && salt[sl] != '$')
sl++;
/* Hash. the password first, since that is what is most unknown */
diff --git a/libbb/pw_encrypt_sha.c b/libbb/pw_encrypt_sha.c
index 8aeaaca..e48b341 100644
--- a/libbb/pw_encrypt_sha.c
+++ b/libbb/pw_encrypt_sha.c
@@ -21,7 +21,7 @@
void (*sha_begin)(void *ctx) FAST_FUNC;
void (*sha_hash)(void *ctx, const void *buffer, size_t len) FAST_FUNC;
void (*sha_end)(void *ctx, void *resbuf) FAST_FUNC;
- int _32or64;
+ unsigned _32or64;
char *result, *resptr;
@@ -152,7 +152,7 @@
/* Start computation of S byte sequence. */
/* For every character in the password add the entire password. */
sha_begin(&alt_ctx);
- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
+ for (cnt = 0; cnt < 16U + alt_result[0]; ++cnt)
sha_hash(&alt_ctx, salt_data, salt_len);
sha_end(&alt_ctx, temp_result);
diff --git a/libbb/rtc.c b/libbb/rtc.c
index 97455e8..c31f848 100644
--- a/libbb/rtc.c
+++ b/libbb/rtc.c
@@ -61,7 +61,7 @@
time_t FAST_FUNC rtc_tm2time(struct tm *ptm, int utc)
{
- char *oldtz = oldtz; /* for compiler */
+ char *oldtz = NULL;
time_t t;
if (utc) {
diff --git a/libbb/run_shell.c b/libbb/run_shell.c
index 4d92c3c..9494f27 100644
--- a/libbb/run_shell.c
+++ b/libbb/run_shell.c
@@ -34,16 +34,18 @@
#endif
#if ENABLE_SELINUX
-static security_context_t current_sid;
+static security_context_t current_sid = NULL;
void FAST_FUNC renew_current_security_context(void)
{
- freecon(current_sid); /* Release old context */
+ if (current_sid)
+ freecon(current_sid); /* Release old context */
getcon(¤t_sid); /* update */
}
void FAST_FUNC set_current_security_context(security_context_t sid)
{
- freecon(current_sid); /* Release old context */
+ if (current_sid)
+ freecon(current_sid); /* Release old context */
current_sid = sid;
}
@@ -82,6 +84,7 @@
args[argno] = NULL;
#if ENABLE_SELINUX
+ renew_current_security_context();
if (current_sid)
setexeccon(current_sid);
if (ENABLE_FEATURE_CLEAN_UP)
diff --git a/libbb/time.c b/libbb/time.c
index 3778a2d..5a64bcb 100644
--- a/libbb/time.c
+++ b/libbb/time.c
@@ -23,14 +23,16 @@
if (sscanf(date_str, "%u:%u%c",
&ptm->tm_hour,
&ptm->tm_min,
- &end) >= 2) {
+ &end) >= 2
+ ) {
/* no adjustments needed */
} else
/* mm.dd-HH:MM */
if (sscanf(date_str, "%u.%u-%u:%u%c",
&ptm->tm_mon, &ptm->tm_mday,
&ptm->tm_hour, &ptm->tm_min,
- &end) >= 4) {
+ &end) >= 4
+ ) {
/* Adjust month from 1-12 to 0-11 */
ptm->tm_mon -= 1;
} else
@@ -38,15 +40,13 @@
if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &ptm->tm_year,
&ptm->tm_mon, &ptm->tm_mday,
&ptm->tm_hour, &ptm->tm_min,
- &end) >= 5) {
- ptm->tm_year -= 1900; /* Adjust years */
- ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
- } else
+ &end) >= 5
/* yyyy-mm-dd HH:MM */
- if (sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year,
+ || sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year,
&ptm->tm_mon, &ptm->tm_mday,
&ptm->tm_hour, &ptm->tm_min,
- &end) >= 5) {
+ &end) >= 5
+ ) {
ptm->tm_year -= 1900; /* Adjust years */
ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
} else
@@ -58,7 +58,6 @@
return; /* don't fall through to end == ":" check */
} else
#endif
-//TODO: coreutils 6.9 also accepts "yyyy-mm-dd HH" (no minutes)
{
bb_error_msg_and_die(bb_msg_invalid_date, date_str);
}
@@ -68,7 +67,29 @@
end = '\0';
/* else end != NUL and we error out */
}
- } else if (date_str[0] == '@') {
+ } else
+ if (strchr(date_str, '-')
+ /* Why strchr('-') check?
+ * sscanf below will trash ptm->tm_year, this breaks
+ * if parse_str is "10101010" (iow, "MMddhhmm" form)
+ * because we destroy year. Do these sscanf
+ * only if we saw a dash in parse_str.
+ */
+ /* yyyy-mm-dd HH */
+ && (sscanf(date_str, "%u-%u-%u %u%c", &ptm->tm_year,
+ &ptm->tm_mon, &ptm->tm_mday,
+ &ptm->tm_hour,
+ &end) >= 4
+ /* yyyy-mm-dd */
+ || sscanf(date_str, "%u-%u-%u%c", &ptm->tm_year,
+ &ptm->tm_mon, &ptm->tm_mday,
+ &end) >= 3
+ )
+ ) {
+ ptm->tm_year -= 1900; /* Adjust years */
+ ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
+ } else
+ if (date_str[0] == '@') {
time_t t = bb_strtol(date_str + 1, NULL, 10);
if (!errno) {
struct tm *lt = localtime(&t);
@@ -187,6 +208,27 @@
return t;
}
+static char* strftime_fmt(char *buf, unsigned len, time_t *tp, const char *fmt)
+{
+ time_t t;
+ if (!tp) {
+ tp = &t;
+ time(tp);
+ }
+ /* Returns pointer to NUL */
+ return buf + strftime(buf, len, fmt, localtime(tp));
+}
+
+char* FAST_FUNC strftime_HHMMSS(char *buf, unsigned len, time_t *tp)
+{
+ return strftime_fmt(buf, len, tp, "%H:%M:%S");
+}
+
+char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp)
+{
+ return strftime_fmt(buf, len, tp, "%Y-%m-%d %H:%M:%S");
+}
+
#if ENABLE_MONOTONIC_SYSCALL
#include <sys/syscall.h>
diff --git a/libbb/unicode.c b/libbb/unicode.c
index 96eb646..6bdb666 100644
--- a/libbb/unicode.c
+++ b/libbb/unicode.c
@@ -34,19 +34,37 @@
static const char unicode_0x394[] = { 0xce, 0x94, 0 };
size_t width;
+ /* We pass "" instead of "C" because some libc's have
+ * non-ASCII default locale for setlocale("") call
+ * (this allows users of such libc to have Unicoded
+ * system without having to mess with env).
+ *
+ * We set LC_CTYPE because (a) we may be called with $LC_CTYPE
+ * value in LANG, not with $LC_ALL, (b) internationalized
+ * LC_NUMERIC and LC_TIME are more PITA than benefit
+ * (for one, some utilities have hard time with comma
+ * used as a fractional separator).
+ */
//TODO: avoid repeated calls by caching last string?
- setlocale(LC_ALL, (LANG && LANG[0]) ? LANG : "C");
+ setlocale(LC_CTYPE, LANG ? LANG : "");
/* In unicode, this is a one character string */
-// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused
- width = mbstowcs(NULL, unicode_0x394, INT_MAX);
+ width = unicode_strlen(unicode_0x394);
unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF);
}
void FAST_FUNC init_unicode(VOID)
{
- if (unicode_status == UNICODE_UNKNOWN)
- reinit_unicode(getenv("LANG"));
+ /* Some people set only $LC_CTYPE, not $LC_ALL, because they want
+ * only Unicode to be activated on their system, not the whole
+ * shebang of wrong decimal points, strange date formats and so on.
+ */
+ if (unicode_status == UNICODE_UNKNOWN) {
+ char *s = getenv("LC_ALL");
+ if (!s) s = getenv("LC_CTYPE");
+ if (!s) s = getenv("LANG");
+ reinit_unicode(s);
+ }
}
#else
@@ -64,8 +82,12 @@
void FAST_FUNC init_unicode(VOID)
{
- if (unicode_status == UNICODE_UNKNOWN)
- reinit_unicode(getenv("LANG"));
+ if (unicode_status == UNICODE_UNKNOWN) {
+ char *s = getenv("LC_ALL");
+ if (!s) s = getenv("LC_CTYPE");
+ if (!s) s = getenv("LANG");
+ reinit_unicode(s);
+ }
}
# endif
@@ -971,7 +993,6 @@
/* The rest is mostly same for libc and for "homegrown" support */
-#if 0 // UNUSED
size_t FAST_FUNC unicode_strlen(const char *string)
{
size_t width = mbstowcs(NULL, string, INT_MAX);
@@ -979,7 +1000,6 @@
return strlen(string);
return width;
}
-#endif
size_t FAST_FUNC unicode_strwidth(const char *string)
{
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c
index a30af6f..b2d0464 100644
--- a/libbb/update_passwd.c
+++ b/libbb/update_passwd.c
@@ -30,7 +30,7 @@
if (!seuser)
bb_error_msg_and_die("invalid context '%s'", context);
if (strcmp(seuser, username) != 0) {
- if (checkPasswdAccess(PASSWD__PASSWD) != 0)
+ if (selinux_check_passwd_access(PASSWD__PASSWD) != 0)
bb_error_msg_and_die("SELinux: access denied");
}
if (ENABLE_FEATURE_CLEAN_UP)
diff --git a/libbb/xatonum.c b/libbb/xatonum.c
index 62bbe53..6f4e023 100644
--- a/libbb/xatonum.c
+++ b/libbb/xatonum.c
@@ -68,3 +68,10 @@
{
return xatou_range(numstr, 0, 0xffff);
}
+
+const struct suffix_mult bkm_suffixes[] = {
+ { "b", 512 },
+ { "k", 1024 },
+ { "m", 1024*1024 },
+ { "", 0 }
+};
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 29c963f..7fb34e1 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -140,15 +140,6 @@
return xopen3(pathname, flags, 0666);
}
-/* Die if we can't open an existing file readonly with O_NONBLOCK
- * and return the fd.
- * Note that for ioctl O_RDONLY is sufficient.
- */
-int FAST_FUNC xopen_nonblocking(const char *pathname)
-{
- return xopen(pathname, O_RDONLY | O_NONBLOCK);
-}
-
// Warn if we can't open a file and return a fd.
int FAST_FUNC open3_or_warn(const char *pathname, int flags, int mode)
{
@@ -167,6 +158,32 @@
return open3_or_warn(pathname, flags, 0666);
}
+/* Die if we can't open an existing file readonly with O_NONBLOCK
+ * and return the fd.
+ * Note that for ioctl O_RDONLY is sufficient.
+ */
+int FAST_FUNC xopen_nonblocking(const char *pathname)
+{
+ return xopen(pathname, O_RDONLY | O_NONBLOCK);
+}
+
+int FAST_FUNC xopen_as_uid_gid(const char *pathname, int flags, uid_t u, gid_t g)
+{
+ int fd;
+ uid_t old_euid = geteuid();
+ gid_t old_egid = getegid();
+
+ xsetegid(g);
+ xseteuid(u);
+
+ fd = xopen(pathname, flags);
+
+ xseteuid(old_euid);
+ xsetegid(old_egid);
+
+ return fd;
+}
+
void FAST_FUNC xunlink(const char *pathname)
{
if (unlink(pathname))
@@ -305,6 +322,11 @@
void FAST_FUNC xsetenv(const char *key, const char *value)
{
+#ifdef __BIONIC__
+ /* on login, can be NULL, and should not be for bionic */
+ if (environ == NULL)
+ bb_error_msg_and_die("environment is not initialized");
+#endif
if (setenv(key, value, 1))
bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
}
@@ -351,6 +373,16 @@
if (setuid(uid)) bb_perror_msg_and_die("setuid");
}
+void FAST_FUNC xsetegid(gid_t egid)
+{
+ if (setegid(egid)) bb_perror_msg_and_die("setegid");
+}
+
+void FAST_FUNC xseteuid(uid_t euid)
+{
+ if (seteuid(euid)) bb_perror_msg_and_die("seteuid");
+}
+
// Die if we can't chdir to a new path.
void FAST_FUNC xchdir(const char *path)
{
@@ -541,13 +573,11 @@
char* FAST_FUNC xmalloc_ttyname(int fd)
{
- char *buf = xzalloc(128);
- int r = ttyname_r(fd, buf, 127);
- if (r) {
- free(buf);
- buf = NULL;
- }
- return buf;
+ char buf[128];
+ int r = ttyname_r(fd, buf, sizeof(buf) - 1);
+ if (r)
+ return NULL;
+ return xstrdup(buf);
}
void FAST_FUNC generate_uuid(uint8_t *buf)
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index ec95af2..bb63da0 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -8,6 +8,12 @@
#include "libbb.h"
+/* some systems (eg Hurd) does not have MAXSYMLINKS definition,
+ * set it to some reasonable value if it isn't defined */
+#ifndef MAXSYMLINKS
+# define MAXSYMLINKS 20
+#endif
+
/*
* NOTE: This function returns a malloced char* that you will have to free
* yourself.
@@ -102,7 +108,8 @@
char* FAST_FUNC xmalloc_realpath(const char *path)
{
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
+#if defined(__GLIBC__) || \
+ (defined(__UCLIBC__) && UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 31))
/* glibc provides a non-standard extension */
/* new: POSIX.1-2008 specifies this behavior as well */
return realpath(path, NULL);