/*****************************************************************************/ /* (wu)util.c Module name says it all. COPYRIGHT --------- Copyright (C) 2020,2021 Mark G.Daniel This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version. http://www.gnu.org/licenses/gpl.txt VERSION HISTORY --------------- 10-DEC-2019 MGD initial (transplanted from WCME) */ /*****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "wucme.h" #define FI_LI "UTIL", __LINE__ /*****************************************************************************/ /* Enable SYSPRV and SYSLCK in the calling process. If the image is INSTALLed with SETPRV then enable that as well. */ void UtilAdjustPriv () { static ulong AdjustPrivMask [2] = { PRV$M_SYSPRV | PRV$M_SYSLCK, 0 }; static ulong AdjustSetPrvMask [2] = { PRV$M_SETPRV, 0 }; int status; /*********/ /* begin */ /*********/ status = sys$setprv (1, &AdjustPrivMask, 0, 0); if (status == SS$_NOTALLPRIV) { if (wucmeMode (IS_SCRIPT)) ScriptStreamHeader (); fputs ("%WUCME-F-NOPRIV, must be INSTALLed with SYSPRV and SYSLCK", stdout); exit (SS$_NOPRIV | STS$M_INHIB_MSG); } if (!(status & 1)) EXIT_FI_LI (status); /* if NOT installed with SETPRV then just ignore */ sys$setprv (1, &AdjustSetPrvMask, 0, 0); } /*****************************************************************************/ /* * Wrap around asprintf(3), which sometimes nullifies the input values, * sometimes not, but always returns <0 on error. * Returns NULL on failure or the pointer on success. */ char * doasprintf(char *fmt, ...) { int c; char *cp; va_list ap; va_start(ap, fmt); c = vasprintf(&cp, fmt, ap); va_end(ap); return(c < 0 ? NULL : cp); } /*****************************************************************************/ /* Return a pointer to an equivalent VMS name. Calling code must cast return value using (char*) and type as -1. Also acts as its own callback routine. */ int UtilVmsName ( char *name, int type ) { static char *vname; /*********/ /* begin */ /*********/ if (type == -1) { if (decc$to_vms (name, UtilVmsName, 0, 0) != 1) { if (vname) free (vname); vname = NULL; } return ((int)vname); } if (vname) free (vname); if (type == DECC$K_DIRECTORY || type == DECC$K_FOREIGN) { vname = NULL; return (0); } vname = strdup(name); return (1); } /*****************************************************************************/ /* Allowed to use the application? */ int UtilHaveSysPrv (void) { static ulong SysPrvMask[2] = { PRV$M_SYSPRV, 0 }; return (UtilHavePriv(SysPrvMask)); } /*****************************************************************************/ /* Check privilege mask. Return true or false. */ int UtilHavePriv (ulong *PrivMask) { static ulong JpiImagPriv [2], JpiProcPriv [2]; static struct { short int buf_len; short int item; void *buf_addr; ushort *ret_len; } JpiItemList[] = { { sizeof(JpiImagPriv), JPI$_IMAGPRIV, &JpiImagPriv, 0 }, { sizeof(JpiProcPriv), JPI$_PROCPRIV, &JpiProcPriv, 0 }, {0,0,0,0} }; int status; /*********/ /* begin */ /*********/ status = sys$getjpiw (0, 0, 0, &JpiItemList, 0, 0, 0); if ((status & 1) == 0) EXIT_FI_LI (status); return ((((JpiImagPriv[0] & PrivMask[0]) == PrivMask[0]) && ((JpiImagPriv[1] & PrivMask[1]) == PrivMask[1])) || (((JpiProcPriv[0] & PrivMask[0]) == PrivMask[0]) && ((JpiProcPriv[1] & PrivMask[1]) == PrivMask[1]))); } /*****************************************************************************/ /* If |name| not NULL sets the process name. Return NULL if this fails. Always returns a pointer to the significant portion of the process name. */ char* UtilSetPrn (char *name) { static char *NamePtr = ""; static char prcnam [16]; char *cptr, *sptr, *zptr; $DESCRIPTOR (NameDsc, (char*)prcnam); /*********/ /* begin */ /*********/ if (!name) return (NamePtr); zptr = (sptr = prcnam) + sizeof(prcnam)-1; for (cptr = name; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; NameDsc.dsc$w_length = sptr - prcnam; if (*name) if (!(sys$setprn (&NameDsc) & 1)) return (NULL); return (NamePtr); } /*****************************************************************************/ /* Divine our image name. */ char* UtilImageName (void) { static char JpiImagName [256]; static struct { ushort buf_len; ushort item; uchar *buf_addr; ushort *short_ret_len; } JpiItems [] = { { sizeof(JpiImagName), JPI$_IMAGNAME, (uchar*)&JpiImagName, 0 }, { 0,0,0,0 } }; int status; char *cptr; /*********/ /* begin */ /*********/ if (JpiImagName[0]) return (JpiImagName); status = sys$getjpiw (0, 0, 0, &JpiItems, 0, 0, 0); if ((status & 1) == 0) EXIT_FI_LI (status); /* when fork()ing ensure we're not using a specific version */ for (cptr = JpiImagName; *cptr && *cptr != ';'; cptr++); if (*cptr == ';') *cptr = '\0'; return (JpiImagName); } /*****************************************************************************/ /* Return a pointer to a static buffer containing the string equivalent of the supplied VMS status value. */ char* UtilGetMsg (int status) { static char buf [256]; unsigned short slen; $DESCRIPTOR (bufDsc, buf); /*********/ /* begin */ /*********/ sys$getmsg (status, &slen, &bufDsc, 1, 0); buf[slen] = '\0'; buf[0] = toupper(buf[0]); return (buf); } /*****************************************************************************/ /* Just a wrapper. */ char* UtilSysTrnLnm (char *lnm) { return (UtilTrnLnm (lnm, "LNM$SYSTEM", 0)); } /*****************************************************************************/ /* Translate a logical name using LNM$FILE_DEV by default or the specified name table. Returns a pointer to the value string, or NULL if the name does not exist. 'IndexValue' should be zero for a 'flat' logical name, or 0..127 for interative translations. Returns pointer to non-reentrant static buffer which must be strdup()ed if retained. */ char* UtilTrnLnm ( char *LogName, char *LogTable, int IndexValue ) { static ushort ValueLength; static ulong LnmAttributes, LnmIndex; static char LogValue [256]; static $DESCRIPTOR (LogNameDsc, ""); static $DESCRIPTOR (LogTableDsc, ""); static struct { short int buf_len; short int item; void *buf_addr; ushort *ret_len; } LnmItems [] = { { sizeof(LnmIndex), LNM$_INDEX, &LnmIndex, 0 }, { sizeof(LnmAttributes), LNM$_ATTRIBUTES, &LnmAttributes, 0 }, { sizeof(LogValue), LNM$_STRING, LogValue, &ValueLength }, { 0,0,0,0 } }; int status; /*********/ /* begin */ /*********/ LnmIndex = IndexValue; if (LogTable) { LogTableDsc.dsc$a_pointer = LogTable; LogTableDsc.dsc$w_length = strlen(LogTable); } else { LogTableDsc.dsc$a_pointer = "LNM$FILE_DEV"; LogTableDsc.dsc$w_length = sizeof("LNM$FILE_DEV")-1; } LogNameDsc.dsc$a_pointer = LogName; LogNameDsc.dsc$w_length = strlen(LogName); status = sys$trnlnm (0, &LogTableDsc, &LogNameDsc, 0, &LnmItems); if (!(status & 1) || !(LnmAttributes & LNM$M_EXISTS)) { if (LogValue) LogValue[0] = '\0'; return (NULL); } LogValue[ValueLength] = '\0'; return (LogValue); } /*****************************************************************************/ /* Create a logical name in the SYSTEM table. */ void UtilSysCreLnm ( char *name, char *value ) { static $DESCRIPTOR (LogNameDsc, ""); static $DESCRIPTOR (LogTableDsc, "LNM$SYSTEM"); static struct { short int buf_len; short int item; unsigned char *buf_addr; unsigned short *ret_len; } CreLnmItem [2]; int status; /*********/ /* begin */ /*********/ LogNameDsc.dsc$a_pointer = name; LogNameDsc.dsc$w_length = strlen(name); CreLnmItem[0].item = LNM$_STRING; CreLnmItem[0].buf_addr = (uchar*)value; CreLnmItem[0].buf_len = strlen(value); status = sys$crelnm (0, &LogTableDsc, &LogNameDsc, 0, &CreLnmItem); if (!(status & 1)) EXIT_FI_LI (status); } /*****************************************************************************/ /* */ /* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. */ errx (int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt); verrx(eval, fmt, ap); va_end(ap); } verrx (int eval, const char *fmt, va_list ap) { rk_warnerr(0, fmt, ap); exit(eval); } /*****************************************************************************/ /* * Find the first occurrence of find in s, ignore case. */ char * strcasestr(const char *s, const char *find) { char c, sc; size_t len; if ((c = *find++) != 0) { c = (char)tolower((unsigned char)c); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); } while ((char)tolower((unsigned char)sc) != c); } while (strncasecmp(s, find, len) != 0); s--; } return ((char *)s); } /*****************************************************************************/ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. */ char * strndup(const char *str, size_t n) { size_t len; char *copy; len = strnlen(str, n); if ((copy = malloc(len + 1)) == NULL) return (NULL); memcpy(copy, str, len); copy[len] = '\0'; return (copy); } /*****************************************************************************/ /* */ /* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. */ void warn(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vwarn(fmt, ap); va_end(ap); } void warnx(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vwarnx(fmt, ap); va_end(ap); } void vwarn(const char *fmt, va_list ap) { rk_warnerr(1, fmt, ap); } void vwarnx(const char *fmt, va_list ap) { rk_warnerr(0, fmt, ap); } void rk_warnerr (int doerrno, const char *fmt, va_list ap) { int sverrno = errno; #ifdef IS_WUCME const char *progname = tstamp(NULL); #else const char *progname = getprogname(); #endif if(progname != NULL){ fprintf(stderr, "%s", progname); if(fmt != NULL || doerrno) fprintf(stderr, ": "); } if (fmt != NULL){ vfprintf(stderr, fmt, ap); if(doerrno) fprintf(stderr, ": "); } if(doerrno) fprintf(stderr, "%s", strerror(sverrno)); fprintf(stderr, "\n"); fflush(stderr); } /*****************************************************************************/ /* */ /** * `asprintf.c' - asprintf * * copyright (c) 2014 joseph werle */ #ifndef HAVE_ASPRINTF #include #include #include // #include "asprintf.h" int asprintf (char **str, const char *fmt, ...) { int size = 0; va_list args; // init variadic argumens va_start(args, fmt); // format and get size size = vasprintf(str, fmt, args); // toss args va_end(args); return size; } int vasprintf (char **str, const char *fmt, va_list args) { int size = 0; va_list tmpa; // copy #ifndef __VMS va_copy(tmpa, args); #else tmpa = args; #endif // apply variadic arguments to // sprintf with format to get size size = vsnprintf(NULL, size, fmt, tmpa); // toss args va_end(tmpa); // return -1 to be compliant if // size is less than 0 if (size < 0) { return -1; } // alloc with size plus 1 for `\0' *str = (char *) malloc(size + 1); // return -1 to be compliant // if pointer is `NULL' if (NULL == *str) { return -1; } // format string with original // variadic arguments and set new size size = vsprintf(*str, fmt, args); return size; } #endif /*****************************************************************************/ /* Return a pointer to string time-stamp "yyyy-mm-dd-hh:mm:ss.hh". Not reentrant. */ char* tstamp (ulong *binptr) { static char stamp [32]; ulong BinTime [2]; ushort NumTime [7]; /*********/ /* begin */ /*********/ if (!binptr) sys$gettim (binptr = (ulong*)&BinTime); sys$numtim (&NumTime, binptr); sprintf (stamp, "%04.04d-%02.02d-%02.02d %02.02d:%02.02d:%02.02d.%02.02d", NumTime[0], NumTime[1], NumTime[2], NumTime[3], NumTime[4], NumTime[5], NumTime[6]); return (stamp); } /*****************************************************************************/ /* Return a pointer to string time-stamp "yyyymmddhhmmsshh". Not reentrant. */ char* tstamp2 (ulong *binptr) { static char stamp [32]; ulong BinTime [2]; ushort NumTime [7]; /*********/ /* begin */ /*********/ if (!binptr) sys$gettim (binptr = (ulong*)&BinTime); sys$numtim (&NumTime, binptr); sprintf (stamp, "%04.04d%02.02d%02.02d%02.02d%02.02d%02.02d%02.02d", NumTime[0], NumTime[1], NumTime[2], NumTime[3], NumTime[4], NumTime[5], NumTime[6]); return (stamp); } /*****************************************************************************/