1 /* pty_unicos.c - routines to allocate ptys - for CRAY UNICOS 5.1 and 6.0 */
5 Original by: Don Libes, NIST, 2/6/90
6 Hacked for Unicos 5.1 by: Frank Terhaar-Yonkers, US EPA, 1/10/91
7 Hacked for Unicos 6.0 by: Pete TerMaat, pete@willow.cray.com, 3/27/91
9 Design and implementation of this program was paid for by U.S. tax
10 dollars. Therefore it is public domain. However, the author and NIST
11 would appreciate credit if this program or parts of it are used.
15 #include "expect_cf.h"
19 #if defined(SIGCLD) && !defined(SIGCHLD)
20 #define SIGCHLD SIGCLD
26 extern int fork(), execl(), wait();
29 #include <sys/types.h>
31 #include <sys/ioctl.h>
33 #ifdef HAVE_SYS_FCNTL_H
34 # include <sys/fcntl.h>
39 #if defined(HAVE_TERMIOS)
40 # include <sys/termios.h>
42 # include <sys/termio.h>
44 #endif /* defined(HAVE_TERMIOS) */
45 #if CRAY>=70 && defined(_CRAY2)
46 #include <sys/session.h>
52 #include "exp_tty_in.h"
53 #include "exp_rename.h"
56 #include <sys/sysconfig.h>
66 #ifndef MAXHOSTNAMELEN
67 #define MAXHOSTNAMELEN 64
68 #endif /* MAXHOSTNAMELEN */
70 static char linep[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
71 static char linet[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
77 static char myname[32];
78 static char hostname[MAXHOSTNAMELEN];
79 char *exp_pty_slave_name;
84 char *s; /* args to stty */
85 char *name; /* name of pty */
87 #define MAX_ARGLIST 10240
88 char buf[MAX_ARGLIST]; /* overkill is easier */
89 RETSIGTYPE (*old)(); /* save old sigalarm handler */
91 #ifdef STTY_READS_STDOUT
92 sprintf(buf,"%s %s > %s",STTY_BIN,s,name);
94 sprintf(buf,"%s %s < %s",STTY_BIN,s,name);
96 old = signal(SIGCHLD, SIG_DFL);
98 signal(SIGCHLD, old); /* restore signal handler */
101 int exp_dev_tty; /* file descriptor to /dev/tty or -1 if none */
102 static int knew_dev_tty;/* true if we had our hands on /dev/tty at any time */
105 static struct winsize winsize = {0, 0};
107 #if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
108 static struct ttysize winsize = {0, 0};
111 /*struct termio exp_tty_original;*/
112 exp_tty exp_tty_original;
114 #define GET_TTYTYPE 0
115 #define SET_TTYTYPE 1
117 ttytype(request,fd,ttycopy,ttyinit,s)
120 /* following are used only if request == SET_TTYTYPE */
121 int ttycopy; /* true/false, copy from /dev/tty */
122 int ttyinit; /* if true, initialize to sane state */
123 char *s; /* stty args, used only if request == SET_TTYTYPE */
125 if (request == GET_TTYTYPE) {
126 if (-1 == ioctl(fd, TCGETA, (char *)&exp_tty_original)) {
127 knew_dev_tty = FALSE;
131 ioctl(fd,TIOCGWINSZ,&winsize);
133 #if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
134 ioctl(fd,TIOCGSIZE,&winsize);
136 } else { /* type == SET_TTYTYPE */
137 if (ttycopy && knew_dev_tty) {
138 (void) ioctl(fd, TCSETA, (char *)&exp_tty_current);
140 ioctl(fd,TIOCSWINSZ,&winsize);
142 #if defined(TIOCSSIZE) && !defined(TIOCSWINSZ)
143 ioctl(fd,TIOCGSIZE,&winsize);
148 /* overlay parms originally supplied by Makefile */
149 pty_stty(DFLT_STTY,linet);
152 /* lastly, give user chance to override any terminal parms */
167 highpty=sysconf(_SC_CRAY_NPTY);
170 #endif /* _SC_CRAY_NPTY */
172 ptys = (int *) malloc(sizeof(int)*(highpty+1));
174 fprintf(stderr,"exp_init_pty: couldn't allocate pty array\n");
177 for (npty = lowpty;npty <= highpty;npty++)
180 realuid=getuid(); /* get REAL uid */
181 realgid=getgid(); /* get REAL uid */
183 exp_dev_tty = open("/dev/tty",O_RDWR);
184 knew_dev_tty = (exp_dev_tty != -1);
185 if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0);
188 * Acquire (as root) current user name and host.
190 (void) cuserid(myname);
191 (void) gethostname(hostname,sizeof(hostname));
194 * Set the real and effective userids to root using 'setuid'. Then
195 * set the real and effective userids to the actual user using
196 * 'setreuid'. This allows using 'seteuid' to go back and forth from
197 * root and the actual userid. Don't ask me why it works.
200 setreuid(realuid,realuid);
203 /* returns fd of master end of pseudotty */
213 expDiagLog("exp_getptymaster: lowpty=%d highpty=%d\n",lowpty,highpty);
214 for (npty = lowpty; npty <= highpty; npty++) {
215 if (seteuid(0) == -1) { /* we need to be root! */
216 expDiagLog("exp_getptymaster: seteuid root errno=%d\n",
219 (void) sprintf(linep, "/dev/pty/%03d", npty);
220 master = open(linep, O_RDWR);
223 expDiagLog("exp_getptymaster: open linep=%s errno=%d\n",
228 (void) sprintf(linet, "/dev/ttyp%03d", npty);
229 if(stat(linet, &sb) < 0) {
230 expDiagLog("exp_getptymaster: stat linet=%s errno=%d\n",
232 (void) close(master);
235 if (sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
236 if (chown(linet, realuid, realgid) == -1) {
237 expDiagLog("exp_getptymaster: chown linet=%s errno=%d\n",
240 if (chmod(linet, 0600) == -1) {
241 expDiagLog("exp_getptymaster: chmod linet=%s errno=%d\n",
245 master = open(linep, 2);
247 expDiagLog("exp_getptymaster: reopen linep=%s errno=%d\n",
252 if (seteuid(realuid) == -1) { /* back to who we are! */
253 expDiagLog("exp_getptymaster: seteuid user errno=%d\n",
256 if (access(linet, R_OK|W_OK) != 0) {
257 expDiagLog("exp_getptymaster: access linet=%s errno=%d\n",
259 (void) close(master);
262 expDiagLog("exp_getptymaster: allocated %s\n",linet);
264 exp_pty_slave_name = linet;
267 if (seteuid(realuid) == -1) { /* back to who we are! */
268 expDiagLog("exp_getptymaster: seteuid user errno=%d\n",errno);
273 /* see comment in pty_termios.c */
276 exp_slave_control(master,control)
283 exp_getptyslave(ttycopy,ttyinit,stty_args)
290 if (0 > (slave = open(linet, O_RDWR))) {
291 expDiagLog("exp_getptyslave: open linet=%s errno=%d\n",linet,errno);
295 /* sanity check - if slave not 0, skip rest of this and return */
296 /* to what will later be detected as an error in caller */
298 expDiagLog("exp_getptyslave: slave fd not 0\n");
303 /* if opened in a new process, slave will be 0 (and */
304 /* ultimately, 1 and 2 as well) */
306 /* duplicate 0 onto 1 and 2 to prepare for stty */
311 ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args);
319 if (seteuid(0) == -1) { /* Need to be root */
320 expDiagLog("setptyutmp: setuid root errno=%d\n",errno);
323 (void) time(&utmp.ut_time);
324 utmp.ut_type = USER_PROCESS;
325 utmp.ut_pid = getpid();
326 strncpy(utmp.ut_user,myname,sizeof(utmp.ut_user));
327 strncpy(utmp.ut_host,hostname,sizeof(utmp.ut_host));
328 strncpy(utmp.ut_line,linet+5,sizeof(utmp.ut_line));
329 strncpy(utmp.ut_id,linet+8,sizeof(utmp.ut_id));
330 if (pututline(&utmp) == NULL) {
331 expDiagLog("setptyutmp: pututline failed\n");
334 if (seteuid(realuid) == -1)
335 expDiagLog("setptyutmp: seteuid user errno=%d\n",errno);
344 for (npty = lowpty; npty <= highpty; npty++) {
345 if (ptys[npty] < 0) {
346 expDiagLog("setptypid: ttyp%03d pid=%d\n",npty,pid);
357 if (seteuid(0) == -1) { /* we need to be root! */
358 expDiagLog("ttyp_reset: seteuid root errno=%d\n",errno);
360 for (npty = lowpty; npty <= highpty; npty++) {
364 (void) sprintf(linet, "/dev/ttyp%03d", npty);
365 expDiagLog("ttyp_reset: resetting %s, killing %d\n",
367 if (chown(linet,0,0) == -1) {
368 expDiagLog("ttyp_reset: chown %s errno=%d\n",linet,errno);
370 if (chmod(linet, 0666) == -1) {
371 expDiagLog("ttyp_reset: chmod %s errno=%d\n",linet,errno);
374 if (kill(ptys[npty],SIGKILL) == -1) {
375 expDiagLog("ttyp_reset: kill pid=%d errno=%d\n",
379 if (seteuid(realuid) == -1) { /* Back to who we really are */
380 expDiagLog("ttyp_reset: seteuid user errno=%d\n",errno);
395 /* set up entry to search for */
396 (void) strncpy(utmp.ut_id, linet + strlen(linet) - 4,
397 sizeof (utmp.ut_id));
398 utmp.ut_type = USER_PROCESS;
400 /* position to entry in utmp file */
401 if(getutid(&utmp) == NULL) {
402 expDiagLog("resetptyutmp: no utmp entry for %s\n",linet);
403 return(-1); /* no utmp entry for this line ??? */
406 /* set up the new entry */
407 strncpy(utmp.ut_name,"",sizeof(utmp.ut_name));
408 strncpy(utmp.ut_host,"",sizeof(utmp.ut_host));
410 utmp.ut_type = DEAD_PROCESS;
411 utmp.ut_exit.e_exit = 0;
413 /* write out the entry */