run.c (2390B)
1 /* run.c - command execution */ 2 3 /* 4 * Copyright (c) 2013, Natacha Porté 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <spawn.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <time.h> 23 #include <unistd.h> 24 25 #include "log.h" 26 #include "run.h" 27 28 /* run_entry - start the command associated with the given entry */ 29 pid_t 30 run_entry(struct watch_entry *wentry) { 31 char *argv[4]; 32 size_t i = 0; 33 pid_t result; 34 int has_delay = (wentry->delay.tv_sec || wentry->delay.tv_nsec); 35 36 /* Create a child process and hand control back to parent */ 37 result = has_delay ? fork() : vfork(); 38 if (result == -1) { 39 log_fork(); 40 return 0; 41 } else if (result != 0) { 42 return result; 43 } 44 45 /* chroot if requested */ 46 if (wentry->chroot) { 47 if (chroot(wentry->chroot) < 0) { 48 log_chroot(wentry->chroot); 49 _exit(EXIT_FAILURE); 50 } 51 if (chdir("/") < 0) { 52 log_chdir(wentry->chroot); 53 _exit(EXIT_FAILURE); 54 } 55 } 56 57 /* Set gid and uid if requested */ 58 if (wentry->gid && setgid(wentry->gid) < 0) { 59 log_setgid(wentry->gid); 60 _exit(EXIT_FAILURE); 61 } 62 if (wentry->uid && setuid(wentry->uid) < 0) { 63 log_setuid(wentry->uid); 64 _exit(EXIT_FAILURE); 65 } 66 67 /* Wait for some time if requested */ 68 if (has_delay) 69 nanosleep(&wentry->delay, 0); 70 71 /* Lookup SHELL environment variable */ 72 argv[0] = 0; 73 for (i = 0; wentry->envp[i]; i++) { 74 if (strncmp(wentry->envp[i], "SHELL=", 6) == 0) { 75 argv[0] = wentry->envp[i] + 6; 76 break; 77 } 78 } 79 80 /* Build argument list */ 81 if (!argv[0]) argv[0] = "/bin/sh"; 82 argv[1] = "-c"; 83 argv[2] = (char *)wentry->command; 84 argv[3] = 0; 85 86 /* Handover control to the command */ 87 execve(argv[0], argv, wentry->envp); 88 89 /* Report error */ 90 log_exec(wentry); 91 _exit(EXIT_FAILURE); 92 }