|
|
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.