|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T s ┃
Length: 7153 (0x1bf1) Types: TextFile Names: »shell.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen └─ ⟦this⟧ »cph85dist/wm/shell.c«
/* ************* * DISTRIBUTION NOTICE July 30 1985 * A Revised Edition of WM, by Matt Lennon and Tom Truscott, * Research Triangle Institute, (919) 541-7005. * Based on the original by Robert Jacob (decvax!nrl-css!jacob), * Naval Research Laboratory, (202) 767-3365. * No claims or warranties of any sort are made for this distribution. * General permission is granted to copy, but not for profit, * any of this distribution, provided that this notice * is always included in the copies. ************* */ /* * This file contains routines dealing * with the window shells. */ #include "wm.h" #include <signal.h> #include <errno.h> static struct sgttyb sgttybuf; static struct tchars tcharsbuf; static struct ltchars ltcharsbuf; static int ttymode; static int ttydisc; static int ttyfd; /* file descriptor for /dev/tty */ /* * Initialize parameters needed for creating new window shells. */ ShellInit() { (void) ioctl(0, (int)TIOCGETD, (char*)&ttydisc); (void) ioctl(0, (int)TIOCGETC, (char*)&tcharsbuf); (void) ioctl(0, (int)TIOCLGET, (char*)&ttymode); (void) ioctl(0, (int)TIOCGLTC, (char*)<charsbuf); (void) ioctl(0, (int)TIOCGETP, (char*)&sgttybuf); /* * The psuedo-tty driver should probably not produce * internal magic delay characters (cf. sys/tty.c (ttyoutput)). * It seems easiest to turn off all delays here. * (Even that is not all that easy, due to an XTABS glitch.) */ { register int i = ALLDELAY; if ((sgttybuf.sg_flags&TBDELAY) == XTABS) i &= ~TBDELAY; sgttybuf.sg_flags &= ~i; } /* We will use 'ttyfd' later when setting * controlling terminals for new shells. */ ttyfd = open("/dev/tty", 0); strcpy(shellpgm, getenv("SHELL") ? getenv("SHELL") : "sh"); strcpy(shellname, rindex(shellpgm,'/') ? rindex(shellpgm,'/')+1 : shellpgm); } /* * spawn shell process for window number w * Finds first available pty and its matching pts and opens them * Returns TRUE if it found you some pty's else FALSE */ NewShell(w) register int w; { static char ptlist[] = "0123456789abcdef"; char ptyname[100], ptsname[100]; /* names of pty master/slave devices */ int fpty, fpts; /* descriptors for "" "" "" */ register int c, i; /* index */ int ptydisc; extern int errno; /* Look for available pty master/slave pair. */ for (c = 'p';; c++) { for (i = 0; ptlist[i]; i++) { (void) sprintf(ptyname, "/dev/pty%c%c", c, ptlist[i]); if ((fpty = open(ptyname, 2)) < 0) { if (errno == ENOENT) return(-1); continue; } (void) sprintf(ptsname, "/dev/tty%c%c", c, ptlist[i]); if ((fpts = open(ptsname, 2)) < 0) { (void) close(fpty); continue; } /* This doesn't close the security hole, * but it helps avoid certain problems. */ if (ioctl(fpts, (int)TIOCGETD, (char *)&ptydisc) || ptydisc) { (void) close(fpts); (void) close(fpty); continue; } /* Okay, this one will do */ goto gottatty; } } gottatty:; (void) ioctl(fpty, (int)FIOCLEX, (char *)0); /* Fork a new shell. */ switch (win[w].pid=fork()) { default: /* parent */ (void) close(fpts); win[w].pty=fpty; break; case 0: /* child */ /* Set up stdin, stdout, stderr streams. */ dup2(fpts,0); dup2(fpts,1); dup2(fpts,2); if (fpts > 2) (void) close(fpts); /* Set up slave as new controlling terminal. */ SetCntrlTerm(ptsname); /* Set up process groups. */ SetProcGrp(); /* Set pty terminal attributes. */ InitPseudoTty(); /* Set env variables TERM & TERMCAP. */ #ifdef SNEAKYTERMCAP SetTerm(w, 1); #else (void) setenv("TERM", "wmvirt"); (void) setenv("TERMCAP", termcap(w)); #endif /* Exec the shell. */ execlp(shellpgm, shellname, (char *)0); exit(1); /* exec failed */ break; case -1: /* fork failed */ (void) close(fpty); (void) close(fpts); break; } return(win[w].pid < 0); } /* * Set up terminal attributes for new pseudo-tty. * The attributes are those of user's regular terminal. * This way, the pseudo-tty will behave just like user's terminal. */ InitPseudoTty() { /* Set tty discipline, edit characters, * mode, etc. */ (void) ioctl(0, (int)TIOCSETP, (char*)&sgttybuf); (void) ioctl(0, (int)TIOCSETD, (char*)&ttydisc); (void) ioctl(0, (int)TIOCSETC, (char*)&tcharsbuf); (void) ioctl(0, (int)TIOCLSET, (char*)&ttymode); (void) ioctl(0, (int)TIOCSLTC, (char*)<charsbuf); } /* * Make 'cterm' the new controlling terminal for * this process. Use TIOCNOTTY to turn off * current control terminal. Then when we open * 'cterm', it automatically becomes the new * controlling terminal. * Can you say 'kludge'? I knew you could. */ SetCntrlTerm(cterm) char *cterm; { /* We really ought to check the return values * of these calls. Oh, well. */ (void) ioctl(ttyfd, (int)TIOCNOTTY, (char*)0); (void) close(ttyfd); ttyfd = open(cterm, 0); (void) close(ttyfd); } /* * Set up a new process group for a process. * Process group id will be the pid of the current process. * Also set up terminal process group for the benefit of * csh job control facilities. */ SetProcGrp() { int pgrp; pgrp = getpid(); (void) setpgrp(0, pgrp); (void) ioctl(0, (int)TIOCSPGRP, (char*)&pgrp); } /* * Kill shell (process group) in window 'w'. */ KillShell(w) register int w; { if (win[w].pid <= 0) return; /* Close pty file. */ (void) close(win[w].pty); /* Send SIGHUP to all process associated * with window w. */ (void) kill(win[w].pid, SIGHUP); #ifdef SNEAKYTERMCAP SetTerm(w, 0); #endif win[w].pid = 0; } setenv(name, val) char *name, *val; { register int n, i; register char **ep, *oldval; char *namecmp(); extern char **environ; ep = environ; /* See if the environment variable is already set. */ for (n=0; ep[n]!=NULL; n++) if ((oldval=namecmp(name,ep[n])) != NULL) break; /* If the environment variable is already set and * the new value is no longer than the old one, * we can just overwrite the old one. */ if (ep[n] != NULL && strlen(oldval) >= strlen(val)) strcpy(oldval, val); /* Else we have to reallocate (name=value). */ else { /* If environment variable not already set, * we have to reallocate entire 'environ' array * with one additional slot in order to add the new variable. * Make sure to terminate array with a NULL entry. */ if (ep[n] == NULL) { if ((ep=alloc(n+2, char*)) == NULL) return(-1); for (i=0; i<n; i++) ep[i] = environ[i]; ep[n+1] = NULL; environ = ep; } /* Allocate space for new variable, add it to 'environ'. */ if ((ep[n]=alloc(strlen(name)+strlen(val)+2, char)) == NULL) return(-1); (void) sprintf(ep[n], "%s=%s", name, val); } return(0); } static char *namecmp(s1, s2) register char *s1, *s2; { for ( ; *s1==*s2; s1++,s2++) ; if (*s1 == '\0' && *s2 == '=') return(s2+1); return(NULL); }