detach

Git mirror of http://inglorion.net/software/detach/
git clone git://git.finwo.net/app/detach
Log | Files | Refs | LICENSE

commit 136eb3c3028cf30170d63bfeaafd6cd1a7306715
parent edab84be7ab59c0673f7c4892228a36c1096d1dc
Author: finwo <finwo@pm.me>
Date:   Fri,  5 Nov 2021 14:13:34 +0100

0.2.3

Diffstat:
Acontrib/zsh-completer/_detach | 9+++++++++
Mdetach.1 | 25++++++++++++++++++++++---
Mdetach.c | 68+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 92 insertions(+), 10 deletions(-)

diff --git a/contrib/zsh-completer/_detach b/contrib/zsh-completer/_detach @@ -0,0 +1,9 @@ +#compdef detach + +_arguments \ + '-e[connect file to standard error of command]:errfile:_files' \ + '-f[run in the foreground]' \ + '-i[connect file to standard input of command]:infile:_files' \ + '-o[connect file to standard output of command]:outfile:_files' \ + '(-):command name: _command_names -e' \ + '*::arguments: _normal' diff --git a/detach.1 b/detach.1 @@ -1,17 +1,36 @@ -.TH detach 1 +.TH detach 1 "" "" "User Commands" .SH NAME .B detach \- run a command after detaching from the terminal .SH SYNOPSIS -\fBdetach\fR \fIcommand\fR [\fIargs\fR] +\fBdetach\fR [\fIoptions\fR] [\fB--\fR] \fIcommand\fR [\fIargs\fR] Forks a new process, detaches is from the terminal, and executes command with the specified arguments. +.SH OPTIONS +\fBdetach\fR recognizes a couple of options, which are discussed below. +The special option \fB--\fR is used to signal that the rest of the arguments +are the \fIcommand\fR and \fIargs\fR to be passed to it. +.TP +\fB-e\fR \fIfile\fR +Connect \fIfile\fR to the standard error of the command. +.TP +\fB-f\fR +Run in the foreground (do not fork). +.TP +\fB-i\fR \fIfile\fR +Connect \fIfile\fR to the standard input of the command. +.TP +\fB-o\fR \fIfile\fR +Connect \fIfile\fR to the standard output of the command. +.TP +\fB-p\fR \fIfile\fR +Write the pid of the detached process to \fIfile\fR. .SH EXAMPLE .B detach xterm Start an xterm that will not be closed when the current shell exits. .SH AUTHOR .B detach -was written by Robbert Haarman. See http://inglorion.net/ for contact +was written by Robbert Haarman. See \fIhttp://inglorion.net/\fR for contact information. diff --git a/detach.c b/detach.c @@ -1,16 +1,70 @@ #include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> #include <unistd.h> +#include <fcntl.h> +#include <string.h> + +#ifndef NULL +#define NULL ((void*) 0) +#endif + +static void replacefd(int fd, const char *filename, int flags, int mode) { + int n; + n = open(filename, flags, mode); + if(n < 0) { + perror(filename); + exit(1); + } else { + dup2(n, fd); + close(n); + } +} int main(int argc, char **argv) { - int j; + int do_fork = 1, command_start, i; + char *infile = NULL, *outfile = NULL, *errfile = NULL, *pidfile = NULL; + FILE *pidfh; + + /* Parse command line */ + for(i = 1; i < argc; i++) { + if(!strcmp(argv[i], "-e")) errfile = argv[++i]; + else if(!strcmp(argv[i], "-f")) do_fork = 0; + else if(!strcmp(argv[i], "-i")) infile = argv[++i]; + else if(!strcmp(argv[i], "-o")) outfile = argv[++i]; + else if(!strcmp(argv[i], "-p")) pidfile = argv[++i]; + else if(!strcmp(argv[i], "--")) { + i++; + break; + } else if(argv[i][0] == '-') { + fprintf(stderr, "Invalid option: %s\n", argv[i]); + exit(0x80); + } else break; + } + command_start = i; - j = 1; - if(fork()) return 0; - close(0); - close(1); - close(2); + if(do_fork && fork()) return 0; + + if(pidfile) { + pidfh = fopen(pidfile, "w"); + if(!pidfh) { + perror(pidfile); + exit(1); + } + fprintf(pidfh, "%d\n", getpid()); + fclose(pidfh); + } + + if(infile) replacefd(0, infile, O_RDONLY, 0666); + else close(0); + if(outfile) replacefd(1, outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + else close(1); + if(errfile) replacefd(2, errfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + else close(2); setsid(); - execvp(argv[j], &argv[j]); + execvp(argv[command_start], &argv[command_start]); + + perror(argv[command_start]); return -1; }