1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)ttymsg.c 5.4 (Berkeley) 02/24/90"; 20 #endif /* not lint */ 21 22 #include <sys/types.h> 23 #include <sys/uio.h> 24 #include <sys/file.h> 25 #include <sys/signal.h> 26 #include <dirent.h> 27 #include <errno.h> 28 #include <paths.h> 29 30 /* 31 * display the contents of a uio structure on a terminal. Used by 32 * wall(1) and syslogd(8). Forks and finishes in child if write 33 * would block, waiting at most five minutes. 34 * Returns pointer to error string on unexpected error; 35 * string is not newline-terminated. Various "normal" errors 36 * are ignored (exclusive-use, lack of permission, etc.). 37 */ 38 char * 39 ttymsg(iov, iovcnt, line, nonblock) 40 struct iovec *iov; 41 int iovcnt; 42 char *line; 43 int nonblock; 44 { 45 extern int errno; 46 static char device[MAXNAMLEN] = _PATH_DEV; 47 static char errbuf[1024]; 48 register int cnt, fd, total, wret; 49 char *strcpy(), *strerror(); 50 51 /* 52 * open will fail on slip lines or exclusive-use lines 53 * if not running as root; not an error. 54 */ 55 (void) strcpy(device + sizeof(_PATH_DEV) - 1, line); 56 if ((fd = open(device, O_WRONLY|(nonblock ? O_NONBLOCK : 0), 0)) < 0) 57 if (errno != EBUSY && errno != EACCES) { 58 (void) sprintf(errbuf, "open %s: %s", device, 59 strerror(errno)); 60 return (errbuf); 61 } else 62 return (NULL); 63 64 for (cnt = total = 0; cnt < iovcnt; ++cnt) 65 total += iov[cnt].iov_len; 66 67 for (;;) 68 if ((wret = writev(fd, iov, iovcnt)) < 0) 69 if (errno == EWOULDBLOCK) { 70 if (fork()) { 71 (void) close(fd); 72 return (NULL); 73 } 74 /* wait at most 5 minutes */ 75 (void) signal(SIGALRM, SIG_DFL); 76 (void) signal(SIGTERM, SIG_DFL); /* XXX */ 77 (void) sigsetmask(0); 78 (void) alarm((u_int)(60 * 5)); 79 (void) ttymsg(iov, iovcnt, line, 0); 80 exit(0); 81 } else { 82 /* 83 * we get ENODEV on a slip line if we're 84 * running as root, and EIO if the line 85 * just went away 86 */ 87 if (errno == ENODEV || errno == EIO) 88 break; 89 (void) sprintf(errbuf, "writing %s: %s", 90 device, strerror(errno)); 91 (void) close(fd); 92 return (errbuf); 93 } 94 else if (wret) { 95 if (wret == total) 96 break; 97 for (cnt = 0; wret >= iov->iov_len; ++cnt) { 98 wret -= iov->iov_len; 99 ++iov; 100 --iovcnt; 101 } 102 if (wret) { 103 iov->iov_base += wret; 104 iov->iov_len -= wret; 105 } 106 } 107 (void) close(fd); 108 return (NULL); 109 } 110