home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / libexec / comsat / comsat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  7.0 KB  |  266 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)comsat.c    5.24 (Berkeley) 2/25/91";
  42. #endif /* not lint */
  43.  
  44. #include <sys/param.h>
  45. #include <sys/socket.h>
  46. #include <sys/stat.h>
  47. #include <sys/file.h>
  48. #include <sys/wait.h>
  49.  
  50. #include <netinet/in.h>
  51.  
  52. #include <stdio.h>
  53. #include <sgtty.h>
  54. #include <utmp.h>
  55. #include <signal.h>
  56. #include <errno.h>
  57. #include <netdb.h>
  58. #include <syslog.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61. #include <paths.h>
  62.  
  63. int    debug = 0;
  64. #define    dsyslog    if (debug) syslog
  65.  
  66. #define MAXIDLE    120
  67.  
  68. char    hostname[MAXHOSTNAMELEN];
  69. struct    utmp *utmp = NULL;
  70. time_t    lastmsgtime, time();
  71. int    nutmp, uf;
  72.  
  73. /* ARGSUSED */
  74. main(argc, argv)
  75.     int argc;
  76.     char **argv;
  77. {
  78.     extern int errno;
  79.     register int cc;
  80.     char msgbuf[100];
  81.     struct sockaddr_in from;
  82.     int fromlen;
  83.     void onalrm(), reapchildren();
  84.  
  85.     /* verify proper invocation */
  86.     fromlen = sizeof(from);
  87.     if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) {
  88.         (void)fprintf(stderr,
  89.             "comsat: getsockname: %s.\n", strerror(errno));
  90.         exit(1);
  91.     }
  92.     openlog("comsat", LOG_PID, LOG_DAEMON);
  93.     if (chdir(_PATH_MAILDIR)) {
  94.         syslog(LOG_ERR, "chdir: %s: %m", _PATH_MAILDIR);
  95.         exit(1);
  96.     }
  97.     if ((uf = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
  98.         syslog(LOG_ERR, ".main: %s: %m", _PATH_UTMP);
  99.         (void) recv(0, msgbuf, sizeof(msgbuf) - 1, 0);
  100.         exit(1);
  101.     }
  102.     (void)time(&lastmsgtime);
  103.     (void)gethostname(hostname, sizeof(hostname));
  104.     onalrm();
  105.     (void)signal(SIGALRM, onalrm);
  106.     (void)signal(SIGTTOU, SIG_IGN);
  107.     (void)signal(SIGCHLD, reapchildren);
  108.     for (;;) {
  109.         cc = recv(0, msgbuf, sizeof(msgbuf) - 1, 0);
  110.         if (cc <= 0) {
  111.             if (errno != EINTR)
  112.                 sleep(1);
  113.             errno = 0;
  114.             continue;
  115.         }
  116.         if (!nutmp)        /* no one has logged in yet */
  117.             continue;
  118.         sigblock(sigmask(SIGALRM));
  119.         msgbuf[cc] = 0;
  120.         (void)time(&lastmsgtime);
  121.         mailfor(msgbuf);
  122.         sigsetmask(0L);
  123.     }
  124. }
  125.  
  126. void
  127. reapchildren()
  128. {
  129.     while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
  130. }
  131.  
  132. void
  133. onalrm()
  134. {
  135.     static u_int utmpsize;        /* last malloced size for utmp */
  136.     static u_int utmpmtime;        /* last modification time for utmp */
  137.     struct stat statbf;
  138.     off_t lseek();
  139.     char *malloc(), *realloc();
  140.  
  141.     if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE)
  142.         exit(0);
  143.     (void)alarm((u_int)15);
  144.     (void)fstat(uf, &statbf);
  145.     if (statbf.st_mtime > utmpmtime) {
  146.         utmpmtime = statbf.st_mtime;
  147.         if (statbf.st_size > utmpsize) {
  148.             utmpsize = statbf.st_size + 10 * sizeof(struct utmp);
  149.             if (utmp)
  150.                 utmp = (struct utmp *)realloc((char *)utmp, utmpsize);
  151.             else
  152.                 utmp = (struct utmp *)malloc(utmpsize);
  153.             if (!utmp) {
  154.                 syslog(LOG_ERR, "malloc failed");
  155.                 exit(1);
  156.             }
  157.         }
  158.         (void)lseek(uf, 0L, L_SET);
  159.         nutmp = read(uf, utmp, (int)statbf.st_size)/sizeof(struct utmp);
  160.     }
  161. }
  162.  
  163. mailfor(name)
  164.     char *name;
  165. {
  166.     register struct utmp *utp = &utmp[nutmp];
  167.     register char *cp;
  168.     off_t offset;
  169.  
  170.     if (!(cp = index(name, '@')))
  171.         return;
  172.     *cp = '\0';
  173.     offset = atoi(cp + 1);
  174.     while (--utp >= utmp)
  175.         if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name)))
  176.             notify(utp, offset);
  177. }
  178.  
  179. static char *cr;
  180.  
  181. notify(utp, offset)
  182.     register struct utmp *utp;
  183.     off_t offset;
  184. {
  185.     static char tty[20] = _PATH_DEV;
  186.     struct sgttyb gttybuf;
  187.     struct stat stb;
  188.     FILE *tp;
  189.     char name[sizeof(utmp[0].ut_name) + 1];
  190.  
  191.     (void)strncpy(tty + sizeof(_PATH_DEV) - 1, utp->ut_line,
  192.         sizeof(utp->ut_line));
  193.     if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) {
  194.         dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty);
  195.         return;
  196.     }
  197.     dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty);
  198.     if (fork())
  199.         return;
  200.     (void)signal(SIGALRM, SIG_DFL);
  201.     (void)alarm((u_int)30);
  202.     if ((tp = fopen(tty, "w")) == NULL) {
  203.         dsyslog(LOG_ERR, "fopen of tty %s failed", tty);
  204.         _exit(-1);
  205.     }
  206.     (void)ioctl(fileno(tp), TIOCGETP, >tybuf);
  207.     cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ?
  208.         "\n" : "\n\r";
  209.     (void)strncpy(name, utp->ut_name, sizeof(utp->ut_name));
  210.     name[sizeof(name) - 1] = '\0';
  211.     (void)fprintf(tp, "%s\007New mail for %s@%.*s\007 has arrived:%s----%s",
  212.         cr, name, sizeof(hostname), hostname, cr, cr);
  213.     jkfprintf(tp, name, offset);
  214.     (void)fclose(tp);
  215.     _exit(0);
  216. }
  217.  
  218. jkfprintf(tp, name, offset)
  219.     register FILE *tp;
  220.     char name[];
  221.     off_t offset;
  222. {
  223.     register char *cp, ch;
  224.     register FILE *fi;
  225.     register int linecnt, charcnt, inheader;
  226.     char line[BUFSIZ];
  227.  
  228.     if ((fi = fopen(name, "r")) == NULL)
  229.         return;
  230.     (void)fseek(fi, offset, L_SET);
  231.     /*
  232.      * Print the first 7 lines or 560 characters of the new mail
  233.      * (whichever comes first).  Skip header crap other than
  234.      * From, Subject, To, and Date.
  235.      */
  236.     linecnt = 7;
  237.     charcnt = 560;
  238.     inheader = 1;
  239.     while (fgets(line, sizeof(line), fi) != NULL) {
  240.         if (inheader) {
  241.             if (line[0] == '\n') {
  242.                 inheader = 0;
  243.                 continue;
  244.             }
  245.             if (line[0] == ' ' || line[0] == '\t' ||
  246.                 strncmp(line, "From:", 5) &&
  247.                 strncmp(line, "Subject:", 8))
  248.                 continue;
  249.         }
  250.         if (linecnt <= 0 || charcnt <= 0) {
  251.             (void)fprintf(tp, "...more...%s", cr);
  252.             return;
  253.         }
  254.         /* strip weird stuff so can't trojan horse stupid terminals */
  255.         for (cp = line; (ch = *cp) && ch != '\n'; ++cp, --charcnt) {
  256.             ch = toascii(ch);
  257.             if (!isprint(ch) && !isspace(ch))
  258.                 ch |= 0x40;
  259.             (void)fputc(ch, tp);
  260.         }
  261.         (void)fputs(cr, tp);
  262.         --linecnt;
  263.     }
  264.     (void)fprintf(tp, "----%s\n", cr);
  265. }
  266.