(linenum→info "unix/slp.c:2238")

glibc/2.7/login/openpty.c

    1: /* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3:    Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <errno.h>
   21: #include <fcntl.h>
   22: #include <limits.h>
   23: #include <pty.h>
   24: #include <stdlib.h>
   25: #include <string.h>
   26: #include <termios.h>
   27: #include <unistd.h>
   28: #include <sys/types.h>
   29: 
   30: 
   31: /* Return the result of ptsname_r in the buffer pointed to by PTS,
   32:    which should be of length BUF_LEN.  If it is too long to fit in
   33:    this buffer, a sufficiently long buffer is allocated using malloc,
   34:    and returned in PTS.  0 is returned upon success, -1 otherwise.  */
   35: static int
   36: pts_name (int fd, char **pts, size_t buf_len)
   37: {
   38:   int rv;
   39:   char *buf = *pts;
   40: 
   41:   for (;;)
   42:     {
   43:       char *new_buf;
   44: 
   45:       if (buf_len)
   46:         {
   47:           rv = ptsname_r (fd, buf, buf_len);
   48: 
   49:           if (rv != 0 || memchr (buf, '\0', buf_len))
   50:             /* We either got an error, or we succeeded and the
   51:                returned name fit in the buffer.  */
   52:             break;
   53: 
   54:           /* Try again with a longer buffer.  */
   55:           buf_len += buf_len;  /* Double it */
   56:         }
   57:       else
   58:         /* No initial buffer; start out by mallocing one.  */
   59:         buf_len = 128;         /* First time guess.  */
   60: 
   61:       if (buf != *pts)
   62:         /* We've already malloced another buffer at least once.  */
   63:         new_buf = realloc (buf, buf_len);
   64:       else
   65:         new_buf = malloc (buf_len);
   66:       if (! new_buf)
   67:         {
   68:           rv = -1;
   69:           __set_errno (ENOMEM);
   70:           break;
   71:         }
   72:       buf = new_buf;
   73:     }
   74: 
   75:   if (rv == 0)
   76:     *pts = buf;         /* Return buffer to the user.  */
   77:   else if (buf != *pts)
   78:     free (buf);         /* Free what we malloced when returning an error.  */
   79: 
   80:   return rv;
   81: }
   82: 
   83: /* Create pseudo tty master slave pair and set terminal attributes
   84:    according to TERMP and WINP.  Return handles for both ends in
   85:    AMASTER and ASLAVE, and return the name of the slave end in NAME.  */
   86: int
   87: openpty (int *amaster, int *aslave, char *name, struct termios *termp,
   88:          struct winsize *winp)
   89: {
   90: #ifdef PATH_MAX
   91:   char _buf[PATH_MAX];
   92: #else
   93:   char _buf[512];
   94: #endif
   95:   char *buf = _buf;
   96:   int master, slave;
   97: 
   98:   master = getpt ();
   99:   if (master == -1)
  100:     return -1;
  101: 
  102:   if (grantpt (master))
  103:     goto fail;
  104: 
  105:   if (unlockpt (master))
  106:     goto fail;
  107: 
  108:   if (pts_name (master, &buf, sizeof (_buf)))
  109:     goto fail;
  110: 
  111:   slave = open (buf, O_RDWR | O_NOCTTY);
  112:   if (slave == -1)
  113:     {
  114:       if (buf != _buf)
  115:         free (buf);
  116: 
  117:       goto fail;
  118:     }
  119: 
  120:   /* XXX Should we ignore errors here?  */
  121:   if(termp)
  122:     tcsetattr (slave, TCSAFLUSH, termp);
  123:   if (winp)
  124:     ioctl (slave, TIOCSWINSZ, winp);
  125: 
  126:   *amaster = master;
  127:   *aslave = slave;
  128:   if (name != NULL)
  129:     strcpy (name, buf);
  130: 
  131:   if (buf != _buf)
  132:     free (buf);
  133:   return 0;
  134: 
  135:  fail:
  136:   close (master);
  137:   return -1;
  138: }
  139: libutil_hidden_def (openpty)
Syntax (Markdown)