httpd: add -u user[:grp] support
[oweals/busybox.git] / libbb / xfuncs.c
index cfb1c29ac582979fd601e691d2d2c01e773e510c..de765a32d949445c84958858dd02f57c418f758d 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (C) 2006 Rob Landley
  * Copyright (C) 2006 Denis Vlasenko
  *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPL version 2, see file LICENSE in this tarball for details.
  */
 
 #include "busybox.h"
  * succeeded. */
 
 #ifndef DMALLOC
-#ifdef L_xmalloc
+/* dmalloc provides variants of these that do abort() on failure.
+ * Since dmalloc's prototypes overwrite the impls here as they are
+ * included after these prototypes in libbb.h, all is well.
+ */
 // Die if we can't allocate size bytes of memory.
 void *xmalloc(size_t size)
 {
@@ -25,9 +28,7 @@ void *xmalloc(size_t size)
                bb_error_msg_and_die(bb_msg_memory_exhausted);
        return ptr;
 }
-#endif
 
-#ifdef L_xrealloc
 // Die if we can't resize previously allocated memory.  (This returns a pointer
 // to the new memory, which may or may not be the same as the old memory.
 // It'll copy the contents to a new chunk and free the old one if necessary.)
@@ -38,9 +39,8 @@ void *xrealloc(void *ptr, size_t size)
                bb_error_msg_and_die(bb_msg_memory_exhausted);
        return ptr;
 }
-#endif
+#endif /* DMALLOC */
 
-#ifdef L_xzalloc
 // Die if we can't allocate and zero size bytes of memory.
 void *xzalloc(size_t size)
 {
@@ -48,11 +48,7 @@ void *xzalloc(size_t size)
        memset(ptr, 0, size);
        return ptr;
 }
-#endif
-
-#endif /* DMALLOC */
 
-#ifdef L_xstrdup
 // Die if we can't copy a string to freshly allocated memory.
 char * xstrdup(const char *s)
 {
@@ -68,9 +64,7 @@ char * xstrdup(const char *s)
 
        return t;
 }
-#endif
 
-#ifdef L_xstrndup
 // Die if we can't allocate n+1 bytes (space for the null terminator) and copy
 // the (possibly truncated to length n) string into it.
 char * xstrndup(const char *s, int n)
@@ -84,9 +78,7 @@ char * xstrndup(const char *s, int n)
 
        return safe_strncpy(t,s,n);
 }
-#endif
 
-#ifdef L_xfopen
 // Die if we can't open a file and return a FILE * to it.
 // Notice we haven't got xfread(), This is for use with fscanf() and friends.
 FILE *xfopen(const char *path, const char *mode)
@@ -96,20 +88,16 @@ FILE *xfopen(const char *path, const char *mode)
                bb_perror_msg_and_die("%s", path);
        return fp;
 }
-#endif
 
-#ifdef L_xopen
 // Die if we can't open an existing file and return an fd.
 int xopen(const char *pathname, int flags)
 {
-       if (ENABLE_DEBUG && (flags && O_CREAT))
-               bb_error_msg_and_die("xopen() with O_CREAT\n");
+       if (ENABLE_DEBUG && (flags & O_CREAT))
+               bb_error_msg_and_die("xopen() with O_CREAT");
 
        return xopen3(pathname, flags, 0777);
 }
-#endif
 
-#ifdef L_xopen3
 // Die if we can't open a new file and return an fd.
 int xopen3(const char *pathname, int flags, int mode)
 {
@@ -121,9 +109,7 @@ int xopen3(const char *pathname, int flags, int mode)
        }
        return ret;
 }
-#endif
 
-#ifdef L_xread
 // Die with an error message if we can't read the entire buffer.
 void xread(int fd, void *buf, size_t count)
 {
@@ -136,9 +122,7 @@ void xread(int fd, void *buf, size_t count)
                buf = ((char *) buf) + size;
        }
 }
-#endif
 
