take responsibility for reseting window size when first opening pty;
[unix-history] / usr / src / libexec / comsat / comsat.c
CommitLineData
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
8char 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 14static 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
36int debug = 0;
37#define dprintf if (debug) printf
6ae77bb7 38
a591911b 39struct sockaddr_in sin = { AF_INET };
9afb4b8a
BJ
40extern errno;
41
ba3dfff4 42char hostname[32];
4c9b3acd 43struct utmp *utmp = NULL;
6ae77bb7
BJ
44int nutmp;
45int uf;
4c9b3acd
JB
46unsigned utmpmtime = 0; /* last modification time for utmp */
47unsigned utmpsize = 0; /* last malloced size for utmp */
6ae77bb7 48int onalrm();
ba3dfff4 49int reapchildren();
bb933cc2 50long lastmsgtime;
4c9b3acd 51char *malloc(), *realloc();
6ae77bb7 52
bb933cc2 53#define MAXIDLE 120
6ae77bb7
BJ
54#define NAMLEN (sizeof (uts[0].ut_name) + 1)
55
56main(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
102reapchildren()
103{
104
105 while (wait3((struct wait *)0, WNOHANG, (struct rusage *)0) > 0)
106 ;
107}
108
6ae77bb7
BJ
109onalrm()
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
138mailfor(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 161char *cr;
6ae77bb7
BJ
162
163notify(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, &gttybuf);
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
197jkfprintf(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}