home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / alt / sources / 2550 < prev    next >
Encoding:
Text File  |  1992-11-18  |  15.4 KB  |  646 lines

  1. Path: sparky!uunet!snorkelwacker.mit.edu!ai-lab!silver.lcs.mit.edu!cutter
  2. From: cutter@silver.lcs.mit.edu (nice guys don't get paid)
  3. Newsgroups: alt.sources
  4. Subject: argus -- repost -- shar file
  5. Date: 18 Nov 1992 15:43:31 GMT
  6. Organization: MIT Artificial Intelligence Lab
  7. Lines: 635
  8. Message-ID: <1edob3INN754@life.ai.mit.edu>
  9. NNTP-Posting-Host: silver.ai.mit.edu
  10.  
  11. Submitted-by: cutter@silver
  12. Archive-name: argus
  13.  
  14. This is a repost of the file I submitted a few days ago.  Some people
  15. complained about sending a uuencoded and compressed file, so I'll
  16. resend it in shar format.  Sorry about that.
  17.  
  18. /joe
  19.  
  20. -|-|-|-|-|-|/\-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-
  21. Joe Turner <  > cutter@silver.lcs.mit.edu
  22.             \/
  23. Don't touch it!  It's PURE EVIL!
  24.  
  25.  
  26. ---- Cut Here and feed the following to sh ----
  27. #!/bin/sh
  28. # This is ARGUS, a shell archive (produced by shar 3.49)
  29. # To extract the files from this archive, save it to a file, remove
  30. # everything above the "!/bin/sh" line above, and type "sh file_name".
  31. #
  32. # made 11/18/1992 15:32 UTC by cutter@silver
  33. # Source directory /usr/guests/cutter/src/dist/argus
  34. #
  35. # existing files will NOT be overwritten unless -c is specified
  36. #
  37. # This shar contains:
  38. # length  mode       name
  39. # ------ ---------- ------------------------------------------
  40. #   1996 -rw-r--r-- INSTALL
  41. #    475 -rw-r--r-- Makefile
  42. #    480 -rw-r--r-- README
  43. #   9431 -rw-r--r-- argus.c
  44. #
  45. # ============= INSTALL ==============
  46. if test -f 'INSTALL' -a X"$1" != X"-c"; then
  47.     echo 'x - skipping INSTALL (File already exists)'
  48. else
  49. echo 'x - extracting INSTALL (Text)'
  50. sed 's/^X//' << 'SHAR_EOF' > 'INSTALL' &&
  51. Installation Notes for ARGUS
  52. X
  53. 1.)    Edit the Makefile.
  54. X
  55. X    Change the ${BIN} field so it points to where the binary will
  56. X    eventually end up.  If you are installing argus on a system
  57. X    not mentioned before, you might want to uncomment CFLAGS so
  58. X    the debugging information will be retained (that is, if you
  59. X    plan to try debugging it if it bombs!).  If you are running
  60. X    under SunOS, you won't have to do much of anything.  If you
  61. X    are running under Ultrix, or Mt Xinu's MORE/bsd, uncomment the
  62. X    appropriate CDEFs.  This program has NOT been tested on
  63. X    anything remotely SysV.
  64. X
  65. 2.)    Type "make install".
  66. X
  67. X    If it works -- hey! great!   If not, try pretending you're on
  68. X    a Sun or a VAX.  If that doesn't work, mail me a bug report
  69. X    (or play around with it yourself).
  70. X
  71. X
  72. How to Use Argus
  73. ================
  74. X
  75. 1.)    Create a file in your home directory called ".argus" (or
  76. X    whatever LISTFILE is set to in argus.c, or whatever the
  77. X    environment variable LISTFILE is set to).  This file should
  78. X    contain a list of usernames, one per line. 
  79. X
  80. 2.)    Type "argus".  If that doesn't work, make sure the executable
  81. X    is in a directory that's in your path.
  82. X
  83. X    Be careful -- if no-one you care about is on, argus will sit
  84. X    quietly and it may look like it's not working.  Typing "ps -x"
  85. X    will give you a list of all your processes, and argus should
  86. X    be listed.  If not, it really *isn't* working, and you should
  87. X    e-mail me.
  88. X
  89. 3.)    If you so desire, put "argus" in your .login file.  You don't
  90. X    have to worry about stopping argus before you log out -- it
  91. X    will stop automatically once you have left.
  92. X
  93. 4.)    Command line options:
  94. X        -w    Who?        Show the current who's-here list.
  95. X        -r *    Reread        Read the usernames file in again.
  96. X        -k *    Kill        Kill argus (quit).
  97. X        -h    Help!        Show me these options.
  98. X        -n *    Notify        Toggle notification beeps.
  99. X    A star next to an option means that the option will affect an
  100. X    already running argus.
  101. X
  102. X    The default notification is set to "quiet".
  103. X
  104. Mail all questions, comments, bomb-threats, etc., to cutter@ra.umb.edu.
  105. SHAR_EOF
  106. chmod 0644 INSTALL ||
  107. echo 'restore of INSTALL failed'
  108. Wc_c="`wc -c < 'INSTALL'`"
  109. test 1996 -eq "$Wc_c" ||
  110.     echo 'INSTALL: original size 1996, current size' "$Wc_c"
  111. fi
  112. # ============= Makefile ==============
  113. if test -f 'Makefile' -a X"$1" != X"-c"; then
  114.     echo 'x - skipping Makefile (File already exists)'
  115. else
  116. echo 'x - extracting Makefile (Text)'
  117. sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
  118. CC    = gcc
  119. #CFLAGS    = -g
  120. #CDEF    = -DMOREBSD
  121. #CDEF    = -DULTRIX
  122. BIN    = ${HOME}/bin
  123. SRC    = ${HOME}/src
  124. DIST    = ${SRC}/dist
  125. X
  126. all: argus
  127. X
  128. install: argus
  129. X    strip argus
  130. X    mv argus ${BIN}/argus
  131. X
  132. argus:    argus.c
  133. X    ${CC} ${CFLAGS} ${CDEF} argus.c -o argus
  134. X
  135. mv:
  136. X    (cd ${SRC}/argus; \
  137. X    cp INSTALL README argus.c ${DIST}/argus; \
  138. X    cp Makefile.dist ${DIST}/argus/Makefile)
  139. X
  140. dist:
  141. X    (cd ${SRC}/dist; \
  142. X    tar cf argus.tar argus; \
  143. X    compress argus.tar; \
  144. X    uuencode argus.tar.Z argus.tar.Z > argus.tar.Z.uu)
  145. SHAR_EOF
  146. chmod 0644 Makefile ||
  147. echo 'restore of Makefile failed'
  148. Wc_c="`wc -c < 'Makefile'`"
  149. test 475 -eq "$Wc_c" ||
  150.     echo 'Makefile: original size 475, current size' "$Wc_c"
  151. fi
  152. # ============= README ==============
  153. if test -f 'README' -a X"$1" != X"-c"; then
  154.     echo 'x - skipping README (File already exists)'
  155. else
  156. echo 'x - extracting README (Text)'
  157. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  158. Before you attempt to install argus, please do the following:
  159. X
  160. X    o    Read the instructions in INSTALL.   Argus is pretty
  161. X        simple to install, but please read it anyway.
  162. X
  163. X    o    Send a short note to me (cutter@ra.cs.umb.edu) telling
  164. X        me you're trying to install argus.  I'd like to keep
  165. X        track (at least at the start) of people who are
  166. X        using it.
  167. X
  168. Enjoy!
  169. X
  170. X
  171. -|-|-|-|-|-|/\-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-
  172. Joe Turner <  > cutter@ra.cs.umb.edu
  173. X            \/
  174. SHAR_EOF
  175. chmod 0644 README ||
  176. echo 'restore of README failed'
  177. Wc_c="`wc -c < 'README'`"
  178. test 480 -eq "$Wc_c" ||
  179.     echo 'README: original size 480, current size' "$Wc_c"
  180. fi
  181. # ============= argus.c ==============
  182. if test -f 'argus.c' -a X"$1" != X"-c"; then
  183.     echo 'x - skipping argus.c (File already exists)'
  184. else
  185. echo 'x - extracting argus.c (Text)'
  186. sed 's/^X//' << 'SHAR_EOF' > 'argus.c' &&
  187. /*
  188. ** argus  -  look for users you care about (or want to avoid)
  189. ** version 1.0 by Joe Turner (cutter@ra.cs.umb.edu)  06-Oct-1992
  190. ** Imagine that the GNU copyleft was right here.
  191. **
  192. ** Thanks to laura@usl.com and roland@gnu.ai.mit.edu for helpful
  193. ** suggestions!
  194. */
  195. X
  196. #include <stdio.h>
  197. #include <errno.h>
  198. #include <string.h>
  199. #include <signal.h>
  200. #include <utmp.h>
  201. #include <pwd.h>
  202. #include <sys/file.h>
  203. #include <sys/types.h>
  204. X
  205. #ifdef ULTRIX
  206. #define DUMBFPRINTF
  207. #define NOSTDLIB
  208. #define NOSTRDUP
  209. #endif
  210. X
  211. #ifdef MOREBSD
  212. #define DUMBFPRINTF
  213. #define NOMALLOCH
  214. #define NOSTDLIB
  215. #define NOSTRDUP
  216. #endif
  217. X
  218. /*
  219. ** LISTFILE says where the list of users you care about is.
  220. ** It is overridden by the LISTFILE environment variable.
  221. */
  222. #define LISTFILE ".argus"
  223. X
  224. /*
  225. ** PIDFILE says where argus stores its current PID.
  226. ** It is overridden by the PIDFILE environment variable.
  227. */
  228. #define PIDFILE ".arguspid"
  229. X
  230. /*
  231. ** How many users are usually on your machine?
  232. */
  233. #define MAXUSER 75
  234. X
  235. #ifndef NOSTDLIB
  236. #include <stdlib.h>
  237. #endif
  238. X
  239. #ifndef NOMALLOCH
  240. #include <malloc.h>
  241. #endif
  242. X
  243. typedef char *List[MAXUSER];
  244. X
  245. /*
  246. ** Some global variables
  247. */
  248. char host[20];
  249. char *PIDF, *LISTF;
  250. int reread_list = 1; /* so it will read the first time argus is run */
  251. int beep = 1; /* beep char */
  252. X
  253. /*
  254. ** gotta write this because Ultrix SUCKS and has no strdup.
  255. ** apparently this is also missing in mtxinu's MORE/bsd.
  256. */
  257. #ifdef NOSTRDUP
  258. void *strdup(char *s)
  259. {
  260. X  return((char *)sprintf(malloc(strlen(s)),"%s",s));
  261. }
  262. #endif
  263. X
  264. /*
  265. ** figure out which files to use.
  266. */
  267. void which_files()
  268. {
  269. X  char *home;
  270. X
  271. X  home = (char *) malloc(50);
  272. X  PIDF = (char *) malloc(50);
  273. X  LISTF = (char *) malloc(50);
  274. X
  275. X  sprintf(home,"%s/",getenv("HOME"));
  276. X
  277. X  if (getenv("PIDFILE") == NULL)
  278. X      sprintf(PIDF,"%s%s",home,PIDFILE);
  279. X  else
  280. X      sprintf(PIDF,"%s%s",home,getenv("PIDFILE"));
  281. X
  282. X  if (getenv("LISTFILE") == NULL)
  283. X      sprintf(LISTF,"%s%s",home,LISTFILE);
  284. X  else
  285. X      sprintf(LISTF,"%s%s",home,getenv("LISTFILE"));
  286. }
  287. X  
  288. /*
  289. ** write the pid of the child to a lockfile.
  290. */
  291. void writepid()
  292. {
  293. X  FILE *fd;
  294. X
  295. X  if ((fd = fopen(PIDF,"w")) == NULL)
  296. X    {
  297. X      perror(strcat(strdup("Couldn't find "),PIDF));
  298. X      exit(errno);
  299. X    }
  300. #ifdef DUMBFPRINTF /* lossage again */
  301. X  if (fprintf(fd,"%d\n",getpid()))
  302. #else
  303. X  if (!fprintf(fd,"%d\n",getpid()))
  304. #endif
  305. X    {
  306. X      perror(strcat(strdup("Couldn't write to "),PIDF));
  307. X      exit(errno);
  308. X    }
  309. X  fclose(fd);
  310. }
  311. X
  312. /*
  313. ** read the PID from PIDF, if we can.
  314. */
  315. int readpid()
  316. {
  317. X  FILE *fd;
  318. X  int pid;
  319. X
  320. X  if ((fd = fopen(PIDF,"r")) == NULL) /* if we couldn't open it... */
  321. X    {
  322. X      if (errno != ENOENT) /* if a major error occurs */
  323. X    {
  324. X      perror(strcat(strdup("Couldn't read "),PIDF));
  325. X      exit(errno);
  326. X    }
  327. X      else /* no file.  assume no other running process and return -1 */
  328. X    return(-1);
  329. X    }
  330. X  else /* we COULD open it, so read the PID and return it */
  331. X    {
  332. X      if (!fscanf(fd,"%d\n",&pid)) /* returns 0 if screwed up */
  333. X    return(-1);
  334. X      else
  335. X    return(pid);
  336. X    }
  337. X  fclose(fd);
  338. }
  339. X
  340. /*
  341. ** is process pid still mine and still running?
  342. */
  343. int already(int pid)
  344. {
  345. X  int a;
  346. X
  347. X  if (pid == -1)
  348. X    return(0);
  349. X  else
  350. X    {
  351. X      errno = 0;
  352. X      a = setpriority(0,pid,getpriority(0,pid));
  353. X      return((errno != EPERM) && (a != -1));
  354. X    }
  355. }
  356. X
  357. /*
  358. ** is "name" anywhere in "list"?
  359. */
  360. int exists(char *name, List list, int num)
  361. {
  362. X  int i = 0;
  363. X  while ((i < num) && strcmp(name,list[i]))
  364. X    i++;
  365. X  return(i < num);
  366. }
  367. X
  368. /*
  369. ** when we get a SIGINT, run this routine.
  370. */
  371. void reread()
  372. {
  373. X  printf("[argus@%s: rereading %s]\n",host,LISTF);
  374. X  reread_list = 1;
  375. }
  376. X
  377. /*
  378. ** when we get a SIGQUIT, run this routine.
  379. */
  380. void quiet()
  381. {
  382. X  printf("[argus@%s: ",host);
  383. X  beep ? printf("quiet]\n",host) : printf("loud]\n");
  384. X  beep = !beep;
  385. }
  386. X
  387. /*
  388. ** read the user's namelist into an array and return the amount read.
  389. */
  390. void read_list(List ul, int *num)
  391. {
  392. X  FILE *fd;
  393. X  int uln = 0;
  394. X
  395. X  if ((fd = fopen(LISTF,"r")) == NULL)   /* open the user's file. */
  396. X    {
  397. X      perror("can't open names file"); /* user is a dim bulb */
  398. X      exit(errno);
  399. X    }
  400. X
  401. X  while (fscanf(fd,"%s\n",(ul[uln] = (char *) malloc(10))) != EOF)
  402. X    uln++; /* read entries */
  403. X
  404. X  fclose(fd);
  405. X  *num = uln;
  406. X  reread_list = 0;
  407. }
  408. X
  409. /*
  410. ** read the /etc/utmp file into an array and return the amount read.
  411. */
  412. void read_utmp(List ut, int *num)
  413. {
  414. X  FILE *fd;
  415. X  struct utmp usr;
  416. X  int utn = 0;
  417. X
  418. X  /* open the /etc/utmp file */
  419. X  if ((fd = fopen("/etc/utmp","r")) == NULL)
  420. X    {
  421. X      perror("can't open utmp");
  422. X      exit(errno);
  423. X    }
  424. X  while (fread(&usr, sizeof(usr), 1, fd) != 0)    /* read it in.  get */
  425. X    if (*usr.ut_name && *usr.ut_line)        /* the usernames and */
  426. X      if (!exists(usr.ut_name,ut,utn))        /* store them in ut */
  427. X    ut[utn++] = strncpy(malloc(8),usr.ut_name,8);
  428. X  fclose(fd);
  429. X  *num = utn;
  430. }
  431. X
  432. display_users(int uln,int ut1n,int ut2n,List ul,List ut1,List ut2)
  433. {
  434. X  int i;
  435. X
  436. X  /*
  437. X  ** check each name we're looking for against the lists.  if
  438. X  ** it's not in ut1 but it is in ut2, that user has just shown
  439. X  ** up and we should announce it.  if it's in ut1 but NOT in
  440. X  ** ut2, then a user left and we should announce it.  The first
  441. X  ** time through, ut1 will be blank.
  442. X  */
  443. X  for (i = 0; i < uln; i++)
  444. X    if (exists(ul[i],ut2,ut2n) && !exists(ul[i],ut1,ut1n))
  445. X      printf("%c[argus@%s: %s is here]\n",beep?'\a':'\0',host,ul[i]);
  446. X    else
  447. X      if (!exists(ul[i],ut2,ut2n) && exists(ul[i],ut1,ut1n))
  448. X    printf("%c[argus@%s: %s is gone]\n",beep?'\a':'\0',host,ul[i]);
  449. }  
  450. X
  451. /*
  452. ** Exit with grace, style, wit, and charm.
  453. */
  454. byebye()
  455. {
  456. X  printf("[Argus says goodbye]\n");
  457. X  execl("/bin/rm","/bin/rm",PIDF,(char *)0);
  458. X  exit(0);
  459. }
  460. X
  461. /*
  462. ** Here we go again...
  463. */
  464. main(int argc, char *argv[])
  465. {
  466. X  /*
  467. X  ** ut1 and ut2 contain valid utmp entries to check names against
  468. X  ** ut1 is "older" than ut2, so if a name is in ut2 but not ut1, then
  469. X  ** that person just showed up.  ut1n and ut2n are the number
  470. X  ** of entries in each list.  ul holds the user's list of names to
  471. X  ** check for.  uln is the number of entries.
  472. X  */
  473. X
  474. X  int i; /* counter variable */
  475. X  int ppid; /* parent pid - not ALWAYS the login proc, tho. :( */
  476. X  int pid; /* child pid */
  477. X  int ut1n = 0, ut2n, uln = 0;
  478. X  int otherpid, another = 0; /* is there an argus running already? */
  479. X
  480. X  int DFLT, HELP, KILL, BELL, READ, WHO;
  481. X
  482. X  char *opt;
  483. X  int op; /* storage variable */
  484. X  char host1[20]; /* hostname */
  485. X  char *ut1[MAXUSER], *ut2[MAXUSER], *ul[MAXUSER];
  486. X
  487. X  struct passwd *pwent; /* for getting username */
  488. X
  489. X
  490. X  /* get the host name (minus domain fields) */
  491. X  if (gethostname(host1,20))
  492. X    {
  493. X      perror("can't get your hostname");
  494. X      exit(errno);
  495. X    }
  496. X  sscanf(host1,"%[^.]",host);
  497. X
  498. X  ppid = getppid();
  499. X
  500. X  which_files();
  501. X
  502. X  another = already((pid = readpid()));
  503. X
  504. X  DFLT = HELP = KILL = BELL = READ = WHO = 0;
  505. X  if (argc == 2)
  506. X    {
  507. X      opt = strchr(argv[1],'-');
  508. X      if (opt == NULL || (opt != NULL && opt+1 == NULL))
  509. X    op = '?';
  510. X      else
  511. X    op = *(++opt);
  512. X      do
  513. X    {
  514. X      switch (op)
  515. X        {
  516. X        case '?': DFLT = !DFLT;
  517. X          break;
  518. X        case 'h': HELP = !HELP;
  519. X          break;
  520. X        case 'k': KILL = !KILL;
  521. X          break;
  522. X        case 'n': BELL = !BELL;
  523. X          break;
  524. X        case 'r': READ = !READ;
  525. X          break;
  526. X        case 'w': WHO = !WHO;
  527. X          break;
  528. X        default: HELP = 1;
  529. X          break;
  530. X        }
  531. X      op = *(++opt);
  532. X    }
  533. X      while (op != NULL);
  534. X
  535. X      if (HELP)
  536. X    {
  537. X      printf("\nargus 1.0\nBugs to cutter@ra.cs.umb.edu\n");
  538. X      printf("Usage: argus [-hknrw]\n\n");
  539. X    }
  540. X      if (KILL)
  541. X    {
  542. X      if (another)
  543. X        kill(pid,1); /* kill the old argus */
  544. X      else
  545. X        printf("argus: there is no other argus to kill.\n");
  546. X    }
  547. X      if (BELL)
  548. X    {
  549. X      if (another && !WHO)
  550. X        kill(pid,3); /* toggle beeps */
  551. X      beep = 0; /* default is silent */
  552. X    }
  553. X      if (READ)
  554. X    {
  555. X      if (another)
  556. X        kill(pid,2); /* make it reread file */
  557. X      else
  558. X        printf("argus: there is no other argus running.\n");
  559. X    }
  560. X      if (WHO)
  561. X    {
  562. X      ut1n = 0; beep = 0;
  563. X      read_list(ul,&uln);
  564. X      read_utmp(ut2,&ut2n);
  565. X      display_users(uln, ut1n, ut2n, ul, ut1, ut2);
  566. X    }
  567. X      if (DFLT)
  568. X    {
  569. X      printf("Usage: argus [-hknrw]\n");
  570. X    }
  571. X    }
  572. X
  573. X  if (DFLT || HELP || KILL || READ || WHO || (BELL && WHO))
  574. X    exit(0);
  575. X
  576. X  if (another)
  577. X    {
  578. X      if (!BELL)
  579. X    printf("Argus is already running, process %d.\n",pid);
  580. X      exit(0);
  581. X    }
  582. X
  583. X  if ((pid = fork()) == -1)
  584. X    {
  585. X      perror("couldn't fork a process");
  586. X      exit(errno);
  587. X    } 
  588. X
  589. X  if (pid != 0)
  590. X    {
  591. X      exit(0);
  592. X    }
  593. X
  594. X  writepid();
  595. X
  596. X  if (nice(10)) /* be nice to the system */
  597. X    {
  598. X      perror("couldn't change priority");
  599. X      exit(errno);
  600. X    }
  601. X
  602. X  signal(SIGHUP,byebye); /* Let's make sure we exit cleanly and all. */
  603. X  signal(SIGINT,reread); /* Trap a SIGINT so it will reread the user's */
  604. X             /* file. */
  605. X  signal(SIGQUIT,quiet); /* Trap a SIGQUIT to turn beeps off */
  606. X
  607. X  if ((pwent = getpwuid(getuid())) == NULL) /* get the user's passwd */
  608. X                        /* file entry */ 
  609. X    {
  610. X      perror("couldn't get username");
  611. X      exit(errno);
  612. X    }
  613. X
  614. X  while (already(ppid)) /* Da Main Loop, duh yeah. */
  615. X    {
  616. X      if (reread_list) /* this will be true on first execution */
  617. X    {
  618. X      ut1n = 0;
  619. X      read_list(ul,&uln);
  620. X    }
  621. X
  622. X      read_utmp(ut2,&ut2n);
  623. X
  624. X      display_users(uln, ut1n, ut2n, ul, ut1, ut2);
  625. X
  626. X      /*
  627. X      ** shift ut2 to ut1 so we can have something to compare when
  628. X      ** the next utmp file is read in.  both  ut2 and ut2n will
  629. X      ** be reset when the next utmp file is read in.
  630. X      */
  631. X      for (i=0; i < ut2n; i++)
  632. X    ut1[i] = ut2[i];
  633. X      ut1n = ut2n;
  634. X
  635. X      sleep(5); /* be even MORE nice to the system */
  636. X    }
  637. }
  638. SHAR_EOF
  639. chmod 0644 argus.c ||
  640. echo 'restore of argus.c failed'
  641. Wc_c="`wc -c < 'argus.c'`"
  642. test 9431 -eq "$Wc_c" ||
  643.     echo 'argus.c: original size 9431, current size' "$Wc_c"
  644. fi
  645. exit 0
  646.