1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * Copyright 1985 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 29 /* 30 * under.c - program to execute a command under a given directory 31 * 32 */ 33 34 #include <errno.h> 35 #include <signal.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include <rpc/rpc.h> 41 #include <nfs/nfs.h> 42 #include <rpcsvc/mount.h> 43 #include <sys/time.h> 44 45 static char **Argv; /* saved argument vector (for ps) */ 46 static char *LastArgv; /* saved end-of-argument vector */ 47 48 int Debug = 0; 49 50 int child = 0; /* pid of the executed process */ 51 int ChildDied = 0; /* true when above is valid */ 52 int HasHelper = 0; /* must kill helpers (interactive mode) */ 53 time_t time_now; 54 /* 55 * SETPROCTITLE -- set the title of this process for "ps" 56 * 57 * Does nothing if there were not enough arguments on the command 58 * line for the information. 59 * 60 * Side Effects: 61 * Clobbers argv[] of our main procedure. 62 */ 63 void 64 setproctitle(user, host) 65 char *user, *host; 66 { 67 register char *tohere; 68 69 tohere = Argv[0]; 70 if ((int)(LastArgv == (char *)NULL) || 71 (int)(strlen(user)+strlen(host)+3) > (int)(LastArgv - tohere)) 72 return; 73 *tohere++ = '-'; /* So ps prints (rpc.rexd) */ 74 sprintf(tohere, "%s@%s", user, host); 75 while (*tohere++) /* Skip to end of printf output */ 76 ; 77 while (tohere < LastArgv) /* Avoid confusing ps */ 78 *tohere++ = ' '; 79 } 80 81 82 void 83 main(argc, argv) 84 int argc; 85 char **argv; 86 { 87 static char usage[] = "Usage: under [-d] dir command...\n"; 88 char *dir, *p; 89 char hostname[255]; 90 char *tmpdir, *subdir, *parsefs(); 91 char dirbuf[1024]; 92 char error[1024]; 93 int status; 94 int len; 95 96 if (argc < 3) 97 { 98 fprintf(stderr, usage); 99 exit(1); 100 } 101 102 /* 103 * argv start and extent for setproctitle() 104 */ 105 Argv = argv; 106 if (argc > 0) 107 LastArgv = argv[argc-1] + strlen(argv[argc-1]); 108 else 109 LastArgv = NULL; 110 111 gethostname(hostname, 255); 112 strcat(hostname, ":/"); 113 len = strlen(hostname); 114 if ( strcmp( argv[1], "-d" ) == 0 ) 115 { 116 Debug = 1; 117 argv++; 118 } 119 dir = argv[1]; 120 if ( (int)strlen(dir) > len && (int)strncmp(dir, hostname, len) == 0) 121 dir = strchr(dir, ':') + 1; 122 else if (p = strchr(dir, ':')) 123 { 124 if (p[1] != '/') 125 { 126 fprintf(stderr, "under: %s invalid name\n", dir); 127 exit(1); 128 } 129 130 tmpdir = mktemp("/tmp/underXXXXXX"); 131 132 if ( Debug && errno ) 133 { 134 if ( errno != ENOENT ) 135 printf("mktemp of %s returned %d %s\n", 136 tmpdir, errno, strerror(errno)); 137 } 138 errno = 0; /* XXX access() call in mktemp sets errno = ENOENT */ 139 140 if (mkdir(tmpdir, 0777)) 141 { 142 perror(tmpdir); 143 exit(1); 144 } 145 146 if ( Debug && errno ) 147 printf("mkdir of %s returned %d %s\n", 148 tmpdir, errno, strerror(errno)); 149 150 subdir = parsefs(dir, error); 151 if (subdir == NULL) 152 { 153 exit(1); 154 } 155 time_now = time((long *) 0); 156 if (mount_nfs(dir, tmpdir, error)) 157 { 158 exit(1); 159 } 160 strcpy(dirbuf, tmpdir); 161 strcat(dirbuf, "/"); 162 strcat(dirbuf, subdir); 163 status = runcmd(dirbuf, argv[2], &argv[2]); 164 if (umount_nfs(dir, tmpdir)) 165 fprintf(stderr, "under: couldn't umount %s\n", dir); 166 rmdir(tmpdir); 167 exit(status); 168 } 169 170 setgid(getgid()); 171 setuid(getuid()); 172 if (chdir(dir)) 173 { 174 perror(dir); 175 exit(1); 176 } 177 execvp(argv[2], &argv[2]); 178 perror(argv[2]); 179 exit(1); 180 /* NOTREACHED */ 181 } 182 183 typedef void (*sig_t)(); 184 185 int 186 runcmd(dir, cmd, args) 187 char *dir; 188 char *cmd; 189 char **args; 190 { 191 int pid, child, status; 192 sig_t sigint, sigquit; 193 194 sigint = sigset(SIGINT, SIG_IGN); 195 sigquit = sigset(SIGQUIT, SIG_IGN); 196 pid = fork(); 197 if (pid == -1) 198 return (0177); 199 if (pid == 0) 200 { 201 setgid(getgid()); 202 setuid(getuid()); 203 if (chdir(dir)) 204 { 205 perror(dir); 206 exit(1); 207 } 208 (void) sigset(SIGINT, sigint); 209 (void) sigset(SIGQUIT, sigquit); 210 execvp(cmd, args); 211 perror(cmd); 212 exit(1); 213 } 214 while ((child = wait(&status)) != pid && child != -1) 215 ; 216 (void) sigset(SIGINT, sigint); 217 (void) sigset(SIGQUIT, sigquit); 218 if (child == -1) 219 return (0177); 220 if (status & 0377) 221 return (status & 0377); 222 return ((status >> 8) & 0377); 223 } 224