/* run-cmd.c -- spawn processes with some options */ /* $Id$ */ /* Carlos Duarte , 990613 */ #define HAVE_GETDTABLESIZE #define HAVE_SETSID #include #include #include #include static int do_args(int first, int ac, char *av[]); static int get_user(char *user); static int add_env(char **var); extern char **environ; #define ARG() \ s[1] ? (t=s+1, s+=strlen(s)-1, t) : ++i #include #include #include #include #include #include #include #if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE) #define RLIMIT_NOFILE RLIMIT_OFILE #endif static int maxfds(void) { #if !defined(done) && defined(HAVE_GETDTABLESIZE) return getdtablesize(); #define done #endif #if !defined(done) && defined(RLIMIT_NOFILE) struct rlimit rr = {-1, -1}; getrlimit(RLIMIT_NOFILE, &rr); return rr.rlim_cur; #define done #endif return -1; #undef done } static int my_setsid() { #if !defined done && defined HAVE_SETSID return setsid(); #define done #endif #if !defined done && defined HAVE_SETPGRP int fd; int r; r = setpgrp(); if ((fd = open("/dev/tty")) != -1) { ioctl(fd, TIOCNOTTY, 0); close(fd); } return r; #endif return -1; #undef done } static int add_env(char **var) { if (strchr(*var, '=') == NULL) return 0; if (opts.env.cur >= (opts.env.max-1)) { /* one for extra NULL */ opts.env.max *= 2; if (opts.env.env == opts.env.s_buf) { opts.env.env = malloc(sizeof(char*) * opts.env.max); if (opts.env.env) memcpy(opts.env.env, opts.env.s_buf, sizeof opts.env.s_buf); } else opts.env.env = realloc(opts.env.env, sizeof(char*) * opts.env.max); if (opts.env.env == NULL) { perror("alloc"); exit(1); } } opts.env.env[opts.env.cur++] = *var; opts.env.env[opts.env.cur] = 0; return 1; } static int get_user(char *user) { #define sz 99 char u[sz]; char g[sz]; char *p; memset(u, 0, sizeof u); memset(g, 0, sizeof g); if ((p = strchr(user, ':')) == NULL) { strncpy(u, user, sz); } else { char *s = user; char *t = u; while (s

pw_uid; } if (g[0]) { struct group *pwd; if (isdigit(g[0])) pwd = getgrgid(atoi(g)); else pwd = getgrnam(g); if (!pwd) { fprintf(stderr, "%s: invalid group\n", g); exit(1); } opts.group = pwd->gr_gid; } return 1; } static int do_args(int ix, int argc, char *argv[]) { int i, d, pid; if (ix == argc) { USAGE(); } if (!opts.no_fork) { pid = fork(); if (pid == -1) { perror("fork"); exit(1); } if (pid) { if (opts.printpid) printf("%d\n", pid); return 0; } } else { if (opts.printpid) fprintf(stderr, "%d\n", getpid()); } d = maxfds(); for (i=3; i2) close(d); } /* keep parent environ */ if (!opts.no_parent_env) { char **env = environ; while (*env) add_env(env++); } if (opts.setsid && my_setsid() == -1) { perror("my_setsid"); exit(1); } if (opts.group != -1 && setgid(opts.group) == -1) { perror("setgid"); exit(1); } if (opts.user != -1 && setuid(opts.user) == -1) { perror("setuid"); exit(1); } execve(argv[ix], &argv[ix], opts.env.env); fprintf(stderr, "execve: %s: %s\n", argv[ix], strerror(errno)); return 1; }