home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / ME.C < prev    next >
C/C++ Source or Header  |  1990-06-19  |  6KB  |  210 lines

  1. /*    me.c    MicroEmacs command interface to kept microemacs
  2.         For VAX/VMS operating system
  3.         for MicroEMACS 3.10
  4.         Copyright 1989 by Jeffrey A. Lomicka and Daniel M. Lawrence
  5.  
  6.     This is a separate program that is used to start and re-attach to
  7.     a microemacs that's kept in a subprocess.  To use the kept
  8.     facility, point the microemacs symbol at this program instead of
  9.     MESHR.EXE, and store MESHR.EXE in the SYS$SHARE search list.
  10.  
  11.     To use microemacs in the normal way, just point the microemacs
  12.     command directly at tghe MESHR.EXE image.
  13. */
  14. #include stdio
  15. #include ssdef
  16. #include descrip
  17. #include jpidef
  18. #include iodef
  19. #include accdef
  20. /*
  21.     These are the LIB$SPAWN mode flags.  There's no .h for
  22.     them in VAX C V2.4.
  23. */
  24. #define CLI$M_NOCONTROL 32
  25. #define CLI$M_NOCLISYM 2
  26. #define CLI$M_NOLOGNAM 4
  27. #define CLI$M_NOKEYPAD 8
  28. #define CLI$M_NOTIFY 16
  29. #define CLI$M_NOWAIT 1
  30. /*
  31.     test macro is used to signal errors from system services
  32. */
  33. #define test( s) {int st; st = (s); if( (st&1)==0) LIB$SIGNAL( st);}
  34.  
  35. /*
  36.     This routine returns a pointer to a descriptor of the supplied
  37.     string. The descriptors are static allocated, and up to
  38.     "NUM_DESCRIPTORS" may be used at once.  After that, the old ones
  39.     are re-used. Be careful!
  40.  
  41.     The primary use of this routine is to allow passing of C strings into
  42.     VMS system facilities and RTL functions.
  43.  
  44.     There are three forms:
  45.  
  46.         descrp( s, l)    String descriptor for buffer s, length l
  47.         descptr( s)    String descriptor for asciz buffer s
  48.         DESCPTR( s)    String descriptor for buffer s, using sizeof()
  49. */
  50. #define NUM_DESCRIPTORS 10
  51. struct  dsc$descriptor_s *descrp( s, l)
  52. char *s;    /* String to make descriptor for */
  53. int l;        /* length of string */
  54.     {
  55.     static next_d = 0;
  56.     static struct dsc$descriptor_s dsclist[ NUM_DESCRIPTORS];
  57.  
  58.     if( next_d >= NUM_DESCRIPTORS) next_d = 0;
  59.     dsclist[ next_d].dsc$w_length = l;
  60.     dsclist[ next_d].dsc$b_dtype =  DSC$K_DTYPE_T;
  61.     dsclist[ next_d].dsc$b_class =  DSC$K_CLASS_S;
  62.     dsclist[ next_d].dsc$a_pointer = s;
  63.     return( &dsclist[ next_d++]);
  64.     }
  65.  
  66. struct  dsc$descriptor_s *descptr( s)    /* Make pointer to descriptor */
  67. char *s;        /* Asciz string to make descriptor for */
  68.     {
  69.     return( descrp( s, strlen( s)));
  70.     }
  71.  
  72. #define DESCPTR( s)    descrp( s, sizeof(s)-1)
  73.  
  74. static long g_pid, g_status, g_efn;
  75. struct acc$record msg;        /* Message buffer */
  76. static int good_reason = 0;    /* True if good reason to exit */
  77.  
  78. me_exited()
  79.    {
  80.    test( LIB$PUT_OUTPUT( DESCPTR( "Microemacs has exited.")));
  81.    good_reason = 1;
  82.    test( SYS$WAKE( 0, 0));
  83.    }
  84.  
  85. start_microemacs( argc, argv)
  86. int argc;
  87. char *argv[];
  88.     {
  89.     char scrap[ 512], imagename[ 256], *i;
  90.     int a;
  91.  
  92.     test( LIB$PUT_OUTPUT( DESCPTR( "Starting a new Microemacs process.")));
  93. /*
  94.     Locate the microemacs sharable image
  95. */
  96.     a = 0;
  97.     test( LIB$FIND_FILE(
  98.     DESCPTR( "MESHR"),
  99.     DESCPTR( imagename),
  100.     &a,
  101.     DESCPTR( "SYS$SHARE:.EXE"),
  102.     0, 0, 0));
  103.     test( LIB$FIND_FILE_END( &a));
  104. /*
  105.     Make it asciz by terminating it at the ";"
  106. */
  107.     for( i=imagename; *i != ';'; i++);
  108.     *i = 0;
  109. /*
  110.     Build a command line that invokes it
  111. */
  112.     strcpy( scrap, "MCR ");
  113.     strcat( scrap, imagename);
  114.     for( a=1; a<argc; a++)
  115.     { /* Build command string */
  116.     strcat( scrap, " ");
  117.     strcat( scrap, argv[ a]);
  118.     }
  119.     test( LIB$GET_EF( &g_efn));
  120.     test( LIB$SPAWN( descptr( scrap), DESCPTR( "NLA0:"), 0, &CLI$M_NOWAIT,
  121.     0, &g_pid, &g_status, &g_efn, me_exited, &g_pid, 0, 0));
  122.     }
  123.  
  124. main( argc, argv)
  125. int argc;
  126. char *argv[];
  127.     {
  128.     char *env;
  129.     char scrap[ 512];
  130.     char defdir[ 512];
  131.     int a;
  132.     unsigned long pid;
  133.     short len;
  134. /*
  135.     Identify where we come from
  136. */
  137.     test( LIB$GETJPI( &JPI$_PID, 0, 0, &pid, 0, 0));
  138.     sprintf( scrap, "%d", pid);
  139.     test( LIB$SET_LOGICAL(
  140.     DESCPTR( "MICROEMACS$PARENT"),
  141.     descptr( scrap),
  142.     DESCPTR( "LNM$JOB")));
  143. /*
  144.     Identify where we are going
  145. */
  146.     env = getenv( "MICROEMACS$PROCESS");
  147.     if( env == NULL) start_microemacs( argc, argv);
  148.     else
  149.     { /* Microemacs exists, send command line to it and wake it up */
  150.     pid = atoi( env);
  151. /*
  152.     Get rid of the old definition.  We know our wakeup is legitimate
  153.     when either a new definition is created, or when our AST routine
  154.     is executed.
  155. */
  156.     test( LIB$DELETE_LOGICAL(
  157.         DESCPTR( "MICROEMACS$PROCESS"),
  158.         DESCPTR( "LNM$JOB")));
  159. /*
  160.     Fetch the current default directory
  161. */
  162.     len = 0;
  163.     test( SYS$SETDDIR( 0, &len, DESCPTR( defdir)));
  164.     defdir[ len] = 0;
  165. /*
  166.     Encode an argv string for emacs to decode.  Using "\200" instead
  167.     of spaces just in case quotes were involved.
  168. */
  169.     strcpy( scrap, getenv( "SYS$DISK"));
  170.     strcat( scrap, "\200");
  171.     strcat( scrap, defdir);
  172.     for( a=0; a<argc; a++)
  173.         { /* Build command string */
  174.         strcat( scrap, "\200");
  175.         strcat( scrap, argv[ a]);
  176.         }
  177.     test( LIB$SET_LOGICAL(
  178.         DESCPTR( "MICROEMACS$COMMAND"),
  179.         descptr( scrap),
  180.         DESCPTR( "LNM$JOB")));
  181. /*
  182.     Attempt to kiss our sleeping beauty, and thus wake it up
  183. */
  184.     test( LIB$PUT_OUTPUT( DESCPTR( "Using existing Microemacs process.")));
  185.     a = SYS$WAKE( &pid, 0);
  186.     if( a == SS$_NONEXPR)
  187.         { /* Failed to wake it up, try starting a new one instead */
  188.         start_microemacs( argc, argv);
  189.         }
  190.     else
  191.         { /* Successful at waking up microemacs, set up for termination */
  192.         test( a);
  193.         test( LIB$GETJPI( &JPI$_TMBU, &pid, 0, &a, 0, 0));
  194.         sprintf( scrap, "MBA%d:", a);
  195.         test( SYS$ASSIGN( descptr( scrap), &a, 0, 0));
  196.         test( SYS$QIO( 0, a, IO$_READVBLK, 0, me_exited, 0,
  197.         msg, sizeof( msg), 0, 0, 0, 0));
  198.         }
  199.     }
  200. /*
  201.     If Emacs was started, hibernate until it comes back
  202. */
  203.     while( !good_reason)
  204.     { /* Hibernate until winter is over */
  205.     test( SYS$HIBER());
  206.     env = getenv( "MICROEMACS$PROCESS");
  207.     if( env != NULL) break;
  208.     }
  209.     }
  210.