tleds (1.05beta10-10.1) tleds.c

Summary

 tleds.c | 1145 +++++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 644 insertions(+), 501 deletions(-)

    
download this patch

Patch contents

--- tleds-1.05beta10.orig/tleds.c
+++ tleds-1.05beta10/tleds.c
@@ -38,6 +38,11 @@
 XkbDisable 	# Needed when EUID non root and Xfree v3.2 or v3.3
 Xleds 2 3	# This line is a must.
 */
+
+/* Modified extensively for Debian by Russ Allbery (2005-08-27) and Zephaniah
+ * E. Hull (1999-08-20, 1999-05-14) for cleaner shutdown, security fixes to
+ * the PID handling, use of daemon for backgrounding, and the -n option. */
+
 #define VERSION	"1.05beta10"
 #define MYNAME	"tleds"
 
@@ -81,6 +86,8 @@
 #include <linux/vt.h>
 #include <assert.h>
 #include <sys/utsname.h>
+/* needed by getfd and friends to support console deallocating */
+#include <errno.h>
 
 #ifndef TRUE
 #define TRUE 1
@@ -89,7 +96,7 @@
 #define MAXLEN		255
 #define KEYBOARDDEVICE	"/dev/console"
 #define CURRENTTTY	"/dev/tty0"
-#define MAXVT		12
+#define MAXVT		64
 #define NETDEVFILENAME	"/proc/net/dev"
 #define TERMINATESTR	"Program (and child) terminated.\n"
 #define DEEPSLEEP	10
@@ -99,8 +106,13 @@
 #define CAPSLOCKLED	1
 #define NUMLOCKLED	2
 #define SCROLLLOCKLED	3
-typedef enum {CLEAR = 0, SET = 1, TOGGLE = 2} LedMode;
-typedef enum {DELAYED = 0, FINISH = 1, NOW = 2} ActionMode;
+typedef enum {
+    CLEAR = 0, SET = 1, TOGGLE = 2
+} LedMode;
+typedef enum {
+    DELAYED = 0, FINISH = 1, NOW = 2
+} ActionMode;
+
 #if KERNEL2_0
 #define FIELDCOUNT 	7	/* 12 really */
 #else
@@ -108,404 +120,435 @@
 #endif
 
 /* Function prototypes */
-void		check_sanity ();
-void		check_kernel_version ();
-ulong		correct_caps (ulong ledVal);
-void		create_pid_file (pid_t pid, const char* name);
-void		detach_all_vt_leds (int wantDetach);
-ulong		detach_vt_leds (int tty, int wantDetach);
-char*		find_device_line (char* buffer, char* netDeviceName);
-inline int	find_max_VT ();
-pid_t		get_old_pid ();
-int		get_sleeptime (int isDefinedByUser, char* interfaceName);
-void		handle_my_argvs (char** interfaceName, int* sleeptime,
-			int argc, char** argv);
-inline int	is_on_X (int ttyFd);
-int		kill_old_process ();
-void		led (int what, LedMode mode, ActionMode doAction);
-void		my_exit ();
-void		my_signal_handler (int);
-inline void	my_sleep (struct timeval sleeptimeval);
-void		parent_wants_me_dead (int);
-void 		report_traffic (char** list);
-char**		split_on_blank (char* line);
-inline void	clear_led (int what) { led(what, CLEAR, NOW); }
-inline void	set_led (int what) { led(what, SET, NOW); }
-inline void	toggle_led (int what) { led(what, TOGGLE, NOW); }
-void		usage (char* name);
+void check_sanity();
+void check_kernel_version();
+ulong correct_caps(ulong ledVal);
+void create_pid_file(pid_t pid, const char *name);
+void detach_all_vt_leds(int wantDetach);
+ulong detach_vt_leds(int tty, int wantDetach);
+char *find_device_line(char *buffer, char *netDeviceName);
+inline int find_max_VT();
+pid_t get_old_pid();
+pid_t get_own_pid(char *fileName);
+int get_sleeptime(int isDefinedByUser, char *interfaceName);
+void handle_my_argvs(char **interfaceName, int *sleeptime,
+		     int argc, char **argv);
+inline int is_on_X(int ttyFd);
+int kill_old_process();
+void led(int what, LedMode mode, ActionMode doAction);
+void my_exit();
+void my_signal_handler(int);
+inline void my_sleep(struct timeval sleeptimeval);
+void parent_wants_me_dead(int);
+void report_traffic(char **list);
+char **split_on_blank(char *line);
+inline void clear_led(int what)
+{
+    led(what, CLEAR, NOW);
+}
+inline void set_led(int what)
+{
+    led(what, SET, NOW);
+}
+inline void toggle_led(int what)
+{
+    led(what, TOGGLE, NOW);
+}
+void usage(char *name);
+/* from kbd-0.99, needed to support console deallocating */
+int getfd();
 
 /* Global and static variables */
-static const char	devFileName [] = NETDEVFILENAME;
-static char		pidFileName [30] = ""; /* 30 should be enough */
-static char		rootPidFileName [30] = "";
+static const char devFileName[] = NETDEVFILENAME;
+static char pidFileName[30] = "";	/* 30 should be enough */
+static char rootPidFileName[30] = "";
+
 #if (! REMOVE_X_CODE)
-static Display 		*myDisplay = NULL;
+static Display *myDisplay = NULL;
+
 #else
-static char		*myDisplay = NULL;
+static char *myDisplay = NULL;
+
 #endif
-static int		keyboardDevice = 0;
-static char		ttyLEDs [MAXVT] = {};
-static ushort		previousActive = (ushort)(MAXVT + 1);
-static int		remindVTcoef = 0;
-static int		opt_b = FALSE, opt_d = FALSE, opt_h = FALSE,
-		opt_k = FALSE, opt_q = FALSE, opt_v = FALSE,
-		opt_V = FALSE, opt_c = FALSE;
+static int keyboardDevice = 0;
+static char ttyLEDs[MAXVT] =
+{};
+static ushort previousActive = (ushort) (MAXVT + 1);
+static int remindVTcoef = 0;
+static int opt_b = FALSE, opt_d = FALSE, opt_h = FALSE, opt_k = FALSE, opt_q
+= FALSE, opt_v = FALSE, opt_V = FALSE, opt_c = FALSE, opt_n = FALSE;
+static int inled = NUMLOCKLED, outled = SCROLLLOCKLED;
 
 /* The code */
