/* File: curl_crtl_init.c * * This file makes sure that the DECC Unix settings are correct for * the mode the the program is run in. * * The CRTL has not been initialized at the time that these routines * are called, so many routines can not be called. * * This is a module that provides a LIB$INITIALIZE routine that * will turn on some CRTL features that are not enabled by default. * * The CRTL features can also be turned on via logical names, but that * impacts all programs and some aren't ready, willing, or able to handle * those settings. * * On VMS versions that are too old to use the feature setting API, this * module falls back to using logical names. * * Copyright 2013, John Malmberg * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ /* Unix headers */ #include <stdio.h> #include <string.h> /* VMS specific headers */ #include <descrip.h> #include <lnmdef.h> #include <stsdef.h> #pragma member_alignment save #pragma nomember_alignment longword #pragma message save #pragma message disable misalgndmem struct itmlst_3 { unsigned short int buflen; unsigned short int itmcode; void *bufadr; unsigned short int *retlen; }; #pragma message restore #pragma member_alignment restore #ifdef __VAX #define ENABLE "ENABLE" #define DISABLE "DISABLE" #else #define ENABLE TRUE #define DISABLE 0 int decc$feature_get_index (const char *name); int decc$feature_set_value (int index, int mode, int value); #endif int SYS$TRNLNM( const unsigned long * attr, const struct dsc$descriptor_s * table_dsc, struct dsc$descriptor_s * name_dsc, const unsigned char * acmode, const struct itmlst_3 * item_list); int SYS$CRELNM( const unsigned long * attr, const struct dsc$descriptor_s * table_dsc, const struct dsc$descriptor_s * name_dsc, const unsigned char * acmode, const struct itmlst_3 * item_list); /* Take all the fun out of simply looking up a logical name */ static int sys_trnlnm (const char * logname, char * value, int value_len) { const $DESCRIPTOR(table_dsc, "LNM$FILE_DEV"); const unsigned long attr = LNM$M_CASE_BLIND; struct dsc$descriptor_s name_dsc; int status; unsigned short result; struct itmlst_3 itlst[2]; itlst[0].buflen = value_len; itlst[0].itmcode = LNM$_STRING; itlst[0].bufadr = value; itlst[0].retlen = &result; itlst[1].buflen = 0; itlst[1].itmcode = 0; name_dsc.dsc$w_length = strlen(logname); name_dsc.dsc$a_pointer = (char *)logname; name_dsc.dsc$b_dtype = DSC$K_DTYPE_T; name_dsc.dsc$b_class = DSC$K_CLASS_S; status = SYS$TRNLNM(&attr, &table_dsc, &name_dsc, 0, itlst); if ($VMS_STATUS_SUCCESS(status)) { /* Null terminate and return the string */ /*--------------------------------------*/ value[result] = '\0'; } return status; } /* How to simply create a logical name */ static int sys_crelnm (const char * logname, const char * value) { int ret_val; const char * proc_table = "LNM$PROCESS_TABLE"; struct dsc$descriptor_s proc_table_dsc; struct dsc$descriptor_s logname_dsc; struct itmlst_3 item_list[2]; proc_table_dsc.dsc$a_pointer = (char *) proc_table; proc_table_dsc.dsc$w_length = strlen(proc_table); proc_table_dsc.dsc$b_dtype = DSC$K_DTYPE_T; proc_table_dsc.dsc$b_class = DSC$K_CLASS_S; logname_dsc.dsc$a_pointer = (char *) logname; logname_dsc.dsc$w_length = strlen(logname); logname_dsc.dsc$b_dtype = DSC$K_DTYPE_T; logname_dsc.dsc$b_class = DSC$K_CLASS_S; item_list[0].buflen = strlen(value); item_list[0].itmcode = LNM$_STRING; item_list[0].bufadr = (char *)value; item_list[0].retlen = NULL; item_list[1].buflen = 0; item_list[1].itmcode = 0; ret_val = SYS$CRELNM(NULL, &proc_table_dsc, &logname_dsc, NULL, item_list); return ret_val; } /* Start of DECC RTL Feature handling */ /* ** Sets default value for a feature */ #ifdef __VAX static void set_feature_default(const char *name, const char *value) { sys_crelnm(name, value); } #else static void set_feature_default(const char *name, int value) { int index; index = decc$feature_get_index(name); if (index > 0) decc$feature_set_value (index, 0, value); } #endif static void set_features(void) { int status; char unix_shell_name[255]; int use_unix_settings = 1; status = sys_trnlnm("GNV$UNIX_SHELL", unix_shell_name, sizeof unix_shell_name -1); if (!$VMS_STATUS_SUCCESS(status)) { unix_shell_name[0] = 0; use_unix_settings = 0; } /* ACCESS should check ACLs or it is lying. */ set_feature_default("DECC$ACL_ACCESS_CHECK", ENABLE); /* We always want the new parse style */ set_feature_default ("DECC$ARGV_PARSE_STYLE" , ENABLE); /* Unless we are in POSIX compliant mode, we want the old POSIX root * enabled. */ set_feature_default("DECC$DISABLE_POSIX_ROOT", DISABLE); /* EFS charset, means UTF-8 support */ /* VTF-7 support is controlled by a feature setting called UTF8 */ set_feature_default ("DECC$EFS_CHARSET", ENABLE); set_feature_default ("DECC$EFS_CASE_PRESERVE", ENABLE); /* Support timestamps when available */ set_feature_default ("DECC$EFS_FILE_TIMESTAMPS", ENABLE); /* Cache environment variables - performance improvements */ set_feature_default ("DECC$ENABLE_GETENV_CACHE", ENABLE); /* Start out with new file attribute inheritance */ #ifdef __VAX set_feature_default ("DECC$EXEC_FILEATTR_INHERITANCE", "2"); #else set_feature_default ("DECC$EXEC_FILEATTR_INHERITANCE", 2); #endif /* Don't display trailing dot after files without type */ set_feature_default ("DECC$READDIR_DROPDOTNOTYPE", ENABLE); /* For standard output channels buffer output until terminator */ /* Gets rid of output logs with single character lines in them. */ set_feature_default ("DECC$STDIO_CTX_EOL", ENABLE); /* Fix mv aa.bb aa */ set_feature_default ("DECC$RENAME_NO_INHERIT", ENABLE); if (use_unix_settings) { /* POSIX requires that open files be able to be removed */ set_feature_default ("DECC$ALLOW_REMOVE_OPEN_FILES", ENABLE); /* Default to outputting Unix filenames in VMS routines */ set_feature_default ("DECC$FILENAME_UNIX_ONLY", ENABLE); /* FILENAME_UNIX_ONLY Implicitly sets */ /* decc$disable_to_vms_logname_translation */ set_feature_default ("DECC$FILE_PERMISSION_UNIX", ENABLE); set_feature_default ("DECC$FILE_SHARING", ENABLE); set_feature_default ("DECC$FILE_OWNER_UNIX", ENABLE); set_feature_default ("DECC$POSIX_SEEK_STREAM_FILE", ENABLE); } else { set_feature_default("DECC$FILENAME_UNIX_REPORT", ENABLE); } /* When reporting Unix filenames, glob the same way */ set_feature_default ("DECC$GLOB_UNIX_STYLE", ENABLE); /* The VMS version numbers on Unix filenames is incompatible with most */ /* ported packages. */ set_feature_default("DECC$FILENAME_UNIX_NO_VERSION", ENABLE); /* The VMS version numbers on Unix filenames is incompatible with most */ /* ported packages. */ set_feature_default("DECC$UNIX_PATH_BEFORE_LOGNAME", ENABLE); /* Set strtol to proper behavior */ set_feature_default("DECC$STRTOL_ERANGE", ENABLE); /* Commented here to prevent future bugs: A program or user should */ /* never ever enable DECC$POSIX_STYLE_UID. */ /* It will probably break all code that accesses UIDs */ /* do_not_set_default ("DECC$POSIX_STYLE_UID", TRUE); */ } /* Some boilerplate to force this to be a proper LIB$INITIALIZE section */ #pragma nostandard #pragma extern_model save #ifdef __VAX #pragma extern_model strict_refdef "LIB$INITIALIZE" nowrt, long, nopic #else #pragma extern_model strict_refdef "LIB$INITIALIZE" nowrt, long # if __INITIAL_POINTER_SIZE # pragma __pointer_size __save # pragma __pointer_size 32 # else # pragma __required_pointer_size __save # pragma __required_pointer_size 32 # endif #endif /* Set our contribution to the LIB$INITIALIZE array */ void (* const iniarray[])(void) = {set_features, } ; #ifndef __VAX # if __INITIAL_POINTER_SIZE # pragma __pointer_size __restore # else # pragma __required_pointer_size __restore # endif #endif /* ** Force a reference to LIB$INITIALIZE to ensure it ** exists in the image. */ int LIB$INITIALIZE(void); #ifdef __DECC #pragma extern_model strict_refdef #endif int lib_init_ref = (int) LIB$INITIALIZE; #ifdef __DECC #pragma extern_model restore #pragma standard #endif