5 kx /*
5 kx
5 kx routines.c
5 kx
5 kx routines for *info
5 kx
5 kx Date: 1995-04-15 23:51:55
5 kx Last Change: 2001-02-24 23:43:21
5 kx
5 kx Copyright (C) 1995-2001 Sander van Malssen <svm@kozmix.cistron.nl>
5 kx
5 kx This software is released under the GNU Public Licence. See the file
5 kx `COPYING' for details. Since you're probably running Linux I'm sure
5 kx your hard disk is already infested with copies of this file, but if
5 kx not, mail me and I'll send you one.
5 kx
5 kx */
5 kx
5 kx static char *rcsid = "$Id: routines.c,v 1.24 2001/02/24 23:30:35 svm Exp svm $";
5 kx
5 kx #include <errno.h>
5 kx #include <signal.h>
5 kx #include <stdarg.h>
5 kx #include <stdio.h>
5 kx #include <stdlib.h>
5 kx #include <string.h>
5 kx #include <termios.h>
5 kx #include <termcap.h>
5 kx #include <time.h>
5 kx #include <unistd.h>
5 kx #include <sys/ioctl.h>
5 kx #include <sys/param.h> /* for HZ -- should be in <time.h> ? */
5 kx
5 kx #ifdef DEBUG
5 kx #define DMALLOC_FUNC_CHECK
5 kx #include <dmalloc.h>
5 kx #endif
5 kx
5 kx #include "procinfo.h"
5 kx
5 kx #ifndef NSIG
5 kx #ifdef _NSIG
5 kx #define NSIG _NSIG
5 kx #else
5 kx #define NSIG 32
5 kx #endif
5 kx #endif
5 kx
5 kx extern char *cd, *ce, *cl, *cm, *ho, *se, *so, *ve, *vi;
5 kx extern int co, li, sg;
5 kx extern int fs, redrawn;
5 kx extern int nr_cpus;
5 kx extern FILE *versionfp;
5 kx extern char *version;
5 kx
5 kx static struct termios oldstate, newstate;
5 kx
5 kx
5 kx /**** SIGNAL and SCREEN HANDLING ****/
5 kx
5 kx void
5 kx window_init (void)
5 kx {
5 kx struct sigaction sa;
5 kx int i;
5 kx
5 kx tcgetattr (0, &oldstate);
5 kx newstate = oldstate;
5 kx newstate.c_lflag &= ~ICANON;
5 kx newstate.c_lflag &= ~ECHO;
5 kx tcsetattr (0, TCSANOW, &newstate);
5 kx
5 kx sa.sa_flags = 0;
5 kx sigfillset (&sa.sa_mask);
5 kx
5 kx sa.sa_handler = quit;
5 kx for (i = 1; i < NSIG; i++)
5 kx sigaction (i, &sa, NULL);
5 kx
5 kx sa.sa_handler = winsz;
5 kx sigaction (SIGWINCH, &sa, NULL);
5 kx
5 kx sa.sa_handler = cont;
5 kx sigaction (SIGCONT, &sa, NULL);
5 kx
5 kx sa.sa_handler = tstp;
5 kx sigaction (SIGTSTP, &sa, NULL);
5 kx }
5 kx
5 kx void
5 kx tstp (int i)
5 kx {
5 kx tcsetattr (0, TCSANOW, &oldstate);
5 kx printf ("%s%s%s", ve, se, tgoto (cm, 0, li - 1));
5 kx fflush (stdout);
5 kx raise (SIGSTOP);
5 kx }
5 kx
5 kx void
5 kx cont (int i)
5 kx {
5 kx printf ("%s%s", cl, vi);
5 kx tcsetattr (0, TCSANOW, &newstate);
5 kx fflush (stdout);
5 kx }
5 kx
5 kx
5 kx /* This function originally stolen from top(1) (kmem-version). */
5 kx
5 kx void
5 kx winsz (int i)
5 kx {
5 kx struct winsize ws;
5 kx
5 kx co = li = 0;
5 kx if (ioctl (1, TIOCGWINSZ, &ws) >= 0) {
5 kx co = ws.ws_col;
5 kx li = ws.ws_row;
5 kx }
5 kx if (isatty(fileno(stdout))) {
5 kx if (co == 0)
5 kx co = tgetnum ("co");
5 kx if (li == 0)
5 kx li = tgetnum ("li");
5 kx }
5 kx
5 kx if (co == 0)
5 kx co = 80;
5 kx if (li == 0)
5 kx li = 24;
5 kx
5 kx li -= 2;
5 kx
5 kx version = make_version (versionfp);
5 kx
5 kx redrawn = 1;
5 kx }
5 kx
5 kx void
5 kx quit (int i)
5 kx {
5 kx tcsetattr (0, TCSANOW, &oldstate);
5 kx
5 kx if (i == 0) { /* This is an official exit. */
5 kx printf ("%s%s%s", ve, se, tgoto (cm, 0, li + 1));
5 kx exit (0);
5 kx } else {
5 kx printf ("%s%s%s", ve, se, tgoto (cm, 0, li));
5 kx printf ("[%s]\n", sys_siglist[i]);
5 kx exit (128 + i);
5 kx }
5 kx }
5 kx
5 kx void
5 kx set_echo (int i)
5 kx {
5 kx if (i) {
5 kx tcsetattr (0, TCSANOW, &oldstate);
5 kx printf ("%s", ve);
5 kx fflush (stdout);
5 kx } else {
5 kx printf ("%s", vi);
5 kx tcsetattr (0, TCSANOW, &newstate);
5 kx }
5 kx }
5 kx
5 kx /*
5 kx The next couple of functions are either directly stolen or else
5 kx adapted from the GNU termcap manual, and therefore presumed
5 kx copyrighted by the FSF.
5 kx See the file `COPYING' for licencing details.
5 kx */
5 kx
5 kx void
5 kx fatal (const char *s,...)
5 kx {
5 kx va_list l;
5 kx
5 kx va_start (l, s);
5 kx vfprintf (stderr, s, l);
5 kx va_end (l);
5 kx
5 kx exit (EXIT_FAILURE);
5 kx }
5 kx
5 kx void *
5 kx my_xcalloc (size_t n, size_t s)
5 kx {
5 kx void *p;
5 kx
5 kx p = calloc (n, s);
5 kx if (p == 0)
5 kx fatal ("my_xmalloc: memory exhausted\n");
5 kx return p;
5 kx }
5 kx
5 kx #ifdef __GNUC__
5 kx #define term_buffer 0
5 kx #else
5 kx static char term_buffer[2048];
5 kx #endif
5 kx
5 kx void
5 kx init_terminal_data (void)
5 kx {
5 kx char *termtype;
5 kx int success;
5 kx
5 kx if (!(termtype = getenv ("TERM")))
5 kx fatal ("Please specify a terminal type.\n");
5 kx
5 kx success = tgetent (term_buffer, termtype);
5 kx if (success < 0)
5 kx fatal ("Could not access the termcap data base.\n");
5 kx if (success == 0)
5 kx fatal ("Terminal type `%s' is not defined.\n", termtype);
5 kx }
5 kx
5 kx char *
5 kx my_tgets (char *te)
5 kx {
5 kx #ifdef __GNUC__
5 kx #define BUFFADDR 0
5 kx #else
5 kx /* Here we assume that an explicit term_buffer was provided to tgetent. */
5 kx char *buffer = (char *) malloc (strlen (term_buffer));
5 kx #define BUFFADDR &buffer
5 kx #endif
5 kx char *temp;
5 kx
5 kx /* Extract information we will use. */
5 kx if ((temp = tgetstr (te, BUFFADDR)) != NULL)
5 kx return temp;
5 kx else
5 kx return "";
5 kx }
5 kx
5 kx /**** END OF FSF STUFF ****/
5 kx
5 kx /**** MISCELLANEOUS ****/
5 kx
5 kx char *
5 kx make_version (FILE * versionfp)
5 kx {
5 kx char line[1024], myname[65];
5 kx static char wheee[1024];
5 kx char *p = line, *here, *there;
5 kx size_t len;
5 kx int ret; /* for gdb */
5 kx
5 kx /* These are the bits of /proc/version */
5 kx char ver[64], host[1024], gcc[1024], date[1024], cpus[16];
5 kx char compno[64];
5 kx
5 kx sprintf (cpus, "%dCPU", nr_cpus);
5 kx
5 kx gethostname (myname, 65);
5 kx if (strchr(myname, '.') == NULL) {
5 kx len = strlen(myname);
5 kx if (len - 2 < 65) { /* otherwise don't bother */
5 kx myname[len] = '.';
5 kx getdomainname(&myname[len+1], 65-2-len);
5 kx }
5 kx }
5 kx
5 kx fseek (versionfp, 0L, SEEK_SET);
5 kx fgets (line, sizeof (line), versionfp);
5 kx
5 kx ret = sscanf (line, "Linux version %s (%[^)]) (gcc %[^)]) #%s %[^\n]",
5 kx ver, host, gcc, compno, date);
5 kx
5 kx if (ret != 5) /* Damn egcs uses nested ()'s... */
5 kx ret = sscanf (line, "Linux version %s (%[^)]) (gcc %[^(] (%*[^)])) #%s %[^\n]",
5 kx ver, host, gcc, compno, date);
5 kx
5 kx if (ret == 3) { /* At least we've got ver & host right... */
5 kx strcpy (gcc, "[can't parse]");
5 kx strcpy (compno, "???");
5 kx date[0] = 0;
5 kx }
5 kx
5 kx /* BTW, from here we're free to re-use line[]. */
5 kx
5 kx here = strdup (myname);
5 kx there = strdup (host);
5 kx
5 kx /*
5 kx gcc[] may now be of the form
5 kx "version 2.7.2"
5 kx for regular gcc releases or
5 kx "driver version 2.7.2p snapshot 970207 executing gcc version 2.7.2p"
5 kx for snapshots. Or worse.
5 kx */
5 kx
5 kx strcpy (line, gcc);
5 kx
5 kx if (strncmp (line, "version egcs", 12) == 0 || /* This is egcs */
5 kx (strncmp (line, "version pgcc", 12) == 0)) /* This is pgcc */
5 kx ret = sscanf (line, "version %s", gcc);
5 kx else if (line[0] == 'v') /* This is "version 2.7.2" */
5 kx strcpy (gcc, &line[8]);
5 kx else if (line[0] == 'd') { /* This is "driver version 2.7.2p" */
5 kx char dee[64], dum[64];
5 kx
5 kx ret = sscanf (line, "driver version %s snapshot %s", dee, dum);
5 kx if (ret == 2)
5 kx sprintf (gcc, "%s-%s", dee, dum);
5 kx else
5 kx strcpy (gcc, "unknown"); /* This is "Or worse." */
5 kx }
5 kx
5 kx /* First, let's see what happens if we put everything in. */
5 kx sprintf (wheee, "Linux %s (%s) (gcc %s) #%s %s %s [%s]",
5 kx ver, host, gcc, compno, date, cpus, myname);
5 kx
5 kx /* Too long: truncate this system's name. */
5 kx if ((len = strlen (wheee)) > (size_t) co) {
5 kx for (p = myname; *p; p++)
5 kx if (*p == '.') {
5 kx *p = '\0';
5 kx break;
5 kx }
5 kx sprintf (wheee, "Linux %s (%s) (gcc %s) #%s %s %s [%s]",
5 kx ver, host, gcc, compno, date, cpus, myname);
5 kx }
5 kx
5 kx /* Too long: truncate compiling system's name. */
5 kx if ((len = strlen (wheee)) > (size_t) co) {
5 kx for (p = host; *p; p++)
5 kx if (*p == '.') {
5 kx *p = '\0';
5 kx break;
5 kx }
5 kx sprintf (wheee, "Linux %s (%s) (gcc %s) #%s %s %s [%s]",
5 kx ver, host, gcc, compno, date, cpus, myname);
5 kx }
5 kx
5 kx /* Restore hostnames, try again without date. */
5 kx strcpy (myname, here);
5 kx free (here);
5 kx strcpy (host, there);
5 kx free (there);
5 kx
5 kx /* Too long: try without date. */
5 kx if ((len = strlen (wheee)) > (size_t) co)
5 kx sprintf (wheee, "Linux %s (%s) (gcc %s) #%s %s [%s]",
5 kx ver, host, gcc, compno, cpus, myname);
5 kx
5 kx /* Too long: truncate this system's name. */
5 kx if ((len = strlen (wheee)) > (size_t) co) {
5 kx for (p = myname; *p; p++)
5 kx if (*p == '.') {
5 kx *p = '\0';
5 kx break;
5 kx }
5 kx sprintf (wheee, "Linux %s (%s) (gcc %s) #%s %s [%s]",
5 kx ver, host, gcc, compno, cpus, myname);
5 kx }
5 kx
5 kx /* Too long: truncate compiling system's name. */
5 kx if ((len = strlen (wheee)) > (size_t) co) {
5 kx for (p = host; *p; p++)
5 kx if (*p == '.') {
5 kx *p = '\0';
5 kx break;
5 kx }
5 kx sprintf (wheee, "Linux %s (%s) (gcc %s) #%s %s [%s]",
5 kx ver, host, gcc, compno, cpus, myname);
5 kx }
5 kx
5 kx return wheee;
5 kx }
5 kx
5 kx FILE *
5 kx myfopen (char *name)
5 kx {
5 kx FILE *fp;
5 kx
5 kx if ((fp = fopen (name, "r")) == NULL) {
5 kx fprintf (stdout, "can't open file %s: %s\n", name, strerror (errno));
5 kx exit (1);
5 kx }
5 kx return fp;
5 kx }
5 kx
5 kx /* Note: we're using a static char array, so use this only once per printf. */
5 kx char *
5 kx hms (unsigned long t)
5 kx {
5 kx unsigned int d, h, m, s;
5 kx static char buf[22];
5 kx
5 kx t = t * 100. / HZ;
5 kx d = (int) (t / 8640000);
5 kx t = t - (long) (d * 8640000);
5 kx h = (int) (t / 360000);
5 kx t = t - (long) (h * 360000);
5 kx m = (int) (t / 6000);
5 kx t = t - (long) (m * 6000);
5 kx s = (int) (t / 100);
5 kx t = t - (long) (s * 100);
5 kx if (d > 0)
5 kx sprintf (buf, "%3ud %2u:%02u:%02u.%02u", d, h, m, s, (int) t);
5 kx else
5 kx sprintf (buf, " %2u:%02u:%02u.%02u", h, m, s, (int) t);
5 kx return buf;
5 kx }
5 kx
5 kx /* Note: we're using a static char array, so use this only once per printf. */
5 kx char *
5 kx perc (unsigned long i, unsigned long t, int cpus)
5 kx {
5 kx unsigned int v;
5 kx static char buf[16];
5 kx
5 kx if ((signed long) i == -1 || t == 0)
5 kx return "---.-%";
5 kx
5 kx v = (unsigned int) (i < 1000000 ?
5 kx ((1000 * i + t / 2) / t) :
5 kx ((i + t / 2000) / (t / 1000)));
5 kx v /= cpus;
5 kx
5 kx /* if (v > 1000)
5 kx return "+++.+%";
5 kx else */
5 kx sprintf (buf, "%3u.%u%%", v / 10, v % 10);
5 kx return buf;
5 kx }
5 kx
5 kx
5 kx /*
5 kx Local variables:
5 kx rm-trailing-spaces: t
5 kx End:
5 kx */