-int	main (int argc, char* argv [])
+int main(int argc, char *argv[])
 {
-char*	interfaceName;
-char	buffer [MAXLEN];
-ulong	ledVal;	
-char*	tmpPointer;
-char**	list;
-pid_t	pid;
-int	sleeptime;
-int	wasInDeepSleep;
-struct timeval sleeptimeval;
-
-interfaceName = NULL;
-sleeptime = 0;
-check_kernel_version(); /* May die here */
-handle_my_argvs(&interfaceName, &sleeptime, argc, argv);
-check_sanity();	/* Checks and maybe changes the option flags. */
+    char *interfaceName;
+    char buffer[MAXLEN];
+    ulong ledVal;
+    char *tmpPointer;
+    char **list;
+    pid_t pid;
+    int sleeptime;
+    int wasInDeepSleep;
+    struct timeval sleeptimeval;
+
+    interfaceName = NULL;
+    sleeptime = 0;
+    check_kernel_version();	/* May die here */
+    handle_my_argvs(&interfaceName, &sleeptime, argc, argv);
+    check_sanity();		/* Checks and maybe changes the option flags. 
+				 */
 #ifdef DEBUG
-opt_b = TRUE;	/* We are debugging so don't go to the background */
+    opt_b = TRUE;		/* We are debugging so don't go to the
+				   background */
 #endif
-if (opt_v && !opt_q) {
+    if (opt_v && !opt_q) {
 	printf(
-	    "%s version %s, GNU GPL (c) 1998 Jouni.Lohikoski@iki.fi\n",
-	    MYNAME, VERSION);
+		  "%s version %s, GNU GPL (c) 1998 Jouni.Lohikoski@iki.fi\n",
+		  MYNAME, VERSION);
 	printf("<URL: http://www.iki.fi/Jouni.Lohikoski/tleds.html>\n");
-}
-strcpy(pidFileName, _PATH_TMP);
-strcpy(rootPidFileName, _PATH_VARRUN);
-strcat(pidFileName, MYNAME); /* Was argv[0]. Probs coz/if path. */
-strcat(rootPidFileName, MYNAME);
-strcat(pidFileName, ".pid");
-strcat(rootPidFileName, ".pid");
-if (opt_k) {
+    }
+    if(opt_n) inled = SCROLLLOCKLED;
+    strcpy(pidFileName, _PATH_TMP);
+    strcpy(rootPidFileName, _PATH_VARRUN);
+    strcat(pidFileName, MYNAME);	/* Was argv[0]. Probs coz/if path. */
+    strcat(rootPidFileName, MYNAME);
+    strcat(pidFileName, ".pid");
+    strcat(rootPidFileName, ".pid");
+    if (opt_k) {
 	return kill_old_process();
-}
-if (opt_h) {
+    }
+    if (opt_h) {
 	usage(argv[0]);
 	return 0;
-}
-if (! opt_q) {
+    }
+    if (!opt_q) {
 	printf("Setting keyboard LEDs based on %s %s %s %s\n",
-	    "changes of Receive/Transmit\npackets of", interfaceName,
-	    "in", devFileName);
+	       "changes of Receive/Transmit\npackets of", interfaceName,
+	       "in", devFileName);
 	printf("Delay between updates is %d milliseconds.\n",
-	    sleeptime);
-}
-if (! find_device_line(buffer, interfaceName) && !opt_q) {
+	       sleeptime);
+    }
+    if (!find_device_line(buffer, interfaceName) && !opt_q) {
 	printf(
-	    "There is currently no such interface as %s in %s.\n%s\n",
-	    interfaceName, devFileName,
-	    "Maybe later there will be. Kill me (-k) if ya want.");
-}
-
-if(! opt_b) {
-	if (-1 == (pid = fork())) {
-		perror("tleds: fork");
-		return 1;
-	}
-} else {
-	pid = getpid();
-}
-if (pid) {
+		  "There is currently no such interface as %s in %s.\n%s\n",
+		  interfaceName, devFileName,
+		  "Maybe later there will be. Kill me (-k) if ya want.");
+    }
+
+    if (!opt_b) {
+        if (-1 == daemon(0, (geteuid() != 0))) {
+            perror("tleds: daemon");
+            return 1;
+        }
+    }
+    pid = getpid();
+    if (pid) {
 	create_pid_file(pid, argv[0]);
-	if (! opt_q)
-		printf("Running in %sground. Pid: %ld\n",
-			(opt_b ? "fore" : "back"),
-			(long)pid);
-	if (! opt_b)
-		exit(0);
-}
-if (atexit(my_exit)) {
+	if (!opt_q)
+	    printf("Running in %sground. Pid: %ld\n",
+		   (opt_b ? "fore" : "back"),
+		   (long) pid);
+    }
+    if (atexit(my_exit)) {
 	perror("tleds: atexit() failed");
 	return 1;
-}
-if (! opt_b) {
+    }
+    if (!opt_b) {
 	signal(SIGUSR1, parent_wants_me_dead);
-}
-signal(SIGHUP, SIG_IGN);
-signal(SIGTERM, my_signal_handler);
-signal(SIGINT, my_signal_handler);
-signal(SIGQUIT, my_signal_handler);
-signal(SIGTSTP, my_signal_handler); 
-signal(SIGUSR2, SIG_IGN);
-signal(SIGPIPE, my_signal_handler);
-if (! geteuid()) {	/* We are running as EUID root - CONSOLE */
+    }
+    signal(SIGHUP, SIG_IGN);
+    signal(SIGTERM, my_signal_handler);
+    signal(SIGINT, my_signal_handler);
+    signal(SIGQUIT, my_signal_handler);
+    signal(SIGTSTP, my_signal_handler);
+    signal(SIGUSR2, SIG_IGN);
+    signal(SIGPIPE, my_signal_handler);
+    if (!geteuid()) {		/* We are running as EUID root - CONSOLE */
 	if (-1 == (keyboardDevice = open(KEYBOARDDEVICE, O_RDONLY))) {
-		perror("tleds");
-		fprintf(stderr, "%s:%s", KEYBOARDDEVICE, TERMINATESTR);
-		exit(1);
+	    perror("tleds");
+	    fprintf(stderr, "%s:%s", KEYBOARDDEVICE, TERMINATESTR);
+	    exit(1);
 	}
-} else {		/* EUID not root */
+    } else {			/* EUID not root */
 #if (! REMOVE_X_CODE)
-	if (! (myDisplay = XOpenDisplay(NULL))		/* X  */
-		&& ioctl(0, KDGETLED, &ledVal) ) { 	/* VT */
-		perror(
-		   "tleds: Can't open X DISPLAY on the current host.");
+	if (!(myDisplay = XOpenDisplay(NULL))	/* X  */
+	    &&ioctl(0, KDGETLED, &ledVal)) {	/* VT */
+	    perror(
+		      "tleds: Can't open X DISPLAY on the current host.");
+	    fprintf(stderr, TERMINATESTR);
+	    exit(1);
+	}
 #else
-	if (ioctl(0, KDGETLED, &ledVal) ) {
-		perror("tleds: KDGETLED");
-		fprintf(stderr,
-			"Error reading current led setting.\n%s\n",
-			"Maybe stdin is not a VT?");
-#endif
-		fprintf(stderr, TERMINATESTR);
-		exit (1);
-	}
-}
-sleeptimeval.tv_sec = (int)((long)sleeptime * 1000L) / 1000000L;
-sleeptimeval.tv_usec = (int)((long)sleeptime * 1000L) % 1000000L;
-remindVTcoef = (int)( (long)REMINDVTDELAY * 1000L / (long)sleeptime ); 
-wasInDeepSleep = TRUE;
+	if (ioctl(0, KDGETLED, &ledVal)) {
+	    perror("main: tleds: KDGETLED");
+	    fprintf(stderr,
+		    "Error reading current led setting.\n%s\n",
+		    "Maybe stdin is not a VT?");
+	    fprintf(stderr, TERMINATESTR);
+	    exit(1);
+	}
+#endif
+    }
+    sleeptimeval.tv_sec = (int) ((long) sleeptime * 1000L) / 1000000L;
+    sleeptimeval.tv_usec = (int) ((long) sleeptime * 1000L) % 1000000L;
+    remindVTcoef = (int) ((long) REMINDVTDELAY * 1000L / (long) sleeptime);
+    wasInDeepSleep = TRUE;
 
