secondary cache feature in vm.
[minix.git] / lib / libutil / openpty.c
blobe280800762ef4cc18fad5128cc7e5b80db2c2821
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];
33 register int i, j;
34 static char tty_name[128];
35 struct group *ttygroup;
36 gid_t tty_gid = 0;
38 if(!amaster || !aslave) {
39 errno = EINVAL;
40 return -1;
43 for(i = 'p'; i < 'w'; i++) {
44 j = 0;
45 do {
46 sprintf(buff, "%s/pty%c%c",
47 DEV_DIR, i, (j < 10) ? j + '0' : j + 'a' - 10);
49 if((*amaster = open(buff, O_RDWR)) >= 0) {
50 sprintf(tty_name, "%s/tty%c%c", DEV_DIR,
51 i, (j < 10) ? j + '0' : j + 'a' - 10);
52 if((*aslave = open(tty_name, O_RDWR)) >= 0)
53 break;
55 close(*amaster);
57 j++;
58 if (j == 16) break;
59 } while(1);
61 /* Did we find one? */
62 if (j < 16) break;
64 if (*amaster < 0) { errno = ENOENT; return(-1); }
66 setgrent();
67 ttygroup = getgrnam("tty");
68 endgrent();
69 if(ttygroup) tty_gid = ttygroup->gr_gid;
71 if(name) strcpy(name, tty_name);
73 /* Ignore errors on these. */
74 chown(tty_name, getuid(), tty_gid);
75 chmod(tty_name, 0620); /* -rw--w---- */
76 if(termp) tcsetattr(*aslave, TCSAFLUSH, termp);
77 if(winp) ioctl(*aslave, TIOCSWINSZ, winp);
79 return(0);