summaryrefslogtreecommitdiffstats
path: root/usbmuxd
diff options
context:
space:
mode:
Diffstat (limited to 'usbmuxd')
-rw-r--r--usbmuxd/main.c201
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
33#include <sys/socket.h> 33#include <sys/socket.h>
34#include <sys/un.h> 34#include <sys/un.h>
35#include <sys/stat.h> 35#include <sys/stat.h>
36#include <sys/fcntl.h> 36#include <sys/types.h>
37#include <fcntl.h>
37#include <getopt.h> 38#include <getopt.h>
38#include <pwd.h> 39#include <pwd.h>
39#include <grp.h> 40#include <grp.h>
@@ -44,7 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44#include "client.h" 45#include "client.h"
45 46
46static const char *socket_path = "/var/run/usbmuxd"; 47static const char *socket_path = "/var/run/usbmuxd";
47static const char *lockfile = "/var/run/usbmuxd.lock"; 48static const char *lockfile = "/var/run/usbmuxd.pid";
48 49
49int should_exit; 50int should_exit;
50 51
@@ -55,6 +56,9 @@ static const char *drop_user = "usbmux";
55static int opt_udev = 0; 56static int opt_udev = 0;
56static int opt_exit = 0; 57static int opt_exit = 0;
57static int exit_signal = 0; 58static int exit_signal = 0;
59static int daemon_pipe;
60
61static int report_to_parent = 0;
58 62
59int create_socket(void) { 63int create_socket(void) {
60 struct sockaddr_un bind_addr; 64 struct sockaddr_un bind_addr;
@@ -191,25 +195,47 @@ int main_loop(int listenfd)
191/** 195/**
192 * make this program run detached from the current console 196 * make this program run detached from the current console
193 */ 197 */
194static int daemonize() 198static int daemonize(void)
195{ 199{
196 pid_t pid; 200 pid_t pid;
197 pid_t sid; 201 pid_t sid;
202 int pfd[2];
203 int res;
198 204
199 // already a daemon 205 // already a daemon
200 if (getppid() == 1) 206 if (getppid() == 1)
201 return 0; 207 return 0;
202 208
209 if((res = pipe(pfd)) < 0) {
210 usbmuxd_log(LL_FATAL, "pipe() failed.");
211 return res;
212 }
213
203 pid = fork(); 214 pid = fork();
204 if (pid < 0) { 215 if (pid < 0) {
205 exit(EXIT_FAILURE); 216 usbmuxd_log(LL_FATAL, "fork() failed.");
217 return pid;
206 } 218 }
207 219
208 if (pid > 0) { 220 if (pid > 0) {
209 // exit parent process 221 // exit parent process
210 exit(EXIT_SUCCESS); 222 int status;
223 close(pfd[1]);
224
225 if((res = read(pfd[0],&status,sizeof(int))) != sizeof(int)) {
226 fprintf(stderr, "usbmuxd: ERROR: Failed to get init status from child, check syslog for messages.\n");
227 exit(1);
228 }
229 if(status != 0)
230 fprintf(stderr, "usbmuxd: ERROR: Child process exited with error %d, check syslog for messages.\n", status);
231 exit(status);
211 } 232 }
212 // At this point we are executing as the child process 233 // At this point we are executing as the child process
234 // but we need to do one more fork
235
236 daemon_pipe = pfd[1];
237 close(pfd[0]);
238 report_to_parent = 1;
213 239
214 // Change the file mode mask 240 // Change the file mode mask
215 umask(0); 241 umask(0);
@@ -217,23 +243,57 @@ static int daemonize()
217 // Create a new SID for the child process 243 // Create a new SID for the child process
218 sid = setsid(); 244 sid = setsid();
219 if (sid < 0) { 245 if (sid < 0) {
246 usbmuxd_log(LL_FATAL, "setsid() failed.");
220 return -1; 247 return -1;
221 } 248 }
249
250 pid = fork();
251 if (pid < 0) {
252 usbmuxd_log(LL_FATAL, "fork() failed (second).");
253 return pid;
254 }
255
256 if (pid > 0) {
257 // exit parent process
258 close(daemon_pipe);
259 exit(0);
260 }
261
222 // Change the current working directory. 262 // Change the current working directory.
223 if ((chdir("/")) < 0) { 263 if ((chdir("/")) < 0) {
264 usbmuxd_log(LL_FATAL, "chdir() failed");
224 return -2; 265 return -2;
225 } 266 }
226 // Redirect standard files to /dev/null 267 // Redirect standard files to /dev/null
227 if (!freopen("/dev/null", "r", stdin)) { 268 if (!freopen("/dev/null", "r", stdin)) {
228 usbmuxd_log(LL_ERROR, "ERROR: redirection of stdin failed."); 269 usbmuxd_log(LL_FATAL, "Redirection of stdin failed.");
270 return -3;
229 } 271 }
230 if (!freopen("/dev/null", "w", stdout)) { 272 if (!freopen("/dev/null", "w", stdout)) {
231 usbmuxd_log(LL_ERROR, "ERROR: redirection of stdout failed."); 273 usbmuxd_log(LL_FATAL, "Redirection of stdout failed.");
274 return -3;
275 }
276
277 return 0;
278}
279
280static int notify_parent(int status)
281{
282 int res;
283
284 report_to_parent = 0;
285 if ((res = write(daemon_pipe, &status, sizeof(int))) != sizeof(int)) {
286 usbmuxd_log(LL_FATAL, "Could not notify parent!");
287 if(res >= 0)
288 return -2;
289 else
290 return res;
232 } 291 }
292 close(daemon_pipe);
233 if (!freopen("/dev/null", "w", stderr)) { 293 if (!freopen("/dev/null", "w", stderr)) {
234 usbmuxd_log(LL_ERROR, "ERROR: redirection of stderr failed."); 294 usbmuxd_log(LL_FATAL, "Redirection of stderr failed.");
295 return -1;
235 } 296 }
236
237 return 0; 297 return 0;
238} 298}
239 299
@@ -310,8 +370,9 @@ int main(int argc, char *argv[])
310{ 370{
311 int listenfd; 371 int listenfd;
312 int res = 0; 372 int res = 0;
313 FILE *lfd = NULL; 373 int lfd;
314 struct flock lock; 374 struct flock lock;
375 char pids[10];
315 376
316 parse_opts(argc, argv); 377 parse_opts(argc, argv);
317 378
@@ -333,60 +394,77 @@ int main(int argc, char *argv[])
333 394
334 set_signal_handlers(); 395 set_signal_handlers();
335 396
336 lfd = fopen(lockfile, "r"); 397 res = lfd = open(lockfile, O_WRONLY|O_CREAT, 0644);
337 if (lfd) { 398 if(res == -1) {
338 lock.l_type = 0; 399 usbmuxd_log(LL_FATAL, "Could not open lockfile");
339 lock.l_whence = SEEK_SET; 400 goto terminate;
340 lock.l_start = 0; 401 }
341 lock.l_len = 0; 402 lock.l_type = F_WRLCK;
342 fcntl(fileno(lfd), F_GETLK, &lock); 403 lock.l_whence = SEEK_SET;
343 fclose(lfd); 404 lock.l_start = 0;
344 if (lock.l_type != F_UNLCK) { 405 lock.l_len = 0;
345 if (opt_exit) { 406 fcntl(lfd, F_GETLK, &lock);
346 if (lock.l_pid && !kill(lock.l_pid, 0)) { 407 close(lfd);
347 usbmuxd_log(LL_NOTICE, "sending signal %d to instance with pid %d", exit_signal, lock.l_pid); 408 if (lock.l_type != F_UNLCK) {
348 if (kill(lock.l_pid, exit_signal) < 0) { 409 if (opt_exit) {
349 usbmuxd_log(LL_FATAL, "Error: could not deliver signal %d to pid %d", exit_signal, lock.l_pid); 410 if (lock.l_pid && !kill(lock.l_pid, 0)) {
350 } 411 usbmuxd_log(LL_NOTICE, "Sending signal %d to instance with pid %d", exit_signal, lock.l_pid);
351 res = 0; 412 res = 0;
352 goto terminate; 413 if (kill(lock.l_pid, exit_signal) < 0) {
353 } else { 414 usbmuxd_log(LL_FATAL, "Could not deliver signal %d to pid %d", exit_signal, lock.l_pid);
354 usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
355 res = -1; 415 res = -1;
356 goto terminate;
357 } 416 }
417 goto terminate;
358 } else { 418 } else {
359 if (!opt_udev) { 419 usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
360 usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid); 420 res = -1;
361 res = -1;
362 } else {
363 usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). exiting.", lock.l_pid);
364 res = 0;
365 }
366 goto terminate; 421 goto terminate;
367 } 422 }
423 } else {
424 if (!opt_udev) {
425 usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid);
426 res = -1;
427 } else {
428 usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). exiting.", lock.l_pid);
429 res = 0;
430 }
431 goto terminate;
368 } 432 }
369 } 433 }
434 unlink(lockfile);
370 435
371 if (opt_exit) { 436 if (opt_exit) {
372 usbmuxd_log(LL_NOTICE, "No running instance found, none killed. exiting."); 437 usbmuxd_log(LL_NOTICE, "No running instance found, none killed. exiting.");
373 goto terminate; 438 goto terminate;
374 } 439 }
375 440
376 // now open the lockfile and place the lock 441 if (!foreground) {
377 lfd = fopen(lockfile, "w"); 442 if ((res = daemonize()) < 0) {
378 if (lfd) { 443 fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n");
379 lock.l_type = F_WRLCK; 444 usbmuxd_log(LL_FATAL, "Could not daemonize!");
380 lock.l_whence = SEEK_SET;
381 lock.l_start = 0;
382 lock.l_len = 0;
383 if ((res = fcntl(fileno(lfd), F_SETLK, &lock)) < 0) {
384 usbmuxd_log(LL_FATAL, "Lockfile locking failed!");
385 goto terminate; 445 goto terminate;
386 } 446 }
387 } else { 447 }
388 usbmuxd_log(LL_FATAL, "Lockfile open failed!"); 448
389 res = -1; 449 // now open the lockfile and place the lock
450 res = lfd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
451 if(res < 0) {
452 usbmuxd_log(LL_FATAL, "Could not open lockfile");
453 goto terminate;
454 }
455 lock.l_type = F_WRLCK;
456 lock.l_whence = SEEK_SET;
457 lock.l_start = 0;
458 lock.l_len = 0;
459 if ((res = fcntl(lfd, F_SETLK, &lock)) < 0) {
460 usbmuxd_log(LL_FATAL, "Lockfile locking failed!");
461 goto terminate;
462 }
463 sprintf(pids, "%d", getpid());
464 if ((res = write(lfd, pids, strlen(pids))) != strlen(pids)) {
465 usbmuxd_log(LL_FATAL, "Could not write pidfile!");
466 if(res >= 0)
467 res = -2;
390 goto terminate; 468 goto terminate;
391 } 469 }
392 470
@@ -400,7 +478,7 @@ int main(int argc, char *argv[])
400 struct passwd *pw = getpwnam(drop_user); 478 struct passwd *pw = getpwnam(drop_user);
401 if (!pw) { 479 if (!pw) {
402 usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user); 480 usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user);
403 res = 1; 481 res = -1;
404 goto terminate; 482 goto terminate;
405 } 483 }
406 484
@@ -420,12 +498,12 @@ int main(int argc, char *argv[])
420 // security check 498 // security check
421 if (setuid(0) != -1) { 499 if (setuid(0) != -1) {
422 usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); 500 usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
423 res = 1; 501 res = -1;
424 goto terminate; 502 goto terminate;
425 } 503 }
426 if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) { 504 if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) {
427 usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); 505 usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
428 res = 1; 506 res = -1;
429 goto terminate; 507 goto terminate;
430 } 508 }
431 usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user); 509 usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user);
@@ -441,13 +519,9 @@ int main(int argc, char *argv[])
441 519
442 usbmuxd_log(LL_NOTICE, "Initialization complete"); 520 usbmuxd_log(LL_NOTICE, "Initialization complete");
443 521
444 if (!foreground) { 522 if (report_to_parent)
445 if ((res = daemonize()) < 0) { 523 if((res = notify_parent(0)) < 0)
446 fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n");
447 usbmuxd_log(LL_FATAL, "Could not daemonize!");
448 goto terminate; 524 goto terminate;
449 }
450 }
451 525
452 res = main_loop(listenfd); 526 res = main_loop(listenfd);
453 if(res < 0) 527 if(res < 0)
@@ -463,7 +537,12 @@ int main(int argc, char *argv[])
463terminate: 537terminate:
464 log_disable_syslog(); 538 log_disable_syslog();
465 539
466 if(res < 0) 540 if (res < 0)
467 return -res; 541 res = -res;
468 return 0; 542 else
543 res = 0;
544 if (report_to_parent)
545 notify_parent(res);
546
547 return res;
469} 548}