📄 vmsutils.c
字号:
static const char CVSID[] = "$Id: vmsUtils.c,v 1.5 2001/08/14 08:37:16 jlous Exp $";/******************************************************************************** ** 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) 1999 Mark Edel ** ** This is free software; you can redistribute it and/or modify it under the ** terms of the GNU General Public License as published by the Free Software ** Foundation; either version 2 of the License, or (at your option) any later ** version. ** ** This software is distributed in the hope that it will be useful, but WITHOUT ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ** for more details. ** ** You should have received a copy of the GNU General Public License along with ** software; if not, write to the Free Software Foundation, Inc., 59 Temple ** Place, Suite 330, Boston, MA 02111-1307 USA ** ** Nirvana Text Editor ** February 22, 1993 ** ** Written by Joy Kyriakopulos ** ********************************************************************************/#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 100static 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);}#if !(defined __ALPHA && (defined _XOPEN_SOURCE_EXTENDED || !defined _ANSI_C_SOURCE))double rint(double dnum){ return floor(dnum + 0.5);}#endif/*** 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<cmdLineLen; c++, i++) { if (*c == '\t') { addArgChar(argc, *argv, ' '); } else if (*c == '/') { addArgChar(argc, *argv, ' '); addArgChar(argc, *argv, '-'); } else if (*c == '=') { addArgChar(argc, *argv, ' '); } else if (*c == ',') { addArgChar(argc, *argv, ' '); } else { addArgChar(argc, *argv, *c); } } addArgChar(argc, *argv, ' ');}/*** Accumulate characters in an argv argc style argument list. Spaces** mean start a new argument and extra ones are ignored. Argument strings** are accumulated internally in the routine and not flushed into argv** until a space is recieved (so a final space is needed to finish argv).*/static void addArgChar(int *argc, char *argv[], char c){ static char str[MAX_CMD_LENGTH]; static char *strPtr = str; static int inQuoted = FALSE, preserveQuotes = FALSE; int strLen; if (c == ' ') { if (strPtr == str) { /* don't form empty arguments */ return; } else if (inQuoted) { /* preserve spaces inside of quoted strings */ *strPtr++ = c; } else { /* flush the accumulating argument */ strLen = strPtr - str; argv[*argc] = (char *)malloc(sizeof(char) * (strLen + 1)); strncpy(argv[*argc], str, strLen); argv[*argc][strLen] = '\0'; (*argc)++; strPtr = str; inQuoted = FALSE; } } else if (c == '"') { /* note when quoted strings begin and end */ if (inQuoted) { inQuoted = FALSE; } else { preserveQuotes = (strPtr != str); /* remove quotes around the */ inQuoted = TRUE; /* outsides of arguments but */ } /* preserve internal ones so */ if (preserveQuotes) /* access strings will work */ *strPtr++ = c; } else if (inQuoted) { *strPtr++ = c; } else { *strPtr++ = tolower(c); }} /* * VMSFileScan -- Routine to call LIB$FILE_SCAN for filenames on VMS systems * * Returns: integer value >= 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*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -