home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Other / upsd / ups_folder / funcs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-28  |  6.6 KB  |  418 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.     writelog(START_MSG);
  149.  
  150.  
  151.  
  152.     if (!fork()) {
  153.  
  154.         /* close standard files */
  155.  
  156.         close(0);    /* stdin */
  157.         close(1);    /* stdout */
  158.         close(2);    /* stderr */
  159.  
  160.  
  161.         setpgrp();    /* disassociate from terminal */
  162.  
  163.         /* ignore interrupts */
  164.         signal(SIGHUP, SIG_IGN);
  165.         signal(SIGINT, SIG_IGN);
  166.         signal(SIGQUIT, SIG_IGN);
  167.  
  168.         /* catch termination signal */
  169.         signal(SIGTERM, sigcatch);
  170.  
  171.         /* and shutdown on alarm */
  172.         signal(SIGALRM, shutdown);
  173.  
  174.         /* open log file for append */
  175.         if ((log_fd = open(ups_log, LOG_FLAGS, LOG_PERMS)) == ERR) {
  176.             perror("could not open log file");
  177.             exit(1);
  178.         }
  179.  
  180.  
  181.         /* and advisory lock it */
  182. /*
  183.         if (lockf(log_fd, F_TLOCK, 0L) == ERR) {
  184.             perror("could not open lock file");
  185.             exit(1);
  186.         }
  187. */
  188.  
  189.         writelog(START_MSG);
  190.  
  191.         ups_fd = open(ups_port,O_RDONLY,0);
  192.         if (stat<0) {
  193.             perror("cant open port");
  194.             exit(1);
  195.         }
  196.         /* get old bits first time */
  197.         stat = ioctl(ups_fd,TIOCMGET,&oldbits);
  198.         while (1) {
  199.  
  200.             stat = ioctl(ups_fd,TIOCMGET,&modembits);
  201.             if (modembits!=oldbits) {
  202.                 
  203.                 if (state==UPS_LINE) {
  204.                     state = UPS_BATTERY;
  205.                 } else {
  206.                     state = UPS_LINE;
  207.                 }
  208.  
  209.                 switch(state) {
  210.  
  211.                 case UPS_LINE :
  212.                     writelog(ONLINE_MSG);
  213.                     writeall(ups_rest);
  214.                     alarm(0);
  215.  
  216.                     break;
  217.  
  218.                 case UPS_BATTERY :
  219.                     writelog(BATTERY_MSG);
  220.                     writeall(ups_fail);
  221.                     alarm(ups_time * SECS_PER_MIN/4);
  222.                     break;
  223.  
  224.                 }
  225.                 oldbits = modembits;
  226.             }
  227.  
  228.             sleep(interval);
  229.         }
  230.         
  231.  
  232.  
  233.         close(log_fd);
  234.         close(ups_fd);
  235.  
  236.     } else {
  237.  
  238.         printf("process forked\n");
  239.     }
  240. }
  241.  
  242. /*
  243. **    s i g c a t c h
  244. **
  245. **    catch termination signal
  246. */
  247. void
  248. sigcatch()
  249. {
  250.     writelog(TERM_MSG);
  251.  
  252.     close(log_fd);
  253.     close(ups_fd);
  254.  
  255.  
  256.     exit(1);
  257. }
  258.  
  259. /*
  260. **    w r i t e l o g
  261. **
  262. **    write message to the UPS log file
  263. */
  264. void
  265. writelog(msg)
  266. char   *msg;
  267. {
  268.     time_t  ticks;
  269.     char   *p, *ct;
  270.     char    msg_buf[80];
  271.     char     *strrchr();
  272.  
  273.     time(&ticks);
  274.     ct = ctime(&ticks);
  275.  
  276.     /* find newline in buffer */
  277.     if ((p = strrchr(ct, '\n')) != NULL)
  278.         *p = NULL;    /* and zap it */
  279.  
  280.     sprintf(msg_buf, "%s -- %s\n", ct, msg);
  281.     write(log_fd, msg_buf, strlen(msg_buf));
  282. }
  283.  
  284. /*
  285. **    w r i t e a l l
  286. **
  287. **    write to all users
  288. */
  289. void
  290. writeall(fn)
  291. char   *fn;
  292. {
  293.     struct stat st;
  294.     void    attach();
  295.  
  296.     /* message file must exist */
  297.     if (stat(fn, &st) == ERR)
  298.         return;
  299.  
  300.     /* and must be a regular file */
  301.     if ((st.st_mode & S_IFMT) != S_IFREG)
  302.         return;
  303.  
  304.     if (!fork()) {
  305.  
  306.         attach(CONSOLE);
  307.  
  308.         /* write message file to users */
  309.         execlp(WALL, WALL, fn, NULL);
  310.     }
  311. }
  312.  
  313. /*
  314. **    s h u t d o w n
  315. **
  316. **    shutdown the system
  317. */
  318. void
  319. shutdown()
  320. {
  321.     void    attach();
  322.  
  323.     writelog(SHUTDOWN_MSG);
  324.  
  325.     close(ups_log);
  326.     close(ups_port);
  327.  
  328.     if (!fork()) {
  329.  
  330.         attach(CONSOLE);
  331.  
  332.         chdir(ROOT);
  333.  
  334.         /* execute shutdown command */
  335.         execlp(SH, SH, ups_shut, NULL);
  336.     }
  337. }
  338.  
  339. /*
  340. **    a t t a c h
  341. **
  342. **    attach standard i/o to a device
  343. */
  344. void
  345. attach(dev)
  346. char   *dev;
  347. {
  348.     int     fd;
  349.  
  350.     /* close standard files */
  351.     close(0);        /* stdin */
  352.     close(1);        /* stdout */
  353.     close(2);        /* stderr */
  354.  
  355.     /* attach stdin to named device */
  356.     if ((fd = open(dev, O_RDWR)) == ERR)
  357.         exit(1);
  358.     dup(fd);        /* and stdout */
  359.     dup(fd);        /* and stderr */
  360. }
  361.  
  362. /*
  363. **    b a s e n a m e
  364. **
  365. **    remove absolute path from filename
  366. **
  367. */
  368. char   *
  369. basename(s)
  370. char   *s;
  371. {
  372.     register char *p;
  373.  
  374.     /* point to char after last '/' */
  375.     if ((p = strrchr(s, '/')) != NULL)
  376.         return (++p);
  377.  
  378.     return (s);
  379. }
  380.  
  381. /*
  382. **    v e r s i o n
  383. **
  384. **    display program version
  385. */
  386. void
  387. version(s)
  388. char   *s;
  389. {
  390.     char   *basename();
  391.  
  392.     /* display version in foreground */
  393.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  394.         fprintf(stderr, "%s release %s version %d.%d patchlevel %d\n",
  395.             basename(s), RELEASE_DATE, RELEASE, REVISION,
  396.             PATCHLEVEL);
  397. }
  398.  
  399. /*
  400. **    u s a g e
  401. **
  402. **    display program usage
  403. */
  404. void
  405. usage(s)
  406. char   *s;
  407. {
  408.     char   *basename();
  409.  
  410.     fprintf(stderr, "usage: %s [-d tty][-c cmd][-l file][-f file][-r file][-t min]\n", basename(s));
  411.     fprintf(stderr, "\t-d tty\t\tpathname of UPS device\n");
  412.     fprintf(stderr, "\t-c cmd\t\tpathname of shutdown command\n");
  413.     fprintf(stderr, "\t-l file\t\tpathname of UPS log file\n");
  414.     fprintf(stderr, "\t-f file\t\tpathname of UPS fail message file\n");
  415.     fprintf(stderr, "\t-r file\t\tpathname of UPS restore message file\n");
  416.     fprintf(stderr, "\t-t min\t\tdelay time in minutes\n");
  417. }
  418.