File killproc-2.13.dif of Package sysvinit

--- Makefile
+++ Makefile	2008-12-05 16:27:17.683465000 +0100
@@ -54,6 +54,8 @@ UBINPRG =
 ifeq ($(DISTRO),SuSE)
    UBINPRG += usleep
    UBINPRG += fsync
+   SBINPRG += vhangup
+   SBINPRG += mkill
 endif
 
 all: $(SBINPRG) $(UBINPRG)
@@ -77,7 +79,7 @@ fsync:		fsync.c
 	$(CC) $(CFLAGS) -o $@ $^
 
 clean:
-	$(RM) *.o *~ killproc startproc checkproc pidofproc start_daemon usleep fsync
+	$(RM) *.o *~ $(SBINPRG) $(UBINPRG)
 
 install:	$(TODO)
 	if test -n "$(SBINPRG)" ; then	\
@@ -120,8 +122,12 @@ FILES	= README      \
 	  libinit.h   \
 	  usleep.c    \
 	  usleep.1    \
-	  fsync.c    \
-	  fsync.1    \
+	  fsync.c     \
+	  fsync.1     \
+	  vhangup.c   \
+	  vhangup.8   \
+	  mkill.c     \
+	  mkill.8     \
 	  killproc-$(VERSION).lsm
 
 dest:
