/******************************************************************************* * * * vmsUtils.c - Utility routines for VMS systems. * * * * This file contains the following functions: * * * * StrDescToNul - Convert VMS String Descriptor to C-like null- * * terminated string. Returns the address of * * the malloc'd string. (Call FreeNulStr() when * * done with the string.) * * NulStrToDesc - Convert C-like null-terminated string to VMS * * String Descriptor. Returns the address of * * the malloc'd descriptor, which should be free'd * * when done by calling FreeStrDesc(). * * NulStrWrtDesc - Convert C-like null-terminated string to VMS * * String Descriptor for writing into. The C * * String should already be allocated and the * * length passed as the second parameter. Returns * * the address of the malloc'd descriptor, which * * should be free'd when done via FreeStrDesc(). * * FreeNulStr - Frees null-terminated strings created by * * StrDescToNul(). * * FreeStrDesc - Frees VMS String Descriptors created by * * NulStrToDesc() and NulStrWrtDesc(). * * ConvertVMSCommandLine - Convert an argument vector representing a * * VMS-style command line to something Unix-like. * * Limitations: no abbreviations, some syntax * * information is lost so some errors will yield * * strange results. * * * * rint - Returns the integer (represented as a double * * precision number) nearest its double argument. * * * * VMSFileScan - Calls LIB$FILE_SCAN for filenames on VMS systems * * * * VMSFileScanDone - Ends LIB$FILE_SCAN context & frees memory used * * * * ProcAlive - See if a process (identified by pID) is still * * alive on VMS. * * * * Copyright (c) 1993 Universities Research Association, Inc. * * All rights reserved. * * * * This material resulted from work developed under a Government Contract and * * is subject to the following license: The Government retains a paid-up, * * nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * * works, perform publicly and display publicly by or for the Government, * * including the right to distribute to other Government contractors. Neither * * the United States nor the United States Department of Energy, nor any of * * their employees, makes any warranty, express or implied, or assumes any * * legal liability or responsibility for the accuracy, completeness, or * * usefulness of any information, apparatus, product, or process disclosed, or * * represents that its use would not infringe privately owned rights. * * * * Fermilab Nirvana GUI Library * * February 22, 1993 * * * * Written by Joy Kyriakopulos * * * *******************************************************************************/ static char SCCSID[] = "@(#)vmsUtils.c 1.8 7/7/94"; #ifdef VMS #include stdio #include string #include stdlib #include ctype #include errno #include math #include unixio #include fab #include nam #include rmsdef #include ssdef #include starlet #include lib$routines #include jpidef #include descrip #include "vmsUtils.h" /* Maximum number and length of arguments for ConvertVMSCommandLine */ #define MAX_ARGS 100 #define MAX_CMD_LENGTH 256 /* Maximum number of files handled by VMSFileScan */ #define MAX_NUM_FILES 100 static void successRtn(struct FAB *dirFab); /* VMSFileScan */ static void errRtn(struct FAB *dirFab); /* VMSFileScan */ static void addArgChar(int *argc, char *argv[], char c); char *StrDescToNul(struct dsc$descriptor_s *vmsString) { char *str; if (vmsString->dsc$b_dtype != DSC$K_DTYPE_T || vmsString->dsc$b_class != DSC$K_CLASS_S) fprintf(stderr,"Warning from StrDescToNul: descriptor class/type = %d/%d\n%s", vmsString->dsc$b_class, vmsString->dsc$b_dtype, " Expecting 1/14\n"); str = malloc(vmsString->dsc$w_length + 1); strncpy(str, vmsString->dsc$a_pointer, vmsString->dsc$w_length); str[vmsString->dsc$w_length + 1] = '\0'; return str; } struct dsc$descriptor_s *NulStrToDesc(char *nulTString) { struct dsc$descriptor_s *vmsString; int strLen; char *tmp; strLen = strlen(nulTString); if (strLen > 32767) fprintf(stderr,"Warning from NulStrToDesc: string > 32767 bytes\n"); vmsString = malloc(sizeof(struct dsc$descriptor_s) + strLen + 1); vmsString->dsc$a_pointer = ((char *)vmsString) + sizeof(struct dsc$descriptor_s); tmp = strcpy(vmsString->dsc$a_pointer, nulTString); vmsString->dsc$w_length = strLen; vmsString->dsc$b_dtype = DSC$K_DTYPE_T; vmsString->dsc$b_class = DSC$K_CLASS_S; return vmsString; } struct dsc$descriptor_s *NulStrWrtDesc(char *nulTString, int strLen) { struct dsc$descriptor_s *vmsString; if (strLen > 32767) fprintf(stderr,"Warning from NulStrToDesc: string > 32767 bytes\n"); memset(nulTString, 0, strLen); /*bzero(nulTString, strLen);*/ vmsString = malloc(sizeof(struct dsc$descriptor_s)); vmsString->dsc$a_pointer = nulTString; vmsString->dsc$w_length = strLen; vmsString->dsc$b_dtype = DSC$K_DTYPE_T; vmsString->dsc$b_class = DSC$K_CLASS_S; return vmsString; } void FreeNulStr(char *nulTString) { free(nulTString); } void FreeStrDesc(struct dsc$descriptor_s *vmsString) { if (vmsString->dsc$b_dtype != DSC$K_DTYPE_T || vmsString->dsc$b_class != DSC$K_CLASS_S) fprintf(stderr,"Warning from FreeStrDesc: descriptor class/type = %d/%d\n%s", vmsString->dsc$b_class, vmsString->dsc$b_dtype, " Expecting 1/14\n"); free(vmsString); } double rint(double dnum) { return floor(dnum + 0.5); } /* ** Re-read the command line and convert it from VMS style to unix style. ** Replaces argv and argc with Unix-correct versions. This is ** a poor solution to parsing VMS command lines because some information ** is lost and some elements of the syntax are not checked. Users also ** can't abbreviate qualifiers as is customary under VMS. */ void ConvertVMSCommandLine(int *argc, char **argv[]) { int i; short cmdLineLen; char *c, cmdLine[MAX_CMD_LENGTH], *oldArg0; struct dsc$descriptor_s *cmdLineDesc; /* get the command line (don't use the old argv and argc because VMS has removed the quotes and altered the line somewhat */ cmdLineDesc = NulStrWrtDesc(cmdLine, MAX_CMD_LENGTH); lib$get_foreign(cmdLineDesc, 0, &cmdLineLen, 0); FreeStrDesc(cmdLineDesc); /* begin a new argv and argc, but preserve the original argv[0] which is not returned by lib$get_foreign */ oldArg0 = (*argv)[0]; *argv = (char **)malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = oldArg0; *argc = 1; /* scan all of the text on the command line, reconstructing the arg list */ for (i=0, c=cmdLine; i= 0, the number of files returned in namelist * = -1, an error was returned from LIB$FILE_SCAN * and the error is printed on stderr * * Parameters: * * dirname: input file specification (can include wildcards) * namelist: array of pointers to the expanded file specs * (free each string and the table of pointers when done) * select: user supplied function (or NULL) to call to select * which filenames are to be included in dirname array. * If NULL, all filenames will be included. * fnf: specify INCLUDE_FNF, EXCLUDE_FNF, or NOT_ERR_FNF * INCLUDE_FNF: the resultant file specification is * passed on to select() routine for returning * in namelist, even though the file doesn't exist * EXCLUDE_FNF: return -1 (error) if dirname doesn't exist * NOT_ERR_FNF: return 0 (no error) if no files found * * Call VMSFileScanDone() to free memory used by the FAB and RAB and clear * sticky filename defaults for another scanning sequence. */ static char **Namelist; static int NumFilesFound; static int Fnf; static int Context = 0; static int (*SelectRoutine)(); /* saves select fcn for successRtn */ static struct FAB *DirFAB = NULL; static struct NAM *DirNAM = NULL; int VMSFileScan(char *dirname, char *(*namelist[]), int (*select)(), int fnf) { char result_name[NAM$C_MAXRSS+1]; /* array for resulting file spec */ char expanded_name[NAM$C_MAXRSS+1]; /* array for expanded file spec */ int stat; if (DirFAB == NULL) { DirFAB = (struct FAB *) malloc(sizeof(struct FAB)); DirNAM = (struct NAM *) malloc(sizeof(struct NAM)); *DirFAB = cc$rms_fab; /* initialize FAB with default values */ *DirNAM = cc$rms_nam; /* " NAMe block " " " */ DirFAB->fab$l_nam = DirNAM; /* point FAB to NAM block */ DirFAB->fab$l_dna = "*."; /* default is no extension */ DirFAB->fab$b_dns = 2; DirNAM->nam$b_ess = sizeof(expanded_name) - 1; DirNAM->nam$b_rss = sizeof(result_name) - 1; } DirFAB->fab$l_fna = dirname; /* wildcard spec for LIB$FILE_SCAN */ DirFAB->fab$b_fns = strlen(dirname); DirNAM->nam$l_esa = &expanded_name[0]; /* expanded file specs ret'nd here */ DirNAM->nam$l_rsa = &result_name[0]; /* resultant file specs ret'nd here */ SelectRoutine = select; NumFilesFound = 0; Fnf = fnf; Namelist = malloc(sizeof(char *) * MAX_NUM_FILES); *namelist = 0; stat = lib$file_scan(DirFAB, successRtn, errRtn, &Context); if (stat != RMS$_NORMAL && stat != RMS$_FNF && stat != RMS$_NMF) { fprintf(stderr, "Error calling LIB$FILE_SCAN: %s\n", strerror(EVMSERR, stat)); return -1; } if (stat == RMS$_FNF && Fnf == EXCLUDE_FNF) return -1; *namelist = Namelist; return NumFilesFound; } static void successRtn(struct FAB *dirFab) { if (NumFilesFound >= MAX_NUM_FILES) return; /* terminate filename string with a null to pass to user's select routine */ dirFab->fab$l_nam->nam$l_rsa[dirFab->fab$l_nam->nam$b_rsl] = '\0'; /* if user's select routine returns value != 0, then put into name list */ if (SelectRoutine == NULL || (*SelectRoutine)(dirFab->fab$l_nam->nam$l_rsa)) { ++NumFilesFound; Namelist[NumFilesFound-1] = malloc(dirFab->fab$l_nam->nam$b_rsl+1); strcpy(Namelist[NumFilesFound-1], dirFab->fab$l_nam->nam$l_rsa); /* printf("File: %s included\n", dirFab->fab$l_nam->nam$l_rsa); */ } } static void errRtn(struct FAB *dirFab) { if (dirFab->fab$l_sts == RMS$_FNF && Fnf == INCLUDE_FNF) successRtn(dirFab); /* return filename even tho' doesn't exist */ else if (dirFab->fab$l_sts != RMS$_FNF || (dirFab->fab$l_sts == RMS$_FNF && Fnf != NOT_ERR_FNF)) fprintf(stderr, "Error - %s: %s\n", strerror(EVMSERR, dirFab->fab$l_sts), dirFab->fab$l_fna); } void VMSFileScanDone(void) { if (DirFAB != NULL) { int s; if ((s=lib$file_scan_end(DirFAB, &Context)) != RMS$_NORMAL && s != SS$_NORMAL) fprintf(stderr, "Error calling LIB$FILE_SCAN_END: %s\n", strerror(EVMSERR,s)); free(DirNAM); DirNAM = NULL; free(DirFAB); DirFAB = NULL; } } /* * ProcAlive: see if a process (identified by pID) is still alive on VMS. * * Returns: 1 - process exists * 0 - process does not exist * -1 - error getting process info */ int ProcAlive(const unsigned int pID) { int jpiStat; short retLen; char userName[13]; /* 12 plus 1 for ending null */ struct getJPIdescriptor { short bufLength; short itemCode; char *bufAddr; short *retLenAddr; int *endList; } getJPID; getJPID.bufLength = 12; /* (max) size of user name */ getJPID.itemCode = JPI$_USERNAME; getJPID.bufAddr = userName; getJPID.retLenAddr = &retLen; getJPID.endList = 0; jpiStat = sys$getjpiw(1,&pID,0,&getJPID,0,0,0); /* printf("in ProcAlive - jpiStat = %d, pid = %X\n", jpiStat, pID); */ if (jpiStat == SS$_NORMAL || jpiStat == SS$_NOPRIV || jpiStat == SS$_SUSPENDED) return 1; /* process exists */ if (jpiStat == SS$_NONEXPR) return 0; /* process does not exist */ fprintf(stderr, "Error calling GETJPI in ProcAlive. Status = %d\n", jpiStat); return -1; /* error */ } #endif /*VMS*/