1*c020d65eSchristos /* $NetBSD: wall.c,v 1.19 2002/08/02 01:52:13 christos Exp $ */ 2a8bfd3d1Sjtc 361f28255Scgd /* 4a8bfd3d1Sjtc * Copyright (c) 1988, 1990, 1993 5a8bfd3d1Sjtc * The Regents of the University of California. All rights reserved. 661f28255Scgd * 761f28255Scgd * Redistribution and use in source and binary forms, with or without 861f28255Scgd * modification, are permitted provided that the following conditions 961f28255Scgd * are met: 1061f28255Scgd * 1. Redistributions of source code must retain the above copyright 1161f28255Scgd * notice, this list of conditions and the following disclaimer. 1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright 1361f28255Scgd * notice, this list of conditions and the following disclaimer in the 1461f28255Scgd * documentation and/or other materials provided with the distribution. 1561f28255Scgd * 3. All advertising materials mentioning features or use of this software 1661f28255Scgd * must display the following acknowledgement: 1761f28255Scgd * This product includes software developed by the University of 1861f28255Scgd * California, Berkeley and its contributors. 1961f28255Scgd * 4. Neither the name of the University nor the names of its contributors 2061f28255Scgd * may be used to endorse or promote products derived from this software 2161f28255Scgd * without specific prior written permission. 2261f28255Scgd * 2361f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2461f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2561f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2661f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2761f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2861f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2961f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3061f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3161f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3261f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3361f28255Scgd * SUCH DAMAGE. 3461f28255Scgd */ 3561f28255Scgd 36c897d730Schristos #include <sys/cdefs.h> 3761f28255Scgd #ifndef lint 38c897d730Schristos __COPYRIGHT("@(#) Copyright (c) 1988, 1990, 1993\n\ 39c897d730Schristos The Regents of the University of California. All rights reserved.\n"); 4061f28255Scgd #endif /* not lint */ 4161f28255Scgd 4261f28255Scgd #ifndef lint 43a8bfd3d1Sjtc #if 0 44a8bfd3d1Sjtc static char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93"; 45a8bfd3d1Sjtc #endif 46*c020d65eSchristos __RCSID("$NetBSD: wall.c,v 1.19 2002/08/02 01:52:13 christos Exp $"); 4761f28255Scgd #endif /* not lint */ 4861f28255Scgd 4961f28255Scgd /* 5061f28255Scgd * This program is not related to David Wall, whose Stanford Ph.D. thesis 5161f28255Scgd * is entitled "Mechanisms for Broadcast and Selective Broadcast". 5261f28255Scgd */ 5361f28255Scgd 5461f28255Scgd #include <sys/param.h> 5561f28255Scgd #include <sys/stat.h> 5661f28255Scgd #include <sys/time.h> 5761f28255Scgd #include <sys/uio.h> 58a8bfd3d1Sjtc 59a6f32a1dSlukem #include <err.h> 60a8bfd3d1Sjtc #include <paths.h> 6161f28255Scgd #include <pwd.h> 6261f28255Scgd #include <stdio.h> 6361f28255Scgd #include <stdlib.h> 64f7c6bf57Sjtc #include <string.h> 65f7c6bf57Sjtc #include <unistd.h> 66c897d730Schristos #include <util.h> 67a8bfd3d1Sjtc 68*c020d65eSchristos #include "utmpentry.h" 69*c020d65eSchristos 70c5775359Smjl void makemsg(const char *); 71c5775359Smjl int main(int, char **); 7261f28255Scgd 7361f28255Scgd int nobanner; 7461f28255Scgd int mbufsize; 7561f28255Scgd char *mbuf; 7661f28255Scgd 7761f28255Scgd /* ARGSUSED */ 78f7c6bf57Sjtc int 79c5775359Smjl main(int argc, char **argv) 8061f28255Scgd { 8161f28255Scgd int ch; 8261f28255Scgd struct iovec iov; 83c897d730Schristos char *p; 84b9b17c30Scgd struct passwd *pep = getpwnam("nobody"); 85*c020d65eSchristos struct utmpentry *ep; 8661f28255Scgd 87a6f32a1dSlukem while ((ch = getopt(argc, argv, "n")) != -1) 8861f28255Scgd switch (ch) { 8961f28255Scgd case 'n': 9061f28255Scgd /* undoc option for shutdown: suppress banner */ 91b9b17c30Scgd if (geteuid() == 0 || (pep && getuid() == pep->pw_uid)) 9261f28255Scgd nobanner = 1; 9361f28255Scgd break; 9461f28255Scgd case '?': 9561f28255Scgd default: 9661f28255Scgd usage: 9761f28255Scgd (void)fprintf(stderr, "usage: wall [file]\n"); 9861f28255Scgd exit(1); 9961f28255Scgd } 10061f28255Scgd argc -= optind; 10161f28255Scgd argv += optind; 10261f28255Scgd if (argc > 1) 10361f28255Scgd goto usage; 10461f28255Scgd 10561f28255Scgd makemsg(*argv); 10661f28255Scgd 10761f28255Scgd iov.iov_base = mbuf; 10861f28255Scgd iov.iov_len = mbufsize; 109*c020d65eSchristos (void)getutentries(NULL, &ep); 110*c020d65eSchristos for (; ep; ep = ep->next) 111*c020d65eSchristos if ((p = ttymsg(&iov, 1, ep->line, 60*5)) != NULL) 112a6f32a1dSlukem warnx("%s", p); 11361f28255Scgd exit(0); 11461f28255Scgd } 11561f28255Scgd 116f7c6bf57Sjtc void 117c5775359Smjl makemsg(const char *fname) 11861f28255Scgd { 11961f28255Scgd register int ch, cnt; 12061f28255Scgd struct tm *lt; 12161f28255Scgd struct passwd *pw; 12261f28255Scgd struct stat sbuf; 123c897d730Schristos time_t now; 12461f28255Scgd FILE *fp; 12561f28255Scgd int fd; 126af26acbcSmycroft const char *whom; 12720117cd1Staca char *p, *tty, tmpname[32], lbuf[100], hostname[MAXHOSTNAMELEN+1]; 12861f28255Scgd 12923768a9eSmrg (void)snprintf(tmpname, sizeof tmpname, "%s/wall.XXXXXX", _PATH_TMP); 130dd3520c0Schristos if ((fd = mkstemp(tmpname)) == -1 || !(fp = fdopen(fd, "r+"))) 131a6f32a1dSlukem err(1, "can't open temporary file"); 13261f28255Scgd (void)unlink(tmpname); 13361f28255Scgd 13461f28255Scgd if (!nobanner) { 13561f28255Scgd if (!(whom = getlogin())) 13661f28255Scgd whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; 13761f28255Scgd (void)gethostname(hostname, sizeof(hostname)); 138ed666575Smrg hostname[sizeof(hostname) - 1] = '\0'; 13961f28255Scgd (void)time(&now); 14061f28255Scgd lt = localtime(&now); 14161f28255Scgd 14261f28255Scgd /* 14361f28255Scgd * all this stuff is to blank out a square for the message; 14461f28255Scgd * we wrap message lines at column 79, not 80, because some 14561f28255Scgd * terminals wrap after 79, some do not, and we can't tell. 14661f28255Scgd * Which means that we may leave a non-blank character 14761f28255Scgd * in column 80, but that can't be helped. 14861f28255Scgd */ 14961f28255Scgd (void)fprintf(fp, "\r%79s\r\n", " "); 15023768a9eSmrg (void)snprintf(lbuf, sizeof lbuf, 15123768a9eSmrg "Broadcast Message from %s@%s", whom, hostname); 15261f28255Scgd (void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf); 15399ebb803Staca tty = ttyname(STDERR_FILENO); 15499ebb803Staca if (tty == NULL) 15520117cd1Staca tty = "??"; 15699ebb803Staca (void)snprintf(lbuf, sizeof lbuf, 15720117cd1Staca " (%s) at %d:%02d ...", tty, lt->tm_hour, 15820117cd1Staca lt->tm_min); 15961f28255Scgd (void)fprintf(fp, "%-79.79s\r\n", lbuf); 16061f28255Scgd } 16161f28255Scgd (void)fprintf(fp, "%79s\r\n", " "); 16261f28255Scgd 163a6f32a1dSlukem if (fname && !(freopen(fname, "r", stdin))) 164a6f32a1dSlukem err(1, "can't read %s", fname); 16561f28255Scgd while (fgets(lbuf, sizeof(lbuf), stdin)) 166a8bfd3d1Sjtc for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { 16761f28255Scgd if (cnt == 79 || ch == '\n') { 16861f28255Scgd for (; cnt < 79; ++cnt) 16961f28255Scgd putc(' ', fp); 17061f28255Scgd putc('\r', fp); 17161f28255Scgd putc('\n', fp); 172f90eda1cSmycroft cnt = -1; 173f90eda1cSmycroft } 174f90eda1cSmycroft if (ch != '\n') 17561f28255Scgd putc(ch, fp); 17661f28255Scgd } 17761f28255Scgd (void)fprintf(fp, "%79s\r\n", " "); 17861f28255Scgd rewind(fp); 17961f28255Scgd 180a6f32a1dSlukem if (fstat(fd, &sbuf)) 181a6f32a1dSlukem err(1, "can't stat temporary file"); 18261f28255Scgd mbufsize = sbuf.st_size; 183a6f32a1dSlukem if (!(mbuf = malloc((u_int)mbufsize))) 184a6f32a1dSlukem err(1, "malloc"); 185a6f32a1dSlukem if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) 186a6f32a1dSlukem err(1, "can't read temporary file"); 18761f28255Scgd (void)close(fd); 18861f28255Scgd } 189