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