11159Sbill /* 240223Skarels * Copyright (c) 1988, 1990 Regents of the University of California. 335531Sbostic * All rights reserved. 435531Sbostic * 5*45220Sbostic * %sccs.include.redist.c% 619909Sdist */ 719909Sdist 819909Sdist #ifndef lint 919909Sdist char copyright[] = 1035531Sbostic "@(#) Copyright (c) 1988 Regents of the University of California.\n\ 1119909Sdist All rights reserved.\n"; 1235531Sbostic #endif /* not lint */ 1319909Sdist 1419909Sdist #ifndef lint 15*45220Sbostic static char sccsid[] = "@(#)wall.c 5.13 (Berkeley) 09/07/90"; 1635531Sbostic #endif /* not lint */ 1719909Sdist 1819909Sdist /* 191159Sbill * This program is not related to David Wall, whose Stanford Ph.D. thesis 201159Sbill * is entitled "Mechanisms for Broadcast and Selective Broadcast". 211159Sbill */ 221159Sbill 2335531Sbostic #include <sys/param.h> 2439423Sbostic #include <sys/stat.h> 2535531Sbostic #include <sys/time.h> 2639423Sbostic #include <sys/uio.h> 271159Sbill #include <utmp.h> 2835531Sbostic #include <pwd.h> 2935531Sbostic #include <stdio.h> 3039124Sbostic #include <paths.h> 3116256Sralph 3235531Sbostic #define IGNOREUSER "sleeper" 331159Sbill 3440223Skarels int nobanner; 3539089Smarc int mbufsize; 3639089Smarc char *mbuf; 371159Sbill 3835531Sbostic /* ARGSUSED */ 391159Sbill main(argc, argv) 4035531Sbostic int argc; 4135531Sbostic char **argv; 421159Sbill { 4340223Skarels extern int optind; 4440223Skarels int ch; 4539423Sbostic struct iovec iov; 4635531Sbostic struct utmp utmp; 4735531Sbostic FILE *fp; 4839423Sbostic char *p, *ttymsg(); 491159Sbill 5040223Skarels while ((ch = getopt(argc, argv, "n")) != EOF) 5140223Skarels switch (ch) { 5240223Skarels case 'n': 5340223Skarels /* undoc option for shutdown: suppress banner */ 5440223Skarels if (geteuid() == 0) 5540223Skarels nobanner = 1; 5640223Skarels break; 5740223Skarels case '?': 5840223Skarels default: 5940223Skarels usage: 6040223Skarels (void)fprintf(stderr, "usage: wall [file]\n"); 6140223Skarels exit(1); 6240223Skarels } 6340223Skarels argc -= optind; 6440223Skarels argv += optind; 6540223Skarels if (argc > 1) 6640223Skarels goto usage; 6735531Sbostic 6840223Skarels makemsg(*argv); 6939423Sbostic 7039089Smarc if (!(fp = fopen(_PATH_UTMP, "r"))) { 7139423Sbostic (void)fprintf(stderr, "wall: cannot read %s.\n", _PATH_UTMP); 7235531Sbostic exit(1); 731159Sbill } 7439423Sbostic iov.iov_base = mbuf; 7539423Sbostic iov.iov_len = mbufsize; 7635531Sbostic /* NOSTRICT */ 7739423Sbostic while (fread((char *)&utmp, sizeof(utmp), 1, fp) == 1) { 7839423Sbostic if (!utmp.ut_name[0] || 7939423Sbostic !strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name))) 8039423Sbostic continue; 8144590Smarc if (p = ttymsg(&iov, 1, utmp.ut_line)) 8239423Sbostic (void)fprintf(stderr, "wall: %s\n", p); 8339423Sbostic } 841159Sbill exit(0); 851159Sbill } 861159Sbill 8739423Sbostic makemsg(fname) 8839423Sbostic char *fname; 891159Sbill { 9035531Sbostic register int ch, cnt; 9135531Sbostic struct tm *lt; 9235531Sbostic struct passwd *pw, *getpwuid(); 9335531Sbostic struct stat sbuf; 9435531Sbostic time_t now, time(); 9535531Sbostic FILE *fp; 9635531Sbostic int fd; 9735531Sbostic char *p, *whom, hostname[MAXHOSTNAMELEN], lbuf[100], tmpname[15]; 9835531Sbostic char *getlogin(), *malloc(), *strcpy(), *ttyname(); 991159Sbill 10039089Smarc (void)strcpy(tmpname, _PATH_TMP); 10139124Sbostic (void)strcat(tmpname, "/wall.XXXXXX"); 10235531Sbostic if (!(fd = mkstemp(tmpname)) || !(fp = fdopen(fd, "r+"))) { 10339423Sbostic (void)fprintf(stderr, "wall: can't open temporary file.\n"); 10435531Sbostic exit(1); 10535531Sbostic } 10635531Sbostic (void)unlink(tmpname); 10716256Sralph 10840223Skarels if (!nobanner) { 10940223Skarels if (!(whom = getlogin())) 11040223Skarels whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; 11140223Skarels (void)gethostname(hostname, sizeof(hostname)); 11240223Skarels (void)time(&now); 11340223Skarels lt = localtime(&now); 11435531Sbostic 11540223Skarels /* 11640223Skarels * all this stuff is to blank out a square for the message; 11740223Skarels * we wrap message lines at column 79, not 80, because some 11840223Skarels * terminals wrap after 79, some do not, and we can't tell. 11940223Skarels * Which means that we may leave a non-blank character 12040223Skarels * in column 80, but that can't be helped. 12140223Skarels */ 12240223Skarels (void)fprintf(fp, "\r%79s\r\n", " "); 12340223Skarels (void)sprintf(lbuf, "Broadcast Message from %s@%s", 12440223Skarels whom, hostname); 12540223Skarels (void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf); 12640223Skarels (void)sprintf(lbuf, " (%s) at %d:%02d ...", ttyname(2), 12740223Skarels lt->tm_hour, lt->tm_min); 12840223Skarels (void)fprintf(fp, "%-79.79s\r\n", lbuf); 12940223Skarels } 13039423Sbostic (void)fprintf(fp, "%79s\r\n", " "); 13135531Sbostic 13239423Sbostic if (*fname && !(freopen(fname, "r", stdin))) { 13339423Sbostic (void)fprintf(stderr, "wall: can't read %s.\n", fname); 13435531Sbostic exit(1); 13516256Sralph } 13635531Sbostic while (fgets(lbuf, sizeof(lbuf), stdin)) 13739089Smarc for (cnt = 0, p = lbuf; ch = *p; ++p, ++cnt) { 13839089Smarc if (cnt == 79 || ch == '\n') { 13939423Sbostic for (; cnt < 79; ++cnt) 14039423Sbostic putc(' ', fp); 14135531Sbostic putc('\r', fp); 14235531Sbostic putc('\n', fp); 14339089Smarc cnt = 0; 14435531Sbostic } else 14535531Sbostic putc(ch, fp); 14639089Smarc } 14739423Sbostic (void)fprintf(fp, "%79s\r\n", " "); 14835531Sbostic rewind(fp); 14935531Sbostic 15035531Sbostic if (fstat(fd, &sbuf)) { 15139423Sbostic (void)fprintf(stderr, "wall: can't stat temporary file.\n"); 15235531Sbostic exit(1); 15316256Sralph } 15435531Sbostic mbufsize = sbuf.st_size; 15535531Sbostic if (!(mbuf = malloc((u_int)mbufsize))) { 15639423Sbostic (void)fprintf(stderr, "wall: out of memory.\n"); 15735531Sbostic exit(1); 15816256Sralph } 15935776Sbostic if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) { 16039423Sbostic (void)fprintf(stderr, "wall: can't read temporary file.\n"); 16135776Sbostic exit(1); 16235776Sbostic } 16335531Sbostic (void)close(fd); 16435531Sbostic } 165