|
|
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: 8709 (0x2205)
Types: TextFile
Names: »spawn.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/micrognu/sys/vms/spawn.c«
/*
* Name: MicroEMACS
* VAX/VMS spawn and attach to a DCL subprocess.
* Created: rex::conroy
* decvax!decwrl!dec-rhea!dec-rex!conroy
* Modified:
* 19-May-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* Add att-to-parent command to attach to the parent
* process. If we can't attach to parent somehow,
* spawn a DCL subjob. This gives us the same
* suspend capability as Unix Emacses.
*
* As an added hook, you can DEFINE/JOB
* MG$ATTACHTO to a process name, and
* the code will try to attach to that name.
*
* Also, if the logical name MG$FILE is
* defined, attachtoparent() will visit that file
* when you re-attach to Emacs. This is useful
* for a lot of applications, especially MAIL/EDIT...
* 26-Jun-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* Specify process we're attaching to when we attempt
* to attach to it.
* 03-Sep-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* Call savebuffers() before leaving the editor.
* Unlike csh, DCL has no problem with people
* logging out without completing subjobs...
* #define NOSAVEONZ if you don't want this behavior.
* 13-Oct-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* Change MICROEMACS$... to MG$... for consistency.
*/
#include "def.h"
#include <ssdef.h>
#include <stsdef.h>
#include <descrip.h>
#include <iodef.h>
#include <jpidef.h>
#define EFN 0 /* Event flag. */
extern int oldmode[3]; /* In "ttyio.c". */
extern int newmode[3];
extern short iochan;
extern int ckttysize(); /* Checks for new term size */
#ifndef NOSAVEONZ
extern int savebuffers(); /* Save all buffers before */
#endif
/*
* Create a subjob with a copy
* of the command intrepreter in it. When the
* command interpreter exits, mark the screen as
* garbage so that you do a full repaint. Bound
* to "C-C" and called from "C-Z". The message at
* the start in VMS puts out a newline. Under
* some (unknown) condition, you don't get one
* free when DCL starts up.
*/
spawncli(f, n, k)
{
register int s;
#ifndef NOSAVEONZ
if (savebuffers() == ABORT) /* TRUE means all saved,*/
return (ABORT); /* FALSE means not. */
#endif
eerase(); /* Get rid of echo line */
ttcolor(CTEXT); /* Normal color. */
ttnowindow(); /* Full screen scroll. */
ttmove(nrow-1, 0); /* Last line. */
eputs("Starting DCL");
ttputc('\r');
ttputc('\n');
ttflush();
sgarbf = TRUE;
s = sys(NULL); /* NULL => DCL. */
return (s);
}
/*
* Run a command. The "cmd" is a pointer
* to a command string, or NULL if you want to run
* a copy of DCL in the subjob (this is how the standard
* routine LIB$SPAWN works. You have to do wierd stuff
* with the terminal on the way in and the way out,
* because DCL does not want the channel to be
* in raw mode.
*/
sys(cmd)
register char *cmd;
{
struct dsc$descriptor cdsc;
struct dsc$descriptor *cdscp;
long status;
long substatus;
long iosb[2];
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
return (FALSE);
cdscp = NULL; /* Assume DCL. */
if (cmd != NULL) { /* Build descriptor. */
cdsc.dsc$a_pointer = cmd;
cdsc.dsc$w_length = strlen(cmd);
cdsc.dsc$b_dtype = DSC$K_DTYPE_T;
cdsc.dsc$b_class = DSC$K_CLASS_S;
cdscp = &cdsc;
}
status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
if (status != SS$_NORMAL)
substatus = status;
ckttysize(); /* check for new terminal size */
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
newmode, sizeof(newmode), 0, 0, 0, 0);
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
return (FALSE);
if ((substatus&STS$M_SUCCESS) == 0) /* Command failed. */
return (FALSE);
return (TRUE);
}
/*
* Front end for combined attach-to-parent and spawn-cli action
*/
attachtoparent(f, n, k)
{
register int s;
s = attparent();
if (s == ABORT)
return (ABORT);
else if (s == FALSE)
return spawncli(f, n, k); /* better than nothing */
else
return (TRUE);
}
/*
* Attach to parent. If the logical name MG$ATTACHTO
* is present, attempt to attach to it. If not, attempt to
* attach to parent process.
*
* On return, see if the logical name MG$FILE contains
* anything, and try to visit that file.
*/
static $DESCRIPTOR(nmdsc,"MG$ATTACHTO");
attparent()
{
long pid, jpi_code;
char equiv[18], msgbuf[60];
struct dsc$descriptor_s eqdsc;
short eqlen;
int status, pos;
register BUFFER *bp;
BUFFER *findbuffer();
int s;
/* Set up string descriptor */
eqdsc.dsc$a_pointer = equiv;
eqdsc.dsc$w_length = sizeof(equiv);
eqdsc.dsc$b_dtype = DSC$K_DTYPE_T;
eqdsc.dsc$b_class = DSC$K_CLASS_S;
/* Try to translate MG$ATTACH */
status = lib$sys_trnlog(&nmdsc, &eqdsc.dsc$w_length, &eqdsc);
if (status!=SS$_NORMAL && status!=SS$_NOTRAN) {
ewprintf("Error translating %s",nmdsc.dsc$a_pointer);/* DEBUG */
return (FALSE);
}
if (status == SS$_NORMAL) {
/* Found a translation -- attempt to attach to it */
jpi_code = JPI$_PID;
status = lib$getjpi(&jpi_code,0,&eqdsc,&pid,0);
equiv[eqdsc.dsc$w_length] = '\0';
if (status != SS$_NORMAL) {
ewprintf("Error getting JPI for \"%s\"",equiv);
return (FALSE);
}
#ifndef NOSAVEONZ
/* Attempt to attach to named process. Save all buffers, */
/* set sgarbf because attach() always trashes the display */
if (savebuffers() == ABORT)
return (ABORT);
#endif
/* indicate process we're attaching to */
strcpy(msgbuf,"Attaching to process \"");
for (pos = strlen(equiv) - 1; pos >= 0; --pos)
if (equiv[pos] != ' ') {
equiv[pos+1] = '\0';
break;
}
strcat(msgbuf,equiv);
strcat(msgbuf,"\"");
sgarbf = TRUE;
if (attach(pid,msgbuf) == FALSE) /* whups -- try spawn */
return (FALSE);
}
else { /* No translation -- attempt to find parent process */
jpi_code = JPI$_OWNER;
status = lib$getjpi(&jpi_code,0,0,&pid,0,0);
if ((status != SS$_NORMAL) || (pid == 0)) /* not found! */
return (FALSE);
#ifndef NOSAVEONZ
if (savebuffers() == ABORT)
return (ABORT);
#endif
sgarbf = TRUE;
if (attach(pid,"Attaching to parent process") == FALSE)
return (FALSE);
}
newfile(); /* attempt to find a new file, but don't care */
/* if we don't find one... */
refresh(FALSE, 0, KRANDOM);
return (TRUE);
}
/*
* If we find after re-attaching that there is
* a new file to be edited, attempt to read it in,
* using essentially the same code as findfile().
*/
static newfile()
{
register BUFFER *bp;
register int s;
char filename[NFILEN];
BUFFER *findbuffer();
if ((s = cknewfile(filename, sizeof filename)) != TRUE)
return (s);
if ((bp = findbuffer(filename, &s)) == NULL)
return (s);
curbp = bp;
if (showbuffer(bp, curwp, WFHARD) != TRUE)
return (FALSE);
if (bp->b_fname[0] == 0)
return (readin(filename)); /* Read it in. */
return (TRUE);
}
/*
* Attach to a process by process number. Restore the
* terminal channel to the way it was when we started.
* Also put out an optional message to the user.
*/
static attach(pid, msg)
long pid;
char *msg;
{
long status, attstatus;
long iosb[2];
ttcolor(CTEXT); /* Normal color. */
ttnowindow(); /* Full screen scroll. */
ttmove(nrow-1, 0); /* Last line. */
if (msg) { /* Display a message */
eputs(msg);
ttputc('\r');
ttputc('\n');
}
ttflush();
/* Set terminal to old modes */
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
return (FALSE);
/* Attach to the process */
attstatus = LIB$ATTACH(&pid);
/* Return terminal to the modes MG needs */
ckttysize(); /* check for new terminal size first */
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
newmode, sizeof(newmode), 0, 0, 0, 0);
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
return (FALSE);
return (attstatus == SS$_NORMAL ? TRUE : FALSE);
}
/*
* Attempt to translate MG$FILE into fname.
* If it's there and non-empty, return TRUE.
*/
static $DESCRIPTOR(filedsc,"MG$FILE");
static cknewfile(fname,fnsiz)
char *fname;
int fnsiz;
{
char equiv[NFILEN];
struct dsc$descriptor_s eqdsc;
short len;
register int status;
eqdsc.dsc$a_pointer = equiv;
eqdsc.dsc$w_length = sizeof(equiv);
eqdsc.dsc$b_dtype = DSC$K_DTYPE_T;
eqdsc.dsc$b_class = DSC$K_CLASS_S;
status = lib$sys_trnlog(&filedsc, &len, &eqdsc);
if (status!=SS$_NORMAL && status!=SS$_NOTRAN) {
ewprintf("Error translating MG$FILE");
return (FALSE);
}
if (status == SS$_NOTRAN) /* No new file found */
return (FALSE);
if (equiv[0] == ' ')
return (FALSE);
equiv[len] = '\0';
strcpy(fname, equiv);
return (TRUE);
}