This is vms.c in view mode; [Download] [Up]
/* Some unix emulation procedures to make XV happy */
/* 1-NOV-1990 GJC@MITECH.COM */
#include <stdio.h>
#ifdef __ALPHA
#include <unixio.h>
#endif
#include <string.h>
#include <descrip.h>
#include <rmsdef.h>
#include <ssdef.h>
#include <stat.h>
int xv_bcmp ( s1, s2, size )
char *s1, *s2;
int size;
{
int i;
for ( i = 0; i < size; i++ ) if ( *s1++ != *s2++ ) {
if ( *(--s1) > *(--s2) ) return 1; else return -1;
}
return 0;
}
bcopy(x,y,n)
char *x,*y;
long n;
{memmove(y,x,n);} /* reverse order of arguments */
static char *getwd_tmp = NULL;
char *getwd(p)
char *p;
{int c;
char *root_dir,*l2;
getcwd(p,512,0); /* get current working directory in unix format*/
root_dir = strstr ( p, "/000000" );
if ( root_dir != NULL ) {
/* trim root directory out of specification */
if ( (strlen(root_dir) == 7) &&
(strpbrk(p+1,"/") == root_dir) ) *root_dir = '\0';
}
/* special kludge for "/" directory */
if ( strcmp ( p, "/DEVICE_LIST_ROOT" ) == 0 ) strcpy ( p, "/" );
return(p);
}
unlink(p)
char *p;
{printf("unlink: '%s'\n",p); delete(p);}
rmdir(p)
char *p;
{printf("rmdir: Sorry, not available on VMS '%s' is unchanged!\n",p);}
rindex(p,c)
char *p;
int c;
{return(strrchr(p,c));}
int lstat(f,st) /* fake a stat operation to return file type */
char *f;
stat_t *st;
{
char *dirext, *name;
int extlen;
st->st_mode = S_IFREG; /* default to normal file */
name = strrchr ( f, '/' ); /* locate rightmost slash */
if ( name == NULL ) name = f; else name++;
dirext = strstr ( name, ".DIR" );
if ( dirext != NULL ) {
/* make it an exact match */
extlen = strcspn(&dirext[1],".;");
if ( (extlen == 0) || (extlen == 3) ) {
st->st_mode = S_IFDIR;
if ( strncmp ( name, "000000.", 7 ) == 0 ) return 0;
else return (stat ( f, st ));
}
}
return 0;
}
do_vms_wildcard(pargc,pargv)
int *pargc;
char ***pargv;
{int j,vsize;
int argc; char **argv;
argc = *pargc;
argv = *pargv;
*pargc = 0;
vsize = 3;
*pargv = (char **) malloc(sizeof (char *) * vsize);
for(j=0;j<argc;++j)
vms_wild_putargs(argv[j],pargc,pargv,&vsize);}
vms_wild_putargs(s,pargc,pargv,pvsize)
char *s; int *pargc; char ***pargv; int *pvsize;
{if ( (!strchr(s,'*')) && (!strchr(s,'%')) )
vms_wild_put_one(s,pargc,pargv,pvsize);
else
vms_wild_put_wild(s,pargc,pargv,pvsize);}
vms_wild_put_one(s,pargc,pargv,pvsize)
char *s; int *pargc; char ***pargv; int *pvsize;
{int nvsize,i;
#ifdef __ALPHA
# define SHELL$TRANSLATE_VMS decc$translate_vms
#else
char *SHELL$TRANSLATE_VMS();
#endif
char ** nargv, *uname;
if (*pargc == *pvsize)
{nvsize = 2 * *pvsize;
nargv = (char **) malloc(sizeof (char *) * nvsize);
for(i=0;i < *pargc; ++i) nargv[i] = (*pargv)[i];
free(*pargv);
*pargv = nargv;
*pvsize = nvsize;}
if ( uname = SHELL$TRANSLATE_VMS ( s ) ) {
/* printf("vms: '%s' -> unix: '%s'\n", s, uname ); */
if ( strlen(s) >= strlen(uname) ) { strcpy(s,uname); free(uname); }
else s = uname; /* will lose s's old allocation */
}
(*pargv)[(*pargc)++] = s;}
set_dsc(x,buff,len)
struct dsc$descriptor *x;
char *buff;
int len;
{(*x).dsc$w_length = len;
(*x).dsc$a_pointer = buff;
(*x).dsc$b_class = DSC$K_CLASS_S;
(*x).dsc$b_dtype = DSC$K_DTYPE_T;
return(x);}
struct dsc$descriptor *
set_dsc_cst(x,buff)
struct dsc$descriptor *x;
char *buff;
{return(set_dsc(x,buff,strlen(buff)));}
vms_wild_put_wild(s,pargc,pargv,pvsize)
char *s; int *pargc; char ***pargv; int *pvsize;
{struct dsc$descriptor fnamed,foutd,rfnamed;
char *ns,*p;
int rval;
long context;
set_dsc_cst(&rfnamed,";");
set_dsc_cst(&fnamed,s);
set_dsc(&foutd,0,0);
foutd.dsc$b_class = DSC$K_CLASS_D;
context = 0;
while(1)
{rval = lib$find_file(&fnamed,&foutd,&context,0,&rfnamed,0,0);
if (rval == RMS$_NMF) break;
if (rval == RMS$_FNF) break;
if (rval != RMS$_NORMAL) exit(rval);
ns = (char *) malloc(foutd.dsc$w_length + 1);
ns[foutd.dsc$w_length] = 0;
memcpy(ns,foutd.dsc$a_pointer,foutd.dsc$w_length);
/*if (p = strchr(ns,']')) ns = p+1;*/
/* if (p = strchr(ns,';')) *p = 0; */
vms_wild_put_one(ns,pargc,pargv,pvsize);}
if (foutd.dsc$a_pointer) lib$sfree1_dd(&foutd);
if (context)
{rval = lib$find_file_end(&context);
if (rval != SS$_NORMAL) exit(rval);}}
/*
* Define substitue qsort for one that dec broke. Only handle case where
* element size is 4 (same as integer).
*/
#ifdef qsort
#undefine qsort
#endif
void xv_qsort ( array, size, unit, compare )
int array[1000]; /* array to be sorted */
int size; /* size of array to sort, should be at least 100 */
int unit; /* Size of array element */
int compare(); /* comaparison function */
{
int stack[68], *top; /* work array, depth of stack is bounded */
int start, finish, lbound, hbound, pivot, temp, i, j;
if ( unit != sizeof(int) ) { /* punt */
qsort ( array, size, unit, compare );
return;
}
if ( size <= 1 ) return;
/* set up initial partition on top of stack */
top = &stack[68];
*--top = 0; /* push lbound */
*--top = size-1; /* push initial hbound */
/* loop until stack is emtpy */
while ( top < &stack[68] ) {
/* pop next range from stack and see if it has at least 3 elements */
finish = *top++; start = *top++;
pivot = array[start];
if ( finish > start + 1 ) {
/*
* more than 2 elements, split range into 2 sections according to
* the relation to the pivot value.
*/
array[start] = array[(start+finish)/2]; /* avoid sequence */
array[(start+finish)/2] = pivot; pivot = array[start];
lbound = start; hbound = finish;
while ( lbound < hbound ) {
if ( compare(&pivot, &array[lbound+1]) > 0 ) {
lbound++;
} else {
temp = array[hbound];
array[hbound] = array[lbound+1];
hbound--;
array[lbound+1] = temp;
}
}
/* determine which parition is bigger and push onto stack */
if ( lbound + lbound < (start+finish) ) {
/* push high partition first. */
*--top = lbound + 1;
*--top = finish;
finish = start; /* skip add step below */
/* either push low partition or sort by inspection */
if ( lbound - start > 1 ) {
*--top = start;
*--top = lbound;
} else {
/* 2 element parition (start+1=lbound), sort by looking */
if ( pivot > array[lbound] ) {
array[start] = array[lbound];
array[lbound] = pivot;
}
}
} else if ( lbound != finish ) {
/* either push low partition or sort by inspection */
if ( lbound - start > 1 ) {
*--top = start;
*--top = lbound;
} else if ( lbound > start ) {
/* 2 element parition (start+1=lbound), sort by looking */
if ( compare(&pivot, &array[lbound]) > 0 ) {
array[start] = array[lbound];
array[lbound] = pivot;
}
}
/* push high partition or sort by inspection */
if ( lbound < finish - 2 ) {
*--top = lbound + 1;
*--top = finish;
} else if ( lbound < finish - 1 ) { /* 2 in partition */
if ( compare(&array[lbound+1], &array[finish]) > 0 ) {
temp = array[lbound+1];
array[lbound+1] = array[finish];
array[finish] = temp;
}
}
} else {
/*
* Special case: high partition is empty, indicating that pivot
* value is at maximum. Move to end and re-push remainder.
*/
array[start] = array[finish];
array[finish] = pivot;
*--top = start;
*--top = finish - 1;
}
} else {
/* only 2 elements in partition, sort inline */
if ( compare(&pivot,&array[finish]) > 0 ) {
array[start] = array[finish];
array[finish] = pivot;
}
}
}
}
/*****************************************************************************/
/*
** VMS readdir() routines.
** Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
** This code has no copyright.
*/
/* 12-NOV-1990 added d_namlen field and special case "." name -GJC@MITECH.COM
*/
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <descrip.h>
#include <rmsdef.h>
#include "dirent.h"
/* Uncomment the next line to get a test routine. */
/*#define TEST*/
/* Number of elements in vms_versions array */
#define VERSIZE(e) (sizeof e->vms_versions / sizeof e->vms_versions[0])
/* Linked in later. */
extern char *strrchr();
extern char *strcpy();
/* Don't need this when all these programs are lumped together. RLD
extern char *malloc();
*/
/*
** Open a directory, return a handle for later use.
*/
DIR *
opendir(name)
char *name;
{
DIR *dd;
/* Get memory for the handle, and the pattern. */
if ((dd = (DIR *)malloc(sizeof *dd)) == NULL) {
errno = ENOMEM;
return NULL;
}
if (strcmp(".",name) == 0) name = "";
dd->pattern = malloc((unsigned int)(strlen(name) + sizeof "*.*" + 1));
if (dd->pattern == NULL) {
free((char *)dd);
errno = ENOMEM;
return NULL;
}
/* Fill in the fields; mainly playing with the descriptor. */
(void)sprintf(dd->pattern, "%s*.*", name);
dd->context = 0;
dd->vms_wantversions = 0;
dd->pat.dsc$a_pointer = dd->pattern;
dd->pat.dsc$w_length = strlen(dd->pattern);
dd->pat.dsc$b_dtype = DSC$K_DTYPE_T;
dd->pat.dsc$b_class = DSC$K_CLASS_S;
return dd;
}
/*
** Set the flag to indicate we want versions or not.
*/
void
vmsreaddirversions(dd, flag)
DIR *dd;
int flag;
{
dd->vms_wantversions = flag;
}
/*
** Free up an opened directory.
*/
void
closedir(dd)
DIR *dd;
{
free(dd->pattern);
free((char *)dd);
}
/*
** Collect all the version numbers for the current file.
*/
static void
collectversions(dd)
DIR *dd;
{
struct dsc$descriptor_s pat;
struct dsc$descriptor_s res;
struct dirent *e;
char *p;
char buff[sizeof dd->entry.d_name];
int i;
char *text;
long context;
/* Convenient shorthand. */
e = &dd->entry;
/* Add the version wildcard, ignoring the "*.*" put on before */
i = strlen(dd->pattern);
text = malloc((unsigned int)(i + strlen(e->d_name)+ 2 + 1));
if (text == NULL)
return;
(void)strcpy(text, dd->pattern);
(void)sprintf(&text[i - 3], "%s;*", e->d_name);
/* Set up the pattern descriptor. */
pat.dsc$a_pointer = text;
pat.dsc$w_length = strlen(text);
pat.dsc$b_dtype = DSC$K_DTYPE_T;
pat.dsc$b_class = DSC$K_CLASS_S;
/* Set up result descriptor. */
res.dsc$a_pointer = buff;
res.dsc$w_length = sizeof buff - 2;
res.dsc$b_dtype = DSC$K_DTYPE_T;
res.dsc$b_class = DSC$K_CLASS_S;
/* Read files, collecting versions. */
for (context = 0; e->vms_verscount < VERSIZE(e); e->vms_verscount++) {
if (lib$find_file(&pat, &res, &context) == RMS$_NMF || context == 0)
break;
buff[sizeof buff - 1] = '\0';
if (p = strchr(buff, ';'))
e->vms_versions[e->vms_verscount] = atoi(p + 1);
else
e->vms_versions[e->vms_verscount] = -1;
}
free(text);
}
/*
** Read the next entry from the directory.
*/
struct dirent *
readdir(dd)
DIR *dd;
{
struct dsc$descriptor_s res;
char *p;
char buff[sizeof dd->entry.d_name];
int i;
/* Set up result descriptor, and get next file. */
res.dsc$a_pointer = buff;
res.dsc$w_length = sizeof buff - 2;
res.dsc$b_dtype = DSC$K_DTYPE_T;
res.dsc$b_class = DSC$K_CLASS_S;
if (lib$find_file(&dd->pat, &res, &dd->context) == RMS$_NMF
|| dd->context == 0L)
/* None left... */
return NULL;
/* Force the buffer to end with a NUL. */
buff[sizeof buff - 1] = '\0';
for (p = buff; !isspace(*p); p++)
;
*p = '\0';
/* Skip any directory component and just copy the name. */
if (p = strchr(buff, ']'))
(void)strcpy(dd->entry.d_name, p + 1);
else
(void)strcpy(dd->entry.d_name, buff);
/* Clobber the version. */
if (p = strchr(dd->entry.d_name, ';'))
*p = '\0';
dd->entry.d_namlen = strlen(dd->entry.d_name);
dd->entry.vms_verscount = 0;
if (dd->vms_wantversions)
collectversions(dd);
return &dd->entry;
}
/*
** Return something that can be used in a seekdir later.
*/
long
telldir(dd)
DIR *dd;
{
return dd->context;
}
/*
** Return to a spot where we used to be.
*/
void
seekdir(dd, pos)
DIR *dd;
long pos;
{
dd->context = pos;
}
#ifdef TEST
main()
{
char buff[256];
DIR *dd;
struct dirent *dp;
int i;
int j;
for ( ; ; ) {
printf("\n\nEnter dir: ");
(void)fflush(stdout);
(void)gets(buff);
if (buff[0] == '\0')
break;
if ((dd = opendir(buff)) == NULL) {
perror(buff);
continue;
}
/* Print the directory contents twice, the second time print
* the versions. */
for (i = 0; i < 2; i++) {
while (dp = readdir(dd)) {
printf("%s%s", i ? "\t" : " ", dp->d_name);
for (j = 0; j < dp->vms_verscount; j++)
printf(" %d", dp->vms_versions[j]);
printf("\n");
}
rewinddir(dd);
vmsreaddirversions(dd, 1);
}
closedir(dd);
}
exit(0);
}
#endif /* TEST */
/*****************************************************************************/
/*
pseudo_root - Return the Window ID of the Pseudo Root
NOTE: This routine is required for DECwindows
because the true root window is hidden behind
a pseudo-root window created by the window manager.
Calling Sequence:
root_win = pseudo_root(display, screen);
where:
display must already be opened and
screen is usually DefaultScreen(display).
*/
#include <X11/Xlib.h>
#ifdef NULL
#undef NULL
#define NULL 0L
#endif
static void chase_root();
static int done;
static Window last_win;
static int root_x, root_y, root_width, root_height;
static int root_bw, root_depth;
Window pseudo_root(dpy, screen)
Display *dpy;
int screen;
{
Window root, win;
/* Start at the real root */
root = RootWindow(dpy, screen);
/* Get the geometry of the root */
if (XGetGeometry(dpy, root, &win, &root_x, &root_y,
&root_width, &root_height,
&root_bw, &root_depth))
{
/* Set up for the tree walk */
done = False;
last_win = root;
/* Run down the tree to find the pseudo root */
chase_root(dpy, root);
return last_win;
}
else
/* Classic case of "this should never happen" */
return root;
} /*** End pseudo_root() ***/
/*
chase_root - Internal to this module
This is a recursive routine for descending the window tree.
It looks for the first window which does NOT overlay the root,
then returns with the ID of the last window it saw in the
global variable last_win.
NOTE: The parameters of the root window must be set up before
calling chase_root().
*/
static void chase_root (dpy, w)
Display *dpy;
Window w;
{
Window root, parent;
unsigned int nchildren;
Window *children = NULL;
Status status;
int n;
int x, y, rx, ry;
unsigned int width, height, bw, depth;
/* Insurance */
if (done)
return;
if (XGetGeometry(dpy, w, &root, &x, &y, &width, &height, &bw, &depth))
{
/*
If this window does not exactly overlay the root
then we have gone one too far, i.e., we have finished.
*/
if ( (x != root_x) ||
(y != root_y) ||
(width != root_width) ||
(height != root_height) )
{
done = True;
return;
}
/* Otherwise, remember where we got up to and continue */
else
last_win = w;
}
else
/* We are in trouble if this happens!!! */
return;
if (!XQueryTree (dpy, w, &root, &parent, &children, &nchildren))
/* Likewise, we hope we never get here!!! */
return;
for (n = 0; n < nchildren; n++)
{
chase_root (dpy, children[n]);
if (done)
break;
}
#ifdef VMS
if (children) XFree ((char *) children);
#else
if (children) free ((char *) children);
#endif
return;
} /*** End chase_root() ***/
/*****************************************************************************/
/*
* @(#)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 */
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.