-/* The main loop */
-while (1) {
+    /* The main loop */
+    while (1) {
 	if ((tmpPointer = find_device_line(buffer, interfaceName))) {
-		if (wasInDeepSleep) {
-			wasInDeepSleep = FALSE;
-			detach_all_vt_leds(TRUE);
-		}
-		list = split_on_blank(tmpPointer);
-		report_traffic(list);
-		my_sleep(sleeptimeval);
+	    if (wasInDeepSleep) {
+		wasInDeepSleep = FALSE;
+		detach_all_vt_leds(TRUE);
+	    }
+	    list = split_on_blank(tmpPointer);
+	    report_traffic(list);
+	    my_sleep(sleeptimeval);
 	} else {
-		if (! wasInDeepSleep) {
-			wasInDeepSleep = TRUE;
-			detach_all_vt_leds(FALSE);
-			previousActive = (ushort)(MAXVT + 1);
-		}
-		sleep(DEEPSLEEP);
+	    if (!wasInDeepSleep) {
+		wasInDeepSleep = TRUE;
+		detach_all_vt_leds(FALSE);
+		previousActive = (ushort) (MAXVT + 1);
+	    }
+	    sleep(DEEPSLEEP);
 	}
-}
-return 0;	/* Yeah right, never gets this far. */
+    }
+    return 0;			/* Yeah right, never gets this far. */
 }
 
-char*	find_device_line (char* buffer, char* netDeviceName)
+char *find_device_line(char *buffer, char *netDeviceName)
 {
-static long	fileOffset = 0L; 
-register FILE*	devFile;
+    static long fileOffset = 0L;
+    register FILE *devFile;
 
-if (! (devFile = fopen(devFileName, "r")) ) {
+    if (!(devFile = fopen(devFileName, "r"))) {
 	perror(devFileName);
 	exit(1);
-}
-/* Skip two lines. (the header) */
-/* Two choices how to do this. Didn't find any differences in speed. */
+    }
+    /* Skip two lines. (the header) */
+    /* Two choices how to do this. Didn't find any differences in speed. */
 #if 0
-fgets(buffer, MAXLEN, devFile);
-fgets(buffer, MAXLEN, devFile);
+    fgets(buffer, MAXLEN, devFile);
+    fgets(buffer, MAXLEN, devFile);
 #else
-if (fileOffset) {
+    if (fileOffset) {
 	fseek(devFile, fileOffset, SEEK_SET);
-} else {
+    } else {
 	fgets(buffer, MAXLEN, devFile);
-	fileOffset += (long)strlen(buffer);
+	fileOffset += (long) strlen(buffer);
 	fgets(buffer, MAXLEN, devFile);
-	fileOffset += (long)strlen(buffer);
-}
+	fileOffset += (long) strlen(buffer);
+    }
 #endif
 
-while ( fgets(buffer, MAXLEN, devFile) ) {
-	while(isblank(*buffer))
-		buffer++;
+    while (fgets(buffer, MAXLEN, devFile)) {
+	while (isblank(*buffer))
+	    buffer++;
 	if (buffer == strstr(buffer, netDeviceName)) {
-		fclose(devFile);
-		return buffer;
+	    fclose(devFile);
+	    return buffer;
 	}
-}
-fclose(devFile);
-return NULL;
+    }
+    fclose(devFile);
+    return NULL;
 }
 
-void	my_sleep (struct timeval sleeptimeval)
+void my_sleep(struct timeval sleeptimeval)
 {
 #if 1
-select(1, NULL, NULL, NULL, &sleeptimeval);
+    select(1, NULL, NULL, NULL, &sleeptimeval);
 #else
-usleep(sleeptimeval.tv_usec);
+    usleep(sleeptimeval.tv_usec);
 #endif
 }
 
