This is openpty.c in view mode; [Download] [Up]
/* * openpty - open a pseudo-terminal * * The first time that the routine is called, the device directory is * searched and a list of all candidate pseudo-terminals is compiled. * Candidates are defined to be those entries in "/dev" whose names * (1) are the same length as PTY_PROTO and (2) start with the * initial string PTY_PREFIX. Further, the master and slave sides * must both exist. * * openpty() attempts to find an unused pseudo-terminal from the list * of candidates. If one is found, the master and slave sides are * opened and the file descriptors and names of these two devices are * returned in a "ptydesc" structure. (The address of this structure * is supplied by the caller. Zero is returned if openpty() was * successful, -1 is returned if no pty could be found. */ #include <sys/types.h> #include <sys/dir.h> #include <fcntl.h> #include <strings.h> #include "openpty.h" #define DEV_DIR "/dev" /* directory where devices live */ #define PT_INDEX (sizeof DEV_DIR) /* location of 'p' in "pty" */ #define PTY_PROTO "ptyp0" /* prototype for pty names */ #define PTY_PREFIX "pty" /* prefix required for name of pty */ struct ptyinfo { struct ptyinfo *pi_next; char *pi_pty; char *pi_tty; }; static struct ptyinfo *ptylist; extern char *malloc(); static char * devname(name) char *name; { register char *fullname; /* * Construct the full name of a device in DEV_DIR. Returns * NULL if it failed (because malloc() failed). */ fullname = malloc((unsigned)(sizeof DEV_DIR + 1 + strlen(name))); if (fullname != NULL) { (void)strcpy(fullname, DEV_DIR); (void)strcat(fullname, "/"); (void)strcat(fullname, name); } return(fullname); } static isapty(dp) struct direct *dp; { static struct ptyinfo *pi; /* * We don't care about the gory details of the directory entry. * Instead, what we really want is an array of pointers to * device names (with DEV_DIR prepended). Therefore, we create * this array ourselves and tell scandir() to ignore every * directory entry. * * If malloc() fails, the current directory entry is ignored. */ if (pi == NULL) { pi = (struct ptyinfo *)malloc((unsigned)sizeof *pi); if (pi == NULL) return(0); } if (strlen(dp->d_name) == sizeof PTY_PROTO - 1 && strncmp(dp->d_name, PTY_PREFIX, sizeof PTY_PREFIX - 1) == 0) { pi->pi_pty = devname(dp->d_name); if (pi->pi_pty == NULL) return(0); pi->pi_tty = malloc((unsigned)(strlen(pi->pi_pty) + 1)); if (pi->pi_tty == NULL) { free(pi->pi_pty); return(0); } (void)strcpy(pi->pi_tty, pi->pi_pty); pi->pi_tty[PT_INDEX] = 't'; if (access(pi->pi_pty, 0) == 0 && access(pi->pi_tty, 0) == 0) { pi->pi_next = ptylist; ptylist = pi; pi = NULL; } else { free(pi->pi_pty); free(pi->pi_tty); } } return(0); } openpty(pt) struct ptydesc *pt; { register struct ptyinfo *pi; static int fail; auto struct direct **dirlist; extern char *re_comp(); extern int alphasort(); /* * If scandir() fails or no possible pty's are found, then "fail" * is set non-zero. If "fail" is non-zero then the routine bombs * out immediately. Otherwise, the list of candidates is examined * starting with the entry following the last one chosen. */ if (fail) return(-1); if (!ptylist) { /* first time */ if (scandir(DEV_DIR, &dirlist, isapty, alphasort) < 0 || ptylist == NULL) { fail = 1; return(-1); } for (pi=ptylist; pi->pi_next; pi=pi->pi_next) ; pi->pi_next = ptylist; /* make the list circular */ } pi = ptylist; do { if ((pt->pt_pfd = open(pi->pi_pty, O_RDWR)) >= 0) { if ((pt->pt_tfd = open(pi->pi_tty, O_RDWR)) >= 0) { ptylist = pi->pi_next; pt->pt_pname = pi->pi_pty; pt->pt_tname = pi->pi_tty; return(0); } else (void)close(pt->pt_pfd); } pi = pi->pi_next; } while (pi != ptylist); return(-1); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.