home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / netpbm_src.lzh / NETPBM / PBM / libpbm1.c < prev    next >
Text File  |  1996-11-24  |  37KB  |  1,560 lines

  1. /* libpbm1.c - pbm utility library part 1
  2. **
  3. ** Copyright (C) 1988 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pbm.h"
  14. #include "version.h"
  15. #include "compile.h"
  16. #include "libpbm.h"
  17. #if __STDC__
  18. #include <stdarg.h>
  19. #else /*__STDC__*/
  20. #include <varargs.h>
  21. #endif /*__STDC__*/
  22.  
  23.  
  24. /* Variable-sized arrays. */
  25.  
  26. char*
  27. pm_allocrow( cols, size )
  28.     int cols;
  29.     int size;
  30.     {
  31.     register char* itrow;
  32.  
  33.     itrow = (char*) malloc( cols * size );
  34.     if ( itrow == (char*) 0 )
  35.         pm_error( "out of memory allocating a row" );
  36.     return itrow;
  37.     }
  38.  
  39. void
  40. pm_freerow( itrow )
  41.     char* itrow;
  42.     {
  43.     free( itrow );
  44.     }
  45.  
  46.  
  47. #ifndef A_FRAGARRAY
  48. char**
  49. pm_allocarray( cols, rows, size )
  50.     int cols, rows;
  51.     int size;
  52.     {
  53.     char** its;
  54.     int i;
  55.  
  56.     its = (char**) malloc( rows * sizeof(char*) );
  57.     if ( its == (char**) 0 )
  58.         pm_error( "out of memory allocating an array" );
  59.     its[0] = (char*) malloc( rows * cols * size );
  60.     if ( its[0] == (char*) 0 )
  61.         pm_error( "out of memory allocating an array" );
  62.     for ( i = 1; i < rows; ++i )
  63.         its[i] = &(its[0][i * cols * size]);
  64.     return its;
  65.     }
  66.  
  67. void
  68. pm_freearray( its, rows )
  69.     char** its;
  70.     int rows;
  71.     {
  72.     free( its[0] );
  73.     free( its );
  74.     }
  75. #else /* A_FRAGARRAY */
  76. char**
  77. pm_allocarray( cols, rows, size )
  78.     int cols, rows;
  79.     int size;
  80.     {
  81.     char** its;
  82.     int i;
  83.     its = (char**) malloc( (rows + 1) * sizeof(char*) );
  84.     if ( its == (char**) 0 )
  85.         pm_error( "out of memory allocating an array" );
  86.     its[rows] = its[0] = (char*) malloc( rows * cols * size );
  87.     if ( its[0] != (char*) 0 )
  88.         for ( i = 1; i < rows; ++i )
  89.             its[i] = &(its[0][i * cols * size]);
  90.     else
  91.         for( i = 0; i < rows; ++i )
  92.             its[i] = pm_allocrow( cols, size );
  93.     return its;
  94.     }
  95. void
  96. pm_freearray( its, rows )
  97.     char** its;
  98.     int rows;
  99.     {
  100.     int i;
  101.     if( its[rows] != (char*) 0 )
  102.         free( its[rows] );
  103.     else
  104.         for( i = 0; i < rows; ++i )
  105.             pm_freerow( its[i] );
  106.     free( its );
  107.     }
  108. #endif /* A_FRAGARRAY */
  109.  
  110.  
  111. /* Case-insensitive keyword matcher. */
  112.  
  113. int
  114. pm_keymatch( str, keyword, minchars )
  115.     char* str;
  116.     char* keyword;
  117.     int minchars;
  118.     {
  119.     register int len;
  120.  
  121.     len = strlen( str );
  122.     if ( len < minchars )
  123.         return 0;
  124.     while ( --len >= 0 )
  125.         {
  126.         register char c1, c2;
  127.  
  128.         c1 = *str++;
  129.         c2 = *keyword++;
  130.         if ( c2 == '\0' )
  131.             return 0;
  132.         if ( isupper( c1 ) )
  133.             c1 = tolower( c1 );
  134.         if ( isupper( c2 ) )
  135.             c2 = tolower( c2 );
  136.         if ( c1 != c2 )
  137.             return 0;
  138.         }
  139.     return 1;
  140.     }
  141.  
  142.  
  143. /* Log base two hacks. */
  144.  
  145. int
  146. pm_maxvaltobits( maxval )
  147.     int maxval;
  148.     {
  149.     if ( maxval <= 1 )
  150.         return 1;
  151.     else if ( maxval <= 3 )
  152.         return 2;
  153.     else if ( maxval <= 7 )
  154.         return 3;
  155.     else if ( maxval <= 15 )
  156.         return 4;
  157.     else if ( maxval <= 31 )
  158.         return 5;
  159.     else if ( maxval <= 63 )
  160.         return 6;
  161.     else if ( maxval <= 127 )
  162.         return 7;
  163.     else if ( maxval <= 255 )
  164.         return 8;
  165.     else if ( maxval <= 511 )
  166.         return 9;
  167.     else if ( maxval <= 1023 )
  168.         return 10;
  169.     else if ( maxval <= 2047 )
  170.         return 11;
  171.     else if ( maxval <= 4095 )
  172.         return 12;
  173.     else if ( maxval <= 8191 )
  174.         return 13;
  175.     else if ( maxval <= 16383 )
  176.         return 14;
  177.     else if ( maxval <= 32767 )
  178.         return 15;
  179.     else if ( (long) maxval <= 65535L )
  180.         return 16;
  181.     else
  182.         pm_error( "maxval of %d is too large!", maxval );
  183.     }
  184.  
  185. int
  186. pm_bitstomaxval( bits )
  187.     int bits;
  188.     {
  189.     return ( 1 << bits ) - 1;
  190.     }
  191.  
  192.  
  193. /* Initialization. */
  194.  
  195. static char* progname;
  196. static int showmessages;
  197.  
  198. void
  199. pm_init( argcP, argv )
  200.     int* argcP;
  201.     char* argv[];
  202.     {
  203.     int argn, i;
  204. #ifdef A_RGBENV
  205.     char *rgbdef;
  206. #endif /* A_RGBENV */
  207.  
  208. #ifndef VMS
  209.     /* Extract program name. */
  210.     progname = rindex( argv[0], '/');
  211. #else
  212. {   char **temp_argv = argv;
  213.     int old_argc = *argcP;
  214.     int i;
  215.     getredirection( argcP, &temp_argv );
  216.     if (*argcP > old_argc) {
  217.         /* Number of command line arguments has increased */
  218.         fprintf( stderr, "Sorry!! getredirection() for VMS has changed the argument list!!!\n");
  219.         fprintf( stderr, "This is intolerable at the present time, so we must stop!!!\n");
  220.         exit(1);
  221.     }
  222.     for (i=0; i<*argcP; i++)
  223.         argv[i] = temp_argv[i];
  224.     }
  225.     if ( progname == NULL ) progname = rindex( argv[0], ']');
  226.     if ( progname == NULL ) progname = rindex( argv[0], '>');
  227. #endif
  228.     if ( progname == NULL )
  229.         progname = argv[0];
  230.     else
  231.         ++progname;
  232.  
  233.     /* Check for any global args. */
  234.     showmessages = 1;
  235.     for ( argn = 1; argn < *argcP; ++argn )
  236.         {
  237.         if ( pm_keymatch( argv[argn], "-quiet", 6 ) )
  238.             {
  239.             showmessages = 0;
  240.             }
  241.         else if ( pm_keymatch( argv[argn], "-version", 7 ) )
  242.             {
  243.             pm_message( "Version: %s", PBMPLUS_VERSION );
  244. #if defined(COMPILE_TIME) && defined(COMPILED_BY)
  245.         pm_message( "Compiled %s by user \"%s\"",
  246.                COMPILE_TIME, COMPILED_BY );
  247. #endif
  248. #ifdef BSD
  249.             pm_message( "BSD defined" );
  250. #endif /*BSD*/
  251. #ifdef SYSV
  252. #ifdef VMS
  253.         pm_message( "VMS & SYSV defined" );
  254. #else
  255.           pm_message( "SYSV defined" );
  256. #endif
  257. #endif /*SYSV*/
  258. #ifdef MSDOS
  259.             pm_message( "MSDOS defined" );
  260. #endif /*MSDOS*/
  261. #ifdef AMIGA
  262.             pm_message( "AMIGA defined" );
  263. #endif /* AMIGA */
  264. #ifdef PBMPLUS_RAWBITS
  265.             pm_message( "PBMPLUS_RAWBITS defined" );
  266. #endif /*PBMPLUS_RAWBITS*/
  267. #ifdef PBMPLUS_BROKENPUTC1
  268.             pm_message( "PBMPLUS_BROKENPUTC1 defined" );
  269. #endif /*PBMPLUS_BROKENPUTC1*/
  270. #ifdef PBMPLUS_BROKENPUTC2
  271.             pm_message( "PBMPLUS_BROKENPUTC2 defined" );
  272. #endif /*PBMPLUS_BROKENPUTC2*/
  273. #ifdef PGM_BIGGRAYS
  274.             pm_message( "PGM_BIGGRAYS defined" );
  275. #endif /*PGM_BIGGRAYS*/
  276. #ifdef PPM_PACKCOLORS
  277.             pm_message( "PPM_PACKCOLORS defined" );
  278. #endif /*PPM_PACKCOLORS*/
  279. #ifdef DEBUG
  280.             pm_message( "DEBUG defined" );
  281. #endif /*DEBUG*/
  282. #ifdef NEED_VFPRINTF1
  283.             pm_message( "NEED_VFPRINTF1 defined" );
  284. #endif /*NEED_VFPRINTF1*/
  285. #ifdef NEED_VFPRINTF2
  286.             pm_message( "NEED_VFPRINTF2 defined" );
  287. #endif /*NEED_VFPRINTF2*/
  288. #ifdef RGB_DB
  289. #ifndef A_RGBENV
  290.             pm_message( "RGB_DB=\"%s\"", RGB_DB );
  291. #else /* A_RGBENV */
  292.             if( rgbdef = getenv(RGB_DB) )
  293.                 pm_message( "RGB_DB= Env-var %s (set to \"%s\")", RGB_DB, rgbdef );
  294.             else
  295.                 pm_message( "RGB_DB= Env-var %s (unset)", RGB_DB );
  296. #endif /* A_RGBENV */
  297. #endif /*RGB_DB*/
  298. #ifdef LIBTIFF
  299.             pm_message( "LIBTIFF defined" );
  300. #endif /*LIBTIFF*/
  301.             exit( 0 );
  302.             }
  303.         else
  304.             continue;
  305.         for ( i = argn + 1; i <= *argcP; ++i )
  306.             argv[i - 1] = argv[i];
  307.         --(*argcP);
  308.         }
  309.     }
  310.  
  311. void
  312. pbm_init( argcP, argv )
  313.     int* argcP;
  314.     char* argv[];
  315.     {
  316.     pm_init( argcP, argv );
  317.     }
  318.  
  319.  
  320. /* Error handling. */
  321.  
  322. void
  323. pm_usage( usage )
  324.     char* usage;
  325.     {
  326.     fprintf( stderr, "usage:  %s %s\n", progname, usage );
  327.     exit( 1 );
  328.     }
  329.  
  330. void
  331. pm_perror( reason )
  332.     char* reason;
  333.     {
  334. #ifndef A_STRERROR
  335.     extern char* sys_errlist[];
  336. #endif /* A_STRERROR */
  337.     extern int errno;
  338.     char* e;
  339.  
  340. #ifndef _OSK
  341. #ifdef A_STRERROR
  342.     e = strerror(errno);
  343. #else /* A_STRERROR */
  344.     e = sys_errlist[errno];
  345. #endif /* A_STRERROR */
  346.  
  347.     if ( reason != 0 && reason[0] != '\0' )
  348.         pm_error( "%s - %s", reason, e );
  349.     else
  350.         pm_error( "%s", e );
  351.     }
  352. #else
  353.     if ( reason != 0 && reason[0] != '\0' )
  354.         pm_error( "%s - %s", reason, errno );
  355.     else
  356.         pm_error( "%s", errno );
  357.     }
  358. #endif
  359.  
  360. #if __STDC__
  361. void
  362. pm_message( char* format, ... )
  363.     {
  364.     va_list args;
  365.  
  366.     va_start( args, format );
  367. #else /*__STDC__*/
  368. /*VARARGS1*/
  369. void
  370. pm_message( va_alist )
  371.     va_dcl
  372.     { /*}*/
  373.     va_list args;
  374.     char* format;
  375.  
  376.     va_start( args );
  377.     format = va_arg( args, char* );
  378. #endif /*__STDC__*/
  379.  
  380.     if ( showmessages )
  381.         {
  382.         fprintf( stderr, "%s: ", progname );
  383.         (void) vfprintf( stderr, format, args );
  384.         fputc( '\n', stderr );
  385.         }
  386.     va_end( args );
  387.     }
  388.  
  389. #if __STDC__
  390. void
  391. pm_error( char* format, ... )
  392.     {
  393.     va_list args;
  394.  
  395.     va_start( args, format );
  396. #else /*__STDC__*/
  397. /*VARARGS1*/
  398. void
  399. pm_error( va_alist )
  400.     va_dcl
  401.     { /*}*/
  402.     va_list args;
  403.     char* format;
  404.  
  405.     va_start( args );
  406.     format = va_arg( args, char* );
  407. #endif /*__STDC__*/
  408.  
  409.     fprintf( stderr, "%s: ", progname );
  410.     (void) vfprintf( stderr, format, args );
  411.     fputc( '\n', stderr );
  412.     va_end( args );
  413.     exit( 1 );
  414.     }
  415.  
  416. #ifdef NEED_VFPRINTF1
  417.  
  418. /* Micro-vfprintf, for systems that don't have vfprintf but do have _doprnt.
  419. */
  420.  
  421. int
  422. vfprintf( stream, format, args )
  423.     FILE* stream;
  424.     char* format;
  425.     va_list args;
  426.     {
  427.     return _doprnt( format, args, stream );
  428.     }
  429. #endif /*NEED_VFPRINTF1*/
  430.  
  431. #ifdef NEED_VFPRINTF2
  432.  
  433. /* Portable mini-vfprintf, for systems that don't have either vfprintf or
  434. ** _doprnt.  This depends only on fprintf.  If you don't have fprintf,
  435. ** you might consider getting a new stdio library.
  436. */
  437.  
  438. int
  439. vfprintf( stream, format, args )
  440.     FILE* stream;
  441.     char* format;
  442.     va_list args;
  443.     {
  444.     int n;
  445.     char* ep;
  446.     char fchar;
  447.     char tformat[512];
  448.     int do_long;
  449.     int i;
  450.     long l;
  451.     unsigned u;
  452.     unsigned long ul;
  453.     char* s;
  454.     double d;
  455.  
  456.     n = 0;
  457.     while ( *format != '\0' )
  458.         {
  459.         if ( *format != '%' )
  460.             { /* Not special, just write out the char. */
  461.             (void) putc( *format, stream );
  462.             ++n;
  463.             ++format;
  464.             }
  465.         else
  466.             {
  467.             do_long = 0;
  468.             ep = format + 1;
  469.  
  470.             /* Skip over all the field width and precision junk. */
  471.             if ( *ep == '-' )
  472.                 ++ep;
  473.             if ( *ep == '0' )
  474.                 ++ep;
  475.             while ( isdigit( *ep ) )
  476.                 ++ep;
  477.             if ( *ep == '.' )
  478.                 {
  479.                 ++ep;
  480.                 while ( isdigit( *ep ) )
  481.                     ++ep;
  482.                 }
  483.             if ( *ep == '#' )
  484.                 ++ep;
  485.             if ( *ep == 'l' )
  486.                 {
  487.                 do_long = 1;
  488.                 ++ep;
  489.                 }
  490.  
  491.             /* Here's the field type.  Extract it, and copy this format
  492.             ** specifier to a temp string so we can add an end-of-string.
  493.             */
  494.             fchar = *ep;
  495.             (void) strncpy( tformat, format, ep - format + 1 );
  496.             tformat[ep - format + 1] = '\0';
  497.  
  498.             /* Now do a one-argument fprintf with the format string we have
  499.             ** isolated.
  500.             */
  501.             switch ( fchar )
  502.                 {
  503.                 case 'd':
  504.                 if ( do_long )
  505.                     {
  506.                     l = va_arg( args, long );
  507.                     n += fprintf( stream, tformat, l );
  508.                     }
  509.                 else
  510.                     {
  511.                     i = va_arg( args, int );
  512.                     n += fprintf( stream, tformat, i );
  513.                     }
  514.                 break;
  515.  
  516.                 case 'o':
  517.                 case 'x':
  518.                 case 'X':
  519.                 case 'u':
  520.                 if ( do_long )
  521.                     {
  522.                     ul = va_arg( args, unsigned long );
  523.                     n += fprintf( stream, tformat, ul );
  524.                     }
  525.                 else
  526.                     {
  527.                     u = va_arg( args, unsigned );
  528.                     n += fprintf( stream, tformat, u );
  529.                     }
  530.                 break;
  531.  
  532.                 case 'c':
  533.                 i = (char) va_arg( args, int );
  534.                 n += fprintf( stream, tformat, i );
  535.                 break;
  536.  
  537.                 case 's':
  538.                 s = va_arg( args, char* );
  539.                 n += fprintf( stream, tformat, s );
  540.                 break;
  541.  
  542.                 case 'e':
  543.                 case 'E':
  544.                 case 'f':
  545.                 case 'g':
  546.                 case 'G':
  547.                 d = va_arg( args, double );
  548.                 n += fprintf( stream, tformat, d );
  549.                 break;
  550.  
  551.                 case '%':
  552.                 (void) putc( '%', stream );
  553.                 ++n;
  554.                 break;
  555.  
  556.                 default:
  557.                 return -1;
  558.                 }
  559.  
  560.             /* Resume formatting on the next character. */
  561.             format = ep + 1;
  562.             }
  563.         }
  564.     return nc;
  565.     }
  566. #endif /*NEED_VFPRINTF2*/
  567.  
  568. #ifdef NEED_STRSTR
  569. /* for systems which do not provide strstr */
  570. char*
  571. strstr(s1, s2)
  572.     char *s1, *s2;
  573. {
  574.     int ls2 = strlen(s2);
  575.  
  576.     if (ls2 == 0)
  577.         return (s1);
  578.     while (strlen(s1) >= ls2) {
  579.         if (strncmp(s1, s2, ls2) == 0)
  580.             return (s1);
  581.         s1++;
  582.     }
  583.     return (0);
  584. }
  585.  
  586. #endif /*NEED_STRSTR*/
  587.  
  588.  
  589. /* File open/close that handles "-" as stdin and checks errors. */
  590.  
  591. FILE*
  592. pm_openr( name )
  593.     char* name;
  594.     {
  595.     FILE* f;
  596.  
  597.     if ( strcmp( name, "-" ) == 0 )
  598.         f = stdin;
  599.     else
  600.         {
  601. #ifdef MSDOS
  602.         f = fopen( name, "rb" );
  603. #else /*MSDOS*/
  604. #ifndef VMS
  605.       f = fopen( name, "r" );
  606. #else
  607.     f = fopen ( name, "r", "ctx=stm" );
  608. #endif
  609. #endif /*MSDOS*/
  610.         if ( f == NULL )
  611.             {
  612.             pm_perror( name );
  613.             exit( 1 );
  614.             }
  615.         }
  616.     return f;
  617.     }
  618.  
  619. FILE*
  620. pm_openw( name )
  621.     char* name;
  622.     {
  623.     FILE* f;
  624.  
  625. #ifdef MSDOS
  626.     f = fopen( name, "wb" );
  627. #else /*MSDOS*/
  628. #ifndef VMS
  629.     f = fopen( name, "w" );
  630. #else
  631.     f = fopen ( name, "w", "mbc=32", "mbf=2" );  /* set buffer factors */
  632. #endif
  633. #endif /*MSDOS*/
  634.     if ( f == NULL )
  635.         {
  636.         pm_perror( name );
  637.         exit( 1 );
  638.         }
  639.     return f;
  640.     }
  641.  
  642. void
  643. pm_close( f )
  644.     FILE* f;
  645.     {
  646.     fflush( f );
  647.     if ( ferror( f ) )
  648.         pm_message( "a file read or write error occurred at some point" );
  649.     if ( f != stdin )
  650.         if ( fclose( f ) != 0 )
  651.             pm_perror( "fclose" );
  652.     }
  653.  
  654. /* Endian I/O.
  655. */
  656.  
  657. int
  658. pm_readbigshort( in, sP )
  659.     FILE* in;
  660.     short* sP;
  661.     {
  662.     int c;
  663.  
  664.     if ( (c = getc( in )) == EOF )
  665.         return -1;
  666.     *sP = ( c & 0xff ) << 8;
  667.     if ( (c = getc( in )) == EOF )
  668.         return -1;
  669.     *sP |= c & 0xff;
  670.     return 0;
  671.     }
  672.  
  673. #if __STDC__
  674. int
  675. pm_writebigshort( FILE* out, short s )
  676. #else /*__STDC__*/
  677. int
  678. pm_writebigshort( out, s )
  679.     FILE* out;
  680.     short s;
  681. #endif /*__STDC__*/
  682.     {
  683.     (void) putc( ( s >> 8 ) & 0xff, out );
  684.     (void) putc( s & 0xff, out );
  685.     return 0;
  686.     }
  687.  
  688. int
  689. pm_readbiglong( in, lP )
  690.     FILE* in;
  691.     long* lP;
  692.     {
  693.     int c;
  694.  
  695.     if ( (c = getc( in )) == EOF )
  696.         return -1;
  697.     *lP = ( c & 0xff ) << 24;
  698.     if ( (c = getc( in )) == EOF )
  699.         return -1;
  700.     *lP |= ( c & 0xff ) << 16;
  701.     if ( (c = getc( in )) == EOF )
  702.         return -1;
  703.     *lP |= ( c & 0xff ) << 8;
  704.     if ( (c = getc( in )) == EOF )
  705.         return -1;
  706.     *lP |= c & 0xff;
  707.     return 0;
  708.     }
  709.  
  710. int
  711. pm_writebiglong( out, l )
  712.     FILE* out;
  713.     long l;
  714.     {
  715.     (void) putc( ( l >> 24 ) & 0xff, out );
  716.     (void) putc( ( l >> 16 ) & 0xff, out );
  717.     (void) putc( ( l >> 8 ) & 0xff, out );
  718.     (void) putc( l & 0xff, out );
  719.     return 0;
  720.     }
  721.  
  722. int
  723. pm_readlittleshort( in, sP )
  724.     FILE* in;
  725.     short* sP;
  726.     {
  727.     int c;
  728.  
  729.     if ( (c = getc( in )) == EOF )
  730.         return -1;
  731.     *sP = c & 0xff;
  732.     if ( (c = getc( in )) == EOF )
  733.         return -1;
  734.     *sP |= ( c & 0xff ) << 8;
  735.     return 0;
  736.     }
  737.  
  738. #if __STDC__
  739. int
  740. pm_writelittleshort( FILE* out, short s )
  741. #else /*__STDC__*/
  742. int
  743. pm_writelittleshort( out, s )
  744.     FILE* out;
  745.     short s;
  746. #endif /*__STDC__*/
  747.     {
  748.     (void) putc( s & 0xff, out );
  749.     (void) putc( ( s >> 8 ) & 0xff, out );
  750.     return 0;
  751.     }
  752.  
  753. int
  754. pm_readlittlelong( in, lP )
  755.     FILE* in;
  756.     long* lP;
  757.     {
  758.     int c;
  759.  
  760.     if ( (c = getc( in )) == EOF )
  761.         return -1;
  762.     *lP = c & 0xff;
  763.     if ( (c = getc( in )) == EOF )
  764.         return -1;
  765.     *lP |= ( c & 0xff ) << 8;
  766.     if ( (c = getc( in )) == EOF )
  767.         return -1;
  768.     *lP |= ( c & 0xff ) << 16;
  769.     if ( (c = getc( in )) == EOF )
  770.         return -1;
  771.     *lP |= ( c & 0xff ) << 24;
  772.     return 0;
  773.     }
  774.  
  775. int
  776. pm_writelittlelong( out, l )
  777.     FILE* out;
  778.     long l;
  779.     {
  780.     (void) putc( l & 0xff, out );
  781.     (void) putc( ( l >> 8 ) & 0xff, out );
  782.     (void) putc( ( l >> 16 ) & 0xff, out );
  783.     (void) putc( ( l >> 24 ) & 0xff, out );
  784.     return 0;
  785.     }
  786.  
  787.  
  788. /* Read a file of unknown size to a buffer. Return the number of bytes
  789.    read. Allocate more memory as we need it. The calling routine has
  790.    to free() the buffer.
  791.  
  792.    Oliver Trepte, oliver@fysik4.kth.se, 930613 */
  793.  
  794. #define PM_BUF_SIZE 16384      /* First try this size of the buffer, then
  795.                                    double this until we reach PM_MAX_BUF_INC */
  796. #define PM_MAX_BUF_INC 65536   /* Don't allocate more memory in larger blocks
  797.                                    than this. */
  798.  
  799. char *pm_read_unknown_size( file, nread )
  800.     FILE* file;
  801.     long* nread;
  802. {
  803.     long nalloc;
  804.     register int val;
  805.     char* buf;
  806.  
  807.     *nread = 0;
  808.     if ((buf=malloc(PM_BUF_SIZE)) == NULL)
  809.         pm_error("Cannot allocate memory");
  810.     nalloc = PM_BUF_SIZE;
  811.  
  812.     while(1) {
  813.         if (*nread >= nalloc) { /* We need a larger buffer */
  814.             if (nalloc > PM_MAX_BUF_INC)
  815.                 nalloc += PM_MAX_BUF_INC;
  816.             else
  817.                 nalloc += nalloc;
  818.             if ((buf=realloc(buf, nalloc)) == NULL)
  819.                 pm_error("Cannot allocate %d bytes of memory", nalloc);
  820.         }
  821.  
  822.         if ((val = getc(file)) == EOF)
  823.             return (buf);
  824.  
  825.         buf[(*nread)++] = val;
  826.     }
  827. }
  828.  
  829. /*****************************************************************************/
  830.  
  831. #ifdef VMS
  832. /*
  833.  * @(#)argproc.c 1.0 89/02/01        Mark Pizzolato (mark@infopiz.uucp)    
  834.  */
  835.  
  836. #ifndef lint
  837. char argproc_version[] = "@(#)argproc.c VMS uucp Version infopiz-1.0";
  838. #endif
  839.  
  840. #include "includes.h"        /* System include files, system dependent */
  841.  
  842.  
  843. /*
  844.  * getredirection() is intended to aid in porting C programs
  845.  * to VMS (Vax-11 C) which does not support '>' and '<'
  846.  * I/O redirection, along with a command line pipe mechanism
  847.  * using the '|' AND background command execution '&'.
  848.  * The piping mechanism will probably work with almost any 'filter' type
  849.  * of program.  With suitable modification, it may useful for other
  850.  * portability problems as well.
  851.  *
  852.  * Author:  Mark Pizzolato    mark@infopiz.UUCP
  853.  */
  854. struct list_item
  855.     {
  856.     struct list_item *next;
  857.     char *value;
  858.     };
  859.  
  860. int
  861. getredirection(ac, av)
  862. int        *ac;
  863. char        ***av;
  864. /*
  865.  * Process vms redirection arg's.  Exit if any error is seen.
  866.  * If getredirection() processes an argument, it is erased
  867.  * from the vector.  getredirection() returns a new argc and argv value.
  868.  * In the event that a background command is requested (by a trailing "&"),
  869.  * this routine creates a background subprocess, and simply exits the program.
  870.  *
  871.  * Warning: do not try to simplify the code for vms.  The code
  872.  * presupposes that getredirection() is called before any data is
  873.  * read from stdin or written to stdout.
  874.  *
  875.  * Normal usage is as follows:
  876.  *
  877.  *    main(argc, argv)
  878.  *    int        argc;
  879.  *        char        *argv[];
  880.  *    {
  881.  *        getredirection(&argc, &argv);
  882.  *    }
  883.  */
  884. {
  885.     int            argc = *ac;    /* Argument Count      */
  886.     char        **argv = *av;    /* Argument Vector      */
  887.     char        *ap;           /* Argument pointer      */
  888.     int                   j;        /* argv[] index          */
  889.     extern int        errno;        /* Last vms i/o error       */
  890.     int            item_count = 0;    /* Count of Items in List */
  891.     int            new_file;    /* flag, true if '>' used */
  892.     struct list_item     *list_head = 0;    /* First Item in List        */
  893.     struct list_item    *list_tail;    /* Last Item in List        */
  894.     char         *in = NULL;    /* Input File Name        */
  895.     char         *out = NULL;    /* Output File Name        */
  896.     char         *outmode = "w";    /* Mode to Open Output File */
  897.     int            cmargc = 0;        /* Piped Command Arg Count  */
  898.     char        **cmargv = NULL;/* Piped Command Arg Vector */
  899.     stat_t        statbuf;    /* fstat buffer            */
  900.  
  901.     /*
  902.      * First handle the case where the last thing on the line ends with
  903.      * a '&'.  This indicates the desire for the command to be run in a
  904.      * subprocess, so we satisfy that desire.
  905.      */
  906.     ap = argv[argc-1];
  907.     if (0 == strcmp("&", ap))
  908.     exit(background_process(--argc, argv));
  909.     if ('&' == ap[strlen(ap)-1])
  910.     {
  911.     ap[strlen(ap)-1] = '\0';
  912.     exit(background_process(argc, argv));
  913.     }
  914.     /*
  915.      * Now we handle the general redirection cases that involve '>', '>>',
  916.      * '<', and pipes '|'.
  917.      */
  918.     for (new_file = 0, j = 0; j < argc; ++j)
  919.     {
  920.     if (0 == strcmp("<", argv[j]))
  921.         {
  922.         if (j+1 >= argc)
  923.         {
  924.         errno = EINVAL;
  925.         perror("No input file");
  926.         exit(EXIT_ERR);
  927.         }
  928.         in = argv[++j];
  929.         continue;
  930.         }
  931.     if ('<' == *(ap = argv[j]))
  932.         {
  933.         in = 1 + ap;
  934.         continue;
  935.         }
  936.     if (0 == strcmp(">", ap))
  937.         {
  938.         if (j+1 >= argc)
  939.         {
  940.         errno = EINVAL;
  941.         perror("No output file");
  942.         exit(EXIT_ERR);
  943.         }
  944.         out = argv[++j];
  945.         new_file = 1;
  946.         continue;
  947.         }
  948.     if ('>' == *ap)
  949.         {
  950.         if ('>' == ap[1])
  951.         {
  952.         outmode = "a";
  953.         if ('\0' == ap[2])
  954.             out = argv[++j];
  955.         else
  956.             out = 2 + ap;
  957.         }
  958.         else
  959.         { out = 1 + ap;  new_file = 1; }
  960.         continue;
  961.         }
  962.     if (0 == strcmp("|", argv[j]))
  963.         {
  964.         if (j+1 >= argc)
  965.         {
  966.         errno = EPIPE;
  967.         perror("No command to Pipe to");
  968.         exit(EXIT_ERR);
  969.         }
  970.         cmargc = argc-(j+1);
  971.         cmargv = &argv[j+1];
  972.         argc = j;
  973.         outmode = "wb";    /* pipes are binary mode devices */
  974.         continue;
  975.         }
  976.     if ('|' == *(ap = argv[j]))
  977.         {
  978.         ++argv[j];
  979.         cmargc = argc-j;
  980.         cmargv = &argv[j];
  981.         argc = j;
  982.         outmode = "wb";    /* pipes are binary mode devices */
  983.         continue;
  984.         }
  985.     expand_wild_cards(ap, &list_head, &list_tail, &item_count);
  986.     }
  987.     /*
  988.      * Allocate and fill in the new argument vector, Some Unix's terminate
  989.      * the list with an extra null pointer.
  990.      */
  991.     argv = *av = calloc(item_count+1, sizeof(char *));
  992.     for (j = 0; j < item_count; ++j, list_head = list_head->next)
  993.     argv[j] = list_head->value;
  994.     *ac = item_count;
  995.     if (cmargv != NULL)
  996.     {
  997.     char subcmd[1024];
  998.     static char *pipe_and_fork();
  999.  
  1000.     if (out != NULL)
  1001.         {
  1002.         errno = EINVAL;
  1003.         perror("Invalid '|' and '>' specified");
  1004.         exit(EXIT_ERR);
  1005.         }
  1006.     strcpy(subcmd, cmargv[0]);
  1007.     for (j = 1; j < cmargc; ++j)
  1008.         {
  1009.         strcat(subcmd, " \"");
  1010.         strcat(subcmd, cmargv[j]);
  1011.         strcat(subcmd, "\"");
  1012.         }
  1013.     out = pipe_and_fork(subcmd);
  1014.     outmode = "wb";
  1015.     }
  1016.     
  1017.     /* Check for input from a pipe (mailbox) */
  1018.  
  1019.     if(fstat(0, &statbuf) == 0){
  1020.     if(strncmp(statbuf.st_dev, "MB", 2) == 0 || 
  1021.         strncmp(statbuf.st_dev, "_MB", 3) == 0){
  1022.  
  1023.         /* Input from a pipe, reopen it in binary mode to disable    */
  1024.         /* carriage control processing.                */
  1025.  
  1026.         if (in != NULL){
  1027.         errno = EINVAL;
  1028.         perror("Invalid '|' and '<' specified");
  1029.         exit(EXIT_ERR);
  1030.         }
  1031.         freopen(statbuf.st_dev, "rb", stdin);
  1032.         }
  1033.     }
  1034.     else {
  1035.     perror("fstat failed");
  1036.     exit(EXIT_ERR);
  1037.     }
  1038.  
  1039. #ifdef __ALPHA
  1040.         /*, "mbc=32", "mbf=2"))) blows up on the ALPHA cbm 11/08/92 */
  1041.     if ((in != NULL) && (NULL == freopen(in, "r", stdin)))
  1042.         {
  1043. #else
  1044.     if ((in != NULL) && (NULL == freopen(in, "r", stdin, "mbc=32", "mbf=2")))
  1045.     {
  1046. #endif
  1047.     perror(in);                   /* Can't find file        */
  1048.     exit(EXIT_ERR);        /* Is a fatal error        */
  1049.     }
  1050. #ifdef __ALPHA
  1051.     if ((out != NULL) && (NULL == freopen(out, outmode, stdout)))
  1052.         {
  1053. #else
  1054.     if ((out != NULL) && (NULL == freopen(out, outmode, stdout, "mbc=32", "mbf=2")))
  1055.     {    
  1056. #endif
  1057.     perror(ap);        /* Error, can't write or append    */
  1058.     exit(EXIT_ERR);        /* Is a fatal error        */
  1059.     }
  1060.  
  1061.      if ( new_file ) {
  1062.     /*
  1063.      * We are making an explicit output file, fstat the file and
  1064.          * declare exit handler to be able change the file to fixed length
  1065.      * records if necessary. 
  1066.      */
  1067.     char fname[256];
  1068.     static int outfile_rundown(), check_outfile_filetype();
  1069.     static stat_t ofile_stat;
  1070.     static struct exit_control_block {
  1071.             struct exit_control_block *flink;
  1072.             int    (*exit_routine)();
  1073.         int arg_count;
  1074.         int *status_address;    /* arg 1 */
  1075.         stat_t *stat;        /* arg 2 */
  1076.         int exit_status;
  1077.         int skew[128];
  1078.     } exit_block = 
  1079.         { 0, outfile_rundown, 2, &exit_block.exit_status, &ofile_stat, 0 };
  1080.  
  1081.     if ( fstat ( fileno(stdout), &ofile_stat ) == 0 )
  1082.          sys$dclexh ( &exit_block );
  1083.     else fprintf(stderr,"Error fstating stdout - %s\n",
  1084.         strerror(errno,vaxc$errno) );
  1085.  
  1086.     if ( fgetname ( stdout, fname, 0 ) ) check_outfile_filetype ( fname );
  1087.      }
  1088. #ifdef DEBUG
  1089.     fprintf(stderr, "Arglist:\n");
  1090.     for (j = 0; j < *ac;  ++j)
  1091.     fprintf(stderr, "argv[%d] = '%s'\n", j, argv[j]);
  1092. #endif
  1093. }
  1094.  
  1095. static int binary_outfile = 0;
  1096. void set_outfile_binary() { binary_outfile = 1; return; }
  1097.  
  1098. /*
  1099.  * Check if output file should be set to binary (fixed 512) on exit based
  1100.  * upon the filetype.
  1101.  */
  1102. static int check_outfile_filetype ( name )
  1103.     char *name;
  1104. {
  1105.     char *binary_filetypes, *ext, *p, *t;
  1106.     binary_filetypes = (char *) getenv ( "PBM_BINARY_FILETYPES" );
  1107.     if ( binary_filetypes == NULL ) return 0;
  1108.  
  1109.     ext = strchr ( name, '.' );  if ( ext == NULL ) return 0;
  1110.     ext++;
  1111.     t = strrchr ( name, '.' );   if ( t != NULL ) *t = '\0';
  1112.  
  1113.     for ( p = binary_filetypes; *p != '\0'; p++ ) {
  1114.     for ( t = p;
  1115.           (*p != '\0' ) && (strchr ( ",     ", *p ) == NULL); 
  1116.          p++ ) *p = toupper(*p);
  1117.     *p = '\0';
  1118.  
  1119.     if ( strcmp ( t, ext ) == 0 ) {
  1120.         binary_outfile = 1;
  1121.         break;
  1122.     }
  1123.     }
  1124.     return binary_outfile;
  1125. }
  1126.  
  1127.  
  1128. /*
  1129.  * Exit handler to set output file to binary on image exit.
  1130.  */
  1131. static int outfile_rundown ( reason, statbuf )
  1132.     int *reason;
  1133.     stat_t *statbuf;
  1134. {
  1135.     int code, channel, status, LIB$GETDVI(), sys$assign(), sys$qiow();
  1136.     long int fib_desc[2], devchar;
  1137.     short int iosb[4];
  1138.     $DESCRIPTOR(device, statbuf->st_dev);
  1139.     struct fibdef fib;        /* File information block (XQP) */
  1140.     struct atrdef atr[2];
  1141.     struct fat {
  1142.       unsigned char rtype, ratattrib;
  1143.       unsigned short int rsize, hiblk[2], efblk[2], ffbyte, maxrec, defext, gbc;
  1144.       unsigned short int reserved[4], versions;
  1145.     } rat;
  1146.  
  1147.     if ( !binary_outfile ) return 1;    /* leave file alone */
  1148.     /*
  1149.      * Assign channel to device listed in stat block and test if it is
  1150.      * a directory structured device, returning if not.
  1151.      */
  1152.     device.dsc$w_length = strlen ( statbuf->st_dev );
  1153.     status = sys$assign ( &device, &channel, 0, 0 );
  1154.     if ((status & 1) == 0) { fprintf(stderr, 
  1155.     "assign error to %s (%d)\n", device.dsc$a_pointer, status);
  1156.         return status; }
  1157.     code = DVI$_DEVCHAR;
  1158.     status = LIB$GETDVI ( &code, &channel, 0, &devchar );
  1159.     if ((status & 1) == 0) { fprintf(stderr, "getdvi error: %d\n", status);
  1160.         return status; }
  1161.     if ( (devchar & DEV$M_DIR) == 0 ) return 1;
  1162.     /*
  1163.      * Build File Information Block and Atrribute block.
  1164.      */
  1165. #ifdef __ALPHA
  1166.     fib.fib$w_fid[0] = statbuf->st_ino[0];
  1167.     fib.fib$w_fid[1] = statbuf->st_ino[1];
  1168.     fib.fib$w_fid[2] = statbuf->st_ino[2];
  1169. #else
  1170.     fib.fib$r_fid_overlay.fib$w_fid[0] = statbuf->st_ino[0];
  1171.     fib.fib$r_fid_overlay.fib$w_fid[1] = statbuf->st_ino[1];
  1172.     fib.fib$r_fid_overlay.fib$w_fid[2] = statbuf->st_ino[2];
  1173. #endif
  1174.  
  1175.     atr[0].atr$w_size = sizeof(rat);
  1176.     atr[0].atr$w_type = ATR$C_RECATTR;
  1177.     atr[0].atr$l_addr = &rat;
  1178.     atr[1].atr$w_size = 0; atr[1].atr$w_type = 0;
  1179.     /*
  1180.      * Perform access function with read_attributes sub-function.
  1181.      */
  1182.     freopen ( "SYS$OUTPUT:", "a", stdout );
  1183.     fib_desc[0] = 10; fib_desc[1] = (long int) &fib;
  1184. #ifdef __ALPHA
  1185.     fib.fib$l_acctl = FIB$M_WRITE;
  1186. #else
  1187.     fib.fib$r_acctl_overlay.fib$l_acctl = FIB$M_WRITE;
  1188. #endif
  1189.     status = sys$qiow ( 0, channel, IO$_ACCESS|IO$M_ACCESS,
  1190.          &iosb, 0, 0, &fib_desc, 0, 0, 0, &atr, 0 );
  1191.     /*
  1192.      * If status successful, update record byte and perform a MODIFY.
  1193.      */
  1194.     if ( (status&1) == 1 ) status = iosb[0];
  1195.     if ( (status&1) == 1 ) {
  1196.       rat.rtype = 1;        /* fixed length records */
  1197.       rat.rsize = 512;      /* 512 byte block recrods */
  1198.       rat.ratattrib = 0;        /* Record attributes: none */
  1199.  
  1200.      status = sys$qiow
  1201.     ( 0, channel, IO$_MODIFY, &iosb, 0, 0, &fib_desc, 0, 0, 0, &atr, 0 );
  1202.        if ( (status&1) == 1 ) status = iosb[0];
  1203.    }
  1204.    sys$dassgn ( channel );
  1205.    if ( (status & 1) == 0 ) fprintf ( stderr,
  1206.     "Failed to convert output file to binary format, status: %d\n", status);
  1207.    return status;
  1208. }
  1209.  
  1210.  
  1211. static add_item(head, tail, value, count)
  1212. struct list_item **head;
  1213. struct list_item **tail;
  1214. char *value;
  1215. int *count;
  1216. {
  1217.     if (*head == 0)
  1218.     {
  1219.     if (NULL == (*head = calloc(1, sizeof(**head))))
  1220.         {
  1221.         errno = ENOMEM;
  1222.         perror("");
  1223.         exit(EXIT_ERR);
  1224.         }
  1225.     *tail = *head;
  1226.     }
  1227.     else
  1228.     if (NULL == ((*tail)->next = calloc(1, sizeof(**head))))
  1229.         {
  1230.         errno = ENOMEM;
  1231.         perror("");
  1232.         exit(EXIT_ERR);
  1233.         }
  1234.     else
  1235.         *tail = (*tail)->next;
  1236.     (*tail)->value = value;
  1237.     ++(*count);
  1238. }
  1239.  
  1240. static expand_wild_cards(item, head, tail, count)
  1241. char *item;
  1242. struct ltem_list **head;
  1243. struct ltem_list **tail;
  1244. int *count;
  1245. {
  1246. int expcount = 0;
  1247. int context = 0;
  1248. int status;
  1249. int status_value;
  1250. int had_version;
  1251. $DESCRIPTOR(filespec, item);
  1252. $DESCRIPTOR(defaultspec, "SYS$DISK:[]*.*;");
  1253. $DESCRIPTOR(resultspec, "");
  1254.  
  1255.     if (strcspn(item, "*%") == strlen(item))
  1256.     {
  1257.     add_item(head, tail, item, count);
  1258.     return;
  1259.     }
  1260.     resultspec.dsc$b_dtype = DSC$K_DTYPE_T;
  1261.     resultspec.dsc$b_class = DSC$K_CLASS_D;
  1262.     resultspec.dsc$a_pointer = NULL;
  1263.     filespec.dsc$w_length = strlen(item);
  1264.     /*
  1265.      * Only return version specs, if the caller specified a version
  1266.      */
  1267.     had_version = strchr(item, ';');
  1268.     while (1 == (1&lib$find_file(&filespec, &resultspec, &context,
  1269.                      &defaultspec, 0, &status_value, &0)))
  1270.     {
  1271.     char *string;
  1272.     char *c;
  1273.  
  1274.     if (NULL == (string = calloc(1, resultspec.dsc$w_length+1)))
  1275.         {
  1276.         errno = ENOMEM;
  1277.         perror("");
  1278.         exit(EXIT_ERR);
  1279.         }
  1280.     strncpy(string, resultspec.dsc$a_pointer, resultspec.dsc$w_length);
  1281.     string[resultspec.dsc$w_length] = '\0';
  1282.     if (NULL == had_version)
  1283.         *((char *)strrchr(string, ';')) = '\0';
  1284.     /*
  1285.      * Be consistent with what the C RTL has already done to the rest of
  1286.      * the argv items and lowercase all of these names.
  1287.      */
  1288.     for (c = string; *c; ++c)
  1289.         if (isupper(*c))
  1290.         *c = tolower(*c);
  1291.     add_item(head, tail, string, count);
  1292.     ++expcount;
  1293.     }
  1294.     if (expcount == 0)
  1295.     add_item(head, tail, item, count);
  1296.     lib$sfree1_dd(&resultspec);
  1297.     lib$find_file_end(&context);
  1298. }
  1299.  
  1300. static int child_st[2];    /* Event Flag set when child process completes    */
  1301.  
  1302. static short child_chan;/* I/O Channel for Pipe Mailbox            */
  1303.  
  1304. static exit_handler(status)
  1305. int *status;
  1306. {
  1307. short iosb[4];
  1308.  
  1309.     if (0 == child_st[0])
  1310.     {
  1311. #ifdef DEBUG
  1312.     fprintf(stderr, "Waiting for Child Process to Finnish . . .\n");
  1313. #endif
  1314.     fflush(stdout);        /* Have to flush pipe for binary data to    */
  1315.                 /* terminate properly -- <tp@mccall.com>    */
  1316. #ifdef DEBUG
  1317.     fprintf(stderr, "    stdout flushed. . .\n");
  1318. #endif
  1319.     sys$qio(0, child_chan, IO$_WRITEOF, iosb, 0, 0, 0, 0, 0, 0, 0, 0);
  1320. #ifdef DEBUG
  1321.     fprintf(stderr, "    Pipe terminated. . .\n");
  1322. #endif
  1323.     fclose(stdout);
  1324. #ifdef DEBUG
  1325.     fprintf(stderr, "    stdout closed. . .\n");
  1326. #endif
  1327.     sys$synch(0, child_st);
  1328.     sys$dassgn(child_chan);
  1329.     }
  1330. #ifdef DEBUG
  1331.     fprintf(stderr, "    sync done. . .\n");
  1332. #endif
  1333. }
  1334.  
  1335. #include <syidef>        /* System Information Definitions    */
  1336.  
  1337. static sig_child(chan)
  1338. int chan;
  1339. {
  1340. #ifdef DEBUG
  1341.     fprintf(stderr, "Child Completion AST, st: %x\n", child_st[0] );
  1342. #endif
  1343.     if (child_st[0] == 0)
  1344.     { child_st[0] = 1; }
  1345.     sys$setef ( 0 );
  1346. }
  1347.  
  1348. static struct exit_control_block
  1349.     {
  1350.     struct exit_control_block *flink;
  1351.     int    (*exit_routine)();
  1352.     int arg_count;
  1353.     int *status_address;
  1354.     int exit_status;
  1355.     } exit_block =
  1356.     {
  1357.     0,
  1358.     exit_handler,
  1359.     1,
  1360.     &exit_block.exit_status,
  1361.     0
  1362.     };
  1363.  
  1364. static char *pipe_and_fork(cmd)
  1365. char *cmd;
  1366. {
  1367.     $DESCRIPTOR(cmddsc, cmd);
  1368.     static char mbxname[64], ef = 0;
  1369.     $DESCRIPTOR(mbxdsc, mbxname);
  1370.     short iosb[4];
  1371.     int status;
  1372.     int pid;
  1373.     struct
  1374.     {
  1375.     short dna_buflen;
  1376.     short dna_itmcod;
  1377.     char *dna_buffer;
  1378.     short *dna_retlen;
  1379.     int listend;
  1380.     } itmlst =
  1381.     {
  1382.     sizeof(mbxname),
  1383.     DVI$_DEVNAM,
  1384.     mbxname,
  1385.     &mbxdsc.dsc$w_length,
  1386.     0
  1387.     };
  1388.     int mbxsize;
  1389.     struct
  1390.     {
  1391.     short mbf_buflen;
  1392.     short mbf_itmcod;
  1393.     int *mbf_maxbuf;
  1394.     short *mbf_retlen;
  1395.     int listend;
  1396.     } syiitmlst =
  1397.     {
  1398.     sizeof(mbxsize),
  1399.     SYI$_MAXBUF,
  1400.     &mbxsize,
  1401.     0,
  1402.     0
  1403.     };
  1404.  
  1405.     cmddsc.dsc$w_length = strlen(cmd);
  1406.     /*
  1407.      * Get the SYSGEN parameter MAXBUF, and the smaller of it and 2048 as
  1408.      * the size of the 'pipe' mailbox.
  1409.      */
  1410.     if (1 == (1&(vaxc$errno = sys$getsyiw(0, 0, 0, &syiitmlst, iosb, 0, 0, 0))))
  1411.     vaxc$errno = iosb[0];
  1412.     if (0 == (1&vaxc$errno))
  1413.     {
  1414.      errno = EVMSERR;
  1415.     perror("Can't get SYSGEN parameter value for MAXBUF");
  1416.     exit(EXIT_ERR);
  1417.     }
  1418.     if (mbxsize > 2048)
  1419.     mbxsize = 2048;
  1420.     if (0 == (1&(vaxc$errno = sys$crembx(0, &child_chan, mbxsize, mbxsize, 0, 0, 0))))
  1421.     {
  1422.     errno = EVMSERR;
  1423.     perror("Can't create pipe mailbox");
  1424.     exit(EXIT_ERR);
  1425.     }
  1426.     if (1 == (1&(vaxc$errno = sys$getdviw(0, child_chan, 0, &itmlst, iosb,
  1427.                           0, 0, 0))))
  1428.     vaxc$errno = iosb[0];
  1429.     if (0 == (1&vaxc$errno))
  1430.     {
  1431.      errno = EVMSERR;
  1432.     perror("Can't get pipe mailbox device name");
  1433.     exit(EXIT_ERR);
  1434.     }
  1435.     mbxname[mbxdsc.dsc$w_length] = '\0';
  1436. #ifdef DEBUG
  1437.     fprintf(stderr, "Pipe Mailbox Name = '%s'\n", mbxname);
  1438. #endif
  1439.     if (0 == (1&(vaxc$errno = lib$spawn(&cmddsc, &mbxdsc, 0, &1,
  1440.                         0, &pid, child_st, &ef, sig_child,
  1441.                         &child_chan))))
  1442.     {
  1443.     errno = EVMSERR;
  1444.     perror("Can't spawn subprocess");
  1445.     exit(EXIT_ERR);
  1446.     }
  1447. #ifdef DEBUG
  1448.     fprintf(stderr, "Subprocess's Pid = %08X\n", pid);
  1449. #endif
  1450.     sys$dclexh(&exit_block);
  1451.     return(mbxname);
  1452. }
  1453.  
  1454. background_process(argc, argv)
  1455. int argc;
  1456. char **argv;
  1457. {
  1458. char command[2048] = "$";
  1459. $DESCRIPTOR(value, command);
  1460. $DESCRIPTOR(cmd, "BACKGROUND$COMMAND");
  1461. $DESCRIPTOR(null, "NLA0:");
  1462. int pid;
  1463.  
  1464.     strcat(command, argv[0]);
  1465.     while (--argc)
  1466.     {
  1467.     strcat(command, " \"");
  1468.     strcat(command, *(++argv));
  1469.     strcat(command, "\"");
  1470.     }
  1471.     value.dsc$w_length = strlen(command);
  1472.     if (0 == (1&(vaxc$errno = lib$set_symbol(&cmd, &value))))
  1473.     {
  1474.     errno = EVMSERR;
  1475.     perror("Can't create symbol for subprocess command");
  1476.     exit(EXIT_ERR);
  1477.     }
  1478.     if (0 == (1&(vaxc$errno = lib$spawn(&cmd, &null, 0, &17, 0, &pid))))
  1479.     {
  1480.     errno = EVMSERR;
  1481.     perror("Can't spawn subprocess");
  1482.     exit(EXIT_ERR);
  1483.     }
  1484. #ifdef DEBUG
  1485.     fprintf(stderr, "%s\n", command);
  1486. #endif
  1487.     fprintf(stderr, "%08X\n", pid);
  1488.     return(EXIT_OK);
  1489. }
  1490.  
  1491. /* got this off net.sources */
  1492.  
  1493. #ifdef    VMS
  1494. #define    index    strchr
  1495. #endif    /*VMS*/
  1496.  
  1497. /*
  1498.  * get option letter from argument vector
  1499.  */
  1500. int    opterr = 1,        /* useless, never set or used */
  1501.     optind = 1,        /* index into parent argv vector */
  1502.     optopt;            /* character checked for validity */
  1503. char    *optarg;        /* argument associated with option */
  1504.  
  1505. #define BADCH    (int)'?'
  1506. #define EMSG    ""
  1507. #define tell(s)    fputs(progname,stderr);fputs(s,stderr); \
  1508.         fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
  1509.  
  1510. getopt(nargc,nargv,ostr)
  1511. int    nargc;
  1512. char    **nargv,
  1513.     *ostr;
  1514. {
  1515.     static char    *place = EMSG;    /* option letter processing */
  1516.     register char    *oli;        /* option letter list index */
  1517.     char    *index();
  1518.     char *progname;
  1519.  
  1520.     if(!*place) {            /* update scanning pointer */
  1521.         if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
  1522.         if (*place == '-') {    /* found "--" */
  1523.             ++optind;
  1524.             return(EOF);
  1525.         }
  1526.     }                /* option letter okay? */
  1527.     if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
  1528.         if(!*place) ++optind;
  1529. #ifdef VMS
  1530.         progname = strrchr(nargv[0],']');
  1531. #else
  1532.         progname = rindex(nargv[0],'/');
  1533. #endif
  1534.         if (!progname) progname = nargv[0]; else progname++;
  1535.         tell(": illegal option -- ");
  1536.     }
  1537.     if (*++oli != ':') {        /* don't need argument */
  1538.         optarg = NULL;
  1539.         if (!*place) ++optind;
  1540.     }
  1541.     else {                /* need an argument */
  1542.         if (*place) optarg = place;    /* no white space */
  1543.         else if (nargc <= ++optind) {    /* no arg */
  1544.             place = EMSG;
  1545. #ifdef VMS
  1546.             progname = strrchr(nargv[0],']');
  1547. #else
  1548.             progname = rindex(nargv[0],'/');
  1549. #endif
  1550.             if (!progname) progname = nargv[0]; else progname++;
  1551.             tell(": option requires an argument -- ");
  1552.         }
  1553.          else optarg = nargv[optind];    /* white space */
  1554.         place = EMSG;
  1555.         ++optind;
  1556.     }
  1557.     return(optopt);            /* dump back option letter */
  1558. }
  1559. #endif /* VMS */
  1560.