map in kernel in 4MB, global-bit-set 'pages' if hardware
[minix.git] / lib / util / openpty.c
blobec6db2525e8e4855ebd74d86b6170b4de9b1302a
1 /*
2 * openpty() tries to open a pty; applications won't have to
3 * duplicate this code all the time (or change it if the system
4 * pty interface changes).
6 * First version by Ben Gras <beng@few.vu.nl>,
7 * Initially heavily based on telnetd/pty.c
8 * by Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>.
11 #include <libutil.h>
12 #include <termios.h>
13 #include <fcntl.h>
14 #include <grp.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <errno.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/ioc_tty.h>
24 #define DEV_DIR "/dev"
27 * Allocate a PTY, by trying to open one repeatedly.
29 int openpty(int *amaster, int *aslave, char *name,
30 struct termios *termp, struct winsize *winp)
32 char buff[128], temp[128];
33 register int i, j;
34 int pty_fd = -1, gr;
35 static char tty_name[128];
36 struct group *ttygroup;
37 gid_t tty_gid = 0;
39 if(!amaster || !aslave) {
40 errno = EINVAL;
41 return -1;
44 for(i = 'p'; i < 'w'; i++) {
45 j = 0;
46 do {
47 sprintf(buff, "%s/pty%c%c",
48 DEV_DIR, i, (j < 10) ? j + '0' : j + 'a' - 10);
50 if((*amaster = open(buff, O_RDWR)) >= 0) {
51 sprintf(tty_name, "%s/tty%c%c", DEV_DIR,
52 i, (j < 10) ? j + '0' : j + 'a' - 10);
53 if((*aslave = open(tty_name, O_RDWR)) >= 0)
54 break;
56 close(*amaster);
58 j++;
59 if (j == 16) break;
60 } while(1);
62 /* Did we find one? */
63 if (j < 16) break;
65 if (*amaster < 0) { errno = ENOENT; return(-1); }
67 setgrent();
68 ttygroup = getgrnam("tty");
69 endgrent();
70 if(ttygroup) tty_gid = ttygroup->gr_gid;
72 if(name) strcpy(name, tty_name);
74 /* Ignore errors on these. */
75 chown(tty_name, getuid(), tty_gid);
76 chmod(tty_name, 0620); /* -rw--w---- */
77 if(termp) tcsetattr(*aslave, TCSAFLUSH, termp);
78 if(winp) ioctl(*aslave, TIOCSWINSZ, winp);
80 return(0);