root/maint/gnulib/tests/test-ptsname.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. same_slave
  2. main

   1 /* Test of ptsname(3).
   2    Copyright (C) 2010-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 #include <config.h>
  18 
  19 #include <stdlib.h>
  20 
  21 #include "signature.h"
  22 SIGNATURE_CHECK (ptsname, char *, (int));
  23 
  24 #include <errno.h>
  25 #include <fcntl.h>
  26 #include <signal.h>
  27 #include <stdio.h>
  28 #include <string.h>
  29 #include <unistd.h>
  30 #include <sys/stat.h>
  31 
  32 #include "same-inode.h"
  33 
  34 #include "macros.h"
  35 
  36 /* Compare two slave names.
  37    On some systems, there are hard links in the /dev/ directory.
  38    For example, on OSF/1 5.1,
  39      /dev/ttyp0 == /dev/pts/0
  40      /dev/ttyp9 == /dev/pts/9
  41      /dev/ttypa == /dev/pts/10
  42      /dev/ttype == /dev/pts/14
  43  */
  44 static int
  45 same_slave (const char *slave_name1, const char *slave_name2)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47   struct stat statbuf1;
  48   struct stat statbuf2;
  49 
  50   return (strcmp (slave_name1, slave_name2) == 0
  51           || (stat (slave_name1, &statbuf1) >= 0
  52               && stat (slave_name2, &statbuf2) >= 0
  53               && SAME_INODE (statbuf1, statbuf2)));
  54 }
  55 
  56 int
  57 main (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59 #if HAVE_DECL_ALARM
  60   /* Declare failure if test takes too long, by using default abort
  61      caused by SIGALRM.  */
  62 # if defined _AIX
  63   int alarm_value = 20;
  64 # else
  65   int alarm_value = 5;
  66 # endif
  67   signal (SIGALRM, SIG_DFL);
  68   alarm (alarm_value);
  69 #endif
  70 
  71   {
  72     char *result;
  73 
  74     errno = 0;
  75     result = ptsname (-1);
  76     ASSERT (result == NULL);
  77     ASSERT (errno == EBADF
  78             || errno == ENOTTY /* seen on glibc */
  79            );
  80   }
  81 
  82   {
  83     int fd;
  84     char *result;
  85 
  86     /* Open the controlling tty of the current process.  */
  87     fd = open ("/dev/tty", O_RDONLY);
  88     if (fd < 0)
  89       {
  90         fprintf (stderr, "Skipping test: cannot open controlling tty\n");
  91         return 77;
  92       }
  93 
  94     result = ptsname (fd);
  95     /* The result is usually NULL, because /dev/tty is a slave, not a
  96        master.  */
  97     if (result != NULL)
  98       {
  99         ASSERT (memcmp (result, "/dev/", 5) == 0);
 100       }
 101 
 102     close (fd);
 103   }
 104 
 105 #if defined __sun || defined __DragonFly__
 106   /* Solaris has BSD-style /dev/pty[p-r][0-9a-f] files, but the function
 107      ptsname() does not work on them.
 108      DragonFly BSD has only /dev/ptmx.  */
 109   {
 110     int fd;
 111     char *result;
 112 
 113     /* Open the controlling tty of the current process.  */
 114     fd = open ("/dev/ptmx", O_RDWR | O_NOCTTY);
 115     if (fd < 0)
 116       {
 117         fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
 118         return 77;
 119       }
 120 
 121     result = ptsname (fd);
 122     ASSERT (result != NULL);
 123     ASSERT (memcmp (result, "/dev/pts/", 9) == 0);
 124 
 125     close (fd);
 126   }
 127 
 128 #elif defined _AIX
 129   /* AIX has BSD-style /dev/ptyp[0-9a-f] files, and the function ptsname()
 130      produces the corresponding /dev/ttyp[0-9a-f] file for each.  But opening
 131      such a pty causes the process to hang in a state where it does not even
 132      react to the SIGALRM signal for N * 15 seconds, where N is the number of
 133      opened ptys, either in the close (fd) call or - when this close (fd) call
 134      is commented out - at the process exit.
 135      So, better don't use these BSD-style ptys.  The modern way to open a pty
 136      is to go through /dev/ptc.  */
 137   {
 138     int fd;
 139     char *result;
 140 
 141     /* Open a pty master.  */
 142     fd = open ("/dev/ptc", O_RDWR | O_NOCTTY);
 143     if (fd < 0)
 144       {
 145         fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
 146         return 77;
 147       }
 148 
 149     result = ptsname (fd);
 150     ASSERT (result != NULL);
 151     ASSERT (memcmp (result, "/dev/pts/", 9) == 0);
 152 
 153     /* This close (fd) call takes 15 seconds.  It would be interruptible by the
 154        SIGALRM timer, but then this test would report failure.  */
 155     close (fd);
 156   }
 157 
 158 #else
 159 
 160   /* Try various master names of Mac OS X: /dev/pty[p-w][0-9a-f]  */
 161   {
 162     int char1;
 163     int char2;
 164 
 165     for (char1 = 'p'; char1 <= 'w'; char1++)
 166       for (char2 = '0'; char2 <= 'f'; (char2 == '9' ? char2 = 'a' : char2++))
 167         {
 168           char master_name[32];
 169           int fd;
 170 
 171           sprintf (master_name, "/dev/pty%c%c", char1, char2);
 172           fd = open (master_name, O_RDONLY);
 173           if (fd >= 0)
 174             {
 175               char *result;
 176               char slave_name[32];
 177 
 178               result = ptsname (fd);
 179               ASSERT (result != NULL);
 180               sprintf (slave_name, "/dev/tty%c%c", char1, char2);
 181               ASSERT (same_slave (result, slave_name));
 182 
 183               close (fd);
 184             }
 185         }
 186   }
 187 
 188   /* Try various master names of *BSD: /dev/pty[p-sP-S][0-9a-v]  */
 189   {
 190     int upper;
 191     int char1;
 192     int char2;
 193 
 194     for (upper = 0; upper <= 1; upper++)
 195       for (char1 = (upper ? 'P' : 'p'); char1 <= (upper ? 'S' : 's'); char1++)
 196         for (char2 = '0'; char2 <= 'v'; (char2 == '9' ? char2 = 'a' : char2++))
 197           {
 198             char master_name[32];
 199             int fd;
 200 
 201             sprintf (master_name, "/dev/pty%c%c", char1, char2);
 202             fd = open (master_name, O_RDONLY);
 203             if (fd >= 0)
 204               {
 205                 char *result;
 206                 char slave_name[32];
 207 
 208                 result = ptsname (fd);
 209                 ASSERT (result != NULL);
 210                 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
 211                 ASSERT (same_slave (result, slave_name));
 212 
 213                 close (fd);
 214               }
 215           }
 216   }
 217 
 218 #endif
 219 
 220   return 0;
 221 }

/* [previous][next][first][last][top][bottom][index][help] */