home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Other / upsd / upsd_NeXT / funcs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-07  |  6.6 KB  |  419 lines

  1. /*
  2. **    f u n c s . c
  3. **
  4. **    functions for UPS monitor daemon
  5. **
  6. **    Arthur W. Neilson III
  7. **    art@pilikia.pegasus.com
  8. **    Sat Mar 30 1991
  9. */
  10.  
  11. #include <sys/ioctl.h>
  12. #include "common.h"
  13.  
  14. /*
  15. **    g e t v a r s
  16. **
  17. **    retrieve environment variables
  18. */
  19. void
  20. getvars()
  21. {
  22.     char   *s, *getenv();
  23.  
  24.     if ((s = getenv(UPSPORT)) != NULL)
  25.         ups_port = s;
  26.     if ((s = getenv(UPSSHUT)) != NULL)
  27.         ups_shut = s;
  28.     if ((s = getenv(UPSLOG)) != NULL)
  29.         ups_log = s;
  30.     if ((s = getenv(UPSFAIL)) != NULL)
  31.         ups_fail = s;
  32.     if ((s = getenv(UPSREST)) != NULL)
  33.         ups_rest = s;
  34.     if ((s = getenv(UPSTIME)) != NULL)
  35.         ups_time = atoi(s);
  36. }
  37.  
  38. /*
  39. **    g e t o p t i o n s
  40. **
  41. **    retrieve and process command line options
  42. */
  43. void
  44. getoptions(ac, av)
  45. int     ac;
  46. char   *av[];
  47. {
  48.     int     c;
  49.  
  50.     void    version();
  51.     void    usage();
  52.  
  53.     extern char *optarg;
  54.     extern int optind, opterr;
  55.  
  56.     /* display program version */
  57.     version(av[0]);
  58.  
  59.     /* parse the command line */
  60.     while ((c = getopt(ac, av, "d:c:l:f:r:t:")) != EOF)
  61.         switch (c) {
  62.         case 'd':    /* device option */
  63.             ups_port = optarg;
  64.             break;
  65.         case 'c':    /* command option */
  66.             ups_shut = optarg;
  67.             break;
  68.         case 'l':    /* logfile option */
  69.             ups_log = optarg;
  70.             break;
  71.         case 'f':    /* failure option */
  72.             ups_fail = optarg;
  73.             break;
  74.         case 'r':    /* restore option */
  75.             ups_rest = optarg;
  76.             break;
  77.         case 't':    /* time option */
  78.             ups_time = atoi(optarg);
  79.             break;
  80.         case '\?':    /* illegal option */
  81.             usage(av[0]);
  82.             exit(1);
  83.         }
  84. }
  85.  
  86. /*
  87. **    c h k o p t i o n s
  88. **
  89. **    check runtime options
  90. **    with various sanity tests
  91. */
  92. void
  93. chkoptions()
  94. {
  95.     struct stat st;
  96.     char   *p, buf[64];
  97.  
  98.     /* UPS port must exist */
  99.     if (stat(ups_port, &st) == ERR) {
  100.         perror(ups_port);
  101.         exit(1);
  102.     }
  103.     /* and must be character special */
  104.     if ((st.st_mode & S_IFMT) != S_IFCHR) {
  105.         fprintf(stderr, "%s not character special\n", ups_port);
  106.         exit(1);
  107.     }
  108.     /* get command name out of shutdown command */
  109.     strcpy(buf, ups_shut);
  110.     if ((p = strtok(buf, " ")) == NULL)
  111.         p = buf;
  112.  
  113.     /* shutdown command must exist */
  114.     if (stat(p, &st) == ERR) {
  115.         perror(ups_shut);
  116.         exit(1);
  117.     }
  118.     /* and must be a regular file */
  119.     if ((st.st_mode & S_IFMT) != S_IFREG) {
  120.         fprintf(stderr, "%s not regular\n", ups_port);
  121.         exit(1);
  122.     }
  123.     /* delay time must be > 0 and <= MAX_TIME */
  124.     if (ups_time < 1 || ups_time > MAX_TIME) {
  125.         fprintf(stderr, "time must be between 1 and %d\n", MAX_TIME);
  126.         exit(1);
  127.     }
  128. }
  129.  
  130. /*
  131. **    m k d a e m o n
  132. **
  133. **    create daemon process
  134. */
  135. void
  136. mkdaemon()
  137. {
  138.     char    c;
  139.     int    stat;
  140.     unsigned int    modembits;
  141.     unsigned int     oldbits;
  142.  
  143.     void    sigcatch();
  144.     void    writelog();
  145.     void    writeall();
  146.     void    shutdown();
  147.     
  148.     
  149.     writelog(START_MSG);
  150.  
  151.  
  152.  
  153.     if (!fork()) {
  154.  
  155.         /* close standard files */
  156.  
  157.         close(0);    /* stdin */
  158.         close(1);    /* stdout */
  159.         close(2);    /* stderr */
  160.  
  161.  
  162.         setpgrp();    /* disassociate from terminal */
  163.  
  164.         /* ignore interrupts */
  165.         signal(SIGHUP, SIG_IGN);
  166.         signal(SIGINT, SIG_IGN);
  167.         signal(SIGQUIT, SIG_IGN);
  168.  
  169.         /* catch termination signal */
  170.         signal(SIGTERM, sigcatch);
  171.  
  172.         /* and shutdown on alarm */
  173.         signal(SIGALRM, shutdown);
  174.  
  175.         /* open log file for append */
  176.         if ((log_fd = open(ups_log, LOG_FLAGS, LOG_PERMS)) == ERR) {
  177.             perror("could not open log file");
  178.             exit(1);
  179.         }
  180.  
  181.  
  182.         /* and advisory lock it */
  183. /*
  184.         if (lockf(log_fd, F_TLOCK, 0L) == ERR) {
  185.             perror("could not open lock file");
  186.             exit(1);
  187.         }
  188. */
  189.  
  190.         writelog(START_MSG);
  191.  
  192.         ups_fd = open(ups_port,O_RDONLY,0);
  193.         if (stat<0) {
  194.             perror("cant open port");
  195.             exit(1);
  196.         }
  197.         /* get old bits first time */
  198.         stat = ioctl(ups_fd,TIOCMGET,&oldbits);
  199.         while (1) {
  200.  
  201.             stat = ioctl(ups_fd,TIOCMGET,&modembits);
  202.             if (modembits!=oldbits) {
  203.                 
  204.                 if (state==UPS_LINE) {
  205.                     state = UPS_BATTERY;
  206.                 } else {
  207.                     state = UPS_LINE;
  208.                 }
  209.  
  210.                 switch(state) {
  211.  
  212.                 case UPS_LINE :
  213.                     writelog(ONLINE_MSG);
  214.                     writeall(ups_rest);
  215.                     alarm(0);
  216.  
  217.                     break;
  218.  
  219.                 case UPS_BATTERY :
  220.                     writelog(BATTERY_MSG);
  221.                     writeall(ups_fail);
  222.                     alarm(ups_time * SECS_PER_MIN);
  223.                     break;
  224.  
  225.                 }
  226.                 oldbits = modembits;
  227.             }
  228.  
  229.             sleep(interval);
  230.         }
  231.         
  232.  
  233.  
  234.         close(log_fd);
  235.         close(ups_fd);
  236.  
  237.     } else {
  238.  
  239.         printf("process forked\n");
  240.     }
  241. }
  242.  
  243. /*
  244. **    s i g c a t c h
  245. **
  246. **    catch termination signal
  247. */
  248. void
  249. sigcatch()
  250. {
  251.     writelog(TERM_MSG);
  252.  
  253.     close(log_fd);
  254.     close(ups_fd);
  255.  
  256.  
  257.     exit(1);
  258. }
  259.  
  260. /*
  261. **    w r i t e l o g
  262. **
  263. **    write message to the UPS log file
  264. */
  265. void
  266. writelog(msg)
  267. char   *msg;
  268. {
  269.     time_t  ticks;
  270.     char   *p, *ct;
  271.     char    msg_buf[80];
  272.     char     *strrchr();
  273.  
  274.     time(&ticks);
  275.     ct = ctime(&ticks);
  276.  
  277.     /* find newline in buffer */
  278.     if ((p = strrchr(ct, '\n')) != NULL)
  279.         *p = NULL;    /* and zap it */
  280.  
  281.     sprintf(msg_buf, "%s -- %s\n", ct, msg);
  282.     write(log_fd, msg_buf, strlen(msg_buf));
  283. }
  284.  
  285. /*
  286. **    w r i t e a l l
  287. **
  288. **    write to all users
  289. */
  290. void
  291. writeall(fn)
  292. char   *fn;
  293. {
  294.     struct stat st;
  295.     void    attach();
  296.  
  297.     /* message file must exist */
  298.     if (stat(fn, &st) == ERR)
  299.         return;
  300.  
  301.     /* and must be a regular file */
  302.     if ((st.st_mode & S_IFMT) != S_IFREG)
  303.         return;
  304.  
  305.     if (!fork()) {
  306.  
  307.         attach(CONSOLE);
  308.  
  309.         /* write message file to users */
  310.         execlp(WALL, WALL, fn, NULL);
  311.     }
  312. }
  313.  
  314. /*
  315. **    s h u t d o w n
  316. **
  317. **    shutdown the system
  318. */
  319. void
  320. shutdown()
  321. {
  322.     void    attach();
  323.  
  324.     writelog(SHUTDOWN_MSG);
  325.  
  326.     close(ups_log);
  327.     close(ups_port);
  328.  
  329.     if (!fork()) {
  330.  
  331.         attach(CONSOLE);
  332.  
  333.         chdir(ROOT);
  334.  
  335.         /* execute shutdown command */
  336.         execlp(SH, SH, ups_shut, NULL);
  337.     }
  338. }
  339.  
  340. /*
  341. **    a t t a c h
  342. **
  343. **    attach standard i/o to a device
  344. */
  345. void
  346. attach(dev)
  347. char   *dev;
  348. {
  349.     int     fd;
  350.  
  351.     /* close standard files */
  352.     close(0);        /* stdin */
  353.     close(1);        /* stdout */
  354.     close(2);        /* stderr */
  355.  
  356.     /* attach stdin to named device */
  357.     if ((fd = open(dev, O_RDWR)) == ERR)
  358.         exit(1);
  359.     dup(fd);        /* and stdout */
  360.     dup(fd);        /* and stderr */
  361. }
  362.  
  363. /*
  364. **    b a s e n a m e
  365. **
  366. **    remove absolute path from filename
  367. **
  368. */
  369. char   *
  370. basename(s)
  371. char   *s;
  372. {
  373.     register char *p;
  374.  
  375.     /* point to char after last '/' */
  376.     if ((p = strrchr(s, '/')) != NULL)
  377.         return (++p);
  378.  
  379.     return (s);
  380. }
  381.  
  382. /*
  383. **    v e r s i o n
  384. **
  385. **    display program version
  386. */
  387. void
  388. version(s)
  389. char   *s;
  390. {
  391.     char   *basename();
  392.  
  393.     /* display version in foreground */
  394.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  395.         fprintf(stderr, "%s release %s version %d.%d patchlevel %d\n",
  396.             basename(s), RELEASE_DATE, RELEASE, REVISION,
  397.             PATCHLEVEL);
  398. }
  399.  
  400. /*
  401. **    u s a g e
  402. **
  403. **    display program usage
  404. */
  405. void
  406. usage(s)
  407. char   *s;
  408. {
  409.     char   *basename();
  410.  
  411.     fprintf(stderr, "usage: %s [-d tty][-c cmd][-l file][-f file][-r file][-t min]\n", basename(s));
  412.     fprintf(stderr, "\t-d tty\t\tpathname of UPS device\n");
  413.     fprintf(stderr, "\t-c cmd\t\tpathname of shutdown command\n");
  414.     fprintf(stderr, "\t-l file\t\tpathname of UPS log file\n");
  415.     fprintf(stderr, "\t-f file\t\tpathname of UPS fail message file\n");
  416.     fprintf(stderr, "\t-r file\t\tpathname of UPS restore message file\n");
  417.     fprintf(stderr, "\t-t min\t\tdelay time in minutes\n");
  418. }
  419.