*: use better isspace implementation
[oweals/busybox.git] / include / libbb.h
index 788140d14a6ec339198ab6aa1eea0f3ddc874571..fb7296f25fe0f79489cbb4853274cc59122f8318 100644 (file)
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
+#if defined __FreeBSD__
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
 #if ENABLE_FEATURE_SHADOWPASSWDS
-# include <shadow.h>
+# if !ENABLE_USE_BB_SHADOW
+/* If using busybox's shadow implementation, do not include the shadow.h
+ * header as the toolchain may not provide it at all.
+ */
+#  include <shadow.h>
+# endif
 #endif
 
 /* Some libc's forget to declare these, do it ourself */
@@ -86,7 +95,9 @@ int klogctl(int type, char *b, int len);
 /* This is declared here rather than #including <libgen.h> in order to avoid
  * confusing the two versions of basename.  See the dirname/basename man page
  * for details. */
+#if !defined __FreeBSD__
 char *dirname(char *path);
+#endif
 /* Include our own copy of struct sysinfo to avoid binary compatibility
  * problems with Linux 2.4, which changed things.  Grumble, grumble. */
 struct sysinfo {
@@ -275,7 +286,9 @@ enum {
        ACTION_DEPTHFIRST     = (1 << 3),
        /*ACTION_REVERSE      = (1 << 4), - unused */
        ACTION_QUIET          = (1 << 5),
+       ACTION_DANGLING_OK    = (1 << 6),
 };
+typedef uint8_t recurse_flags_t;
 extern int recursive_action(const char *fileName, unsigned flags,
        int FAST_FUNC (*fileAction)(const char *fileName, struct stat* statbuf, void* userData, int depth),
        int FAST_FUNC (*dirAction)(const char *fileName, struct stat* statbuf, void* userData, int depth),
@@ -382,7 +395,7 @@ void xsetenv(const char *key, const char *value) FAST_FUNC;
 void bb_unsetenv(const char *key) FAST_FUNC;
 void xunlink(const char *pathname) FAST_FUNC;
 void xstat(const char *pathname, struct stat *buf) FAST_FUNC;
-int xopen(const char *pathname, int flags) FAST_FUNC FAST_FUNC;
+int xopen(const char *pathname, int flags) FAST_FUNC;
 int xopen3(const char *pathname, int flags, int mode) FAST_FUNC;
 int open_or_warn(const char *pathname, int flags) FAST_FUNC;
 int open3_or_warn(const char *pathname, int flags, int mode) FAST_FUNC;
@@ -426,6 +439,10 @@ struct BUG_too_small {
 };
 
 
+void parse_datestr(const char *date_str, struct tm *tm_time) FAST_FUNC;
+time_t validate_tm_time(const char *date_str, struct tm *tm_time) FAST_FUNC;
+
+
 int xsocket(int domain, int type, int protocol) FAST_FUNC;
 void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) FAST_FUNC;
 void xlisten(int s, int backlog) FAST_FUNC;
@@ -614,6 +631,9 @@ extern void xwrite(int fd, const void *buf, size_t count) FAST_FUNC;
 extern void xwrite_str(int fd, const char *str) FAST_FUNC;
 extern void xopen_xwrite_close(const char* file, const char *str) FAST_FUNC;
 
+/* Close fd, but check for failures (some types of write errors) */
+extern void xclose(int fd) FAST_FUNC;
+
 /* Reads and prints to stdout till eof, then closes FILE. Exits on error: */
 extern void xprint_and_close_file(FILE *file) FAST_FUNC;
 
@@ -671,12 +691,19 @@ char *itoa_to_buf(int n, char *buf, unsigned buflen) FAST_FUNC;
 /* Intelligent formatters of bignums */
 void smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC;
 void smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC;
+/* If block_size == 0, display size without fractional part,
+ * else display (size * block_size) with one decimal digit.
+ * If display_unit == 0, add suffix (K,M,G...),
+ * else divide by display_unit and do not use suffix. */
 //TODO: provide pointer to buf (avoid statics)?
 const char *make_human_readable_str(unsigned long long size,
                unsigned long block_size, unsigned long display_unit) FAST_FUNC;
 /* Put a string of hex bytes ("1b2e66fe"...), return advanced pointer */
 char *bin2hex(char *buf, const char *cp, int count) FAST_FUNC;
 
+/* Generate a UUID */
+void generate_uuid(uint8_t *buf) FAST_FUNC;
+
 /* Last element is marked by mult == 0 */
 struct suffix_mult {
        char suffix[4];
@@ -765,12 +792,8 @@ pid_t safe_waitpid(pid_t pid, int *wstat, int options) FAST_FUNC;
  */
 int wait4pid(pid_t pid) FAST_FUNC;
 pid_t wait_any_nohang(int *wstat) FAST_FUNC;
-#define wait_crashed(w) ((w) & 127)
-#define wait_exitcode(w) ((w) >> 8)
-#define wait_stopsig(w) ((w) >> 8)
-#define wait_stopped(w) (((w) & 127) == 127)
 /* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */
-pid_t spawn_and_wait(char **argv) FAST_FUNC;
+int spawn_and_wait(char **argv) FAST_FUNC;
 struct nofork_save_area {
        jmp_buf die_jmp;
        const char *applet_name;
@@ -839,7 +862,7 @@ int sanitize_env_if_suid(void) FAST_FUNC;
 
 extern const char *const bb_argv_dash[]; /* "-", NULL */
 extern const char *opt_complementary;
-#if ENABLE_GETOPT_LONG
+#if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
 #define No_argument "\0"
 #define Required_argument "\001"
 #define Optional_argument "\002"
@@ -933,54 +956,6 @@ void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC;
 #endif
 
 
-/* "Keycodes" that report an escape sequence.
- * We use something which fits into signed char,
- * yet doesn't represent any valid Unicode characher.
- * Also, -1 is reserved for error indication and we don't use it. */
-enum {
-       KEYCODE_UP       =  -2,
-       KEYCODE_DOWN     =  -3,
-       KEYCODE_RIGHT    =  -4,
-       KEYCODE_LEFT     =  -5,
-       KEYCODE_HOME     =  -6,
-       KEYCODE_END      =  -7,
-       KEYCODE_INSERT   =  -8,
-       KEYCODE_DELETE   =  -9,
-       KEYCODE_PAGEUP   = -10,
-       KEYCODE_PAGEDOWN = -11,
-#if 0
-       KEYCODE_FUN1     = -12,
-       KEYCODE_FUN2     = -13,
-       KEYCODE_FUN3     = -14,
-       KEYCODE_FUN4     = -15,
-       KEYCODE_FUN5     = -16,
-       KEYCODE_FUN6     = -17,
-       KEYCODE_FUN7     = -18,
-       KEYCODE_FUN8     = -19,
-       KEYCODE_FUN9     = -20,
-       KEYCODE_FUN10    = -21,
-       KEYCODE_FUN11    = -22,
-       KEYCODE_FUN12    = -23,
-#endif
-       KEYCODE_CURSOR_POS = -0x100,
-       /* How long is the longest ESC sequence we know?
-        * We want it big enough to be able to contain
-        * cursor position sequence "ESC [ 9999 ; 9999 R"
-        */
-       KEYCODE_BUFFER_SIZE = 16
-};
-/* Note: fd may be in blocking or non-blocking mode, both make sense.
- * For one, less uses non-blocking mode.
- * Only the first read syscall inside read_key may block indefinitely
- * (unless fd is in non-blocking mode),
- * subsequent reads will time out after a few milliseconds.
- * Return of -1 means EOF or error (errno == 0 on EOF).
- * buffer[0] is used as a counter of buffered chars and must be 0
- * on first call.
- */
-int64_t read_key(int fd, char *buffer) FAST_FUNC;
-
-
 /* Networking */
 int create_icmp_socket(void) FAST_FUNC;
 int create_icmp6_socket(void) FAST_FUNC;
@@ -1032,7 +1007,7 @@ extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
 
 #ifdef HAVE_MNTENT_H
 extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC;
-extern struct mntent *find_mount_point(const char *name, const char *table) FAST_FUNC;
+extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC;
 #endif
 extern void erase_mtab(const char * name) FAST_FUNC;
 extern unsigned int tty_baud_to_value(speed_t speed) FAST_FUNC;
@@ -1209,6 +1184,54 @@ unsigned long long bb_makedev(unsigned int major, unsigned int minor) FAST_FUNC;
 #endif
 
 
+/* "Keycodes" that report an escape sequence.
+ * We use something which fits into signed char,
+ * yet doesn't represent any valid Unicode character.
+ * Also, -1 is reserved for error indication and we don't use it. */
+enum {
+       KEYCODE_UP       =  -2,
+       KEYCODE_DOWN     =  -3,
+       KEYCODE_RIGHT    =  -4,
+       KEYCODE_LEFT     =  -5,
+       KEYCODE_HOME     =  -6,
+       KEYCODE_END      =  -7,
+       KEYCODE_INSERT   =  -8,
+       KEYCODE_DELETE   =  -9,
+       KEYCODE_PAGEUP   = -10,
+       KEYCODE_PAGEDOWN = -11,
+#if 0
+       KEYCODE_FUN1     = -12,
+       KEYCODE_FUN2     = -13,
+       KEYCODE_FUN3     = -14,
+       KEYCODE_FUN4     = -15,
+       KEYCODE_FUN5     = -16,
+       KEYCODE_FUN6     = -17,
+       KEYCODE_FUN7     = -18,
+       KEYCODE_FUN8     = -19,
+       KEYCODE_FUN9     = -20,
+       KEYCODE_FUN10    = -21,
+       KEYCODE_FUN11    = -22,
+       KEYCODE_FUN12    = -23,
+#endif
+       KEYCODE_CURSOR_POS = -0x100,
+       /* How long is the longest ESC sequence we know?
+        * We want it big enough to be able to contain
+        * cursor position sequence "ESC [ 9999 ; 9999 R"
+        */
+       KEYCODE_BUFFER_SIZE = 16
+};
+/* Note: fd may be in blocking or non-blocking mode, both make sense.
+ * For one, less uses non-blocking mode.
+ * Only the first read syscall inside read_key may block indefinitely
+ * (unless fd is in non-blocking mode),
+ * subsequent reads will time out after a few milliseconds.
+ * Return of -1 means EOF or error (errno == 0 on EOF).
+ * buffer[0] is used as a counter of buffered chars and must be 0
+ * on first call.
+ */
+int64_t read_key(int fd, char *buffer) FAST_FUNC;
+
+
 #if ENABLE_FEATURE_EDITING
 /* It's NOT just ENABLEd or disabled. It's a number: */
 # ifdef CONFIG_FEATURE_EDITING_HISTORY
@@ -1239,14 +1262,16 @@ enum {
        FOR_SHELL = DO_HISTORY | SAVE_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
 };
 line_input_t *new_line_input_t(int flags) FAST_FUNC;
-/* so far static: void free_line_input_t(line_input_t *n) FAST_FUNC; */
-/* Returns:
+/* So far static: void free_line_input_t(line_input_t *n) FAST_FUNC; */
+/* maxsize must be >= 2.
+ * Returns:
  * -1 on read errors or EOF, or on bare Ctrl-D,
  * 0  on ctrl-C (the line entered is still returned in 'command'),
  * >0 length of input string, including terminating '\n'
  */
 int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state) FAST_FUNC;
 #else
+#define MAX_HISTORY 0
 int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
 #define read_line_input(prompt, command, maxsize, state) \
        read_line_input(prompt, command, maxsize)
@@ -1263,11 +1288,13 @@ enum { COMM_LEN = 16 };
 #endif
 typedef struct procps_status_t {
        DIR *dir;
+       IF_FEATURE_SHOW_THREADS(DIR *task_dir;)
        uint8_t shift_pages_to_bytes;
        uint8_t shift_pages_to_kb;
 /* Fields are set to 0/NULL if failed to determine (or not requested) */
        uint16_t argv_len;
        char *argv0;
+       char *exe;
        IF_SELINUX(char *context;)
        /* Everything below must contain no ptrs to malloc'ed data:
         * it is memset(0) for each process in procps_scan() */
@@ -1280,6 +1307,11 @@ typedef struct procps_status_t {
        unsigned sid;
        unsigned uid;
        unsigned gid;
+#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
+       unsigned ruid;
+       unsigned rgid;
+       int niceness;
+#endif
        unsigned tty_major,tty_minor;
 #if ENABLE_FEATURE_TOPMEM
        unsigned long mapped_rw;
@@ -1300,6 +1332,7 @@ typedef struct procps_status_t {
        int last_seen_on_cpu;
 #endif
 } procps_status_t;
+/* flag bits for procps_scan(xx, flags) calls */
 enum {
        PSSCAN_PID      = 1 << 0,
        PSSCAN_PPID     = 1 << 1,
@@ -1309,7 +1342,7 @@ enum {
        PSSCAN_COMM     = 1 << 5,
        /* PSSCAN_CMD      = 1 << 6, - use read_cmdline instead */
        PSSCAN_ARGV0    = 1 << 7,
-       /* PSSCAN_EXE      = 1 << 8, - not implemented */
+       PSSCAN_EXE      = 1 << 8,
        PSSCAN_STATE    = 1 << 9,
        PSSCAN_VSZ      = 1 << 10,
        PSSCAN_RSS      = 1 << 11,
@@ -1324,25 +1357,26 @@ enum {
                                || ENABLE_PIDOF
                                || ENABLE_SESTATUS
                                ),
-       IF_SELINUX(PSSCAN_CONTEXT = 1 << 17,)
+       PSSCAN_CONTEXT  = (1 << 17) * ENABLE_SELINUX,
        PSSCAN_START_TIME = 1 << 18,
-       PSSCAN_CPU      = 1 << 19,
+       PSSCAN_CPU      = (1 << 19) * ENABLE_FEATURE_TOP_SMP_PROCESS,
+       PSSCAN_NICE     = (1 << 20) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
+       PSSCAN_RUIDGID  = (1 << 21) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
+       PSSCAN_TASKS    = (1 << 22) * ENABLE_FEATURE_SHOW_THREADS,
        /* These are all retrieved from proc/NN/stat in one go: */
        PSSCAN_STAT     = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
        /**/            | PSSCAN_COMM | PSSCAN_STATE
        /**/            | PSSCAN_VSZ | PSSCAN_RSS
        /**/            | PSSCAN_STIME | PSSCAN_UTIME | PSSCAN_START_TIME
-       /**/            | PSSCAN_TTY
-#if ENABLE_FEATURE_TOP_SMP_PROCESS
+       /**/            | PSSCAN_TTY | PSSCAN_NICE
        /**/            | PSSCAN_CPU
-#endif
 };
 //procps_status_t* alloc_procps_scan(void) FAST_FUNC;
 void free_procps_scan(procps_status_t* sp) FAST_FUNC;
 procps_status_t* procps_scan(procps_status_t* sp, int flags) FAST_FUNC;
-/* Format cmdline (up to col chars) into char buf[col+1] */
+/* Format cmdline (up to col chars) into char buf[size] */
 /* Puts [comm] if cmdline is empty (-> process is a kernel thread) */
-void read_cmdline(char *buf, int col, unsigned pid, const char *comm) FAST_FUNC;
+void read_cmdline(char *buf, int size, unsigned pid, const char *comm) FAST_FUNC;
 pid_t *find_pid_by_name(const char* procName) FAST_FUNC;
 pid_t *pidlist_reverse(pid_t *pidList) FAST_FUNC;
 
@@ -1460,7 +1494,7 @@ extern struct globals *const ptr_to_globals;
 /* At least gcc 3.4.6 on mipsel system needs optimization barrier */
 #define barrier() __asm__ __volatile__("":::"memory")
 #define SET_PTR_TO_GLOBALS(x) do { \
-       (*(struct globals**)&ptr_to_globals) = (x); \
+       (*(struct globals**)&ptr_to_globals) = (void*)(x); \
        barrier(); \
 } while (0)
 
@@ -1542,7 +1576,6 @@ extern const char bb_default_login_shell[];
 #undef islower
 #undef isprint
 #undef ispunct
-#undef isspace
 #undef isupper
 #undef isxdigit
 
@@ -1550,6 +1583,16 @@ extern const char bb_default_login_shell[];
 #undef isdigit
 #define isdigit(a) ((unsigned)((a) - '0') <= 9)
 
+/* This one is more efficient too! ~200 bytes */
+/* In POSIX/C locale (the only locale we care about: do we REALLY want
+ * to allow Unicode whitespace in, say, .conf files? nuts!)
+ * isspace is only these chars: "\t\n\v\f\r" and space.
+ * "\t\n\v\f\r" happen to have ASCII codes 9,10,11,12,13.
+ * Use that.
+ */
+#undef isspace
+#define isspace(a) ({ unsigned char bb__isspace = (a) - 9; bb__isspace == (' ' - 9) || bb__isspace <= (13 - 9); })
+
 #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))