getttyent(3) - Update for unix98 ptys
authorAlex Hornung <ahornung@gmail.com>
Wed, 2 Sep 2009 07:26:26 +0000 (08:26 +0100)
committerAlex Hornung <ahornung@gmail.com>
Wed, 2 Sep 2009 08:40:00 +0000 (09:40 +0100)
* Update getttyent(3) to be compatible with unix98 ptys. This fixes
  problems with logins on unix98 ptys not appearing in utmp.

Obtained-from: FreeBSD

lib/libc/gen/getttyent.c

index 418f6a9..c6cbb1f 100644 (file)
  * @(#)getttyent.c     8.1 (Berkeley) 6/4/93
  */
 
+#include <sys/cdefs.h>
+
 #include <ttyent.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
+#include <dirent.h>
+#include <paths.h>
 
 static char zapchar;
 static FILE *tf;
+static int maxpts = -1;
+static int curpts = 0;
 static size_t lbsize;
 static char *line;
 
+#define PTS    "pts/"
 #define        MALLOCCHUNK     100
 
 static char *skip (char *);
@@ -71,6 +78,7 @@ struct ttyent *
 getttyent(void)
 {
        static struct ttyent tty;
+       static char devpts_name[] = "pts/9999999999";
        char *p;
        int c;
        size_t i;
@@ -78,8 +86,20 @@ getttyent(void)
        if (!tf && !setttyent())
                return (NULL);
        for (;;) {
-               if (!fgets(p = line, lbsize, tf))
+               if (!fgets(p = line, lbsize, tf)) {
+                       if (curpts <= maxpts) {
+                               sprintf(devpts_name, "pts/%d", curpts++);
+                               tty.ty_name = devpts_name;
+                               tty.ty_getty = NULL;
+                               tty.ty_type = NULL;
+                               tty.ty_status = TTY_NETWORK;
+                               tty.ty_window = NULL;
+                               tty.ty_comment = NULL;
+                               tty.ty_group = _TTYS_NOGROUP;
+                               return (&tty);
+                       }
                        return (NULL);
+               }
                /* extend buffer if line was too big, and retry */
                while (!index(p, '\n') && !feof(tf)) {
                        i = strlen(p);
@@ -205,12 +225,32 @@ value(char *p)
 int
 setttyent(void)
 {
+       DIR *devpts_dir;
+       struct dirent *dp;
+       int unit;
 
        if (line == NULL) {
                if ((line = malloc(MALLOCCHUNK)) == NULL)
                        return (0);
                lbsize = MALLOCCHUNK;
        }
+       devpts_dir = opendir(_PATH_DEV PTS);
+       if (devpts_dir) {
+               maxpts = -1;
+               while ((dp = readdir(devpts_dir))) {
+                       if (strcmp(dp->d_name, ".") == 0 ||
+                           strcmp(dp->d_name, "..") == 0)
+                               continue;
+
+                       unit = (int)strtol(dp->d_name, NULL, 10);
+
+                       if (unit > maxpts) {
+                               maxpts = unit;
+                               curpts = 0;
+                       }
+               }
+               closedir(devpts_dir);
+       }
        if (tf) {
                rewind(tf);
                return (1);
@@ -224,6 +264,7 @@ endttyent(void)
 {
        int rval;
 
+       maxpts = -1;
        /*
          * NB: Don't free `line' because getttynam()
         * may still be referencing it