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 >
Wrap
Text File
|
1996-11-24
|
37KB
|
1,560 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 ) )
c2 = 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 );
#if defined(COMPILE_TIME) && defined(COMPILED_BY)
pm_message( "Compiled %s by user \"%s\"",
COMPILE_TIME, COMPILED_BY );
#endif
#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;
#ifndef _OSK
#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 );
}
#else
if ( reason != 0 && reason[0] != '\0' )
pm_error( "%s - %s", reason, errno );
else
pm_error( "%s", errno );
}
#endif
#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 */