I changed the tleds code to get LED display of net traffic in X.
I added an option '-x' that would if used, open the available X displays and flask the LEDs. Bug#50842 now into its seventh year, prevents the NumLock LED from working, so under X the LEDs work as if the -n option is specified. The diff file is attached. Hugo
diff -Naur tleds-1.05beta10-orig/Makefile tleds-1.05beta10/Makefile --- tleds-1.05beta10-orig/Makefile 2006-10-10 15:20:26.000000000 -0500 +++ tleds-1.05beta10/Makefile 2007-01-08 13:27:21.000000000 -0600 @@ -22,8 +22,8 @@ # in the source code. tleds: tleds.c Makefile # Making tleds - gcc -DNO_X_SUPPORT $(GCCOPTS) -o tleds_20 tleds.c - gcc -DNO_X_SUPPORT -DKERNEL2_1 $(GCCOPTS) -o tleds_21 tleds.c + gcc $(GCCOPTS) -o tleds_20 tleds.c -I /usr/X11R6/include/ -L /usr/X11R6/lib/ -lX11 + gcc -DKERNEL2_1 $(GCCOPTS) -o tleds_21 tleds.c -I /usr/X11R6/include/ -L /usr/X11R6/lib/ -lX11 help: # make help - this. diff -Naur tleds-1.05beta10-orig/tleds.c tleds-1.05beta10/tleds.c --- tleds-1.05beta10-orig/tleds.c 2006-10-10 15:20:26.000000000 -0500 +++ tleds-1.05beta10/tleds.c 2007-01-08 13:45:26.000000000 -0600 @@ -43,6 +43,11 @@ * 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. */ +/* Modified extensively by HVW (2006-01-08) to eliminate the NO_X_SUPPORT + * and use X to flash the LEDs if the -x option is given. + * This because in kernel > 2.6.17 LEDs would not work in X without the X api-use. + * The displays are attempted to be opened and are used, all by the daemon. */ + #define VERSION "1.05beta10" #define MYNAME "tleds" @@ -56,13 +61,6 @@ #define KERNEL2_0 1 #endif -/* If you don't want X stuff. */ -#ifdef NO_X_SUPPORT -#define REMOVE_X_CODE 1 -#else -#define REMOVE_X_CODE 0 -#endif - #include <stdio.h> #include <unistd.h> #include <string.h> @@ -71,12 +69,7 @@ #include <stdlib.h> #include <time.h> #include <signal.h> -#if (! REMOVE_X_CODE) #include <X11/Xlib.h> -#else -#define LedModeOff 0 -#define LedModeOn 1 -#endif #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> @@ -97,6 +90,7 @@ #define KEYBOARDDEVICE "/dev/console" #define CURRENTTTY "/dev/tty0" #define MAXVT 64 +#define MAXDISPLAYS 2 #define NETDEVFILENAME "/proc/net/dev" #define TERMINATESTR "Program (and child) terminated.\n" #define DEEPSLEEP 10 @@ -128,6 +122,13 @@ ulong detach_vt_leds(int tty, int wantDetach); char *find_device_line(char *buffer, char *netDeviceName); inline int find_max_VT(); + +void opendisplays(); +void closedisplays(); +void changekeyboardcontrol( unsigned long, XKeyboardControl* ); +void xsync( Bool ); +Bool was_at_least_five_secs_ago(); + pid_t get_old_pid(); pid_t get_own_pid(char *fileName); int get_sleeptime(int isDefinedByUser, char *interfaceName); @@ -163,20 +164,17 @@ static char pidFileName[30] = ""; /* 30 should be enough */ static char rootPidFileName[30] = ""; -#if (! REMOVE_X_CODE) -static Display *myDisplay = NULL; - -#else -static char *myDisplay = NULL; +static Display *myDisplay[MAXDISPLAYS]; +FILE *stream; -#endif static int keyboardDevice = 0; +static long int last_time; 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; += FALSE, opt_v = FALSE, opt_V = FALSE, opt_c = FALSE, opt_n = FALSE, opt_x = FALSE; static int inled = NUMLOCKLED, outled = SCROLLLOCKLED; /* The code */ @@ -184,7 +182,7 @@ { char *interfaceName; char buffer[MAXLEN]; - ulong ledVal; +// ulong ledVal; char *tmpPointer; char **list; pid_t pid; @@ -192,6 +190,10 @@ int wasInDeepSleep; struct timeval sleeptimeval; + int i; + for (i=0; i<MAXDISPLAYS; i++) + myDisplay[i] = NULL; + interfaceName = NULL; sleeptime = 0; check_kernel_version(); /* May die here */ @@ -270,26 +272,9 @@ fprintf(stderr, "%s:%s", KEYBOARDDEVICE, TERMINATESTR); exit(1); } - } 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."); - fprintf(stderr, TERMINATESTR); - exit(1); - } -#else - 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 - } + if (opt_x) + opendisplays(); /* this will try to open any displays - no errors to stderr */ + } sleeptimeval.tv_sec = (int) ((long) sleeptime * 1000L) / 1000000L; sleeptimeval.tv_usec = (int) ((long) sleeptime * 1000L) % 1000000L; remindVTcoef = (int) ((long) REMINDVTDELAY * 1000L / (long) sleeptime); @@ -432,76 +417,68 @@ static ulong ledReminder = 0x00; ulong ledVal; -#if (! REMOVE_X_CODE) XKeyboardControl values; -#endif #ifdef DEBUG printf("led(%d, %d)\n", led, (int) mode); #endif -#if (! REMOVE_X_CODE) - if (myDisplay) { - switch (mode) { - case SET: - values.led_mode = LedModeOn; - break; - case CLEAR: - values.led_mode = LedModeOff; - break; - case TOGGLE: - values.led_mode = LedModeOn; - } + + switch (mode) { + case SET: + values.led_mode = LedModeOn; + break; + case CLEAR: + values.led_mode = LedModeOff; + break; + case TOGGLE: + values.led_mode = LedModeOn; } values.led = led; -#endif - if (myDisplay) { -#if (! REMOVE_X_CODE) - XChangeKeyboardControl(myDisplay, KBLed | KBLedMode, &values); + if (opt_x) { + changekeyboardcontrol(KBLed | KBLedMode, &values); if (doAction != DELAYED) - XSync(myDisplay, FALSE); -#endif - } else { - if (doAction != FINISH) { - if (ioctl(keyboardDevice, KDGETLED, &ledVal)) { - perror("led: tleds: KDGETLED"); - exit(1); - } - } else { - 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("led: tleds: wrong led-value"); + xsync(FALSE); + } + if (doAction != FINISH) { + if (ioctl(keyboardDevice, KDGETLED, &ledVal)) { + perror("led: tleds: KDGETLED"); exit(1); } - if (opt_c && doAction != FINISH) { - ledVal = correct_caps(ledVal); + } else { + 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("led: tleds: wrong led-value"); + exit(1); + } + if (opt_c && doAction != FINISH) { + ledVal = correct_caps(ledVal); + } + if (doAction) { /* FINISH or NOW */ + if (doAction == FINISH) + ledVal |= ledReminder; + if (ioctl(keyboardDevice, KDSETLED, (char) ledVal)) { + perror("led: tleds: KDSETLED"); + exit(1); } - 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 { + ledReminder = 0x00; + } else { /* Well, we know from report_traffic(), LED_SCR is processed later. OK, kludge. */ - ledReminder = ledVal & ~LED_SCR; - } + ledReminder = ledVal & ~LED_SCR; } } @@ -621,12 +598,10 @@ { if (opt_b && !opt_q) printf("Bye-Bye !\n"); - if (myDisplay) { -#if (! REMOVE_X_CODE) + if (opt_x) { clear_led(NUMLOCKLED); clear_led(SCROLLLOCKLED); - XCloseDisplay(myDisplay); /* X */ -#endif + closedisplays(); } detach_all_vt_leds(FALSE); /* re-attach */ if (keyboardDevice) /* EUID root - CONSOLE */ @@ -794,7 +769,7 @@ { int c; - while (EOF != (c = getopt(argc, argv, "bncd:hkqvV"))) { + while (EOF != (c = getopt(argc, argv, "bncd:hkqvxV"))) { switch (c) { case 'V': opt_V = TRUE; @@ -825,6 +800,9 @@ case 'v': opt_v = TRUE; break; + case 'x': + opt_x = TRUE; + break; default: opt_h = TRUE; /* assert(0); */ @@ -902,13 +880,15 @@ 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", + printf("Options:\n%s\n%s\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-n\tUse only ScrollLock LED.", + "\t-x\tAlso use X to flash LEDs.", "\t-q\tBe quiet.", "\t-v\tPrint version information.", "\t\t(`cat /proc/net/dev` to see your interfaces.)"); @@ -971,6 +951,112 @@ } /* End (almost) verbatim copy of kbd-0.99's getfd.c */ + + +void opendisplays(void) +{ +// XSetErrorHandler(X_error_handler); // but these don't do anything for XOpen +// XSetIOErrorHandler(X_IO_error_handler); // ... + + int std_err = dup(2); // save the original stderr + stream = freopen("/dev/null", "w", stderr); // now dump the messages + int i; + + char displayName[10]; // Try to open the displays + for (i=0; i<MAXDISPLAYS; i++) { + sprintf(displayName,":%d.0",i); + if ( !myDisplay[i] ) + if ( NULL == (myDisplay[i] = XOpenDisplay (displayName)) ) + /*printf("Fail %s\n",displayName);*/ + ; + } + + fclose(stream); // close the new stderr + dup2(std_err,2); // put it back to the orig + + struct timeval t0; + int n; + + if ( (n=gettimeofday(&t0, NULL)) !=0) { + fprintf(stderr, "t0 gettimeofday error =%d\n", n); + } + else +// printf("t0=%li%s%li%s\n", t0.tv_sec, ".", t0.tv_usec,"sec"); + last_time = t0.tv_sec; // has present second in the epoch + +} + +Bool was_at_least_five_secs_ago() +{ + + struct timeval t0; + int n; + int long this_time, this_time_m_5; + + if ( (n=gettimeofday(&t0, NULL)) !=0) { + fprintf(stderr, "t0 gettimeofday error =%d\n", n); + } + else { +// printf("t0=%li%s%li%s\n", t0.tv_sec, ".", t0.tv_usec,"sec"); + this_time = t0.tv_sec; + this_time_m_5 = (int) ((long) this_time - 5); + if ( last_time < this_time_m_5 ) { + last_time = this_time; + return TRUE; + } + else + return FALSE; + } + return FALSE; +} + +void closedisplays(void) +{ + int i; + for (i=0; i<MAXDISPLAYS; i++) + if ( myDisplay[i] ) + XCloseDisplay(myDisplay[i]); /* X */ + +} + +void changekeyboardcontrol( unsigned long values, XKeyboardControl* myxkbc) +{ +// are all displays open? + int are_open = 0; + int i; + + for (i=0; i<MAXDISPLAYS; i++) + if ( myDisplay[i] ) + are_open++; + + if ( (are_open < MAXDISPLAYS) && was_at_least_five_secs_ago() ) + opendisplays(); + + for (i=0; i<MAXDISPLAYS; i++) + if ( myDisplay[i] ) + XChangeKeyboardControl(myDisplay[i], values, myxkbc); + +} + +void xsync( Bool value ) +{ +// are all displays open? + int are_open = 0; + int i; + + for (i=0; i<MAXDISPLAYS; i++) + if ( myDisplay[i] ) + are_open++; + + if ( (are_open < MAXDISPLAYS) && was_at_least_five_secs_ago() ) + opendisplays(); + + for (i=0; i<MAXDISPLAYS; i++) + if ( myDisplay[i] ) + XSync(myDisplay[i], value); + +} + /* In v2.0.x kernels: $ cat /proc/net/dev