aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/other/setsid.c36
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);
}