wall.c revision 28695
138032Speter/* 2112810Sgshapiro * Copyright (c) 1988, 1990, 1993 338032Speter * The Regents of the University of California. All rights reserved. 438032Speter * 538032Speter * Redistribution and use in source and binary forms, with or without 638032Speter * modification, are permitted provided that the following conditions 738032Speter * are met: 838032Speter * 1. Redistributions of source code must retain the above copyright 9112810Sgshapiro * notice, this list of conditions and the following disclaimer. 10112810Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright 11112810Sgshapiro * notice, this list of conditions and the following disclaimer in the 12112810Sgshapiro * documentation and/or other materials provided with the distribution. 13112810Sgshapiro * 3. All advertising materials mentioning features or use of this software 14112810Sgshapiro * must display the following acknowledgement: 15112810Sgshapiro * This product includes software developed by the University of 16112810Sgshapiro * California, Berkeley and its contributors. 17112810Sgshapiro * 4. Neither the name of the University nor the names of its contributors 18112810Sgshapiro * may be used to endorse or promote products derived from this software 19112810Sgshapiro * without specific prior written permission. 20112810Sgshapiro * 21112810Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22112810Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23112810Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24112810Sgshapiro * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25112810Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26112810Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27112810Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28112810Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29112810Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30112810Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31112810Sgshapiro * SUCH DAMAGE. 32112810Sgshapiro */ 33112810Sgshapiro 34112810Sgshapiro#ifndef lint 35112810Sgshapirostatic const char copyright[] = 36112810Sgshapiro"@(#) Copyright (c) 1988, 1990, 1993\n\ 37112810Sgshapiro The Regents of the University of California. All rights reserved.\n"; 38112810Sgshapiro#endif /* not lint */ 39112810Sgshapiro 40112810Sgshapiro#ifndef lint 41112810Sgshapiro#if 0 42112810Sgshapirostatic char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93"; 43112810Sgshapiro#endif 44112810Sgshapirostatic const char rcsid[] = 45112810Sgshapiro "$Id$"; 46111823Sgshapiro#endif /* not lint */ 47111823Sgshapiro 48111823Sgshapiro/* 49111823Sgshapiro * This program is not related to David Wall, whose Stanford Ph.D. thesis 50111823Sgshapiro * is entitled "Mechanisms for Broadcast and Selective Broadcast". 51111823Sgshapiro */ 52111823Sgshapiro 53111823Sgshapiro#include <sys/param.h> 54111823Sgshapiro#include <sys/stat.h> 55111823Sgshapiro#include <sys/time.h> 56111823Sgshapiro#include <sys/uio.h> 57111823Sgshapiro 58111823Sgshapiro#include <ctype.h> 59111823Sgshapiro#include <err.h> 60111823Sgshapiro#include <locale.h> 61111823Sgshapiro#include <paths.h> 62111823Sgshapiro#include <pwd.h> 63111823Sgshapiro#include <stdio.h> 64111823Sgshapiro#include <stdlib.h> 65111823Sgshapiro#include <string.h> 66110560Sgshapiro#include <unistd.h> 67110560Sgshapiro#include <utmp.h> 68110560Sgshapiro 69110560Sgshapirovoid makemsg __P((char *)); 70110560Sgshapirostatic void usage __P((void)); 71110560Sgshapiro 72110560Sgshapiro#define IGNOREUSER "sleeper" 73110560Sgshapiro 74110560Sgshapiroint nobanner; 75110560Sgshapiroint mbufsize; 76110560Sgshapirochar *mbuf; 77110560Sgshapiro 78110560Sgshapiro/* ARGSUSED */ 79110560Sgshapiroint 80110560Sgshapiromain(argc, argv) 81110560Sgshapiro int argc; 82110560Sgshapiro char **argv; 83110560Sgshapiro{ 84110560Sgshapiro int ch; 85110560Sgshapiro struct iovec iov; 86110560Sgshapiro struct utmp utmp; 87110560Sgshapiro FILE *fp; 88110560Sgshapiro char *p, *ttymsg(); 89110560Sgshapiro char line[sizeof(utmp.ut_line) + 1]; 90110560Sgshapiro 91110560Sgshapiro (void)setlocale(LC_CTYPE, ""); 92110560Sgshapiro 93110560Sgshapiro while ((ch = getopt(argc, argv, "n")) != -1) 94110560Sgshapiro switch (ch) { 95110560Sgshapiro case 'n': 96110560Sgshapiro /* undoc option for shutdown: suppress banner */ 97110560Sgshapiro if (geteuid() == 0) 98110560Sgshapiro nobanner = 1; 99110560Sgshapiro break; 100110560Sgshapiro case '?': 101110560Sgshapiro default: 102110560Sgshapiro usage(); 103110560Sgshapiro } 104110560Sgshapiro argc -= optind; 105110560Sgshapiro argv += optind; 106110560Sgshapiro if (argc > 1) 107110560Sgshapiro usage(); 108110560Sgshapiro 109110560Sgshapiro makemsg(*argv); 110110560Sgshapiro 111110560Sgshapiro if (!(fp = fopen(_PATH_UTMP, "r"))) 112110560Sgshapiro errx(1, "cannot read %s", _PATH_UTMP); 113110560Sgshapiro iov.iov_base = mbuf; 114110560Sgshapiro iov.iov_len = mbufsize; 115110560Sgshapiro /* NOSTRICT */ 116110560Sgshapiro while (fread((char *)&utmp, sizeof(utmp), 1, fp) == 1) { 117110560Sgshapiro if (!utmp.ut_name[0] || 118110560Sgshapiro !strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name))) 119110560Sgshapiro continue; 120111823Sgshapiro strncpy(line, utmp.ut_line, sizeof(utmp.ut_line)); 121110560Sgshapiro line[sizeof(utmp.ut_line)] = '\0'; 122110560Sgshapiro if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL) 123110560Sgshapiro warnx("%s", p); 124110560Sgshapiro } 125110560Sgshapiro exit(0); 126110560Sgshapiro} 127110560Sgshapiro 128110560Sgshapirostatic void 129110560Sgshapirousage() 130110560Sgshapiro{ 131110560Sgshapiro (void)fprintf(stderr, "usage: wall [file]\n"); 132110560Sgshapiro exit(1); 133110560Sgshapiro} 134110560Sgshapiro 135110560Sgshapirovoid 136110560Sgshapiromakemsg(fname) 137110560Sgshapiro char *fname; 138110560Sgshapiro{ 139110560Sgshapiro register int cnt; 140110560Sgshapiro register unsigned char ch; 141110560Sgshapiro struct tm *lt; 142110560Sgshapiro struct passwd *pw; 143110560Sgshapiro struct stat sbuf; 144110560Sgshapiro time_t now, time(); 145110560Sgshapiro FILE *fp; 146110560Sgshapiro int fd; 147110560Sgshapiro char *p, *whom, hostname[MAXHOSTNAMELEN], lbuf[100], tmpname[15]; 148110560Sgshapiro char *getlogin(), *strcpy(), *ttyname(); 149110560Sgshapiro 150110560Sgshapiro (void)strcpy(tmpname, _PATH_TMP); 151110560Sgshapiro (void)strcat(tmpname, "/wall.XXXXXX"); 152110560Sgshapiro if (!(fd = mkstemp(tmpname)) || !(fp = fdopen(fd, "r+"))) 153110560Sgshapiro errx(1, "can't open temporary file"); 154110560Sgshapiro (void)unlink(tmpname); 155110560Sgshapiro 156110560Sgshapiro if (!nobanner) { 157110560Sgshapiro if (!(whom = getlogin())) 158110560Sgshapiro whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; 159110560Sgshapiro (void)gethostname(hostname, sizeof(hostname)); 160110560Sgshapiro (void)time(&now); 161110560Sgshapiro lt = localtime(&now); 162110560Sgshapiro 163110560Sgshapiro /* 164110560Sgshapiro * all this stuff is to blank out a square for the message; 165110560Sgshapiro * we wrap message lines at column 79, not 80, because some 166110560Sgshapiro * terminals wrap after 79, some do not, and we can't tell. 167110560Sgshapiro * Which means that we may leave a non-blank character 168110560Sgshapiro * in column 80, but that can't be helped. 169110560Sgshapiro */ 170110560Sgshapiro (void)fprintf(fp, "\r%79s\r\n", " "); 171110560Sgshapiro (void)sprintf(lbuf, "Broadcast Message from %s@%s", 172110560Sgshapiro whom, hostname); 173110560Sgshapiro (void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf); 174110560Sgshapiro (void)sprintf(lbuf, " (%s) at %d:%02d ...", ttyname(2), 175110560Sgshapiro lt->tm_hour, lt->tm_min); 176110560Sgshapiro (void)fprintf(fp, "%-79.79s\r\n", lbuf); 177110560Sgshapiro } 178102528Sgshapiro (void)fprintf(fp, "%79s\r\n", " "); 179102528Sgshapiro 180102528Sgshapiro if (fname && !(freopen(fname, "r", stdin))) 181102528Sgshapiro errx(1, "can't read %s", fname); 182102528Sgshapiro while (fgets(lbuf, sizeof(lbuf), stdin)) 183102528Sgshapiro for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { 184102528Sgshapiro again: 185102528Sgshapiro if (cnt == 79 || ch == '\n') { 186102528Sgshapiro for (; cnt < 79; ++cnt) 187102528Sgshapiro putc(' ', fp); 188102528Sgshapiro putc('\r', fp); 189102528Sgshapiro putc('\n', fp); 190102528Sgshapiro cnt = 0; 191102528Sgshapiro } else if ( ( (ch & 0x7F) < ' ' /* locale-independent */ 192102528Sgshapiro || (!isprint(ch) && !isspace(ch)) 193102528Sgshapiro ) 194102528Sgshapiro && strchr("\a\f\t\v\b\r\n", ch) == NULL 195102528Sgshapiro ) { 196102528Sgshapiro if (ch & 0x80) { 197102528Sgshapiro ch &= 0x7F; 198102528Sgshapiro (void)fprintf(fp, "M-"); 199102528Sgshapiro goto again; 200102528Sgshapiro } 201102528Sgshapiro putc('^', fp); 202102528Sgshapiro putc(ch^0x40, fp); /* DEL to ?, others to alpha */ 203102528Sgshapiro } else 204102528Sgshapiro putc(ch, fp); 205102528Sgshapiro } 206102528Sgshapiro (void)fprintf(fp, "%79s\r\n", " "); 207102528Sgshapiro rewind(fp); 208102528Sgshapiro 209102528Sgshapiro if (fstat(fd, &sbuf)) 210102528Sgshapiro errx(1, "can't stat temporary file"); 211102528Sgshapiro mbufsize = sbuf.st_size; 212102528Sgshapiro if (!(mbuf = malloc((u_int)mbufsize))) 213102528Sgshapiro errx(1, "out of memory"); 214102528Sgshapiro if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) 215102528Sgshapiro errx(1, "can't read temporary file"); 216102528Sgshapiro (void)close(fd); 217102528Sgshapiro} 218102528Sgshapiro