Annotation of 43BSDReno/usr.bin/write/write.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory.
                      7:  *
                      8:  * Redistribution and use in source and binary forms are permitted provided
                      9:  * that: (1) source distributions retain this entire copyright notice and
                     10:  * comment, and (2) distributions including binaries display the following
                     11:  * acknowledgement:  ``This product includes software developed by the
                     12:  * University of California, Berkeley and its contributors'' in the
                     13:  * documentation or other materials provided with the distribution and in
                     14:  * all advertising materials mentioning features or use of this software.
                     15:  * Neither the name of the University nor the names of its contributors may
                     16:  * be used to endorse or promote products derived from this software without
                     17:  * specific prior written permission.
                     18:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     19:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     20:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     21:  */
                     22: 
                     23: #ifndef lint
                     24: char copyright[] =
                     25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
                     26:  All rights reserved.\n";
                     27: #endif /* not lint */
                     28: 
                     29: #ifndef lint
                     30: static char sccsid[] = "@(#)write.c    4.22 (Berkeley) 6/1/90";
                     31: #endif /* not lint */
                     32: 
                     33: #include <sys/param.h>
                     34: #include <sys/signal.h>
                     35: #include <sys/stat.h>
                     36: #include <sys/file.h>
                     37: #include <sys/time.h>
                     38: #include <utmp.h>
                     39: #include <ctype.h>
                     40: #include <pwd.h>
                     41: #include <stdio.h>
                     42: #include <string.h>
                     43: 
                     44: extern int errno;
                     45: 
                     46: main(argc, argv)
                     47:        int argc;
                     48:        char **argv;
                     49: {
                     50:        register char *cp;
                     51:        time_t atime;
                     52:        uid_t myuid;
                     53:        int msgsok, myttyfd;
                     54:        char tty[MAXPATHLEN], *mytty, *ttyname();
                     55:        void done();
                     56: 
                     57:        /* check that sender has write enabled */
                     58:        if (isatty(fileno(stdin)))
                     59:                myttyfd = fileno(stdin);
                     60:        else if (isatty(fileno(stdout)))
                     61:                myttyfd = fileno(stdout);
                     62:        else if (isatty(fileno(stderr)))
                     63:                myttyfd = fileno(stderr);
                     64:        else {
                     65:                (void)fprintf(stderr, "write: can't find your tty\n");
                     66:                exit(1);
                     67:        }
                     68:        if (!(mytty = ttyname(myttyfd))) {
                     69:                (void)fprintf(stderr, "write: can't find your tty's name\n");
                     70:                exit(1);
                     71:        }
                     72:        if (cp = rindex(mytty, '/'))
                     73:                mytty = cp + 1;
                     74:        if (term_chk(mytty, &msgsok, &atime, 1))
                     75:                exit(1);
                     76:        if (!msgsok) {
                     77:                (void)fprintf(stderr,
                     78:                    "write: you have write permission turned off.\n");
                     79:                exit(1);
                     80:        }
                     81: 
                     82:        myuid = getuid();
                     83: 
                     84:        /* check args */
                     85:        switch (argc) {
                     86:        case 2:
                     87:                search_utmp(argv[1], tty, mytty, myuid);
                     88:                do_write(tty, mytty, myuid);
                     89:                break;
                     90:        case 3:
                     91:                if (!strncmp(argv[2], "/dev/", 5))
                     92:                        argv[2] += 5;
                     93:                if (utmp_chk(argv[1], argv[2])) {
                     94:                        (void)fprintf(stderr,
                     95:                            "write: %s is not logged in on %s.\n",
                     96:                            argv[1], argv[2]);
                     97:                        exit(1);
                     98:                }
                     99:                if (term_chk(argv[2], &msgsok, &atime, 1))
                    100:                        exit(1);
                    101:                if (myuid && !msgsok) {
                    102:                        (void)fprintf(stderr,
                    103:                            "write: %s has messages disabled on %s\n",
                    104:                            argv[1], argv[2]);
                    105:                        exit(1);
                    106:                }
                    107:                do_write(argv[2], mytty, myuid);
                    108:                break;
                    109:        default:
                    110:                (void)fprintf(stderr, "usage: write user [tty]\n");
                    111:                exit(1);
                    112:        }
                    113:        done();
                    114:        /* NOTREACHED */
                    115: }
                    116: 
                    117: /*
                    118:  * utmp_chk - checks that the given user is actually logged in on
                    119:  *     the given tty
                    120:  */
                    121: utmp_chk(user, tty)
                    122:        char *user, *tty;
                    123: {
                    124:        struct utmp u;
                    125:        int ufd;
                    126: 
                    127:        if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0)
                    128:                return(0);      /* ignore error, shouldn't happen anyway */
                    129: 
                    130:        while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u))
                    131:                if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0 &&
                    132:                    strncmp(tty, u.ut_line, sizeof(u.ut_line)) == 0) {
                    133:                        (void)close(ufd);
                    134:                        return(0);
                    135:                }
                    136: 
                    137:        (void)close(ufd);
                    138:        return(1);
                    139: }
                    140: 
                    141: /*
                    142:  * search_utmp - search utmp for the "best" terminal to write to
                    143:  *
                    144:  * Ignores terminals with messages disabled, and of the rest, returns
                    145:  * the one with the most recent access time.  Returns as value the number
                    146:  * of the user's terminals with messages enabled, or -1 if the user is
                    147:  * not logged in at all.
                    148:  *
                    149:  * Special case for writing to yourself - ignore the terminal you're
                    150:  * writing from, unless that's the only terminal with messages enabled.
                    151:  */
                    152: search_utmp(user, tty, mytty, myuid)
                    153:        char *user, *tty, *mytty;
                    154:        uid_t myuid;
                    155: {
                    156:        struct utmp u;
                    157:        time_t bestatime, atime;
                    158:        int ufd, nloggedttys, nttys, msgsok, user_is_me;
                    159:        char atty[UT_LINESIZE + 1];
                    160: 
                    161:        if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) {
                    162:                perror("utmp");
                    163:                exit(1);
                    164:        }
                    165: 
                    166:        nloggedttys = nttys = 0;
                    167:        bestatime = 0;
                    168:        user_is_me = 0;
                    169:        while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u))
                    170:                if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) {
                    171:                        ++nloggedttys;
                    172:                        (void)strncpy(atty, u.ut_line, UT_LINESIZE);
                    173:                        atty[UT_LINESIZE] = '\0';
                    174:                        if (term_chk(atty, &msgsok, &atime, 0))
                    175:                                continue;       /* bad term? skip */
                    176:                        if (myuid && !msgsok)
                    177:                                continue;       /* skip ttys with msgs off */
                    178:                        if (strcmp(atty, mytty) == 0) {
                    179:                                user_is_me = 1;
                    180:                                continue;       /* don't write to yourself */
                    181:                        }
                    182:                        ++nttys;
                    183:                        if (atime > bestatime) {
                    184:                                bestatime = atime;
                    185:                                (void)strcpy(tty, atty);
                    186:                        }
                    187:                }
                    188: 
                    189:        (void)close(ufd);
                    190:        if (nloggedttys == 0) {
                    191:                (void)fprintf(stderr, "write: %s is not logged in\n", user);
                    192:                exit(1);
                    193:        }
                    194:        if (nttys == 0) {
                    195:                if (user_is_me) {               /* ok, so write to yourself! */
                    196:                        (void)strcpy(tty, mytty);
                    197:                        return;
                    198:                }
                    199:                (void)fprintf(stderr,
                    200:                    "write: %s has messages disabled\n", user);
                    201:                exit(1);
                    202:        } else if (nttys > 1) {
                    203:                (void)fprintf(stderr,
                    204:                    "write: %s is logged in more than once; writing to %s\n",
                    205:                    user, tty);
                    206:        }
                    207: }
                    208: 
                    209: /*
                    210:  * term_chk - check that a terminal exists, and get the message bit
                    211:  *     and the access time
                    212:  */
                    213: term_chk(tty, msgsokP, atimeP, showerror)
                    214:        char *tty;
                    215:        int *msgsokP, showerror;
                    216:        time_t *atimeP;
                    217: {
                    218:        struct stat s;
                    219:        char path[MAXPATHLEN];
                    220: 
                    221:        (void)sprintf(path, "/dev/%s", tty);
                    222:        if (stat(path, &s) < 0) {
                    223:                if (showerror)
                    224:                        (void)fprintf(stderr,
                    225:                            "write: %s: %s\n", path, strerror(errno));
                    226:                return(1);
                    227:        }
                    228:        *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0;  /* group write bit */
                    229:        *atimeP = s.st_atime;
                    230:        return(0);
                    231: }
                    232: 
                    233: /*
                    234:  * do_write - actually make the connection
                    235:  */
                    236: do_write(tty, mytty, myuid)
                    237:        char *tty, *mytty;
                    238:        uid_t myuid;
                    239: {
                    240:        register char *login, *nows;
                    241:        register struct passwd *pwd;
                    242:        time_t now, time();
                    243:        char *getlogin(), path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512];
                    244:        void done();
                    245: 
                    246:        /* Determine our login name before the we reopen() stdout */
                    247:        if ((login = getlogin()) == NULL)
                    248:                if (pwd = getpwuid(myuid))
                    249:                        login = pwd->pw_name;
                    250:                else
                    251:                        login = "???";
                    252: 
                    253:        (void)sprintf(path, "/dev/%s", tty);
                    254:        if ((freopen(path, "w", stdout)) == NULL) {
                    255:                (void)fprintf(stderr, "write: %s: %s\n", path, strerror(errno));
                    256:                exit(1);
                    257:        }
                    258: 
                    259:        (void)signal(SIGINT, done);
                    260:        (void)signal(SIGHUP, done);
                    261: 
                    262:        /* print greeting */
                    263:        if (gethostname(host, sizeof(host)) < 0)
                    264:                (void)strcpy(host, "???");
                    265:        now = time((time_t *)NULL);
                    266:        nows = ctime(&now);
                    267:        nows[16] = '\0';
                    268:        (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n",
                    269:            login, host, mytty, nows + 11);
                    270: 
                    271:        while (fgets(line, sizeof(line), stdin) != NULL)
                    272:                wr_fputs(line);
                    273: }
                    274: 
                    275: /*
                    276:  * done - cleanup and exit
                    277:  */
                    278: void
                    279: done()
                    280: {
                    281:        (void)printf("EOF\r\n");
                    282:        exit(0);
                    283: }
                    284: 
                    285: /*
                    286:  * wr_fputs - like fputs(), but makes control characters visible and
                    287:  *     turns \n into \r\n
                    288:  */
                    289: wr_fputs(s)
                    290:        register char *s;
                    291: {
                    292:        register char c;
                    293: 
                    294: #define        PUTC(c) if (putchar(c) == EOF) goto err;
                    295: 
                    296:        for (; *s != '\0'; ++s) {
                    297:                c = toascii(*s);
                    298:                if (c == '\n') {
                    299:                        PUTC('\r');
                    300:                        PUTC('\n');
                    301:                } else if (!isprint(c) && !isspace(c) && c != '\007') {
                    302:                        PUTC('^');
                    303:                        PUTC(c^0x40);   /* DEL to ?, others to alpha */
                    304:                } else
                    305:                        PUTC(c);
                    306:        }
                    307:        return;
                    308: 
                    309: err:   (void)fprintf(stderr, "write: %s\n", strerror(errno));
                    310:        exit(1);
                    311: #undef PUTC
                    312: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.