-#ifdef L_xwrite
 // Die with an error message if we can't write the entire buffer.
 void xwrite(int fd, void *buf, size_t count)
 {
@@ -151,17 +135,13 @@ void xwrite(int fd, void *buf, size_t count)
                buf = ((char *) buf) + size;
        }
 }
-#endif
 
-#ifdef L_xlseek
 // Die with an error message if we can't lseek to the right spot.
 void xlseek(int fd, off_t offset, int whence)
 {
        if (offset != lseek(fd, offset, whence)) bb_error_msg_and_die("lseek");
 }
-#endif
 
-#ifdef L_xread_char
 // Die with an error message if we can't read one character.
 unsigned char xread_char(int fd)
 {
@@ -171,9 +151,7 @@ unsigned char xread_char(int fd)
 
        return(tmp);
 }
-#endif
 
-#ifdef L_xferror
 // Die with supplied error message if this FILE * has ferror set.
 void xferror(FILE *fp, const char *fn)
 {
@@ -181,17 +159,13 @@ void xferror(FILE *fp, const char *fn)
                bb_error_msg_and_die("%s", fn);
        }
 }
-#endif
 
-#ifdef L_xferror_stdout
 // Die with an error message if stdout has ferror set.
 void xferror_stdout(void)
 {
        xferror(stdout, bb_msg_standard_output);
 }
-#endif
 
-#ifdef L_xfflush_stdout
 // Die with an error message if we have trouble flushing stdout.
 void xfflush_stdout(void)
 {
@@ -199,16 +173,14 @@ void xfflush_stdout(void)
                bb_perror_msg_and_die(bb_msg_standard_output);
        }
 }
-#endif
 
-#ifdef L_spawn
 // This does a fork/exec in one call, using vfork().  Return PID of new child,
 // -1 for failure.  Runs argv[0], searching path if that has no / in it.
 pid_t spawn(char **argv)
 {
        static int failed;
        pid_t pid;
-       void *app = find_applet_by_name(argv[0]);
+       void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0;
 
        // Be nice to nommu machines.
        failed = 0;
@@ -226,9 +198,7 @@ pid_t spawn(char **argv)
        }
        return failed ? failed : pid;
 }
-#endif
 
-#ifdef L_xspawn
 // Die with an error message if we can't spawn a child process.
 pid_t xspawn(char **argv)
 {
@@ -236,9 +206,7 @@ pid_t xspawn(char **argv)
        if (pid < 0) bb_perror_msg_and_die("%s", *argv);
        return pid;
 }
-#endif
 
-#ifdef L_wait4
 // Wait for the specified child PID to exit, returning child's error return.
 int wait4pid(int pid)
 {
@@ -249,9 +217,13 @@ int wait4pid(int pid)
        if (WIFSIGNALED(status)) return WTERMSIG(status);
        return 0;
 }
-#endif
 
-#ifdef L_itoa
+void xsetenv(const char *key, const char *value)
+{
+       if(setenv(key, value, 1))
+               bb_error_msg_and_die(bb_msg_memory_exhausted);
+}
+
 // Convert unsigned integer to ascii, writing into supplied buffer.  A
 // truncated result is always null terminated (unless buflen is 0), and
 // contains the first few digits of the result ala strncpy.
@@ -307,9 +279,7 @@ char *itoa(int n)
 
        return local_buf;
 }
-#endif
 
-#ifdef L_setuid
 // Die with an error message if we can't set gid.  (Because resource limits may
 // limit this user to a given number of processes, and if that fills up the
 // setgid() will fail and we'll _still_be_root_, which is bad.)
@@ -323,9 +293,7 @@ void xsetuid(uid_t uid)
 {
        if (setuid(uid)) bb_error_msg_and_die("setuid");
 }
-#endif
 