--- mkill.8
+++ mkill.8	2008-12-05 17:16:14.313863000 +0100
@@ -0,0 +1,77 @@
+.\"
+.\" Copyright 2008 Werner Fink, 2008 SUSE LINUX Products GmbH, Germany.
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.TH MKILL 8 "Jan 31, 2008" "Version 1.16" "The SuSE boot concept"
+.UC 8
+.SH MKILL
+Mkill \- Send processes making a active mount point busy a signal
+.\"
+.SH SYNOPSIS
+.\"
+.B mkill
+[\-\fISIG\fR]
+\fI/mnt1\fR [\fI/mnt2\fR...]
+.\"
+.SH DESCRIPTION
+.B mkill
+determines all active mount points from
+.I /proc/mounts
+and compares this with the specified mount points. Then
+.B mkill
+seeks for processes making this mount points busy. For
+this search only the links found in
+.I /proc/<pid>/
+are used to avoid hangs on files provided by network
+file systems like
+.BR nfs (5).
+The default signal is
+.B SIGTERM
+for termination. If a mount point is not active, that is
+that it is not found in
+.IR /proc/mounts ,
+.B mkill
+will do exactly nothing.
+.\"
+.SH OPTIONS
+.TP
+.B \-\fI<SIG>\fP
+Signals  can be specified either by name
+.RB (e.g. " -HUP" , " -SIGHUP" )
+or by number
+.RB (e.g. " -1" ).
+.IP
+\."
+.SH EXAMPLES
+.nf
+.B mkill -TERM /var
+
+.fi
+This will terminate all processes accessing a seperate
+.I /var
+partition.
+.PP
+.nf
+.B mkill -HUP /dev/pts
+
+.fi
+All processes using a pseudo-terminal slave will
+hangup.
+\."
+.SH RETURN VALUE
+Always success which is that zero is returned.
+\."
+.SH SEE ALSO
+.BR fuser (1),
+.BR proc (5),
+.BR umount (8).
+\."
+.SH COPYRIGHT
+2008 Werner Fink,
+2008 SUSE LINUX Products GmbH, Germany.
+.SH AUTHOR
+Werner Fink <werner@suse.de>
--- mkill.c
+++ mkill.c	2009-04-29 14:20:07.016314197 +0200
@@ -0,0 +1,811 @@
+/*
+ * mkill.c	Send a signal to all processes accessing a mount point
+ *
+ * Usage:	mkill [-SIG] /mnt ...
+ *
+ * Copyright 2008 Werner Fink, 2008 SUSE LINUX Products GmbH, Germany.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author:      Werner Fink <werner@suse.de>
+ */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <dirent.h>
+#include <errno.h>
+#include <mntent.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
+# ifndef  restrict
+#  define restrict		__restrict__
+# endif
+#endif
+#define alignof(type)		((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1))
+
+typedef enum _boolean {false, true} boolean;
+typedef struct _s_mnt
+{
+    struct _s_mnt *next;	/* Pointer to next struct. */
+    struct _s_mnt *prev;	/* Pointer to previous st. */
+    size_t nlen;
+    char * name;
+    int order;			/* Order of the mount point*/
+} mntent_t;
+
+typedef struct _s_proc_
+{
+    struct _s_proc_ *next;	/* Pointer to next struct. */
+    struct _s_proc_ *prev;	/* Pointer to previous st. */
+    pid_t pid;			/* Process ID.             */
+    int order;			/* Order of the mount point*/
+} proc_t;
+
+static int maxorder = 1;	/* This has to be initial 1 */
+static mntent_t * mntent;
+static proc_t * procs;
+static char *sys_signame [NSIG+1];
+static char *sys_sigalias[NSIG+1];
+
+static void init_signames(void);
+static int signame_to_signum(const char *sig);
+static void init_mnt(int argc, char* argv[]);
+static void clear_mnt(void);
+static void add_proc(pid_t pid, int order);
+static void sort_proc(void);
+static int check(const char *restrict name);
+
+int main(int argc, char* argv[])
+{
+    const pid_t pid = getpid();
+    const pid_t sid = getsid(0);
+    const pid_t ppid = getppid();
+    proc_t * this, *ptr, * last;
+    struct dirent * dent;
+    int num, nsig = SIGTERM;
+    struct stat st;
+    boolean found;
+    DIR * proc;
+
+    num = argc;
+    while (--num) {
+	if (*(argv[num]) == '-') {
+	    char *sig = argv[num];
+	    int tmp, len = strlen(sig);
+	    sig++;
+	    if (*sig == '0') {
+		memset(argv[num], '\0', len);
+		nsig = 0;
+		break;
+	    } else if ((tmp = atoi(sig)) > 0 && tmp < NSIG) {
+		memset(argv[num], '\0', len);
+		nsig = tmp;
+		break;
+	    } else if ((tmp = signame_to_signum(sig)) > 0) {
+		memset(argv[num], '\0', len);
+		nsig = tmp;
+		break;
+	    }
+	}
+    }
+
+    for (num = 1; num < argc; num++) {
+	const size_t alen = strlen(argv[num]);
+	char * astr = argv[num];
+
+	if (alen == 0)
+	    continue;
+
+	if (*(astr+(alen-1)) == '/')
+	    *(astr+(alen-1)) = '\0';
+    }
+
+    init_mnt(argc, argv);
+
+    if ((proc = opendir("/proc")) == (DIR*)0) {
+	fprintf(stderr, "mkill: can not open /proc: %s\n", strerror(errno));
+	exit(1);
+    }
+
+    signal(SIGTERM, SIG_IGN);
+    signal(SIGTSTP, SIG_IGN);
+    signal(SIGSTOP, SIG_IGN);
+
+    while ((dent = readdir(proc)) != (struct dirent*)0) {
+	const pid_t curr = (pid_t)atol(dent->d_name);
+	char path[256] = { "/proc/" };
+	char name[PATH_MAX+1];
+	char line[BUFSIZ+1];
+	char * slash = &path[6];
+	struct dirent * dfd;
+	ssize_t len;
+	size_t flen;
+	FILE * maps;
+	DIR * fdir;
+	int order;
+
+	if (*dent->d_name == '.')
+	    continue;
+	if (*dent->d_name < '0' || *dent->d_name > '9')
+	    continue;
+
+	if (1 == curr)
+	    continue;
+
+	if (pid == curr)
+	    continue;
+
+	if (ppid == curr)
+	    continue;
+
+	if (sid == curr)
+	    continue;
+
+	found = false;
+
+	*slash = '\0';
+	strncpy(slash, dent->d_name, 246);
+	strcat(slash, "/root");
+
+	errno = 0;
+	if ((len = readlink(path, name, PATH_MAX)) < 0)
+	    continue;
+	name[len] = '\0';
+	if ((order = check(name))) {
+	    add_proc(curr, order);
+	    goto fuse;
+	}
+
+	*slash = '\0';
+	strncpy(slash, dent->d_name, 246);
+	strcat(slash, "/cwd");
+
+	errno = 0;
+	if ((len = readlink(path, name, PATH_MAX)) < 0)
+	    continue;
+	name[len] = '\0';
+	if ((order = check(name))) {
+	    add_proc(curr, order);
+	    goto fuse;
+	}
+
+	*slash = '\0';
+	strncpy(slash, dent->d_name, 246);
+	strcat(slash, "/exe");
+
+	errno = 0;
+	if ((len = readlink(path, name, PATH_MAX)) < 0)
+	    continue;
+	name[len] = '\0';
+	if (strncmp(name, "/sbin/udevd", 11) == 0)
+	    continue;
+	if ((order = check(name))) {
+	    add_proc(curr, order);
+	    goto fuse;
+	}
+
+	*slash = '\0';
+	strncpy(slash, dent->d_name, 246);
+	strcat(slash, "/maps");
+
+	if ((maps = fopen(path, "r")) == (FILE*)0)
+	    continue;
+	while (fgets(line, BUFSIZ, maps)) {
+	    if (sscanf(line, "%*s %*s %*s %*x:%*x %*d %s", name) == 1) {
+
+		if (name[0] == '\0' || name[0] == '[')
+		    continue;
+
+		if ((order = check(name))) {
+		    found = true;
+		    break;
+		}
+	    }
+	    if (found) break;
+	}
+	(void)fclose(maps);
+
+	if (found) {
+	    add_proc(curr, order);
+	    goto fuse;
+	}
+
+    fuse:
+	*(slash+strlen(dent->d_name)) = '\0';
+	strcat(slash, "/fd");
+
+	if ((fdir = opendir(path)) == (DIR*)0)
+	    continue;
+	strcat(slash, "/");
+	flen = strlen(path);
+	while ((dfd = readdir(fdir)) != (struct dirent*)0) {
+	    boolean isfuse = false;
+
+	    if (*dfd->d_name == '.')
+		continue;
+
+	    slash = &path[flen];
+	    *slash = '\0';
+	    strcat(slash, dfd->d_name);
+
+	    errno = 0;
+	    if ((len = readlink(path, name, PATH_MAX)) < 0)
+		continue;
+	    name[len] = '\0';
+
+	    if (strcmp("/dev/fuse", name) == 0)
+		isfuse = true;
+
+	    if (found) {
+		if (isfuse) {
+		    this = procs;
+		    last = (proc_t*)0;
+
+		    for (ptr = procs; this; ptr = this) {
+			last = ptr->prev;
+			this = ptr->next;
+			if (ptr->pid != curr)
+			    continue;
+			if (ptr == procs) {
+			    if (this) this->prev = (proc_t*)0;
+			    procs = this;
+			} else if (last) {
+			    if (this) this->prev = last;
+			    last->next = this;
+			}
+			free(ptr);
+		    }
+		    break;
+		}
+		continue;
+	    }
+
+	    if ((*name == '/') && (order = check(name))) {
+		if (isfuse)
+		    break;
+		found = true;
+		add_proc(curr, order);
+	    }
+	}
+	(void)closedir(fdir);
+    }
+    (void)closedir(proc);
+    clear_mnt();
+    sort_proc();
+
+    num = 0;
+    this = procs;
+    last = (proc_t*)0;
+    found = false;
+    for (ptr = procs; this; ptr = this) {
+	last = ptr->prev;
+	this = ptr->next;
+	if (nsig) {
+	    kill(ptr->pid, SIGSTOP);
+	    kill(ptr->pid, nsig);
+	    found = true;
+	} else {
+	    if (num++ > 0)
+		putc(' ', stdout);
+	    printf("%d", ptr->pid);
+	}
+    }
+    kill(-1, SIGCONT);
+
+    if (num > 0)
+	putc('\n', stdout);
+
+    if (stat("/fastboot", &st) < 0)
+	num = 2000000;
+    else
+	num = 6000000;
+
+    if (nsig == SIGTERM) while (found) {
+
+	if ((num <= 0) || !found)
+	    break;
+	usleep(10000);
+	num -= 10000;
+
+	this = procs;
+	last = (proc_t*)0;
+	found = false;
+	for (ptr = procs; this; ptr = this) {
+	    last = ptr->prev;
+	    this = ptr->next;
+
+	    if (kill (ptr->pid, 0) < 0) {
+		if (ptr == procs) {
+		    if (this) this->prev = (proc_t*)0;
+		    procs = this;
+		} else if (last) {
+		    if (this) this->prev = last;
+		    last->next = this;
+		}
+		free(ptr);
+		continue;
+	    }
+
+	    found = true;
+	}
+    }
+
+    if ((nsig == SIGTERM) && found) {
+	this = procs;
+	last = (proc_t*)0;
+	for (ptr = procs; this; ptr = this) {
+	    last = ptr->prev;
+	    this = ptr->next;
+	    kill(ptr->pid, SIGSTOP);
+	    kill(ptr->pid, SIGKILL);
+	}
+	kill(-1, SIGCONT);
+    }
+
+    return 0;
+}
+
+static void init_mnt(int argc, char* argv[])
+{
+    struct stat st;
+    struct mntent * ent;
+    FILE * mnt;
+    int order;
+
+    /* Stat /proc/version to see if /proc is mounted. */
+    if (stat("/proc/version", &st) < 0) {
+	fprintf(stderr, "mkill: /proc file system: %s\n", strerror(errno));
+	exit(1);
+    }
+
+    if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0) {
+	fprintf(stderr, "mkill: can not open /proc/mounts: %s\n", strerror(errno));
+	exit(1);
+    }
+
+    order = maxorder;
+    while ((ent = getmntent(mnt))) {
+	const size_t nlen = strlen(ent->mnt_dir);
+	mntent_t *restrict ptr;
+	boolean found = false;
+	int num;
+
+	for (num = 1; num < argc; num++) {
+	    if (*(argv[num]) == '\0')
+		continue;
+	    if ((found = (strcmp(argv[num], ent->mnt_dir) == 0)))
+		break;
+	}
+
+	if (!found)
+	    continue;
+
+	if (posix_memalign((void*)&ptr, sizeof(void*), alignof(mntent_t)+(nlen+1)) != 0) {
+	    fprintf(stderr, "mkill: %s\n", strerror(errno));
+	    exit(1);
+	}
+	ptr->order = order++;
+	ptr->name = ((char*)ptr)+alignof(mntent_t);
+
+	strcpy(ptr->name, ent->mnt_dir);
+	ptr->nlen = strlen(ptr->name);
+	if (mntent)
+	    mntent->prev = ptr;
+	ptr->next = mntent;
+	ptr->prev = (mntent_t*)0;
+	mntent = ptr;
+    }
+    endmntent(mnt);
+    maxorder = order;
+}
+
+static void clear_mnt(void)
+{
+    mntent_t *p, *n, *l;
+
+    n = mntent;
+    l = (mntent_t*)0;
+    for (p = mntent; n; p = n) {
+	l = p->prev;
+	n = p->next;
+	if (p == mntent) {
+	    if (n) n->prev = (mntent_t*)0;
+	    mntent = n;
+	} else if (l) {
+	    if (n) n->prev = l;
+	    l->next = n;
+	}
+	free(p);
+    }
+}
+
+static void add_proc(pid_t pid, int order)
+{
+    proc_t * ptr = (proc_t*)malloc(sizeof(proc_t));
+    if (ptr == (proc_t*)0) {
+	fprintf(stderr, "mkill: %s\n", strerror(errno));
+	exit(1);
+    }
+    ptr->pid = pid;
+    ptr->order = order;
+    if (procs)
+	procs->prev = ptr;
+    ptr->next = procs;
+    ptr->prev = (proc_t*)0;
+    procs = ptr;
+}
+
+static void sort_proc(void)
+{
+    proc_t * sort = (proc_t*)0;
+    int order;
+
+    for (order = maxorder; order > 0; order--) {
+	proc_t * this = procs;
+	proc_t * last = (proc_t*)0;
+	proc_t * ptr;
+
+	for (ptr = procs; this; ptr = this) {
+	    proc_t * new;
+
+	    last = ptr->prev;
+	    this = ptr->next;
+
+	    if (ptr->order != order)
+		continue;
+
+	    if (ptr == procs) {
+		    if (this) this->prev = (proc_t*)0;
+		    procs = this;
+	    } else if (last) {
+		    if (this) this->prev = last;
+		    last->next = this;
+	    }
+
+	    if ((new = (proc_t*)malloc(sizeof(proc_t))) == (proc_t*)0) {
+		fprintf(stderr, "mkill: %s\n", strerror(errno));
+		exit(1);
+	    }
+	    new->pid = ptr->pid;
+	    new->order = ptr->order;
+	    if (sort)
+		sort->prev = new;
+	    new->next = sort;
+	    new->prev = (proc_t*)0;
+	    sort = new;
+
+	    free(ptr);
+	}
+    }
+
+    procs = sort;
+}
+
+static int check(const char *restrict name)
+{
+    const size_t nlen = strlen(name);
+    mntent_t *p, *n, *l;
+
+    n = mntent;
+    l = (mntent_t*)0;
+    for (p = mntent; n; p = n) {
+	l = p->prev;
+	n = p->next;
+	if (nlen < p->nlen)
+	    continue;
+	if (strncmp(name, p->name, p->nlen) == 0) {
+	    const char end = name[p->nlen];
+	    if (end != '\0' && end != '/')
+		continue;
+	    return p->order;
+	}
+    }
+    return 0;
+}
+
+static int signame_to_signum(const char *sig)
+{
+    int n;
+
+    init_signames();
+    if (!strncasecmp(sig, "sig", 3))
+	sig += 3;
+    for (n = 1; n < NSIG+1; n++) {
+	if (sys_signame [n] && !strcasecmp(sys_signame [n], sig) )
+	    return n;
+	if (sys_sigalias[n] && !strcasecmp(sys_sigalias[n], sig) )
+	    return n;
+    }
+    return -1;
+}
+
+static void init_signames(void)
+{
+    int n;
+
+    for (n = 0; n < NSIG+1; n++) {
+	sys_signame [n] = (char *)0;
+	sys_sigalias[n] = (char *)0;
+    }
+
+    sys_signame [0] = "EXIT";
+    sys_sigalias[0] = "EXIT";
+
+/*     Signal        Value  Action     Comment */
+#ifdef SIGHUP    /*    1       A       Hangup detected on controlling terminal or */
+				    /* death of controlling process */
+    if (!sys_signame[SIGHUP])
+	sys_signame [SIGHUP]    = "HUP";
+    else
+	sys_sigalias[SIGHUP]    = "HUP";
+#endif
+#ifdef SIGINT    /*    2       A       Interrupt from keyboard */
+
+    if (!sys_signame[SIGINT])
+	sys_signame [SIGINT]    = "INT";
+    else
+	sys_sigalias[SIGINT]    = "INT";
+#endif
+#ifdef SIGQUIT   /*    3       A       Quit from keyboard */
+
+    if (!sys_signame[SIGQUIT])
+	sys_signame [SIGQUIT]   = "QUIT";
+    else
+	sys_sigalias[SIGQUIT]   = "QUIT";
+#endif
+#ifdef SIGILL    /*    4       A       Illegal Instruction */
+
+    if (!sys_signame[SIGILL])
+	sys_signame [SIGILL]    = "ILL";
+    else
+	sys_sigalias[SIGILL]    = "ILL";
+#endif
+#ifdef SIGABRT   /*    6       C       Abort signal from abort(3) */
+
+    if (!sys_signame[SIGABRT])
+	sys_signame [SIGABRT]   = "ABRT";
+    else
+	sys_sigalias[SIGABRT]   = "ABRT";
+#endif
+#ifdef SIGFPE    /*    8       C       Floating point exception */
+    if (!sys_signame[SIGFPE])
+	sys_signame [SIGFPE]    = "FPE";
+    else
+	sys_sigalias[SIGFPE]    = "FPE";
+#endif
+#ifdef SIGKILL   /*    9      AEF      Kill signal */
+
+    if (!sys_signame[SIGKILL])
+	sys_signame [SIGKILL]   = "KILL";
+    else
+	sys_sigalias[SIGKILL]   = "KILL";
+#endif
+#ifdef SIGSEGV   /*    11      C       Invalid memory reference */
+
+    if (!sys_signame[SIGSEGV])
+	sys_signame [SIGSEGV]   = "SEGV";
+    else
+	sys_sigalias[SIGSEGV]   = "SEGV";
+#endif
+#ifdef SIGPIPE   /*    13      A       Broken pipe: */
+
+    if (!sys_signame[SIGPIPE])
+	sys_signame [SIGPIPE]   = "PIPE";/* write to pipe with no readers */
+    else
+	sys_sigalias[SIGPIPE]   = "PIPE";/* write to pipe with no readers */
+#endif
+#ifdef SIGALRM   /*    14      A       Timer signal from alarm(1) */
+
+    if (!sys_signame[SIGALRM])
+	sys_signame [SIGALRM]   = "ALRM";
+    else
+	sys_sigalias[SIGALRM]   = "ALRM";
+#endif
+#ifdef SIGTERM   /*    15      A       Termination signal */
+
+    if (!sys_signame[SIGTERM])
+	sys_signame [SIGTERM]   = "TERM";
+    else
+	sys_sigalias[SIGTERM]   = "TERM";
+#endif
+#ifdef SIGUSR1   /* 30,10,16   A       User-defined signal 1 */
+
+    if (!sys_signame[SIGUSR1])
+	sys_signame [SIGUSR1]   = "USR1";
+    else
+	sys_sigalias[SIGUSR1]   = "USR1";
+#endif
+#ifdef SIGUSR2   /* 31,12,17   A       User-defined signal 2 */
+
+    if (!sys_signame[SIGUSR2])
+	sys_signame [SIGUSR2]   = "USR2";
+    else
+	sys_sigalias[SIGUSR2]   = "USR2";
+#endif
+#ifdef SIGCHLD   /* 20,17,18   B       Child stopped or terminated */
+
+    if (!sys_signame[SIGCHLD])
+	sys_signame [SIGCHLD]   = "CHLD";
+    else
+	sys_sigalias[SIGCHLD]   = "CHLD";
+#endif
+#ifdef SIGCONT   /* 19,18,25           Continue if stopped */
+
+    if (!sys_signame[SIGCONT])
+	sys_signame [SIGCONT]   = "CONT";
+    else
+	sys_sigalias[SIGCONT]   = "CONT";
+#endif
+#ifdef SIGSTOP   /* 17,19,23  DEF      Stop process */
+
+    if (!sys_signame[SIGSTOP])
+	sys_signame [SIGSTOP]   = "STOP";
+    else
+	sys_sigalias[SIGSTOP]   = "STOP";
+#endif
+#ifdef SIGTSTP   /* 18,20,24   D       Stop typed at tty */
+
+    if (!sys_signame[SIGTSTP])
+	sys_signame [SIGTSTP]   = "TSTP";
+    else
+	sys_sigalias[SIGTSTP]   = "TSTP";
+#endif
+#ifdef SIGTTIN   /* 21,21,26   D       tty input for background process */
+
+    if (!sys_signame[SIGTTIN])
+	sys_signame [SIGTTIN]   = "TTIN";
+    else
+	sys_sigalias[SIGTTIN]   = "TTIN";
+#endif
+#ifdef SIGTTOU   /* 22,22,27   D       tty output for background process */
+
+    if (!sys_signame[SIGTTOU])
+	sys_signame [SIGTTOU]   = "TTOU";
+    else
+	sys_sigalias[SIGTTOU]   = "TTOU";
+#endif
+#ifdef SIGTRAP   /*    5       CG      Trace/breakpoint trap */
+
+    if (!sys_signame[SIGTRAP])
+	sys_signame [SIGTRAP]   = "TRAP";
+    else
+	sys_sigalias[SIGTRAP]   = "TRAP";
+#endif
+#ifdef SIGIOT    /*    6       CG      IOT trap. A synonym for SIGABRT */
+
+    if (!sys_signame[SIGIOT])
+	sys_signame [SIGIOT]    = "IOT";
+    else
+	sys_sigalias[SIGIOT]    = "IOT";
+#endif
+#ifdef SIGEMT    /*  7,-,7     G */
+
+    if (!sys_signame[SIGEMT])
+	sys_signame [SIGEMT]    = "EMT";
+    else
+	sys_sigalias[SIGEMT]    = "EMT";
+#endif
+#ifdef SIGBUS    /* 10,7,10    AG      Bus error */
+
+    if (!sys_signame[SIGBUS])
+	sys_signame [SIGBUS]    = "BUS";
+    else
+	sys_sigalias[SIGBUS]    = "BUS";
+#endif
+#ifdef SIGSYS    /* 12,-,12    G       Bad argument to routine (SVID) */
+
+    if (!sys_signame[SIGSYS])
+	sys_signame [SIGSYS]    = "SYS";
+    else
+	sys_sigalias[SIGSYS]    = "SYS";
+#endif
+#ifdef SIGSTKFLT /*  -,16,-    AG      Stack fault on coprocessor */
+
+    if (!sys_signame[SIGSTKFLT])
+	sys_signame [SIGSTKFLT] = "STKFLT";
+    else
+	sys_sigalias[SIGSTKFLT] = "STKFLT";
+#endif
+#ifdef SIGURG    /* 16,23,21   BG      Urgent condition on socket (4.2 BSD) */
+
+    if (!sys_signame[SIGURG])
+	sys_signame [SIGURG]    = "URG";
+    else
+	sys_sigalias[SIGURG]    = "URG";
+#endif
+#ifdef SIGIO     /* 23,29,22   AG      I/O now possible (4.2 BSD) */
+
+    if (!sys_signame[SIGIO])
+	sys_signame [SIGIO]     = "IO";
+    else
+	sys_sigalias[SIGIO]     = "IO";
+#endif
+#ifdef SIGPOLL   /*            AG      A synonym for SIGIO (System V) */
+
+    if (!sys_signame[SIGPOLL])
+	sys_signame [SIGPOLL]   = "POLL";
+    else
+	sys_sigalias[SIGPOLL]   = "POLL";
+#endif
+#ifdef SIGCLD    /*  -,-,18    G       A synonym for SIGCHLD */
+
+    if (!sys_signame[SIGCLD])
+	sys_signame [SIGCLD]    = "CLD";
+    else
+	sys_sigalias[SIGCLD]    = "CLD";
+#endif
+#ifdef SIGXCPU   /* 24,24,30   AG      CPU time limit exceeded (4.2 BSD) */
+
+    if (!sys_signame[SIGXCPU])
+	sys_signame [SIGXCPU]   = "XCPU";
+    else
+	sys_sigalias[SIGXCPU]   = "XCPU";
+#endif
+#ifdef SIGXFSZ   /* 25,25,31   AG      File size limit exceeded (4.2 BSD) */
+
+    if (!sys_signame[SIGXFSZ])
+	sys_signame [SIGXFSZ]   = "XFSZ";
+    else
+	sys_sigalias[SIGXFSZ]   = "XFSZ";
+#endif
+#ifdef SIGVTALRM /* 26,26,28   AG      Virtual alarm clock (4.2 BSD) */
+
+    if (!sys_signame[SIGVTALRM])
+	sys_signame [SIGVTALRM] = "VTALRM";
+    else
+	sys_sigalias[SIGVTALRM] = "VTALRM";
+#endif
+#ifdef SIGPROF   /* 27,27,29   AG      Profile alarm clock */
+
+    if (!sys_signame[SIGPROF])
+	sys_signame [SIGPROF]   = "PROF";
+    else
+	sys_sigalias[SIGPROF]   = "PROF";
+#endif
+#ifdef SIGPWR    /* 29,30,19   AG      Power failure (System V) */
+
+    if (!sys_signame[SIGPWR])
+	sys_signame [SIGPWR]    = "PWR";
+    else
+	sys_sigalias[SIGPWR]    = "PWR";
+#endif
+#ifdef SIGINFO   /* 29,-,-     G       A synonym for SIGPWR */
+
+    if (!sys_signame[SIGINFO])
+	sys_signame [SIGINFO]   = "INFO";
+    else
+	sys_sigalias[SIGINFO]   = "INFO";
+#endif
+#ifdef SIGLOST   /*  -,-,-     AG      File lock lost */
+
+    if (!sys_signame[SIGLOST])
+	sys_signame [SIGLOST]   = "LOST";
+    else
+	sys_sigalias[SIGLOST]   = "LOST";
+#endif
+#ifdef SIGWINCH  /* 28,28,20   BG      Window resize signal (4.3 BSD, Sun) */
+
+    if (!sys_signame[SIGWINCH])
+	sys_signame [SIGWINCH]  = "WINCH";
+    else
+	sys_sigalias[SIGWINCH]  = "WINCH";
+#endif
+#ifdef SIGUNUSED /*  -,31,-    AG      Unused signal */
+
+    if (!sys_signame[SIGUNUSED])
+	sys_signame [SIGUNUSED] = "UNUSED";
+    else
+	sys_sigalias[SIGUNUSED] = "UNUSED";
+#endif
+}
--- vhangup.8
+++ vhangup.8	2008-12-05 16:32:40.062425000 +0100
@@ -0,0 +1,47 @@
+.\"
+.\" Copyright 2008 Werner Fink, 2008 SUSE LINUX Products GmbH, Germany.
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.TH VHANGUP 8 "Jan 31, 2008" "Version 1.16" "The SuSE boot concept"
+.UC 8
+.SH NAME
+Vhangup \- Cause a virtually hangup on the specified terminals
+.\"
+.SH SYNOPSIS
+.\"
+.B vhangup
+[\fI/dev/<terminal>\fR [\fI/dev/<terminal>\fR]]
+.\"
+.SH DESCRIPTION
+.B vhangup
+simulates a hangup on the specified terminals.  Not existing
+device files or devices will be ignored.
+\."
+.SH EXAMPLES
+.nf
+.B vhangup /dev/tty1 /dev/tty2 /dev/tty3 /dev/tty4 /dev/tty5 /dev/tty6 /dev/ttyS1
+
+.fi
+This will replace all open file descriptors in the kernel that points
+to the listed ttys by a dummy that will deny further reading/writing
+to the device. It also send the signals SIGHUP/SIGCONT to the processes
+which have file descriptors open on the listed ttys.
+\."
+.SH RETURN VALUE
+On success, zero is returned.  On error, 1 is returned.
+\."
+.SH SEE ALSO
+.BR vhangup (2),
+.BR tty (4),
+.BR ttyS (4),
+.BR pts (4).
+\."
+.SH COPYRIGHT
+2008 Werner Fink,
+2008 SUSE LINUX Products GmbH, Germany.
+.SH AUTHOR
+Werner Fink <werner@suse.de>
--- vhangup.c
+++ vhangup.c	2008-12-05 11:47:35.881479000 +0100
@@ -0,0 +1,77 @@
+/*
+ * vhangup.c    Cause a hangup on the specified terminals
+ *
+ * Usage:       vhangup /dev/tty1 ...
+ *
+ * Copyright 2008 Werner Fink, 2008 SUSE LINUX Products GmbH, Germany.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author:      Werner Fink <werner@suse.de>
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <unistd.h>
+
+int main(int argc, char* argv[])
+{
+    int ret;
+
+    switch (fork()) {
+    case -1:
+	fprintf(stderr, "vhangup: %s\n", strerror(errno));
+	return 1;
+    case 0: {
+	struct sigaction sa, sa_old;
+	int num;
+
+	setsid();
+
+	sa.sa_flags = 0;
+	sa.sa_handler = SIG_IGN;
+	sigemptyset (&sa.sa_mask);
+	sigaction (SIGHUP, &sa, &sa_old);
+
+	for (ret = num = 1; num < argc; num++) {
+	    int fd = open(argv[num], O_RDWR|O_NONBLOCK|O_NOCTTY, 0);
+	    if (fd < 0) {
+		switch (errno) {
+		case ENOENT:
+		case ENODEV:
+		case ENXIO:
+		   ret++;
+		default:
+		   break;
+		}
+		continue;
+	    }
+	    if ((ioctl (fd, TIOCSCTTY, 1) == 0) && (vhangup() == 0))
+		ret++;
+	    close(fd);
+	}
+
+	sigaction (SIGHUP, &sa_old, NULL);
+	exit(ret != num);
+    }
+    default:
+	waitpid(-1, &ret, 0);
+	break;
+    }
+
+    return (WIFEXITED(ret)) ? WEXITSTATUS(ret) : 1;
+}
openSUSE Build Service is sponsored by