xref: /csrg-svn/usr.bin/wall/ttymsg.c (revision 40221)
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*40221Skarels static char sccsid[] = "@(#)ttymsg.c	5.3 (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*40221Skarels  * Returns pointer to error string on error;
35*40221Skarels  * string is not newline-terminated.
3639422Sbostic  */
3739422Sbostic char *
3839422Sbostic ttymsg(iov, iovcnt, line, nonblock)
3939422Sbostic 	struct iovec *iov;
4039422Sbostic 	int iovcnt;
4139422Sbostic 	char *line;
4239422Sbostic 	int nonblock;
4339422Sbostic {
4439422Sbostic 	extern int errno;
4539422Sbostic 	static char device[MAXNAMLEN] = _PATH_DEV;
4639422Sbostic 	static char errbuf[1024];
4739422Sbostic 	register int cnt, fd, total, wret;
4839422Sbostic 	char *strcpy(), *strerror();
4939422Sbostic 
5039422Sbostic 	/*
5139422Sbostic 	 * open will fail on slip lines or exclusive-use lines
5239422Sbostic 	 * if not running as root; not an error.
5339422Sbostic 	 */
5439496Skarels 	(void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
5539422Sbostic 	if ((fd = open(device, O_WRONLY|(nonblock ? O_NONBLOCK : 0), 0)) < 0)
56*40221Skarels 		if (errno != EBUSY && errno != EACCES) {
57*40221Skarels 			(void) sprintf(errbuf, "open %s: %s", device,
5839496Skarels 			    strerror(errno));
5939496Skarels 			return (errbuf);
6039496Skarels 		} else
6139496Skarels 			return (NULL);
6239422Sbostic 
6339422Sbostic 	for (cnt = total = 0; cnt < iovcnt; ++cnt)
6439422Sbostic 		total += iov[cnt].iov_len;
6539422Sbostic 
6639422Sbostic 	for (;;)
6739422Sbostic 		if ((wret = writev(fd, iov, iovcnt)) < 0)
6839422Sbostic 			if (errno == EWOULDBLOCK) {
6939496Skarels 				if (fork()) {
7039496Skarels 					(void) close(fd);
7139496Skarels 					return (NULL);
7239496Skarels 				}
7339422Sbostic 				/* wait at most 5 minutes */
7439496Skarels 				(void) signal(SIGALRM, SIG_DFL);
7539496Skarels 				(void) signal(SIGTERM, SIG_DFL); /* XXX */
7639496Skarels 				(void) sigsetmask(0);
7739496Skarels 				(void) alarm((u_int)(60 * 5));
7839496Skarels 				(void) ttymsg(iov, iovcnt, line, 0);
7939422Sbostic 				exit(0);
8039422Sbostic 			} else {
8139422Sbostic 				/*
8239422Sbostic 				 * we get ENODEV on a slip line if we're
8339422Sbostic 				 * running as root
8439422Sbostic 				 */
8539422Sbostic 				if (errno == ENODEV)
8639422Sbostic 					break;
87*40221Skarels 				(void) sprintf(errbuf, "writing %s: %s",
8839496Skarels 				    device, strerror(errno));
8939496Skarels 				(void) close(fd);
9039496Skarels 				return (errbuf);
9139422Sbostic 			}
9239422Sbostic 		else if (wret) {
9339422Sbostic 			if (wret == total)
9439422Sbostic 				break;
9539422Sbostic 			for (cnt = 0; wret >= iov->iov_len; ++cnt) {
9639422Sbostic 				wret -= iov->iov_len;
9739422Sbostic 				++iov;
9839422Sbostic 				--iovcnt;
9939422Sbostic 			}
10039422Sbostic 			if (wret) {
10139422Sbostic 				iov->iov_base += wret;
10239422Sbostic 				iov->iov_len -= wret;
10339422Sbostic 			}
10439422Sbostic 		}
10539496Skarels 	(void) close(fd);
10639496Skarels 	return (NULL);
10739422Sbostic }
108