diff options
-rw-r--r-- | toys/other/setsid.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/toys/other/setsid.c b/toys/other/setsid.c index 95698260..57a926ef 100644 --- a/toys/other/setsid.c +++ b/toys/other/setsid.c @@ -2,27 +2,49 @@ * * Copyright 2006 Rob Landley <rob@landley.net> -USE_SETSID(NEWTOY(setsid, "^<1t", TOYFLAG_USR|TOYFLAG_BIN)) +USE_SETSID(NEWTOY(setsid, "^<1wcd[!dc]", TOYFLAG_USR|TOYFLAG_BIN)) config SETSID bool "setsid" default y help - usage: setsid [-t] command [args...] + usage: setsid [-cdw] command [args...] Run process in a new session. - -t Grab tty (become foreground process, receiving keyboard signals) + -d Detach from tty + -c Control tty (become foreground process & receive keyboard signals) */ +#define FOR_setsid #include "toys.h" void setsid_main(void) { - while (setsid()<0) if (XVFORK()) _exit(0); - if (toys.optflags) { - setpgid(0, 0); - tcsetpgrp(0, getpid()); + int i; + + // This must be before vfork() or tcsetpgrp() will hang waiting for parent. + setpgid(0, 0); + + // setsid() fails if we're already session leader, ala "exec setsid" from sh. + // Second call can't fail, so loop won't continue endlessly. + while (setsid()<0) { + pid_t pid = XVFORK(); + + if (pid) { + i = 0; + if (FLAG(w)) { + i = 127; + if (pid>0) i = xwaitpid(pid); + } + _exit(i); + } + } + + if (FLAG(c)) tcsetpgrp(0, getpid()); + if (FLAG(d) && (i = open("/dev/tty", O_RDONLY)) != -1) { + ioctl(i, TIOCNOTTY); + close(i); } xexec(toys.optargs); } |