home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
UE311C.ZIP
/
ME.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-19
|
6KB
|
210 lines
/* me.c MicroEmacs command interface to kept microemacs
For VAX/VMS operating system
for MicroEMACS 3.10
Copyright 1989 by Jeffrey A. Lomicka and Daniel M. Lawrence
This is a separate program that is used to start and re-attach to
a microemacs that's kept in a subprocess. To use the kept
facility, point the microemacs symbol at this program instead of
MESHR.EXE, and store MESHR.EXE in the SYS$SHARE search list.
To use microemacs in the normal way, just point the microemacs
command directly at tghe MESHR.EXE image.
*/
#include stdio
#include ssdef
#include descrip
#include jpidef
#include iodef
#include accdef
/*
These are the LIB$SPAWN mode flags. There's no .h for
them in VAX C V2.4.
*/
#define CLI$M_NOCONTROL 32
#define CLI$M_NOCLISYM 2
#define CLI$M_NOLOGNAM 4
#define CLI$M_NOKEYPAD 8
#define CLI$M_NOTIFY 16
#define CLI$M_NOWAIT 1
/*
test macro is used to signal errors from system services
*/
#define test( s) {int st; st = (s); if( (st&1)==0) LIB$SIGNAL( st);}
/*
This routine returns a pointer to a descriptor of the supplied
string. The descriptors are static allocated, and up to
"NUM_DESCRIPTORS" may be used at once. After that, the old ones
are re-used. Be careful!
The primary use of this routine is to allow passing of C strings into
VMS system facilities and RTL functions.
There are three forms:
descrp( s, l) String descriptor for buffer s, length l
descptr( s) String descriptor for asciz buffer s
DESCPTR( s) String descriptor for buffer s, using sizeof()
*/
#define NUM_DESCRIPTORS 10
struct dsc$descriptor_s *descrp( s, l)
char *s; /* String to make descriptor for */
int l; /* length of string */
{
static next_d = 0;
static struct dsc$descriptor_s dsclist[ NUM_DESCRIPTORS];
if( next_d >= NUM_DESCRIPTORS) next_d = 0;
dsclist[ next_d].dsc$w_length = l;
dsclist[ next_d].dsc$b_dtype = DSC$K_DTYPE_T;
dsclist[ next_d].dsc$b_class = DSC$K_CLASS_S;
dsclist[ next_d].dsc$a_pointer = s;
return( &dsclist[ next_d++]);
}
struct dsc$descriptor_s *descptr( s) /* Make pointer to descriptor */
char *s; /* Asciz string to make descriptor for */
{
return( descrp( s, strlen( s)));
}
#define DESCPTR( s) descrp( s, sizeof(s)-1)
static long g_pid, g_status, g_efn;
struct acc$record msg; /* Message buffer */
static int good_reason = 0; /* True if good reason to exit */
me_exited()
{
test( LIB$PUT_OUTPUT( DESCPTR( "Microemacs has exited.")));
good_reason = 1;
test( SYS$WAKE( 0, 0));
}
start_microemacs( argc, argv)
int argc;
char *argv[];
{
char scrap[ 512], imagename[ 256], *i;
int a;
test( LIB$PUT_OUTPUT( DESCPTR( "Starting a new Microemacs process.")));
/*
Locate the microemacs sharable image
*/
a = 0;
test( LIB$FIND_FILE(
DESCPTR( "MESHR"),
DESCPTR( imagename),
&a,
DESCPTR( "SYS$SHARE:.EXE"),
0, 0, 0));
test( LIB$FIND_FILE_END( &a));
/*
Make it asciz by terminating it at the ";"
*/
for( i=imagename; *i != ';'; i++);
*i = 0;
/*
Build a command line that invokes it
*/
strcpy( scrap, "MCR ");
strcat( scrap, imagename);
for( a=1; a<argc; a++)
{ /* Build command string */
strcat( scrap, " ");
strcat( scrap, argv[ a]);
}
test( LIB$GET_EF( &g_efn));
test( LIB$SPAWN( descptr( scrap), DESCPTR( "NLA0:"), 0, &CLI$M_NOWAIT,
0, &g_pid, &g_status, &g_efn, me_exited, &g_pid, 0, 0));
}
main( argc, argv)
int argc;
char *argv[];
{
char *env;
char scrap[ 512];
char defdir[ 512];
int a;
unsigned long pid;
short len;
/*
Identify where we come from
*/
test( LIB$GETJPI( &JPI$_PID, 0, 0, &pid, 0, 0));
sprintf( scrap, "%d", pid);
test( LIB$SET_LOGICAL(
DESCPTR( "MICROEMACS$PARENT"),
descptr( scrap),
DESCPTR( "LNM$JOB")));
/*
Identify where we are going
*/
env = getenv( "MICROEMACS$PROCESS");
if( env == NULL) start_microemacs( argc, argv);
else
{ /* Microemacs exists, send command line to it and wake it up */
pid = atoi( env);
/*
Get rid of the old definition. We know our wakeup is legitimate
when either a new definition is created, or when our AST routine
is executed.
*/
test( LIB$DELETE_LOGICAL(
DESCPTR( "MICROEMACS$PROCESS"),
DESCPTR( "LNM$JOB")));
/*
Fetch the current default directory
*/
len = 0;
test( SYS$SETDDIR( 0, &len, DESCPTR( defdir)));
defdir[ len] = 0;
/*
Encode an argv string for emacs to decode. Using "\200" instead
of spaces just in case quotes were involved.
*/
strcpy( scrap, getenv( "SYS$DISK"));
strcat( scrap, "\200");
strcat( scrap, defdir);
for( a=0; a<argc; a++)
{ /* Build command string */
strcat( scrap, "\200");
strcat( scrap, argv[ a]);
}
test( LIB$SET_LOGICAL(
DESCPTR( "MICROEMACS$COMMAND"),
descptr( scrap),
DESCPTR( "LNM$JOB")));
/*
Attempt to kiss our sleeping beauty, and thus wake it up
*/
test( LIB$PUT_OUTPUT( DESCPTR( "Using existing Microemacs process.")));
a = SYS$WAKE( &pid, 0);
if( a == SS$_NONEXPR)
{ /* Failed to wake it up, try starting a new one instead */
start_microemacs( argc, argv);
}
else
{ /* Successful at waking up microemacs, set up for termination */
test( a);
test( LIB$GETJPI( &JPI$_TMBU, &pid, 0, &a, 0, 0));
sprintf( scrap, "MBA%d:", a);
test( SYS$ASSIGN( descptr( scrap), &a, 0, 0));
test( SYS$QIO( 0, a, IO$_READVBLK, 0, me_exited, 0,
msg, sizeof( msg), 0, 0, 0, 0));
}
}
/*
If Emacs was started, hibernate until it comes back
*/
while( !good_reason)
{ /* Hibernate until winter is over */
test( SYS$HIBER());
env = getenv( "MICROEMACS$PROCESS");
if( env != NULL) break;
}
}