busybox/libbb/xfuncs.c
Rob Landley c7ddefc062 Attempt at fixing bug 815 by upgrading bb_spawn() so that builtins are at
the start of the path.  (This should be under the same config option as
the standalone shell, but right now that's buried in the shell menu.)

Also add the ability to specify CONFIG_BUSYBOX_EXEC_PATH with /proc/self/exe
as an overrideable default.
2006-06-14 01:24:33 +00:00

233 lines
3.9 KiB
C

/* vi: set sw=4 ts=4: */
/*
* Utility routines.
*
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "busybox.h"
#ifndef DMALLOC
#ifdef L_xmalloc
void *xmalloc(size_t size)
{
void *ptr = malloc(size);
if (ptr == NULL && size != 0)
bb_error_msg_and_die(bb_msg_memory_exhausted);
return ptr;
}
#endif
#ifdef L_xrealloc
void *xrealloc(void *ptr, size_t size)
{
ptr = realloc(ptr, size);
if (ptr == NULL && size != 0)
bb_error_msg_and_die(bb_msg_memory_exhausted);
return ptr;
}
#endif
#ifdef L_xzalloc
void *xzalloc(size_t size)
{
void *ptr = xmalloc(size);
memset(ptr, 0, size);
return ptr;
}
#endif
#ifdef L_xcalloc
void *xcalloc(size_t nmemb, size_t size)
{
void *ptr = calloc(nmemb, size);
if (ptr == NULL && nmemb != 0 && size != 0)
bb_error_msg_and_die(bb_msg_memory_exhausted);
return ptr;
}
#endif
#endif /* DMALLOC */
#ifdef L_xstrdup
char * bb_xstrdup (const char *s)
{
char *t;
if (s == NULL)
return NULL;
t = strdup (s);
if (t == NULL)
bb_error_msg_and_die(bb_msg_memory_exhausted);
return t;
}
#endif
#ifdef L_xstrndup
char * bb_xstrndup (const char *s, int n)
{
char *t;
if (s == NULL)
bb_error_msg_and_die("bb_xstrndup bug");
t = xmalloc(++n);
return safe_strncpy(t,s,n);
}
#endif
#ifdef L_xfopen
FILE *bb_xfopen(const char *path, const char *mode)
{
FILE *fp;
if ((fp = fopen(path, mode)) == NULL)
bb_perror_msg_and_die("%s", path);
return fp;
}
#endif
#ifdef L_xopen
int bb_xopen(const char *pathname, int flags)
{
return bb_xopen3(pathname, flags, 0777);
}
#endif
#ifdef L_xopen3
int bb_xopen3(const char *pathname, int flags, int mode)
{
int ret;
ret = open(pathname, flags, mode);
if (ret < 0) {
bb_perror_msg_and_die("%s", pathname);
}
return ret;
}
#endif
#ifdef L_xread
ssize_t bb_xread(int fd, void *buf, size_t count)
{
ssize_t size;
size = read(fd, buf, count);
if (size < 0) {
bb_perror_msg_and_die(bb_msg_read_error);
}
return(size);
}
#endif
#ifdef L_xread_all
void bb_xread_all(int fd, void *buf, size_t count)
{
ssize_t size;
while (count) {
if ((size = bb_xread(fd, buf, count)) == 0) { /* EOF */
bb_error_msg_and_die("Short read");
}
count -= size;
buf = ((char *) buf) + size;
}
return;
}
#endif
#ifdef L_xread_char
unsigned char bb_xread_char(int fd)
{
char tmp;
bb_xread_all(fd, &tmp, 1);
return(tmp);
}
#endif
#ifdef L_xferror
void bb_xferror(FILE *fp, const char *fn)
{
if (ferror(fp)) {
bb_error_msg_and_die("%s", fn);
}
}
#endif
#ifdef L_xferror_stdout
void bb_xferror_stdout(void)
{
bb_xferror(stdout, bb_msg_standard_output);
}
#endif
#ifdef L_xfflush_stdout
void bb_xfflush_stdout(void)
{
if (fflush(stdout)) {
bb_perror_msg_and_die(bb_msg_standard_output);
}
}
#endif
#ifdef L_spawn
// This does a fork/exec in one call, using vfork().
pid_t bb_spawn(char **argv)
{
static int failed;
pid_t pid;
void *app = find_applet_by_name(argv[0]);
// Be nice to nommu machines.
failed = 0;
pid = vfork();
if (pid < 0) return pid;
if (!pid) {
execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);
// We're sharing a stack with blocked parent, let parent know we failed
// and then exit to unblock parent (but don't run atexit() stuff, which
// would screw up parent.)
failed = -1;
_exit(0);
}
return failed ? failed : pid;
}
#endif
#ifdef L_xspawn
pid_t bb_xspawn(char **argv)
{
pid_t pid = bb_spawn(argv);
if (pid < 0) bb_perror_msg_and_die("%s", *argv);
return pid;
}
#endif
#ifdef L_wait4
int wait4pid(int pid)
{
int status;
if (pid == -1 || waitpid(pid, &status, 0) == -1) return -1;
if (WIFEXITED(status)) return WEXITSTATUS(status);
if (WIFSIGNALED(status)) return WTERMSIG(status);
return 0;
}
#endif