home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-11-20 | 35.6 KB | 1,550 lines |
- /* libpbm1.c - pbm utility library part 1
- **
- ** Copyright (C) 1988 by Jef Poskanzer.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
- #include "pbm.h"
- #include "version.h"
- #include "compile.h"
- #include "libpbm.h"
- #if __STDC__
- #include <stdarg.h>
- #else /*__STDC__*/
- #include <varargs.h>
- #endif /*__STDC__*/
-
-
- /* Variable-sized arrays. */
-
- char*
- pm_allocrow( cols, size )
- int cols;
- int size;
- {
- register char* itrow;
-
- itrow = (char*) malloc( cols * size );
- if ( itrow == (char*) 0 )
- pm_error( "out of memory allocating a row" );
- return itrow;
- }
-
- void
- pm_freerow( itrow )
- char* itrow;
- {
- free( itrow );
- }
-
-
- #ifndef A_FRAGARRAY
- char**
- pm_allocarray( cols, rows, size )
- int cols, rows;
- int size;
- {
- char** its;
- int i;
-
- its = (char**) malloc( rows * sizeof(char*) );
- if ( its == (char**) 0 )
- pm_error( "out of memory allocating an array" );
- its[0] = (char*) malloc( rows * cols * size );
- if ( its[0] == (char*) 0 )
- pm_error( "out of memory allocating an array" );
- for ( i = 1; i < rows; ++i )
- its[i] = &(its[0][i * cols * size]);
- return its;
- }
-
- void
- pm_freearray( its, rows )
- char** its;
- int rows;
- {
- free( its[0] );
- free( its );
- }
- #else /* A_FRAGARRAY */
- char**
- pm_allocarray( cols, rows, size )
- int cols, rows;
- int size;
- {
- char** its;
- int i;
- its = (char**) malloc( (rows + 1) * sizeof(char*) );
- if ( its == (char**) 0 )
- pm_error( "out of memory allocating an array" );
- its[rows] = its[0] = (char*) malloc( rows * cols * size );
- if ( its[0] != (char*) 0 )
- for ( i = 1; i < rows; ++i )
- its[i] = &(its[0][i * cols * size]);
- else
- for( i = 0; i < rows; ++i )
- its[i] = pm_allocrow( cols, size );
- return its;
- }
- void
- pm_freearray( its, rows )
- char** its;
- int rows;
- {
- int i;
- if( its[rows] != (char*) 0 )
- free( its[rows] );
- else
- for( i = 0; i < rows; ++i )
- pm_freerow( its[i] );
- free( its );
- }
- #endif /* A_FRAGARRAY */
-
-
- /* Case-insensitive keyword matcher. */
-
- int
- pm_keymatch( str, keyword, minchars )
- char* str;
- char* keyword;
- int minchars;
- {
- register int len;
-
- len = strlen( str );
- if ( len < minchars )
- return 0;
- while ( --len >= 0 )
- {
- register char c1, c2;
-
- c1 = *str++;
- c2 = *keyword++;
- if ( c2 == '\0' )
- return 0;
- if ( isupper( c1 ) )
- c1 = tolower( c1 );
- if ( isupper( c2 ) )
- c1 = tolower( c2 );
- if ( c1 != c2 )
- return 0;
- }
- return 1;
- }
-
-
- /* Log base two hacks. */
-
- int
- pm_maxvaltobits( maxval )
- int maxval;
- {
- if ( maxval <= 1 )
- return 1;
- else if ( maxval <= 3 )
- return 2;
- else if ( maxval <= 7 )
- return 3;
- else if ( maxval <= 15 )
- return 4;
- else if ( maxval <= 31 )
- return 5;
- else if ( maxval <= 63 )
- return 6;
- else if ( maxval <= 127 )
- return 7;
- else if ( maxval <= 255 )
- return 8;
- else if ( maxval <= 511 )
- return 9;
- else if ( maxval <= 1023 )
- return 10;
- else if ( maxval <= 2047 )
- return 11;
- else if ( maxval <= 4095 )
- return 12;
- else if ( maxval <= 8191 )
- return 13;
- else if ( maxval <= 16383 )
- return 14;
- else if ( maxval <= 32767 )
- return 15;
- else if ( (long) maxval <= 65535L )
- return 16;
- else
- pm_error( "maxval of %d is too large!", maxval );
- }
-
- int
- pm_bitstomaxval( bits )
- int bits;
- {
- return ( 1 << bits ) - 1;
- }
-
-
- /* Initialization. */
-
- static char* progname;
- static int showmessages;
-
- void
- pm_init( argcP, argv )
- int* argcP;
- char* argv[];
- {
- int argn, i;
- #ifdef A_RGBENV
- char *rgbdef;
- #endif /* A_RGBENV */
-
- #ifndef VMS
- /* Extract program name. */
- progname = rindex( argv[0], '/');
- #else
- { char **temp_argv = argv;
- int old_argc = *argcP;
- int i;
- getredirection( argcP, &temp_argv );
- if (*argcP > old_argc) {
- /* Number of command line arguments has increased */
- fprintf( stderr, "Sorry!! getredirection() for VMS has changed the argument list!!!\n");
- fprintf( stderr, "This is intolerable at the present time, so we must stop!!!\n");
- exit(1);
- }
- for (i=0; i<*argcP; i++)
- argv[i] = temp_argv[i];
- }
- if ( progname == NULL ) progname = rindex( argv[0], ']');
- if ( progname == NULL ) progname = rindex( argv[0], '>');
- #endif
- if ( progname == NULL )
- progname = argv[0];
- else
- ++progname;
-
- /* Check for any global args. */
- showmessages = 1;
- for ( argn = 1; argn < *argcP; ++argn )
- {
- if ( pm_keymatch( argv[argn], "-quiet", 6 ) )
- {
- showmessages = 0;
- }
- else if ( pm_keymatch( argv[argn], "-version", 7 ) )
- {
- pm_message( "Version: %s", PBMPLUS_VERSION );
- pm_message( "Compiled %s by user \"%s\"",
- COMPILE_TIME, COMPILED_BY );
- #ifdef BSD
- pm_message( "BSD defined" );
- #endif /*BSD*/
- #ifdef SYSV
- #ifdef VMS
- pm_message( "VMS & SYSV defined" );
- #else
- pm_message( "SYSV defined" );
- #endif
- #endif /*SYSV*/
- #ifdef MSDOS
- pm_message( "MSDOS defined" );
- #endif /*MSDOS*/
- #ifdef AMIGA
- pm_message( "AMIGA defined" );
- #endif /* AMIGA */
- #ifdef PBMPLUS_RAWBITS
- pm_message( "PBMPLUS_RAWBITS defined" );
- #endif /*PBMPLUS_RAWBITS*/
- #ifdef PBMPLUS_BROKENPUTC1
- pm_message( "PBMPLUS_BROKENPUTC1 defined" );
- #endif /*PBMPLUS_BROKENPUTC1*/
- #ifdef PBMPLUS_BROKENPUTC2
- pm_message( "PBMPLUS_BROKENPUTC2 defined" );
- #endif /*PBMPLUS_BROKENPUTC2*/
- #ifdef PGM_BIGGRAYS
- pm_message( "PGM_BIGGRAYS defined" );
- #endif /*PGM_BIGGRAYS*/
- #ifdef PPM_PACKCOLORS
- pm_message( "PPM_PACKCOLORS defined" );
- #endif /*PPM_PACKCOLORS*/
- #ifdef DEBUG
- pm_message( "DEBUG defined" );
- #endif /*DEBUG*/
- #ifdef NEED_VFPRINTF1
- pm_message( "NEED_VFPRINTF1 defined" );
- #endif /*NEED_VFPRINTF1*/
- #ifdef NEED_VFPRINTF2
- pm_message( "NEED_VFPRINTF2 defined" );
- #endif /*NEED_VFPRINTF2*/
- #ifdef RGB_DB
- #ifndef A_RGBENV
- pm_message( "RGB_DB=\"%s\"", RGB_DB );
- #else /* A_RGBENV */
- if( rgbdef = getenv(RGB_DB) )
- pm_message( "RGB_DB= Env-var %s (set to \"%s\")", RGB_DB, rgbdef );
- else
- pm_message( "RGB_DB= Env-var %s (unset)", RGB_DB );
- #endif /* A_RGBENV */
- #endif /*RGB_DB*/
- #ifdef LIBTIFF
- pm_message( "LIBTIFF defined" );
- #endif /*LIBTIFF*/
- exit( 0 );
- }
- else
- continue;
- for ( i = argn + 1; i <= *argcP; ++i )
- argv[i - 1] = argv[i];
- --(*argcP);
- }
- }
-
- void
- pbm_init( argcP, argv )
- int* argcP;
- char* argv[];
- {
- pm_init( argcP, argv );
- }
-
-
- /* Error handling. */
-
- void
- pm_usage( usage )
- char* usage;
- {
- fprintf( stderr, "usage: %s %s\n", progname, usage );
- exit( 1 );
- }
-
- void
- pm_perror( reason )
- char* reason;
- {
- #ifndef A_STRERROR
- extern char* sys_errlist[];
- #endif /* A_STRERROR */
- extern int errno;
- char* e;
-
- #ifdef A_STRERROR
- e = strerror(errno);
- #else /* A_STRERROR */
- e = sys_errlist[errno];
- #endif /* A_STRERROR */
-
- if ( reason != 0 && reason[0] != '\0' )
- pm_error( "%s - %s", reason, e );
- else
- pm_error( "%s", e );
- }
-
- #if __STDC__
- void
- pm_message( char* format, ... )
- {
- va_list args;
-
- va_start( args, format );
- #else /*__STDC__*/
- /*VARARGS1*/
- void
- pm_message( va_alist )
- va_dcl
- { /*}*/
- va_list args;
- char* format;
-
- va_start( args );
- format = va_arg( args, char* );
- #endif /*__STDC__*/
-
- if ( showmessages )
- {
- fprintf( stderr, "%s: ", progname );
- (void) vfprintf( stderr, format, args );
- fputc( '\n', stderr );
- }
- va_end( args );
- }
-
- #if __STDC__
- void
- pm_error( char* format, ... )
- {
- va_list args;
-
- va_start( args, format );
- #else /*__STDC__*/
- /*VARARGS1*/
- void
- pm_error( va_alist )
- va_dcl
- { /*}*/
- va_list args;
- char* format;
-
- va_start( args );
- format = va_arg( args, char* );
- #endif /*__STDC__*/
-
- fprintf( stderr, "%s: ", progname );
- (void) vfprintf( stderr, format, args );
- fputc( '\n', stderr );
- va_end( args );
- exit( 1 );
- }
-
- #ifdef NEED_VFPRINTF1
-
- /* Micro-vfprintf, for systems that don't have vfprintf but do have _doprnt.
- */
-
- int
- vfprintf( stream, format, args )
- FILE* stream;
- char* format;
- va_list args;
- {
- return _doprnt( format, args, stream );
- }
- #endif /*NEED_VFPRINTF1*/
-
- #ifdef NEED_VFPRINTF2
-
- /* Portable mini-vfprintf, for systems that don't have either vfprintf or
- ** _doprnt. This depends only on fprintf. If you don't have fprintf,
- ** you might consider getting a new stdio library.
- */
-
- int
- vfprintf( stream, format, args )
- FILE* stream;
- char* format;
- va_list args;
- {
- int n;
- char* ep;
- char fchar;
- char tformat[512];
- int do_long;
- int i;
- long l;
- unsigned u;
- unsigned long ul;
- char* s;
- double d;
-
- n = 0;
- while ( *format != '\0' )
- {
- if ( *format != '%' )
- { /* Not special, just write out the char. */
- (void) putc( *format, stream );
- ++n;
- ++format;
- }
- else
- {
- do_long = 0;
- ep = format + 1;
-
- /* Skip over all the field width and precision junk. */
- if ( *ep == '-' )
- ++ep;
- if ( *ep == '0' )
- ++ep;
- while ( isdigit( *ep ) )
- ++ep;
- if ( *ep == '.' )
- {
- ++ep;
- while ( isdigit( *ep ) )
- ++ep;
- }
- if ( *ep == '#' )
- ++ep;
- if ( *ep == 'l' )
- {
- do_long = 1;
- ++ep;
- }
-
- /* Here's the field type. Extract it, and copy this format
- ** specifier to a temp string so we can add an end-of-string.
- */
- fchar = *ep;
- (void) strncpy( tformat, format, ep - format + 1 );
- tformat[ep - format + 1] = '\0';
-
- /* Now do a one-argument fprintf with the format string we have
- ** isolated.
- */
- switch ( fchar )
- {
- case 'd':
- if ( do_long )
- {
- l = va_arg( args, long );
- n += fprintf( stream, tformat, l );
- }
- else
- {
- i = va_arg( args, int );
- n += fprintf( stream, tformat, i );
- }
- break;
-
- case 'o':
- case 'x':
- case 'X':
- case 'u':
- if ( do_long )
- {
- ul = va_arg( args, unsigned long );
- n += fprintf( stream, tformat, ul );
- }
- else
- {
- u = va_arg( args, unsigned );
- n += fprintf( stream, tformat, u );
- }
- break;
-
- case 'c':
- i = (char) va_arg( args, int );
- n += fprintf( stream, tformat, i );
- break;
-
- case 's':
- s = va_arg( args, char* );
- n += fprintf( stream, tformat, s );
- break;
-
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- d = va_arg( args, double );
- n += fprintf( stream, tformat, d );
- break;
-
- case '%':
- (void) putc( '%', stream );
- ++n;
- break;
-
- default:
- return -1;
- }
-
- /* Resume formatting on the next character. */
- format = ep + 1;
- }
- }
- return nc;
- }
- #endif /*NEED_VFPRINTF2*/
-
- #ifdef NEED_STRSTR
- /* for systems which do not provide strstr */
- char*
- strstr(s1, s2)
- char *s1, *s2;
- {
- int ls2 = strlen(s2);
-
- if (ls2 == 0)
- return (s1);
- while (strlen(s1) >= ls2) {
- if (strncmp(s1, s2, ls2) == 0)
- return (s1);
- s1++;
- }
- return (0);
- }
-
- #endif /*NEED_STRSTR*/
-
-
- /* File open/close that handles "-" as stdin and checks errors. */
-
- FILE*
- pm_openr( name )
- char* name;
- {
- FILE* f;
-
- if ( strcmp( name, "-" ) == 0 )
- f = stdin;
- else
- {
- #ifdef MSDOS
- f = fopen( name, "rb" );
- #else /*MSDOS*/
- #ifndef VMS
- f = fopen( name, "r" );
- #else
- f = fopen ( name, "r", "ctx=stm" );
- #endif
- #endif /*MSDOS*/
- if ( f == NULL )
- {
- pm_perror( name );
- exit( 1 );
- }
- }
- return f;
- }
-
- FILE*
- pm_openw( name )
- char* name;
- {
- FILE* f;
-
- #ifdef MSDOS
- f = fopen( name, "wb" );
- #else /*MSDOS*/
- #ifndef VMS
- f = fopen( name, "w" );
- #else
- f = fopen ( name, "w", "mbc=32", "mbf=2" ); /* set buffer factors */
- #endif
- #endif /*MSDOS*/
- if ( f == NULL )
- {
- pm_perror( name );
- exit( 1 );
- }
- return f;
- }
-
- void
- pm_close( f )
- FILE* f;
- {
- fflush( f );
- if ( ferror( f ) )
- pm_message( "a file read or write error occurred at some point" );
- if ( f != stdin )
- if ( fclose( f ) != 0 )
- pm_perror( "fclose" );
- }
-
- /* Endian I/O.
- */
-
- int
- pm_readbigshort( in, sP )
- FILE* in;
- short* sP;
- {
- int c;
-
- if ( (c = getc( in )) == EOF )
- return -1;
- *sP = ( c & 0xff ) << 8;
- if ( (c = getc( in )) == EOF )
- return -1;
- *sP |= c & 0xff;
- return 0;
- }
-
- #if __STDC__
- int
- pm_writebigshort( FILE* out, short s )
- #else /*__STDC__*/
- int
- pm_writebigshort( out, s )
- FILE* out;
- short s;
- #endif /*__STDC__*/
- {
- (void) putc( ( s >> 8 ) & 0xff, out );
- (void) putc( s & 0xff, out );
- return 0;
- }
-
- int
- pm_readbiglong( in, lP )
- FILE* in;
- long* lP;
- {
- int c;
-
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP = ( c & 0xff ) << 24;
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP |= ( c & 0xff ) << 16;
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP |= ( c & 0xff ) << 8;
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP |= c & 0xff;
- return 0;
- }
-
- int
- pm_writebiglong( out, l )
- FILE* out;
- long l;
- {
- (void) putc( ( l >> 24 ) & 0xff, out );
- (void) putc( ( l >> 16 ) & 0xff, out );
- (void) putc( ( l >> 8 ) & 0xff, out );
- (void) putc( l & 0xff, out );
- return 0;
- }
-
- int
- pm_readlittleshort( in, sP )
- FILE* in;
- short* sP;
- {
- int c;
-
- if ( (c = getc( in )) == EOF )
- return -1;
- *sP = c & 0xff;
- if ( (c = getc( in )) == EOF )
- return -1;
- *sP |= ( c & 0xff ) << 8;
- return 0;
- }
-
- #if __STDC__
- int
- pm_writelittleshort( FILE* out, short s )
- #else /*__STDC__*/
- int
- pm_writelittleshort( out, s )
- FILE* out;
- short s;
- #endif /*__STDC__*/
- {
- (void) putc( s & 0xff, out );
- (void) putc( ( s >> 8 ) & 0xff, out );
- return 0;
- }
-
- int
- pm_readlittlelong( in, lP )
- FILE* in;
- long* lP;
- {
- int c;
-
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP = c & 0xff;
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP |= ( c & 0xff ) << 8;
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP |= ( c & 0xff ) << 16;
- if ( (c = getc( in )) == EOF )
- return -1;
- *lP |= ( c & 0xff ) << 24;
- return 0;
- }
-
- int
- pm_writelittlelong( out, l )
- FILE* out;
- long l;
- {
- (void) putc( l & 0xff, out );
- (void) putc( ( l >> 8 ) & 0xff, out );
- (void) putc( ( l >> 16 ) & 0xff, out );
- (void) putc( ( l >> 24 ) & 0xff, out );
- return 0;
- }
-
-
- /* Read a file of unknown size to a buffer. Return the number of bytes
- read. Allocate more memory as we need it. The calling routine has
- to free() the buffer.
-
- Oliver Trepte, oliver@fysik4.kth.se, 930613 */
-
- #define PM_BUF_SIZE 16384 /* First try this size of the buffer, then
- double this until we reach PM_MAX_BUF_INC */
- #define PM_MAX_BUF_INC 65536 /* Don't allocate more memory in larger blocks
- than this. */
-
- char *pm_read_unknown_size( file, nread )
- FILE* file;
- long* nread;
- {
- long nalloc;
- register int val;
- char* buf;
-
- *nread = 0;
- if ((buf=malloc(PM_BUF_SIZE)) == NULL)
- pm_error("Cannot allocate memory");
- nalloc = PM_BUF_SIZE;
-
- while(1) {
- if (*nread >= nalloc) { /* We need a larger buffer */
- if (nalloc > PM_MAX_BUF_INC)
- nalloc += PM_MAX_BUF_INC;
- else
- nalloc += nalloc;
- if ((buf=realloc(buf, nalloc)) == NULL)
- pm_error("Cannot allocate %d bytes of memory", nalloc);
- }
-
- if ((val = getc(file)) == EOF)
- return (buf);
-
- buf[(*nread)++] = val;
- }
- }
-
- /*****************************************************************************/
-
- #ifdef VMS
- /*
- * @(#)argproc.c 1.0 89/02/01 Mark Pizzolato (mark@infopiz.uucp)
- */
-
- #ifndef lint
- char argproc_version[] = "@(#)argproc.c VMS uucp Version infopiz-1.0";
- #endif
-
- #include "includes.h" /* System include files, system dependent */
-
-
- /*
- * getredirection() is intended to aid in porting C programs
- * to VMS (Vax-11 C) which does not support '>' and '<'
- * I/O redirection, along with a command line pipe mechanism
- * using the '|' AND background command execution '&'.
- * The piping mechanism will probably work with almost any 'filter' type
- * of program. With suitable modification, it may useful for other
- * portability problems as well.
- *
- * Author: Mark Pizzolato mark@infopiz.UUCP
- */
- struct list_item
- {
- struct list_item *next;
- char *value;
- };
-
- int
- getredirection(ac, av)
- int *ac;
- char ***av;
- /*
- * Process vms redirection arg's. Exit if any error is seen.
- * If getredirection() processes an argument, it is erased
- * from the vector. getredirection() returns a new argc and argv value.
- * In the event that a background command is requested (by a trailing "&"),
- * this routine creates a background subprocess, and simply exits the program.
- *
- * Warning: do not try to simplify the code for vms. The code
- * presupposes that getredirection() is called before any data is
- * read from stdin or written to stdout.
- *
- * Normal usage is as follows:
- *
- * main(argc, argv)
- * int argc;
- * char *argv[];
- * {
- * getredirection(&argc, &argv);
- * }
- */
- {
- int argc = *ac; /* Argument Count */
- char **argv = *av; /* Argument Vector */
- char *ap; /* Argument pointer */
- int j; /* argv[] index */
- extern int errno; /* Last vms i/o error */
- int item_count = 0; /* Count of Items in List */
- int new_file; /* flag, true if '>' used */
- struct list_item *list_head = 0; /* First Item in List */
- struct list_item *list_tail; /* Last Item in List */
- char *in = NULL; /* Input File Name */
- char *out = NULL; /* Output File Name */
- char *outmode = "w"; /* Mode to Open Output File */
- int cmargc = 0; /* Piped Command Arg Count */
- char **cmargv = NULL;/* Piped Command Arg Vector */
- stat_t statbuf; /* fstat buffer */
-
- /*
- * First handle the case where the last thing on the line ends with
- * a '&'. This indicates the desire for the command to be run in a
- * subprocess, so we satisfy that desire.
- */
- ap = argv[argc-1];
- if (0 == strcmp("&", ap))
- exit(background_process(--argc, argv));
- if ('&' == ap[strlen(ap)-1])
- {
- ap[strlen(ap)-1] = '\0';
- exit(background_process(argc, argv));
- }
- /*
- * Now we handle the general redirection cases that involve '>', '>>',
- * '<', and pipes '|'.
- */
- for (new_file = 0, j = 0; j < argc; ++j)
- {
- if (0 == strcmp("<", argv[j]))
- {
- if (j+1 >= argc)
- {
- errno = EINVAL;
- perror("No input file");
- exit(EXIT_ERR);
- }
- in = argv[++j];
- continue;
- }
- if ('<' == *(ap = argv[j]))
- {
- in = 1 + ap;
- continue;
- }
- if (0 == strcmp(">", ap))
- {
- if (j+1 >= argc)
- {
- errno = EINVAL;
- perror("No output file");
- exit(EXIT_ERR);
- }
- out = argv[++j];
- new_file = 1;
- continue;
- }
- if ('>' == *ap)
- {
- if ('>' == ap[1])
- {
- outmode = "a";
- if ('\0' == ap[2])
- out = argv[++j];
- else
- out = 2 + ap;
- }
- else
- { out = 1 + ap; new_file = 1; }
- continue;
- }
- if (0 == strcmp("|", argv[j]))
- {
- if (j+1 >= argc)
- {
- errno = EPIPE;
- perror("No command to Pipe to");
- exit(EXIT_ERR);
- }
- cmargc = argc-(j+1);
- cmargv = &argv[j+1];
- argc = j;
- outmode = "wb"; /* pipes are binary mode devices */
- continue;
- }
- if ('|' == *(ap = argv[j]))
- {
- ++argv[j];
- cmargc = argc-j;
- cmargv = &argv[j];
- argc = j;
- outmode = "wb"; /* pipes are binary mode devices */
- continue;
- }
- expand_wild_cards(ap, &list_head, &list_tail, &item_count);
- }
- /*
- * Allocate and fill in the new argument vector, Some Unix's terminate
- * the list with an extra null pointer.
- */
- argv = *av = calloc(item_count+1, sizeof(char *));
- for (j = 0; j < item_count; ++j, list_head = list_head->next)
- argv[j] = list_head->value;
- *ac = item_count;
- if (cmargv != NULL)
- {
- char subcmd[1024];
- static char *pipe_and_fork();
-
- if (out != NULL)
- {
- errno = EINVAL;
- perror("Invalid '|' and '>' specified");
- exit(EXIT_ERR);
- }
- strcpy(subcmd, cmargv[0]);
- for (j = 1; j < cmargc; ++j)
- {
- strcat(subcmd, " \"");
- strcat(subcmd, cmargv[j]);
- strcat(subcmd, "\"");
- }
- out = pipe_and_fork(subcmd);
- outmode = "wb";
- }
-
- /* Check for input from a pipe (mailbox) */
-
- if(fstat(0, &statbuf) == 0){
- if(strncmp(statbuf.st_dev, "MB", 2) == 0 ||
- strncmp(statbuf.st_dev, "_MB", 3) == 0){
-
- /* Input from a pipe, reopen it in binary mode to disable */
- /* carriage control processing. */
-
- if (in != NULL){
- errno = EINVAL;
- perror("Invalid '|' and '<' specified");
- exit(EXIT_ERR);
- }
- freopen(statbuf.st_dev, "rb", stdin);
- }
- }
- else {
- perror("fstat failed");
- exit(EXIT_ERR);
- }
-
- #ifdef __ALPHA
- /*, "mbc=32", "mbf=2"))) blows up on the ALPHA cbm 11/08/92 */
- if ((in != NULL) && (NULL == freopen(in, "r", stdin)))
- {
- #else
- if ((in != NULL) && (NULL == freopen(in, "r", stdin, "mbc=32", "mbf=2")))
- {
- #endif
- perror(in); /* Can't find file */
- exit(EXIT_ERR); /* Is a fatal error */
- }
- #ifdef __ALPHA
- if ((out != NULL) && (NULL == freopen(out, outmode, stdout)))
- {
- #else
- if ((out != NULL) && (NULL == freopen(out, outmode, stdout, "mbc=32", "mbf=2")))
- {
- #endif
- perror(ap); /* Error, can't write or append */
- exit(EXIT_ERR); /* Is a fatal error */
- }
-
- if ( new_file ) {
- /*
- * We are making an explicit output file, fstat the file and
- * declare exit handler to be able change the file to fixed length
- * records if necessary.
- */
- char fname[256];
- static int outfile_rundown(), check_outfile_filetype();
- static stat_t ofile_stat;
- static struct exit_control_block {
- struct exit_control_block *flink;
- int (*exit_routine)();
- int arg_count;
- int *status_address; /* arg 1 */
- stat_t *stat; /* arg 2 */
- int exit_status;
- int skew[128];
- } exit_block =
- { 0, outfile_rundown, 2, &exit_block.exit_status, &ofile_stat, 0 };
-
- if ( fstat ( fileno(stdout), &ofile_stat ) == 0 )
- sys$dclexh ( &exit_block );
- else fprintf(stderr,"Error fstating stdout - %s\n",
- strerror(errno,vaxc$errno) );
-
- if ( fgetname ( stdout, fname, 0 ) ) check_outfile_filetype ( fname );
- }
- #ifdef DEBUG
- fprintf(stderr, "Arglist:\n");
- for (j = 0; j < *ac; ++j)
- fprintf(stderr, "argv[%d] = '%s'\n", j, argv[j]);
- #endif
- }
-
- static int binary_outfile = 0;
- void set_outfile_binary() { binary_outfile = 1; return; }
-
- /*
- * Check if output file should be set to binary (fixed 512) on exit based
- * upon the filetype.
- */
- static int check_outfile_filetype ( name )
- char *name;
- {
- char *binary_filetypes, *ext, *p, *t;
- binary_filetypes = (char *) getenv ( "PBM_BINARY_FILETYPES" );
- if ( binary_filetypes == NULL ) return 0;
-
- ext = strchr ( name, '.' ); if ( ext == NULL ) return 0;
- ext++;
- t = strrchr ( name, '.' ); if ( t != NULL ) *t = '\0';
-
- for ( p = binary_filetypes; *p != '\0'; p++ ) {
- for ( t = p;
- (*p != '\0' ) && (strchr ( ", ", *p ) == NULL);
- p++ ) *p = toupper(*p);
- *p = '\0';
-
- if ( strcmp ( t, ext ) == 0 ) {
- binary_outfile = 1;
- break;
- }
- }
- return binary_outfile;
- }
-
-
- /*
- * Exit handler to set output file to binary on image exit.
- */
- static int outfile_rundown ( reason, statbuf )
- int *reason;
- stat_t *statbuf;
- {
- int code, channel, status, LIB$GETDVI(), sys$assign(), sys$qiow();
- long int fib_desc[2], devchar;
- short int iosb[4];
- $DESCRIPTOR(device, statbuf->st_dev);
- struct fibdef fib; /* File information block (XQP) */
- struct atrdef atr[2];
- struct fat {
- unsigned char rtype, ratattrib;
- unsigned short int rsize, hiblk[2], efblk[2], ffbyte, maxrec, defext, gbc;
- unsigned short int reserved[4], versions;
- } rat;
-
- if ( !binary_outfile ) return 1; /* leave file alone */
- /*
- * Assign channel to device listed in stat block and test if it is
- * a directory structured device, returning if not.
- */
- device.dsc$w_length = strlen ( statbuf->st_dev );
- status = sys$assign ( &device, &channel, 0, 0 );
- if ((status & 1) == 0) { fprintf(stderr,
- "assign error to %s (%d)\n", device.dsc$a_pointer, status);
- return status; }
- code = DVI$_DEVCHAR;
- status = LIB$GETDVI ( &code, &channel, 0, &devchar );
- if ((status & 1) == 0) { fprintf(stderr, "getdvi error: %d\n", status);
- return status; }
- if ( (devchar & DEV$M_DIR) == 0 ) return 1;
- /*
- * Build File Information Block and Atrribute block.
- */
- #ifdef __ALPHA
- fib.fib$w_fid[0] = statbuf->st_ino[0];
- fib.fib$w_fid[1] = statbuf->st_ino[1];
- fib.fib$w_fid[2] = statbuf->st_ino[2];
- #else
- fib.fib$r_fid_overlay.fib$w_fid[0] = statbuf->st_ino[0];
- fib.fib$r_fid_overlay.fib$w_fid[1] = statbuf->st_ino[1];
- fib.fib$r_fid_overlay.fib$w_fid[2] = statbuf->st_ino[2];
- #endif
-
- atr[0].atr$w_size = sizeof(rat);
- atr[0].atr$w_type = ATR$C_RECATTR;
- atr[0].atr$l_addr = &rat;
- atr[1].atr$w_size = 0; atr[1].atr$w_type = 0;
- /*
- * Perform access function with read_attributes sub-function.
- */
- freopen ( "SYS$OUTPUT:", "a", stdout );
- fib_desc[0] = 10; fib_desc[1] = (long int) &fib;
- #ifdef __ALPHA
- fib.fib$l_acctl = FIB$M_WRITE;
- #else
- fib.fib$r_acctl_overlay.fib$l_acctl = FIB$M_WRITE;
- #endif
- status = sys$qiow ( 0, channel, IO$_ACCESS|IO$M_ACCESS,
- &iosb, 0, 0, &fib_desc, 0, 0, 0, &atr, 0 );
- /*
- * If status successful, update record byte and perform a MODIFY.
- */
- if ( (status&1) == 1 ) status = iosb[0];
- if ( (status&1) == 1 ) {
- rat.rtype = 1; /* fixed length records */
- rat.rsize = 512; /* 512 byte block recrods */
- rat.ratattrib = 0; /* Record attributes: none */
-
- status = sys$qiow
- ( 0, channel, IO$_MODIFY, &iosb, 0, 0, &fib_desc, 0, 0, 0, &atr, 0 );
- if ( (status&1) == 1 ) status = iosb[0];
- }
- sys$dassgn ( channel );
- if ( (status & 1) == 0 ) fprintf ( stderr,
- "Failed to convert output file to binary format, status: %d\n", status);
- return status;
- }
-
-
- static add_item(head, tail, value, count)
- struct list_item **head;
- struct list_item **tail;
- char *value;
- int *count;
- {
- if (*head == 0)
- {
- if (NULL == (*head = calloc(1, sizeof(**head))))
- {
- errno = ENOMEM;
- perror("");
- exit(EXIT_ERR);
- }
- *tail = *head;
- }
- else
- if (NULL == ((*tail)->next = calloc(1, sizeof(**head))))
- {
- errno = ENOMEM;
- perror("");
- exit(EXIT_ERR);
- }
- else
- *tail = (*tail)->next;
- (*tail)->value = value;
- ++(*count);
- }
-
- static expand_wild_cards(item, head, tail, count)
- char *item;
- struct ltem_list **head;
- struct ltem_list **tail;
- int *count;
- {
- int expcount = 0;
- int context = 0;
- int status;
- int status_value;
- int had_version;
- $DESCRIPTOR(filespec, item);
- $DESCRIPTOR(defaultspec, "SYS$DISK:[]*.*;");
- $DESCRIPTOR(resultspec, "");
-
- if (strcspn(item, "*%") == strlen(item))
- {
- add_item(head, tail, item, count);
- return;
- }
- resultspec.dsc$b_dtype = DSC$K_DTYPE_T;
- resultspec.dsc$b_class = DSC$K_CLASS_D;
- resultspec.dsc$a_pointer = NULL;
- filespec.dsc$w_length = strlen(item);
- /*
- * Only return version specs, if the caller specified a version
- */
- had_version = strchr(item, ';');
- while (1 == (1&lib$find_file(&filespec, &resultspec, &context,
- &defaultspec, 0, &status_value, &0)))
- {
- char *string;
- char *c;
-
- if (NULL == (string = calloc(1, resultspec.dsc$w_length+1)))
- {
- errno = ENOMEM;
- perror("");
- exit(EXIT_ERR);
- }
- strncpy(string, resultspec.dsc$a_pointer, resultspec.dsc$w_length);
- string[resultspec.dsc$w_length] = '\0';
- if (NULL == had_version)
- *((char *)strrchr(string, ';')) = '\0';
- /*
- * Be consistent with what the C RTL has already done to the rest of
- * the argv items and lowercase all of these names.
- */
- for (c = string; *c; ++c)
- if (isupper(*c))
- *c = tolower(*c);
- add_item(head, tail, string, count);
- ++expcount;
- }
- if (expcount == 0)
- add_item(head, tail, item, count);
- lib$sfree1_dd(&resultspec);
- lib$find_file_end(&context);
- }
-
- static int child_st[2]; /* Event Flag set when child process completes */
-
- static short child_chan;/* I/O Channel for Pipe Mailbox */
-
- static exit_handler(status)
- int *status;
- {
- short iosb[4];
-
- if (0 == child_st[0])
- {
- #ifdef DEBUG
- fprintf(stderr, "Waiting for Child Process to Finnish . . .\n");
- #endif
- fflush(stdout); /* Have to flush pipe for binary data to */
- /* terminate properly -- <tp@mccall.com> */
- #ifdef DEBUG
- fprintf(stderr, " stdout flushed. . .\n");
- #endif
- sys$qio(0, child_chan, IO$_WRITEOF, iosb, 0, 0, 0, 0, 0, 0, 0, 0);
- #ifdef DEBUG
- fprintf(stderr, " Pipe terminated. . .\n");
- #endif
- fclose(stdout);
- #ifdef DEBUG
- fprintf(stderr, " stdout closed. . .\n");
- #endif
- sys$synch(0, child_st);
- sys$dassgn(child_chan);
- }
- #ifdef DEBUG
- fprintf(stderr, " sync done. . .\n");
- #endif
- }
-
- #include <syidef> /* System Information Definitions */
-
- static sig_child(chan)
- int chan;
- {
- #ifdef DEBUG
- fprintf(stderr, "Child Completion AST, st: %x\n", child_st[0] );
- #endif
- if (child_st[0] == 0)
- { child_st[0] = 1; }
- sys$setef ( 0 );
- }
-
- static struct exit_control_block
- {
- struct exit_control_block *flink;
- int (*exit_routine)();
- int arg_count;
- int *status_address;
- int exit_status;
- } exit_block =
- {
- 0,
- exit_handler,
- 1,
- &exit_block.exit_status,
- 0
- };
-
- static char *pipe_and_fork(cmd)
- char *cmd;
- {
- $DESCRIPTOR(cmddsc, cmd);
- static char mbxname[64], ef = 0;
- $DESCRIPTOR(mbxdsc, mbxname);
- short iosb[4];
- int status;
- int pid;
- struct
- {
- short dna_buflen;
- short dna_itmcod;
- char *dna_buffer;
- short *dna_retlen;
- int listend;
- } itmlst =
- {
- sizeof(mbxname),
- DVI$_DEVNAM,
- mbxname,
- &mbxdsc.dsc$w_length,
- 0
- };
- int mbxsize;
- struct
- {
- short mbf_buflen;
- short mbf_itmcod;
- int *mbf_maxbuf;
- short *mbf_retlen;
- int listend;
- } syiitmlst =
- {
- sizeof(mbxsize),
- SYI$_MAXBUF,
- &mbxsize,
- 0,
- 0
- };
-
- cmddsc.dsc$w_length = strlen(cmd);
- /*
- * Get the SYSGEN parameter MAXBUF, and the smaller of it and 2048 as
- * the size of the 'pipe' mailbox.
- */
- if (1 == (1&(vaxc$errno = sys$getsyiw(0, 0, 0, &syiitmlst, iosb, 0, 0, 0))))
- vaxc$errno = iosb[0];
- if (0 == (1&vaxc$errno))
- {
- errno = EVMSERR;
- perror("Can't get SYSGEN parameter value for MAXBUF");
- exit(EXIT_ERR);
- }
- if (mbxsize > 2048)
- mbxsize = 2048;
- if (0 == (1&(vaxc$errno = sys$crembx(0, &child_chan, mbxsize, mbxsize, 0, 0, 0))))
- {
- errno = EVMSERR;
- perror("Can't create pipe mailbox");
- exit(EXIT_ERR);
- }
- if (1 == (1&(vaxc$errno = sys$getdviw(0, child_chan, 0, &itmlst, iosb,
- 0, 0, 0))))
- vaxc$errno = iosb[0];
- if (0 == (1&vaxc$errno))
- {
- errno = EVMSERR;
- perror("Can't get pipe mailbox device name");
- exit(EXIT_ERR);
- }
- mbxname[mbxdsc.dsc$w_length] = '\0';
- #ifdef DEBUG
- fprintf(stderr, "Pipe Mailbox Name = '%s'\n", mbxname);
- #endif
- if (0 == (1&(vaxc$errno = lib$spawn(&cmddsc, &mbxdsc, 0, &1,
- 0, &pid, child_st, &ef, sig_child,
- &child_chan))))
- {
- errno = EVMSERR;
- perror("Can't spawn subprocess");
- exit(EXIT_ERR);
- }
- #ifdef DEBUG
- fprintf(stderr, "Subprocess's Pid = %08X\n", pid);
- #endif
- sys$dclexh(&exit_block);
- return(mbxname);
- }
-
- background_process(argc, argv)
- int argc;
- char **argv;
- {
- char command[2048] = "$";
- $DESCRIPTOR(value, command);
- $DESCRIPTOR(cmd, "BACKGROUND$COMMAND");
- $DESCRIPTOR(null, "NLA0:");
- int pid;
-
- strcat(command, argv[0]);
- while (--argc)
- {
- strcat(command, " \"");
- strcat(command, *(++argv));
- strcat(command, "\"");
- }
- value.dsc$w_length = strlen(command);
- if (0 == (1&(vaxc$errno = lib$set_symbol(&cmd, &value))))
- {
- errno = EVMSERR;
- perror("Can't create symbol for subprocess command");
- exit(EXIT_ERR);
- }
- if (0 == (1&(vaxc$errno = lib$spawn(&cmd, &null, 0, &17, 0, &pid))))
- {
- errno = EVMSERR;
- perror("Can't spawn subprocess");
- exit(EXIT_ERR);
- }
- #ifdef DEBUG
- fprintf(stderr, "%s\n", command);
- #endif
- fprintf(stderr, "%08X\n", pid);
- return(EXIT_OK);
- }
-
- /* got this off net.sources */
-
- #ifdef VMS
- #define index strchr
- #endif /*VMS*/
-
- /*
- * get option letter from argument vector
- */
- int opterr = 1, /* useless, never set or used */
- optind = 1, /* index into parent argv vector */
- optopt; /* character checked for validity */
- char *optarg; /* argument associated with option */
-
- #define BADCH (int)'?'
- #define EMSG ""
- #define tell(s) fputs(progname,stderr);fputs(s,stderr); \
- fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
-
- getopt(nargc,nargv,ostr)
- int nargc;
- char **nargv,
- *ostr;
- {
- static char *place = EMSG; /* option letter processing */
- register char *oli; /* option letter list index */
- char *index();
- char *progname;
-
- if(!*place) { /* update scanning pointer */
- if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
- if (*place == '-') { /* found "--" */
- ++optind;
- return(EOF);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
- if(!*place) ++optind;
- #ifdef VMS
- progname = strrchr(nargv[0],']');
- #else
- progname = rindex(nargv[0],'/');
- #endif
- if (!progname) progname = nargv[0]; else progname++;
- tell(": illegal option -- ");
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place) ++optind;
- }
- else { /* need an argument */
- if (*place) optarg = place; /* no white space */
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- #ifdef VMS
- progname = strrchr(nargv[0],']');
- #else
- progname = rindex(nargv[0],'/');
- #endif
- if (!progname) progname = nargv[0]; else progname++;
- tell(": option requires an argument -- ");
- }
- else optarg = nargv[optind]; /* white space */
- place = EMSG;
- ++optind;
- }
- return(optopt); /* dump back option letter */
- }
- #endif /* VMS */
-