From 784eb9c2d2cbd8ec49ff40dbaba17f4407f3b85a Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 14 Oct 2014 14:16:34 -0500 Subject: Use O_CLOEXEC instead of O_RDONLY to signal loopfiles_rw() to close filehandles. --- lib/lib.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 7911315..19d28d2 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -421,8 +421,8 @@ void poke(void *ptr, uint64_t val, int size) // flags is O_RDONLY, stdout otherwise. An empty argument list calls // function() on just stdin/stdout. // -// Note: read only filehandles are automatically closed when function() -// returns, but writeable filehandles must be close by function() +// Note: pass O_CLOEXEC to automatically close filehandles when function() +// returns, otherwise filehandles must be closed by function() void loopfiles_rw(char **argv, int flags, int permissions, int failok, void (*function)(int fd, char *name)) { @@ -441,14 +441,14 @@ void loopfiles_rw(char **argv, int flags, int permissions, int failok, continue; } function(fd, *argv); - if (flags == O_RDONLY) close(fd); + if (flags & O_CLOEXEC) close(fd); } while (*++argv); } -// Call loopfiles_rw with O_RDONLY and !failok (common case). +// Call loopfiles_rw with O_RDONLY|O_CLOEXEC and !failok (common case). void loopfiles(char **argv, void (*function)(int fd, char *name)) { - loopfiles_rw(argv, O_RDONLY, 0, 0, function); + loopfiles_rw(argv, O_RDONLY|O_CLOEXEC, 0, 0, function); } // Slow, but small. -- cgit v1.2.3 From 5fcc71581abdf8839d10786d7ac437cc5b0bf4c5 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 18 Oct 2014 17:14:12 -0500 Subject: Factor out printf-style escape parsing logic from echo.c. --- lib/lib.c | 8 ++++++++ lib/lib.h | 1 + 2 files changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 19d28d2..dc2de12 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -283,6 +283,14 @@ int stridx(char *haystack, char needle) return off-haystack; } +int unescape(char c) +{ + char *from = "\\abefnrtv", *to = "\\\a\b\033\f\n\r\t\v"; + int idx = stridx(from, c); + + return (idx == -1) ? 0 : to[idx]; +} + // If *a starts with b, advance *a past it and return 1, else return 0; int strstart(char **a, char *b) { diff --git a/lib/lib.h b/lib/lib.h index 887c1d5..49b02bb 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -152,6 +152,7 @@ long atolx(char *c); long atolx_range(char *numstr, long low, long high); int numlen(long l); int stridx(char *haystack, char needle); +int unescape(char c); int strstart(char **a, char *b); off_t fdlength(int fd); void loopfiles_rw(char **argv, int flags, int permissions, int failok, -- cgit v1.2.3 From 977e48e1626b3e3f1f1f9b14f05ffc11e252455f Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 20 Oct 2014 19:52:29 -0500 Subject: Add TOYBOX_NORECURSE so xexec() won't make internal function calls. --- lib/xwrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/xwrap.c b/lib/xwrap.c index 341aac3..b7eb274 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -137,7 +137,7 @@ void xexec_optargs(int skip) // with a path isn't a builtin, so /bin/sh won't match the builtin sh. void xexec(char **argv) { - if (CFG_TOYBOX) toy_exec(argv); + if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE) toy_exec(argv); execvp(argv[0], argv); perror_exit("exec %s", argv[0]); -- cgit v1.2.3 From 21f3c8db00f0d4a3f0989559847d2564f4c73a11 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 20 Oct 2014 19:56:05 -0500 Subject: More static analysis fixes from Ashwini Sharma. --- lib/xwrap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/xwrap.c b/lib/xwrap.c index b7eb274..6216d91 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -94,6 +94,7 @@ void xprintf(char *format, ...) va_start(va, format); vprintf(format, va); + va_end(va); if (fflush(stdout) || ferror(stdout)) perror_exit("write"); } -- cgit v1.2.3 From 45b3882a1187f0e957efbc4fc5d797ba9603f545 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 27 Oct 2014 18:08:59 -0500 Subject: O_CLOEXEC was confusing the O_RDONLY test in loopfiles(), resulting in attempts to read from stdout instead of stdin for "-" or no arguments. --- lib/lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index dc2de12..5923176 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -437,12 +437,12 @@ void loopfiles_rw(char **argv, int flags, int permissions, int failok, int fd; // If no arguments, read from stdin. - if (!*argv) function(flags ? 1 : 0, "-"); + if (!*argv) function((flags & O_ACCMODE) != O_RDONLY ? 1 : 0, "-"); else do { // Filename "-" means read from stdin. // Inability to open a file prints a warning, but doesn't exit. - if (!strcmp(*argv,"-")) fd=0; + if (!strcmp(*argv, "-")) fd=0; else if (0>(fd = open(*argv, flags, permissions)) && !failok) { perror_msg("%s", *argv); toys.exitval = 1; -- cgit v1.2.3 From 6e087a3a6fb420efc5cb77e13818668212034225 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 11 Nov 2014 15:08:25 -0600 Subject: Remove unnecessary assignment spotted by Cynt Rynt. --- lib/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/password.c b/lib/password.c index 40cbead..985bd57 100644 --- a/lib/password.c +++ b/lib/password.c @@ -156,7 +156,7 @@ int update_password(char *filename, char* username, char* entry) } *sfx = '-'; - ret = unlink(filenamesfx); + unlink(filenamesfx); ret = link(filename, filenamesfx); if (ret < 0) error_msg("can't create backup file"); -- cgit v1.2.3 From 46ddf0e34b03f7711a9c80f7a70dc8cbf732f782 Mon Sep 17 00:00:00 2001 From: Isaac Dunham Date: Wed, 19 Nov 2014 16:38:46 -0600 Subject: probe for getspnam(), forkpty(), utmpx, replace sethostname() Android is missing all of these; we need to probe for some so we have a config symbol to depend on. sethostname() is easily replaced. We got termios.h via pty.h; now it's not included in configure-step tools, so we need termios.h to generate globals. --- lib/portability.c | 10 ++++++++++ lib/portability.h | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/portability.c b/lib/portability.c index d901a4b..29608bc 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -5,6 +5,9 @@ */ #include "toys.h" +#if defined(__ANDROID__) +#include +#endif #if defined(__APPLE__) || defined(__ANDROID__) ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) @@ -61,6 +64,13 @@ ssize_t getline(char **linep, size_t *np, FILE *stream) } #endif +#if defined(__ANDROID__) +int sethostname(const char *name, size_t len) +{ + return syscall(__NR_sethostname, name, len); +} +#endif + #if defined(__APPLE__) extern char **environ; diff --git a/lib/portability.h b/lib/portability.h index b7a7c79..5383efa 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -180,10 +180,25 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); #endif // Linux headers not listed by POSIX or LSB -#include #include #include +// Android is missing some headers and functions +#if defined(__ANDROID__) +int sethostname(const char *name, size_t len); +#endif +// "generated/config.h" is included first +#if defined(CFG_TOYBOX_SHADOW) && CFG_TOYBOX_SHADOW +#include +#endif +#if defined(CFG_TOYBOX_UTMPX) && CFG_TOYBOX_UTMPX +#include +#endif +#if defined(CFG_TOYBOX_PTY) && CFG_TOYBOX_PTY +#include +#endif + + // Some systems don't define O_NOFOLLOW, and it varies by architecture, so... #include #ifndef O_NOFOLLOW -- cgit v1.2.3 From 561478541dbeb92e2c82c2fda7b43461293938e9 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 19 Nov 2014 16:55:12 -0600 Subject: Fixups for the android/bionic build probes patch. The CFG_* symbols are always defined so if() can use them as compile-time constants, so don't if defined() them. Doing USE_BLAH() around variable definitions opens up the same potential for config-dependent build breaks as #ifdefs do, just make the whole command depend on the symbol for now, factor out the utmpx infrastructure later. The PTY probe was always failing because it used NULL without #including the header that defines it. Substitute 0 instead. --- lib/portability.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 5383efa..0dace96 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -188,14 +188,16 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); int sethostname(const char *name, size_t len); #endif // "generated/config.h" is included first -#if defined(CFG_TOYBOX_SHADOW) && CFG_TOYBOX_SHADOW +#if CFG_TOYBOX_SHADOW #include #endif -#if defined(CFG_TOYBOX_UTMPX) && CFG_TOYBOX_UTMPX +#if CFG_TOYBOX_UTMPX #include #endif -#if defined(CFG_TOYBOX_PTY) && CFG_TOYBOX_PTY +#if CFG_TOYBOX_PTY #include +#else +pid_t forkpty(int *amaster, char *name, void *termp, void *winp); #endif -- cgit v1.2.3 From 69a9f257234a32b3aab2b0cdced8e898c940d3e9 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 21 Nov 2014 06:42:37 -0600 Subject: Patch from Elliott Hughes for Android/bionic build. --- lib/portability.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 0dace96..548c128 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -11,7 +11,10 @@ // This makes it stop. +// Except on Android, where fortify is mandatory. +#if !defined(__ANDROID__) #undef _FORTIFY_SOURCE +#endif // For musl #define _ALL_SOURCE @@ -173,7 +176,7 @@ int clearenv(void); #define SWAP_LE64(x) (x) #endif -#if defined(__APPLE__) || defined(__ANDROID__) \ +#if defined(__APPLE__) \ || (defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 10) ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); ssize_t getline(char **lineptr, size_t *n, FILE *stream); -- cgit v1.2.3 From 3280d995b3447b7a94af006ac26d7d3656aee961 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 21 Nov 2014 10:06:45 -0600 Subject: Don't include asm/* files directly. --- lib/portability.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/portability.c b/lib/portability.c index 29608bc..17efc91 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -6,7 +6,7 @@ #include "toys.h" #if defined(__ANDROID__) -#include +#include #endif #if defined(__APPLE__) || defined(__ANDROID__) -- cgit v1.2.3 From 6a29bb1ebe62ada2dad5fb50f84f23a497cd677a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 21 Nov 2014 21:49:05 -0600 Subject: A patch against your current ToT that builds in AOSP master. --- lib/portability.c | 14 +------------- lib/portability.h | 3 --- 2 files changed, 1 insertion(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/portability.c b/lib/portability.c index 17efc91..910b1ea 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -5,11 +5,8 @@ */ #include "toys.h" -#if defined(__ANDROID__) -#include -#endif -#if defined(__APPLE__) || defined(__ANDROID__) +#if defined(__APPLE__) ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) { int ch; @@ -62,16 +59,7 @@ ssize_t getline(char **linep, size_t *np, FILE *stream) { return getdelim(linep, np, '\n', stream); } -#endif - -#if defined(__ANDROID__) -int sethostname(const char *name, size_t len) -{ - return syscall(__NR_sethostname, name, len); -} -#endif -#if defined(__APPLE__) extern char **environ; int clearenv(void) diff --git a/lib/portability.h b/lib/portability.h index 548c128..2f2421d 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -187,9 +187,6 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); #include // Android is missing some headers and functions -#if defined(__ANDROID__) -int sethostname(const char *name, size_t len); -#endif // "generated/config.h" is included first #if CFG_TOYBOX_SHADOW #include -- cgit v1.2.3 From f6c28b6e0017ac36190ee31132721a1c9e30f2b6 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 22 Nov 2014 00:36:45 -0600 Subject: As long as Android's going to require fortify, fixup the warnings it generates. --- lib/portability.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 2f2421d..d58e592 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -4,18 +4,6 @@ // in specific compiler, library, or OS versions, localize all that here // and in portability.c -// The tendency of gcc to produce stupid warnings continues with -// warn_unused_result, which warns about things like ignoring the return code -// of nice(2) (which is completely useless since -1 is a legitimate return -// value on success and even the man page tells you to use errno instead). - -// This makes it stop. - -// Except on Android, where fortify is mandatory. -#if !defined(__ANDROID__) -#undef _FORTIFY_SOURCE -#endif - // For musl #define _ALL_SOURCE -- cgit v1.2.3 From 6d28370f22aa6b7c97a57a434339fa57ce322c8b Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 28 Nov 2014 16:57:45 -0600 Subject: Make sendfile use libbuf. --- lib/xwrap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/xwrap.c b/lib/xwrap.c index 6216d91..a2dd1c6 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -587,13 +587,12 @@ void xpidfile(char *name) void xsendfile(int in, int out) { long len; - char buf[4096]; if (in<0) return; for (;;) { - len = xread(in, buf, 4096); + len = xread(in, libbuf, sizeof(libbuf)); if (len<1) break; - xwrite(out, buf, len); + xwrite(out, libbuf, len); } } -- cgit v1.2.3 From 2fb85a3588bf2271e0506c5ab3bcb6a84bf77255 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 4 Dec 2014 21:41:12 -0600 Subject: Implement xstrncat() and fix xstrndup(). --- lib/lib.h | 1 + lib/xwrap.c | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index 49b02bb..0755539 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -81,6 +81,7 @@ void show_help(void); // xwrap.c void xstrncpy(char *dest, char *src, size_t size); +void xstrncat(char *dest, char *src, size_t size); void xexit(void) noreturn; void *xmalloc(size_t size); void *xzalloc(size_t size); diff --git a/lib/xwrap.c b/lib/xwrap.c index a2dd1c6..96db352 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -9,13 +9,25 @@ #include "toys.h" -// Strcpy with size checking: exit if there's not enough space for the string. +// strcpy and strncat with size checking. Size is the total space in "dest", +// including null terminator. Exit if there's not enough space for the string +// (including space for the null terminator), because silently truncating is +// still broken behavior. (And leaving the string unterminated is INSANE.) void xstrncpy(char *dest, char *src, size_t size) { if (strlen(src)+1 > size) error_exit("'%s' > %ld bytes", src, (long)size); strcpy(dest, src); } +void xstrncat(char *dest, char *src, size_t size) +{ + long len = strlen(src); + + if (len+strlen(dest)+1 > size) + error_exit("'%s%s' > %ld bytes", src, (long)size); + strcpy(dest+len, src); +} + void xexit(void) { if (toys.rebound) longjmp(*toys.rebound, 1); @@ -52,9 +64,10 @@ void *xrealloc(void *ptr, size_t size) // Die unless we can allocate a copy of this many bytes of string. char *xstrndup(char *s, size_t n) { - char *ret = xmalloc(++n); - strncpy(ret, s, n); - ret[--n]=0; + char *ret = strndup(s, ++n); + + if (!ret) error_exit("xstrndup"); + ret[--n] = 0; return ret; } -- cgit v1.2.3 From 50fc9ed007b084883fb09c64866c45c571e70a99 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 4 Dec 2014 21:46:59 -0600 Subject: Work with buildroot's extensively patched uClibc, and for nommu support move xfork() to portability.h and #ifdef based on __uClinux__ (which seems to be the nommu compiler define). --- lib/lib.h | 1 - lib/portability.c | 11 +++++++++++ lib/portability.h | 21 +++++++++++++++++++++ lib/xwrap.c | 9 --------- 4 files changed, 32 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index 0755539..a51ae07 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -93,7 +93,6 @@ void xprintf(char *format, ...); void xputs(char *s); void xputc(char c); void xflush(void); -pid_t xfork(void); void xexec_optargs(int skip); void xexec(char **argv); pid_t xpopen_both(char **argv, int *pipes); diff --git a/lib/portability.c b/lib/portability.c index 910b1ea..7d6d85f 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -6,6 +6,17 @@ #include "toys.h" +#if !defined(__uClinux__) +pid_t xfork(void) +{ + pid_t pid = fork(); + + if (pid < 0) perror_exit("fork"); + + return pid; +} +#endif + #if defined(__APPLE__) ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) { diff --git a/lib/portability.h b/lib/portability.h index d58e592..1464c65 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -72,13 +72,28 @@ pid_t getsid(pid_t pid); // any flag newer than MS_MOVE, which was added in 2001 (linux 2.5.0.5), // eleven years earlier. +#include +#ifndef MS_MOVE #define MS_MOVE (1<<13) +#endif +#ifndef MS_REC #define MS_REC (1<<14) +#endif +#ifndef MS_SILENT #define MS_SILENT (1<<15) +#endif +#ifndef MS_UNBINDABLE #define MS_UNBINDABLE (1<<17) +#endif +#ifndef MS_PRIVATE #define MS_PRIVATE (1<<18) +#endif +#ifndef MS_SLAVE #define MS_SLAVE (1<<19) +#endif +#ifndef MS_SHARED #define MS_SHARED (1<<20) +#endif // When building under obsolete glibc (Ubuntu 8.04-ish), hold its hand a bit. #elif __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 @@ -206,3 +221,9 @@ typedef double FLOAT; typedef float FLOAT; #endif +#ifndef __uClinux__ +pid_t xfork(void); +#endif + +//#define strncpy(...) @@strncpyisbadmmkay@@ +//#define strncat(...) @@strcatisbadmmkay@@ diff --git a/lib/xwrap.c b/lib/xwrap.c index 96db352..d703065 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -127,15 +127,6 @@ void xflush(void) if (fflush(stdout) || ferror(stdout)) perror_exit("write");; } -pid_t xfork(void) -{ - pid_t pid = fork(); - - if (pid < 0) perror_exit("fork"); - - return pid; -} - // Call xexec with a chunk of optargs, starting at skip. (You can't just // call xexec() directly because toy_init() frees optargs.) void xexec_optargs(int skip) -- cgit v1.2.3 From 87fbe12dbba8278d58d6581626e4cf4224dbca8d Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 13 Dec 2014 11:56:41 -0600 Subject: Remove more strncpy() calls. The semantics of strncat() and strncpy() are non-obvious, so let's not use 'em. Both zero all their remaining buffer space, and with strncat() the size is the space left at the _end_ of the string (not the size of the buffer) so it's way too easy to stomp memory you don't own. As long as we have to measure stuff ourselves to get it right, just use memcpy(). --- lib/lib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 5923176..33be44b 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -177,7 +177,7 @@ struct string_list **splitpath(char *path, struct string_list **list) if (len > 0) { *list = xmalloc(sizeof(struct string_list) + len + 1); (*list)->next = 0; - strncpy((*list)->str, new, len); + memcpy((*list)->str, new, len); (*list)->str[len] = 0; list = &(*list)->next; } @@ -210,7 +210,8 @@ struct string_list *find_in_path(char *path, char *filename) if (!len) sprintf(rnext->str, "%s/%s", cwd, filename); else { char *res = rnext->str; - strncpy(res, path, len); + + memcpy(res, path, len); res += len; *(res++) = '/'; strcpy(res, filename); -- cgit v1.2.3 From 0517eb7d604da454213e42d55f477401dc7f7ebf Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 13 Dec 2014 11:58:08 -0600 Subject: Add base64. The tizen guys wanted this. Yeah, I know there's base64 code in uuencode/uudecode, but that this has -i, input lines aren't of fixed length, encode/decode are in same file, there's no prefix/suffix code, it always writes to stdout... Eliminating the code duplication wouldn't be worth the if/else I'd have to add, so I just did a new one. Factored out the base64 table init into lib.c though: that was worth sharing. --- lib/lib.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 33be44b..490235f 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -571,6 +571,21 @@ void crc_init(unsigned int *crc_table, int little_endian) } } +// Init base64 table + +void base64_init(char *p) +{ + int i; + + for (i = 'A'; i != ':'; i++) { + if (i == 'Z'+1) i = 'a'; + if (i == 'z'+1) i = '0'; + *(p++) = i; + } + *(p++) = '+'; + *(p++) = '/'; +} + // Quick and dirty query size of terminal, doesn't do ANSI probe fallback. // set x=80 y=25 before calling to provide defaults. Returns 0 if couldn't // determine size. -- cgit v1.2.3 From 5bec5ba825d07b7be73ff16b3d9c649248690783 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 13 Dec 2014 11:59:37 -0600 Subject: Forgot to check in a header file for base64. --- lib/lib.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index a51ae07..00c7a05 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -166,12 +166,14 @@ int copy_tempfile(int fdin, char *name, char **tempname); void delete_tempfile(int fdin, int fdout, char **tempname); void replace_tempfile(int fdin, int fdout, char **tempname); void crc_init(unsigned int *crc_table, int little_endian); +void base64_init(char *p); int terminal_size(unsigned *x, unsigned *y); int yesno(char *prompt, int def); int human_readable(char *buf, unsigned long long num); // net.c int xsocket(int domain, int type, int protocol); +void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len); // password.c int get_salt(char *salt, char * algo); -- cgit v1.2.3 From 9b5000c920f2ba44dea1ef45f3a23191d46489b8 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 22 Dec 2014 17:04:47 -0600 Subject: Allocate space for null terminator. --- lib/lib.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 490235f..ade0786 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -512,8 +512,7 @@ int copy_tempfile(int fdin, char *name, char **tempname) struct stat statbuf; int fd; - *tempname = xstrndup(name, strlen(name)+6); - strcat(*tempname,"XXXXXX"); + *tempname = xmprintf("%s%s", name, "XXXXXX"); if(-1 == (fd = mkstemp(*tempname))) error_exit("no temp file"); if (!tempfile2zap) sigatexit(tempfile_handler); tempfile2zap = *tempname; -- cgit v1.2.3 From de699accf6804e8b1d8042b46c85500ee8c672c6 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 31 Dec 2014 16:22:31 -0600 Subject: When you include the posix header libgen.h, glibc #defines basename to some random other symbol name (because gnu) and this screws up nontrivial macro expansions of NEWTOY(basename), so work around it in portability.h. --- lib/portability.c | 8 ++++++++ lib/portability.h | 9 +++++++++ 2 files changed, 17 insertions(+) (limited to 'lib') diff --git a/lib/portability.c b/lib/portability.c index 7d6d85f..4fd1e22 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -6,6 +6,14 @@ #include "toys.h" +#if defined(__GLIBC__) +#include +char *basename(char *path) +{ + return __xpg_basename(path); +} +#endif + #if !defined(__uClinux__) pid_t xfork(void) { diff --git a/lib/portability.h b/lib/portability.h index 1464c65..8bbbdb2 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -60,6 +60,15 @@ int wcwidth(wchar_t wc); #include char *strptime(const char *buf, const char *format, struct tm *tm); +// They didn't like posix basename so they defined another function with the +// same name and if you include libgen.h it #defines basename to something +// else (where they implemented the real basename), and that define breaks +// the table entry for the basename command. They didn't make a new function +// with a different name for their new behavior because gnu. +// +// Implement our own in portability.c and don't use their broken header. +char *basename(char *path); + // uClibc pretends to be glibc and copied a lot of its bugs, but has a few more #if defined(__UCLIBC__) #include -- cgit v1.2.3 From f3e56f4e4ff773de95fa2c9daf979734d826fc33 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 31 Dec 2014 21:30:59 -0600 Subject: Redo option parsing infrastructure so #define FORCE_FLAGS can unzero flag macros for a disabled command (needed when multiple commands share infrastructure with a common set of flags). This means the flag space is no longer packed, but leaves gaps where the zeroes go. (Actual flag bit positions are the same for all configs.) Since the option parsing needs to know where the holes are, the OPTSTR values are now generated as part of flags.h with ascii 1 values for the disabled values. (So generated/oldflags.h went away.) This also means that the option string argument for OLDTOY() went away, it now uses the same arguments as the NEWTOY() it references. --- lib/help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/help.c b/lib/help.c index 9965539..b5d8f6b 100644 --- a/lib/help.c +++ b/lib/help.c @@ -10,7 +10,7 @@ void show_help(void) {;} #undef NEWTOY #undef OLDTOY #define NEWTOY(name,opt,flags) help_##name "\0" -#define OLDTOY(name,oldname,opts,flags) "\xff" #oldname "\0" +#define OLDTOY(name,oldname,flags) "\xff" #oldname "\0" static char *help_data = #include "generated/newtoys.h" ; -- cgit v1.2.3 From cf2516ab4bcf2c1d4cb571539dae794c6a40c5c6 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 1 Jan 2015 16:19:40 -0600 Subject: Debris from flag handling rewrite: don't allow -^A to actually trigger. --- lib/args.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/args.c b/lib/args.c index d0b483a..b385dd4 100644 --- a/lib/args.c +++ b/lib/args.c @@ -327,6 +327,7 @@ void parse_optflaglist(struct getoptflagstate *gof) for (new = gof->opts; new; new = new->next) { unsigned u = 1<c == 1) new->c = 0; new->dex[1] = u; if (new->flags & 1) gof->requires |= u; if (new->type) { -- cgit v1.2.3 From 86c747a4493b2b1aabab9b20d1c4566fddeeb2ca Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 1 Jan 2015 16:28:51 -0600 Subject: strtol() doesn't return error indicator for overflow, it just sets errno. So add estrtol() (which clears errno first), and xstrtol() (which error_exit()s on overflow). --- lib/lib.c | 28 +++++++++++++++++++++++----- lib/lib.h | 2 ++ 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index ade0786..808c149 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -233,13 +233,30 @@ struct string_list *find_in_path(char *path, char *filename) return rlist; } +long estrtol(char *str, char **end, int base) +{ + errno = 0; + + return strtol(str, end, base); +} + +long xstrtol(char *str, char **end, int base) +{ + long l = estrtol(str, end, base); + + if (errno) perror_exit("%s", str); + + return l; +} + // atol() with the kilo/mega/giga/tera/peta/exa extensions. // (zetta and yotta don't fit in 64 bits.) long atolx(char *numstr) { char *c, *suffixes="cbkmgtpe", *end; - long val = strtol(numstr, &c, 0); + long val; + val = xstrtol(numstr, &c, 0); if (*c) { if (c != numstr && (end = strchr(suffixes, tolower(*c)))) { int shift = end-suffixes-2; @@ -685,8 +702,9 @@ int sig_to_num(char *pidstr) if (pidstr) { char *s; - i = strtol(pidstr, &s, 10); - if (!*s) return i; + + i = estrtol(pidstr, &s, 10); + if (!errno && !*s) return i; if (!strncasecmp(pidstr, "sig", 3)) pidstr+=3; } @@ -715,8 +733,8 @@ mode_t string_to_mode(char *modestr, mode_t mode) // Handle octal mode if (isdigit(*str)) { - mode = strtol(str, &s, 8); - if (*s || (mode & ~(07777))) goto barf; + mode = estrtol(str, &s, 8); + if (errno || *s || (mode & ~(07777))) goto barf; return mode | extrabits; } diff --git a/lib/lib.h b/lib/lib.h index 00c7a05..34c1a19 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -148,6 +148,8 @@ int64_t peek_be(void *ptr, unsigned size); int64_t peek(void *ptr, unsigned size); void poke(void *ptr, uint64_t val, int size); struct string_list *find_in_path(char *path, char *filename); +long estrtol(char *str, char **end, int base); +long xstrtol(char *str, char **end, int base); long atolx(char *c); long atolx_range(char *numstr, long low, long high); int numlen(long l); -- cgit v1.2.3 From aad492fd87d689c443e87561c23abc2e12b785a9 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 3 Jan 2015 16:25:36 -0600 Subject: Move fflush() checking to xexit() and have exit paths in main() call that. --- lib/xwrap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/xwrap.c b/lib/xwrap.c index d703065..de7ae83 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -30,6 +30,8 @@ void xstrncat(char *dest, char *src, size_t size) void xexit(void) { + if (fflush(NULL) || ferror(stdout)) + if (!toys.exitval) perror_msg("write"); if (toys.rebound) longjmp(*toys.rebound, 1); else exit(toys.exitval); } -- cgit v1.2.3 From 7e2af1c7489cbf974a57d482bb9d23c884d2aa49 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 16 Jan 2015 13:36:53 -0600 Subject: This patch adds a TOYBOX_SELINUX configuration option to control both the SELinux commands (such as chcon) and the SELinux-specific options to regular commands (such as ls -Z). This lets us #include in portability.h. I've also fixed chcon to insist on being given the a context argument. This patch also adds -Z to id and fixes id's regular output (-G should be separated by spaces, non-G output should be separated by commas, and you don't want a double comma where the egid is omitted from the list of groups). --- lib/portability.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 8bbbdb2..67ac5b5 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -236,3 +236,7 @@ pid_t xfork(void); //#define strncpy(...) @@strncpyisbadmmkay@@ //#define strncat(...) @@strcatisbadmmkay@@ + +#if CFG_TOYBOX_SELINUX +#include +#endif -- cgit v1.2.3 From 3b915991f8c8648f939498777f4d76aad04f2817 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 16 Jan 2015 13:43:09 -0600 Subject: id.c #ifdefectomy. (ifdefs belong in headers, not in C code.) --- lib/portability.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 67ac5b5..4097def 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -239,4 +239,7 @@ pid_t xfork(void); #if CFG_TOYBOX_SELINUX #include +#else +#define is_selinux_enabled() 0 +int getcon(void* con); #endif -- cgit v1.2.3 From c2415d16a8991e2192bda002baab840bfa4d5d79 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 16 Jan 2015 13:49:23 -0600 Subject: AOSP master has and builds netcat/nc. --- lib/portability.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 4097def..9a7b349 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -206,11 +206,8 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); #if CFG_TOYBOX_UTMPX #include #endif -#if CFG_TOYBOX_PTY + #include -#else -pid_t forkpty(int *amaster, char *name, void *termp, void *winp); -#endif // Some systems don't define O_NOFOLLOW, and it varies by architecture, so... -- cgit v1.2.3 From 0a4bd4b89f9a17e4ba8c7873d1384fb04f79b14d Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 16 Jan 2015 13:55:32 -0600 Subject: Move pty.h back to toys.h (under LSB 4.1 headers). --- lib/portability.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 9a7b349..f6f7672 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -207,9 +207,6 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); #include #endif -#include - - // Some systems don't define O_NOFOLLOW, and it varies by architecture, so... #include #ifndef O_NOFOLLOW -- cgit v1.2.3 From e910826c812fcde8d122990a1e43e17f46b6d03f Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Sun, 18 Jan 2015 13:36:31 -0600 Subject: fix non-glibc basename(3) usage I considered a #else on the big #ifdef __GLIBC__ above, but that seemed harder to follow. --- lib/portability.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index f6f7672..bb1f5ae 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -141,6 +141,11 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag #endif +#ifndef __GLIBC__ +// POSIX basename. +#include +#endif + #ifdef __MUSL__ #include // Without this "rm -r dir" fails with "is directory". -- cgit v1.2.3 From 468f155ecefec275e6d2299470d35bd912f69a94 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 18 Jan 2015 13:44:24 -0600 Subject: Lift the basename/libgen.h shenanigans back out of portability.c and make it a static inline in portability.h, and prototype dirname() while we're at it. --- lib/portability.c | 8 -------- lib/portability.h | 12 ++++++++---- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/portability.c b/lib/portability.c index 4fd1e22..7d6d85f 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -6,14 +6,6 @@ #include "toys.h" -#if defined(__GLIBC__) -#include -char *basename(char *path) -{ - return __xpg_basename(path); -} -#endif - #if !defined(__uClinux__) pid_t xfork(void) { diff --git a/lib/portability.h b/lib/portability.h index bb1f5ae..143d10f 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -66,8 +66,12 @@ char *strptime(const char *buf, const char *format, struct tm *tm); // the table entry for the basename command. They didn't make a new function // with a different name for their new behavior because gnu. // -// Implement our own in portability.c and don't use their broken header. -char *basename(char *path); +// Solution: don't use their broken header, provide an inline to redirect the +// correct name to the broken name. + +char *dirname(char *path); +char *__xpg_basename (char *path); +static inline char *basename(char *path) { return __xpg_basename(path); } // uClibc pretends to be glibc and copied a lot of its bugs, but has a few more #if defined(__UCLIBC__) @@ -137,9 +141,9 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag #ifndef MNT_DETACH #define MNT_DETACH 2 #endif -#endif +#endif // Old glibc -#endif +#endif // glibc in general #ifndef __GLIBC__ // POSIX basename. -- cgit v1.2.3 From 2c1cf4a02783e2a570ddf7b7ea968c7bed781f91 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 18 Jan 2015 14:06:14 -0600 Subject: Remove trailing whitespace. --- lib/args.c | 1 - lib/lib.c | 2 +- lib/password.c | 8 ++++---- lib/xwrap.c | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/args.c b/lib/args.c index b385dd4..592d33c 100644 --- a/lib/args.c +++ b/lib/args.c @@ -82,7 +82,6 @@ // + Synonyms (switch on all) [+abc] means -ab=-abc, -c=-abc // ! More than one in group is error [!abc] means -ab calls error_exit() // primarily useful if you can switch things back off again. -// // Notes from getopt man page // - and -- cannot be arguments. diff --git a/lib/lib.c b/lib/lib.c index 808c149..f70d379 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -155,7 +155,7 @@ int mkpathat(int atfd, char *dir, mode_t lastmode, int flags) if (!(flags&2) || errno != EEXIST) return 1; } else if (flags&4) fprintf(stderr, "%s: created directory '%s'\n", toys.which->name, dir); - + if (!(*s = save)) break; } diff --git a/lib/password.c b/lib/password.c index 985bd57..b3cc199 100644 --- a/lib/password.c +++ b/lib/password.c @@ -8,7 +8,7 @@ // generate appropriate random salt string for given encryption algorithm. int get_salt(char *salt, char *algo) -{ +{ struct { char *type, id, len; } al[] = {{"des", 0, 2}, {"md5", 1, 8}, {"sha256", 5, 16}, {"sha512", 6, 16}}; @@ -128,9 +128,9 @@ static char *get_nextcolon(char *line, int cnt) } /*update_password is used by multiple utilities to update /etc/passwd, - * /etc/shadow, /etc/group and /etc/gshadow files, + * /etc/shadow, /etc/group and /etc/gshadow files, * which are used as user, group databeses - * entry can be + * entry can be * 1. encrypted password, when updating user password. * 2. complete entry for user details, when creating new user * 3. group members comma',' separated list, when adding user to group @@ -197,7 +197,7 @@ int update_password(char *filename, char* username, char* entry) current_ptr = get_nextcolon(current_ptr, 1); fprintf(newfp, "%s\n",current_ptr); } else fprintf(newfp, "%s\n",current_ptr); - } else if (!strcmp(toys.which->name, "groupadd") || + } else if (!strcmp(toys.which->name, "groupadd") || !strcmp(toys.which->name, "addgroup") || !strcmp(toys.which->name, "delgroup") || !strcmp(toys.which->name, "groupdel")){ diff --git a/lib/xwrap.c b/lib/xwrap.c index de7ae83..bfe1c8e 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -349,7 +349,7 @@ void xstat(char *path, struct stat *st) // Cannonicalize path, even to file with one or more missing components at end. // if exact, require last path component to exist -char *xabspath(char *path, int exact) +char *xabspath(char *path, int exact) { struct string_list *todo, *done = 0; int try = 9999, dirfd = open("/", 0);; @@ -610,7 +610,7 @@ long xparsetime(char *arg, long units, long *fraction) if (CFG_TOYBOX_FLOAT) d = strtod(arg, &arg); else l = strtoul(arg, &arg, 10); - + // Parse suffix if (*arg) { int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *arg); -- cgit v1.2.3 From bd6c3f35ae226125737503dddac48e7924425b49 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 6 Feb 2015 16:42:44 -0600 Subject: Alright, the Android guys agree with the musl guys: faccessat(AT_SYMLINK_NOFOLLOW) is not supported. --- lib/portability.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 143d10f..70e33bf 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -150,12 +150,6 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag #include #endif -#ifdef __MUSL__ -#include -// Without this "rm -r dir" fails with "is directory". -#define faccessat(A, B, C, D) faccessat(A, B, C, 0) -#endif - // Work out how to do endianness #ifndef __APPLE__ -- cgit v1.2.3 From fb4ae952a6d75ae74a84fc2599f58c3c5398af8b Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 7 Feb 2015 16:23:59 -0600 Subject: Remove xexec_optargs(). --- lib/lib.h | 1 - lib/xwrap.c | 11 ----------- 2 files changed, 12 deletions(-) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index 34c1a19..621ed27 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -93,7 +93,6 @@ void xprintf(char *format, ...); void xputs(char *s); void xputc(char c); void xflush(void); -void xexec_optargs(int skip); void xexec(char **argv); pid_t xpopen_both(char **argv, int *pipes); int xpclose_both(pid_t pid, int *pipes); diff --git a/lib/xwrap.c b/lib/xwrap.c index bfe1c8e..cd3c684 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -129,17 +129,6 @@ void xflush(void) if (fflush(stdout) || ferror(stdout)) perror_exit("write");; } -// Call xexec with a chunk of optargs, starting at skip. (You can't just -// call xexec() directly because toy_init() frees optargs.) -void xexec_optargs(int skip) -{ - char **s = toys.optargs; - - toys.optargs = 0; - xexec(s+skip); -} - - // Die unless we can exec argv[] (or run builtin command). Note that anything // with a path isn't a builtin, so /bin/sh won't match the builtin sh. void xexec(char **argv) -- cgit v1.2.3 From c277f347bba2417106b32212d9d40aceb4a88fb5 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 9 Feb 2015 16:34:24 -0600 Subject: Cleanup/refactoring pass on hwclock. Inline open_wall_clock_rtc() into rtc_open(), factor out xtzset(), inline set_sysclock_from_hwclock(), set_hwclock_from_sysclock(), and set_sysclock_timezone(). /etc/adjtime is short enough we don't need to bother with a break. The final "else" case in main() should always trigger because >0 in optstr says "at most zero arguments", so the || at the end is always true, so take the test off. --- lib/lib.h | 1 + lib/xwrap.c | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index 621ed27..a659b69 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -128,6 +128,7 @@ char *xreadlink(char *name); long xparsetime(char *arg, long units, long *fraction); void xpidfile(char *name); void xregcomp(regex_t *preg, char *rexec, int cflags); +char *xtzset(char *new); // lib.c void verror_msg(char *msg, int err, va_list va); diff --git a/lib/xwrap.c b/lib/xwrap.c index cd3c684..0a2b38f 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -627,3 +627,14 @@ void xregcomp(regex_t *preg, char *regex, int cflags) error_exit("xregcomp: %s", libbuf); } } + +char *xtzset(char *new) +{ + char *tz = getenv("TZ"); + + if (tz) tz = xstrdup(tz); + if (setenv("TZ", new, 1)) perror_exit("setenv"); + tzset(); + + return tz; +} -- cgit v1.2.3 From 70a84a356b1c56743618362867b9300007d11998 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 1 Mar 2015 15:58:40 -0600 Subject: Patches from Elliott Hughes to add missing arguments to error_exit() calls. --- lib/xwrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/xwrap.c b/lib/xwrap.c index 0a2b38f..14703a7 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -24,7 +24,7 @@ void xstrncat(char *dest, char *src, size_t size) long len = strlen(src); if (len+strlen(dest)+1 > size) - error_exit("'%s%s' > %ld bytes", src, (long)size); + error_exit("'%s%s' > %ld bytes", dest, src, (long)size); strcpy(dest+len, src); } -- cgit v1.2.3 From 1be99e695059ba7dbe44765f4b477f7e173e98d1 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Sun, 1 Mar 2015 16:16:50 -0600 Subject: let the compiler check format strings i'll be AFK for a week, so here's the patch i've been using this evening to find other format string mistakes. BSD uses __printflike and takes two arguments instead of hard-coding (1,2), but i figured that as long as you don't need the generality you'd prefer not to have it. and it's easy enough to retrofit if we ever do have a formatting function that takes other arguments. --- lib/lib.h | 12 ++++++------ lib/portability.h | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index a659b69..a183fd5 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -88,8 +88,8 @@ void *xzalloc(size_t size); void *xrealloc(void *ptr, size_t size); char *xstrndup(char *s, size_t n); char *xstrdup(char *s); -char *xmprintf(char *format, ...); -void xprintf(char *format, ...); +char *xmprintf(char *format, ...) printf_format; +void xprintf(char *format, ...) printf_format; void xputs(char *s); void xputc(char c); void xflush(void); @@ -132,10 +132,10 @@ char *xtzset(char *new); // lib.c void verror_msg(char *msg, int err, va_list va); -void error_msg(char *msg, ...); -void perror_msg(char *msg, ...); -void error_exit(char *msg, ...) noreturn; -void perror_exit(char *msg, ...) noreturn; +void error_msg(char *msg, ...) printf_format; +void perror_msg(char *msg, ...) printf_format; +void error_exit(char *msg, ...) printf_format noreturn; +void perror_exit(char *msg, ...) printf_format noreturn; ssize_t readall(int fd, void *buf, size_t len); ssize_t writeall(int fd, void *buf, size_t len); off_t lskip(int fd, off_t offset); diff --git a/lib/portability.h b/lib/portability.h index 70e33bf..809f376 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -11,8 +11,10 @@ #ifdef __GNUC__ #define noreturn __attribute__((noreturn)) +#define printf_format __attribute__((format(printf, 1, 2))) #else #define noreturn +#define printf_format #endif // Always use long file support. -- cgit v1.2.3 From eb4b1143b1f54a96002a83ea961d40d3169e1ae2 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 1 Mar 2015 16:35:05 -0600 Subject: Only switch on printf format warnings for error_exit() and friends when TOYBOX_DEBUG enabled. One again gcc manages to be incompetent about producing warnings. For example, in bzcat we error_exit() with a message that's an error code fed into an array of string constants, and apparently dereferencing an array of string literals doesn't give you a string literal according to -Wformat-security. Not breaking the code to humor the compiler here, the compiler is wrong. --- lib/portability.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 809f376..a10213e 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -11,8 +11,12 @@ #ifdef __GNUC__ #define noreturn __attribute__((noreturn)) +#if CFG_TOYBOX_DEBUG #define printf_format __attribute__((format(printf, 1, 2))) #else +#define printf_format +#endif +#else #define noreturn #define printf_format #endif -- cgit v1.2.3 From e6abb61e057d55a08c263a48648aaf7b776dfcee Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 9 Mar 2015 14:52:32 -0500 Subject: Upgrade oneit with -r (restart), -3 (send exiting PID values to child), and signal handling. --- lib/lib.h | 1 + lib/xwrap.c | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index a183fd5..e566751 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -129,6 +129,7 @@ long xparsetime(char *arg, long units, long *fraction); void xpidfile(char *name); void xregcomp(regex_t *preg, char *rexec, int cflags); char *xtzset(char *new); +void xsignal(int signal, void *handler); // lib.c void verror_msg(char *msg, int err, va_list va); diff --git a/lib/xwrap.c b/lib/xwrap.c index 14703a7..44cd168 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -638,3 +638,14 @@ char *xtzset(char *new) return tz; } + +// Set a signal handler +void xsignal(int signal, void *handler) +{ + struct sigaction *sa = (void *)libbuf; + + memset(sa, 0, sizeof(struct sigaction)); + sa->sa_handler = handler; + + if (sigaction(signal, sa, 0)) perror_exit("xsignal %d", signal); +} -- cgit v1.2.3 From b8140d18800e7094cdacb0a61526f46181dc132d Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 12 Mar 2015 11:11:08 -0500 Subject: Factor out xgetgrnamid() and xgetpwnamid() into xwrap.c. --- lib/lib.h | 2 ++ lib/xwrap.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index e566751..d8a1503 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -123,6 +123,8 @@ struct passwd *xgetpwuid(uid_t uid); struct group *xgetgrgid(gid_t gid); struct passwd *xgetpwnam(char *name); struct group *xgetgrnam(char *name); +struct passwd *xgetpwnamid(char *user); +struct group *xgetgrnamid(char *group); void xsetuser(struct passwd *pwd); char *xreadlink(char *name); long xparsetime(char *arg, long units, long *fraction); diff --git a/lib/xwrap.c b/lib/xwrap.c index 44cd168..54f2cbb 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -477,6 +477,38 @@ struct group *xgetgrgid(gid_t gid) return group; } +struct passwd *xgetpwnamid(char *user) +{ + struct passwd *up = getpwnam(user); + uid_t uid; + + if (!up) { + char *s = 0; + + uid = estrtol(user, &s, 10); + if (!errno && s && !*s) up = getpwuid(uid); + } + if (!up) perror_exit("user '%s'", user); + + return up; +} + +struct group *xgetgrnamid(char *group) +{ + struct group *gr = getgrnam(group); + gid_t gid; + + if (!gr) { + char *s = 0; + + gid = estrtol(group, &s, 10); + if (!errno && s && !*s) gr = getgrgid(gid); + } + if (!gr) perror_exit("group '%s'", group); + + return gr; +} + struct passwd *xgetpwnam(char *name) { struct passwd *up = getpwnam(name); -- cgit v1.2.3 From d111b9572125b70f821e89ac118c80bc4d9ad5b6 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 16 Mar 2015 13:25:29 -0500 Subject: Rename a function to better describe what it does. --- lib/getmountlist.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/getmountlist.c b/lib/getmountlist.c index 5f4bc63..c0e6875 100644 --- a/lib/getmountlist.c +++ b/lib/getmountlist.c @@ -41,7 +41,7 @@ char *comma_iterate(char **list, int *len) return start; } -static void deslash(char *s) +static void octal_deslash(char *s) { char *o = s; @@ -165,8 +165,8 @@ struct mtab_list *xgetmountlist(char *path) mt->opts = stpcpy(mt->device, me->mnt_fsname)+1; strcpy(mt->opts, me->mnt_opts); - deslash(mt->dir); - deslash(mt->device); + octal_deslash(mt->dir); + octal_deslash(mt->device); } endmntent(fp); -- cgit v1.2.3 From 4437be0e2610c8b537ba90c2ef35ddcf0bb5fc78 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 16 Mar 2015 13:27:16 -0500 Subject: Fix mount -a segfault without -O, reported by Janus Troelsen. --- lib/getmountlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/getmountlist.c b/lib/getmountlist.c index c0e6875..30fb9a3 100644 --- a/lib/getmountlist.c +++ b/lib/getmountlist.c @@ -90,7 +90,7 @@ int comma_scanall(char *optlist, char *scanlist) { int i = 1; - for (;;) { + while (scanlist && *scanlist) { char *opt = comma_iterate(&scanlist, &i), *s = xstrndup(opt, i); i = comma_scan(optlist, s, 0); -- cgit v1.2.3 From cff8e136c02fb3c03289acd98e274f85dca42023 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 21 Mar 2015 15:29:21 -0500 Subject: Patch from David Halls to fix mac/ios portability issue. --- lib/portability.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/portability.c b/lib/portability.c index 7d6d85f..4da49dd 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -45,7 +45,7 @@ ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) new_line = realloc(*linep, new_len); if (!new_line) return -1; *np = new_len; - *linep = new_line; + line = *linep = new_line; } line[i] = ch; @@ -59,7 +59,7 @@ ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) new_line = realloc(*linep, new_len); if (!new_line) return -1; *np = new_len; - *linep = new_line; + line = *linep = new_line; } line[i + 1] = '\0'; -- cgit v1.2.3 From 4b77d5419a0f2f4f8fdb9ad39dceddf75305b2a1 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 23 Mar 2015 11:49:58 -0500 Subject: Tweak of Elliott Hughes's fix for an off by one error in human_readable (137 returned "137 KB".) --- lib/lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index f70d379..0f2b012 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -868,8 +868,8 @@ int human_readable(char *buf, unsigned long long num) { int end, len; - len = sprintf(buf, "%lld", num); - end = ((len-1)%3)+1; + len = sprintf(buf, "%lld", num)-1; + end = (len%3)+1; len /= 3; if (len && end == 1) { -- cgit v1.2.3 From e10483fdc9ef8b69b2a420e8d991b865e05b85b9 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 3 Apr 2015 11:49:31 -0500 Subject: Add readfileat() to lib --- lib/lib.c | 11 +++++++---- lib/lib.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 0f2b012..9664bec 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -362,14 +362,12 @@ off_t fdlength(int fd) // Read contents of file as a single nul-terminated string. // malloc new one if buf=len=0 -char *readfile(char *name, char *ibuf, off_t len) +char *readfileat(int dirfd, char *name, char *ibuf, off_t len) { int fd; char *buf; - fd = open(name, O_RDONLY); - if (fd == -1) return 0; - + if (-1 == (fd = openat(dirfd, name, O_RDONLY))) return 0; if (len<1) { len = fdlength(fd); // proc files don't report a length, so try 1 page minimum. @@ -388,6 +386,11 @@ char *readfile(char *name, char *ibuf, off_t len) return buf; } +char *readfile(char *name, char *ibuf, off_t len) +{ + return readfileat(AT_FDCWD, name, ibuf, len); +} + // Sleep for this many thousandths of a second void msleep(long miliseconds) { diff --git a/lib/lib.h b/lib/lib.h index d8a1503..3cda7d9 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -144,6 +144,7 @@ ssize_t writeall(int fd, void *buf, size_t len); off_t lskip(int fd, off_t offset); int mkpathat(int atfd, char *dir, mode_t lastmode, int flags); struct string_list **splitpath(char *path, struct string_list **list); +char *readfileat(int dirfd, char *name, char *buf, off_t len); char *readfile(char *name, char *buf, off_t len); void msleep(long miliseconds); int64_t peek_le(void *ptr, unsigned size); -- cgit v1.2.3 From 08f51b53be06671f4bd6f57467182fd2b081b2c4 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 15 Apr 2015 20:53:00 -0500 Subject: Put SELINUX in a a menu, and add config option for SMACK. --- lib/portability.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index a10213e..f23d4f6 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -246,3 +246,7 @@ pid_t xfork(void); #define is_selinux_enabled() 0 int getcon(void* con); #endif + +#if CFG_TOYBOX_SMACK +#include +#endif -- cgit v1.2.3 From 17499c3731273d2cffdd96d011cf8ed6aca103da Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 16 Apr 2015 21:21:02 -0500 Subject: terminal_size should use LINES, not ROWS. The shell's pseudo-variable is called LINES. This is true of at least bash and mksh. --- lib/lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 9664bec..99d2ea6 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -627,7 +627,7 @@ int terminal_size(unsigned *xx, unsigned *yy) } s = getenv("COLUMNS"); if (s) sscanf(s, "%u", &x); - s = getenv("ROWS"); + s = getenv("LINES"); if (s) sscanf(s, "%u", &y); // Never return 0 for either value, leave it at default instead. -- cgit v1.2.3 From 58c326901827e1b54a7d82fb38633eafc448874d Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Fri, 17 Apr 2015 20:18:30 -0500 Subject: Link against libattr and libsmack. --- lib/portability.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index f23d4f6..740a4ee 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -249,4 +249,13 @@ int getcon(void* con); #if CFG_TOYBOX_SMACK #include +#include +#include +#else +#define smack_new_label_from_path(...) (-1) +#define smack_set_label_for_path(...) (-1) +#define smack_set_label_for_self(...) (-1) +#define XATTR_NAME_SMACK "" +#define SMACK_LABEL_LEN (1) /* for just ? */ #endif + -- cgit v1.2.3 From 5b493dc48db03c7e27c8ce002fe216bcd778fe92 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 19 Apr 2015 21:50:51 -0500 Subject: Cleanup getprop, add qstrcmp() to lib for qsort (because posix-2008 broke alphasort), add compile-time probe for config symbol TOYBOX_ON_ANDROID. --- lib/lib.c | 8 ++++++++ lib/lib.h | 1 + 2 files changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 99d2ea6..1a60a7f 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -887,3 +887,11 @@ int human_readable(char *buf, unsigned long long num) return end; } + +// The qsort man page says you can use alphasort, the posix committee +// disagreed, and doubled down: http://austingroupbugs.net/view.php?id=142 +// So just do our own. (The const is entirely to humor the stupid compiler.) +int qstrcmp(const void *a, const void *b) +{ + return strcmp(*(char **)a, *(char **)b); +} diff --git a/lib/lib.h b/lib/lib.h index 3cda7d9..a4e5808 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -176,6 +176,7 @@ void base64_init(char *p); int terminal_size(unsigned *x, unsigned *y); int yesno(char *prompt, int def); int human_readable(char *buf, unsigned long long num); +int qstrcmp(const void *a, const void *b); // net.c int xsocket(int domain, int type, int protocol); -- cgit v1.2.3 From 2fd8624cc612e946f593b2c9e9031c46f862562e Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 27 Apr 2015 11:13:19 -0500 Subject: Some infrastructure hexedit needs. (Poor man's curses.) --- lib/lib.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/lib.h | 3 ++ lib/net.c | 5 +++ lib/password.c | 33 -------------------- 4 files changed, 106 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index 1a60a7f..ab773b5 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -637,6 +637,40 @@ int terminal_size(unsigned *xx, unsigned *yy) return x || y; } +// Reset terminal to known state, saving copy of old state if old != NULL. +int set_terminal(int fd, int raw, struct termios *old) +{ + struct termios termio; + + // Fetch local copy of old terminfo, and copy struct contents to *old if set + if (!tcgetattr(fd, &termio) && old) *old = termio; + + // the following are the bits set for an xterm. Linux text mode TTYs by + // default add two additional bits that only matter for serial processing + // (turn serial line break into an interrupt, and XON/XOFF flow control) + + // Any key unblocks output, swap CR and NL on input + termio.c_iflag = IXANY|ICRNL|INLCR; + if (toys.which->flags & TOYFLAG_LOCALE) termio.c_iflag |= IUTF8; + + // Output appends CR to NL, does magic undocumented postprocessing + termio.c_oflag = ONLCR|OPOST; + + // Leave serial port speed alone + // termio.c_cflag = C_READ|CS8|EXTB; + + // Generate signals, input entire line at once, echo output + // erase, line kill, escape control characters with ^ + // erase line char at a time + // "extended" behavior: ctrl-V quotes next char, ctrl-R reprints unread chars, + // ctrl-W erases word + termio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; + + if (raw) cfmakeraw(&termio); + + return tcsetattr(fd, TCSANOW, &termio); +} + int yesno(char *prompt, int def) { char buf; @@ -895,3 +929,67 @@ int qstrcmp(const void *a, const void *b) { return strcmp(*(char **)a, *(char **)b); } + +int xpoll(struct pollfd *fds, int nfds, int timeout) +{ + int i; + + for (;;) { + if (0>(i = poll(fds, nfds, timeout))) { + if (errno != EINTR && errno != ENOMEM) perror_exit("xpoll"); + else if (timeout>0) timeout--; + } else return i; + } +} + +// Scan stdin for a keypress, parsing known escape sequences +// seq is array of char * strings, ends with NULL ptr +// Returns: 0-255=literal, -1=EOF, -2=NONE, 256-...=index into seq +// scratch space is necessary because last char of !seq could start new seq +// Zero out first byte of scratch before first call to scan_key +// block=0 allows fetching multiple characters before updating display +int scan_key(char *scratch, char **seqs, int block) +{ + struct pollfd pfd; + int maybe, i, j; + char *test; + + for (;;) { + pfd.fd = 0; + pfd.events = POLLIN; + pfd.revents = 0; + + // check sequences + maybe = 0; + if (*scratch) { + for (i = maybe = 0; (test = seqs[i]); i++) { + for (j = 0; j<*scratch; j++) if (scratch[j+1] != test[j]) break; + if (j == *scratch) { + maybe = 1; + if (!test[j]) { + // We recognized current sequence: consume and return + *scratch = 0; + return 256+i; + } + } + } + // If current data can't be a known sequence, return next raw char + if (!maybe) break; + } + + // Need more data to decide + + // 30 miliseconds is about the gap between characters at 300 baud + if (maybe || !block) if (!xpoll(&pfd, 1, 30*maybe)) break; + + if (1 != read(0, scratch+1+*scratch, 1)) return -1; + ++*scratch; + } + + // Was not a sequence + if (!*scratch) return -2; + i = scratch[1]; + if (--*scratch) memmove(scratch+1, scratch+2, *scratch); + + return i; +} diff --git a/lib/lib.h b/lib/lib.h index a4e5808..bdd78c9 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -174,9 +174,12 @@ void replace_tempfile(int fdin, int fdout, char **tempname); void crc_init(unsigned int *crc_table, int little_endian); void base64_init(char *p); int terminal_size(unsigned *x, unsigned *y); +int set_terminal(int fd, int raw, struct termios *old); int yesno(char *prompt, int def); int human_readable(char *buf, unsigned long long num); int qstrcmp(const void *a, const void *b); +int xpoll(struct pollfd *fds, int nfds, int timeout); +int scan_key(char *scratch, char **seqs, int block); // net.c int xsocket(int domain, int type, int protocol); diff --git a/lib/net.c b/lib/net.c index c12eff4..5d3ea4a 100644 --- a/lib/net.c +++ b/lib/net.c @@ -7,3 +7,8 @@ int xsocket(int domain, int type, int protocol) if (fd < 0) perror_exit("socket %x %x", type, protocol); return fd; } + +void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len) +{ + if (-1 == setsockopt(fd, level, opt, val, len)) perror_exit("setsockopt"); +} diff --git a/lib/password.c b/lib/password.c index b3cc199..9654d42 100644 --- a/lib/password.c +++ b/lib/password.c @@ -46,39 +46,6 @@ int get_salt(char *salt, char *algo) return -1; } -// Reset terminal to known state, returning old state if old != NULL. -int set_terminal(int fd, int raw, struct termios *old) -{ - struct termios termio; - - if (!tcgetattr(fd, &termio) && old) *old = termio; - - // the following are the bits set for an xterm. Linux text mode TTYs by - // default add two additional bits that only matter for serial processing - // (turn serial line break into an interrupt, and XON/XOFF flow control) - - // Any key unblocks output, swap CR and NL on input - termio.c_iflag = IXANY|ICRNL|INLCR; - if (toys.which->flags & TOYFLAG_LOCALE) termio.c_iflag |= IUTF8; - - // Output appends CR to NL, does magic undocumented postprocessing - termio.c_oflag = ONLCR|OPOST; - - // Leave serial port speed alone - // termio.c_cflag = C_READ|CS8|EXTB; - - // Generate signals, input entire line at once, echo output - // erase, line kill, escape control characters with ^ - // erase line char at a time - // "extended" behavior: ctrl-V quotes next char, ctrl-R reprints unread chars, - // ctrl-W erases word - termio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; - - if (raw) cfmakeraw(&termio); - - return tcsetattr(fd, TCSANOW, &termio); -} - // Prompt with mesg, read password into buf, return 0 for success 1 for fail int read_password(char *buf, int buflen, char *mesg) { -- cgit v1.2.3 From 9c3d1657f1a3561910ceb87c1ea21d349fbfaaed Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 30 Apr 2015 14:01:35 -0500 Subject: Remove redundant numlen. --- lib/lib.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index ab773b5..2f7d28f 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -280,16 +280,6 @@ long atolx_range(char *numstr, long low, long high) return val; } -int numlen(long l) -{ - int len = 0; - while (l) { - l /= 10; - len++; - } - return len; -} - int stridx(char *haystack, char needle) { char *off; -- cgit v1.2.3 From cb7ed52786ffab798455c88fbd73bc32276bcfed Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 30 Apr 2015 14:18:47 -0500 Subject: And remove the header part too. --- lib/lib.h | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/lib.h b/lib/lib.h index bdd78c9..dc5edd3 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -156,7 +156,6 @@ long estrtol(char *str, char **end, int base); long xstrtol(char *str, char **end, int base); long atolx(char *c); long atolx_range(char *numstr, long low, long high); -int numlen(long l); int stridx(char *haystack, char needle); int unescape(char c); int strstart(char **a, char *b); -- cgit v1.2.3 From 06d378325b9e7b6fd06fe45b284e189ac440345b Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 1 May 2015 14:40:49 -0500 Subject: Portability bits for the recent ls smack changes. --- lib/portability.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index 740a4ee..b25048f 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -226,6 +226,10 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); #define O_CLOEXEC 02000000 #endif +#ifndef O_PATH +#define O_PATH 010000000 +#endif + #if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \ && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__ typedef double FLOAT; @@ -257,5 +261,7 @@ int getcon(void* con); #define smack_set_label_for_self(...) (-1) #define XATTR_NAME_SMACK "" #define SMACK_LABEL_LEN (1) /* for just ? */ + +ssize_t fgetxattr (int fd, char *name, void *value, size_t size); #endif -- cgit v1.2.3 From 9398f05d34453e9306f7a91993ee4c8fcf1102ec Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 3 May 2015 16:20:27 -0500 Subject: Move a prototype to the start of portability.h (suggested by Elliott Hughes) --- lib/portability.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index b25048f..7bab646 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -28,6 +28,9 @@ #include +// Types various replacement prototypes need +#include + // Various constants old build environments might not have even if kernel does #ifndef AT_FDCWD -- cgit v1.2.3 From 72cd2e07f1cea190925021472465325e72589f47 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 8 May 2015 20:20:29 -0500 Subject: Move not-curses code into interstingtimes.c --- lib/interestingtimes.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/lib.c | 118 ---------------------------------------------- lib/lib.h | 6 ++- lib/portability.h | 2 +- 4 files changed, 129 insertions(+), 121 deletions(-) create mode 100644 lib/interestingtimes.c (limited to 'lib') diff --git a/lib/interestingtimes.c b/lib/interestingtimes.c new file mode 100644 index 0000000..cea5039 --- /dev/null +++ b/lib/interestingtimes.c @@ -0,0 +1,124 @@ +/* interestingtimes.c - cursor control + * + * Copyright 2015 Rob Landley + */ + +#include "toys.h" + +// Quick and dirty query size of terminal, doesn't do ANSI probe fallback. +// set x=80 y=25 before calling to provide defaults. Returns 0 if couldn't +// determine size. + +int terminal_size(unsigned *xx, unsigned *yy) +{ + struct winsize ws; + unsigned i, x = 0, y = 0; + char *s; + + // stdin, stdout, stderr + for (i=0; i<3; i++) { + memset(&ws, 0, sizeof(ws)); + if (!ioctl(i, TIOCGWINSZ, &ws)) { + if (ws.ws_col) x = ws.ws_col; + if (ws.ws_row) y = ws.ws_row; + + break; + } + } + s = getenv("COLUMNS"); + if (s) sscanf(s, "%u", &x); + s = getenv("LINES"); + if (s) sscanf(s, "%u", &y); + + // Never return 0 for either value, leave it at default instead. + if (xx && x) *xx = x; + if (yy && y) *yy = y; + + return x || y; +} + +// Reset terminal to known state, saving copy of old state if old != NULL. +int set_terminal(int fd, int raw, struct termios *old) +{ + struct termios termio; + + // Fetch local copy of old terminfo, and copy struct contents to *old if set + if (!tcgetattr(fd, &termio) && old) *old = termio; + + // the following are the bits set for an xterm. Linux text mode TTYs by + // default add two additional bits that only matter for serial processing + // (turn serial line break into an interrupt, and XON/XOFF flow control) + + // Any key unblocks output, swap CR and NL on input + termio.c_iflag = IXANY|ICRNL|INLCR; + if (toys.which->flags & TOYFLAG_LOCALE) termio.c_iflag |= IUTF8; + + // Output appends CR to NL, does magic undocumented postprocessing + termio.c_oflag = ONLCR|OPOST; + + // Leave serial port speed alone + // termio.c_cflag = C_READ|CS8|EXTB; + + // Generate signals, input entire line at once, echo output + // erase, line kill, escape control characters with ^ + // erase line char at a time + // "extended" behavior: ctrl-V quotes next char, ctrl-R reprints unread chars, + // ctrl-W erases word + termio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; + + if (raw) cfmakeraw(&termio); + + return tcsetattr(fd, TCSANOW, &termio); +} + +// Scan stdin for a keypress, parsing known escape sequences +// seqs is array of char * strings, ends with NULL ptr +// Returns: 0-255=literal, -1=EOF, -2=NONE, 256-...=index into seq +// scratch space is necessary because last char of !seq could start new seq +// Zero out first byte of scratch before first call to scan_key +// block=0 allows fetching multiple characters before updating display +int scan_key(char *scratch, char **seqs, int block) +{ + struct pollfd pfd; + int maybe, i, j; + char *test; + + for (;;) { + pfd.fd = 0; + pfd.events = POLLIN; + pfd.revents = 0; + + // check sequences + maybe = 0; + if (*scratch) { + for (i = maybe = 0; (test = seqs[i]); i++) { + for (j = 0; j<*scratch; j++) if (scratch[j+1] != test[j]) break; + if (j == *scratch) { + maybe = 1; + if (!test[j]) { + // We recognized current sequence: consume and return + *scratch = 0; + return 256+i; + } + } + } + // If current data can't be a known sequence, return next raw char + if (!maybe) break; + } + + // Need more data to decide + + // 30 miliseconds is about the gap between characters at 300 baud + if (maybe || !block) if (!xpoll(&pfd, 1, 30*maybe)) break; + + if (1 != read(0, scratch+1+*scratch, 1)) return -1; + ++*scratch; + } + + // Was not a sequence + if (!*scratch) return -2; + i = scratch[1]; + if (--*scratch) memmove(scratch+1, scratch+2, *scratch); + + return i; +} diff --git a/lib/lib.c b/lib/lib.c index 2f7d28f..ea65f77 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -595,72 +595,6 @@ void base64_init(char *p) *(p++) = '/'; } -// Quick and dirty query size of terminal, doesn't do ANSI probe fallback. -// set x=80 y=25 before calling to provide defaults. Returns 0 if couldn't -// determine size. - -int terminal_size(unsigned *xx, unsigned *yy) -{ - struct winsize ws; - unsigned i, x = 0, y = 0; - char *s; - - // stdin, stdout, stderr - for (i=0; i<3; i++) { - memset(&ws, 0, sizeof(ws)); - if (!ioctl(i, TIOCGWINSZ, &ws)) { - if (ws.ws_col) x = ws.ws_col; - if (ws.ws_row) y = ws.ws_row; - - break; - } - } - s = getenv("COLUMNS"); - if (s) sscanf(s, "%u", &x); - s = getenv("LINES"); - if (s) sscanf(s, "%u", &y); - - // Never return 0 for either value, leave it at default instead. - if (xx && x) *xx = x; - if (yy && y) *yy = y; - - return x || y; -} - -// Reset terminal to known state, saving copy of old state if old != NULL. -int set_terminal(int fd, int raw, struct termios *old) -{ - struct termios termio; - - // Fetch local copy of old terminfo, and copy struct contents to *old if set - if (!tcgetattr(fd, &termio) && old) *old = termio; - - // the following are the bits set for an xterm. Linux text mode TTYs by - // default add two additional bits that only matter for serial processing - // (turn serial line break into an interrupt, and XON/XOFF flow control) - - // Any key unblocks output, swap CR and NL on input - termio.c_iflag = IXANY|ICRNL|INLCR; - if (toys.which->flags & TOYFLAG_LOCALE) termio.c_iflag |= IUTF8; - - // Output appends CR to NL, does magic undocumented postprocessing - termio.c_oflag = ONLCR|OPOST; - - // Leave serial port speed alone - // termio.c_cflag = C_READ|CS8|EXTB; - - // Generate signals, input entire line at once, echo output - // erase, line kill, escape control characters with ^ - // erase line char at a time - // "extended" behavior: ctrl-V quotes next char, ctrl-R reprints unread chars, - // ctrl-W erases word - termio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; - - if (raw) cfmakeraw(&termio); - - return tcsetattr(fd, TCSANOW, &termio); -} - int yesno(char *prompt, int def) { char buf; @@ -931,55 +865,3 @@ int xpoll(struct pollfd *fds, int nfds, int timeout) } else return i; } } - -// Scan stdin for a keypress, parsing known escape sequences -// seq is array of char * strings, ends with NULL ptr -// Returns: 0-255=literal, -1=EOF, -2=NONE, 256-...=index into seq -// scratch space is necessary because last char of !seq could start new seq -// Zero out first byte of scratch before first call to scan_key -// block=0 allows fetching multiple characters before updating display -int scan_key(char *scratch, char **seqs, int block) -{ - struct pollfd pfd; - int maybe, i, j; - char *test; - - for (;;) { - pfd.fd = 0; - pfd.events = POLLIN; - pfd.revents = 0; - - // check sequences - maybe = 0; - if (*scratch) { - for (i = maybe = 0; (test = seqs[i]); i++) { - for (j = 0; j<*scratch; j++) if (scratch[j+1] != test[j]) break; - if (j == *scratch) { - maybe = 1; - if (!test[j]) { - // We recognized current sequence: consume and return - *scratch = 0; - return 256+i; - } - } - } - // If current data can't be a known sequence, return next raw char - if (!maybe) break; - } - - // Need more data to decide - - // 30 miliseconds is about the gap between characters at 300 baud - if (maybe || !block) if (!xpoll(&pfd, 1, 30*maybe)) break; - - if (1 != read(0, scratch+1+*scratch, 1)) return -1; - ++*scratch; - } - - // Was not a sequence - if (!*scratch) return -2; - i = scratch[1]; - if (--*scratch) memmove(scratch+1, scratch+2, *scratch); - - return i; -} diff --git a/lib/lib.h b/lib/lib.h index dc5edd3..be4051e 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -172,12 +172,14 @@ void delete_tempfile(int fdin, int fdout, char **tempname); void replace_tempfile(int fdin, int fdout, char **tempname); void crc_init(unsigned int *crc_table, int little_endian); void base64_init(char *p); -int terminal_size(unsigned *x, unsigned *y); -int set_terminal(int fd, int raw, struct termios *old); int yesno(char *prompt, int def); int human_readable(char *buf, unsigned long long num); int qstrcmp(const void *a, const void *b); int xpoll(struct pollfd *fds, int nfds, int timeout); + +// interestingtimes.c +int terminal_size(unsigned *xx, unsigned *yy); +int set_terminal(int fd, int raw, struct termios *old); int scan_key(char *scratch, char **seqs, int block); // net.c diff --git a/lib/portability.h b/lib/portability.h index 7bab646..aa1ee48 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -245,7 +245,7 @@ pid_t xfork(void); #endif //#define strncpy(...) @@strncpyisbadmmkay@@ -//#define strncat(...) @@strcatisbadmmkay@@ +//#define strncat(...) @@strncatisbadmmkay@@ #if CFG_TOYBOX_SELINUX #include -- cgit v1.2.3 From aab9164df395a4b0878b0ad930a5ec8a806a58e9 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 9 May 2015 18:11:22 -0500 Subject: Add DIRTREE_SHUTUP to disable dirtree warnings if file vanishes out from under traversal. Pass through full flag set in dirtree_add_node(), add dirtree_start() wrapper to provide symlink-only behavior (avoiding a lot of DIRTREE_SYMFOLLOW*!!(logic) repeated in callers). --- lib/dirtree.c | 41 +++++++++++++++++++++++------------------ lib/lib.h | 5 ++++- 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/dirtree.c b/lib/dirtree.c index 60ce56b..1e89816 100644 --- a/lib/dirtree.c +++ b/lib/dirtree.c @@ -24,22 +24,21 @@ int dirtree_notdotdot(struct dirtree *catch) // (This doesn't open directory filehandles yet so as not to exhaust the // filehandle space on large trees, dirtree_handle_callback() does that.) -struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, - int symfollow) +struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, int flags) { struct dirtree *dt = NULL; struct stat st; - char buf[4096]; int len = 0, linklen = 0; if (name) { // open code this because haven't got node to call dirtree_parentfd() on yet int fd = parent ? parent->data : AT_FDCWD; - if (fstatat(fd, name, &st, symfollow ? 0 : AT_SYMLINK_NOFOLLOW)) goto error; + if (fstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW*!(flags&DIRTREE_SYMFOLLOW))) + goto error; if (S_ISLNK(st.st_mode)) { - if (0>(linklen = readlinkat(fd, name, buf, 4095))) goto error; - buf[linklen++]=0; + if (0>(linklen = readlinkat(fd, name, libbuf, 4095))) goto error; + libbuf[linklen++]=0; } len = strlen(name); } @@ -50,7 +49,7 @@ struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, strcpy(dt->name, name); if (linklen) { - dt->symlink = memcpy(len+(char *)dt, buf, linklen); + dt->symlink = memcpy(len+(char *)dt, libbuf, linklen); dt->data = --linklen; } } @@ -58,7 +57,7 @@ struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, return dt; error: - if (notdotdot(name)) { + if (!(flags&DIRTREE_SHUTUP) && notdotdot(name)) { char *path = parent ? dirtree_path(parent, 0) : ""; perror_msg("%s%s%s", path, parent ? "/" : "", name); @@ -111,13 +110,13 @@ int dirtree_parentfd(struct dirtree *node) struct dirtree *dirtree_handle_callback(struct dirtree *new, int (*callback)(struct dirtree *node)) { - int flags, dir = S_ISDIR(new->st.st_mode); + int flags; + if (!new) return 0; if (!callback) callback = dirtree_notdotdot; - flags = callback(new); - if (dir) { + if (S_ISDIR(new->st.st_mode)) { if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) { new->data = openat(dirtree_parentfd(new), new->name, O_CLOEXEC); flags = dirtree_recurse(new, callback, flags); @@ -144,9 +143,11 @@ int dirtree_recurse(struct dirtree *node, DIR *dir; if (node->data == -1 || !(dir = fdopendir(node->data))) { - char *path = dirtree_path(node, 0); - perror_msg("No %s", path); - free(path); + if (!(flags & DIRTREE_SHUTUP)) { + char *path = dirtree_path(node, 0); + perror_msg("No %s", path); + free(path); + } close(node->data); return flags; @@ -157,8 +158,7 @@ int dirtree_recurse(struct dirtree *node, // The extra parentheses are to shut the stupid compiler up. while ((entry = readdir(dir))) { - if (!(new = dirtree_add_node(node, entry->d_name, flags&DIRTREE_SYMFOLLOW))) - continue; + if (!(new = dirtree_add_node(node, entry->d_name, flags))) continue; new = dirtree_handle_callback(new, callback); if (new == DIRTREE_ABORTVAL) break; if (new) { @@ -179,14 +179,19 @@ int dirtree_recurse(struct dirtree *node, return flags; } +// Create dirtree root +struct dirtree *dirtree_start(char *name, int symfollow) +{ + return dirtree_add_node(0, name, DIRTREE_SYMFOLLOW*!!symfollow); +} + // Create dirtree from path, using callback to filter nodes. // If callback == NULL allocate a tree of struct dirtree nodes and return // pointer to root node. -// symfollow is just for the top of tree, callback return code controls children struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)) { - struct dirtree *root = dirtree_add_node(0, path, 0); + struct dirtree *root = dirtree_start(path, 0); return root ? dirtree_handle_callback(root, callback) : DIRTREE_ABORTVAL; } diff --git a/lib/lib.h b/lib/lib.h index be4051e..03a0570 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -50,6 +50,8 @@ void get_optflags(void); #define DIRTREE_COMEAGAIN 4 // Follow symlinks to directories #define DIRTREE_SYMFOLLOW 8 +// Don't warn about failure to stat +#define DIRTREE_SHUTUP 16 // Don't look at any more files in this directory. #define DIRTREE_ABORT 256 @@ -65,7 +67,8 @@ struct dirtree { char name[]; }; -struct dirtree *dirtree_add_node(struct dirtree *p, char *name, int symfollow); +struct dirtree *dirtree_start(char *name, int symfollow); +struct dirtree *dirtree_add_node(struct dirtree *p, char *name, int flags); char *dirtree_path(struct dirtree *node, int *plen); int dirtree_notdotdot(struct dirtree *catch); int dirtree_parentfd(struct dirtree *node); -- cgit v1.2.3 From 5b2644cafc8a619b617ba0fbb5473667dbd634ba Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 14 May 2015 13:43:01 -0500 Subject: Promote reset (actually write a new one using the simple man 4 console_codes terminal reset escape sequence) and add gettty() function to lib so terminal gets reset even when we redirect stdout/stderr. (This is apparently the expected behavior.) --- lib/interestingtimes.c | 9 +++++++++ lib/lib.h | 1 + 2 files changed, 10 insertions(+) (limited to 'lib') diff --git a/lib/interestingtimes.c b/lib/interestingtimes.c index cea5039..85b8eb4 100644 --- a/lib/interestingtimes.c +++ b/lib/interestingtimes.c @@ -5,6 +5,15 @@ #include "toys.h" +int xgettty(void) +{ + int i, j; + + for (i = 0; i<3; i++) if (isatty(j = (i+1)%3)) return j; + + return xopen("/dev/tty", O_RDWR); +} + // Quick and dirty query size of terminal, doesn't do ANSI probe fallback. // set x=80 y=25 before calling to provide defaults. Returns 0 if couldn't // determine size. diff --git a/lib/lib.h b/lib/lib.h index 03a0570..54876b6 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -181,6 +181,7 @@ int qstrcmp(const void *a, const void *b); int xpoll(struct pollfd *fds, int nfds, int timeout); // interestingtimes.c +int xgettty(void); int terminal_size(unsigned *xx, unsigned *yy); int set_terminal(int fd, int raw, struct termios *old); int scan_key(char *scratch, char **seqs, int block); -- cgit v1.2.3 From c565b06325960a16ebf44afd8ae73f363775e58d Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 18 May 2015 02:00:43 -0500 Subject: More ls -Z upgrading. Move TOYBOX_SELINUX and TOYBOX_SMACK support from portability.h to new lib/lsm.h. Update ls.c to use it. Fix "ls . toys" (two directories when one is . or ..), which was filtering out the . as something we shouldn't recurse into even though it was explicitly listed on the command line. For some reason "ls -Z . toys" is still segfaulting though (but "ls -Z ." isn't), need to figure out why... --- lib/lsm.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/portability.h | 25 +++------------ 2 files changed, 100 insertions(+), 21 deletions(-) create mode 100644 lib/lsm.h (limited to 'lib') diff --git a/lib/lsm.h b/lib/lsm.h new file mode 100644 index 0000000..b16138a --- /dev/null +++ b/lib/lsm.h @@ -0,0 +1,96 @@ +/* lsm.h - header file for lib directory + * + * Copyright 2015 Rob Landley + */ + +#if CFG_TOYBOX_SELINUX +#include +#else +#define is_selinux_enabled() 0 +#define getcon(...) (-1) +#define getfilecon(...) (-1) +#define lgetfilecon(...) (-1) +#define fgetfilecon(...) (-1) +#define setfilecon(...) (-1) +#define lsetfilecon(...) (-1) +#define fsetfilecon(...) (-1) +#endif + +#if CFG_TOYBOX_SMACK +#include +#include +#include +#else +#define XATTR_NAME_SMACK 0 +//ssize_t fgetxattr (int fd, char *name, void *value, size_t size); +#define smack_smackfs_path(...) (-1) +#define smack_new_label_from_self(...) (-1) +#define smack_new_label_from_path(...) (-1) +#define smack_new_label_from_file(...) (-1) +#define smack_set_label_for_path(...) (-1) +#define smack_set_label_for_file(...) (-1) +#endif + +// This turns into "return 0" when no LSM and lets code optimize out. +static inline int lsm_enabled(void) +{ + if (CFG_TOYBOX_SMACK) return !!smack_smackfs_path(); + else return is_selinux_enabled() == 1; +} + +// Fetch this process's lsm context +static inline char *lsm_context(void) +{ + int ok = 0; + char *result; + + if (CFG_TOYBOX_SMACK) ok = smack_new_label_from_self(&result) > 0; + else ok = getcon(&result) == 0; + + return ok ? result : strdup("?"); +} + +static inline int lsm_set_context(char *filename, char *context) +{ + if (CFG_TOYBOX_SMACK) + return smack_set_label_for_path(filename, XATTR_NAME_SMACK, 1, context); + else return setfilecon(filename, context); +} + +static inline int lsm_lset_context(char *filename, char *context) +{ + if (CFG_TOYBOX_SMACK) + return smack_set_label_for_path(filename, XATTR_NAME_SMACK, 0, context); + else return lsetfilecon(filename, context); +} + +static inline int lsm_fset_context(int file, char *context) +{ + if (CFG_TOYBOX_SMACK) + return smack_set_label_for_file(file, XATTR_NAME_SMACK, context); + else return fsetfilecon(file, context); +} + + +// returns -1 in case of error or else the length of the context */ +// context can be NULL to get the length only */ +static inline int lsm_get_context(char *filename, char **context) +{ + if (CFG_TOYBOX_SMACK) + return smack_new_label_from_path(filename, XATTR_NAME_SMACK, 1, context); + else return getfilecon(filename, context); +} + +static inline int lsm_lget_context(char *filename, char **context) +{ + if (CFG_TOYBOX_SMACK) + return smack_new_label_from_path(filename, XATTR_NAME_SMACK, 0, context); + else return lgetfilecon(filename, context); +} + +static inline int lsm_fget_context(int file, char **context) +{ + if (CFG_TOYBOX_SMACK) + return smack_new_label_from_file(file, XATTR_NAME_SMACK, context); + return fgetfilecon(file, context); +} diff --git a/lib/portability.h b/lib/portability.h index aa1ee48..f83cab6 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -225,6 +225,10 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream); #define O_NOFOLLOW 0 #endif +#ifndef O_NOATIME +#define O_NOATIME 01000000 +#endif + #ifndef O_CLOEXEC #define O_CLOEXEC 02000000 #endif @@ -247,24 +251,3 @@ pid_t xfork(void); //#define strncpy(...) @@strncpyisbadmmkay@@ //#define strncat(...) @@strncatisbadmmkay@@ -#if CFG_TOYBOX_SELINUX -#include -#else -#define is_selinux_enabled() 0 -int getcon(void* con); -#endif - -#if CFG_TOYBOX_SMACK -#include -#include -#include -#else -#define smack_new_label_from_path(...) (-1) -#define smack_set_label_for_path(...) (-1) -#define smack_set_label_for_self(...) (-1) -#define XATTR_NAME_SMACK "" -#define SMACK_LABEL_LEN (1) /* for just ? */ - -ssize_t fgetxattr (int fd, char *name, void *value, size_t size); -#endif - -- cgit v1.2.3 From 0cb5b70fa4ef093b08e59db813e73f3be6ecef4b Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 18 May 2015 19:14:53 -0500 Subject: Switch id over to new infrastructure, switch id to use FORCE_FLAGS, and make lib/lsm.h auto-include from toys.h. --- lib/lsm.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/lsm.h b/lib/lsm.h index b16138a..660917a 100644 --- a/lib/lsm.h +++ b/lib/lsm.h @@ -38,6 +38,14 @@ static inline int lsm_enabled(void) else return is_selinux_enabled() == 1; } +static inline char *lsm_name(void) +{ + if (CFG_TOYBOX_SMACK) return "Smack"; + if (CFG_TOYBOX_SELINUX) return "SELinux"; + + return "LSM"; +} + // Fetch this process's lsm context static inline char *lsm_context(void) { -- cgit v1.2.3 From 2d66e6a23822a500ecf6610411941e99127129c8 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 28 May 2015 01:43:47 -0500 Subject: Attempt to fix the mkdir LSM race. Doing a world writeable mkdir and _then_ adding a label seems like a race window, so set the global "create stuff with these labels" context, then do the creates. --- lib/lsm.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/lsm.h b/lib/lsm.h index 660917a..d7e7de9 100644 --- a/lib/lsm.h +++ b/lib/lsm.h @@ -7,6 +7,7 @@ #include #else #define is_selinux_enabled() 0 +#define setfscreatecon(...) (-1) #define getcon(...) (-1) #define getfilecon(...) (-1) #define lgetfilecon(...) (-1) @@ -27,6 +28,7 @@ #define smack_new_label_from_self(...) (-1) #define smack_new_label_from_path(...) (-1) #define smack_new_label_from_file(...) (-1) +#define smack_set_label_for_self(...) (-1) #define smack_set_label_for_path(...) (-1) #define smack_set_label_for_file(...) (-1) #endif @@ -58,6 +60,14 @@ static inline char *lsm_context(void) return ok ? result : strdup("?"); } +// Set default label to apply to newly created stuff (NULL to clear it) +static inline int lsm_set_create(char *context) +{ + if (CFG_TOYBOX_SMACK) return smack_set_label_for_self(context); + else return setfscreatecon(context); +} + +// Label a file, following symlinks static inline int lsm_set_context(char *filename, char *context) { if (CFG_TOYBOX_SMACK) @@ -65,6 +75,7 @@ static inline int lsm_set_context(char *filename, char *context) else return setfilecon(filename, context); } +// Label a file, don't follow symlinks static inline int lsm_lset_context(char *filename, char *context) { if (CFG_TOYBOX_SMACK) @@ -72,6 +83,7 @@ static inline int lsm_lset_context(char *filename, char *context) else return lsetfilecon(filename, context); } +// Label a file by filehandle static inline int lsm_fset_context(int file, char *context) { if (CFG_TOYBOX_SMACK) @@ -79,7 +91,6 @@ static inline int lsm_fset_context(int file, char *context) else return fsetfilecon(file, context); } - // returns -1 in case of error or else the length of the context */ // context can be NULL to get the length only */ static inline int lsm_get_context(char *filename, char **context) -- cgit v1.2.3 From f033f8607f156464747abe57487c1f6226f94001 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 31 May 2015 05:11:28 -0500 Subject: Move the magic list of commands needing cleanup from toys/pending/README to greppable TODO annotations in the individual files. (grep -riw TODO) --- lib/password.c | 2 ++ lib/pending.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/password.c b/lib/password.c index 9654d42..bf13c44 100644 --- a/lib/password.c +++ b/lib/password.c @@ -1,6 +1,8 @@ /* password.c - password read/update helper functions. * * Copyright 2012 Ashwini Kumar + * + * TODO: cleanup */ #include "toys.h" diff --git a/lib/pending.h b/lib/pending.h index c67d81c..ffbd025 100644 --- a/lib/pending.h +++ b/lib/pending.h @@ -4,3 +4,5 @@ #define MAX_SALT_LEN 20 //3 for id, 16 for key, 1 for '\0' int read_password(char * buff, int buflen, char* mesg); int update_password(char *filename, char* username, char* encrypted); + +// TODO this goes away when lib/password.c cleaned up -- cgit v1.2.3 From b20c80b603c1795c473b3957fd2538485ec4eb90 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 26 Jun 2015 16:26:15 -0500 Subject: Factor out more not-curses infrastructure into lib. --- lib/interestingtimes.c | 34 ++++++++++++++++++++++++++++++++-- lib/lib.h | 17 ++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/interestingtimes.c b/lib/interestingtimes.c index 85b8eb4..8f8b35c 100644 --- a/lib/interestingtimes.c +++ b/lib/interestingtimes.c @@ -81,13 +81,15 @@ int set_terminal(int fd, int raw, struct termios *old) } // Scan stdin for a keypress, parsing known escape sequences -// seqs is array of char * strings, ends with NULL ptr // Returns: 0-255=literal, -1=EOF, -2=NONE, 256-...=index into seq // scratch space is necessary because last char of !seq could start new seq // Zero out first byte of scratch before first call to scan_key // block=0 allows fetching multiple characters before updating display -int scan_key(char *scratch, char **seqs, int block) +int scan_key(char *scratch, int block) { + // up down right left pgup pgdn home end ins + char *seqs[] = {"\033[A", "\033[B", "\033[C", "\033[D", "\033[5~", "\033[6~", + "\033OH", "\033OF", "\033[2~", 0}; struct pollfd pfd; int maybe, i, j; char *test; @@ -131,3 +133,31 @@ int scan_key(char *scratch, char **seqs, int block) return i; } + +void tty_esc(char *s) +{ + printf("\033[%s", s); +} + +void tty_jump(int x, int y) +{ + char s[32]; + + sprintf(s, "%d;%dH", y+1, x+1); + tty_esc(s); +} + +void tty_reset(void) +{ + set_terminal(1, 0, 0); + tty_esc("?25h"); + tty_esc("0m"); + tty_jump(0, 999); + tty_esc("K"); +} + +void tty_sigreset(int i) +{ + tty_reset(); + _exit(128+i); +} diff --git a/lib/lib.h b/lib/lib.h index 54876b6..92bd6b5 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -184,7 +184,22 @@ int xpoll(struct pollfd *fds, int nfds, int timeout); int xgettty(void); int terminal_size(unsigned *xx, unsigned *yy); int set_terminal(int fd, int raw, struct termios *old); -int scan_key(char *scratch, char **seqs, int block); +int scan_key(char *scratch, int block); +void tty_esc(char *s); +void tty_jump(int x, int y); +void tty_reset(void); +void tty_sigreset(int i); + +// Results from scan_key() +#define KEY_UP 256 +#define KEY_DOWN 257 +#define KEY_RIGHT 258 +#define KEY_LEFT 259 +#define KEY_PGUP 260 +#define KEY_PGDN 261 +#define KEY_HOME 262 +#define KEY_END 263 +#define KEY_INSERT 264 // net.c int xsocket(int domain, int type, int protocol); -- cgit v1.2.3 From 8a2c0876754baa2085bce94d6778b5d2f4aee937 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 1 Jul 2015 15:00:06 -0500 Subject: Fix segfault with "mount -o ro,remount". Or any call to comma_scan where 'opt' appears as the last item in 'optlist'. --- lib/getmountlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/getmountlist.c b/lib/getmountlist.c index 30fb9a3..4fec41b 100644 --- a/lib/getmountlist.c +++ b/lib/getmountlist.c @@ -78,7 +78,7 @@ int comma_scan(char *optlist, char *opt, int clean) no = 2*(*s == 'n' && s[1] == 'o'); if (optlen == len-no && !strncmp(opt, s+no, optlen)) { got = !no; - if (clean) memmove(s, optlist, strlen(optlist)+1); + if (clean && optlist) memmove(s, optlist, strlen(optlist)+1); } } -- cgit v1.2.3 From 9933273c5b7b6e0471d9195e8c2facb795b795ae Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 3 Jul 2015 15:17:25 -0500 Subject: Probe for fork() instead of relying on a distro-specific #define. --- lib/portability.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/portability.c b/lib/portability.c index 4da49dd..78e500b 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -6,7 +6,20 @@ #include "toys.h" -#if !defined(__uClinux__) +// We can't fork() on nommu systems, and vfork() requires an exec() or exit() +// before resuming the parent (because they share a heap until then). And no, +// we can't implement our own clone() call that does the equivalent of fork() +// because nommu heaps use physical addresses so if we copy the heap all our +// pointers are wrong. (You need an mmu in order to map two heaps to the same +// address range without interfering with each other.) In the absence of +// a portable way to tell malloc() to start a new heap without freeing the old +// one, you pretty much need the exec().) + +// So we exec ourselves (via /proc/self/exe, if anybody knows a way to +// re-exec self without depending on the filesystem, I'm all ears), +// and use the arguments to signal reentry. + +#if CFG_TOYBOX_FORK pid_t xfork(void) { pid_t pid = fork(); -- cgit v1.2.3 From 1e7b49e25990b6141ffa25da2cd4b6124d435f3d Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 10 Jul 2015 14:12:44 -0500 Subject: Move comment about TOYBOX_DEBUG to start of file so it's more obvious. --- lib/args.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/args.c b/lib/args.c index 592d33c..d5fbb17 100644 --- a/lib/args.c +++ b/lib/args.c @@ -3,6 +3,12 @@ * Copyright 2006 Rob Landley */ +// NOTE: If option parsing segfaults, switch on TOYBOX_DEBUG in menuconfig. + +// Enabling TOYBOX_DEBUG in .config adds syntax checks to option string parsing +// which aren't needed in the final code (your option string is hardwired and +// should be correct when you ship), but are useful for development. + #include "toys.h" // Design goals: @@ -39,10 +45,6 @@ * this[1]="fruit" (argument to -b) */ -// Enabling TOYBOX_DEBUG in .config adds syntax checks to option string parsing -// which aren't needed in the final code (your option string is hardwired and -// should be correct when you ship), but are useful for development. - // What you can put in a get_opt string: // Any otherwise unused character (all letters, unprefixed numbers) specify // an option that sets a flag. The bit value is the same as the binary digit -- cgit v1.2.3 From 6292beb86fa9a3999f0f0b76185e0a893af85cd0 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 10 Jul 2015 14:52:14 -0500 Subject: Add a basename_r() and use it in names_to_pid() to avoid basename() overwriting itself on some inputs. (Which makes killall really impolite. Bug report from Nicholas Noury via Elliott Hughes.) --- lib/lib.c | 10 +++++++++- lib/lib.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/lib.c b/lib/lib.c index ea65f77..05e377f 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -798,6 +798,14 @@ void mode_to_string(mode_t mode, char *buf) *buf = c; } +char *basename_r(char *name) +{ + char *s = strrchr(name, '/'); + + if (s) return s+1; + return name; +} + // Execute a callback for each PID that matches a process name from a list. void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)) { @@ -816,7 +824,7 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)) for (curname = names; *curname; curname++) if (**curname == '/' ? !strcmp(cmd, *curname) - : !strcmp(basename(cmd), basename(*curname))) + : !strcmp(basename_r(cmd), basename_r(*curname))) if (callback(u, *curname)) break; if (*curname) break; } diff --git a/lib/lib.h b/lib/lib.h index 92bd6b5..3183f32 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -235,6 +235,7 @@ char *num_to_sig(int sig); mode_t string_to_mode(char *mode_str, mode_t base); void mode_to_string(mode_t mode, char *buf); +char *basename_r(char *name); void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)); // Functions in need of further review/cleanup -- cgit v1.2.3 From ba555808e068d9cc418b6b3bd6fa4238877a599d Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Sat, 11 Jul 2015 14:20:31 -0500 Subject: Fix 32-bit bionic toybox build. https://android-review.googlesource.com/159035/ --- lib/portability.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/portability.h b/lib/portability.h index f83cab6..ff22fa5 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -79,7 +79,7 @@ char *strptime(const char *buf, const char *format, struct tm *tm); // correct name to the broken name. char *dirname(char *path); -char *__xpg_basename (char *path); +char *__xpg_basename(char *path); static inline char *basename(char *path) { return __xpg_basename(path); } // uClibc pretends to be glibc and copied a lot of its bugs, but has a few more @@ -154,11 +154,19 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag #endif // glibc in general -#ifndef __GLIBC__ +#if !defined(__GLIBC__) && !defined(__BIONIC__) // POSIX basename. #include #endif +// glibc was handled above; for 32-bit bionic we need to avoid a collision +// with toybox's basename_r so we can't include even though that +// would give us a POSIX basename(3). +#if defined(__BIONIC__) +char *basename(char *path); +char *dirname(char *path); +#endif + // Work out how to do endianness #ifndef __APPLE__ -- cgit v1.2.3