1 /* setsid.c - Run program in a new session ID.
2  *
3  * Copyright 2006 Rob Landley <rob@landley.net>
4 
5 USE_SETSID(NEWTOY(setsid, "^<1wcd[!dc]", TOYFLAG_USR|TOYFLAG_BIN))
6 
7 config SETSID
8   bool "setsid"
9   default y
10   help
11     usage: setsid [-cdw] command [args...]
12 
13     Run process in a new session.
14 
15     -d	Detach from tty
16     -c	Control tty (become foreground process & receive keyboard signals)
17     -w	Wait for child (and exit with its status)
18 */
19 
20 #define FOR_setsid
21 #include "toys.h"
22 
setsid_main(void)23 void setsid_main(void)
24 {
25   int i;
26 
27   // setsid() fails if we're already session leader, ala "exec setsid" from sh.
28   // Second call can't fail, so loop won't continue endlessly.
29   while (setsid()<0) {
30     pid_t pid;
31 
32     // This must be before vfork() or tcsetpgrp() will hang waiting for parent.
33     setpgid(0, 0);
34 
35     pid = XVFORK();
36     if (pid) {
37       i = 0;
38       if (FLAG(w)) {
39         i = 127;
40         if (pid>0) i = xwaitpid(pid);
41       }
42       _exit(i);
43     }
44   }
45 
46   if (FLAG(c)) tcsetpgrp(0, getpid());
47   if (FLAG(d) && (i = open("/dev/tty", O_RDONLY)) != -1) {
48     ioctl(i, TIOCNOTTY);
49     close(i);
50   }
51   xexec(toys.optargs);
52 }
53