Annotation of 43BSDReno/usr.bin/write/write.c, revision 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.