1/* File: curl_crtl_init.c 2 * 3 * This file makes sure that the DECC Unix settings are correct for 4 * the mode the the program is run in. 5 * 6 * The CRTL has not been initialized at the time that these routines 7 * are called, so many routines can not be called. 8 * 9 * This is a module that provides a LIB$INITIALIZE routine that 10 * will turn on some CRTL features that are not enabled by default. 11 * 12 * The CRTL features can also be turned on via logical names, but that 13 * impacts all programs and some aren't ready, willing, or able to handle 14 * those settings. 15 * 16 * On VMS versions that are too old to use the feature setting API, this 17 * module falls back to using logical names. 18 * 19 * Copyright 2013, John Malmberg 20 * 21 * Permission to use, copy, modify, and/or distribute this software for any 22 * purpose with or without fee is hereby granted, provided that the above 23 * copyright notice and this permission notice appear in all copies. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 26 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 28 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 31 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 32 * 33 */ 34 35/* Unix headers */ 36#include <stdio.h> 37#include <string.h> 38 39/* VMS specific headers */ 40#include <descrip.h> 41#include <lnmdef.h> 42#include <stsdef.h> 43 44#pragma member_alignment save 45#pragma nomember_alignment longword 46#pragma message save 47#pragma message disable misalgndmem 48struct itmlst_3 { 49 unsigned short int buflen; 50 unsigned short int itmcode; 51 void *bufadr; 52 unsigned short int *retlen; 53}; 54#pragma message restore 55#pragma member_alignment restore 56 57#ifdef __VAX 58#define ENABLE "ENABLE" 59#define DISABLE "DISABLE" 60#else 61 62#define ENABLE TRUE 63#define DISABLE 0 64int decc$feature_get_index (const char *name); 65int decc$feature_set_value (int index, int mode, int value); 66#endif 67 68int SYS$TRNLNM( 69 const unsigned long * attr, 70 const struct dsc$descriptor_s * table_dsc, 71 struct dsc$descriptor_s * name_dsc, 72 const unsigned char * acmode, 73 const struct itmlst_3 * item_list); 74int SYS$CRELNM( 75 const unsigned long * attr, 76 const struct dsc$descriptor_s * table_dsc, 77 const struct dsc$descriptor_s * name_dsc, 78 const unsigned char * acmode, 79 const struct itmlst_3 * item_list); 80 81 82/* Take all the fun out of simply looking up a logical name */ 83static int sys_trnlnm 84 (const char * logname, 85 char * value, 86 int value_len) 87{ 88 const $DESCRIPTOR(table_dsc, "LNM$FILE_DEV"); 89 const unsigned long attr = LNM$M_CASE_BLIND; 90 struct dsc$descriptor_s name_dsc; 91 int status; 92 unsigned short result; 93 struct itmlst_3 itlst[2]; 94 95 itlst[0].buflen = value_len; 96 itlst[0].itmcode = LNM$_STRING; 97 itlst[0].bufadr = value; 98 itlst[0].retlen = &result; 99 100 itlst[1].buflen = 0; 101 itlst[1].itmcode = 0; 102 103 name_dsc.dsc$w_length = strlen(logname); 104 name_dsc.dsc$a_pointer = (char *)logname; 105 name_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 106 name_dsc.dsc$b_class = DSC$K_CLASS_S; 107 108 status = SYS$TRNLNM(&attr, &table_dsc, &name_dsc, 0, itlst); 109 110 if ($VMS_STATUS_SUCCESS(status)) { 111 112 /* Null terminate and return the string */ 113 /*--------------------------------------*/ 114 value[result] = '\0'; 115 } 116 117 return status; 118} 119 120/* How to simply create a logical name */ 121static int sys_crelnm 122 (const char * logname, 123 const char * value) 124{ 125 int ret_val; 126 const char * proc_table = "LNM$PROCESS_TABLE"; 127 struct dsc$descriptor_s proc_table_dsc; 128 struct dsc$descriptor_s logname_dsc; 129 struct itmlst_3 item_list[2]; 130 131 proc_table_dsc.dsc$a_pointer = (char *) proc_table; 132 proc_table_dsc.dsc$w_length = strlen(proc_table); 133 proc_table_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 134 proc_table_dsc.dsc$b_class = DSC$K_CLASS_S; 135 136 logname_dsc.dsc$a_pointer = (char *) logname; 137 logname_dsc.dsc$w_length = strlen(logname); 138 logname_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 139 logname_dsc.dsc$b_class = DSC$K_CLASS_S; 140 141 item_list[0].buflen = strlen(value); 142 item_list[0].itmcode = LNM$_STRING; 143 item_list[0].bufadr = (char *)value; 144 item_list[0].retlen = NULL; 145 146 item_list[1].buflen = 0; 147 item_list[1].itmcode = 0; 148 149 ret_val = SYS$CRELNM(NULL, &proc_table_dsc, &logname_dsc, NULL, item_list); 150 151 return ret_val; 152} 153 154 155 /* Start of DECC RTL Feature handling */ 156 157/* 158** Sets default value for a feature 159*/ 160#ifdef __VAX 161static void set_feature_default(const char *name, const char *value) 162{ 163 sys_crelnm(name, value); 164} 165#else 166static void set_feature_default(const char *name, int value) 167{ 168 int index; 169 170 index = decc$feature_get_index(name); 171 172 if (index > 0) 173 decc$feature_set_value (index, 0, value); 174} 175#endif 176 177static void set_features(void) 178{ 179 int status; 180 char unix_shell_name[255]; 181 int use_unix_settings = 1; 182 183 status = sys_trnlnm("GNV$UNIX_SHELL", 184 unix_shell_name, sizeof unix_shell_name -1); 185 if (!$VMS_STATUS_SUCCESS(status)) { 186 unix_shell_name[0] = 0; 187 use_unix_settings = 0; 188 } 189 190 /* ACCESS should check ACLs or it is lying. */ 191 set_feature_default("DECC$ACL_ACCESS_CHECK", ENABLE); 192 193 /* We always want the new parse style */ 194 set_feature_default ("DECC$ARGV_PARSE_STYLE" , ENABLE); 195 196 197 /* Unless we are in POSIX compliant mode, we want the old POSIX root 198 * enabled. 199 */ 200 set_feature_default("DECC$DISABLE_POSIX_ROOT", DISABLE); 201 202 /* EFS charset, means UTF-8 support */ 203 /* VTF-7 support is controlled by a feature setting called UTF8 */ 204 set_feature_default ("DECC$EFS_CHARSET", ENABLE); 205 set_feature_default ("DECC$EFS_CASE_PRESERVE", ENABLE); 206 207 /* Support timestamps when available */ 208 set_feature_default ("DECC$EFS_FILE_TIMESTAMPS", ENABLE); 209 210 /* Cache environment variables - performance improvements */ 211 set_feature_default ("DECC$ENABLE_GETENV_CACHE", ENABLE); 212 213 /* Start out with new file attribute inheritance */ 214#ifdef __VAX 215 set_feature_default ("DECC$EXEC_FILEATTR_INHERITANCE", "2"); 216#else 217 set_feature_default ("DECC$EXEC_FILEATTR_INHERITANCE", 2); 218#endif 219 220 /* Don't display trailing dot after files without type */ 221 set_feature_default ("DECC$READDIR_DROPDOTNOTYPE", ENABLE); 222 223 /* For standard output channels buffer output until terminator */ 224 /* Gets rid of output logs with single character lines in them. */ 225 set_feature_default ("DECC$STDIO_CTX_EOL", ENABLE); 226 227 /* Fix mv aa.bb aa */ 228 set_feature_default ("DECC$RENAME_NO_INHERIT", ENABLE); 229 230 if (use_unix_settings) { 231 232 /* POSIX requires that open files be able to be removed */ 233 set_feature_default ("DECC$ALLOW_REMOVE_OPEN_FILES", ENABLE); 234 235 /* Default to outputting Unix filenames in VMS routines */ 236 set_feature_default ("DECC$FILENAME_UNIX_ONLY", ENABLE); 237 /* FILENAME_UNIX_ONLY Implicitly sets */ 238 /* decc$disable_to_vms_logname_translation */ 239 240 set_feature_default ("DECC$FILE_PERMISSION_UNIX", ENABLE); 241 242 set_feature_default ("DECC$FILE_SHARING", ENABLE); 243 244 set_feature_default ("DECC$FILE_OWNER_UNIX", ENABLE); 245 set_feature_default ("DECC$POSIX_SEEK_STREAM_FILE", ENABLE); 246 247 } else { 248 set_feature_default("DECC$FILENAME_UNIX_REPORT", ENABLE); 249 } 250 251 /* When reporting Unix filenames, glob the same way */ 252 set_feature_default ("DECC$GLOB_UNIX_STYLE", ENABLE); 253 254 /* The VMS version numbers on Unix filenames is incompatible with most */ 255 /* ported packages. */ 256 set_feature_default("DECC$FILENAME_UNIX_NO_VERSION", ENABLE); 257 258 /* The VMS version numbers on Unix filenames is incompatible with most */ 259 /* ported packages. */ 260 set_feature_default("DECC$UNIX_PATH_BEFORE_LOGNAME", ENABLE); 261 262 /* Set strtol to proper behavior */ 263 set_feature_default("DECC$STRTOL_ERANGE", ENABLE); 264 265 /* Commented here to prevent future bugs: A program or user should */ 266 /* never ever enable DECC$POSIX_STYLE_UID. */ 267 /* It will probably break all code that accesses UIDs */ 268 /* do_not_set_default ("DECC$POSIX_STYLE_UID", TRUE); */ 269} 270 271 272/* Some boilerplate to force this to be a proper LIB$INITIALIZE section */ 273 274#pragma nostandard 275#pragma extern_model save 276#ifdef __VAX 277#pragma extern_model strict_refdef "LIB$INITIALIZE" nowrt, long, nopic 278#else 279#pragma extern_model strict_refdef "LIB$INITIALIZE" nowrt, long 280# if __INITIAL_POINTER_SIZE 281# pragma __pointer_size __save 282# pragma __pointer_size 32 283# else 284# pragma __required_pointer_size __save 285# pragma __required_pointer_size 32 286# endif 287#endif 288/* Set our contribution to the LIB$INITIALIZE array */ 289void (* const iniarray[])(void) = {set_features, } ; 290#ifndef __VAX 291# if __INITIAL_POINTER_SIZE 292# pragma __pointer_size __restore 293# else 294# pragma __required_pointer_size __restore 295# endif 296#endif 297 298 299/* 300** Force a reference to LIB$INITIALIZE to ensure it 301** exists in the image. 302*/ 303int LIB$INITIALIZE(void); 304#ifdef __DECC 305#pragma extern_model strict_refdef 306#endif 307 int lib_init_ref = (int) LIB$INITIALIZE; 308#ifdef __DECC 309#pragma extern_model restore 310#pragma standard 311#endif 312