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

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