[patch] new pty allocation strategy for BSD



Hi,

subshell.c currently contains hard-coded values for the available pty names. These names do not match with the ptys that can be found on actual systems. NetBSD 3.0 has ptyp[0-9A-Za-z], as well as pty[qrs][0-9A-Za-z], so mc can only use 64 of the 100 available ptys.

There may be similar issues on other systems, I haven't checked.

The appended patch just scans through the /dev/ directory, looking for anything that matches /^pty..$/.

Roland
Index: subshell.c
===================================================================
RCS file: /cvsroot/mc/mc/src/subshell.c,v
retrieving revision 1.90
diff -u -p -r1.90 subshell.c
--- subshell.c	23 Jan 2006 18:55:36 -0000	1.90
+++ subshell.c	4 Feb 2006 11:57:08 -0000
@@ -39,6 +39,10 @@
 #endif
 #include <unistd.h>
 
+#ifndef HAVE_GRANTPT
+#  include <dirent.h>
+#endif
+
 #ifdef HAVE_STROPTS_H
 #  include <stropts.h> /* For I_PUSH */
 #endif /* HAVE_STROPTS_H */
@@ -67,7 +71,7 @@ static char tcsh_fifo[128];
 static void init_raw_mode (void);
 static int feed_subshell (int how, int fail_on_error);
 static void synchronize (void);
-static int pty_open_master (char *pty_name);
+static int pty_open_master (char *pty_name, size_t pty_name_size);
 static int pty_open_slave (const char *pty_name);
 static int resize_tty (int fd);
 
@@ -406,7 +410,7 @@ init_subshell (void)
 
 	/* FIXME: We may need to open a fresh pty each time on SVR4 */
 
-	subshell_pty = pty_open_master (pty_name);
+	subshell_pty = pty_open_master (pty_name, sizeof(pty_name));
 	if (subshell_pty == -1) {
 	    fprintf (stderr, "Cannot open master side of pty: %s\r\n",
 		     unix_error_string (errno));
@@ -1071,7 +1075,7 @@ static void synchronize (void)
 
 /* System V version of pty_open_master */
 
-static int pty_open_master (char *pty_name)
+static int pty_open_master (char *pty_name, size_t pty_name_size)
 {
     char *slave_name;
     int pty_master;
@@ -1082,10 +1086,10 @@ static int pty_open_master (char *pty_na
     /* getpt () is a GNU extension (glibc 2.1.x) */
     pty_master = getpt ();
 #elif IS_AIX
-    strcpy (pty_name, "/dev/ptc");
+    g_strlcpy (pty_name, "/dev/ptc", pty_name_size);
     pty_master = open (pty_name, O_RDWR);
 #else
-    strcpy (pty_name, "/dev/ptmx");
+    g_strlcpy (pty_name, "/dev/ptmx", pty_name_size);
     pty_master = open (pty_name, O_RDWR);
 #endif 
 
@@ -1099,7 +1103,7 @@ static int pty_open_master (char *pty_na
 	close (pty_master);
 	return -1;
     }
-    strcpy (pty_name, slave_name);
+    g_strlcpy (pty_name, slave_name, pty_name_size);
     return pty_master;
 }
 
@@ -1151,36 +1155,45 @@ pty_open_slave (const char *pty_name)
 #else /* !HAVE_GRANTPT */
 
 /* BSD version of pty_open_master */
-static int pty_open_master (char *pty_name)
+static int pty_open_master (char *pty_name, size_t pty_name_size)
 {
     int pty_master;
-    const char *ptr1, *ptr2;
+    DIR *dir;
+    struct dirent *ent;
+    const char *p;
 
-    strcpy (pty_name, "/dev/ptyXX");
-    for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1; ++ptr1)
-    {
-	pty_name [8] = *ptr1;
-	for (ptr2 = "0123456789abcdef"; *ptr2; ++ptr2)
-	{
-	    pty_name [9] = *ptr2;
+    pty_master = -1;
 
-	    /* Try to open master */
-	    if ((pty_master = open (pty_name, O_RDWR)) == -1) {
-		if (errno == ENOENT)  /* Different from EIO */
-		    return -1;	      /* Out of pty devices */
-		else
-		    continue;	      /* Try next pty device */
-	    }
-	    pty_name [5] = 't';	      /* Change "pty" to "tty" */
-	    if (access (pty_name, 6)){
-		close (pty_master);
-		pty_name [5] = 'p';
-		continue;
-	    }
-	    return pty_master;
-	}
+    if ((dir = opendir ("/dev")) == NULL)
+	return -1;
+
+    while ((ent = readdir (dir)) != NULL) {
+
+	/* d_name =~ qr"^pty..$" */
+    	p = ent->d_name;
+	if (!(*p++ == 'p' && *p++ == 't' && *p++ == 'y' &&
+	      *p++ != '\0' && *p++ != '\0' && *p++ == '\0')) {
+	    continue;
+	}
+
+	if (g_strlcpy (pty_name, "/dev/", pty_name_size) >= pty_name_size ||
+	    g_strlcat (pty_name, ent->d_name, pty_name_size) >= pty_name_size)
+	    break;		/* pty_name too short */
+
+	/* Try to open master */
+	if ((pty_master = open (pty_name, O_RDWR)) == -1)
+	    continue;
+
+	pty_name [5] = 't';	/* Change "/dev/pty" to "/dev/tty" */
+	if (access (pty_name, W_OK | R_OK) == 0)
+	    break;		/* We've found a terminal */
+
+	close (pty_master);
+	pty_master = -1;
     }
-    return -1;  /* Ran out of pty devices */
+
+    closedir (dir);
+    return pty_master;
 }
 
 /* BSD version of pty_open_slave */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]