filewatcherd

FreeBSD daemon that watches files and runs commands when they change
git clone https://git.instinctive.eu/filewatcherd.git
Log | Files | Refs | README | LICENSE

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 }