|
|
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 - metrics - 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);
}