/*****************************************************************************/ /* (wu)util.c Module name says it all. COPYRIGHT --------- Copyright (C) 2020,2024 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 --------------- 20-APR-2021 MGD rework doasprintf(), asprintf(), vasprintf() 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); } /*****************************************************************************/ /* Rude and crude (but works). */ char* doasprintf (char *fmt, ...) { int cnt; char *cptr; va_list aptr; va_start(aptr, fmt); cnt = vasprintf (&cptr, (const char*)fmt, aptr); va_end(aptr); return (cnt < 0 ? NULL : cptr); } /*****************************************************************************/ /* 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); } /*****************************************************************************/ /* */ int wucme_asprintf ( char **sptr, const char *fmt, ... ) { int cnt; va_list aptr; char buf [8192]; va_start(aptr, fmt); cnt = vsnprintf (buf, sizeof(buf), fmt, aptr); if (cnt >= 0 && sptr) *sptr = strdup(buf); va_end(aptr); return (cnt); } /*****************************************************************************/ /* Rude and crude (but works). */ int wucme_vasprintf ( char **sptr, const char *fmt, va_list aptr ) { int cnt; char buf [8192]; cnt = vsnprintf (buf, sizeof(buf), fmt, aptr); if (cnt >= 0 && sptr) *sptr = strdup(buf); return (cnt); } /*****************************************************************************/ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. */ char * wucme_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); } /*****************************************************************************/ /* 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); } /*****************************************************************************/