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*40222Skarels static char sccsid[] = "@(#)ttymsg.c 5.4 (Berkeley) 02/24/90"; 2039422Sbostic #endif /* not lint */ 2139422Sbostic 2239422Sbostic #include <sys/types.h> 2339422Sbostic #include <sys/uio.h> 2439422Sbostic #include <sys/file.h> 2539496Skarels #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 3239496Skarels * wall(1) and syslogd(8). Forks and finishes in child if write 3339496Skarels * would block, waiting at most five minutes. 34*40222Skarels * Returns pointer to error string on unexpected error; 35*40222Skarels * string is not newline-terminated. Various "normal" errors 36*40222Skarels * are ignored (exclusive-use, lack of permission, etc.). 3739422Sbostic */ 3839422Sbostic char * 3939422Sbostic ttymsg(iov, iovcnt, line, nonblock) 4039422Sbostic struct iovec *iov; 4139422Sbostic int iovcnt; 4239422Sbostic char *line; 4339422Sbostic int nonblock; 4439422Sbostic { 4539422Sbostic extern int errno; 4639422Sbostic static char device[MAXNAMLEN] = _PATH_DEV; 4739422Sbostic static char errbuf[1024]; 4839422Sbostic register int cnt, fd, total, wret; 4939422Sbostic char *strcpy(), *strerror(); 5039422Sbostic 5139422Sbostic /* 5239422Sbostic * open will fail on slip lines or exclusive-use lines 5339422Sbostic * if not running as root; not an error. 5439422Sbostic */ 5539496Skarels (void) strcpy(device + sizeof(_PATH_DEV) - 1, line); 5639422Sbostic if ((fd = open(device, O_WRONLY|(nonblock ? O_NONBLOCK : 0), 0)) < 0) 5740221Skarels if (errno != EBUSY && errno != EACCES) { 5840221Skarels (void) sprintf(errbuf, "open %s: %s", device, 5939496Skarels strerror(errno)); 6039496Skarels return (errbuf); 6139496Skarels } else 6239496Skarels return (NULL); 6339422Sbostic 6439422Sbostic for (cnt = total = 0; cnt < iovcnt; ++cnt) 6539422Sbostic total += iov[cnt].iov_len; 6639422Sbostic 6739422Sbostic for (;;) 6839422Sbostic if ((wret = writev(fd, iov, iovcnt)) < 0) 6939422Sbostic if (errno == EWOULDBLOCK) { 7039496Skarels if (fork()) { 7139496Skarels (void) close(fd); 7239496Skarels return (NULL); 7339496Skarels } 7439422Sbostic /* wait at most 5 minutes */ 7539496Skarels (void) signal(SIGALRM, SIG_DFL); 7639496Skarels (void) signal(SIGTERM, SIG_DFL); /* XXX */ 7739496Skarels (void) sigsetmask(0); 7839496Skarels (void) alarm((u_int)(60 * 5)); 7939496Skarels (void) ttymsg(iov, iovcnt, line, 0); 8039422Sbostic exit(0); 8139422Sbostic } else { 8239422Sbostic /* 8339422Sbostic * we get ENODEV on a slip line if we're 84*40222Skarels * running as root, and EIO if the line 85*40222Skarels * just went away 8639422Sbostic */ 87*40222Skarels if (errno == ENODEV || errno == EIO) 8839422Sbostic break; 8940221Skarels (void) sprintf(errbuf, "writing %s: %s", 9039496Skarels device, strerror(errno)); 9139496Skarels (void) close(fd); 9239496Skarels return (errbuf); 9339422Sbostic } 9439422Sbostic else if (wret) { 9539422Sbostic if (wret == total) 9639422Sbostic break; 9739422Sbostic for (cnt = 0; wret >= iov->iov_len; ++cnt) { 9839422Sbostic wret -= iov->iov_len; 9939422Sbostic ++iov; 10039422Sbostic --iovcnt; 10139422Sbostic } 10239422Sbostic if (wret) { 10339422Sbostic iov->iov_base += wret; 10439422Sbostic iov->iov_len -= wret; 10539422Sbostic } 10639422Sbostic } 10739496Skarels (void) close(fd); 10839496Skarels return (NULL); 10939422Sbostic } 110