xref: /aosp_15_r20/external/toybox/toys/other/setsid.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1 /* setsid.c - Run program in a new session ID.
2  *
3  * Copyright 2006 Rob Landley <[email protected]>
4 
5 USE_SETSID(NEWTOY(setsid, "^<1wc@d[!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 (repeat to steal)
17     -w	Wait for child (and exit with its status)
18 */
19 
20 #define FOR_setsid
21 #include "toys.h"
22 
GLOBALS(long c;)23 GLOBALS(
24   long c;
25 )
26 
27 void setsid_main(void)
28 {
29   int i;
30 
31   // setsid() fails if we're already session leader, ala "exec setsid" from sh.
32   // Second call can't fail, so loop won't continue endlessly.
33   while (setsid()<0) {
34     pid_t pid;
35 
36     // This must be before vfork() or tcsetpgrp() will hang waiting for parent.
37     setpgid(0, 0);
38 
39     pid = XVFORK();
40     if (pid) {
41       i = 0;
42       if (FLAG(w)) {
43         i = 127;
44         if (pid>0) i = xwaitpid(pid);
45       }
46       _exit(i);
47     }
48   }
49 
50   if (FLAG(c)) {
51     ioctl(0, TIOCSCTTY, TT.c>1);
52     tcsetpgrp(0, getpid());
53   } if (FLAG(d) && (i = open("/dev/tty", O_RDONLY)) != -1) {
54     ioctl(i, TIOCNOTTY);
55     close(i);
56   }
57   xexec(toys.optargs);
58 }
59