dynamically configure utmp size
[unix-history] / usr / src / libexec / comsat / comsat.c
CommitLineData
ebc8086f 1#ifndef lint
4c9b3acd 2static 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
24int debug = 0;
25#define dprintf if (debug) printf
6ae77bb7 26
a591911b 27struct sockaddr_in sin = { AF_INET };
9afb4b8a
BJ
28extern errno;
29
ba3dfff4 30char hostname[32];
4c9b3acd 31struct utmp *utmp = NULL;
6ae77bb7
BJ
32int nutmp;
33int uf;
4c9b3acd
JB
34unsigned utmpmtime = 0; /* last modification time for utmp */
35unsigned utmpsize = 0; /* last malloced size for utmp */
6ae77bb7 36int onalrm();
ba3dfff4 37int reapchildren();
bb933cc2 38long lastmsgtime;
4c9b3acd 39char *malloc(), *realloc();
6ae77bb7 40
bb933cc2 41#define MAXIDLE 120
6ae77bb7
BJ
42#define NAMLEN (sizeof (uts[0].ut_name) + 1)
43
44main(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
90reapchildren()
91{
92
93 while (wait3((struct wait *)0, WNOHANG, (struct rusage *)0) > 0)
94 ;
95}
96
6ae77bb7
BJ
97onalrm()
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
126mailfor(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 149char *cr;
6ae77bb7
BJ
150
151notify(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, &gttybuf);
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
185jkfprintf(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}