-char**	split_on_blank (char* line)
+char **split_on_blank(char *line)
 {
-/*
-Has a "bug". If tried to monitor network traffic e.g. on "dummy".
-Look at the end of this file for example /proc/net/dev listing.
-*/
+    /* 
+       Has a "bug". If tried to monitor network traffic e.g. on "dummy". Look 
+       at the end of this file for example /proc/net/dev listing. */
 
-static char* 	list [FIELDCOUNT] = {};
-register int 	i;
+    static char *list[FIELDCOUNT] =
+    {};
+    register int i;
 
-i = 0;
-goto middle;	/* speed(?) hack */
-for (; i < FIELDCOUNT; i++) {
+    i = 0;
+    goto middle;		/* speed(?) hack */
+    for (; i < FIELDCOUNT; i++) {
 	while (isblank(*line))
-		line++;
-middle:
+	    line++;
+      middle:
 	list[i] = line;
-	while (! isblank(*line) && *line != ':' && *line != '\n')
-		line++;
+	while (!isblank(*line) && *line != ':' && *line != '\n')
+	    line++;
 	*(line++) = '\0';
-}
-return list;
+    }
+    return list;
 }
 
-void	report_traffic (char** list)
+void report_traffic(char **list)
 {
-static long	formerReceived = 0L;
-static long	formerTransmitted = 0L;
-register long	received, transmitted;
+    static long formerReceived = 0L;
+    static long formerTransmitted = 0L;
+    register long received, transmitted;
 
 #if KERNEL2_0
-received = atol(list[1]);
-transmitted = atol(list[6]);
+    received = atol(list[1]);
+    transmitted = atol(list[6]);
 #else
-received = atol(list[2]);
-transmitted = atol(list[10]);	/* Kernel v2.1.119 */
+    received = atol(list[2]);
+    transmitted = atol(list[10]);	/* Kernel v2.1.119 */
 #endif
 
-if (received != formerReceived) {
-	led(NUMLOCKLED, SET, DELAYED);
-	formerReceived = received;
-} else {
-	led(NUMLOCKLED, CLEAR, DELAYED);
-}
-
-if (transmitted != formerTransmitted) {
-	led(SCROLLLOCKLED, SET, FINISH);
-	formerTransmitted = transmitted;
-} else {
-	led(SCROLLLOCKLED, CLEAR, FINISH);
-}
+    if (!opt_n) {
+        if (received != formerReceived) {
+	    led(inled, SET, DELAYED);
+	    formerReceived = received;
+        } else {
+	    led(inled, CLEAR, DELAYED);
+        }
+
+        if (transmitted != formerTransmitted) {
+	    led(outled, SET, FINISH);
+	    formerTransmitted = transmitted;
+        } else {
+	    led(outled, CLEAR, FINISH);
+        }
+    } else {
+	if (received != formerReceived || transmitted != formerTransmitted) {
+	    led(inled, SET, FINISH);
+	    formerReceived = received;
+	    formerTransmitted = transmitted;
+	} else {
+	    led(inled, CLEAR, FINISH);
+	}
+    }
 }
 
