BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / wall / ttymsg.c
index 62dfd14..71a3ca1 100644 (file)
@@ -2,39 +2,57 @@
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)ttymsg.c   5.5 (Berkeley) 6/29/90";
+static char sccsid[] = "@(#)ttymsg.c   5.8 (Berkeley) 7/1/91";
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/uio.h>
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/uio.h>
-#include <sys/file.h>
-#include <sys/signal.h>
+#include <signal.h>
+#include <fcntl.h>
 #include <dirent.h>
 #include <errno.h>
 #include <paths.h>
 #include <dirent.h>
 #include <errno.h>
 #include <paths.h>
+#include <unistd.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
 
 /*
 
 /*
- * display the contents of a uio structure on a terminal.  Used by
- * wall(1) and syslogd(8).  Forks and finishes in child if write
- * would block, waiting at most five minutes.
- * Returns pointer to error string on unexpected error;
- * string is not newline-terminated.  Various "normal" errors
- * are ignored (exclusive-use, lack of permission, etc.).
+ * Display the contents of a uio structure on a terminal.  Used by wall(1)
+ * and syslogd(8).  Forks and finishes in child if write would block, waiting
+ * at most five minutes.  Returns pointer to error string on unexpected error;
+ * string is not newline-terminated.  Various "normal" errors are ignored
+ * (exclusive-use, lack of permission, etc.).
  */
 char *
 ttymsg(iov, iovcnt, line)
  */
 char *
 ttymsg(iov, iovcnt, line)
@@ -42,11 +60,9 @@ ttymsg(iov, iovcnt, line)
        int iovcnt;
        char *line;
 {
        int iovcnt;
        char *line;
 {
-       extern int errno;
        static char device[MAXNAMLEN] = _PATH_DEV;
        static char errbuf[1024];
        register int cnt, fd, left, wret;
        static char device[MAXNAMLEN] = _PATH_DEV;
        static char errbuf[1024];
        register int cnt, fd, left, wret;
-       char *strcpy(), *strerror();
        struct iovec localiov[6];
        int forked = 0;
 
        struct iovec localiov[6];
        int forked = 0;
 
@@ -58,67 +74,25 @@ ttymsg(iov, iovcnt, line)
         */
        (void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
        if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
         */
        (void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
        if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
-               if (errno != EBUSY && errno != EACCES) {
-                       (void) sprintf(errbuf, "open %s: %s", device,
-                           strerror(errno));
-                       return (errbuf);
-               } else
+               if (errno == EBUSY || errno == EACCES)
                        return (NULL);
                        return (NULL);
+               (void) snprintf(errbuf, sizeof(errbuf),
+                   "%s: %s", device, strerror(errno));
+               return (errbuf);
        }
 
        for (cnt = left = 0; cnt < iovcnt; ++cnt)
                left += iov[cnt].iov_len;
 
        for (;;) {
        }
 
        for (cnt = left = 0; cnt < iovcnt; ++cnt)
                left += iov[cnt].iov_len;
 
        for (;;) {
-               if ((wret = writev(fd, iov, iovcnt)) < 0) {
-                       if (errno == EWOULDBLOCK) {
-                               int off = 0;
-                               int cpid;
-
-                               if (forked) {
-                                       (void) close(fd);
-                                       /* return ("already forked"); */
-                                       /* "can't happen" */
-                                       exit(1);
-                               }
-                               cpid = fork();
-                               if (cpid < 0) {
-                                       (void) sprintf(errbuf, "can't fork: %s",
-                                               strerror(errno));
-                                       (void) close(fd);
-                                       return (errbuf);
-                               }
-                               if (cpid) {     /* parent */
-                                       (void) close(fd);
-                                       return (NULL);
-                               }
-                               forked++;
-                               /* wait at most 5 minutes */
-                               (void) signal(SIGALRM, SIG_DFL);
-                               (void) signal(SIGTERM, SIG_DFL); /* XXX */
-                               (void) sigsetmask(0);
-                               (void) alarm((u_int)(60 * 5));
-                               (void) fcntl(fd, FNDELAY, &off);
-                               continue;
-                       } else {
-                               /*
-                                * we get ENODEV on a slip line if we're
-                                * running as root, and EIO if the line
-                                * just went away
-                                */
-                               if (errno == ENODEV || errno == EIO)
-                                       break;
-                               (void) sprintf(errbuf, "writing %s: %s",
-                                   device, strerror(errno));
-                               (void) close(fd);
-                               return (errbuf);
-                       }
-               } 
-               if (wret < left) {
+               wret = writev(fd, iov, iovcnt);
+               if (wret >= left)
+                       break;
+               if (wret >= 0) {
                        left -= wret;
                        if (iov != localiov) {
                                bcopy(iov, localiov, 
                        left -= wret;
                        if (iov != localiov) {
                                bcopy(iov, localiov, 
-                                       iovcnt * sizeof (struct iovec));
+                                   iovcnt * sizeof(struct iovec));
                                iov = localiov;
                        }
                        for (cnt = 0; wret >= iov->iov_len; ++cnt) {
                                iov = localiov;
                        }
                        for (cnt = 0; wret >= iov->iov_len; ++cnt) {
@@ -130,11 +104,51 @@ ttymsg(iov, iovcnt, line)
                                iov->iov_base += wret;
                                iov->iov_len -= wret;
                        }
                                iov->iov_base += wret;
                                iov->iov_len -= wret;
                        }
-               } else
+                       continue;
+               }
+               if (errno == EWOULDBLOCK) {
+                       int cpid, off = 0;
+
+                       if (forked) {
+                               (void) close(fd);
+                               _exit(1);
+                       }
+                       cpid = fork();
+                       if (cpid < 0) {
+                               (void) snprintf(errbuf, sizeof(errbuf),
+                                   "fork: %s", strerror(errno));
+                               (void) close(fd);
+                               return (errbuf);
+                       }
+                       if (cpid) {     /* parent */
+                               (void) close(fd);
+                               return (NULL);
+                       }
+                       forked++;
+                       /* wait at most 5 minutes */
+                       (void) signal(SIGALRM, SIG_DFL);
+                       (void) signal(SIGTERM, SIG_DFL); /* XXX */
+                       (void) sigsetmask(0);
+                       (void) alarm((u_int)(60 * 5));
+                       (void) fcntl(fd, O_NONBLOCK, &off);
+                       continue;
+               } 
+               /*
+                * We get ENODEV on a slip line if we're running as root,
+                * and EIO if the line just went away.
+                */
+               if (errno == ENODEV || errno == EIO)
                        break;
                        break;
+               (void) close(fd);
+               if (forked)
+                       _exit(1);
+               (void) snprintf(errbuf, sizeof(errbuf),
+                   "%s: %s", device, strerror(errno));
+               return (errbuf);
        }
        }
-       if (forked)
-               exit(0);
+
        (void) close(fd);
        (void) close(fd);
+       if (forked)
+               _exit(0);
        return (NULL);
 }
        return (NULL);
 }