1 /*
   2  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
   3  * Copyright (c) 1990, 1993, 1994
   4  *      The Regents of the University of California.  All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  * 1. Redistributions of source code must retain the above copyright
  10  *    notice, this list of conditions and the following disclaimer.
  11  * 2. Redistributions in binary form must reproduce the above copyright
  12  *    notice, this list of conditions and the following disclaimer in the
  13  *    documentation and/or other materials provided with the distribution.
  14  * 4. Neither the name of the University nor the names of its contributors
  15  *    may be used to endorse or promote products derived from this software
  16  *    without specific prior written permission.
  17  *
  18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28  * SUCH DAMAGE.
  29  */
  30 
  31 
  32 #include <sys/types.h>
  33 #include <stropts.h>
  34 #include <errno.h>
  35 #include <fcntl.h>
  36 #include <grp.h>
  37 #include <stdlib.h>
  38 #include <string.h>
  39 #include <termios.h>
  40 #include <unistd.h>
  41 #include <limits.h>
  42 
  43 int
  44 openpty(int *amaster, int *aslave, char *name, const struct termios *termp,
  45     const struct winsize *winp)
  46 {
  47         const char *slavename;
  48         int master, slave;
  49         int err;
  50 
  51         if ((master = open("/dev/ptmx", O_RDWR|O_NOCTTY)) == -1)
  52                 return (-1);
  53 
  54         if (grantpt(master) == -1)
  55                 goto bad;
  56 
  57         if (unlockpt(master) == -1)
  58                 goto bad;
  59 
  60         slavename = ptsname(master);
  61         if (slavename == NULL) {
  62                 goto bad;
  63         }
  64 
  65         if ((slave = open(slavename, O_RDWR)) == -1)
  66                 goto bad;
  67 
  68         if (ioctl(slave, I_PUSH, "ptem") < 0 ||
  69             ioctl(slave, I_PUSH, "ldterm") < 0 ||
  70             ioctl(slave, I_PUSH, "ttcompat") < 0) {
  71                 goto bad;
  72         }
  73 
  74         if (termp != NULL) {
  75                 if (tcsetattr(slave, TCSAFLUSH, termp) != 0) {
  76                         goto bad;
  77                 }
  78         }
  79         if (winp != NULL) {
  80                 if (ioctl(slave, TIOCSWINSZ, winp) != 0)
  81                         goto bad;
  82         }
  83 
  84         *amaster = master;
  85         *aslave = slave;
  86 
  87         if (name != NULL)
  88                 (void) strncpy(name, slavename, TTYNAME_MAX);
  89         return (0);
  90 
  91 bad:
  92         err = errno;
  93         if (master != -1)
  94                 (void) close(master);
  95         if (slave != -1)
  96                 (void) close(slave);
  97         errno = err;  /* restore the original value of errno */
  98         return (-1);
  99 }
 100 
 101 int
 102 login_tty(int fd)
 103 {
 104 
 105         if (setsid() < 0) {
 106                 return (-1);
 107         }
 108 
 109         if (ioctl(fd, TIOCSCTTY, NULL) < 0)
 110                 return (-1);
 111         if (dup2(fd, 0) < 0 ||
 112             dup2(fd, 1) < 0 ||
 113             dup2(fd, 2) < 0) {
 114                 return (-1);
 115         }
 116         if (fd > 2 && close(fd) < 0)
 117                 return (-1);
 118         return (0);
 119 }
 120 
 121 int
 122 forkpty(int *amaster, char *name, const struct termios *termp,
 123     const struct winsize *winp)
 124 {
 125         int master, slave, pid;
 126         int err;
 127 
 128         if (openpty(&master, &slave, name, termp, winp) == -1)
 129                 return (-1);
 130         switch (pid = fork()) {
 131         case -1:
 132                 err = errno;
 133                 (void) close(master);
 134                 (void) close(slave);
 135                 errno = err;  /* restore the original value of errno */
 136                 return (-1);
 137                 }
 138         case 0:
 139                 /*
 140                  * child
 141                  */
 142                 (void) close(master);
 143                 if (login_tty(slave) < 0) {
 144                         return (-1);
 145                 }
 146                 return (0);
 147         }
 148         /*
 149          * parent
 150          */
 151         *amaster = master;
 152         (void) close(slave);
 153 
 154         return (pid);
 155 }