|
|
1.1 ! root 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.5 (Berkeley) 6/29/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: #include <stdio.h> ! 30: ! 31: /* ! 32: * display the contents of a uio structure on a terminal. Used by ! 33: * wall(1) and syslogd(8). Forks and finishes in child if write ! 34: * would block, waiting at most five minutes. ! 35: * Returns pointer to error string on unexpected error; ! 36: * string is not newline-terminated. Various "normal" errors ! 37: * are ignored (exclusive-use, lack of permission, etc.). ! 38: */ ! 39: char * ! 40: ttymsg(iov, iovcnt, line) ! 41: struct iovec *iov; ! 42: int iovcnt; ! 43: char *line; ! 44: { ! 45: extern int errno; ! 46: static char device[MAXNAMLEN] = _PATH_DEV; ! 47: static char errbuf[1024]; ! 48: register int cnt, fd, left, wret; ! 49: char *strcpy(), *strerror(); ! 50: struct iovec localiov[6]; ! 51: int forked = 0; ! 52: ! 53: if (iovcnt > 6) ! 54: return ("too many iov's (change code in wall/ttymsg.c)"); ! 55: /* ! 56: * open will fail on slip lines or exclusive-use lines ! 57: * if not running as root; not an error. ! 58: */ ! 59: (void) strcpy(device + sizeof(_PATH_DEV) - 1, line); ! 60: if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) { ! 61: if (errno != EBUSY && errno != EACCES) { ! 62: (void) sprintf(errbuf, "open %s: %s", device, ! 63: strerror(errno)); ! 64: return (errbuf); ! 65: } else ! 66: return (NULL); ! 67: } ! 68: ! 69: for (cnt = left = 0; cnt < iovcnt; ++cnt) ! 70: left += iov[cnt].iov_len; ! 71: ! 72: for (;;) { ! 73: if ((wret = writev(fd, iov, iovcnt)) < 0) { ! 74: if (errno == EWOULDBLOCK) { ! 75: int off = 0; ! 76: int cpid; ! 77: ! 78: if (forked) { ! 79: (void) close(fd); ! 80: /* return ("already forked"); */ ! 81: /* "can't happen" */ ! 82: exit(1); ! 83: } ! 84: cpid = fork(); ! 85: if (cpid < 0) { ! 86: (void) sprintf(errbuf, "can't fork: %s", ! 87: strerror(errno)); ! 88: (void) close(fd); ! 89: return (errbuf); ! 90: } ! 91: if (cpid) { /* parent */ ! 92: (void) close(fd); ! 93: return (NULL); ! 94: } ! 95: forked++; ! 96: /* wait at most 5 minutes */ ! 97: (void) signal(SIGALRM, SIG_DFL); ! 98: (void) signal(SIGTERM, SIG_DFL); /* XXX */ ! 99: (void) sigsetmask(0); ! 100: (void) alarm((u_int)(60 * 5)); ! 101: (void) fcntl(fd, FNDELAY, &off); ! 102: continue; ! 103: } else { ! 104: /* ! 105: * we get ENODEV on a slip line if we're ! 106: * running as root, and EIO if the line ! 107: * just went away ! 108: */ ! 109: if (errno == ENODEV || errno == EIO) ! 110: break; ! 111: (void) sprintf(errbuf, "writing %s: %s", ! 112: device, strerror(errno)); ! 113: (void) close(fd); ! 114: return (errbuf); ! 115: } ! 116: } ! 117: if (wret < left) { ! 118: left -= wret; ! 119: if (iov != localiov) { ! 120: bcopy(iov, localiov, ! 121: iovcnt * sizeof (struct iovec)); ! 122: iov = localiov; ! 123: } ! 124: for (cnt = 0; wret >= iov->iov_len; ++cnt) { ! 125: wret -= iov->iov_len; ! 126: ++iov; ! 127: --iovcnt; ! 128: } ! 129: if (wret) { ! 130: iov->iov_base += wret; ! 131: iov->iov_len -= wret; ! 132: } ! 133: } else ! 134: break; ! 135: } ! 136: if (forked) ! 137: exit(0); ! 138: (void) close(fd); ! 139: return (NULL); ! 140: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.