source: trunk/athena/bin/write/write.c @ 497

Revision 497, 7.6 KB checked in by ens, 37 years ago (diff)
Merged in spook's fixes so write doesn't get ctrl-z'd by accident
Line 
1/*
2 *      $Source: /afs/dev.mit.edu/source/repository/athena/bin/write/write.c,v $
3 *      $Header: /afs/dev.mit.edu/source/repository/athena/bin/write/write.c,v 1.4 1987-07-03 17:52:23 ens Exp $
4 */
5
6#ifndef lint
7static char *rcsid_write_c = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/write/write.c,v 1.4 1987-07-03 17:52:23 ens Exp $";
8#endif lint
9
10#ifndef lint
11static char *sccsid = "@(#)write.c      4.13 3/13/86";
12#endif
13/*
14 * write to another user
15 */
16
17#include <stdio.h>
18#include <ctype.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <signal.h>
22#include <utmp.h>
23#include <sys/time.h>
24#include        <sys/socket.h>
25#include        <netinet/in.h>
26#include        <netdb.h>
27#include <pwd.h>
28
29#define NMAX    sizeof(ubuf.ut_name)
30#define LMAX    sizeof(ubuf.ut_line)
31
32char    *strcat();
33char    *strcpy();
34struct  utmp ubuf;
35int     signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
36char    mebuf[NMAX + 1] = "???";
37char    *me;
38char    *him;
39int     netme = 0;
40int     nethim = 0;
41char    *mytty;
42char    histty[32];
43char    ttybuf[32];
44char    *histtya;
45char    myhost[32];
46char    *hishost;
47struct hostent *hp;
48struct servent *sp;
49struct sockaddr_in sin;
50int     fds;
51char    buf[128];
52struct passwd *pwdent;
53FILE    *tf;
54int     logcnt;
55char    *ttyname();
56char    *rindex();
57int     eof();
58int     timout();
59char    *getenv();
60
61main(argc, argv)
62        int argc;
63        char *argv[];
64{
65        struct stat stbuf;
66        register i;
67        register FILE *uf;
68        int c1, c2;
69        long clock = time(0);
70        int suser = getuid() == 0;
71        int nomesg = 0;
72        struct tm *localtime();
73        struct tm *localclock = localtime( &clock );
74
75        me = mebuf;
76        if ((argc > 3) && (getuid() == 0) &&
77            (strcmp("-f", argv[1]) == 0) &&
78            (mytty = rindex(argv[2], '@'))) {
79                me = argv[2];
80                *mytty++ = '\0';
81                netme = 1;
82                argc -= 2;
83                argv += 2;
84        }
85        if (argc < 2 || argc > 3) {
86                fprintf(stderr, "Usage: write user [ttyname]\n");
87                exit(1);
88        }
89        him = argv[1];
90        if ((!netme) && (hishost = rindex(him, '@'))) {
91                *hishost++ = '\0';
92                hp = gethostbyname(hishost);
93                if (hp == NULL) {
94                        static struct hostent def;
95                        static struct in_addr defaddr;
96                        static char namebuf[128];
97                        int inet_addr();
98
99                        defaddr.s_addr = inet_addr(hishost);
100                        if (defaddr.s_addr == -1) {
101                                printf("unknown host: %s\n", hishost);
102                                exit(1);
103                        }
104                        strcpy(namebuf, hishost);
105                        def.h_name = namebuf;
106                        def.h_addr = (char *)&defaddr;
107                        def.h_length = sizeof (struct in_addr);
108                        def.h_addrtype = AF_INET;
109                        def.h_aliases = 0;
110                        hp = &def;
111                }
112                nethim = 1;
113        }
114
115        if (argc == 3)
116                histtya = argv[2];
117        if ((uf = fopen("/etc/utmp", "r")) == NULL) {
118                perror("write: Can't open /etc/utmp");
119                if (histtya == 0)
120                        exit(10);
121                goto cont;
122        }
123        if (!netme) {
124            mytty = ttyname(2);
125            if (mytty == NULL) {
126                fprintf(stderr, "write: Can't find your tty\n");
127                exit(1);
128            }
129            if (stat(mytty, &stbuf) < 0) {
130                perror("write: Can't stat your tty");
131                exit(1);
132            }
133            if ((stbuf.st_mode&020) == 0) {
134                fprintf(stderr,
135                        "write: You have write permission turned off\n");
136                if (!suser)
137                  exit(1);
138            }
139            mytty = rindex(mytty, '/') + 1;
140        }
141        if (histtya) {
142                strcpy(histty, "/dev/");
143                strcat(histty, histtya);
144        }
145        while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) {
146                if (ubuf.ut_name[0] == '\0')
147                        continue;
148                if ((!netme) && strcmp(ubuf.ut_line, mytty)==0) {
149                        for (i=0; i<NMAX; i++) {
150                                c1 = ubuf.ut_name[i];
151                                if (c1 == ' ')
152                                        c1 = 0;
153                                me[i] = c1;
154                                if (c1 == 0)
155                                        break;
156                        }
157                }
158                if (nethim) goto nomat;
159                if (him[0] == '-' && him[1] == 0)
160                        goto nomat;
161                for (i=0; i<NMAX; i++) {
162                        c1 = him[i];
163                        c2 = ubuf.ut_name[i];
164                        if (c1 == 0)
165                                if (c2 == 0 || c2 == ' ')
166                                        break;
167                        if (c1 != c2)
168                                goto nomat;
169                }
170                if (histtya && strncmp(histtya, ubuf.ut_line,
171                    sizeof(ubuf.ut_line)))
172                        continue;
173                logcnt++;
174                if (histty[0]==0 || nomesg && histtya == 0) {
175                        strcpy(ttybuf, "/dev/");
176                        strcat(ttybuf, ubuf.ut_line);
177                        if (histty[0]==0)
178                                strcpy(histty, ttybuf);
179                        if (access(ttybuf, 0) < 0 || stat(ttybuf, &stbuf) < 0 ||
180                            (stbuf.st_mode&020) == 0)
181                                nomesg++;
182                        else {
183                                strcpy(histty, ttybuf);
184                                nomesg = 0;
185                        }
186                }
187        nomat:
188                ;
189        }
190        fclose(uf);
191        if (!nethim) {
192            if (logcnt==0) {
193                fprintf(stderr, "write: %s not logged in%s\n", him,
194                        histtya ? " on that tty" : "");
195                exit(1);
196            }
197            if (histtya==0 && logcnt > 1) {
198                fprintf(stderr,
199                        "write: %s logged in more than once ... writing to %s\n",
200                        him, histty+5);
201            }
202        }
203cont:
204        fclose(uf);
205        if((!netme) && (mebuf[0] == '?')) {
206            pwdent = getpwuid(getuid());
207            if (pwdent == NULL) {
208                printf("You don't exist. Go away.\n");
209                exit(-1);
210            }
211            strcpy(mebuf, pwdent->pw_name);
212        }
213        if (nethim) {
214                sp = getservbyname("write", "tcp");
215                if (sp == 0) {
216                        printf("tcp/write: unknown service\n");
217                        exit(1);
218                }
219                sin.sin_family = hp->h_addrtype;
220                bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
221                sin.sin_port = sp->s_port;
222                fds = socket(hp->h_addrtype, SOCK_STREAM, 0);
223                if (fds < 0) {
224                        perror("socket");
225                        exit(1);
226                }
227                if (connect(fds, (char *)&sin, sizeof (sin)) < 0) {
228                        perror("connect");
229                        close(fds);
230                        exit(1);
231                }
232
233                write(fds, me, strlen(me));
234                write(fds, "@", 1);
235                gethostname(myhost, sizeof (myhost));
236                write(fds, myhost, strlen(myhost));
237                write(fds, " ", 1);
238                write(fds, him, strlen(him));
239                if (histtya) {
240                        write(fds, " ", 1);
241                        write(fds, histtya, strlen(histtya));
242                }
243                write(fds, "\r\n", 2);
244                sigs(eof);
245                tf = fdopen(fds, "r+");
246                while (1) {
247                        if (fgets(buf, sizeof(buf), tf) == NULL) exit(1);
248                        if (buf[0] == '\n') break;
249                        write(1, buf, strlen(buf));
250                }
251        } else {
252            if (access(histty, 0) < 0) {
253                fprintf(stderr, "write: No such tty\n");
254                exit(1);
255            }
256            signal(SIGALRM, timout);
257            alarm(5);
258            if (setpgrp(0,0))
259                 perror("setpgrp 0");
260            if (stat(histty, &stbuf) < 0 || (stbuf.st_mode&020) == 0
261                        || (tf = fopen(histty, "w")) == NULL) {
262                fprintf(stderr, "write: Permission denied\n");
263                exit(1);
264            }
265            if (setpgrp(0,getpid()))
266                 perror("setpgrp !0");
267            alarm(0);
268            sigs(eof);
269            if (netme) {
270                printf("\n");
271                fflush(stdout);
272                fprintf(tf,
273                 "\r\nMessage from %s on %s at %d:%02d ...\r\n\007\007\007",
274                 me, mytty, localclock->tm_hour, localclock->tm_min);
275            } else
276            { char hostname[32];
277              gethostname(hostname, sizeof (hostname));
278              fprintf(tf,
279                 "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007",
280                 me, hostname, mytty, localclock->tm_hour, localclock->tm_min);
281            }
282            fflush(tf);
283            fds = fileno(tf);
284        }
285        for (;;) {
286                char buf[BUFSIZ];
287                register char *bp;
288                i = read(0, buf, sizeof buf);
289                if (i <= 0)
290                        eof();
291                if ((!netme) && buf[0] == '!') {
292                        buf[i] = 0;
293                        ex(buf);
294                        continue;
295                }
296                for (bp = buf; --i >= 0; bp++) {
297                        if (*bp == '\n')
298                                putc('\r', tf);
299
300                        if (!isascii(*bp)) {
301                                putc('M', tf);
302                                putc('-', tf);
303                                *bp = toascii(*bp);
304                        }
305
306                        if (isprint(*bp) ||
307                            *bp == ' ' || *bp == '\t' || *bp == '\n'
308                            || *bp == '\r') {
309                                putc(*bp, tf);
310                        } else {
311                                putc('^', tf);
312                                putc(*bp ^ 0100, tf);
313                        }
314
315                        if (*bp == '\n')
316                                fflush(tf);
317
318                        if (ferror(tf) || feof(tf)) {
319                                printf("\n\007Write failed (%s logged out?)\n",
320                                        him);
321                                exit(1);
322                        }
323                }
324        }
325}
326
327timout()
328{
329
330        fprintf(stderr, "write: Timeout opening their tty\n");
331        exit(1);
332}
333
334eof()
335{
336
337        if (!nethim) {
338            fprintf(tf, "EOF\r\n");
339            fflush(tf);
340        }
341        exit(0);
342}
343
344ex(bp)
345        char *bp;
346{
347        register i;
348
349        sigs(SIG_IGN);
350        i = fork();
351        if (i < 0) {
352                printf("Try again\n");
353                goto out;
354        }
355        if (i == 0) {
356                fclose(tf);             /* Close his terminal */
357                setgid(getgid());       /* Give up effective group privs */
358                sigs((int (*)())0);
359                execl(getenv("SHELL") ?
360                    getenv("SHELL") : "/bin/sh", "sh", "-c", bp+1, 0);
361                exit(0);
362        }
363        while (wait((int *)NULL) != i)
364                ;
365        printf("!\n");
366out:
367        sigs(eof);
368}
369
370sigs(sig)
371        int (*sig)();
372{
373        register i;
374
375        for (i=0; signum[i]; i++)
376                signal(signum[i], sig);
377}
Note: See TracBrowser for help on using the repository browser.