diff options
Diffstat (limited to 'usbmuxd/main.c')
| -rw-r--r-- | usbmuxd/main.c | 201 | 
1 files changed, 140 insertions, 61 deletions
| diff --git a/usbmuxd/main.c b/usbmuxd/main.c index be7451f..6b3c881 100644 --- a/usbmuxd/main.c +++ b/usbmuxd/main.c @@ -33,7 +33,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  #include <sys/socket.h>  #include <sys/un.h>  #include <sys/stat.h> -#include <sys/fcntl.h> +#include <sys/types.h> +#include <fcntl.h>  #include <getopt.h>  #include <pwd.h>  #include <grp.h> @@ -44,7 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  #include "client.h"  static const char *socket_path = "/var/run/usbmuxd"; -static const char *lockfile = "/var/run/usbmuxd.lock"; +static const char *lockfile = "/var/run/usbmuxd.pid";  int should_exit; @@ -55,6 +56,9 @@ static const char *drop_user = "usbmux";  static int opt_udev = 0;  static int opt_exit = 0;  static int exit_signal = 0; +static int daemon_pipe; + +static int report_to_parent = 0;  int create_socket(void) {  	struct sockaddr_un bind_addr; @@ -191,25 +195,47 @@ int main_loop(int listenfd)  /**   * make this program run detached from the current console   */ -static int daemonize() +static int daemonize(void)  {  	pid_t pid;  	pid_t sid; +	int pfd[2]; +	int res;  	// already a daemon  	if (getppid() == 1)  		return 0; +	if((res = pipe(pfd)) < 0) { +		usbmuxd_log(LL_FATAL, "pipe() failed."); +		return res; +	} +  	pid = fork();  	if (pid < 0) { -		exit(EXIT_FAILURE); +		usbmuxd_log(LL_FATAL, "fork() failed."); +		return pid;  	}  	if (pid > 0) {  		// exit parent process -		exit(EXIT_SUCCESS); +		int status; +		close(pfd[1]); + +		if((res = read(pfd[0],&status,sizeof(int))) != sizeof(int)) { +			fprintf(stderr, "usbmuxd: ERROR: Failed to get init status from child, check syslog for messages.\n"); +			exit(1); +		} +		if(status != 0) +			fprintf(stderr, "usbmuxd: ERROR: Child process exited with error %d, check syslog for messages.\n", status); +		exit(status);  	}  	// At this point we are executing as the child process +	// but we need to do one more fork + +	daemon_pipe = pfd[1]; +	close(pfd[0]); +	report_to_parent = 1;  	// Change the file mode mask  	umask(0); @@ -217,23 +243,57 @@ static int daemonize()  	// Create a new SID for the child process  	sid = setsid();  	if (sid < 0) { +		usbmuxd_log(LL_FATAL, "setsid() failed.");  		return -1;  	} + +	pid = fork(); +	if (pid < 0) { +		usbmuxd_log(LL_FATAL, "fork() failed (second)."); +		return pid; +	} + +	if (pid > 0) { +		// exit parent process +		close(daemon_pipe); +		exit(0); +	} +  	// Change the current working directory.  	if ((chdir("/")) < 0) { +		usbmuxd_log(LL_FATAL, "chdir() failed");  		return -2;  	}  	// Redirect standard files to /dev/null  	if (!freopen("/dev/null", "r", stdin)) { -		usbmuxd_log(LL_ERROR, "ERROR: redirection of stdin failed."); +		usbmuxd_log(LL_FATAL, "Redirection of stdin failed."); +		return -3;  	}  	if (!freopen("/dev/null", "w", stdout)) { -		usbmuxd_log(LL_ERROR, "ERROR: redirection of stdout failed."); +		usbmuxd_log(LL_FATAL, "Redirection of stdout failed."); +		return -3; +	} + +	return 0; +} + +static int notify_parent(int status) +{ +	int res; + +	report_to_parent = 0; +	if ((res = write(daemon_pipe, &status, sizeof(int))) != sizeof(int)) { +		usbmuxd_log(LL_FATAL, "Could not notify parent!"); +		if(res >= 0) +			return -2; +		else +			return res;  	} +	close(daemon_pipe);  	if (!freopen("/dev/null", "w", stderr)) { -		usbmuxd_log(LL_ERROR, "ERROR: redirection of stderr failed."); +		usbmuxd_log(LL_FATAL, "Redirection of stderr failed."); +		return -1;  	} -  	return 0;  } @@ -310,8 +370,9 @@ int main(int argc, char *argv[])  {  	int listenfd;  	int res = 0; -	FILE *lfd = NULL; +	int lfd;  	struct flock lock; +	char pids[10];  	parse_opts(argc, argv); @@ -333,60 +394,77 @@ int main(int argc, char *argv[])  	set_signal_handlers(); -	lfd = fopen(lockfile, "r"); -	if (lfd) { -		lock.l_type = 0; -		lock.l_whence = SEEK_SET; -		lock.l_start = 0; -		lock.l_len = 0; -		fcntl(fileno(lfd), F_GETLK, &lock); -		fclose(lfd); -		if (lock.l_type != F_UNLCK) { -			if (opt_exit) { -				if (lock.l_pid && !kill(lock.l_pid, 0)) { -					usbmuxd_log(LL_NOTICE, "sending signal %d to instance with pid %d", exit_signal, lock.l_pid); -					if (kill(lock.l_pid, exit_signal) < 0) { -						usbmuxd_log(LL_FATAL, "Error: could not deliver signal %d to pid %d", exit_signal, lock.l_pid); -					} -					res = 0; -					goto terminate; -				} else { -					usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!"); +	res = lfd = open(lockfile, O_WRONLY|O_CREAT, 0644); +	if(res == -1) { +		usbmuxd_log(LL_FATAL, "Could not open lockfile"); +		goto terminate; +	} +	lock.l_type = F_WRLCK; +	lock.l_whence = SEEK_SET; +	lock.l_start = 0; +	lock.l_len = 0; +	fcntl(lfd, F_GETLK, &lock); +	close(lfd); +	if (lock.l_type != F_UNLCK) { +		if (opt_exit) { +			if (lock.l_pid && !kill(lock.l_pid, 0)) { +				usbmuxd_log(LL_NOTICE, "Sending signal %d to instance with pid %d", exit_signal, lock.l_pid); +				res = 0; +				if (kill(lock.l_pid, exit_signal) < 0) { +					usbmuxd_log(LL_FATAL, "Could not deliver signal %d to pid %d", exit_signal, lock.l_pid);  					res = -1; -					goto terminate;  				} +				goto terminate;  			} else { -				if (!opt_udev) { -					usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid); -					res = -1; -				} else { -					usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). exiting.", lock.l_pid); -					res = 0; -				} +				usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!"); +				res = -1;  				goto terminate;  			} +		} else { +			if (!opt_udev) { +				usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid); +				res = -1; +			} else { +				usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). exiting.", lock.l_pid); +				res = 0; +			} +			goto terminate;  		}  	} +	unlink(lockfile);  	if (opt_exit) {  		usbmuxd_log(LL_NOTICE, "No running instance found, none killed. exiting.");  		goto terminate;  	} -	// now open the lockfile and place the lock -	lfd = fopen(lockfile, "w"); -	if (lfd) { -		lock.l_type = F_WRLCK; -		lock.l_whence = SEEK_SET; -		lock.l_start = 0; -		lock.l_len = 0; -		if ((res = fcntl(fileno(lfd), F_SETLK, &lock)) < 0) { -			usbmuxd_log(LL_FATAL, "Lockfile locking failed!"); +	if (!foreground) { +		if ((res = daemonize()) < 0) { +			fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); +			usbmuxd_log(LL_FATAL, "Could not daemonize!");  			goto terminate;  		} -	} else { -		usbmuxd_log(LL_FATAL, "Lockfile open failed!"); -		res = -1; +	} + +	// now open the lockfile and place the lock +	res = lfd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); +	if(res < 0) { +		usbmuxd_log(LL_FATAL, "Could not open lockfile"); +		goto terminate; +	} +	lock.l_type = F_WRLCK; +	lock.l_whence = SEEK_SET; +	lock.l_start = 0; +	lock.l_len = 0; +	if ((res = fcntl(lfd, F_SETLK, &lock)) < 0) { +		usbmuxd_log(LL_FATAL, "Lockfile locking failed!"); +		goto terminate; +	} +	sprintf(pids, "%d", getpid()); +	if ((res = write(lfd, pids, strlen(pids))) != strlen(pids)) { +		usbmuxd_log(LL_FATAL, "Could not write pidfile!"); +		if(res >= 0) +			res = -2;  		goto terminate;  	} @@ -400,7 +478,7 @@ int main(int argc, char *argv[])  		struct passwd *pw = getpwnam(drop_user);  		if (!pw) {  			usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user); -			res = 1; +			res = -1;  			goto terminate;  		} @@ -420,12 +498,12 @@ int main(int argc, char *argv[])  		// security check  		if (setuid(0) != -1) {  			usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); -			res = 1; +			res = -1;  			goto terminate;  		}  		if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) {  			usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); -			res = 1; +			res = -1;  			goto terminate;  		}  		usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user); @@ -441,13 +519,9 @@ int main(int argc, char *argv[])  	usbmuxd_log(LL_NOTICE, "Initialization complete"); -	if (!foreground) { -		if ((res = daemonize()) < 0) { -			fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); -			usbmuxd_log(LL_FATAL, "Could not daemonize!"); +	if (report_to_parent) +		if((res = notify_parent(0)) < 0)  			goto terminate; -		} -	}  	res = main_loop(listenfd);  	if(res < 0) @@ -463,7 +537,12 @@ int main(int argc, char *argv[])  terminate:  	log_disable_syslog(); -	if(res < 0) -		return -res; -	return 0; +	if (res < 0) +		res = -res; +	else +		res = 0; +	if (report_to_parent) +		notify_parent(res); + +	return res;  } | 