-void	led (int led, LedMode mode, ActionMode doAction)
+void led(int led, LedMode mode, ActionMode doAction)
 /* Only LED_NUM can be ActionMode DELAYED */
 {
-static ulong	ledReminder = 0x00;
-ulong		ledVal;
+    static ulong ledReminder = 0x00;
+    ulong ledVal;
+
 #if (! REMOVE_X_CODE)
-XKeyboardControl values;
+    XKeyboardControl values;
+
 #endif
 #ifdef DEBUG
-printf("led(%d, %d)\n", led, (int)mode);
+    printf("led(%d, %d)\n", led, (int) mode);
 #endif
 #if (! REMOVE_X_CODE)
-if (myDisplay) {
+    if (myDisplay) {
 	switch (mode) {
-		case SET:
-			values.led_mode = LedModeOn;
-			break;
-		case CLEAR:
-			values.led_mode = LedModeOff;
-			break;
-		case TOGGLE:
-			values.led_mode = LedModeOn;
+	case SET:
+	    values.led_mode = LedModeOn;
+	    break;
+	case CLEAR:
+	    values.led_mode = LedModeOff;
+	    break;
+	case TOGGLE:
+	    values.led_mode = LedModeOn;
 	}
-}
-values.led = led;
+    }
+    values.led = led;
 #endif
-if (myDisplay) {
+    if (myDisplay) {
 #if (! REMOVE_X_CODE)
 	XChangeKeyboardControl(myDisplay, KBLed | KBLedMode, &values);
 	if (doAction != DELAYED)
-		XSync(myDisplay, FALSE);
+	    XSync(myDisplay, FALSE);
 #endif
-} else {
-	if (doAction != FINISH) { 
-		if (ioctl(keyboardDevice, KDGETLED, &ledVal)) {
-			perror("tleds: KDGETLED");
-			exit(1);
-		}
+    } else {
+	if (doAction != FINISH) {
+	    if (ioctl(keyboardDevice, KDGETLED, &ledVal)) {
+		perror("led: tleds: KDGETLED");
+		exit(1);
+	    }
 	} else {
-		ledVal = 0L;
+	    ledVal = 0L;
 	}
 	switch (led) {
-		case SCROLLLOCKLED:
-			if (mode == SET)
-				ledVal |= LED_SCR;
-			else
-				ledVal &= ~LED_SCR;
-			break;
-		case NUMLOCKLED:
-			if (mode == SET)
-				ledVal |= LED_NUM;
-			else
-				ledVal &= ~LED_NUM;
-			break;
-		default:
-			perror("tleds: wrong led-value");
-			exit(1);
+	case SCROLLLOCKLED:
+	    if (mode == SET)
+		ledVal |= LED_SCR;
+	    else
+		ledVal &= ~LED_SCR;
+	    break;
+	case NUMLOCKLED:
+	    if (mode == SET)
+		ledVal |= LED_NUM;
+	    else
+		ledVal &= ~LED_NUM;
+	    break;
+	default:
+	    perror("led: tleds: wrong led-value");
+	    exit(1);
 	}
 	if (opt_c && doAction != FINISH) {
-		ledVal = correct_caps(ledVal);
+	    ledVal = correct_caps(ledVal);
 	}
-	if (doAction) { /* FINISH or NOW */
-		if (doAction == FINISH)
-			ledVal |= ledReminder;
-		if (ioctl(keyboardDevice, KDSETLED, (char)ledVal)) {
-			perror("tleds: KDSETLED");
-			exit(1);
-		}
-		ledReminder = 0x00;
+	if (doAction) {		/* FINISH or NOW */
+	    if (doAction == FINISH)
+		ledVal |= ledReminder;
+	    if (ioctl(keyboardDevice, KDSETLED, (char) ledVal)) {
+		perror("led: tleds: KDSETLED");
+		exit(1);
+	    }
+	    ledReminder = 0x00;
 	} else {
-		/* Well, we know from report_traffic(), LED_SCR is
-		   processed later. OK, kludge. */
-		ledReminder = ledVal & ~LED_SCR;
+	    /* Well, we know from report_traffic(), LED_SCR is processed
+	       later. OK, kludge. */
+	    ledReminder = ledVal & ~LED_SCR;
 	}
-}
+    }
 }
 
-int	is_on_X (int ttyFd)
+int is_on_X(int ttyFd)
 {
-long	mode;
+    long mode;
 
-if (ioctl(ttyFd, KDGETMODE, &mode))
-	return TRUE;	/* perror is not wanted here */
-return (mode & KD_GRAPHICS);
+    if (ioctl(ttyFd, KDGETMODE, &mode))
+	return TRUE;		/* perror is not wanted here */
+    return (mode & KD_GRAPHICS);
 }
 
-ulong	correct_caps (ulong ledVal)
+ulong correct_caps(ulong ledVal)
 {
-static int	remindVTRound = 0;
-struct vt_stat	vtStat;
-int		currentVT;
-ulong		flagVal;
+    static int remindVTRound = 0;
+    struct vt_stat vtStat;
+    int currentVT;
+    ulong flagVal;
 
-currentVT = open(CURRENTTTY, O_RDONLY); /* Blah, only for root. */
-if (-1 != currentVT) {
-	if (! ioctl(currentVT, KDGKBLED, &flagVal)
-	    && ! ioctl(currentVT, VT_GETSTATE, &vtStat)) {
-		if (previousActive == --vtStat.v_active) {
-			if (is_on_X(currentVT)) {
-				ioctl(currentVT, KDGETLED, &flagVal);
-			}
-			if (flagVal & LED_CAP)
-				ledVal |= LED_CAP;
-			else
-				ledVal &= ~LED_CAP;
-			ttyLEDs[previousActive] = (char)ledVal;
-		} else {
-			previousActive = vtStat.v_active;
-			ledVal = (ulong)ttyLEDs[previousActive];
+    currentVT = open(CURRENTTTY, O_RDONLY);	/* Blah, only for root. */
+    if (-1 != currentVT) {
+	if (!ioctl(currentVT, KDGKBLED, &flagVal)
+	    && !ioctl(currentVT, VT_GETSTATE, &vtStat)) {
+	    if (previousActive == --vtStat.v_active) {
+		if (is_on_X(currentVT)) {
+		    ioctl(currentVT, KDGETLED, &flagVal);
 		}
-	}
-	if(remindVTRound++ > remindVTcoef) {
-		remindVTRound = 0;
-		detach_vt_leds(currentVT, TRUE);
+		if (flagVal & LED_CAP)
+		    ledVal |= LED_CAP;
+		else
+		    ledVal &= ~LED_CAP;
+		ttyLEDs[previousActive] = (char) ledVal;
+	    } else {
+		previousActive = vtStat.v_active;
+		ledVal = (ulong) ttyLEDs[previousActive];
+	    }
+	}
+	if (remindVTRound++ > remindVTcoef) {
+	    remindVTRound = 0;
+	    detach_vt_leds(currentVT, TRUE);
 	}
 	close(currentVT);
-}
-return ledVal;
+    }
+    return ledVal;
 }
 
-ulong	detach_vt_leds (int tty, int wantDetach)
+ulong detach_vt_leds(int tty, int wantDetach)
 /* 
 What I really would like to do, is to deattach only num-lock and scroll-lock
 leds and leave caps-lock led attached to indicate current keyboard caps
@@ -513,320 +556,421 @@
 nothing. Someone should patch the kernel to correct this for 2.2.0?
 */
 {
-ulong	ledVal;
+    ulong ledVal;
 
-if (ioctl(tty, KDGETLED, &ledVal)) {
+    if (ioctl(tty, KDGETLED, &ledVal)) {
 	return 0;
-}
-ledVal &= ~LED_SCR;
-ledVal &= ~LED_NUM;
-if (!wantDetach && !is_on_X(tty)) {
+    }
+    ledVal &= ~LED_SCR;
+    ledVal &= ~LED_NUM;
+    if (!wantDetach && !is_on_X(tty)) {
 	ioctl(tty, KDGKBLED, &ledVal);
-	ledVal |= 0x08;	/* Reattach. */
-}
-ioctl(tty, KDSETLED, (char)ledVal);
-return ledVal;
-}
-
-void	detach_all_vt_leds (int wantDetach)
-{
-ulong	ledVal;
-int	i, maxVT, tty;
-char	ttyFileName [30];
-char	ttyFileNameTmp [30];
-
-strcpy(ttyFileName, _PATH_TTY);
-maxVT = find_max_VT();
-for (i=0; i <= maxVT; i++) {
+	ledVal |= 0x08;		/* Reattach. */
+    }
+    ioctl(tty, KDSETLED, (char) ledVal);
+    return ledVal;
+}
+
+void detach_all_vt_leds(int wantDetach)
+{
+    ulong ledVal;
+    int i, maxVT, tty, fd;
+    char ttyFileName[30];
+    char ttyFileNameTmp[30];
+
+    strcpy(ttyFileName, _PATH_TTY);
+    maxVT = find_max_VT();
+    for (i = 0; i <= maxVT; i++) {
 	if (i > 0)
-		ttyLEDs[i-1] = 0x00;
+	    ttyLEDs[i - 1] = 0x00;
 	/* No error checkings here, if we can't, we can't. */
 	sprintf(ttyFileNameTmp, "%s%d", ttyFileName, i);
 	if (-1 == (tty = open(ttyFileNameTmp, O_RDONLY))) {
-		continue;
+	    continue;
 	}
 	ledVal = detach_vt_leds(tty, wantDetach);
 	if (i > 0)
-		ttyLEDs[i-1] = (char)ledVal;
+	    ttyLEDs[i - 1] = (char) ledVal;
 	close(tty);
-}
+    }
+
+    /* Close all unused VT's: stolen from kdb-0.99, deallocvt.c */
+    fd = getfd();
+    /* don't bother checking for errors -- we really don't care */
+    /* I don't even know if this _can_ fail, for that matter */
+    if (fd != -1) 
+        ioctl(fd,VT_DISALLOCATE,0);
 }
 
-int	find_max_VT ()
+int find_max_VT()
 {
-return MAXVT;
+    return MAXVT;
 }
 
-void	parent_wants_me_dead (int x)
+void parent_wants_me_dead(int x)
 {
-exit(x);
+    exit(x);
 }
 
-void	my_signal_handler (int x)
+void my_signal_handler(int x)
 {
-exit(x);
+    exit(x);
 }
 
-void	my_exit ()
+void my_exit()
 {
-if (opt_b && ! opt_q)
+    if (opt_b && !opt_q)
 	printf("Bye-Bye !\n");
-if (myDisplay) {
+    if (myDisplay) {
 #if (! REMOVE_X_CODE)
 	clear_led(NUMLOCKLED);
 	clear_led(SCROLLLOCKLED);
 	XCloseDisplay(myDisplay);	/* X */
 #endif
-}
-detach_all_vt_leds(FALSE);		/* re-attach */
-if (keyboardDevice) 	/* EUID root - CONSOLE */
+    }
+    detach_all_vt_leds(FALSE);	/* re-attach */
+    if (keyboardDevice)		/* EUID root - CONSOLE */
 	close(keyboardDevice);
-if(getpid() == get_old_pid()) {
+    if (getpid() == get_old_pid()) {
 	unlink(pidFileName);
 	unlink(rootPidFileName);
-}
+    }
 }
 
-int	kill_old_process ()
+int kill_old_process()
 {
-pid_t	pid, pid2;
+    FILE *pidFile;
+    pid_t pid;
+    char *ownPidFileName;
+    struct stat st;
+
+    /* 
+     * We use ownPidFileName here as we don't want to
+     * kill foreign processes (or become vulnerable by 
+     * forged pidfiles) when running as root.
+     */  
+
+    if (geteuid())
+	ownPidFileName = pidFileName;
+    else
+	ownPidFileName = rootPidFileName;	/* root */
 
-if (! (pid = get_old_pid())) {
+    pidFile = fopen(ownPidFileName, "r");
+    if (!(pidFile)) {
 	if (!opt_q) {
-		fprintf(stderr,
-			"Couldn't find what to kill.\n");
-		perror(pidFileName);
+	    fprintf(stderr,
+		    "Couldn't find what to kill.\n");
+	    perror(ownPidFileName);
 	}
 	return 1;
-}
-kill(pid, SIGUSR1);
-if (!opt_q) 
-	printf("One moment...(3 secs)...\n");
-sleep(3);
-if ((pid2 = get_old_pid())) {
+    }
+    if (fstat(fileno(pidFile), &st) < 0) {
+        if (!opt_q) {
+            fprintf(stderr, "Couldn't stat %s.\n", ownPidFileName);
+            perror(ownPidFileName);
+        }
+        fclose(pidFile);
+        return 1;
+    }
+    if (st.st_uid != geteuid()) {
+        if (!opt_q) {
+            fprintf(stderr,
+                    "The running process seems to be owned by someone else\n"
+                    "  (your UID = %lu, theirs = %lu).\n",
+                    (unsigned long) geteuid(), (unsigned long) st.st_uid);
+        }
+        fclose(pidFile);
+        return 1;
+    }
+    fscanf(pidFile, "%d", (int *) &pid);
+    if (!pid) {
+        if (!opt_q)
+            fprintf(stderr, "Bad process ID in %s.\n", ownPidFileName);
+        return 1;
+    }
+    kill(pid, SIGUSR1);
+    if (!opt_q)
+	printf("One moment...(1 sec)...\n");
+    sleep(1);
+    if (kill(pid, 0) > 0) {
 	if (!opt_q)
-		fprintf(stderr,
-		"PID: %d - Hmm...not sure if I succeeded in kill.\n",
-			pid2);
+	    fprintf(stderr,
+		    "PID: %d - Hmm...not sure if I succeeded in kill.\n",
+		    pid);
 	return 1;
-}
-if (! opt_q)
+    }
+    if (!opt_q)
 	printf("Killed. (The old PID was %d)\n", pid);
-return 0;
+    return 0;
 }
 
-void	create_pid_file (pid_t pid, const char* name)
+void create_pid_file(pid_t pid, const char *name)
 {
-FILE*		pidFile;
-pid_t		oldPid;
-char		procFileName [80];
-char		*tmpPidFileName;
-char		pidString [11]; /* "length" of UINT_MAX */
-struct stat	status;
-int		isAnother;
+    FILE *pidFile;
+    pid_t oldPid;
+    char procFileName[80];
+    char *tmpPidFileName;
+    char pidString[11];		/* "length" of UINT_MAX */
+    struct stat status;
+    int isAnother;
+    int fd;
 
-if (geteuid())
+    if (geteuid())
 	tmpPidFileName = pidFileName;
-else
-	tmpPidFileName = rootPidFileName;  /* root */
-/*
-We check if there already is the *.pid file and if maybe the
-process' (child) which created it is dead, so we could try to fix.
-*/
-isAnother = FALSE;
-oldPid = (pid_t) 0;
-if (! stat(pidFileName, &status)
-    || ! stat(rootPidFileName, &status)) { 
+    else
+	tmpPidFileName = rootPidFileName;	/* root */
+    /* 
+       We check if there already is the *.pid file and if maybe the process'
+       (child) which created it is dead, so we could try to fix. */
+    isAnother = FALSE;
+    oldPid = (pid_t) 0;
+    if (!stat(pidFileName, &status)
+	|| !stat(rootPidFileName, &status)) {
 	if ((oldPid = get_old_pid())) {
-		strcpy(procFileName, "/proc/");
-		sprintf(pidString, "%ld", (long)oldPid);
-		strcat(procFileName, pidString);
-		strcat(procFileName, "/environ");			
-		if(! stat(procFileName, &status)) { /* The old proc. */
-			isAnother = TRUE;
-		} else {
+	    strcpy(procFileName, "/proc/");
+	    sprintf(pidString, "%ld", (long) oldPid);
+	    strcat(procFileName, pidString);
+	    strcat(procFileName, "/environ");
+	    if (!stat(procFileName, &status)) {		/* The old proc. */
+		isAnother = TRUE;
+	    } else {
 		/* The old process was not alive, so we try to fix. */
-			unlink(rootPidFileName);
-			unlink(pidFileName);
-			if (get_old_pid()) {
-				fprintf(stderr,
-				  "%s: Can't remove %s or %s\n%s\n",
-				  MYNAME, pidFileName,
-				  rootPidFileName,
-				  "Program terminated.");
-				  exit(1);
-			}
+		unlink(rootPidFileName);
+		unlink(pidFileName);
+		if (get_old_pid()) {
+		    fprintf(stderr,
+			    "%s: Can't remove %s or %s\n%s\n",
+			    MYNAME, pidFileName,
+			    rootPidFileName,
+			    "Program terminated.");
+		    exit(1);
 		}
+	    }
 	} else {
-		isAnother = TRUE;
-	}				
-}
+	    isAnother = TRUE;
+	}
+    }
 
-if (isAnother) {
+    if (isAnother) {
 	if (oldPid)
-		fprintf(stderr, "(The old PID %ld) ", (long)oldPid);
+	    fprintf(stderr, "(The old PID %ld) ", (long) oldPid);
 	fprintf(stderr, "%s %s runnning.\n%s %s %s\n",
 		"\nSorry, can't run. There might be another",
 		name, "If not, try: rm", pidFileName, rootPidFileName);
 	kill(pid, SIGUSR1);
 	exit(1);
-}
-	
-if( !(pidFile = fopen(tmpPidFileName, "w"))) {
+    }
+
+    fd = open(tmpPidFileName, O_WRONLY | O_CREAT | O_EXCL, 0644);
+    if (fd < 0 || !(pidFile = fdopen(fd, "w"))) {
 	perror(tmpPidFileName);
 	kill(pid, SIGUSR1);
 	exit(1);
-}
-fprintf(pidFile, "%ld\n", (long)pid);
-fclose(pidFile);
-if (chmod(tmpPidFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
+    }
+    fprintf(pidFile, "%ld\n", (long) pid);
+    fclose(pidFile);
+    if (chmod(tmpPidFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
 	perror(tmpPidFileName);
 	exit(1);
-}
-if (! geteuid()) {  /* EUID root */
-	if (symlink(tmpPidFileName, pidFileName)) {
-		perror(pidFileName);
-		exit(1);
-	}
-}
+    }
 }
 
-pid_t	get_old_pid ()
+pid_t get_old_pid()
 {
-FILE*	pidFile;
-long	returnValue;
+    FILE *pidFile;
+    long returnValue;
 
-if (! (pidFile = fopen(pidFileName, "r"))) {
-	if (! (pidFile = fopen(rootPidFileName, "r")))
-		return (pid_t)0L;
-}
-fscanf(pidFile, "%ld", &returnValue);
-fclose(pidFile);
-return (pid_t)returnValue;
+    if (!(pidFile = fopen(pidFileName, "r"))) {
+	if (!(pidFile = fopen(rootPidFileName, "r")))
+	    return (pid_t) 0L;
+    }
+    fscanf(pidFile, "%ld", &returnValue);
+    fclose(pidFile);
+    return (pid_t) returnValue;
 }
 
-void	handle_my_argvs (char** interfaceName, int* sleeptime,
-		int argc, char* argv [])
+void handle_my_argvs(char **interfaceName, int *sleeptime,
+		     int argc, char *argv[])
 {
-int	c;
+    int c;
 
-while(EOF != (c = getopt(argc, argv, "bcd:hkqvV"))) {
+    while (EOF != (c = getopt(argc, argv, "bncd:hkqvV"))) {
 	switch (c) {
-		case 'V':
-			opt_V = TRUE;
-			break;
-		case 'b':
-			opt_b = TRUE;
-			break;
-		case 'c':
-			opt_c = TRUE;
-			break;
-		case 'd':
-			opt_d = TRUE;
-			*sleeptime
-				= get_sleeptime(TRUE, NULL);
-			break;
-		case 'h':
-			opt_h = TRUE;
-			break;
-		case 'k':
-			opt_k = TRUE;
-			break;
-		case 'q':
-			opt_q = TRUE;
-			break;
-		case 'v':
-			opt_v = TRUE;
-			break;
-		default:
-			opt_h = TRUE;
-			/* assert(0); */
-	}
-}
-*interfaceName = argv[optind];
-if (! *interfaceName || ! (*interfaceName)[0]) {
-	opt_h = TRUE; /* We may also have opt_k so we won't get h. */
+	case 'V':
+	    opt_V = TRUE;
+	    break;
+	case 'b':
+	    opt_b = TRUE;
+	    break;
+	case 'n':
+	  opt_n = TRUE;
+	  break;
+	case 'c':
+	    opt_c = TRUE;
+	    break;
+	case 'd':
+	    opt_d = TRUE;
+	    *sleeptime
+		= get_sleeptime(TRUE, NULL);
+	    break;
+	case 'h':
+	    opt_h = TRUE;
+	    break;
+	case 'k':
+	    opt_k = TRUE;
+	    break;
+	case 'q':
+	    opt_q = TRUE;
+	    break;
+	case 'v':
+	    opt_v = TRUE;
+	    break;
+	default:
+	    opt_h = TRUE;
+	    /* assert(0); */
+	}
+    }
+    *interfaceName = argv[optind];
+    if (!*interfaceName || !(*interfaceName)[0]) {
+	opt_h = TRUE;		/* We may also have opt_k so we won't get h. */
 	return;
-}
-if (opt_V)
+    }
+    if (opt_V)
 	printf("Marjo Helena Salmela on %svalehtelija ja paskiainen.\n",
-		"minua kohtaan ollut "); /* Don't ask. */
-if (! *sleeptime)
+	       "minua kohtaan ollut ");		/* Don't ask. */
+    if (!*sleeptime)
 	*sleeptime = get_sleeptime(FALSE, *interfaceName);
 }
 
-void	check_sanity ()
+void check_sanity()
 {
-if (opt_c && geteuid()) {
+    if (opt_c && geteuid()) {
 	opt_c = FALSE;
-	if (! opt_q)
-		fprintf(stderr,
+	if (!opt_q)
+	    fprintf(stderr,
 		    "You have to be EUID root for -c. -c removed.\n");
-}
+    }
 }
 
-int	get_sleeptime (int isDefinedByUser, char* interfaceName)
+int get_sleeptime(int isDefinedByUser, char *interfaceName)
 {
-int	returnValue;
+    int returnValue;
 
-if (isDefinedByUser) {
+    if (isDefinedByUser) {
 	returnValue = atol(optarg);
 	if (returnValue < 0 || returnValue > 10000) {
-		opt_h = TRUE;  /* Illegal value. */
-		return 0;
+	    opt_h = TRUE;	/* Illegal value. */
+	    return 0;
 	}
 	return returnValue;
-} else {
-/* Ok, we have to figure ourselves what would be good update delay. */
+    } else {
+	/* Ok, we have to figure ourselves what would be good update delay. */
 	if (interfaceName == strstr(interfaceName, "eth"))
-		returnValue = DEFETHDELAY;
+	    returnValue = DEFETHDELAY;
 	else
-		returnValue = DEFPPPDELAY;
+	    returnValue = DEFPPPDELAY;
 	return returnValue;
-}
+    }
 }
 
-void	check_kernel_version ()
+void check_kernel_version()
 {
-struct utsname	buffer;
+    struct utsname buffer;
 
-if (-1 == uname(&buffer)) {
+    if (-1 == uname(&buffer)) {
 	perror("tleds: check_kernel_version()");
 	exit(1);
-}
+    }
 #if KERNEL2_0
-if (strncmp("2.0.", (const char*)buffer.release, 4)) {
+    if (strncmp("2.0.", (const char *) buffer.release, 4)) {
 	fprintf(stderr,
 		"%s was compiled for v2.0 kernel. Check Makefile. %s",
 		MYNAME, TERMINATESTR);
 	exit(1);
-}
+    }
 #else
-if (! strncmp("2.0.", (const char*)buffer.release, 4)) {
+    if (!strncmp("2.0.", (const char *) buffer.release, 4)) {
 	fprintf(stderr, "%s was compiled for v2.1 (2.2?) kernel. %s",
 		MYNAME, TERMINATESTR);
 	exit(1);
-}
+    }
 #endif
 }
 
-void	usage (char* name)
+void usage(char *name)
 {
-printf("Usage: %s [-bchkqv] [-d <update_delay>] <interface_name>\n",
-    name);
-printf("Example: %s -d 300 ppp0\n", name);
-printf("Options:\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-	"\t-b\tDon't go to the background.",
-	"\t-c\tFix the CapsLED in VTs. Only for EUID root.",
-	"\t-d N\tSet update delay.",
-	"\t\tN must be between 1 and 10000 (milliseconds)",
-	"\t-h\tHelp. (this)",
-	"\t-k\tKill (old) (x)tleds running.",
-	"\t-q\tBe quiet.",
-	"\t-v\tPrint version information.",
-	"\t\t(`cat /proc/net/dev` to see your interfaces.)");
+    printf("Usage: %s [-bchkqv] [-d <update_delay>] <interface_name>\n",
+	   name);
+    printf("Example: %s -d 300 ppp0\n", name);
+    printf("Options:\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+	   "\t-b\tDon't go to the background.",
+	   "\t-c\tFix the CapsLED in VTs. Only for EUID root.",
+	   "\t-d N\tSet update delay.",
+	   "\t\tN must be between 1 and 10000 (milliseconds)",
+	   "\t-h\tHelp. (this)",
+	   "\t-k\tKill (old) (x)tleds running.",
+	   "\t-q\tBe quiet.",
+	   "\t-v\tPrint version information.",
+	   "\t\t(`cat /proc/net/dev` to see your interfaces.)");
 }
 
+/* Begin (almost) verbatim copy of kbd-0.99's getfd.c */
+/*
+ * getfd.c
+ *
+ * Get an fd for use with kbd/console ioctls.
+ * We try several things because opening /dev/console will fail
+ * if someone else used X (which does a chown on /dev/console).
+ */
+
+static int
+is_a_console(int fd) {
+    char arg;
+
+    arg = 0;
+    return (ioctl(fd, KDGKBTYPE, &arg) == 0
+	    && ((arg == KB_101) || (arg == KB_84)));
+}
+
+static int
+open_a_console(char *fnam) {
+    int fd;
+
+    fd = open(fnam, O_RDONLY);
+    if (fd < 0 && errno == EACCES)
+      fd = open(fnam, O_WRONLY);
+    if (fd < 0 || ! is_a_console(fd))
+      return -1;
+    return fd;
+}
+
+int getfd() {
+    int fd;
+
+    fd = open_a_console("/dev/tty");
+    if (fd >= 0)
+      return fd;
+
+    fd = open_a_console("/dev/tty0");
+    if (fd >= 0)
+      return fd;
+
+    fd = open_a_console("/dev/console");
+    if (fd >= 0)
+      return fd;
+
+    for (fd = 0; fd < 3; fd++)
+      if (is_a_console(fd))
+	return fd;
+    
+    /* failure */
+    return -1;
+    /* fprintf(stderr,
+	    ("Couldnt get a file descriptor referring to the console\n"));
+    exit(1); */		/* total failure */
+}
+/* End (almost) verbatim copy of kbd-0.99's getfd.c */
+
 /*
 In v2.0.x kernels:
 $ cat /proc/net/dev
@@ -856,5 +1000,4 @@
 eth0: 2699632   19917    0    0    0     0          0         0  15993153 23079    0    0    0  1983    0    0
 ppp0:  391413    4588    1    0    0     0          0         0   4447 6560    0    0    0     0    0    0
 $
-*/   
-
+*/