1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. |
9 | * |
10 | * This software is licensed as described in the file COPYING, which |
11 | * you should have received as part of this distribution. The terms |
12 | * are also available at https://curl.haxx.se/docs/copyright.html. |
13 | * |
14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
15 | * copies of the Software, and permit persons to whom the Software is |
16 | * furnished to do so, under the terms of the COPYING file. |
17 | * |
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
19 | * KIND, either express or implied. |
20 | * |
21 | ***************************************************************************/ |
22 | #include "tool_setup.h" |
23 | |
24 | #ifdef __VMS |
25 | |
26 | #if defined(__DECC) && !defined(__VAX) && \ |
27 | defined(__CRTL_VER) && (__CRTL_VER >= 70301000) |
28 | #include <unixlib.h> |
29 | #endif |
30 | |
31 | #define ENABLE_CURLX_PRINTF |
32 | #include "curlx.h" |
33 | |
34 | #include "curlmsg_vms.h" |
35 | #include "tool_vms.h" |
36 | |
37 | #include "memdebug.h" /* keep this as LAST include */ |
38 | |
39 | void decc$__posix_exit(int __status); |
40 | void decc$exit(int __status); |
41 | |
42 | static int vms_shell = -1; |
43 | |
44 | /* VMS has a DCL shell and and also has Unix shells ported to it. |
45 | * When curl is running under a Unix shell, we want it to be as much |
46 | * like Unix as possible. |
47 | */ |
48 | int is_vms_shell(void) |
49 | { |
50 | char *shell; |
51 | |
52 | /* Have we checked the shell yet? */ |
53 | if(vms_shell >= 0) |
54 | return vms_shell; |
55 | |
56 | shell = getenv("SHELL" ); |
57 | |
58 | /* No shell, means DCL */ |
59 | if(shell == NULL) { |
60 | vms_shell = 1; |
61 | return 1; |
62 | } |
63 | |
64 | /* Have to make sure some one did not set shell to DCL */ |
65 | if(strcmp(shell, "DCL" ) == 0) { |
66 | vms_shell = 1; |
67 | return 1; |
68 | } |
69 | |
70 | vms_shell = 0; |
71 | return 0; |
72 | } |
73 | |
74 | /* |
75 | * VMS has two exit() routines. When running under a Unix style shell, then |
76 | * Unix style and the __posix_exit() routine is used. |
77 | * |
78 | * When running under the DCL shell, then the VMS encoded codes and decc$exit() |
79 | * is used. |
80 | * |
81 | * We can not use exit() or return a code from main() because the actual |
82 | * routine called depends on both the compiler version, compile options, and |
83 | * feature macro settings, and one of the exit routines is hidden at compile |
84 | * time. |
85 | * |
86 | * Since we want Curl to work properly under the VMS DCL shell and Unix |
87 | * shells under VMS, this routine should compile correctly regardless of |
88 | * the settings. |
89 | */ |
90 | |
91 | void vms_special_exit(int code, int vms_show) |
92 | { |
93 | int vms_code; |
94 | |
95 | /* The Posix exit mode is only available after VMS 7.0 */ |
96 | #if __CRTL_VER >= 70000000 |
97 | if(is_vms_shell() == 0) { |
98 | decc$__posix_exit(code); |
99 | } |
100 | #endif |
101 | |
102 | if(code > CURL_LAST) { /* If CURL_LAST exceeded then */ |
103 | vms_code = CURL_LAST; /* curlmsg.h is out of sync. */ |
104 | } |
105 | else { |
106 | vms_code = vms_cond[code] | vms_show; |
107 | } |
108 | decc$exit(vms_code); |
109 | } |
110 | |
111 | #if defined(__DECC) && !defined(__VAX) && \ |
112 | defined(__CRTL_VER) && (__CRTL_VER >= 70301000) |
113 | |
114 | /* |
115 | * 2004-09-19 SMS. |
116 | * |
117 | * decc_init() |
118 | * |
119 | * On non-VAX systems, use LIB$INITIALIZE to set a collection of C |
120 | * RTL features without using the DECC$* logical name method, nor |
121 | * requiring the user to define the corresponding logical names. |
122 | */ |
123 | |
124 | /* Structure to hold a DECC$* feature name and its desired value. */ |
125 | typedef struct { |
126 | char *name; |
127 | int value; |
128 | } decc_feat_t; |
129 | |
130 | /* Array of DECC$* feature names and their desired values. */ |
131 | static decc_feat_t decc_feat_array[] = { |
132 | /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */ |
133 | { "DECC$ARGV_PARSE_STYLE" , 1 }, |
134 | /* Preserve case for file names on ODS5 disks. */ |
135 | { "DECC$EFS_CASE_PRESERVE" , 1 }, |
136 | /* Enable multiple dots (and most characters) in ODS5 file names, |
137 | while preserving VMS-ness of ";version". */ |
138 | { "DECC$EFS_CHARSET" , 1 }, |
139 | /* List terminator. */ |
140 | { (char *)NULL, 0 } |
141 | }; |
142 | |
143 | /* Flag to sense if decc_init() was called. */ |
144 | static int decc_init_done = -1; |
145 | |
146 | /* LIB$INITIALIZE initialization function. */ |
147 | static void decc_init(void) |
148 | { |
149 | int feat_index; |
150 | int feat_value; |
151 | int feat_value_max; |
152 | int feat_value_min; |
153 | int i; |
154 | int sts; |
155 | |
156 | /* Set the global flag to indicate that LIB$INITIALIZE worked. */ |
157 | decc_init_done = 1; |
158 | |
159 | /* Loop through all items in the decc_feat_array[]. */ |
160 | for(i = 0; decc_feat_array[i].name != NULL; i++) { |
161 | |
162 | /* Get the feature index. */ |
163 | feat_index = decc$feature_get_index(decc_feat_array[i].name); |
164 | |
165 | if(feat_index >= 0) { |
166 | /* Valid item. Collect its properties. */ |
167 | feat_value = decc$feature_get_value(feat_index, 1); |
168 | feat_value_min = decc$feature_get_value(feat_index, 2); |
169 | feat_value_max = decc$feature_get_value(feat_index, 3); |
170 | |
171 | if((decc_feat_array[i].value >= feat_value_min) && |
172 | (decc_feat_array[i].value <= feat_value_max)) { |
173 | /* Valid value. Set it if necessary. */ |
174 | if(feat_value != decc_feat_array[i].value) { |
175 | sts = decc$feature_set_value(feat_index, 1, |
176 | decc_feat_array[i].value); |
177 | } |
178 | } |
179 | else { |
180 | /* Invalid DECC feature value. */ |
181 | printf(" INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n" , |
182 | feat_value, |
183 | feat_value_min, decc_feat_array[i].name, feat_value_max); |
184 | } |
185 | } |
186 | else { |
187 | /* Invalid DECC feature name. */ |
188 | printf(" UNKNOWN DECC FEATURE: %s.\n" , decc_feat_array[i].name); |
189 | } |
190 | |
191 | } |
192 | } |
193 | |
194 | /* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */ |
195 | |
196 | #pragma nostandard |
197 | |
198 | /* Establish the LIB$INITIALIZE PSECTs, with proper alignment and |
199 | other attributes. Note that "nopic" is significant only on VAX. */ |
200 | #pragma extern_model save |
201 | #pragma extern_model strict_refdef "LIB$INITIALIZ" 2, nopic, nowrt |
202 | const int spare[8] = {0}; |
203 | #pragma extern_model strict_refdef "LIB$INITIALIZE" 2, nopic, nowrt |
204 | void (*const x_decc_init)() = decc_init; |
205 | #pragma extern_model restore |
206 | |
207 | /* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */ |
208 | #pragma extern_model save |
209 | int LIB$INITIALIZE(void); |
210 | #pragma extern_model strict_refdef |
211 | int dmy_lib$initialize = (int) LIB$INITIALIZE; |
212 | #pragma extern_model restore |
213 | |
214 | #pragma standard |
215 | |
216 | #endif /* __DECC && !__VAX && __CRTL_VER && __CRTL_VER >= 70301000 */ |
217 | |
218 | #endif /* __VMS */ |
219 | |