home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / 3b1 / volume02 / pcmgr / part03 < prev    next >
Encoding:
Internet Message Format  |  1992-07-14  |  22.3 KB

  1. Path: comp-sources-3b1
  2. From: dave@galaxia.network23.com (David H. Brierley)
  3. Subject:  v02i019:  pcmgr: replacement status and window manager, Part03/03
  4. Newsgroups: comp.sources.3b1
  5. Approved: dave@galaxia.network23.com
  6. X-Checksum-Snefru: 1ee51ee8 84395320 73273a75 e5b35095
  7.  
  8. Submitted-by: dave@galaxia.network23.com (David H. Brierley)
  9. Posting-number: Volume 2, Issue 19
  10. Archive-name: pcmgr/part03
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 3 (of 3)."
  19. # Contents:  sysinfo.c
  20. # Wrapped by dave@galaxia on Tue Jul 14 21:15:55 1992
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'sysinfo.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'sysinfo.c'\"
  24. else
  25. echo shar: Extracting \"'sysinfo.c'\" \(20171 characters\)
  26. sed "s/^X//" >'sysinfo.c' <<'END_OF_FILE'
  27. X/*
  28. X * Module: sysinfo.c
  29. X *
  30. X * Primarily based on the sysinfo program by Lenny Tropiano (see below)
  31. X * but heavily hacked for inclusion in the pcmgr program.
  32. X *
  33. X * Various enhancements implememented by Floyd L. Davidson and released
  34. X * as "sysinfo V4.4" have also been incorporated.  These include displaying
  35. X * the amount of available swap space and highlighting the values on the
  36. X * display if they exceed (or drop below) some defined threshhold.
  37. X *
  38. X * David H. Brierley (dave@galaxia.network23.com)
  39. X */
  40. X
  41. X/************************************************************************\
  42. X**                                                                      **
  43. X** Program name: sysinfo.c (System Info)                                **
  44. X** Programmer:   Lenny Tropiano            UUCP: ...icus!lenny          **
  45. X** Organization: ICUS Software Systems     (c)1988, 1989                **
  46. X** Date:         January 23, 1988                                       **
  47. X** Version 2.0:  June 27, 1988                                          **
  48. X** Version 2.1:  Februrary 19, 1989 (Revision Level 4)                  **
  49. X**                                                                      **
  50. X** Revision Level: 1  [Updated to switch to current window]             **
  51. X** Revision Level: 2  [Updated to show load average in the window]      **
  52. X** Revision Level: 3  [Updated to available main memory in the window]  **
  53. X** Revision Level: 4  [Updated by David H. Brierley to check the the    **
  54. X**                     current status of the SLK lines for existing     **
  55. X**                     information and not display the sysinfo lines    **
  56. X**                     over those SLK's if in CHGWIND #define'd, good   **
  57. X**                     for use with the UA and Telephone Manager F-key  **
  58. X**                     SLK definitions]  -- dave@galaxia.Newport.RI.US  **
  59. X**                                                                      **
  60. X**************************************************************************
  61. X**                                                                      **
  62. X** Credits:      The idea of displaying the file system information     **
  63. X**               came from Scott Hazen Mueller's  newmgr, the replace-  **
  64. X**               ment to the smgr.                                      **
  65. X**                                                                      **
  66. X**************************************************************************
  67. X**                                                                      **
  68. X** Program use:  Program is run as a info process from your .profile    **
  69. X**               This program the file system and displays the          **
  70. X**               pertinent information on the bottom of the screen      **
  71. X**               where the software labels would normally be displayed. **
  72. X**               The program also displays the uptime.                  **
  73. X**                                                                      **
  74. X**************************************************************************
  75. X** Permission is granted to distribute this program by any means as     **
  76. X** long as credit is given for my work.     I would also like to see    **
  77. X** any modifications or enhancements to this program.                   **
  78. X\************************************************************************/
  79. X
  80. X#include <stdio.h>
  81. X#include <fcntl.h>
  82. X#include <errno.h>
  83. X#include <signal.h>
  84. X#include <sys/types.h>
  85. X#include <sys/stat.h>
  86. X#include <sys/font.h>
  87. X#include <sys/window.h>
  88. X#include <sys/filsys.h>
  89. X#include <sys/param.h>
  90. X#include <sys/ipc.h>
  91. X#include <sys/shm.h>
  92. X#include <nlist.h>
  93. X#include <utmp.h>
  94. X#include <string.h>
  95. X#include <mnttab.h>
  96. X#include <sys/map.h>
  97. X#include <sys/ino.h>
  98. X#include <sys/user.h>
  99. X#include <menu.h>
  100. X#ifdef    DEBUG
  101. X#include <syslog.h>
  102. X#endif
  103. X
  104. X#ifndef ctob            /* For System V */
  105. X#include <sys/sysmacros.h>
  106. X#endif
  107. X
  108. X#include "config.h"        /* local config options */
  109. X#include "pcmgr.h"        /* prototypes for all pcmgr routines */
  110. X
  111. X#ifndef    MNTTAB
  112. X#define MNTTAB        "/etc/mnttab"
  113. X#endif
  114. X
  115. X#define N_SWAPMAP    0
  116. X#define N_NSWAP        1
  117. X#define N_FREEMEM    2
  118. X#define N_MAXMEM    3
  119. X#define N_PHYSMEM    4
  120. X
  121. Xstatic struct nlist unixsym[] = {
  122. X    {"swapmap", 0, 0, 0, 0, 0},
  123. X    {"nswap", 0, 0, 0, 0, 0},
  124. X    {"freemem", 0, 0, 0, 0, 0},
  125. X    {"maxmem", 0, 0, 0, 0, 0},
  126. X    {"physmem", 0, 0, 0, 0, 0},
  127. X    {"", 0, 0, 0, 0, 0},
  128. X    {NULL}
  129. X};
  130. X
  131. Xstatic char    *LINE_1 = "%-43.43s%-23.23s%14s";
  132. X#ifdef        SHOW_DISK_TOTALS
  133. Xstatic char    *LINE_2a = "%ld/%ld blks %s, %ld/%ld inodes %s  ";
  134. X#else
  135. Xstatic char    *LINE_2a = "%ld/%.0f%% blks %s, %ld/%.0f%% inodes %s  ";
  136. X#endif
  137. X#ifdef        SHOW_DISK_FREE
  138. Xstatic char    *LINE_2_type = "free";
  139. X#else
  140. Xstatic char    *LINE_2_type = "used";
  141. X#endif
  142. Xstatic char    *LINE_2b = "Swap: %dK  Mem: %dK";
  143. Xstatic char    *LINE_2 = "%-10.10s %45.45s %23.23s";
  144. X
  145. X#define UNIX    "/unix"
  146. X#define KMEM    "/dev/kmem"
  147. X#define    MINUTE    60L
  148. X#define    HOUR    (60L * 60L)
  149. X#define    DAY    (24L * 60L * 60L)
  150. X#define    SLEEP    60        /* Sleep time (interval between) */
  151. X#define    NICE    5        /* Niceness value         */
  152. X#define KILOBYTE 1024
  153. X#define INOPERBLOCK (512 / sizeof (struct dinode))
  154. X
  155. X#define    FILESYS    "/dev/rfp002"
  156. X#ifndef TRUE
  157. X#define TRUE    1
  158. X#endif
  159. X
  160. Xstruct user_info {
  161. X    char            u_name[10];
  162. X    int             u_flag;    /* 1 == logged in */
  163. X    int             u_msgs;    /* number of mail messages */
  164. X    time_t          u_mailtime;    /* time stamp of mail file */
  165. X    char            u_mailfile[32];    /* name of mailbox */
  166. X};
  167. X
  168. X#ifndef MAX_USERS
  169. X#define MAX_USERS    32
  170. X#endif
  171. X
  172. Xstatic int      wd;        /* window descriptor         */
  173. Xstatic int      kmem;        /* kmem file descriptor         */
  174. Xstatic struct utdata utd;    /* Window data structure        */
  175. Xstatic struct filsys fs;    /* Filesystem superblock struct */
  176. Xstatic time_t   boottime;    /* system boot time in sec      */
  177. Xstatic int      shm;
  178. Xstatic struct user_info user_info[MAX_USERS];
  179. Xstatic struct mnttab filesys[NMOUNT];    /* mounted file systems */
  180. Xstatic int      fs_index = 0;    /* index into filesys array */
  181. Xstatic int      max_fs_index = 0;
  182. Xstatic time_t   mtab_time = 0;    /* time stamp of mnttab file */
  183. X
  184. Xstruct utmp    *getutent (void);
  185. X
  186. X/************************************************************************/
  187. X
  188. Xvoid
  189. Xinit_sysinfo (void)
  190. X{
  191. X    char           *getenv ();
  192. X    struct utmp    *utent;
  193. X    int             n;
  194. X
  195. X    setutent ();
  196. X    while ((utent = getutent ()) != (struct utmp *) NULL) {
  197. X    if (utent -> ut_type == BOOT_TIME) {
  198. X        boottime = utent -> ut_time;
  199. X        break;
  200. X    }
  201. X    }
  202. X
  203. X    while ((shm = shmget (ftok ("/unix", 'a'), 12, 0)) == -1) {
  204. X    (void) sleep (5);
  205. X    }
  206. X
  207. X    /*
  208. X     * Look up addresses of variables.
  209. X     */
  210. X    if (nlist (UNIX, unixsym) < 0) {
  211. X    (void) fprintf (stderr, "%s: no namelist.\n", UNIX);
  212. X    exit (1);
  213. X    }
  214. X
  215. X    /*
  216. X     * Open kernel memory.
  217. X     */
  218. X    if ((kmem = open (KMEM, 0)) < 0) {
  219. X    perror (KMEM);
  220. X    exit (1);
  221. X    }
  222. X
  223. X    /*
  224. X     * initialize the user_info list
  225. X     */
  226. X    for (n = 0; n < MAX_USERS; ++n) {
  227. X    user_info[n].u_name[0] = '\0';
  228. X    user_info[n].u_flag = -1;
  229. X    }
  230. X
  231. X}
  232. X
  233. Xvoid
  234. Xinfo_process (void)
  235. X{
  236. X    long            memory ();
  237. X    long            free_mem, freepage;
  238. X    float           pct_disk, pct_ino;
  239. X    long            tot_blocks, tot_inodes;
  240. X    long            show_blocks, show_inodes;
  241. X    int             fs_type;
  242. X    char            mailbuffer[64], loadbuf[30];
  243. X    char            user_buf[16], up_buf[16];
  244. X    char            line2a[80], line2b[80];
  245. X    char           *lptr;
  246. X
  247. X    open_current_window ();
  248. X
  249. X    if (slktest () == 0) {
  250. X    filestatus ();
  251. X    uptime (up_buf);
  252. X
  253. X    /*
  254. X     * even tho the number of users is no longer displayed, the call to
  255. X     * count_users is needed because it fills in a global structure that
  256. X     * is used by mailcheck().
  257. X     */
  258. X    count_users (user_buf);
  259. X    mailcheck (mailbuffer);
  260. X    loadaverage (loadbuf);
  261. X
  262. X    utd.ut_num = WTXTSLK1;
  263. X    (void) sprintf (utd.ut_text, LINE_1,
  264. X            mailbuffer, loadbuf, up_buf);
  265. X    (void) ioctl (wd, WIOCSETTEXT, &utd);
  266. X
  267. X    /* compute free memory and swap space */
  268. X    free_mem = memory () / KILOBYTE;
  269. X    freepage = 4 * page ();
  270. X
  271. X    /* what kind of a file system are we using */
  272. X    fs_type = 1;
  273. X    if (fs.s_magic == FsMAGIC) {
  274. X        fs_type = fs.s_type;
  275. X    }
  276. X
  277. X    /* compute blocks used/free and percentage */
  278. X    tot_blocks = fs.s_fsize * fs_type;
  279. X#ifdef    SHOW_DISK_FREE
  280. X    show_blocks = fs.s_tfree * fs_type;
  281. X#else
  282. X    show_blocks = tot_blocks - (fs.s_tfree * fs_type);
  283. X#endif
  284. X    pct_disk = ((float) show_blocks / (float) tot_blocks) * 100.0;
  285. X
  286. X    /* compute inodes used/free and percentage */
  287. X    tot_inodes = ((fs.s_isize - 2) * fs_type) * INOPERBLOCK;
  288. X#ifdef    SHOW_DISK_FREE
  289. X    show_inodes = fs.s_tinode;
  290. X#else
  291. X    show_inodes = tot_inodes - fs.s_tinode;
  292. X#endif
  293. X    pct_ino = ((float) show_inodes / (float) tot_inodes) * 100.0;
  294. X
  295. X    /*
  296. X     * fill in the first half of the line, depending on the
  297. X     * value of the SHOW_DISK_TOTALS option.
  298. X     */
  299. X#ifdef    SHOW_DISK_TOTALS
  300. X    (void) sprintf (line2a, LINE_2a,
  301. X            show_blocks, tot_blocks, LINE_2_type,
  302. X            show_inodes, tot_inodes, LINE_2_type);
  303. X#else
  304. X    (void) sprintf (line2a, LINE_2a,
  305. X            show_blocks, pct_disk, LINE_2_type,
  306. X            show_inodes, pct_ino, LINE_2_type);
  307. X#endif
  308. X
  309. X    /*
  310. X     * Fill in the second half of the line.
  311. X     */
  312. X    (void) sprintf (line2b, LINE_2b, freepage, free_mem);
  313. X
  314. X    /*
  315. X     * The checks for minimum space  always use the free space so
  316. X     * if we are showing the space used we must reverse the sense
  317. X     * of the data
  318. X     */
  319. X#ifndef    SHOW_DISK_FREE
  320. X    pct_disk = 100.0 - pct_disk;
  321. X    pct_ino = 100.0 - pct_ino;
  322. X#endif
  323. X
  324. X    /* Check to see if any alarms are needed */
  325. X    if (pct_disk < MIN_BLK_PCT) {
  326. X        highlight (line2a, strchr (line2a, ',') - 1);
  327. X    }
  328. X    lptr = strchr (line2a, ',') + 2;
  329. X    if (pct_ino < MIN_INO_PCT) {
  330. X        highlight (lptr, line2a + strlen (line2a));
  331. X    }
  332. X    if (freepage < MIN_SWAP) {
  333. X        highlight (line2b, strchr (line2b, 'K'));
  334. X    }
  335. X    if (free_mem < MIN_FREE) {
  336. X        highlight (strchr (line2b, 'M'), line2b + strlen (line2b));
  337. X    }
  338. X
  339. X    /*
  340. X     * Display the data.
  341. X     */
  342. X    utd.ut_num = WTXTSLK2;
  343. X    (void) sprintf (utd.ut_text, LINE_2,
  344. X            filesys[fs_index].mt_filsys,
  345. X            line2a, line2b);
  346. X    (void) ioctl (wd, WIOCSETTEXT, &utd);
  347. X    }
  348. X    (void) close (wd);
  349. X
  350. X}
  351. X
  352. Xvoid
  353. Xopen_current_window (void)
  354. X{
  355. X    int             window;
  356. X    char            windev[16];
  357. X
  358. X    window = ioctl (0, WIOCGCURR, NULL);
  359. X    (void) sprintf (windev, "/dev/w%d", window);
  360. X    if ((wd = open (windev, O_RDWR | O_NDELAY)) == -1)
  361. X    wd = 0;
  362. X
  363. X}
  364. X
  365. Xvoid
  366. Xfilestatus (void)
  367. X{
  368. X    int             fd;
  369. X    static char     device[64];
  370. X    static struct stat sbuf;
  371. X
  372. X    if ((stat (MNTTAB, &sbuf) != -1) && (sbuf.st_mtime != mtab_time)) {
  373. X#ifdef    DEBUG
  374. X    (void) syslog (LOG_DEBUG, "reading mnttab: st_mtime=%d, mtab_time=%d",
  375. X               sbuf.st_mtime, mtab_time);
  376. X#endif
  377. X    read_mtab ();
  378. X    mtab_time = sbuf.st_mtime;
  379. X    }
  380. X
  381. X#ifdef    DEBUG
  382. X    (void) syslog (LOG_DEBUG, "filestatus: fs_index = %d", fs_index);
  383. X#endif
  384. X    (void) sprintf (device, "/dev/r%.10s", filesys[fs_index].mt_dev);
  385. X    if ((fd = open (device, O_RDONLY)) == -1) {
  386. X    return;
  387. X    }
  388. X
  389. X    if (lseek (fd, 512, 0) == -1) {
  390. X    (void) close (fd);
  391. X    return;
  392. X    }
  393. X
  394. X    if (read (fd, (char *) &fs, sizeof (struct filsys)) == -1) {
  395. X    (void) close (fd);
  396. X    return;
  397. X    }
  398. X
  399. X    (void) close (fd);
  400. X
  401. X}
  402. X
  403. Xvoid
  404. Xcycle_fs (void)
  405. X{
  406. X
  407. X    if (++fs_index > max_fs_index) {
  408. X    fs_index = 0;
  409. X    }
  410. X
  411. X}
  412. X
  413. Xvoid
  414. Xread_mtab (void)
  415. X{
  416. X    int             fd;
  417. X    int             len = sizeof (struct mnttab);
  418. X    struct mnttab  *ptr;
  419. X
  420. X    if ((fd = open (MNTTAB, O_RDONLY)) == -1) {
  421. X    (void) strcpy (filesys[0].mt_dev, "fp002");
  422. X    (void) strcpy (filesys[0].mt_filsys, "/");
  423. X    fs_index = 0;
  424. X    max_fs_index = 0;
  425. X    return;
  426. X    }
  427. X
  428. X    ptr = filesys;
  429. X    for (max_fs_index = 0; max_fs_index < NMOUNT; ++max_fs_index) {
  430. X    if (read (fd, (char *) ptr, len) != len) {
  431. X        break;
  432. X    }
  433. X    ++ptr;
  434. X    }
  435. X
  436. X    max_fs_index--;
  437. X#ifdef    DEBUG
  438. X    (void) syslog (LOG_DEBUG, "read_mtab done: max_fs_index=%d", max_fs_index);
  439. X#endif
  440. X    (void) close (fd);
  441. X
  442. X}
  443. X
  444. Xvoid
  445. Xuptime (char *buf)
  446. X{
  447. X    time_t          curtime, bootsec;
  448. X    int             days;
  449. X    int             hrs;
  450. X    int             mins;
  451. X
  452. X    (void) time (&curtime);
  453. X    bootsec = curtime - boottime;
  454. X
  455. X    days = bootsec / DAY;
  456. X    bootsec -= DAY * days;
  457. X    hrs = bootsec / HOUR;
  458. X    bootsec -= HOUR * hrs;
  459. X    mins = bootsec / MINUTE;
  460. X    bootsec -= MINUTE * mins;
  461. X
  462. X    if (days > 0) {
  463. X    (void) sprintf (buf, "Up: %dd %02d:%02d", days, hrs, mins);
  464. X    }
  465. X    else {
  466. X    (void) sprintf (buf, "Up: %02d:%02d", hrs, mins);
  467. X    }
  468. X
  469. X}
  470. X
  471. Xvoid
  472. Xmailcheck (char *buf)
  473. X{
  474. X    FILE           *fp;
  475. X    char            buffer[BUFSIZ];
  476. X    char           *bufptr;
  477. X    struct stat     statbuf;
  478. X    int             n;
  479. X
  480. X    bufptr = buf;
  481. X    *buf = '\0';
  482. X    for (n = 0; n < MAX_USERS; ++n) {
  483. X    if (user_info[n].u_flag != 1) {
  484. X        continue;
  485. X    }
  486. X    if (access (user_info[n].u_mailfile, 4) == 0) {
  487. X        if (stat (user_info[n].u_mailfile, &statbuf) != -1) {
  488. X        if (statbuf.st_mtime > user_info[n].u_mailtime) {
  489. X            user_info[n].u_msgs = 0;
  490. X            if ((fp = fopen (user_info[n].u_mailfile, "r")) != NULL) {
  491. X            while (fgets (buffer, BUFSIZ, fp) != NULL)
  492. X                if (strncmp (buffer, "From ", 5) == 0)
  493. X                user_info[n].u_msgs++;
  494. X            }
  495. X            (void) fclose (fp);
  496. X            user_info[n].u_mailtime = statbuf.st_ctime;
  497. X        }
  498. X        }
  499. X    }
  500. X    if (bufptr != buf) {
  501. X        *bufptr++ = ' ';
  502. X    }
  503. X    (void) sprintf (bufptr, "%s/%d",
  504. X            user_info[n].u_name, user_info[n].u_msgs);
  505. X    bufptr += strlen (bufptr);
  506. X    }
  507. X}
  508. X
  509. Xvoid
  510. Xloadaverage (char *lbuf)
  511. X{
  512. X    double         *shmseg;
  513. X
  514. X    shmseg = (double *) shmat (shm, (char *) 0, SHM_RDONLY);
  515. X    (void) sprintf (lbuf, "Load: %.2f %.2f %.2f",
  516. X            shmseg[0], shmseg[1], shmseg[2]);
  517. X    if (shmseg[0] > MAX_LOAD_AVG) {
  518. X    highlight (lbuf, lbuf + strlen (lbuf) - 1);
  519. X    }
  520. X    (void) shmdt ((char *) shmseg);
  521. X}
  522. X
  523. Xlong
  524. Xmemory (void)
  525. X{
  526. X    int             mem;
  527. X
  528. X    /*
  529. X     * Read variables.
  530. X     */
  531. X    (void) lseek (kmem, (long) unixsym[N_FREEMEM].n_value, 0);
  532. X    (void) read (kmem, (char *) &mem, sizeof (int));
  533. X
  534. X    return (ctob (mem));
  535. X}
  536. X
  537. Xint
  538. Xslktest (void)
  539. X{
  540. X
  541. X#if    !defined(STANDARD_SLK_TEST) && !defined(PICKY_SLK_TEST)
  542. X    /*
  543. X     * If no slk tests are desired then simply return 0.
  544. X     */
  545. X    return (0);
  546. X
  547. X#else
  548. X
  549. X    /*
  550. X     * check the SLK lines for the existence of anything currently there if
  551. X     * found two blank SLK lines or some remaining sysinfo information,
  552. X     * denoted by "Filesystem" in the second line, then return 0, else return
  553. X     * -1 Developed by David H. Brierley (dave@galaxia.Newport.RI.US)
  554. X     */
  555. X
  556. X    int             rvalue;
  557. X    int             n;
  558. X    char           *p;
  559. X
  560. X    rvalue = 0;
  561. X    utd.ut_num = WTXTSLK1;
  562. X    (void) ioctl (wd, WIOCGETTEXT, &utd);
  563. X    if (utd.ut_text[0] == '\0') {
  564. X    ++rvalue;
  565. X    }
  566. X    else {
  567. X    for (n = 0; n < WTXTLEN; ++n)
  568. X        if ((utd.ut_text[n] != '\0') &&
  569. X        (utd.ut_text[n] != ' '))
  570. X        break;
  571. X    if (n == WTXTLEN)
  572. X        ++rvalue;
  573. X    }
  574. X
  575. X    utd.ut_num = WTXTSLK2;
  576. X    (void) ioctl (wd, WIOCGETTEXT, &utd);
  577. X    if (utd.ut_text[0] == '\0') {
  578. X    ++rvalue;
  579. X    }
  580. X    else {
  581. X    for (n = 0; n < WTXTLEN; ++n)
  582. X        if ((utd.ut_text[n] != '\0') &&
  583. X        (utd.ut_text[n] != ' '))
  584. X        break;
  585. X    if (n == WTXTLEN)
  586. X        ++rvalue;
  587. X    }
  588. X
  589. X    if (rvalue == 2)        /* two blank lines */
  590. X    return (0);
  591. X
  592. X    /*
  593. X     * check to see if the text looks line LINE_2.  since the beginning of
  594. X     * the line is no longer a constant, this is done by checking for the
  595. X     * various words that comprise LINE_2.  Since the text might contain high
  596. X     * bits we firts turn them all off.
  597. X     * 
  598. X     * Note that this is highly dependant on the exact definition of LINE_2 at
  599. X     * the beginning of this file.
  600. X     */
  601. X
  602. X    for (n = 0; n < WTXTLEN; ++n) {
  603. X    utd.ut_text[n] &= 0x7f;
  604. X    }
  605. X    /* skip over the file system name */
  606. X    if ((p = strchr (utd.ut_text, ' ')) == NULL) {
  607. X    return (-1);
  608. X    }
  609. X    /*
  610. X     * Scan for the first occurence of the letter b on the line and check
  611. X     * to see if this is the word "blks" surrounded by blanks.
  612. X     */
  613. X    if (((p = strchr (p, 'b')) == NULL) || strncmp (p - 1, " blks ", 6)) {
  614. X    return (-1);
  615. X    }
  616. X    /*
  617. X     * The following test are only done if PICKY_SLK_TEST is defined.  The
  618. X     * basic idea is that the test for the first letter b on the line being
  619. X     * the word "blks" surrounded by blanks is probably good enough for most
  620. X     * cases.  If you want to be gauranteed that the line contains a LINE_2
  621. X     * info line you can enable any or all of the following tests.  Each
  622. X     * additional test that is enabled requires a call to strchr and a call
  623. X     * to strncmp so this can increase execution time.
  624. X     */
  625. X#ifdef    PICKY_SLK_TEST
  626. X    if (((p = strchr (p, 'i')) == NULL) || strncmp (p - 1, " inodes ", 8)) {
  627. X    return (-1);
  628. X    }
  629. X    if (((p = strchr (p, 'S')) == NULL) || strncmp (p - 1, " Swap: ", 7)) {
  630. X    return (-1);
  631. X    }
  632. X    if (((p = strchr (p, 'M')) == NULL) || strncmp (p - 1, " Mem: ", 6)) {
  633. X    return (-1);
  634. X    }
  635. X#endif
  636. X
  637. X    /*
  638. X     * If all of the tests above failed (or succeeded, depending upon your
  639. X     * point of view), then this must be a LINE_2
  640. X     */
  641. X    return (0);
  642. X#endif
  643. X
  644. X}
  645. X
  646. Xvoid
  647. Xcount_users (char *buf)
  648. X{
  649. X    int             num;
  650. X    int             found;
  651. X    struct utmp    *ut;
  652. X    int             n;
  653. X
  654. X    for (n = 0; n < MAX_USERS; ++n) {
  655. X    if (user_info[n].u_flag == 1) {
  656. X        user_info[n].u_flag = 0;
  657. X    }
  658. X    }
  659. X
  660. X    setutent ();
  661. X    num = 0;
  662. X    while ((ut = getutent ()) != NULL) {
  663. X    if (ut -> ut_type != USER_PROCESS) {
  664. X        continue;
  665. X    }
  666. X    ++num;
  667. X    found = 0;
  668. X    for (n = 0; n < MAX_USERS; ++n) {
  669. X        if (strncmp (ut -> ut_user, user_info[n].u_name, 8) == 0) {
  670. X        user_info[n].u_flag = 1;
  671. X        found = 1;
  672. X        break;
  673. X        }
  674. X        if (user_info[n].u_flag == -1) {
  675. X        (void) strncpy (user_info[n].u_name, ut -> ut_name, 8);
  676. X        user_info[n].u_name[8] = '\0';
  677. X        (void) sprintf (user_info[n].u_mailfile,
  678. X                "/usr/mail/%s",
  679. X                user_info[n].u_name);
  680. X        user_info[n].u_flag = 1;
  681. X        user_info[n].u_mailtime = 0;
  682. X        user_info[n].u_msgs = 0;
  683. X        found = 1;
  684. X        break;
  685. X        }
  686. X    }
  687. X    if (found == 0) {
  688. X        for (n = 0; n < MAX_USERS; ++n) {
  689. X        if (user_info[n].u_flag == 0) {
  690. X            (void) strncpy (user_info[n].u_name, ut -> ut_name, 8);
  691. X            user_info[n].u_name[8] = '\0';
  692. X            (void) sprintf (user_info[n].u_mailfile,
  693. X                    "/usr/mail/%s",
  694. X                    user_info[n].u_name);
  695. X            user_info[n].u_flag = 1;
  696. X            user_info[n].u_mailtime = 0;
  697. X            user_info[n].u_msgs = 0;
  698. X            found = 1;
  699. X            break;
  700. X        }
  701. X        }
  702. X    }
  703. X    }
  704. X
  705. X    (void) sprintf (buf, "%d user%s", num, (num == 1) ? "" : "s");
  706. X    if (num == 0) {
  707. X    num = -1;
  708. X    (void) ioctl (0, WIOCSCR, num);
  709. X    }
  710. X
  711. X}
  712. X
  713. X/*
  714. X * get swap device free block count
  715. X *
  716. X * loops through a copy of the swap device allocation map
  717. X * counting free blocks.  Returns the total number of free blocks.
  718. X */
  719. Xlong
  720. Xpage (void)
  721. X{
  722. X    int             total_free = 0;
  723. X    struct mapent  *smap;
  724. X    struct mapent  *next_smap;
  725. X    struct mapent   sentry;
  726. X    struct map      sheader;
  727. X    static int      last_size;
  728. X    int             temp_last;
  729. X
  730. X    smap = (struct mapent *) unixsym[N_SWAPMAP].n_value;
  731. X
  732. X    if (lseek (kmem, (long) smap, 0) != (long) smap) {
  733. X    return (0);
  734. X    }
  735. X
  736. X    if (read (kmem, (char *) &sheader, sizeof (struct map *)) != sizeof (struct map *)) {
  737. X    return (0);
  738. X    }
  739. X
  740. X    for (next_smap = smap + 1; next_smap != sheader.m_limit; ++next_smap) {
  741. X    if (lseek (kmem, (long) next_smap, 0) != (long) next_smap) {
  742. X        return (0);
  743. X    }
  744. X    if (read (kmem, (char *) &sentry, sizeof (struct mapent)) != sizeof (struct mapent)) {
  745. X        return (0);
  746. X    }
  747. X    total_free += sentry.m_size;
  748. X    }
  749. X
  750. X
  751. X    /*
  752. X     * There is a bug here somewhere.  Occassional bogus figures (very low
  753. X     * numbers) show up.  A stupid hack that does not fix it or even stop it,
  754. X     * but does reduce the number of times it is seen, is implemented.  Low
  755. X     * values are deleted, by repeating the last size the first time it is
  756. X     * lower than minimum.  If the value is less than the minimum twice in a
  757. X     * row it will be displayed.  Sometimes even this is wrong.
  758. X     */
  759. X
  760. X    if (total_free < MIN_SWAP) {
  761. X    if (last_size >= MIN_SWAP) {
  762. X        temp_last = total_free;
  763. X        total_free = last_size;
  764. X        last_size = temp_last;
  765. X    }
  766. X    else {
  767. X        last_size = total_free;
  768. X    }
  769. X    }
  770. X    else {
  771. X    last_size = total_free;
  772. X    }
  773. X
  774. X    return total_free;
  775. X
  776. X}
  777. X
  778. X/*
  779. X * set the high bit on characters of an array.
  780. X */
  781. Xvoid
  782. Xhighlight (char *start, char *end)
  783. X{
  784. X    if (!start || start >= end) {
  785. X    return;
  786. X    }
  787. X
  788. X    for (; start <= end && *start; ++start) {
  789. X    *start |= 0x80;
  790. X    }
  791. X}
  792. END_OF_FILE
  793. if test 20171 -ne `wc -c <'sysinfo.c'`; then
  794.     echo shar: \"'sysinfo.c'\" unpacked with wrong size!
  795. fi
  796. # end of 'sysinfo.c'
  797. fi
  798. echo shar: End of archive 3 \(of 3\).
  799. cp /dev/null ark3isdone
  800. MISSING=""
  801. for I in 1 2 3 ; do
  802.     if test ! -f ark${I}isdone ; then
  803.     MISSING="${MISSING} ${I}"
  804.     fi
  805. done
  806. if test "${MISSING}" = "" ; then
  807.     echo You have unpacked all 3 archives.
  808.     rm -f ark[1-9]isdone
  809. else
  810.     echo You still need to unpack the following archives:
  811.     echo "        " ${MISSING}
  812. fi
  813. ##  End of shell archive.
  814. exit 0
  815. -- 
  816. David H. Brierley
  817. Home: dave@galaxia.network23.com; Work: dhb@quahog.ssd.ray.com
  818. Send comp.sources.3b1 submissions to comp-sources-3b1@galaxia.network23.com
  819. %% Can I be excused, my brain is full. **
  820.