} *cpplace;
-static int slpipe[2], ptmaster;
+static int slpipe[2], ptmaster, undoslattach;
static const char *ifname;
static const char *ptyname;
sigset_t emptyset, fullset;
+static int cleantask(void) {
+ pid_t pid;
+
+ pid= fork();
+ if (!pid) return 1;
+ if (pid == (pid_t)-1)
+ perror("userv-ipif: fork for undo slattach failed - cannot clean up properly");
+ return 0;
+}
+
static void terminate(int estatus) {
int i, status;
pid_t pid;
for (i=0; i<NPIDS; i++)
if (pids.bynumber[i]) kill(pids.bynumber[i], SIGTERM);
-
+
+ if (undoslattach) {
+ if (cleantask()) {
+ execlp("slattach", "slattach", "-p", "tty", ptyname, (char*)0);
+ perror("userv-ipif: exec slattach for undo slattach failed");
+ exit(-1);
+ }
+ if (ifname && cleantask()) {
+ execlp("ifconfig", "ifconfig", ifname, "down", (char*)0);
+ perror("userv-ipif: exec ifconfig for undo ifconfig failed");
+ exit(-1);
+ }
+ }
+
for (;;) {
pid= waitpid(-1,&status,0);
if (pid == (pid_t)-1) break;
e= errno;
va_start(al,fmt);
- fputs("userv-ipif service: fatal system error",stderr);
+ fputs("userv-ipif service: fatal system error: ",stderr);
vfprintf(stderr, fmt, al);
- fprintf(stderr,"%s\n", strerror(e));
+ fprintf(stderr,": %s\n", strerror(e));
terminate(12);
}
exit(0);
}
+
+static void setsigmask(const sigset_t *ss) {
+ int r;
+
+ r= sigprocmask(SIG_SETMASK, ss, 0);
+ if (r) sysfatal("[un]block signals");
+}
+
static void setsignals(void (*handler)(int), struct sigaction *sa, int chldflags) {
const int *signalp;
int r, sig;
r= sigaction(SIGCHLD, sa, 0); if (r) sysfatal("uncatch children");
}
-static void setsigmask(const sigset_t *ss) {
- int r;
-
- r= sigprocmask(SIG_SETMASK, ss, 0);
- if (r) sysfatal("[un]block signals");
-}
-
static void infork(void) {
struct sigaction sa;
sigemptyset(&sa.sa_mask);
setsignals(SIG_DFL,&sa,0);
setsigmask(&emptyset);
+ undoslattach= 0;
}
static pid_t makesubproc(void (*entry)(void)) {
pid_t pid;
pid= fork();
- if (pids.byname.task == (pid_t)-1) sysfatal("fork for task");
- if (!pids.byname.task) { infork(); return 1; }
+ if (pid == (pid_t)-1) sysfatal("fork for task");
+ if (!pid) { infork(); return 1; }
pids.byname.task= pid;
while (pids.byname.task) sigsuspend(&emptyset);
return 0;
}
+static void mdup2(int fd1, int fd2, const char *what) {
+ int r;
+
+ for (;;) {
+ r= dup2(fd1,fd2); if (r==fd2) return;
+ if (r!=-1) fatal("dup2 in %s gave wrong answer %d instead of %d",what,r,fd2);
+ if (errno != EINTR) sysfatal("dup2 failed in %s",what);
+ }
+}
+
static void sl_entry(void) {
- if (dup2(slpipe[1],1) != 1) sysfatal("dup2 stdout in slattach child");
+ mdup2(slpipe[1],1,"slattach child");
execlp("slattach", "slattach", "-v", "-L", "-p",proto, ptyname, (char*)0);
sysfatal("cannot exec slattach");
}
static void cin_entry(void) {
- if (dup2(ptmaster,1) != 1) sysfatal("dup2 stdout in cat input child");
+ mdup2(ptmaster,1,"cat input child");
execlp("cat", "cat", (char*)0);
sysfatal("cannot exec cat input");
}
static void cout_entry(void) {
- if (dup2(ptmaster,0) != 1) sysfatal("dup2 stdin in cat output child");
+ mdup2(ptmaster,0,"cat output child");
execlp("cat", "cat", (char*)0);
sysfatal("cannot exec cat output");
}
} else {
continue;
}
+ break;
}
if (taskfail) {
- fprintf(stderr,
- "userv-ipif service: %s unexpected terminated with status code %d\n",
- taskfail, status);
+ if (WIFEXITED(status)) {
+ fprintf(stderr,
+ "userv-ipif service: %s unexpectedly exited with exit status %d\n",
+ taskfail, WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ fprintf(stderr,
+ "userv-ipif service: %s unexpectedly killed by signal %s%s\n",
+ taskfail, strsignal(WTERMSIG(status)),
+ WCOREDUMP(status) ? " (core dumped)" : "");
+ } else {
+ fprintf(stderr, "userv-ipif service: %s unexpectedly terminated"
+ " with unknown status code %d\n", taskfail, status);
+ }
}
} else {
fprintf(stderr,
r= grantpt(ptmaster); if (r) sysfatal("grab/grant pty slave");
ptyname= ptsname(ptmaster); if (!ptyname) sysfatal("get pty slave name");
r= chmod(ptyname,0600); if (r) sysfatal("chmod pty slave");
+ r= unlockpt(ptmaster); if (r) sysfatal("unlock pty");
sigfillset(&sa.sa_mask);
setsignals(sighandler,&sa,SA_NOCLDSTOP);
}
static void startslattach(void) {
+ static char ifnbuf[200];
+
FILE *piper;
- char ifnbuf[200];
int r, l, k;
r= pipe(slpipe); if (r) sysfatal("create pipe");
piper= fdopen(slpipe[0],"r"); if (!piper) sysfatal("fdopen pipe");
+ undoslattach= 1;
pids.byname.sl= makesubproc(sl_entry);
close(slpipe[1]);
}
if (task()) {
- execlp("route","route", "-host",localtxt, "netmask","255.255.255.255",
+ execlp("route","route", "add", "-host",localtxt,
"dev",ifname, (char*)0);
sysfatal("cannot exec route (for local)");
}
if (task()) {
- execlp("route","route", "-host",peertxt, "netmask","255.255.255.255",
+ execlp("route","route", "add", "-host",peertxt,
"dev",ifname, (char*)0);
sysfatal("cannot exec route (for peer)");
}
for (i=0; i<nexroutes; i++) {
if (task()) {
- execlp("route","route", "-net",exroutes[i].prefixtxt,
+ execlp("route","route", "add", "-net",exroutes[i].prefixtxt,
"netmask",exroutes[i].masktxt,
"gw",peertxt, "dev",ifname, (char*)0);
sysfatal("cannot exec route (for route)");