/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 1985 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * under.c - program to execute a command under a given directory * */ #include #include #include #include #include #include #include #include #include static char **Argv; /* saved argument vector (for ps) */ static char *LastArgv; /* saved end-of-argument vector */ int Debug = 0; int child = 0; /* pid of the executed process */ int ChildDied = 0; /* true when above is valid */ int HasHelper = 0; /* must kill helpers (interactive mode) */ time_t time_now; /* * SETPROCTITLE -- set the title of this process for "ps" * * Does nothing if there were not enough arguments on the command * line for the information. * * Side Effects: * Clobbers argv[] of our main procedure. */ void setproctitle(user, host) char *user, *host; { register char *tohere; tohere = Argv[0]; if ((int)(LastArgv == (char *)NULL) || (int)(strlen(user)+strlen(host)+3) > (int)(LastArgv - tohere)) return; *tohere++ = '-'; /* So ps prints (rpc.rexd) */ sprintf(tohere, "%s@%s", user, host); while (*tohere++) /* Skip to end of printf output */ ; while (tohere < LastArgv) /* Avoid confusing ps */ *tohere++ = ' '; } void main(argc, argv) int argc; char **argv; { static char usage[] = "Usage: under [-d] dir command...\n"; char *dir, *p; char hostname[255]; char *tmpdir, *subdir, *parsefs(); char dirbuf[1024]; char error[1024]; int status; int len; if (argc < 3) { fprintf(stderr, usage); exit(1); } /* * argv start and extent for setproctitle() */ Argv = argv; if (argc > 0) LastArgv = argv[argc-1] + strlen(argv[argc-1]); else LastArgv = NULL; gethostname(hostname, 255); strcat(hostname, ":/"); len = strlen(hostname); if ( strcmp( argv[1], "-d" ) == 0 ) { Debug = 1; argv++; } dir = argv[1]; if ( (int)strlen(dir) > len && (int)strncmp(dir, hostname, len) == 0) dir = strchr(dir, ':') + 1; else if (p = strchr(dir, ':')) { if (p[1] != '/') { fprintf(stderr, "under: %s invalid name\n", dir); exit(1); } tmpdir = mktemp("/tmp/underXXXXXX"); if ( Debug && errno ) { if ( errno != ENOENT ) printf("mktemp of %s returned %d %s\n", tmpdir, errno, strerror(errno)); } errno = 0; /* XXX access() call in mktemp sets errno = ENOENT */ if (mkdir(tmpdir, 0777)) { perror(tmpdir); exit(1); } if ( Debug && errno ) printf("mkdir of %s returned %d %s\n", tmpdir, errno, strerror(errno)); subdir = parsefs(dir, error); if (subdir == NULL) { exit(1); } time_now = time((long *) 0); if (mount_nfs(dir, tmpdir, error)) { exit(1); } strcpy(dirbuf, tmpdir); strcat(dirbuf, "/"); strcat(dirbuf, subdir); status = runcmd(dirbuf, argv[2], &argv[2]); if (umount_nfs(dir, tmpdir)) fprintf(stderr, "under: couldn't umount %s\n", dir); rmdir(tmpdir); exit(status); } setgid(getgid()); setuid(getuid()); if (chdir(dir)) { perror(dir); exit(1); } execvp(argv[2], &argv[2]); perror(argv[2]); exit(1); /* NOTREACHED */ } typedef void (*sig_t)(); int runcmd(dir, cmd, args) char *dir; char *cmd; char **args; { int pid, child, status; sig_t sigint, sigquit; sigint = sigset(SIGINT, SIG_IGN); sigquit = sigset(SIGQUIT, SIG_IGN); pid = fork(); if (pid == -1) return (0177); if (pid == 0) { setgid(getgid()); setuid(getuid()); if (chdir(dir)) { perror(dir); exit(1); } (void) sigset(SIGINT, sigint); (void) sigset(SIGQUIT, sigquit); execvp(cmd, args); perror(cmd); exit(1); } while ((child = wait(&status)) != pid && child != -1) ; (void) sigset(SIGINT, sigint); (void) sigset(SIGQUIT, sigquit); if (child == -1) return (0177); if (status & 0377) return (status & 0377); return ((status >> 8) & 0377); }