1*4724848cSchristos /*
2*4724848cSchristos * Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved.
3*4724848cSchristos *
4*4724848cSchristos * Licensed under the OpenSSL license (the "License"). You may not use
5*4724848cSchristos * this file except in compliance with the License. You can obtain a copy
6*4724848cSchristos * in the file LICENSE in the source distribution or at
7*4724848cSchristos * https://www.openssl.org/source/license.html
8*4724848cSchristos */
9*4724848cSchristos
10c9496f6bSchristos #if defined( __VMS) && !defined( OPENSSL_NO_DECC_INIT) && \
11c9496f6bSchristos defined( __DECC) && !defined( __VAX) && (__CRTL_VER >= 70301000)
12c9496f6bSchristos # define USE_DECC_INIT 1
13c9496f6bSchristos #endif
14c9496f6bSchristos
15c9496f6bSchristos #ifdef USE_DECC_INIT
16c9496f6bSchristos
17*4724848cSchristos /*
18c9496f6bSchristos * ----------------------------------------------------------------------
19*4724848cSchristos * decc_init() On non-VAX systems, uses LIB$INITIALIZE to set a collection
20*4724848cSchristos * of C RTL features without using the DECC$* logical name method.
21c9496f6bSchristos * ----------------------------------------------------------------------
22c9496f6bSchristos */
23c9496f6bSchristos
24c9496f6bSchristos # include <stdio.h>
25c9496f6bSchristos # include <stdlib.h>
26c9496f6bSchristos # include <unixlib.h>
27c9496f6bSchristos
28c9496f6bSchristos /* Global storage. */
29c9496f6bSchristos
30c9496f6bSchristos /* Flag to sense if decc_init() was called. */
31c9496f6bSchristos
32c9496f6bSchristos int decc_init_done = -1;
33c9496f6bSchristos
34c9496f6bSchristos /* Structure to hold a DECC$* feature name and its desired value. */
35c9496f6bSchristos
36c9496f6bSchristos typedef struct {
37c9496f6bSchristos char *name;
38c9496f6bSchristos int value;
39c9496f6bSchristos } decc_feat_t;
40c9496f6bSchristos
41c9496f6bSchristos /*
42c9496f6bSchristos * Array of DECC$* feature names and their desired values. Note:
43c9496f6bSchristos * DECC$ARGV_PARSE_STYLE is the urgent one.
44c9496f6bSchristos */
45c9496f6bSchristos
46c9496f6bSchristos decc_feat_t decc_feat_array[] = {
47c9496f6bSchristos /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
48c9496f6bSchristos {"DECC$ARGV_PARSE_STYLE", 1},
49c9496f6bSchristos
50c9496f6bSchristos /* Preserve case for file names on ODS5 disks. */
51c9496f6bSchristos {"DECC$EFS_CASE_PRESERVE", 1},
52c9496f6bSchristos
53c9496f6bSchristos /*
54c9496f6bSchristos * Enable multiple dots (and most characters) in ODS5 file names, while
55c9496f6bSchristos * preserving VMS-ness of ";version".
56c9496f6bSchristos */
57c9496f6bSchristos {"DECC$EFS_CHARSET", 1},
58c9496f6bSchristos
59c9496f6bSchristos /* List terminator. */
60c9496f6bSchristos {(char *)NULL, 0}
61c9496f6bSchristos };
62c9496f6bSchristos
63*4724848cSchristos
64c9496f6bSchristos /* LIB$INITIALIZE initialization function. */
65c9496f6bSchristos
decc_init(void)66c9496f6bSchristos static void decc_init(void)
67c9496f6bSchristos {
68c9496f6bSchristos char *openssl_debug_decc_init;
69c9496f6bSchristos int verbose = 0;
70c9496f6bSchristos int feat_index;
71c9496f6bSchristos int feat_value;
72c9496f6bSchristos int feat_value_max;
73c9496f6bSchristos int feat_value_min;
74c9496f6bSchristos int i;
75c9496f6bSchristos int sts;
76c9496f6bSchristos
77c9496f6bSchristos /* Get debug option. */
78c9496f6bSchristos openssl_debug_decc_init = getenv("OPENSSL_DEBUG_DECC_INIT");
79c9496f6bSchristos if (openssl_debug_decc_init != NULL) {
80c9496f6bSchristos verbose = strtol(openssl_debug_decc_init, NULL, 10);
81c9496f6bSchristos if (verbose <= 0) {
82c9496f6bSchristos verbose = 1;
83c9496f6bSchristos }
84c9496f6bSchristos }
85c9496f6bSchristos
86c9496f6bSchristos /* Set the global flag to indicate that LIB$INITIALIZE worked. */
87c9496f6bSchristos decc_init_done = 1;
88c9496f6bSchristos
89c9496f6bSchristos /* Loop through all items in the decc_feat_array[]. */
90c9496f6bSchristos
91c9496f6bSchristos for (i = 0; decc_feat_array[i].name != NULL; i++) {
92c9496f6bSchristos /* Get the feature index. */
93c9496f6bSchristos feat_index = decc$feature_get_index(decc_feat_array[i].name);
94c9496f6bSchristos if (feat_index >= 0) {
95c9496f6bSchristos /* Valid item. Collect its properties. */
96c9496f6bSchristos feat_value = decc$feature_get_value(feat_index, 1);
97c9496f6bSchristos feat_value_min = decc$feature_get_value(feat_index, 2);
98c9496f6bSchristos feat_value_max = decc$feature_get_value(feat_index, 3);
99c9496f6bSchristos
100c9496f6bSchristos /* Check the validity of our desired value. */
101c9496f6bSchristos if ((decc_feat_array[i].value >= feat_value_min) &&
102c9496f6bSchristos (decc_feat_array[i].value <= feat_value_max)) {
103c9496f6bSchristos /* Valid value. Set it if necessary. */
104c9496f6bSchristos if (feat_value != decc_feat_array[i].value) {
105c9496f6bSchristos sts = decc$feature_set_value(feat_index,
106c9496f6bSchristos 1, decc_feat_array[i].value);
107c9496f6bSchristos
108c9496f6bSchristos if (verbose > 1) {
109c9496f6bSchristos fprintf(stderr, " %s = %d, sts = %d.\n",
110c9496f6bSchristos decc_feat_array[i].name,
111c9496f6bSchristos decc_feat_array[i].value, sts);
112c9496f6bSchristos }
113c9496f6bSchristos }
114c9496f6bSchristos } else {
115c9496f6bSchristos /* Invalid DECC feature value. */
116c9496f6bSchristos fprintf(stderr,
117c9496f6bSchristos " INVALID DECC$FEATURE VALUE, %d: %d <= %s <= %d.\n",
118c9496f6bSchristos feat_value,
119c9496f6bSchristos feat_value_min, decc_feat_array[i].name,
120c9496f6bSchristos feat_value_max);
121c9496f6bSchristos }
122c9496f6bSchristos } else {
123c9496f6bSchristos /* Invalid DECC feature name. */
124c9496f6bSchristos fprintf(stderr,
125c9496f6bSchristos " UNKNOWN DECC$FEATURE: %s.\n", decc_feat_array[i].name);
126c9496f6bSchristos }
127c9496f6bSchristos }
128c9496f6bSchristos
129c9496f6bSchristos if (verbose > 0) {
130c9496f6bSchristos fprintf(stderr, " DECC_INIT complete.\n");
131c9496f6bSchristos }
132c9496f6bSchristos }
133c9496f6bSchristos
134c9496f6bSchristos /* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
135c9496f6bSchristos
136c9496f6bSchristos # pragma nostandard
137c9496f6bSchristos
138c9496f6bSchristos /*
139c9496f6bSchristos * Establish the LIB$INITIALIZE PSECTs, with proper alignment and other
140c9496f6bSchristos * attributes. Note that "nopic" is significant only on VAX.
141c9496f6bSchristos */
142c9496f6bSchristos # pragma extern_model save
143c9496f6bSchristos
144c9496f6bSchristos # if __INITIAL_POINTER_SIZE == 64
145c9496f6bSchristos # define PSECT_ALIGN 3
146c9496f6bSchristos # else
147c9496f6bSchristos # define PSECT_ALIGN 2
148c9496f6bSchristos # endif
149c9496f6bSchristos
150c9496f6bSchristos # pragma extern_model strict_refdef "LIB$INITIALIZ" PSECT_ALIGN, nopic, nowrt
151c9496f6bSchristos const int spare[8] = { 0 };
152c9496f6bSchristos
153c9496f6bSchristos # pragma extern_model strict_refdef "LIB$INITIALIZE" PSECT_ALIGN, nopic, nowrt
154c9496f6bSchristos void (*const x_decc_init) () = decc_init;
155c9496f6bSchristos
156c9496f6bSchristos # pragma extern_model restore
157c9496f6bSchristos
158c9496f6bSchristos /* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
159c9496f6bSchristos
160c9496f6bSchristos # pragma extern_model save
161c9496f6bSchristos
162c9496f6bSchristos int LIB$INITIALIZE(void);
163c9496f6bSchristos
164c9496f6bSchristos # pragma extern_model strict_refdef
165c9496f6bSchristos int dmy_lib$initialize = (int)LIB$INITIALIZE;
166c9496f6bSchristos
167c9496f6bSchristos # pragma extern_model restore
168c9496f6bSchristos
169c9496f6bSchristos # pragma standard
170c9496f6bSchristos
171c9496f6bSchristos #else /* def USE_DECC_INIT */
172c9496f6bSchristos
173c9496f6bSchristos /* Dummy code to avoid a %CC-W-EMPTYFILE complaint. */
174c9496f6bSchristos int decc_init_dummy(void);
175c9496f6bSchristos
176c9496f6bSchristos #endif /* def USE_DECC_INIT */
177