Commit | Line | Data |
---|---|---|
3b86b0f6 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
7 | #ifndef lint | |
8 | char copyright[] = | |
9 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
10 | All rights reserved.\n"; | |
11 | #endif not lint | |
12 | ||
ebc8086f | 13 | #ifndef lint |
076ae92c | 14 | static char sccsid[] = "@(#)comsat.c 5.4 (Berkeley) %G%"; |
3b86b0f6 | 15 | #endif not lint |
ebc8086f SL |
16 | |
17 | #include <sys/types.h> | |
18 | #include <sys/socket.h> | |
a7b24fe9 SL |
19 | #include <sys/stat.h> |
20 | #include <sys/wait.h> | |
ba3dfff4 | 21 | #include <sys/file.h> |
ebc8086f SL |
22 | |
23 | #include <netinet/in.h> | |
9afb4b8a | 24 | |
6ae77bb7 | 25 | #include <stdio.h> |
6ae77bb7 BJ |
26 | #include <sgtty.h> |
27 | #include <utmp.h> | |
6ae77bb7 | 28 | #include <signal.h> |
9afb4b8a | 29 | #include <errno.h> |
ebc8086f | 30 | #include <netdb.h> |
c8ee8ed6 | 31 | #include <syslog.h> |
6ae77bb7 BJ |
32 | |
33 | /* | |
34 | * comsat | |
35 | */ | |
65a66573 SL |
36 | int debug = 0; |
37 | #define dprintf if (debug) printf | |
6ae77bb7 | 38 | |
a591911b | 39 | struct sockaddr_in sin = { AF_INET }; |
9afb4b8a BJ |
40 | extern errno; |
41 | ||
ba3dfff4 | 42 | char hostname[32]; |
4c9b3acd | 43 | struct utmp *utmp = NULL; |
6ae77bb7 BJ |
44 | int nutmp; |
45 | int uf; | |
4c9b3acd JB |
46 | unsigned utmpmtime = 0; /* last modification time for utmp */ |
47 | unsigned utmpsize = 0; /* last malloced size for utmp */ | |
6ae77bb7 | 48 | int onalrm(); |
ba3dfff4 | 49 | int reapchildren(); |
bb933cc2 | 50 | long lastmsgtime; |
4c9b3acd | 51 | char *malloc(), *realloc(); |
6ae77bb7 | 52 | |
bb933cc2 | 53 | #define MAXIDLE 120 |
6ae77bb7 BJ |
54 | #define NAMLEN (sizeof (uts[0].ut_name) + 1) |
55 | ||
56 | main(argc, argv) | |
bb933cc2 MK |
57 | int argc; |
58 | char *argv[]; | |
6ae77bb7 | 59 | { |
bb933cc2 | 60 | register int cc; |
6ae77bb7 | 61 | char buf[BUFSIZ]; |
bb933cc2 MK |
62 | char msgbuf[100]; |
63 | struct sockaddr_in from; | |
64 | int fromlen; | |
65 | ||
66 | /* verify proper invocation */ | |
67 | fromlen = sizeof (from); | |
68 | if (getsockname(0, &from, &fromlen) < 0) { | |
69 | fprintf(stderr, "%s: ", argv[0]); | |
70 | perror("getsockname"); | |
71 | _exit(1); | |
ebc8086f | 72 | } |
6ae77bb7 | 73 | chdir("/usr/spool/mail"); |
bb933cc2 | 74 | if ((uf = open("/etc/utmp",0)) < 0) { |
076ae92c | 75 | openlog("comsat", 0, LOG_DAEMON); |
c8ee8ed6 | 76 | syslog(LOG_ERR, "/etc/utmp: %m"); |
bb933cc2 MK |
77 | (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); |
78 | exit(1); | |
79 | } | |
80 | lastmsgtime = time(0); | |
ba3dfff4 | 81 | gethostname(hostname, sizeof (hostname)); |
6ae77bb7 | 82 | onalrm(); |
8daa86a6 SL |
83 | signal(SIGALRM, onalrm); |
84 | signal(SIGTTOU, SIG_IGN); | |
ba3dfff4 | 85 | signal(SIGCHLD, reapchildren); |
9afb4b8a | 86 | for (;;) { |
bb933cc2 | 87 | cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); |
9afb4b8a BJ |
88 | if (cc <= 0) { |
89 | if (errno != EINTR) | |
90 | sleep(1); | |
91 | errno = 0; | |
92 | continue; | |
6ae77bb7 | 93 | } |
911d33c3 | 94 | sigblock(sigmask(SIGALRM)); |
9afb4b8a | 95 | msgbuf[cc] = 0; |
bb933cc2 | 96 | lastmsgtime = time(0); |
9afb4b8a | 97 | mailfor(msgbuf); |
bb933cc2 | 98 | sigsetmask(0); |
6ae77bb7 BJ |
99 | } |
100 | } | |
101 | ||
ba3dfff4 SL |
102 | reapchildren() |
103 | { | |
104 | ||
105 | while (wait3((struct wait *)0, WNOHANG, (struct rusage *)0) > 0) | |
106 | ; | |
107 | } | |
108 | ||
6ae77bb7 BJ |
109 | onalrm() |
110 | { | |
111 | struct stat statbf; | |
6ae77bb7 | 112 | |
bb933cc2 | 113 | if (time(0) - lastmsgtime >= MAXIDLE) |
c8ee8ed6 | 114 | exit(0); |
6ae77bb7 BJ |
115 | dprintf("alarm\n"); |
116 | alarm(15); | |
c8ee8ed6 | 117 | fstat(uf, &statbf); |
6ae77bb7 BJ |
118 | if (statbf.st_mtime > utmpmtime) { |
119 | dprintf(" changed\n"); | |
120 | utmpmtime = statbf.st_mtime; | |
4c9b3acd JB |
121 | if (statbf.st_size > utmpsize) { |
122 | utmpsize = statbf.st_size + 10 * sizeof(struct utmp); | |
123 | if (utmp) | |
124 | utmp = (struct utmp *)realloc(utmp, utmpsize); | |
125 | else | |
126 | utmp = (struct utmp *)malloc(utmpsize); | |
127 | if (! utmp) { | |
128 | dprintf("malloc failed\n"); | |
129 | exit(1); | |
130 | } | |
131 | } | |
6ae77bb7 | 132 | lseek(uf, 0, 0); |
4c9b3acd | 133 | nutmp = read(uf,utmp,statbf.st_size)/sizeof(struct utmp); |
6ae77bb7 BJ |
134 | } else |
135 | dprintf(" ok\n"); | |
136 | } | |
137 | ||
138 | mailfor(name) | |
139 | char *name; | |
140 | { | |
141 | register struct utmp *utp = &utmp[nutmp]; | |
142 | register char *cp; | |
143 | char *rindex(); | |
144 | int offset; | |
145 | ||
146 | dprintf("mailfor %s\n", name); | |
147 | cp = name; | |
148 | while (*cp && *cp != '@') | |
149 | cp++; | |
150 | if (*cp == 0) { | |
151 | dprintf("bad format\n"); | |
152 | return; | |
153 | } | |
154 | *cp = 0; | |
155 | offset = atoi(cp+1); | |
156 | while (--utp >= utmp) | |
157 | if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) | |
ba3dfff4 | 158 | notify(utp, offset); |
6ae77bb7 BJ |
159 | } |
160 | ||
c8ee8ed6 | 161 | char *cr; |
6ae77bb7 BJ |
162 | |
163 | notify(utp, offset) | |
164 | register struct utmp *utp; | |
165 | { | |
072d8b0d | 166 | FILE *tp; |
6ae77bb7 | 167 | struct sgttyb gttybuf; |
072d8b0d | 168 | char tty[20], name[sizeof (utmp[0].ut_name) + 1]; |
6ae77bb7 BJ |
169 | struct stat stb; |
170 | ||
171 | strcpy(tty, "/dev/"); | |
172 | strncat(tty, utp->ut_line, sizeof(utp->ut_line)); | |
173 | dprintf("notify %s on %s\n", utp->ut_name, tty); | |
174 | if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { | |
175 | dprintf("wrong mode\n"); | |
176 | return; | |
177 | } | |
072d8b0d | 178 | if (fork()) |
c8ee8ed6 | 179 | return; |
072d8b0d RC |
180 | signal(SIGALRM, SIG_DFL); |
181 | alarm(30); | |
182 | if ((tp = fopen(tty,"w")) == 0) { | |
183 | dprintf("fopen failed\n"); | |
184 | exit(-1); | |
c8ee8ed6 | 185 | } |
072d8b0d | 186 | ioctl(fileno(tp), TIOCGETP, >tybuf); |
3e00400b | 187 | cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? "" : "\r"; |
6ae77bb7 | 188 | strncpy(name, utp->ut_name, sizeof (utp->ut_name)); |
ba3dfff4 | 189 | name[sizeof (name) - 1] = '\0'; |
072d8b0d | 190 | fprintf(tp,"%s\n\007New mail for %s@%s\007 has arrived:%s\n", |
65a66573 | 191 | cr, name, hostname, cr); |
072d8b0d RC |
192 | fprintf(tp,"----%s\n", cr); |
193 | jkfprintf(tp, name, offset); | |
ba3dfff4 | 194 | exit(0); |
6ae77bb7 BJ |
195 | } |
196 | ||
072d8b0d RC |
197 | jkfprintf(tp, name, offset) |
198 | register FILE *tp; | |
6ae77bb7 BJ |
199 | { |
200 | register FILE *fi; | |
201 | register int linecnt, charcnt; | |
65a66573 | 202 | char line[BUFSIZ]; |
77d16cad | 203 | int inheader; |
6ae77bb7 | 204 | |
072d8b0d RC |
205 | dprintf("HERE %s's mail starting at %d\n", |
206 | name, offset); | |
207 | if ((fi = fopen(name,"r")) == NULL) { | |
6ae77bb7 BJ |
208 | dprintf("Cant read the mail\n"); |
209 | return; | |
210 | } | |
ba3dfff4 | 211 | fseek(fi, offset, L_SET); |
6ae77bb7 | 212 | /* |
65a66573 SL |
213 | * Print the first 7 lines or 560 characters of the new mail |
214 | * (whichever comes first). Skip header crap other than | |
77d16cad | 215 | * From, Subject, To, and Date. |
6ae77bb7 | 216 | */ |
65a66573 SL |
217 | linecnt = 7; |
218 | charcnt = 560; | |
77d16cad | 219 | inheader = 1; |
65a66573 SL |
220 | while (fgets(line, sizeof (line), fi) != NULL) { |
221 | register char *cp; | |
222 | char *index(); | |
77d16cad | 223 | int cnt; |
6ae77bb7 | 224 | |
65a66573 | 225 | if (linecnt <= 0 || charcnt <= 0) { |
072d8b0d | 226 | fprintf(tp,"...more...%s\n", cr); |
8daa86a6 | 227 | return; |
6ae77bb7 | 228 | } |
77d16cad SL |
229 | if (strncmp(line, "From ", 5) == 0) |
230 | continue; | |
231 | if (inheader && (line[0] == ' ' || line[0] == '\t')) | |
232 | continue; | |
65a66573 | 233 | cp = index(line, ':'); |
77d16cad SL |
234 | if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp)) |
235 | inheader = 0; | |
236 | else | |
237 | cnt = cp - line; | |
238 | if (inheader && | |
239 | strncmp(line, "Date", cnt) && | |
240 | strncmp(line, "From", cnt) && | |
241 | strncmp(line, "Subject", cnt) && | |
242 | strncmp(line, "To", cnt)) | |
65a66573 SL |
243 | continue; |
244 | cp = index(line, '\n'); | |
245 | if (cp) | |
246 | *cp = '\0'; | |
072d8b0d | 247 | fprintf(tp,"%s%s\n", line, cr); |
65a66573 | 248 | linecnt--, charcnt -= strlen(line); |
6ae77bb7 | 249 | } |
072d8b0d | 250 | fprintf(tp,"----%s\n", cr); |
6ae77bb7 | 251 | } |