2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)ttymsg.c 8.2 (Berkeley) 11/16/93
34 * $FreeBSD: src/usr.bin/wall/ttymsg.c,v 1.4.2.3 2001/10/18 08:08:17 des Exp $
35 * $DragonFly: src/usr.bin/wall/ttymsg.c,v 1.3 2005/08/08 16:39:17 joerg Exp $
38 #include <sys/types.h>
53 * Display the contents of a uio structure on a terminal. Used by wall(1),
54 * syslogd(8), and talkd(8). Forks and finishes in child if write would block,
55 * waiting up to tmout seconds. Returns pointer to error string on unexpected
56 * error; string is not newline-terminated. Various "normal" errors are
57 * ignored (exclusive-use, lack of permission, etc.).
60 ttymsg(struct iovec
*iov
, int iovcnt
, const char *line
, int tmout
)
62 struct iovec localiov
[7];
65 static char device
[PATH_MAX
] = _PATH_DEV
;
66 static char errbuf
[1024];
71 if (iovcnt
> (int)(sizeof(localiov
) / sizeof(localiov
[0])))
72 return ("too many iov's (change code in wall/ttymsg.c)");
74 p
= device
+ sizeof(_PATH_DEV
) - 1;
75 strlcpy(p
, line
, sizeof(device
));
76 if (!strncmp(p
, "pts/", 4))
78 if (strchr(p
, '/') != NULL
) {
79 /* A slash is an attempt to break security... */
80 (void) snprintf(errbuf
, sizeof(errbuf
),
81 "Too many '/' in \"%s\"", device
);
86 * open will fail on slip lines or exclusive-use lines
87 * if not running as root; not an error.
89 if ((fd
= open(device
, O_WRONLY
|O_NONBLOCK
, 0)) < 0) {
90 if (errno
== EBUSY
|| errno
== EACCES
)
92 (void) snprintf(errbuf
, sizeof(errbuf
), "%s: %s", device
,
97 for (cnt
= 0, left
= 0; cnt
< iovcnt
; ++cnt
)
98 left
+= iov
[cnt
].iov_len
;
101 wret
= writev(fd
, iov
, iovcnt
);
106 if (iov
!= localiov
) {
108 iovcnt
* sizeof(struct iovec
));
111 for (cnt
= 0; (size_t)wret
>= iov
->iov_len
; ++cnt
) {
112 wret
-= iov
->iov_len
;
117 iov
->iov_base
+= wret
;
118 iov
->iov_len
-= wret
;
122 if (errno
== EWOULDBLOCK
) {
131 (void) snprintf(errbuf
, sizeof(errbuf
),
132 "fork: %s", strerror(errno
));
136 if (cpid
) { /* parent */
141 /* wait at most tmout seconds */
142 (void) signal(SIGALRM
, SIG_DFL
);
143 (void) signal(SIGTERM
, SIG_DFL
); /* XXX */
144 (void) sigsetmask(0);
145 (void) alarm((u_int
)tmout
);
146 (void) fcntl(fd
, F_SETFL
, 0); /* clear O_NONBLOCK */
150 * We get ENODEV on a slip line if we're running as root,
151 * and EIO if the line just went away.
153 if (errno
== ENODEV
|| errno
== EIO
)
158 (void) snprintf(errbuf
, sizeof(errbuf
),
159 "%s: %s", device
, strerror(errno
));