Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/5/84; site mordor.UUCP
Path: utzoo!linus!philabs!cmcl2!seismo!ut-sally!mordor!jdb
From: jdb@mordor.UUCP (John Bruner)
Newsgroups: net.sources.mac
Subject: uw re-posting, part 3 of 3
Message-ID: <3069@mordor.UUCP>
Date: Thu, 15-Aug-85 20:35:51 EDT
Article-I.D.: mordor.3069
Posted: Thu Aug 15 20:35:51 1985
Date-Received: Mon, 19-Aug-85 20:15:02 EDT
Distribution: net
Organization: S-1 Project, LLNL
Lines: 1201
: This is a shar archive. Extract with sh, not csh.
echo x - uw.old.c
cat > uw.old.c << '!Funky!Stuff!'
#
/*
* uw - UNIX windows program for the Macintosh (VAX end)
*
* Copyright 1985 by John D. Bruner. All rights reserved. Permission to
* copy this program is given provided that the copy is not sold and that
* this copyright notice is included.
*
* Compile: cc -o uw -O uw.c
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "uw.h"
#define MAXENV 128 /* maximum environment size */
#define W_IN 0
#define W_OUT 1
#define NFDS 20 /* max number of file descriptors */
#define XON 0021 /* ASCII XON */
#define XOFF 0023 /* ASCII XOFF */
#define RUB 0177 /* ASCII RUBOUT */
#define META 0200 /* "meta" bit for whatever it's worth */
#define RCV_OK (-1) /* see recvcmd() */
#define RCV_META (-2) /* see recvcmd() */
typedef int fildes_t; /* file descriptor data type */
typedef int nwin_t; /* window index data type */
struct window {
fildes_t w_fd;
char w_tty[32];
};
struct window window[NWINDOW]; /* window data structures */
struct window *fdmap[NFDS]; /* mapping from fd's to windows */
struct window *curwin[2]; /* current input and output windows */
char portal[] = "/tmp/uwXXXXXX"; /* UNIX-domain network address */
/* The following are added to the environment of all child processes */
char env_uwin[64] = "UWIN=";
char *env[] = {
env_uwin,
"TERM=adm31",
"TERMCAP=adm31:cr=^M:do=^J:nl=^J:al=\\EE:am:le=^H:bs:ce=\\ET:cm=\\E=%+ %+ :cl=^Z:cd=\\EY:co#80:dc=\\EW:dl=\\ER:ei=\\Er:ho=^^:im=\\Eq:li#24:mi:nd=^L:up=^K:MT:km:",
NULL
};
int ctlch[] = { -1, IAC, XON, XOFF, -1, -1, -1, -1 }; /* CTL char mapping */
struct selmask {
int sm_rd;
int sm_wt;
int sm_ex;
} selmask[2];
extern char *strncpy(), *strncat();
extern char *mktemp();
extern char *getenv();
extern done(), cwait(), onalarm();
extern int errno;
main(argc, argv)
char **argv;
{
register fildes_t fd, sd;
register struct window *w;
struct sockaddr sa;
/*
* Make sure we don't accidentally try to run this inside itself.
*/
if (getenv("UWIN")) {
fprintf(stderr, "%s is already running\n", *argv);
exit(1);
}
/*
* Close all file descriptors except 0, 1, and 2.
*/
for (fd=3; fd < NFDS; fd++)
(void)close(fd);
/*
* Mark all windows closed.
*/
for (w=window; w < window+NWINDOW; w++)
w->w_fd = -1;
/*
* Create a UNIX-domain network address, and put its name into
* the environment so that descendents can contact us with new
* window requests.
*/
(void)strncat(env_uwin, mktemp(portal), sizeof env_uwin - 1);
setenv(env);
if ((sd=socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(1);
}
sa.sa_family = AF_UNIX;
(void)strncpy(sa.sa_data, portal, sizeof sa.sa_data-1);
sa.sa_data[sizeof sa.sa_data-1] = '\0';
if (bind(sd, &sa, sizeof sa.sa_family + strlen(sa.sa_data)) < 0) {
perror("bind");
exit(1);
}
if (fcntl(sd, F_SETFL, FNDELAY))
perror("fcntl(sd, F_SETFL, FNDELAY)");
/*
* Ignore interrupts, quits, and terminal stops. Clean up and exit
* if a hangup or termination is received. Also catch changes in
* child status (so that we can wait for them). Set up the terminal
* modes.
*/
(void)signal(SIGHUP, done);
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGTERM, done);
(void)signal(SIGTSTP, SIG_IGN);
(void)signal(SIGCHLD, cwait);
tmode(1);
/*
* Tell the Macintosh to initialize. Initialize the current input
* and output windows to NULL.
*/
xmitcmd(CB_FN_MAINT|CB_MF_ENTRY);
curwin[W_IN] = curwin[W_OUT] = NULL;
/*
* Initialize the "select" masks, create window 1 (to start
* things off) and wait for input. When input is available,
* process it.
*/
selmask[0].sm_rd = (1<<0)|(1<>= 1, fd++) {
if (selmask[1].sm_rd&(1<<0)) {
if (fd < 2)
mrecv();
else if (fd == sd)
netrecv(sd);
else
mxmit(fd);
}
}
}
}
mrecv()
{
register int len;
register char *cp, *cq;
auto int nready;
char ibuf[512], obuf[512];
static int seen_iac, seen_meta;
/*
* The received bytestream is examined. Non-command bytes are
* written to the file descriptor corresponding to the current
* "input" window (relative to the Macintosh -- the window the
* user types input to).
*/
if (ioctl(0, (int)FIONREAD, (char *)&nready) < 0) {
perror("FIONREAD");
return;
}
cq = obuf;
while (nready > 0) {
if (nready > sizeof ibuf)
len = read(0, ibuf, sizeof ibuf);
else
len = read(0, ibuf, nready);
if (len <= 0) {
perror("read");
return;
}
for (cp=ibuf; cp < ibuf+len; cp++) {
if (seen_iac) {
if ((*cp&CB_DIR) == CB_DIR_MTOH) {
if (cq > obuf) {
(void)write(curwin[W_IN]->w_fd,
obuf, cq-obuf);
cq = obuf;
}
switch (*cq = recvcmd(*cp)) {
case RCV_OK:
break;
case RCV_META:
seen_meta = 1;
break;
default:
if (seen_meta) {
seen_meta = 0;
*cq |= META;
}
if (curwin[W_IN])
cq++;
break;
}
}
seen_iac = 0;
} else if (*cp == IAC)
seen_iac++;
else if (curwin[W_IN]) {
if (seen_meta) {
seen_meta = 0;
*cq++ = *cp|META;
} else
*cq++ = *cp;
if (cq >= obuf+sizeof obuf) {
(void)write(curwin[W_IN]->w_fd,
obuf, cq-obuf);
cq = obuf;
}
}
}
nready -= len;
}
if (cq > obuf)
(void)write(curwin[W_IN]->w_fd, obuf, cq-obuf);
}
recvcmd(cmd)
char cmd;
{
register int nwin, fn;
register struct window *w;
/*
* Perform the function the Mac is asking for. There are three
* broad categories of these functions: RCV_META, which tells
* the caller that the next character is a "meta" character;
* an ASCII data character, which is passed back to the caller
* for proper handling; and RCV_OK, which means that this routine
* has done everything which was required to process the command.
*/
fn = cmd&CB_FN;
switch (fn) {
case CB_FN_NEWW:
case CB_FN_KILLW:
case CB_FN_ISELW:
nwin = cmd&CB_WINDOW;
if (!nwin)
break;
w = &window[nwin-1];
switch (fn) {
case CB_FN_NEWW:
if (w->w_fd < 0 && newwind(w) < 0)
xmitcmd(CB_FN_KILLW|nwin);
break;
case CB_FN_KILLW:
killwind(w, 0);
break;
case CB_FN_ISELW:
if (w->w_fd >= 0)
curwin[W_IN] = w;
break;
}
break;
case CB_FN_META:
return(RCV_META);
case CB_FN_CTLCH:
return(ctlch[cmd&CB_CC]);
case CB_FN_MAINT:
if ((cmd&CB_MF) == CB_MF_EXIT)
done(0);
/*NOTREACHED*/
}
return(RCV_OK);
}
xmitcmd(cmd)
char cmd;
{
static char cmdbuf[2] = { IAC, '\0' };
/*
* Transmit the command "cmd" to the Macintosh. The byte is ORed
* with the host-to-Mac direction indicator.
*/
cmdbuf[1] = cmd|CB_DIR_HTOM;
(void)write(1, cmdbuf, sizeof cmdbuf);
}
netrecv(sd)
register fildes_t sd;
{
register struct window *w;
register int cnt;
struct msghdr msg;
auto int fd;
struct iovec iov;
struct stat st1, st2;
static int unity = 1;
char buf[256];
/*
* main() calls this routine when there is a message waiting on
* the UNIX-domain socket. The message's access rights are
* expected to contain the file descriptor for the "master" side
* of a pseudo-tty. The message contains the name of the pty.
* The sender is expected to start up a process on the slave side
* of the pty. This allows the host end to create windows which
* run something other than the shell.
*/
fd = -1;
iov.iov_base = (caddr_t)buf;
iov.iov_len = sizeof buf - 1;
msg.msg_name = (caddr_t)0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof fd;
if ((cnt=recvmsg(sd, &msg, 0)) < 0)
perror("recvmsg");
if (msg.msg_accrightslen > 0 && fd >= 0) {
/*
* We can't trust the process which connected to us, so
* we verify that it really passed us a pseudo-tty's
* file descriptor by checking the device name and its
* inode number. [Of course, if someone else wants to
* hand us a terminal session running under their uid....]
*/
buf[cnt] = 0;
if (strncmp(buf, "/dev/ptyp", sizeof "/dev/ptyp" - 1) ||
fstat(fd, &st1) < 0 || stat(buf, &st2) < 0 ||
st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
(void)close(fd);
return;
}
/*
* OK, we believe the sender. We allocate a window and
* tell the Macintosh to create that window on its end.
*/
buf[5] = 't'; /* switch to "/dev/ttyp?" */
for (w=window; w < window+NWINDOW; w++) {
if (w->w_fd < 0) {
w->w_fd = fd;
fdmap[fd] = w;
selmask[0].sm_rd |= (1<w_tty, buf, sizeof w->w_tty-1);
xmitcmd(CB_FN_NEWW|(w-window+1));
break;
}
}
/*
* If we have no free windows, then we close the file
* descriptor (which will terminate the slave process).
*/
if (w == window+NWINDOW)
(void)close(fd);
/*
* Set non-blocking I/O on the master side.
*/
(void)ioctl(fd, FIONBIO, &unity);
}
}
mxmit(fd)
register fildes_t fd;
{
register char *cp, *cq, i;
register int len;
char ibuf[32], obuf[32];
/*
* Copy input from file "fd" to the Macintosh. Be sure to convert
* any embedded IAC characters.
*
* Note that the input/output buffers should NOT be very large.
* It is undesirable to perform large reads and effectively
* "lock out" all other file descriptors. The chosen size
* should preserve a reasonable amount of efficiency.
*/
if (fdmap[fd]) {
curwin[W_OUT] = fdmap[fd];
xmitcmd(CB_FN_OSELW|(fdmap[fd]-window+1));
cq = obuf;
if ((len = read(fd, ibuf, sizeof ibuf)) < 0 &&
errno != EWOULDBLOCK) {
killwind(fdmap[fd], 1);
return;
}
for (cp=ibuf; cp < ibuf+len; cp++) {
if (*cp&META) {
if (cq > obuf) {
(void)write(1, obuf, cq-obuf);
cq = obuf;
}
xmitcmd(CB_FN_META);
*cp &= ~META;
}
i = -1;
if (*cp == RUB || *cp < ' ') {
i = sizeof ctlch;
while (i >= 0 && ctlch[i] != *cp)
i--;
}
if (i >= 0) {
if (cq > obuf) {
(void)write(1, obuf, cq-obuf);
cq = obuf;
}
xmitcmd(CB_FN_CTLCH|i);
} else {
*cq++ = *cp;
if (cq >= obuf+sizeof obuf) {
(void)write(1, obuf, cq-obuf);
cq = obuf;
}
}
}
} else
(void)read(fd, ibuf, sizeof ibuf);
if (cq > obuf)
(void)write(1, obuf, cq-obuf);
}
killwind(w, notify)
register struct window *w;
{
register int mask;
/*
* Kill window "w". Notify the Macintosh that it is gone if
* "notify" is nonzero.
*/
(void)close(w->w_fd);
mask = ~(1<w_fd);
fdmap[w->w_fd] = NULL;
w->w_fd = -1;
if (curwin[W_IN] == w)
curwin[W_IN] = NULL;
if (curwin[W_OUT] == w)
curwin[W_OUT] = NULL;
selmask[0].sm_rd &= mask;
selmask[0].sm_wt &= mask;
selmask[0].sm_ex &= mask;
if (notify)
xmitcmd(CB_FN_KILLW|(w-window+1));
}
newwind(w)
register struct window *w;
{
register char *cp;
register fildes_t fd;
register int pid;
register char *shell;
char pty[32], ptysufx[2];
static char ptyidx[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static int unity = 1;
extern char *getenv();
/*
* Create a new window using the specified component of "window".
* This routine isn't very smart at finding pseudo-ttys.
*/
ptysufx[1] = '\0';
for (cp=ptyidx; *cp; cp++) {
ptysufx[0] = *cp;
(void)strncpy(pty, "/dev/ptyp", sizeof pty-1);
(void)strncat(pty, ptysufx, sizeof pty-1);
if ((fd = open(pty, 2)) >= 0)
break;
}
if (fd < 0)
return(-1);
(void)ioctl(fd, FIONBIO, &unity); /* set non-blocking I/O */
fdmap[fd] = w;
w->w_fd = fd;
selmask[0].sm_rd |= (1<w_tty, "/dev/ttyp", sizeof w->w_tty-1);
(void)strncat(w->w_tty, ptysufx, sizeof w->w_tty-1);
while ((pid=fork()) < 0)
sleep(5);
if (!pid) {
(void)signal(SIGHUP, SIG_DFL);
(void)signal(SIGINT, SIG_DFL);
(void)signal(SIGQUIT, SIG_DFL);
(void)signal(SIGTERM, SIG_DFL);
(void)signal(SIGTSTP, SIG_IGN);
(void)signal(SIGCHLD, SIG_DFL);
(void)ioctl(open("/dev/tty", 2), (int)TIOCNOTTY, (char *)0);
(void)setuid(getuid()); /* shouldn't need this */
if ((fd=open(w->w_tty, 2)) < 0)
_exit(1);
if (!(shell = getenv("SHELL")))
shell = "/bin/sh";
(void)dup2(fd, 0);
(void)dup2(0, 1);
(void)dup2(0, 2);
for (fd=3; fd < NFDS; fd++)
(void)close(fd);
tmode(0); /* HACK! */
execl(shell, shell, (char *)0);
_exit(1);
}
return(0);
}
tmode(f)
{
static struct sgttyb ostty, nstty;
static struct tchars otchars, ntchars;
static struct ltchars oltchars, nltchars;
static int olmode, nlmode;
static saved;
/*
* This routine either saves the current terminal modes and then
* sets up the terminal line or resets the terminal modes (depending
* upon the value of "f"). The terminal line is used in "cbreak"
* mode with all special characters except XON/XOFF disabled. The
* hated (by me) LDECCTQ mode is required for the Macintosh to
* handle flow control properly.
*/
if (f == 1) {
if (ioctl(0, (int)TIOCGETP, (char *)&ostty) < 0) {
perror("ioctl((int)TIOCGETP)");
done(1);
}
if (ioctl(0, (int)TIOCGETC, (char *)&otchars) < 0) {
perror("ioctl((int)TIOCGETC)");
done(1);
}
if (ioctl(0, (int)TIOCGLTC, (char *)&oltchars) < 0) {
perror("ioctl((int)TIOCGLTC)");
done(1);
}
if (ioctl(0, (int)TIOCLGET, (char *)&olmode) < 0) {
perror("ioctl((int)TIOCLGET)");
done(1);
}
nstty = ostty;
nstty.sg_erase = nstty.sg_kill = -1;
nstty.sg_flags |= CBREAK;
nstty.sg_flags &= ~(RAW|CRMOD|ECHO|LCASE|XTABS);
ntchars.t_intrc = ntchars.t_quitc = -1;
ntchars.t_eofc = ntchars.t_brkc = -1;
ntchars.t_startc = XON;
ntchars.t_stopc = XOFF;
nltchars.t_suspc = nltchars.t_dsuspc = -1;
nltchars.t_rprntc = nltchars.t_flushc = -1;
nltchars.t_werasc = nltchars.t_lnextc = -1;
nlmode = olmode | LDECCTQ;
if (ioctl(0, (int)TIOCSETN, (char *)&nstty) < 0) {
perror("ioctl((int)TIOCSETN)");
done(1);
}
if (ioctl(0, (int)TIOCSETC, (char *)&ntchars) < 0) {
perror("ioctl((int)TIOCSETC");
done(1);
}
if (ioctl(0, (int)TIOCSLTC, (char *)&nltchars) < 0) {
perror("ioctl((int)TIOCSLTC");
done(1);
}
if (ioctl(0, (int)TIOCLSET, (char *)&nlmode) < 0) {
perror("ioctl((int)TIOCLSET)");
done(1);
}
saved = 1;
} else if (saved) {
(void)ioctl(0, (int)TIOCSETP, (char *)&ostty);
(void)ioctl(0, (int)TIOCSETC, (char *)&otchars);
(void)ioctl(0, (int)TIOCSLTC, (char *)&oltchars);
(void)ioctl(0, (int)TIOCLSET, (char *)&olmode);
}
}
done(s)
{
register struct window *w;
register fildes_t fd;
/*
* Clean up and exit. It is overkill to close all of the file
* descriptors, but it causes no harm. After we are sure that
* our UNIX-domain network connection is closed we remove the
* entry that it created (as a side effect) in the filesystem.
*
* We also restore the terminal modes.
*/
/*xmitcmd(CB_FN_MAINT|CB_MF_EXIT);*/
for (fd=3; fd < NFDS; fd++)
(void)close(fd);
(void)unlink(portal);
tmode(0);
exit(s);
}
cwait()
{
union wait status;
struct rusage rusage;
/*
* Collect dead children. We don't use the information that
* wait3() returns. (Someday we might.)
*/
while (wait3(&status, WNOHANG, &rusage) > 0)
;
}
static char *earray[MAXENV+1];
setenv(env)
char **env;
{
register char **ep1, **ep2, *cp;
char **ep3;
extern char **environ;
/*
* Merge the set of environment strings in "env" into the
* environment.
*/
/*
* The first time through, copy the environment from its
* original location to the array "earray". This makes it a
* little easier to change things.
*/
if (environ != earray){
ep1=environ;
ep2=earray;
while(*ep1 && ep2 <= earray+MAXENV)
*ep2++ = *ep1++;
*ep2++ = NULL;
environ = earray;
}
/*
* If "env" is non-NULL, it points to a list of new items to
* be added to the environment. These replace existing items
* with the same name.
*/
if (env){
for(ep1=env; *ep1; ep1++){
for(ep2=environ; *ep2; ep2++)
if (!envcmp(*ep1, *ep2))
break;
if (ep2 < earray+MAXENV) {
if (!*ep2)
ep2[1] = NULL;
*ep2 = *ep1;
}
}
}
/* Finally, use an insertion sort to put things in order. */
for(ep1=environ+1; cp = *ep1; ep1++){
for(ep2=environ; ep2 < ep1; ep2++)
if (envcmp(*ep1, *ep2) < 0)
break;
ep3 = ep2;
for(ep2=ep1; ep2 > ep3; ep2--)
ep2[0] = ep2[-1];
*ep2 = cp;
}
}
static
envcmp(e1, e2)
register char *e1, *e2;
{
register d;
do {
if (d = *e1 - *e2++)
return(d);
} while(*e1 && *e1++ != '=');
return(0);
}
!Funky!Stuff!
echo x - uwtool.old.c
cat > uwtool.old.c << '!Funky!Stuff!'
#
/*
* uwtool
*
* Copyright 1985 by John D. Bruner. All rights reserved. Permission to
* copy this program is given provided that the copy is not sold and that
* this copyright notice is included.
*
* Compile: cc -o uwtool -O uwtool.c
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define NFDS 20 /* max number of file descriptors */
typedef int fildes_t;
extern char *strncpy(), *strncat();
extern char *getenv();
main(argc, argv)
char **argv;
{
register char *cp;
register int pid;
register fildes_t sd;
auto fildes_t fd;
char *portal, *shell;
char tty[32], pty[32], ptysufx[2];
int lmode;
struct sgttyb sg;
struct tchars tc;
struct ltchars ltc;
struct iovec iov;
struct msghdr msg;
static char ptyidx[] = "0123456789abcdefghijklmnopqrstuvwxyz";
struct sockaddr sa;
/*
* Close all file descriptors except 0, 1, and 2.
*/
for (fd=3; fd < NFDS; fd++)
(void)close(fd);
/*
* Get the terminal configuration for this tty.
*/
(void)ioctl(0, (int)TIOCGETP, (char *)&sg);
(void)ioctl(0, (int)TIOCGETC, (char *)&tc);
(void)ioctl(0, (int)TIOCGLTC, (char *)<c);
(void)ioctl(0, (int)TIOCLGET, (char *)&lmode);
/*
* Create a UNIX-domain socket.
*/
if (!(portal=getenv("UWIN"))) {
fprintf(stderr,
"You must run %s under the window manager\n", *argv);
exit(1);
}
if ((sd=socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(1);
}
sa.sa_family = AF_UNIX;
(void)strncpy(sa.sa_data, portal, sizeof sa.sa_data-1);
sa.sa_data[sizeof sa.sa_data-1] = '\0';
/*
* Obtain a pseudo-tty. This code isn't very smart about finding one.
*/
ptysufx[1] = '\0';
for (cp=ptyidx; *cp; cp++) {
ptysufx[0] = *cp;
(void)strncpy(pty, "/dev/ptyp", sizeof pty-1);
(void)strncat(pty, ptysufx, sizeof pty-1);
if ((fd = open(pty, 2)) >= 0)
break;
}
if (fd < 0) {
fprintf(stderr, "Can't obtain a pseudo-tty for a new window\n");
exit(1);
}
(void)strncpy(tty, "/dev/ttyp", sizeof tty-1);
(void)strncat(tty, ptysufx, sizeof tty-1);
/*
* Fork a child process using this pseudo-tty. Initialize the
* terminal modes on the pseudo-tty to match those of the parent
* tty.
*/
while ((pid=fork()) < 0)
sleep(5);
if (!pid) {
setuid(getuid()); /* in case it is setuid-root by mistake */
(void)signal(SIGTSTP, SIG_IGN);
(void)ioctl(open("/dev/tty", 2), (int)TIOCNOTTY, (char *)0);
if ((fd=open(tty, 2)) < 0)
_exit(1);
(void)dup2(fd, 0);
(void)dup2(0, 1);
(void)dup2(0, 2);
for (fd=3; fd < NFDS; fd++)
(void)close(fd);
(void)ioctl(0, (int)TIOCSETN, (char *)&sg);
(void)ioctl(0, (int)TIOCSETC, (char *)&tc);
(void)ioctl(0, (int)TIOCSLTC, (char *)<c);
(void)ioctl(0, (int)TIOCLSET, (char *)&lmode);
if (argc == 1) {
if (!(shell=getenv("SHELL")))
shell = "/bin/sh";
execl(shell, shell, (char *)0);
perror(shell);
} else {
execvp(argv[1], argv+1);
perror(argv[1]);
}
_exit(1);
}
/*
* Pass the file descriptor to the window server and exit.
*/
iov.iov_base = pty;
iov.iov_len = strlen(pty);
msg.msg_name = (caddr_t)&sa;
msg.msg_namelen = sizeof sa.sa_family + strlen(sa.sa_data);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof fd;
if (sendmsg(sd, &msg, 0) < 0) {
perror("sendmsg");
exit(1);
}
exit(0);
}
!Funky!Stuff!
echo x - foo
cat > foo << '!Funky!Stuff!'
Here are fixes to my original version of "uw.c" from mcvax!guido.
(Unfortunately, I lost the article he posted to "net.sources.mac"
so I can't provide a reference ID.)
--------------------------------------------------------------------------
*** uw.c.orig Sun Jul 21 18:11:31 1985
--- uw.c Sun Jul 28 22:04:48 1985
***************
*** 387,393
* hand us a terminal session running under their uid....]
*/
buf[cnt] = 0;
! if (strncmp(buf, "/dev/ptyp", sizeof "/dev/ptyp" - 1) ||
fstat(fd, &st1) < 0 || stat(buf, &st2) < 0 ||
st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
(void)close(fd);
--- 387,393 -----
* hand us a terminal session running under their uid....]
*/
buf[cnt] = 0;
! if (strncmp(buf, "/dev/pty", sizeof "/dev/pty" - 1) ||
fstat(fd, &st1) < 0 || stat(buf, &st2) < 0 ||
st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
(void)close(fd);
***************
*** 510,517
newwind(w)
register struct window *w;
{
! register char *cp;
! register fildes_t fd;
register int pid;
register char *shell;
char pty[32], ptysufx[2];
--- 510,517 -----
newwind(w)
register struct window *w;
{
! register char *cpmajor, *cp;
! register fildes_t fd, fd2;
register int pid;
register char *shell;
char pty[32], ptysufx[3];
***************
*** 514,520
register fildes_t fd;
register int pid;
register char *shell;
! char pty[32], ptysufx[2];
static char ptyidx[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static int unity = 1;
extern char *getenv();
--- 514,521 -----
register fildes_t fd, fd2;
register int pid;
register char *shell;
! char pty[32], ptysufx[3];
! static char ptyidmajor[] = "pqrs";
static char ptyidx[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static int unity = 1;
extern char *getenv();
***************
*** 521,527
/*
* Create a new window using the specified component of "window".
! * This routine isn't very smart at finding pseudo-ttys.
*/
ptysufx[1] = '\0';
--- 522,534 -----
/*
* Create a new window using the specified component of "window".
! * This routine tries to be smart at finding pseudo-ttys:
! * it tries all of /dev/pty[p-s][0-9a-z] until it finds one
! * that can be opened AND whose slave end can be opened.
! * (The latter is necessary because we often suffer from pty's
! * whose slave end is still busy while the master has been
! * closed; the slave ends are usually open exclusively
! * so another open would fail.)
*/
ptysufx[2] = '\0';
***************
*** 524,533
* This routine isn't very smart at finding pseudo-ttys.
*/
! ptysufx[1] = '\0';
! for (cp=ptyidx; *cp; cp++) {
! ptysufx[0] = *cp;
! (void)strncpy(pty, "/dev/ptyp", sizeof pty-1);
(void)strncat(pty, ptysufx, sizeof pty-1);
if ((fd = open(pty, 2)) >= 0)
break;
--- 531,542 -----
* so another open would fail.)
*/
! ptysufx[2] = '\0';
! for (cpmajor=ptyidmajor; *cpmajor; ++cpmajor) {
! ptysufx[0]= *cpmajor;
! for (cp=ptyidx; *cp; cp++) {
! ptysufx[1] = *cp;
! (void)strncpy(pty, "/dev/pty", sizeof pty-1);
(void)strncat(pty, ptysufx, sizeof pty-1);
if ((fd = open(pty, 2)) >= 0) {
/* Now check slave end. */
***************
*** 529,535
ptysufx[0] = *cp;
(void)strncpy(pty, "/dev/ptyp", sizeof pty-1);
(void)strncat(pty, ptysufx, sizeof pty-1);
! if ((fd = open(pty, 2)) >= 0)
break;
}
if (fd < 0)
--- 538,560 -----
ptysufx[1] = *cp;
(void)strncpy(pty, "/dev/pty", sizeof pty-1);
(void)strncat(pty, ptysufx, sizeof pty-1);
! if ((fd = open(pty, 2)) >= 0) {
! /* Now check slave end. */
! (void)strncpy(w->w_tty, "/dev/tty", sizeof w->w_tty-1);
! (void)strncat(w->w_tty, ptysufx, sizeof w->w_tty-1);
! if ((fd2 = open(w->w_tty, 2)) < 0) {
! close(fd);
! continue; /* Bad luck, try another. */
! }
! goto found_one;
! }
! /*
! * If a file really isn't there, don't check the rest of
! * this major series. This avoids trying to open 48
! * nonexistent pty's when the system is configured with
! * only 16 instead of the expected 64.
! */
! if (errno == ENOENT)
break;
}
}
***************
*** 531,536
(void)strncat(pty, ptysufx, sizeof pty-1);
if ((fd = open(pty, 2)) >= 0)
break;
}
if (fd < 0)
return(-1);
--- 556,562 -----
*/
if (errno == ENOENT)
break;
+ }
}
return(-1);
***************
*** 532,539
if ((fd = open(pty, 2)) >= 0)
break;
}
! if (fd < 0)
! return(-1);
(void)ioctl(fd, FIONBIO, &unity); /* set non-blocking I/O */
fdmap[fd] = w;
w->w_fd = fd;
--- 558,566 -----
break;
}
}
! return(-1);
!
! found_one:
(void)ioctl(fd, FIONBIO, &unity); /* set non-blocking I/O */
fdmap[fd] = w;
w->w_fd = fd;
***************
*** 538,545
fdmap[fd] = w;
w->w_fd = fd;
selmask[0].sm_rd |= (1<w_tty, "/dev/ttyp", sizeof w->w_tty-1);
- (void)strncat(w->w_tty, ptysufx, sizeof w->w_tty-1);
while ((pid=fork()) < 0)
sleep(5);
--- 565,570 -----
fdmap[fd] = w;
w->w_fd = fd;
selmask[0].sm_rd |= (1<w_tty, "/dev/ttyp", sizeof w->w_tty-1);
(void)strncat(w->w_tty, ptysufx, sizeof w->w_tty-1);
! while ((pid=fork()) < 0)
sleep(5);
if (!pid) {
(void)signal(SIGHUP, SIG_DFL);
--- 566,572 -----
w->w_fd = fd;
selmask[0].sm_rd |= (1<w_tty, 2)) < 0)
- _exit(1);
if (!(shell = getenv("SHELL")))
shell = "/bin/sh";
(void)dup2(fd, 0);
--- 577,582 -----
(void)signal(SIGCHLD, SIG_DFL);
(void)ioctl(open("/dev/tty", 2), (int)TIOCNOTTY, (char *)0);
(void)setuid(getuid()); /* shouldn't need this */
if (!(shell = getenv("SHELL")))
shell = "/bin/sh";
(void)dup2(fd2, 0);
***************
*** 556,562
_exit(1);
if (!(shell = getenv("SHELL")))
shell = "/bin/sh";
! (void)dup2(fd, 0);
(void)dup2(0, 1);
(void)dup2(0, 2);
for (fd=3; fd < NFDS; fd++)
--- 579,585 -----
(void)setuid(getuid()); /* shouldn't need this */
if (!(shell = getenv("SHELL")))
shell = "/bin/sh";
! (void)dup2(fd2, 0);
(void)dup2(0, 1);
(void)dup2(0, 2);
for (fd=3; fd < NFDS; fd++)
***************
*** 566,571
_exit(1);
}
return(0);
}
--- 589,595 -----
_exit(1);
}
+ close(fd2);
return(0);
}
!Funky!Stuff!
exit 0
: end of shell archive
--
John Bruner (S-1 Project, Lawrence Livermore National Laboratory)
MILNET: jdb@mordor [jdb@s1-c.ARPA] (415) 422-0758
UUCP: ...!ucbvax!dual!mordor!jdb ...!seismo!mordor!jdb