-#ifdef L_fdlength
 // Return how long the file at fd is, if there's any way to determine it.
 off_t fdlength(int fd)
 {
@@ -342,7 +310,7 @@ off_t fdlength(int fd)
        do {
                char temp;
 
-               pos = bottom + (top - bottom) / 2;;
+               pos = bottom + (top - bottom) / 2;
 
                // If we can read from the current location, it's bigger.
 
@@ -363,9 +331,7 @@ off_t fdlength(int fd)
 
        return pos + 1;
 }
-#endif
 
-#ifdef L_xasprintf
 // Die with an error message if we can't malloc() enough space and do an
 // sprintf() into that space.
 char *xasprintf(const char *format, ...)
@@ -390,33 +356,28 @@ char *xasprintf(const char *format, ...)
        va_end(p);
 #endif
 
-       if (r < 0) bb_perror_msg_and_die("xasprintf");
+       if (r < 0) bb_error_msg_and_die(bb_msg_memory_exhausted);
        return string_ptr;
 }
-#endif
 
-#ifdef L_xprint_and_close_file
 // Die with an error message if we can't copy an entire FILE * to stdout, then
 // close that file.
 void xprint_and_close_file(FILE *file)
 {
        // copyfd outputs error messages for us.
-       if (bb_copyfd_eof(fileno(file), 1) == -1) exit(bb_default_error_retval);
+       if (bb_copyfd_eof(fileno(file), 1) == -1)
+               exit(xfunc_error_retval);
 
        fclose(file);
 }
-#endif
 
-#ifdef L_xchdir
 // Die if we can't chdir to a new path.
 void xchdir(const char *path)
 {
        if (chdir(path))
                bb_perror_msg_and_die("chdir(%s)", path);
 }
-#endif
 
-#ifdef L_warn_opendir
 // Print a warning message if opendir() fails, but don't die.
 DIR *warn_opendir(const char *path)
 {
@@ -428,9 +389,7 @@ DIR *warn_opendir(const char *path)
        }
        return dp;
 }
-#endif
 
-#ifdef L_xopendir
 // Die with an error message if opendir() fails.
 DIR *xopendir(const char *path)
 {
@@ -440,19 +399,15 @@ DIR *xopendir(const char *path)
                bb_perror_msg_and_die("unable to open `%s'", path);
        return dp;
 }
-#endif
 
-#ifdef L_xdaemon
 #ifndef BB_NOMMU
 // Die with an error message if we can't daemonize.
 void xdaemon(int nochdir, int noclose)
 {
-           if (daemon(nochdir, noclose)) bb_perror_msg_and_die("daemon");
+       if (daemon(nochdir, noclose)) bb_perror_msg_and_die("daemon");
 }
 #endif
-#endif
 
-#ifdef L_xsocket
 // Die with an error message if we can't open a new socket.
 int xsocket(int domain, int type, int protocol)
 {
@@ -462,20 +417,44 @@ int xsocket(int domain, int type, int protocol)
 
        return r;
 }
-#endif
 
-#ifdef L_xbind
 // Die with an error message if we can't bind a socket to an address.
 void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
 {
        if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
 }
-#endif
 
-#ifdef L_xlisten
 // Die with an error message if we can't listen for connections on a socket.
 void xlisten(int s, int backlog)
 {
        if (listen(s, backlog)) bb_perror_msg_and_die("listen");
 }
-#endif
+
+// xstat() - a stat() which dies on failure with meaningful error message
+void xstat(char *name, struct stat *stat_buf)
+{
+       if (stat(name, stat_buf))
+               bb_perror_msg_and_die("can't stat '%s'", name);
+}
+
+/* It is perfectly ok to pass in a NULL for either width or for
+ *  * height, in which case that value will not be set.  */
+int get_terminal_width_height(int fd, int *width, int *height)
+{
+       struct winsize win = { 0, 0, 0, 0 };
+       int ret = ioctl(fd, TIOCGWINSZ, &win);
+       if (!win.ws_row) {
+               char *s = getenv("LINES");
+               if (s) win.ws_row = atoi(s);
+       }
+       if (win.ws_row <= 1) win.ws_row = 24;
+       if (!win.ws_col) {
+               char *s = getenv("COLUMNS");
+               if (s) win.ws_col = atoi(s);
+       }
+       if (win.ws_col <= 1) win.ws_col = 80;
+       if (height) *height = (int) win.ws_row;
+       if (width) *width = (int) win.ws_col;
+
+       return ret;
+}