home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume23 / ison / part01 / ison.c next >
Encoding:
C/C++ Source or Header  |  1991-10-22  |  9.4 KB  |  303 lines

  1. /* IsOn... Copyright 1990, 1991 NCEMRSoft.  Use at your own risk!
  2.     - v1.0 : 1990      : Phil Dietz, NCEMRSoft.
  3.                        : Original release.    
  4.     - v2.0 : 05 Feb 91 : Phil Dietz, NCEMRSoft.
  5.                        : Added 'finger'ing remote machines.
  6.                        : Names and searches are now case insensitive.
  7.     - v3.0 : 04 Aug 91 : Mike Gleason, NCEMRSoft.
  8.                        : Complete rewrite, using unix system calls.
  9.                        : Remote addresses are recognized automatically.
  10.                        : IsOn nice's (lowers it's priority) itself.
  11.                        : Remote commands are exec'd instead of subshelled.
  12.                        : Uses handy getopt() function.
  13.                        : Added -f option, in case you don't have finger,
  14.                        :   our finger flags don't work, or want to try
  15.                        :   it rwho, etc.
  16.                        : Added -d debugging option, so you can watch
  17.                        :   ison's progress.  This is also useful if you
  18.                        :   want to log to a file.
  19.                        
  20.     To compile: "cc -O ison.c -o ison"   */
  21.  
  22. #define VERSION_STR "Version 3.0 (04 Aug 91)"
  23.  
  24. #include <sys/types.h>
  25. #include <sys/time.h>
  26. #include <utmp.h>
  27. #include <stdio.h>
  28. #include <ctype.h>
  29.  
  30. #define SZ(expr) ((size_t) (expr))
  31. #define DSLEEP 10       /* seconds to delay between iterations */
  32. #define DDEBUG 0        /* prints stuff if > 0 */
  33. #define DMAXITER -1L    /* loop forever until we find the guy */
  34. #define DCOMMAND NULL   /* command line to do when user is found */
  35. #define DFINGER "finger -fq"
  36.  
  37. #ifndef INDEX
  38. #   ifdef _SYSTYPE_SYSV
  39. #       define INDEX strchr
  40. #   else    /* bsd */
  41. #       define INDEX index
  42. #   endif
  43. #endif
  44.  
  45. extern size_t fread();
  46. extern FILE *fopen(), *popen();
  47. extern char *INDEX();
  48. int strnicmp(), Nice(), Utmp(), Finger();
  49.  
  50. main(argc, argv)
  51.     int argc;
  52.     char **argv;
  53. {
  54.     int                 sleep_sec = DSLEEP;
  55.     int                 debug = DDEBUG;
  56.     long                maxiter = DMAXITER;
  57.     int                 notfound, flag;
  58.     char                *username, hostname[64], *cp;
  59.     char                *fingercmd = DFINGER;
  60.     char                *cmd = DCOMMAND;
  61.     time_t              logontime;
  62.     extern int          getopt(), optind;   /* getopt() stuff */
  63.     extern char         *optarg;            /* getopt() stuff */
  64.  
  65.     if (argc <= 1)
  66.         usage (argv[0], fingercmd);
  67.  
  68.     while ((flag = getopt (argc, argv, "dvs:p:i:f:")) != EOF)
  69.         switch(flag) {
  70.             case 'd':
  71.             case 'v':   /* debug mode, verbose mode, same thing */
  72.                 debug++;
  73.                 break;
  74.             case 's':
  75.                 cmd = optarg;
  76.                 break;
  77.             case 'p':
  78.                 sleep_sec = atoi (optarg);
  79.                 if (sleep_sec < 0) sleep_sec = DSLEEP;
  80.                 break;
  81.             case 'i':
  82.                 maxiter = (long) atol (optarg);
  83.                 break;
  84.             case 'f':
  85.                 fingercmd = optarg;
  86.                 break;
  87.             default: usage (argv[0], fingercmd);
  88.         }
  89.     username = argv[optind];
  90.     if (username == NULL || strlen(username) == SZ(0))
  91.         usage (argv[0], fingercmd); /* no user specified! */
  92.         
  93.     /* lower our process' priority (nice) */
  94.     if (Nice (getpid ()))
  95.         perror ("Nice");
  96.     
  97.     /*  Check the username for an @, which would suggest that it is
  98.         a domain-style address. */
  99.     if ((cp = INDEX (username, (int)'@')) != NULL) {
  100.         strcpy (hostname, cp);  /* @machine.domain.xxx */
  101.         *cp = '\0';             /* shorten address down to just username */
  102.         notfound = Finger (username, sleep_sec, maxiter, argv[0],
  103.             hostname, fingercmd, debug);
  104.         time(&logontime);
  105.     } else
  106.         notfound = Utmp (username, sleep_sec, maxiter, argv[0],
  107.             debug, &logontime);
  108.  
  109.     /* See if the user was found.  If not, explain why not. */
  110.     if (notfound != 0) {
  111.         if (notfound > 0)   /* maxiter encoutered */
  112.             (void) fprintf (stderr, "## %s is not on.\n", username);
  113.         else (void) fprintf (stderr,
  114.             "## %s: cannot go on because of errors.\n", argv[0]);
  115.     } else {
  116.         /* When we get here, the user we're looking for was detected. */
  117.         (void) fprintf (stderr, "** %s%s logged in since %s",
  118. #ifdef NO_BEEP
  119.             "",
  120. #else
  121.             "\007",     /* Control-G, the ascii BEL character */
  122. #endif
  123.             username, ctime(&logontime));
  124.         if (cmd != NULL) {
  125.             /* Run a command (script) if the user requested to. */
  126.             (void) execlp ("/bin/sh", "sh", "-c", cmd, NULL);
  127.             (void) perror (cmd);
  128.         }
  129.     }
  130.     exit (notfound);
  131. }   /* main */
  132.  
  133.  
  134.  
  135.  
  136. int Utmp(username, sleep_sec, maxiter, progname, debug, tyme)
  137.     char                *username, *progname;
  138.     int                 sleep_sec, debug;
  139.     long                maxiter;
  140.     time_t              *tyme;
  141. {
  142.     struct utmp         info;
  143.     FILE                *in;
  144.     register int        not_on = 1, iter = 1;
  145.     register size_t     unamelen = strlen (username);
  146.  
  147.     /* Open the utmp file, which is a list of all logged on users. */
  148.     if ((in = fopen (UTMP_FILE, "r")) == NULL) {
  149.         (void) perror (UTMP_FILE);
  150.         return (1);
  151.     }
  152.     
  153.     do {
  154.         if (debug > 0) {
  155.             time(tyme);
  156.             (void) printf("## %s: checking utmp (try #%d) at %s",
  157.                 progname, iter, ctime(tyme));
  158.         }
  159.  
  160.         /* Reset the utmp file and re-read it. */
  161.         (void) rewind (in);
  162.         
  163.         /* Cycle through all 'users' logged in. */
  164.         while (not_on && (fread (&info, SZ(sizeof (info)), SZ(1), in)) == SZ(1)) {
  165.             not_on = strnicmp(info.ut_name, username, unamelen);
  166.             if (debug > 1 && *info.ut_name) {
  167.                 info.ut_name[8] = '\0';
  168.                 printf("%s\n", info.ut_name);
  169.             }
  170.         }
  171.         
  172.         /* Delay a little so we won't hog the CPU */
  173.         if (not_on) {
  174.             if (maxiter > 0 && ++iter > maxiter) {
  175.                 not_on = 1; break;
  176.             }
  177.             (void) sleep (sleep_sec);
  178.         }
  179.     } while (not_on);
  180.     
  181.     *tyme = info.ut_time;   /* will hold garbage if user not found! */
  182.     (void) fclose (in);
  183.     return (not_on);
  184. }   /* Utmp */
  185.  
  186.  
  187.  
  188.  
  189. int Finger(username, sleep_sec, maxiter, progname, hostname, fingercmd, debug)
  190.     char *username, *progname, *hostname, *fingercmd;
  191.     int sleep_sec, debug;
  192.     long maxiter;
  193. {
  194.     FILE                *in;
  195.     register int        not_on = 1, iter = 1, piperesult;
  196.     register size_t     unamelen = strlen (username);
  197.     extern int          errno;
  198.     char                buf[160], pipename[128];
  199.     time_t              now;
  200.     
  201.     strcpy(pipename, fingercmd);
  202.     strcat(pipename, " ");
  203.     if (strnicmp("finger", fingercmd, SZ(6)) != 0)
  204.         hostname++; /* Skip the @ sign if it's not finger! */
  205.     strcat(pipename, hostname);
  206.     
  207.     do {
  208.         if (debug > 0) {        
  209.             time(&now);
  210.             (void) printf("## %s: %s (try #%d), at %s",
  211.                 progname, pipename, iter, ctime(&now));
  212.         }
  213.         
  214.         if ((in = popen (pipename, "r")) == NULL) {
  215.             perror (fingercmd);
  216.             not_on = -errno;
  217.             break;
  218.         }
  219.         
  220.         /* Cycle through all 'users' logged in. */
  221.         while (not_on && fgets (buf, (int)sizeof(buf), in) != NULL) {
  222.             if (debug > 1) printf(buf);
  223.             not_on = strnicmp(buf, username, unamelen);
  224.         }
  225.         
  226.         piperesult = pclose(in);            /* close pipe */
  227.         if (piperesult && not_on) {
  228.             not_on = (piperesult > 0) ? -piperesult : piperesult;
  229.             break;
  230.         }
  231.         
  232.         /* Delay a little so we won't hog the CPU */
  233.         if (not_on) {
  234.             if (maxiter > 0 && ++iter > maxiter) {
  235.                 not_on = 1; break;
  236.             }
  237.             (void) sleep (sleep_sec);
  238.         }
  239.     } while (not_on);
  240.     return (not_on);
  241. }   /* Finger */
  242.  
  243.  
  244.  
  245. strnicmp(a, b, n)
  246.     char *a, *b;
  247.     register size_t n;
  248. {
  249.     register int i;
  250.     
  251.     for ( ; tolower(*a) == tolower(*b) && n-- > 0; a++, b++)
  252.         if (*a == '\0')
  253.             return (0); /* equal */
  254.     return (n <= 0 ? 0 : tolower(*a) - tolower(*b));
  255. }
  256.  
  257.  
  258.  
  259.  
  260. usage(progname, fingercmd)
  261.     char *progname, *fingercmd;
  262. {   
  263.     (void) fprintf (stderr,
  264. "usage: %s [-p N] [-i N] [-s cmd] [-f cmd] [-d] username &\n\
  265. \t-p N   : Delay 'N' seconds between iterations (default 10).\n\
  266. \t-i N   : Give up after 'N' iterations (default is infinity)\n\
  267. \t-s cmd : Command to execute when user is found (i.e. \"talk username\")\n\
  268. \t-f cmd : Command to execute for remote addresses (def: \"%s\")\n\
  269. \t-d     : Debugging mode. More d's, more stuff.\n\n\
  270. %s by Phil Dietz & Mike Gleason, NCEMRSoft.\n\
  271. This is TuitionWare.  Please send a buck to help us through school!\n\
  272. \tPhil Dietz, Box 306, Yutan, NE  68073, USA... Thanks!\n\n",
  273.     progname, fingercmd, VERSION_STR);
  274.     exit (1);
  275. }   /* usage */
  276.  
  277.  
  278.  
  279.  
  280. #include <sys/resource.h>
  281. #define DEFAULT_NICE_INCREMENT 10
  282.  
  283. int Nice(pid)
  284.     pid_t pid;
  285. {
  286.     extern int errno;
  287.     register int priority;
  288.  
  289. #ifndef NOT_NICE        /* #define it if you don't want to be nice'd */
  290.     errno = 0;  /* clear it, since priority can be -1! */
  291.     priority = getpriority(PRIO_PROCESS, pid);
  292.     if (errno == 0) {
  293.         priority += DEFAULT_NICE_INCREMENT;
  294.         if (priority > PRIO_MAX)
  295.             priority = PRIO_MAX;
  296.         (void) setpriority(PRIO_PROCESS, pid, priority);
  297.     }
  298. #endif
  299.     return (errno);
  300. }   /* Nice */
  301.  
  302. /* eof */
  303.