This is uw_fork.c in view mode; [Download] [Up]
/* * uw library - uw_fork * * Copyright 1986 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. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/ioctl.h> #include <sys/uio.h> #include <sys/file.h> #include <strings.h> #include <signal.h> #include "openpty.h" #include "uwlib.h" extern char *malloc(); extern char *getenv(); uwid_t uw_fork(wtype, pidp) uwtype_t wtype; int *pidp; { register int pid; register int sd; register struct uwipc *uwip; register uwid_t wid; auto int fd; char *portal; int lmode, ldisc; struct sgttyb sg; struct tchars tc; struct ltchars ltc; struct iovec iov; struct msghdr msg; struct sockaddr_un sa; struct ptydesc pt; char idstr[20]; char *env[2]; extern char *ltoa(); /* * Create a new window attached to a pseudo-terminal. This routine * returns twice -- once in the parent and once in the (new) child. * The parent receives the window ID of the child (or -1 if the * window creation failed). Zero is returned to the child. * If "pidp" is a non-NULL pointer, the process ID from the fork() * is stored there. */ /* * Get the terminal configuration for this tty. For now we * assume that "/dev/tty" is defined. Eventually we'll have to * provide defaults in case it is not. */ if ((fd = open("/dev/tty", O_RDWR)) >= 0) { (void)ioctl(fd, (int)TIOCGETP, (char *)&sg); (void)ioctl(fd, (int)TIOCGETC, (char *)&tc); (void)ioctl(fd, (int)TIOCGLTC, (char *)<c); (void)ioctl(fd, (int)TIOCLGET, (char *)&lmode); (void)ioctl(fd, (int)TIOCGETD, (char *)&ldisc); (void)close(fd); } else { /* ... */ } /* * Create a UNIX-domain socket. */ if (!(portal=getenv("UW_UIPC"))) { uwerrno = UWE_NXSERV; return(-1); } if ((sd=socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { uwerrno = UWE_ERRNO; return(-1); } sa.sun_family = AF_UNIX; (void)strncpy(sa.sun_path, portal, sizeof sa.sun_path-1); sa.sun_path[sizeof sa.sun_path-1] = '\0'; /* * Obtain a pseudo-tty and construct the datagram we will send later. */ if (openpty(&pt) < 0) { uwerrno = UWE_ERRNO; return(-1); } uwip = (struct uwipc *)malloc(sizeof(struct uwipc)+strlen(pt.pt_pname)); env[0] = malloc(sizeof "UW_ID=" + sizeof idstr); if (uwip == (struct uwipc *)0 || env[0] == (char *)0) { uwerrno = UWE_NOMEM; return(-1); } uwip->uwip_cmd = UWC_NEWT; uwip->uwip_len = (char *)&uwip->uwip_newt - (char *)uwip + sizeof(struct uwnewt) + strlen(pt.pt_pname); uwip->uwip_newt.uwnt_type = wtype; (void)strcpy(uwip->uwip_newt.uwnt_pty, pt.pt_pname); /* * Fork a child process using this pseudo-tty. Initialize the * terminal modes on the pseudo-tty to match those of the parent * tty. We really want a fork() here, not a vfork(). */ while ((pid=fork()) < 0) sleep(5); if (pidp != (int *)0) *pidp = pid; if (pid) { wid = (long)pid << 16; uwip->uwip_newt.uwnt_id = wid; } else { (void)setgid(getgid()); (void)setuid(getuid()); wid = (long)getpid() << 16; (void)strcat(strcpy(env[0], "UW_ID="), ltoa(wid, idstr, sizeof idstr)); env[1] = (char *)0; env_set(env); (void)signal(SIGTSTP, SIG_IGN); (void)ioctl(open("/dev/tty", 2), (int)TIOCNOTTY, (char *)0); (void)close(open(pt.pt_tname, 0)); /*set new ctrl tty */ (void)dup2(pt.pt_tfd, 0); (void)dup2(0, 1); (void)dup2(0, 2); fd = getdtablesize(); while (--fd > 2) (void)close(fd); (void)ioctl(fd, (int)TIOCSETD, (char *)&ldisc); (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); uwerrno = UWE_NONE; return(0); } /* * Pass the file descriptor to the window server. */ iov.iov_base = (char *)uwip; iov.iov_len = uwip->uwip_len; msg.msg_name = (caddr_t)&sa; msg.msg_namelen = sizeof sa.sun_family + strlen(sa.sun_path); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_accrights = (caddr_t)&pt.pt_pfd; msg.msg_accrightslen = sizeof pt.pt_pfd; if (sendmsg(sd, &msg, 0) < 0) { free((char *)uwip); uwerrno = UWE_ERRNO; return(-1); } free((char *)uwip); uwerrno = UWE_NONE; return(wid); } static char * ltoa(l, buf, buflen) long l; char *buf; int buflen; { register char *cp; register unsigned long ul; static char digits[] = "0123456789"; /* * This routine replaces a call to sprintf() so that the library * is independent of stdio. */ cp = buf+buflen; *--cp = '\0'; ul = l; if (cp > buf) { do { *--cp = digits[ul%10]; ul /= 10; } while (cp > buf && ul != 0); } return(cp); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.