This is etermSupport.c in view mode; [Download] [Up]
/* * Copyright 1990, John G. Myers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <libc.h> #include <signal.h> #include <errno.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/wait.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include "etermSupport.h" /* Some random lab's phone number. Ask Tom Lord */ #define FIB20 6765 extern int errno; /* * Given the current environment, give us a new environment suitable * for an emacs process with an event server on port 'eventportno' */ char **patch_env (char **currentEnv, int eventportno) { static char term[] = "TERM=eterm"; static char termcap[] = "TERMCAP=69|eterm|Terminal emulator for Gnu-emacs:co#80:li#24:cm=^u%d^u%d.:IC=^u%d_:DC=^u%d^d:AL=^u%d^o:DL=^u%d^k:bc=^b:bl=^g:cd=^[k:ce=^k:ch=^u%d.:cl=^[c:cr=^a:do=^n:im=^i:ei=^i:le=^b:mi:ms:nd=^f:nl=^j:se=^s:so=^s:up=^p:am:km:"; char *eventhost; static char eventport[80]; char ** newEnv; int envSize,x,y; char hostname[1024]; if (gethostname(hostname, sizeof(hostname)) == -1) { perror("gethostname"); exit(1); } eventhost = malloc(strlen(hostname)+12); strcpy(eventhost, "EVENT_HOST="); strcat(eventhost, hostname); sprintf(eventport, "EVENT_PORT=%d", eventportno); for (envSize = 0; currentEnv[ envSize ] != NULL; envSize++); newEnv = (char **)malloc( sizeof( char * ) * (envSize + 5) ); for (x = y = 0; x < envSize; x++) if (strncmp( currentEnv[x], "TERM=", 5 ) && strncmp( currentEnv[x], "TERMCAP=", 8 ) && strncmp( currentEnv[x], "EVENT_HOST=", 11) && strncmp( currentEnv[x], "EVENT_PORT=", 11)) newEnv[ y++ ] = currentEnv[ x ]; newEnv[ y++ ] = term; newEnv[ y++ ] = termcap; newEnv[ y++ ] = eventhost; newEnv[ y++ ] = eventport; newEnv[ y ] = NULL; return newEnv; } /* * Create the event server socket for an emacs process. * Store the port number in the int ponted to by eventportno */ int create_server_socket(int *eventportno) { int EventServerSocket; struct sockaddr_in name; int portno = FIB20; if ((EventServerSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0) { perror("socket"); exit(1); } while (portno < FIB20 + 100) { name.sin_family = AF_INET; name.sin_port = htons(portno); name.sin_addr.s_addr = INADDR_ANY; if (bind(EventServerSocket, (struct sockaddr *)&name, sizeof(name)) == -1) { portno++; continue; } if (listen(EventServerSocket, 1) == -1) { perror("listen"); exit(1); } *eventportno = portno; return EventServerSocket; } perror("bind"); exit(1); } /* * Accept a connection on an event server socket */ int accept_server_connection(int serversocket) { int s; struct sockaddr_in name; int namelen = sizeof(name); if ((s = accept(serversocket, (struct sockaddr *)&name, &namelen)) == -1) return -1; return s; } /* the create_channel code is stolen from h19. "it should be replaced" */ char ptcname[] = "/dev/ptyXX"; char ptyname[] = "/dev/ttyXX"; /* * Grab a pty/tty pair for running a child emacs process. */ void create_channel(int *master, int *slave, int *ptynumber) { int MasterChannel, ShellChannel, PtyNumber; int pid; char c; pid = getpid (); if (setpgrp (0, pid) < 0) perror("setpgrp"); /* remove the current controling terminal -- will create a new one */ { int fd; fd = open ("/dev/tty", 2); if (fd >= 0) { if (ioctl (fd, TIOCNOTTY, NULL) < 0) perror ("ioctl (TIOCNOTTY)"); close (fd); } } /* find pseudo-teletype for subchannel to shell */ for (c = 'p'; c <= 'r'; c++) { ptcname[strlen ("/dev/pty")] = c; ptcname[strlen ("/dev/ptyX")] = '0'; for (PtyNumber = 0; PtyNumber < 16; PtyNumber++) { ptcname[strlen ("/dev/ptyX")] = "0123456789abcdef"[PtyNumber]; MasterChannel = open (ptcname, 2); if (MasterChannel < 0) continue; ptyname[strlen ("/dev/tty")] = c; ptyname[strlen ("/dev/ttyX")] = "0123456789abcdef"[PtyNumber]; ShellChannel = open (ptyname, 2); if (ShellChannel >= 0) goto gotpty; close (MasterChannel); } } gotpty: if (MasterChannel < 0 || ShellChannel < 0) { fprintf (stderr, "Can't connect subchannel\n"); exit (1); } /* adjust terminal driver for Master Channel */ { /* exclusive use of Master */ if (ioctl (MasterChannel, FIOCLEX, NULL) < 0) perror ("ioctl (FIOCLEX)"); } /* adjust terminal driver for Shell Channel */ { int line_discipline = NTTYDISC; int local_mode; struct sgttyb ttystate; if (ioctl (ShellChannel, TIOCHPCL, NULL) < 0) perror ("TIOCHPCL"); if (ioctl (ShellChannel, TIOCSETD, &line_discipline) < 0) perror ("TIOCSETD"); if (ioctl (ShellChannel, TIOCGETP, &ttystate) < 0) perror ("TIOCGETP"); ttystate.sg_flags = CRMOD | ANYP | ECHO; /* CRMOD - tread CR like LF; output of LF is CR/LF XTABS - change TABS to sequence of blanks ANYP - Any parity okay ECHO - echo characters (full duplex) */ ttystate.sg_erase = '\010'; if (ioctl (ShellChannel, TIOCSETP, &ttystate) < 0) perror ("TIOCSETP"); if (ioctl (ShellChannel, TIOCLGET, &local_mode) < 0) perror ("TIOCLGET"); /* LCRTBS - CRT back space to ^H * LCRTERA - backspace-space-backspace * LCRTKIL - erase as LCRTERA for line kill too * LCTLECH - echo non-printing characters as ^X */ local_mode |= LCRTBS|LCRTKIL|LCRTERA|LCTLECH; if (ioctl (ShellChannel, TIOCLSET, &local_mode) < 0) perror ("TIOCLSET"); } *master = MasterChannel; *slave = ShellChannel; *ptynumber = PtyNumber; } /* * Reap zombie processes. If any child processes stopped themselves, * give them a kick in the pants. */ static void ShellDone () { int pid; union wait stat; while ((pid = wait3( &stat, WUNTRACED | WNOHANG, 0 )) > 0) { if (WIFSTOPPED(stat)) kill(pid,SIGCONT); } } /* * Fork and exec the child emacs. */ void fork_shell (char *name, char **args, char **env, int channel) { int pid; signal(SIGCLD, ShellDone); signal(SIGTTOU, SIG_IGN); if ((pid = fork ()) < 0) { fprintf (stderr, "Fork failed\n"); exit (1); } if (pid == 0) { int i; int cpid; cpid = getpid (); if (ioctl (channel, TIOCSPGRP, &cpid) < 0) perror ("TIOCSPGRP"); if (setpgrp (0, cpid) < 0) perror ("setpgrp"); dup2 (channel, 0); dup2 (channel, 1); for (i=getdtablesize(); i>2; i--) (void) close(i); execve (name, args, env); write (2, "Couldn't exec emacs.\n", 21); exit (1); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.