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