aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/src/tool_vms.c
blob: 36d05870c94e06fcd860cc0d0891387ef00f58a1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 * SPDX-License-Identifier: curl
 *
 ***************************************************************************/
#include "tool_setup.h"

#ifdef __VMS

#if defined(__DECC) && !defined(__VAX) && \
    defined(__CRTL_VER) && (__CRTL_VER >= 70301000)
#include <unixlib.h>
#endif

#include "curlx.h"

#error #include "curlmsg_vms.h"
#include "tool_vms.h"

#include "memdebug.h" /* keep this as LAST include */

void decc$__posix_exit(int __status);
void decc$exit(int __status);

static int vms_shell = -1;

/* VMS has a DCL shell and also has Unix shells ported to it.
 * When curl is running under a Unix shell, we want it to be as much
 * like Unix as possible.
 */
int is_vms_shell(void)
{
  char *shell;

  /* Have we checked the shell yet? */
  if(vms_shell >= 0)
    return vms_shell;

  shell = getenv("SHELL");

  /* No shell, means DCL */
  if(!shell) {
    vms_shell = 1;
    return 1;
  }

  /* Have to make sure some one did not set shell to DCL */
  if(strcmp(shell, "DCL") == 0) {
    vms_shell = 1;
    return 1;
  }

  vms_shell = 0;
  return 0;
}

/*
 * VMS has two exit() routines. When running under a Unix style shell, then
 * Unix style and the __posix_exit() routine is used.
 *
 * When running under the DCL shell, then the VMS encoded codes and decc$exit()
 * is used.
 *
 * We can not use exit() or return a code from main() because the actual
 * routine called depends on both the compiler version, compile options, and
 * feature macro settings, and one of the exit routines is hidden at compile
 * time.
 *
 * Since we want Curl to work properly under the VMS DCL shell and Unix
 * shells under VMS, this routine should compile correctly regardless of
 * the settings.
 */

void vms_special_exit(int code, int vms_show)
{
  int vms_code;

  /* The POSIX exit mode is only available after VMS 7.0 */
#if __CRTL_VER >= 70000000
  if(is_vms_shell() == 0) {
    decc$__posix_exit(code);
  }
#endif

  if(code > CURL_LAST) {   /* If CURL_LAST exceeded then */
    vms_code = CURL_LAST;  /* curlmsg.h is out of sync.  */
  }
  else {
    vms_code = vms_cond[code] | vms_show;
  }
  decc$exit(vms_code);
}

#if defined(__DECC) && !defined(__VAX) && \
    defined(__CRTL_VER) && (__CRTL_VER >= 70301000)

/*
 * 2004-09-19 SMS.
 *
 * decc_init()
 *
 * On non-VAX systems, use LIB$INITIALIZE to set a collection of C
 * RTL features without using the DECC$* logical name method, nor
 * requiring the user to define the corresponding logical names.
 */

/* Structure to hold a DECC$* feature name and its desired value. */
struct decc_feat_t {
  char *name;
  int value;
};

/* Array of DECC$* feature names and their desired values. */
static const struct decc_feat_t decc_feat_array[] = {
  /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
  { "DECC$ARGV_PARSE_STYLE", 1 },
  /* Preserve case for filenames on ODS5 disks. */
  { "DECC$EFS_CASE_PRESERVE", 1 },
  /* Enable multiple dots (and most characters) in ODS5 filenames,
     while preserving VMS-ness of ";version". */
  { "DECC$EFS_CHARSET", 1 },
  /* List terminator. */
  { (char *)NULL, 0 }
};

/* Flag to sense if decc_init() was called. */
static int decc_init_done = -1;

/* LIB$INITIALIZE initialization function. */
static void decc_init(void)
{
  int feat_index;
  int feat_value;
  int feat_value_max;
  int feat_value_min;
  int i;
  int sts;

  /* Set the global flag to indicate that LIB$INITIALIZE worked. */
  decc_init_done = 1;

  /* Loop through all items in the decc_feat_array[]. */
  for(i = 0; decc_feat_array[i].name != NULL; i++) {

    /* Get the feature index. */
    feat_index = decc$feature_get_index(decc_feat_array[i].name);

    if(feat_index >= 0) {
      /* Valid item. Collect its properties. */
      feat_value = decc$feature_get_value(feat_index, 1);
      feat_value_min = decc$feature_get_value(feat_index, 2);
      feat_value_max = decc$feature_get_value(feat_index, 3);

      if((decc_feat_array[i].value >= feat_value_min) &&
         (decc_feat_array[i].value <= feat_value_max)) {
        /* Valid value. Set it if necessary. */
        if(feat_value != decc_feat_array[i].value) {
          sts = decc$feature_set_value(feat_index, 1,
                                       decc_feat_array[i].value);
        }
      }
      else {
        /* Invalid DECC feature value. */
        printf(" INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n",
               feat_value,
               feat_value_min, decc_feat_array[i].name, feat_value_max);
      }
    }
    else {
      /* Invalid DECC feature name. */
      printf(" UNKNOWN DECC FEATURE: %s.\n", decc_feat_array[i].name);
    }

  }
}

/* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */

#pragma nostandard

/* Establish the LIB$INITIALIZE PSECTs, with proper alignment and
   other attributes. Note that "nopic" is significant only on VAX. */
#pragma extern_model save
#pragma extern_model strict_refdef "LIB$INITIALIZ" 2, nopic, nowrt
const int spare[8] = {0};
#pragma extern_model strict_refdef "LIB$INITIALIZE" 2, nopic, nowrt
void (*const x_decc_init)() = decc_init;
#pragma extern_model restore

/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
#pragma extern_model save
int LIB$INITIALIZE(void);
#pragma extern_model strict_refdef
int dmy_lib$initialize = (int) LIB$INITIALIZE;
#pragma extern_model restore

#pragma standard

#endif /* __DECC && !__VAX && __CRTL_VER && __CRTL_VER >= 70301000 */

#endif /* __VMS */