home *** CD-ROM | disk | FTP | other *** search
/ The Best of Select: Windows 95 Special 1 / WINDOWS95_1.ISO / utils / w32-rex / regina / srccode / src / vmscmd.c < prev    next >
C/C++ Source or Header  |  1994-05-15  |  11KB  |  420 lines

  1. /*
  2.  *  The Regina Rexx Interpreter
  3.  *  Copyright (C) 1992  Anders Christensen <anders@pvv.unit.no>
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /*
  21.  * $Id: vmscmd.c,v 1.1 1993/02/09 19:05:49 anders Exp anders $
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <errno.h>
  27. #include <processes.h>
  28. #include <descrip.h>
  29. #include <dvidef.h>
  30. #include <clidef.h>
  31. #include <climsgdef.h>
  32. #include <ssdef.h>
  33. #include <iodef.h>
  34. #include <jpidef.h>
  35. #include <rmsdef.h>
  36.  
  37. #include "rexx.h"
  38. #include "strings.h"
  39.  
  40. struct mbox_status {
  41.    unsigned short status ;
  42.    unsigned short size ;
  43.    int pid ; 
  44.  } ;
  45.  
  46. #define BUFSIZE 128
  47. #define NUMBUFS  1
  48.  
  49. /* #define VMS_DEBUG */
  50.  
  51. #define MAX(a,b) (((a)>(b))?(a):(b))
  52. #define MIN(a,b) (((a)<(b))?(a):(b))
  53.  
  54. #define MAX_SYM_LENGTH 256
  55.  
  56. volatile static int ichan=0, ochan=0, pid=0, oflag=0 ;
  57. volatile static int comp_stat=0 ;
  58.  
  59. static void read_in_ast( int read )
  60. {
  61.    static char buffer[BUFSIZE] ;
  62.    static struct mbox_status ostat ;
  63.    streng *ptr ;
  64.    int rc ;
  65.  
  66. /* fprintf( stderr, "read_in_ast() status=%d, size=%d, read=%d\n", ostat.status,
  67.                 ostat.size, read ) ; */
  68.  
  69.    if (read) 
  70.    {
  71.       switch ( ostat.status ) 
  72.       {
  73.          case SS$_NORMAL:
  74.             if (ostat.size >= BUFSIZE) 
  75.                complain( SS$_NORMAL ) ;
  76.             ptr = Str_make( ostat.size ) ;
  77.             ptr = Str_ncatstr( ptr, buffer, ostat.size ) ;
  78.             tmp_stack( ptr ) ;
  79.             break ;
  80.  
  81.          case SS$_ENDOFFILE:
  82.             rc = sys$dassgn( (short)ochan ) ;
  83.             if (rc != SS$_NORMAL) complain( rc ) ;
  84.             ochan = 0 ;
  85.             rc = sys$setef( oflag ) ;
  86.             if (rc != SS$_NORMAL) complain( rc ) ;
  87.             break ;
  88.  
  89.          default: 
  90.             fprintf( stderr, 
  91.                 "sys$qio() return unexpected status value %d\n", 
  92.                 ostat.status ) ;
  93.  
  94.             complain( rc ) ;
  95.       }
  96.    }
  97.  
  98.    if (ochan)
  99.    {   
  100.       rc = sys$qio(0, (short)ochan, IO$_READVBLK, &ostat, 
  101.                     read_in_ast, 1,
  102.                     buffer, BUFSIZE, 0, 0, 0, 0 ) ;
  103. #ifdef VMS_DEBUG
  104.       printf( "I" ) ;
  105.       fflush( stdout ) ;
  106. #endif
  107.  
  108.       if (rc != SS$_NORMAL) complain( rc ) ;
  109.    }
  110. }
  111.  
  112. static int dead=0 ;
  113. volatile static int queue=0 ;
  114.  
  115. static void write_out_ast()
  116. {
  117.    static struct mbox_status istat ;
  118.    static streng *kill=NULL ;
  119.    static char buffer[BUFSIZE] ;
  120.    int rc, len ;
  121.  
  122.    if (queue++)
  123.       return ;
  124.  
  125.    start:
  126.    if (kill)
  127.    {
  128.       Free( kill ) ;
  129.       kill = NULL ;
  130.    }
  131.  
  132.       if (! stack_empty())
  133.       {
  134.           kill = popline() ;
  135.  
  136.           if (!ichan) return ;
  137.           rc = sys$qio(0, ichan, IO$_WRITEVBLK, &istat,  
  138.                        write_out_ast, 0,
  139.                        kill->value, Str_len(kill), 0, 0, 0, 0 ) ; 
  140. #ifdef VMS_DEBUG
  141.           printf( "O" ) ;
  142.           fflush( stdout ) ;
  143. #endif
  144.  
  145.           if (rc != SS$_NORMAL) complain( rc ) ;
  146.       }
  147.       else 
  148.       {
  149.           if (dead++ >= 5) 
  150.           {
  151.              dead = 0 ; 
  152.              return ;
  153.           }
  154.           if (!ichan) return ;
  155.           rc = sys$qio(0, ichan, IO$_WRITEOF, &istat, 
  156.                        write_out_ast, 0, 0, 0, 0, 0, 0, 0 ) ;
  157.           if (rc == SS$_IVCHAN) return ;
  158.           if (rc != SS$_NORMAL) complain( rc ) ;
  159.       }
  160.  
  161.    if (--queue)
  162.       goto start ;
  163.  
  164. }
  165.  
  166.  
  167. vms_do_command( streng *cmd, int in, int out, int fout, int envir )
  168. {
  169.    struct dsc$descriptor_s name, input, output, prc_name ;
  170.    int fdin[2], fdout[2], strval[2], strval2[2], lim=0, max=0 ;
  171.    int rc, rc1, child, status, fin, eflag, olen, ilen ;
  172.    char line[128], obuf[32], buf2[32], ibuf[32], nbuf[32] ;
  173.    struct mbox_status stat ;
  174.  
  175.    name.dsc$w_length = Str_len( cmd ) ;
  176.    name.dsc$b_dtype = DSC$K_DTYPE_T ;
  177.    name.dsc$b_class = DSC$K_CLASS_S ;
  178.    name.dsc$a_pointer = cmd->value ; 
  179.  
  180.    ichan = ochan = 0 ;
  181.    if (in)
  182.    {
  183.       dead = queue = 0 ;
  184.       rc = sys$crembx(0, &ichan, BUFSIZE, BUFSIZE*NUMBUFS, 0, 0, 0) ;
  185.       if (rc != SS$_NORMAL) complain( rc ) ;
  186.       strval[0] = sizeof(ibuf) ;
  187.       strval[1] = ibuf ;
  188.       rc = lib$getdvi( &DVI$_DEVNAM, &ichan, 0, 0, strval, &ilen) ;
  189.       if (rc != SS$_NORMAL) complain( rc ) ;
  190.  
  191.       input.dsc$w_length = ilen ;
  192.       input.dsc$b_dtype = DSC$K_DTYPE_T ;
  193.       input.dsc$b_class = DSC$K_CLASS_S ;
  194.       input.dsc$a_pointer = ibuf ; 
  195.  
  196.    }
  197.  
  198.    if (out || fout)
  199.    {
  200.       rc = sys$crembx(0,&ochan,BUFSIZE,BUFSIZE*NUMBUFS,0,0,0) ;
  201.       if (rc != SS$_NORMAL) complain( rc ) ;
  202. #ifdef VMS_DEBUG
  203.       printf( "sys$crembx() ochan=%d, rc=%d\n", ochan, rc ) ; 
  204. #endif
  205.  
  206.       strval[0] = sizeof(obuf) ;
  207.       strval[1] = obuf ;
  208.       rc=lib$getdvi( &DVI$_DEVNAM, &ochan, 0, 0, strval, &olen) ;
  209.       if (rc != SS$_NORMAL) complain( rc ) ;
  210. #ifdef VMS_DEBUG
  211.       printf( "lib$getdvi() name=(%d) <%s>\n", olen, obuf ) ; 
  212. #endif
  213.  
  214.       output.dsc$w_length = olen ;
  215.       output.dsc$b_dtype = DSC$K_DTYPE_T ;
  216.       output.dsc$b_class = DSC$K_CLASS_S ;
  217.       output.dsc$a_pointer = obuf ; 
  218.    }
  219.  
  220.    sprintf( nbuf, "REXX-%d", getpid()) ; 
  221.    prc_name.dsc$w_length = strlen( nbuf ) ;
  222.    prc_name.dsc$b_dtype = DSC$K_DTYPE_T ;
  223.    prc_name.dsc$b_class = DSC$K_CLASS_S ;
  224.    prc_name.dsc$a_pointer = nbuf ; 
  225.  
  226.    if (out || fout)
  227.    {
  228.       rc = lib$get_ef( &oflag ) ;
  229.       if (rc != SS$_NORMAL) complain( rc ) ;
  230.  
  231.       rc = sys$clref( oflag ) ;
  232. /*      if (rc != SS$_NORMAL) complain( rc ) ; */
  233.    }
  234.  
  235.    rc = lib$get_ef( &eflag ) ;
  236.    if (rc != SS$_NORMAL) complain( rc ) ;
  237.  
  238.    rc = sys$clref( eflag ) ;
  239. /*   if (rc != SS$_NORMAL) complain( rc ) ; */
  240.  
  241.    comp_stat = 0 ;
  242.    rc = lib$spawn( &name, 
  243.                    ((in) ? &input : NULL), 
  244.                    ((out || fout) ? &output : NULL), 
  245.                    &CLI$M_NOWAIT, &prc_name, &pid, &comp_stat, 
  246.                    &eflag, NULL, NULL, NULL, NULL ) ;
  247.  
  248.    if (rc != SS$_NORMAL) complain( rc ) ;
  249.  
  250. #ifdef VMS_DEBUG
  251.    printf( "lib$spawn() rc=%d\n", rc ) ;
  252. #endif
  253.  
  254.    if (in)
  255.       write_out_ast() ;
  256.  
  257.    if (out || fout)
  258.       read_in_ast( 0 ) ;
  259.  
  260. #ifdef VMS_DEBUG
  261.    printf( "Input and output asts started, synching on process\n" ) ;
  262. #endif
  263.    rc = sys$synch( eflag, NULL ) ;
  264. #ifdef VMS_DEBUG
  265.    printf( "sys$synch() rc=%d, ochan=%d\n", rc, ochan ) ;
  266. #endif
  267.    if (ichan)
  268.    {
  269.       rc = sys$dassgn( (short)ichan ) ;
  270.       ichan = 0 ;
  271.       if (rc != SS$_NORMAL) complain( rc ) ;
  272.    }
  273.  
  274.    if (out || fout)
  275.    {
  276.       rc = sys$synch( oflag, NULL ) ;
  277.       if (ochan)
  278.          printf( "Warning ... output channel still exists ochan=%d\n",ochan);
  279.  
  280.       if (rc != SS$_NORMAL) 
  281.          complain( rc ) ;
  282.  
  283.       rc = lib$free_ef( &oflag ) ;
  284.       if (rc != SS$_NORMAL) complain( rc ) ;
  285.    }
  286.  
  287.    rc = lib$free_ef( &eflag ) ;
  288.    if (rc != SS$_NORMAL) complain( rc ) ;
  289.  
  290.    /* 
  291.     * Warning, kludge ahead!!!   When a process under VMS exits, it 
  292.     * seems like there is a little delay until the PRCCNT (process 
  293.     * count) is decremented. So ... if we just continues without 
  294.     * sync'ing up against the PRCCNT, we might get a 'quota exceeded' 
  295.     * on the next command (if it is started very soon)
  296.     */
  297.    lib$getjpi( &JPI$_PRCLM, 0, 0, &max, 0, 0 ) ;
  298.    for (lim=max; lim>=max; )
  299.       lib$getjpi( &JPI$_PRCCNT, 0, 0, &lim, 0, 0 ) ;
  300.  
  301.    complain( 0 ) ;
  302.  
  303.    if (out || fout)
  304.       flush_stack( fout ) ;
  305.  
  306. /*
  307.  * I have no idea _why_, but bit 28 is sometimes set in the comp_stat.
  308.  * Manuals indicate that this is an internal field, but at least it 
  309.  * kills checking against the predefined symbols, so I strip it away.
  310.  * This should most probably have been handled differently, can someone
  311.  * educate me on this?   .... please???
  312.  */
  313.    if ((comp_stat & 0x0fffffff) == CLI$_NORMAL) comp_stat = SS$_NORMAL ;
  314.    return (((comp_stat & 0x0fffffff)==SS$_NORMAL) ? (0) : (comp_stat)) ;
  315. }
  316.  
  317.  
  318. int vms_killproc()
  319. {
  320.    if (pid)
  321.       sys$delprc( &pid, NULL ) ;
  322.  
  323.    pid = 0 ;
  324. }
  325.  
  326.  
  327.  
  328. int complain( int rc ) 
  329. {
  330.  
  331. #ifdef VMS_DEBUG
  332.    printf( "About to complain ... rc=%d, pid=%d, ochan=%d, ichan=%d\n", 
  333.            rc, pid, ochan, ichan ) ; 
  334. #endif
  335.  
  336.     if ((rc != SS$_NORMAL) && pid)
  337.        sys$delprc( &pid, NULL ), pid=0 ; 
  338.  
  339. /*
  340.     if (ochan)
  341.        sys$dassgn( (short)ochan ), ochan=0 ;
  342.  */
  343.     if (ichan)
  344.        sys$dassgn( (short)ichan ), ichan=0 ;
  345.  
  346. #ifdef VMS_DEBUG
  347.    printf( "No more complains left ...about to give error\n" ) ;
  348. #endif
  349.    if (rc && (rc != SS$_NORMAL))
  350.       vms_error( rc ) ;
  351.  
  352. #ifdef VMS_DEBUG
  353.    printf( "Exiting complain\n" ) ; 
  354. #endif
  355.     return ;
  356. }
  357.  
  358.  
  359.  
  360. streng *vms_resolv_symbol( streng *name, streng *new, streng *pool ) 
  361. {
  362.    struct dsc$descriptor_s sym_name, sym_val, new_val ;
  363.    char buffer[MAX_SYM_LENGTH] ;
  364.    unsigned int length=0 ;
  365.    int rc ;
  366.    streng *old ;
  367.  
  368.    sym_name.dsc$w_length = Str_len( name ) ;
  369.    sym_name.dsc$b_dtype = DSC$K_DTYPE_T ;
  370.    sym_name.dsc$b_class = DSC$K_CLASS_S ;
  371.    sym_name.dsc$a_pointer = name->value ; 
  372.    
  373.    if (new) 
  374.    {
  375.       new_val.dsc$w_length = Str_len( new ) ;
  376.       new_val.dsc$b_dtype = DSC$K_DTYPE_T ;
  377.       new_val.dsc$b_class = DSC$K_CLASS_S ;
  378.       new_val.dsc$a_pointer = new->value ; 
  379.    }
  380.    
  381.    sym_val.dsc$w_length = MAX_SYM_LENGTH ;
  382.    sym_val.dsc$b_dtype = DSC$K_DTYPE_T ;
  383.    sym_val.dsc$b_class = DSC$K_CLASS_S ;
  384.    sym_val.dsc$a_pointer = buffer ; 
  385.    
  386.    if (strncmp( pool->value, "SYMBOL", MAX(6,Str_len(pool))) ||
  387.        strncmp( pool->value, "SYSTEM", MAX(6,Str_len(pool))))
  388.    {
  389.       rc = lib$get_symbol( &sym_name, &sym_val, &length ) ;
  390.       if (new) 
  391.          lib$set_symbol( &sym_name, &new_val ) ;
  392.    }
  393.    else if (strncmp( pool->value, "LOGICAL", MAX(7, Str_len(pool))))
  394.    {
  395. /*    rc = lib$get_logical( ... ) */
  396.       if (new)
  397.          lib$set_symbol( &sym_name, &new_val ) ;
  398.       else
  399.          lib$delete_logical( &sym_name ) ;
  400.    }
  401.    else 
  402.       return(NULL) ;
  403.  
  404.    old = Str_make( length ) ;
  405.    Str_ncatstr( old, buffer, length ) ;
  406.    return(old) ;
  407. }
  408.  
  409.  
  410.  
  411. int vms_set_defdir( streng *newdir ) 
  412. {
  413.     int rc ;
  414.     struct dsc$descriptor_s dir = {
  415.        newdir->len, DSC$K_DTYPE_T, DSC$K_CLASS_S, &newdir->value } ;
  416.  
  417.     rc = sys$setddir( &dir ) ;
  418.     return (rc==RMS$_NORMAL) ;
  419. }
  420.