139422Sbostic /* 239422Sbostic * Copyright (c) 1989 The Regents of the University of California. 339422Sbostic * All rights reserved. 439422Sbostic * 539422Sbostic * Redistribution and use in source and binary forms are permitted 639422Sbostic * provided that the above copyright notice and this paragraph are 739422Sbostic * duplicated in all such forms and that any documentation, 839422Sbostic * advertising materials, and other materials related to such 939422Sbostic * distribution and use acknowledge that the software was developed 1039422Sbostic * by the University of California, Berkeley. The name of the 1139422Sbostic * University may not be used to endorse or promote products derived 1239422Sbostic * from this software without specific prior written permission. 1339422Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1439422Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1539422Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1639422Sbostic */ 1739422Sbostic 1839422Sbostic #ifndef lint 19*39496Skarels static char sccsid[] = "@(#)ttymsg.c 5.2 (Berkeley) 11/07/89"; 2039422Sbostic #endif /* not lint */ 2139422Sbostic 2239422Sbostic #include <sys/types.h> 2339422Sbostic #include <sys/uio.h> 2439422Sbostic #include <sys/file.h> 25*39496Skarels #include <sys/signal.h> 2639422Sbostic #include <dirent.h> 2739422Sbostic #include <errno.h> 2839422Sbostic #include <paths.h> 2939422Sbostic 3039422Sbostic /* 3139422Sbostic * display the contents of a uio structure on a terminal. Used by 32*39496Skarels * wall(1) and syslogd(8). Forks and finishes in child if write 33*39496Skarels * would block, waiting at most five minutes. 3439422Sbostic */ 3539422Sbostic char * 3639422Sbostic ttymsg(iov, iovcnt, line, nonblock) 3739422Sbostic struct iovec *iov; 3839422Sbostic int iovcnt; 3939422Sbostic char *line; 4039422Sbostic int nonblock; 4139422Sbostic { 4239422Sbostic extern int errno; 4339422Sbostic static char device[MAXNAMLEN] = _PATH_DEV; 4439422Sbostic static char errbuf[1024]; 4539422Sbostic register int cnt, fd, total, wret; 4639422Sbostic char *strcpy(), *strerror(); 4739422Sbostic 4839422Sbostic /* 4939422Sbostic * open will fail on slip lines or exclusive-use lines 5039422Sbostic * if not running as root; not an error. 5139422Sbostic */ 52*39496Skarels (void) strcpy(device + sizeof(_PATH_DEV) - 1, line); 5339422Sbostic if ((fd = open(device, O_WRONLY|(nonblock ? O_NONBLOCK : 0), 0)) < 0) 54*39496Skarels if (errno != EBUSY && errno != EPERM) { 55*39496Skarels (void) sprintf(errbuf, "open %s: %s\n", device, 56*39496Skarels strerror(errno)); 57*39496Skarels return (errbuf); 58*39496Skarels } else 59*39496Skarels return (NULL); 6039422Sbostic 6139422Sbostic for (cnt = total = 0; cnt < iovcnt; ++cnt) 6239422Sbostic total += iov[cnt].iov_len; 6339422Sbostic 6439422Sbostic for (;;) 6539422Sbostic if ((wret = writev(fd, iov, iovcnt)) < 0) 6639422Sbostic if (errno == EWOULDBLOCK) { 67*39496Skarels if (fork()) { 68*39496Skarels (void) close(fd); 69*39496Skarels return (NULL); 70*39496Skarels } 7139422Sbostic /* wait at most 5 minutes */ 72*39496Skarels (void) signal(SIGALRM, SIG_DFL); 73*39496Skarels (void) signal(SIGTERM, SIG_DFL); /* XXX */ 74*39496Skarels (void) sigsetmask(0); 75*39496Skarels (void) alarm((u_int)(60 * 5)); 76*39496Skarels (void) ttymsg(iov, iovcnt, line, 0); 7739422Sbostic exit(0); 7839422Sbostic } else { 7939422Sbostic /* 8039422Sbostic * we get ENODEV on a slip line if we're 8139422Sbostic * running as root 8239422Sbostic */ 8339422Sbostic if (errno == ENODEV) 8439422Sbostic break; 85*39496Skarels (void) sprintf(errbuf, "writing %s: %s\n", 86*39496Skarels device, strerror(errno)); 87*39496Skarels (void) close(fd); 88*39496Skarels return (errbuf); 8939422Sbostic } 9039422Sbostic else if (wret) { 9139422Sbostic if (wret == total) 9239422Sbostic break; 9339422Sbostic for (cnt = 0; wret >= iov->iov_len; ++cnt) { 9439422Sbostic wret -= iov->iov_len; 9539422Sbostic ++iov; 9639422Sbostic --iovcnt; 9739422Sbostic } 9839422Sbostic if (wret) { 9939422Sbostic iov->iov_base += wret; 10039422Sbostic iov->iov_len -= wret; 10139422Sbostic } 10239422Sbostic } 103*39496Skarels (void) close(fd); 104*39496Skarels return (NULL); 10539422Sbostic } 106