summaryrefslogtreecommitdiffstats
path: root/src/util/pty/getpty.c
blob: b0eb602a771ac771baac410240ff03e6fb69ffd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
 * pty_getpty: open a PTY master.
 * and utmp entries.
 *
 * Copyright 1990 by the Massachusetts Institute of Technology.
 *
 * 
 *Permission to use, copy, modify, and
 * distribute this software and its documentation for any purpose and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of M.I.T. not be used in advertising or publicity pertaining
 * to distribution of the software without specific, written prior
 * permission.  M.I.T. makes no representations about the suitability of
 * this software for any purpose.  It is provided "as is" without express
 * or implied warranty.
 * 
 */

#include "mit-copyright.h"
#include <com_err.h>
#include "libpty.h"
#include "pty-int.h"

long pty_getpty (fd, slave, slavelength)
    int slavelength;
    int *fd; char *slave;
{
    char c;
    char *p;
    int i,ptynum;
    struct stat stb;
char slavebuf[1024];


#ifdef HAVE_OPENPTY
    int slavefd;

    if(openpty(fd, &slavefd, slave, (struct termios *) 0,
         (struct winsize *) 0)) return 1;
close(slavefd);
    return 0;
#else

    *fd = open("/dev/ptmx", O_RDWR|O_NDELAY);	/* Solaris, IRIX */
    if (*fd < 0) *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */
    if (*fd < 0) *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */

    if (*fd >= 0) {

#ifdef HAVE_GRANTPT
	if (grantpt(*fd) || unlockpt(*fd)) return PTY_GETPTY_STREAMS;
#endif
    
#ifdef HAVE_PTSNAME
	p = ptsname(*fd);
#else
#ifdef	HAVE_TTYNAME
	p = ttyname(*fd);
#else
	/* XXX If we don't have either what do we do */
#endif
#endif
	if (p) {
	    if ( strlen(p) > slavelength)
		{
		    close (*fd);
		    *fd = -1;
		    return PTY_GETPTY_SLAVE_TOOLONG;
		}
	    
	    strcpy(slave, p);
	    return 0;
	}

	if (fstat(*fd, &stb) < 0) {
	    close(*fd);
	    return PTY_GETPTY_FSTAT;
	}
	ptynum = (int)(stb.st_rdev&0xFF);
    sprintf(slavebuf, "/dev/ttyp%x", ptynum);
    if ( strlen(slavebuf) > slavelength) {
	close(*fd);
	*fd = -1;
	return PTY_GETPTY_SLAVE_TOOLONG;
    }
    strncpy ( slave, slavebuf, slavelength);
	return 0;

    } else {
    
	for (c = 'p'; c <= 's'; c++) {
	    sprintf(slavebuf,"/dev/ptyXX");
	    slavebuf[strlen("/dev/pty")] = c;
	    slavebuf[strlen("/dev/ptyp")] = '0';
	    if (stat(slavebuf, &stb) < 0)
		break;
	    for (i = 0; i < 16; i++) {
		slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
		*fd = open(slavebuf, O_RDWR);
		if (*fd < 0) continue;

		/* got pty */
		slavebuf[strlen("/dev/")] = 't';
		if ( strlen(slavebuf) < slavelength ) {
		    close ( *fd);
		    *fd = -1;
return PTY_GETPTY_SLAVE_TOOLONG;
		}
		strncpy ( slave, slavebuf, slavelength);
		
		return 0;
	    }
	}
	return PTY_GETPTY_NOPTY;
    }
#endif /* HAVE_OPENPTY */
}