xref: /openbsd/gnu/usr.bin/perl/vms/vmsish.h (revision e0680481)
1 /*    vmsish.h
2  *
3  *    VMS-specific C header file for perl5.
4  *
5  *    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
6  *    2002, 2003, 2004, 2005, 2006, 2007 by Charles Bailey and others.
7  *
8  *    You may distribute under the terms of either the GNU General Public
9  *    License or the Artistic License, as specified in the README file.
10  *
11  *    Please see Changes*.* or the Perl Repository Browser for revision history.
12  */
13 
14 #ifndef __vmsish_h_included
15 #define __vmsish_h_included
16 
17 #include <descrip.h> /* for dirent struct definitions */
18 #include <libdef.h>  /* status codes for various places */
19 #include <rmsdef.h>  /* at which errno and vaxc$errno are */
20 #include <ssdef.h>   /* explicitly set in the perl source code */
21 #include <stsdef.h>  /* bitmasks for exit status testing */
22 
23 /* Suppress compiler warnings from DECC for VMS-specific extensions:
24  * ADDRCONSTEXT,NEEDCONSTEXT: initialization of data with non-constant values
25  *                            (e.g. pointer fields of descriptors)
26  */
27 #ifdef __DECC
28 #  pragma message disable (ADDRCONSTEXT,NEEDCONSTEXT)
29 #endif
30 #ifdef __DECCXX
31 #  pragma message informational (INTSIGNCHANGE,CASTQUALTYP,ASSCOMMEA,NOCTOBUTCONREFM,MISSINGRETURN)
32 #endif
33 
34 /* DEC's C compilers and gcc use incompatible definitions of _to(upp|low)er() */
35 #ifdef _toupper
36 #  undef _toupper
37 #endif
38 #define _toupper(c) (((c) < 'a' || (c) > 'z') ? (c) : (c) & ~040)
39 #ifdef _tolower
40 #  undef _tolower
41 #endif
42 #define _tolower(c) (((c) < 'A' || (c) > 'Z') ? (c) : (c) | 040)
43 
44 /* Assorted things to look like Unix */
45 #include <processes.h> /* for vfork() */
46 #include <unixio.h>
47 #include <unixlib.h>
48 #include <file.h>  /* it's not <sys/file.h>, so don't use I_SYS_FILE */
49 #include <unistd.h>
50 
51 #ifdef NO_PERL_TYPEDEFS /* a2p; we don't want Perl's special routines */
52 #  define DONT_MASK_RTL_CALLS
53 #endif
54 
55 #include <namdef.h>
56 
57 /* Set the maximum filespec size here as it is larger for EFS file
58  * specifications.
59  */
60 #ifndef VMS_MAXRSS
61 #ifdef NAML$C_MAXRSS
62 #define VMS_MAXRSS (NAML$C_MAXRSS+1)
63 #ifndef VMS_LONGNAME_SUPPORT
64 #define VMS_LONGNAME_SUPPORT 1
65 #endif /* VMS_LONGNAME_SUPPORT */
66 #endif /* NAML$C_MAXRSS */
67 #endif /* VMS_MAXRSS */
68 
69 #ifndef VMS_MAXRSS
70 #define VMS_MAXRSS (NAM$C_MAXRSS + 1)
71 #endif
72 
73 #ifndef MAXPATHLEN
74 #define MAXPATHLEN (VMS_MAXRSS - 1)
75 #endif
76 
77 
78 /* Note that we do, in fact, have this */
79 #define HAS_GETENV_SV
80 #define HAS_GETENV_LEN
81 
82 
83 #ifndef PERL_FOR_X2P
84 
85 #ifndef DONT_MASK_RTL_CALLS
86 #  ifdef getenv
87 #    undef getenv
88 #  endif
89   /* getenv used for regular logical names */
90 #  define getenv(v) Perl_my_getenv(aTHX_ v,TRUE)
91 #endif
92 #ifdef getenv_len
93 #  undef getenv_len
94 #endif
95 #define getenv_len(v,l) Perl_my_getenv_len(aTHX_ v,l,TRUE)
96 
97 /* DECC introduces this routine in the RTL as of VMS 7.0; for now,
98  * we'll use ours, since it gives us the full VMS exit status. */
99 #define waitpid my_waitpid
100 
101 /* Our own contribution to PerlShr's global symbols . . . */
102 
103 #if !defined(MULTIPLICITY)
104 #define opendir			Perl_opendir
105 #define rename			Perl_rename
106 #define seekdir			Perl_seekdir
107 #define readdir			Perl_readdir
108 #define readdir_r		Perl_readdir_r
109 #else
110 #define opendir(a)		Perl_opendir(aTHX_ a)
111 #define rename(a,b)		Perl_rename(aTHX_ a,b)
112 #define seekdir(a,b)		Perl_seekdir(aTHX_ a,b)
113 #define readdir(a)		Perl_readdir(aTHX_ a)
114 #define readdir_r(a,b,c)	Perl_readdir_r(aTHX_ a,b,c)
115 #endif
116 #define closedir(a)		Perl_closedir(a)
117 #define telldir(a)		Perl_telldir(a)
118 #define vmsreaddirversions(a,b)	Perl_vmsreaddirversions(a,b)
119 
120 #define cando_by_name(a,b,c)		Perl_cando_by_name(aTHX_ a,b,c)
121 #define do_rmdir(a)			Perl_do_rmdir(aTHX_ a)
122 #define fileify_dirspec(a,b)		Perl_fileify_dirspec(aTHX_ a,b)
123 #define fileify_dirspec(a,b)		Perl_fileify_dirspec(aTHX_ a,b)
124 #define fileify_dirspec_ts(a,b)		Perl_fileify_dirspec_ts(aTHX_ a,b)
125 #define fileify_dirspec_ts(a,b)		Perl_fileify_dirspec_ts(aTHX_ a,b)
126 #define fileify_dirspec_utf8(a,b,c)	Perl_fileify_dirspec(aTHX_ a,b,utf8)
127 #define fileify_dirspec_utf8_ts(a,b,c)	Perl_fileify_dirspec_ts(aTHX_ a,b,utf8)
128 #define flex_fstat(a,b)			Perl_flex_fstat(aTHX_ a,b)
129 #define flex_lstat(a,b)			Perl_flex_lstat(aTHX_ a,b)
130 #define flex_stat(a,b)			Perl_flex_stat(aTHX_ a,b)
131 #define init_os_extras			Perl_init_os_extras
132 #define kill_file(a)			Perl_kill_file(aTHX_ a)
133 #define my_chdir(a)			Perl_my_chdir(aTHX_ a)
134 #define my_chmod(a,b)			Perl_my_chmod(aTHX_ a,b)
135 #define my_crypt(a,b)			Perl_my_crypt(aTHX_ a,b)
136 #define my_endpwent()			Perl_my_endpwent(aTHX)
137 #define my_fclose(a)			Perl_my_fclose(a)
138 #define my_fdopen(a,b)			Perl_my_fdopen(a,b)
139 #define my_flush(a)			Perl_my_flush(aTHX_ a)
140 #define my_fwrite(a,b,c,d)		Perl_my_fwrite(a,b,c,d)
141 #define my_fgetname(a,b)		Perl_my_fgetname(a,b)
142 #define my_gconvert(a,b,c,d)		Perl_my_gconvert(a,b,c,d)
143 #define my_getenv(a,b)			Perl_my_getenv(aTHX_ a,b)
144 #define my_getenv_len(a,b,c)		Perl_my_getenv_len(aTHX_ a,b,c)
145 #define my_getpwent()			Perl_my_getpwent(aTHX)
146 #define my_getpwnam(a)			Perl_my_getpwnam(aTHX_ a)
147 #define my_getpwuid(a)			Perl_my_getpwuid(aTHX_ a)
148 #define my_gmtime(a)			Perl_my_gmtime(aTHX_ a)
149 #define my_localtime(a)			Perl_my_localtime(aTHX_ a)
150 #define my_mkdir(a,b)			Perl_my_mkdir(aTHX_ a,b)
151 #ifdef HAS_SYMLINK
152 #  define my_symlink(a,b)		Perl_my_symlink(aTHX_ a,b)
153 #endif
154 #define my_time(a)			Perl_my_time(aTHX_ a)
155 #define my_tmpfile			Perl_my_tmpfile
156 #define my_trnlnm(a,b,c)		Perl_my_trnlnm(aTHX_ a,b,c)
157 #define my_utime(a,b)			Perl_my_utime(aTHX_ a,b)
158 #define my_vfork			Perl_my_vfork
159 #define my_waitpid(a,b,c)		Perl_my_waitpid(aTHX_ a,b,c)
160 #define pathify_dirspec(a,b)		Perl_pathify_dirspec(aTHX a,b)
161 #define pathify_dirspec_ts(a,b)		Perl_pathify_dirspec_ts(aTHX a,b)
162 #define pathify_dirspec_utf8(a,b,c)	Perl_pathify_dirspec_utf8(aTHX a,b,c)
163 #define pathify_dirspec_utf8_ts(a,b,c)	Perl_pathify_dirspec_utf8_ts(aTHX a,b,c)
164 #define prime_env_iter			Perl_prime_env_iter
165 #define rmscopy(a,b,c)			Perl_rmscopy(aTHX_ a,b,c)
166 #define rmsexpand(a,b,c,d)		Perl_rmsexpand_utf8(aTHX_ a,b,c,d,NULL,NULL)
167 #define rmsexpand_ts(a,b,c,d)		Perl_rmsexpand_utf8_ts(aTHX_ a,b,c,d,NULL,NULL)
168 #define rmsexpand_utf8(a,b,c,d,e,f)	Perl_rmsexpand_utf8(aTHX_ a,b,c,d,e,f)
169 #define rmsexpand_utf8_ts(a,b,c,d,e,f)	Perl_rmsexpand_utf8_ts(aTHX_ a,b,c,d,e,f)
170 #define tounixpath(a,b)			Perl_tounixpath_utf8(aTHX_ a,b,NULL)
171 #define tounixpath_ts(a,b)		Perl_tounixpath_utf8_ts(aTHX_ a,b,NULL)
172 #define tounixpath_utf8(a,b,c)		Perl_tounixpath_utf8(aTHX_ a,b,c)
173 #define tounixpath_utf8_ts(a,b,c)	Perl_tounixpath_utf8_ts(aTHX_ a,b,c)
174 #define tounixspec(a,b)			Perl_tounixspec_utf8(aTHX_ a,b,NULL)
175 #define tounixspec_ts(a,b)		Perl_tounixspec_utf8_ts(aTHX_ a,b,NULL)
176 #define tounixspec_utf8(a,b,c)		Perl_tounixspec_utf8(aTHX_ a,b,c)
177 #define tounixspec_utf8_ts(a,b,c)	Perl_tounixspec_utf8_ts(aTHX_ a,b,c)
178 #define tovmspath(a,b)			Perl_tovmspath_utf8(aTHX_ a,b,NULL)
179 #define tovmspath_ts(a,b)		Perl_tovmspath_utf8_ts(aTHX_ a,b,NULL)
180 #define tovmspath_utf8(a,b,c)		Perl_tovmspath_utf8(aTHX_ a,b,c)
181 #define tovmspath_utf8_ts(a,b,c)	Perl_tovmspath_utf8_ts(aTHX_ a,b,c)
182 #define tovmsspec(a,b)			Perl_tovmsspec_utf8(aTHX_ a,b,NULL)
183 #define tovmsspec_ts(a,b)		Perl_tovmsspec_utf8_ts(aTHX_ a,b)
184 #define tovmsspec_utf8(a,b,c)		Perl_tovmsspec_utf8(aTHX_ a,b,c)
185 #define tovmsspec_utf8_ts(a,b,c)	Perl_tovmsspec_utf8_ts(aTHX_ a,b,c)
186 #define trim_unixpath(a,b,c)		Perl_trim_unixpath(aTHX_ a,b,c)
187 #define vms_do_aexec(a,b,c)		Perl_vms_do_aexec(aTHX_ a,b,c)
188 #define vms_do_exec(a)			Perl_vms_do_exec(aTHX_ a)
189 #define vms_case_tolerant(a)		Perl_vms_case_tolerant(a)
190 #define vms_image_init(a,b)		Perl_vms_image_init(a,b)
191 #define vms_realname(a,b,c)		Perl_vms_realname(aTHX_ a,b,c)
192 #define vms_realpath(a,b,c)		Perl_vms_realpath(aTHX_ a,b,c)
193 #define vmssetenv(a,b,c)		Perl_vmssetenv(aTHX_ a,b,c)
194 #define vmstrnenv(a,b,c,d,e)		Perl_vmstrnenv(a,b,c,d,e)
195 #define vmssetuserlnm(a,b)		Perl_vmssetuserlnm(a,b)
196 
197 /* Delete if at all possible, changing protections if necessary. */
198 #define unlink(a) kill_file(a)
199 
200 /*
201  * Intercept calls to fork, so we know whether subsequent calls to
202  * exec should be handled in VMSish or Unixish style.
203  */
204 #define fork my_vfork
205 #ifndef DONT_MASK_RTL_CALLS     /* #defined in vms.c so we see real vfork */
206 #  ifdef vfork
207 #    undef vfork
208 #  endif
209 #  define vfork my_vfork
210 #endif
211 
212 /*
213  * Toss in a shim to tmpfile which creates a plain temp file if the
214  * RMS tmp mechanism won't work (e.g. if someone is relying on ACLs
215  * from a specific directory to permit creation of files).
216  */
217 #ifndef DONT_MASK_RTL_CALLS
218 #  define tmpfile Perl_my_tmpfile
219 #endif
220 #endif
221 
222 
223 /* BIG_TIME:
224  *	This symbol is defined if Time_t is an unsigned type on this system.
225  */
226 #define BIG_TIME
227 
228 /* ACME_MESS:
229  *	This symbol, if defined, indicates that error messages should be
230  *	should be generated in a format that allows the use of the Acme
231  *	GUI/editor's autofind feature.
232  */
233 #undef ACME_MESS	/**/
234 
235 /* ALTERNATE_SHEBANG:
236  *	This symbol, if defined, contains a "magic" string which may be used
237  *	as the first line of a Perl program designed to be executed directly
238  *	by name, instead of the standard Unix #!.  If ALTERNATE_SHEBANG
239  *	begins with a character other then #, then Perl will only treat
240  *	it as a command line if if finds the string "perl" in the first
241  *	word; otherwise it's treated as the first line of code in the script.
242  *	(IOW, Perl won't hand off to another interpreter via an alternate
243  *	shebang sequence that might be legal Perl code.)
244  */
245 #define ALTERNATE_SHEBANG "$"
246 
247 /* Macros to set errno.  */
248 #define set_errno(v)      (errno = (v))
249 #define set_vaxc_errno(v) (vaxc$errno = (v))
250 
251 /* Support for 'vmsish' behaviors enabled with C<use vmsish> pragma */
252 
253 #define COMPLEX_STATUS	1	/* We track both "POSIX" and VMS values */
254 
255 #define HINT_M_VMSISH_STATUS	0x40000000 /* system, $? return VMS status */
256 #define HINT_M_VMSISH_TIME	0x80000000 /* times are local, not UTC */
257 
258 #ifdef MULTIPLICITY
259 #  define TEST_VMSISH(h)	(my_perl && PL_curcop && (PL_curcop->cop_hints & (h)))
260 #else
261 #  define TEST_VMSISH(h)	(PL_curcop && (PL_curcop->cop_hints & (h)))
262 #endif
263 #define VMSISH_STATUS	TEST_VMSISH(HINT_M_VMSISH_STATUS)
264 #define VMSISH_TIME	TEST_VMSISH(HINT_M_VMSISH_TIME)
265 
266 /* VMS-specific data storage */
267 
268 #define HAVE_INTERP_INTERN
269 struct interp_intern {
270     int    hushed;
271     int	   posix_exit;
272     double inv_rand_max;
273 };
274 #define VMSISH_HUSHED     (PL_sys_intern.hushed)
275 #define MY_INV_RAND_MAX   (PL_sys_intern.inv_rand_max)
276 #define MY_POSIX_EXIT	(PL_sys_intern.posix_exit)
277 
278 /* Flags for vmstrnenv() */
279 #define PERL__TRNENV_SECURE 0x01
280 #define PERL__TRNENV_JOIN_SEARCHLIST 0x02
281 
282 /* Handy way to vet calls to VMS system services and RTL routines. */
283 #define _ckvmssts(call) STMT_START { unsigned long int __ckvms_sts; \
284   if (!((__ckvms_sts=(call))&1)) { \
285   set_errno(EVMSERR); set_vaxc_errno(__ckvms_sts); \
286   Perl_croak(aTHX_ "Fatal VMS error (status=%d) at %s, line %d", \
287   __ckvms_sts,__FILE__,__LINE__); } } STMT_END
288 
289 /* Same thing, but don't call back to Perl's croak(); useful for errors
290  * occurring during startup, before Perl's state is initialized */
291 #define _ckvmssts_noperl(call) STMT_START { unsigned long int __ckvms_sts; \
292   if (!((__ckvms_sts=(call))&1)) { \
293   set_errno(EVMSERR); set_vaxc_errno(__ckvms_sts); \
294   (void)fprintf(stderr,"Fatal VMS error (status=%d) at %s, line %d", \
295   __ckvms_sts,__FILE__,__LINE__); (void)lib$signal(__ckvms_sts); } } STMT_END
296 
297 #ifdef VMS_DO_SOCKETS
298 #define PERL_SOCK_SYSREAD_IS_RECV
299 #define PERL_SOCK_SYSWRITE_IS_SEND
300 #endif
301 
302 #define BIT_BUCKET "/dev/null"
303 #define PERL_SYS_INIT_BODY(c,v)	MALLOC_CHECK_TAINT2(*c,*v) vms_image_init((c),(v)); PERLIO_INIT; MALLOC_INIT
304 /* Use standard PERL_SYS_TERM_BODY */
305 
306 #define dXSUB_SYS dNOOP
307 #define HAS_KILL
308 #define HAS_WAIT
309 
310 #ifndef PERL_CORE
311 #  define PERL_FS_VER_FMT	"%d_%d_%d"
312 #endif
313 #define PERL_FS_VERSION		STRINGIFY(PERL_REVISION) "_" \
314                                 STRINGIFY(PERL_VERSION) "_" \
315                                 STRINGIFY(PERL_SUBVERSION)
316 /* Temporary; we need to add support for this to Configure.Com */
317 #ifdef PERL_INC_VERSION_LIST
318 #  undef PERL_INC_VERSION_LIST
319 #endif
320 
321 /* VMS:
322  *	This symbol, if defined, indicates that the program is running under
323  *	VMS.  It's a symbol automagically defined by all VMS C compilers I've seen.
324  * Just in case, however . . . */
325 /* Note that code really should be using __VMS to comply with ANSI */
326 #ifndef VMS
327 #define VMS		/**/
328 #endif
329 
330 /* HAS_IOCTL:
331  *	This symbol, if defined, indicates that the ioctl() routine is
332  *	available to set I/O characteristics
333  */
334 #define HAS_IOCTL               /**/
335 
336 /* HAS_UTIME:
337  *	This symbol, if defined, indicates that the routine utime() is
338  *	available to update the access and modification times of files.
339  */
340 #define HAS_UTIME		/**/
341 
342 /* HAS_GROUP
343  *	This symbol, if defined, indicates that the getgrnam() and
344  *	getgrgid() routines are available to get group entries.
345  *	The getgrent() has a separate definition, HAS_GETGRENT.
346  */
347 #define HAS_GROUP		/**/
348 
349 /* HAS_PASSWD
350  *	This symbol, if defined, indicates that the getpwnam() and
351  *	getpwuid() routines are available to get password entries.
352  *	The getpwent() has a separate definition, HAS_GETPWENT.
353  */
354 #define HAS_PASSWD		/**/
355 
356 #define HAS_KILL
357 #define HAS_WAIT
358 
359 /* USEMYBINMODE
360  *	This symbol, if defined, indicates that the program should
361  *	use the routine my_binmode(FILE *fp, char iotype, int mode) to insure
362  *	that a file is in "binary" mode -- that is, that no translation
363  *	of bytes occurs on read or write operations.
364  */
365 #undef USEMYBINMODE
366 
367 /* Stat_t:
368  *	This symbol holds the type used to declare buffers for information
369  *	returned by stat().  It's usually just struct stat.  It may be necessary
370  *	to include <sys/stat.h> and <sys/types.h> to get any typedef'ed
371  *	information.
372  */
373 /* VMS:
374  * We need this typedef to point to the new type even if DONT_MASK_RTL_CALLS
375  * is in effect, since Perl's thread.h embeds one of these structs in its
376  * thread data struct, and our struct mystat is a different size from the
377  * regular struct stat (cf. note above about having to pad struct to work
378  * around bug in compiler.)
379  * It's OK to pass one of these to the RTL's stat(), though, since the
380  * fields it fills are the same in each struct.
381  */
382 #define Stat_t struct mystat
383 
384 /* USE_STAT_RDEV:
385 *	This symbol is defined if this system has a stat structure declaring
386 *	st_rdev
387 *	VMS: Field exists in POSIXish version of struct stat(), but is not used.
388 *
389 *  No definition of what value an operating system or file system should
390 *  put in the st_rdev field has been found by me so far.  Examination of
391 *  LINUX source code indicates that the value is both very platform and
392 *  file system specific, with many filesystems just putting 1 or 0 in it.
393 *  J. Malmberg.
394 */
395 #undef USE_STAT_RDEV		/**/
396 
397 /*
398  * fwrite1() should be a routine with the same calling sequence as fwrite(),
399  * but which outputs all of the bytes requested as a single stream (unlike
400  * fwrite() itself, which on some systems outputs several distinct records
401  * if the number_of_items parameter is >1).
402  */
403 #define fwrite1 my_fwrite
404 
405 
406 #ifndef DONT_MASK_RTL_CALLS
407 #  define fwrite my_fwrite     /* for PerlSIO_fwrite */
408 #  define fdopen my_fdopen
409 #  define fclose my_fclose
410 #  define fgetname(a, b) my_fgetname(a, b)
411 #ifdef HAS_SYMLINK
412 #  define symlink my_symlink
413 #endif
414 #endif
415 
416 
417 /* By default, flush data all the way to disk, not just to RMS buffers */
418 #define Fflush(fp) my_flush(fp)
419 
420 /* Use our own rmdir() */
421 #ifndef DONT_MASK_RTL_CALLS
422 #define rmdir(name) do_rmdir(name)
423 #endif
424 
425 /* Assorted fiddling with sigs . . . */
426 # include <signal.h>
427 #define ABORT() abort()
428 
429 #ifdef I_UTIME
430 #include <utime.h>
431 #else
432 /* Used with our my_utime() routine in vms.c */
433 struct utimbuf {
434   time_t actime;
435   time_t modtime;
436 };
437 #endif
438 #ifndef DONT_MASK_RTL_CALLS
439 #define utime my_utime
440 #endif
441 
442 /* tbuffer_t was replaced with struct tms in v7.0.  We no longer support
443  * systems prior to v7.0, but there could be old XS code out there that
444  * references tbuffer_t, so provide a compatibility macro.
445  */
446 
447 #define tbuffer_t struct tms
448 
449 /* Substitute our own routines for gmtime(), localtime(), and time(),
450  * which allow us to implement the vmsish 'time' pragma, and work
451  * around absence of system-level UTC support on old versions of VMS.
452  */
453 #define gmtime(t) my_gmtime(t)
454 #define localtime(t) my_localtime(t)
455 #define time(t) my_time(t)
456 
457 /*
458  * The C RTL's sigaction fails to check for invalid signal numbers so we
459  * help it out a bit.
460  */
461 #ifndef DONT_MASK_RTL_CALLS
462 #    define sigaction(a,b,c) Perl_my_sigaction(aTHX_ a,b,c)
463 #endif
464 #ifdef KILL_BY_SIGPRC
465 #  define kill  Perl_my_kill
466 #endif
467 # define killpg  Perl_my_killpg
468 
469 
470 /* VMS doesn't use a real sys_nerr, but we need this when scanning for error
471  * messages in text strings . . .
472  */
473 
474 #define sys_nerr EVMSERR  /* EVMSERR is as high as we can go. */
475 
476 /* Look up new %ENV values on the fly */
477 #define DYNAMIC_ENV_FETCH 1
478   /* Special getenv function for retrieving %ENV elements. */
479 #define ENVgetenv(v) my_getenv(v,FALSE)
480 #define ENVgetenv_len(v,l) my_getenv_len(v,l,FALSE)
481 
482 
483 /* Ditto for sys$hash_password() . . . */
484 #define crypt(a,b)  Perl_my_crypt(aTHX_ a,b)
485 
486 /* Tweak arg to mkdir & chdir first, so we can tolerate trailing /. */
487 #define Mkdir(dir,mode) Perl_my_mkdir(aTHX_ (dir),(mode))
488 #define Chdir(dir) my_chdir((dir))
489 #ifndef DONT_MASK_RTL_CALLS
490 #define chmod(file_spec, mode) my_chmod((file_spec), (mode))
491 #endif
492 
493 /* Use our own stat() clones, which handle Unix-style directory names */
494 #define Stat(name,bufptr) flex_stat(name,bufptr)
495 #define Fstat(fd,bufptr) Perl_flex_fstat(aTHX_ fd,bufptr)
496 #ifndef DONT_MASK_RTL_CALLS
497 #define lstat(name, bufptr) flex_lstat(name, bufptr)
498 #endif
499 
500 /* Setup for the dirent routines:
501  * opendir(), closedir(), readdir(), seekdir(), telldir(), and
502  * vmsreaddirversions(), and preprocessor stuff on which these depend:
503  *    Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
504  *
505  */
506 
507 /* Flags for the _dirdesc structure */
508 #define PERL_VMSDIR_M_VERSIONS		0x02 /* Want VMS versions */
509 #define PERL_VMSDIR_M_UNIXSPECS		0x04 /* Want UNIX specifications */
510 
511 
512     /* Data structure returned by READDIR(). */
513 struct dirent {
514     char	d_name[256];		/* File name		*/
515     int		d_namlen;		/* Length of d_name */
516     int		vms_verscount;		/* Number of versions	*/
517     int		vms_versions[20];	/* Version numbers	*/
518 };
519 
520     /* Handle returned by opendir(), used by the other routines.  You
521      * are not supposed to care what's inside this structure. */
522 typedef struct _dirdesc {
523     long			context;
524     int				flags;
525     unsigned long int           count;
526     char			*pattern;
527     struct dirent		entry;
528     struct dsc$descriptor_s	pat;
529     void			*mutex;
530 } DIR;
531 
532 
533 #define rewinddir(dirp)		seekdir((dirp), 0)
534 
535 /* used for our emulation of getpw* */
536 struct passwd {
537         char    *pw_name;    /* Username */
538         char    *pw_passwd;
539         Uid_t   pw_uid;      /* UIC member number */
540         Gid_t   pw_gid;      /* UIC group  number */
541         char    *pw_comment; /* Default device/directory (Unix-style) */
542         char    *pw_gecos;   /* Owner */
543         char    *pw_dir;     /* Default device/directory (VMS-style) */
544         char    *pw_shell;   /* Default CLI name (eg. DCL) */
545 };
546 #define pw_unixdir pw_comment  /* Default device/directory (Unix-style) */
547 #define getpwnam my_getpwnam
548 #define getpwuid my_getpwuid
549 #define getpwent my_getpwent
550 #define endpwent my_endpwent
551 #define setpwent my_endpwent
552 
553 /* Our own stat_t substitute, since we play with st_dev and st_ino -
554  * we want atomic types so Unix-bound code which compares these fields
555  * for two files will work most of the time under VMS.
556  * N.B. 1. The st_ino hack assumes that sizeof(unsigned short[3]) ==
557  * sizeof(unsigned) + sizeof(unsigned short).  We can't use a union type
558  * to map the unsigned int we want and the unsigned short[3] the CRTL
559  * returns into the same member, since gcc has different ideas than DECC
560  * and VAXC about sizing union types.
561  * N.B. 2. The routine cando() in vms.c assumes that &stat.st_ino is the
562  * address of a FID.
563  */
564 /* First, grab the system types, so we don't clobber them later */
565 #include <stat.h>
566 /* Since we've got to match the size of the CRTL's stat_t, we need
567  * to mimic DECC's alignment settings.
568  *
569  * The simplest thing is to just put a wrapper around the stat structure
570  * supplied by the CRTL and use #defines to redirect references to the
571  * members to the real names.
572  */
573 
574 #if defined(__DECC) || defined(__DECCXX)
575 #  pragma __member_alignment __save
576 #  pragma member_alignment
577 #endif
578 
579 typedef unsigned mydev_t;
580 #if !defined(_USE_STD_STAT) && !defined(_LARGEFILE)
581 typedef unsigned myino_t;
582 #else
583 typedef __ino64_t myino_t;
584 #endif
585 
586 struct mystat
587 {
588     struct stat crtl_stat;
589     myino_t st_ino;
590 #if !defined(_USE_STD_STAT) && !defined(_LARGEFILE)
591     unsigned rvn; /* FID (num,seq,rvn) + pad */
592 #endif
593     mydev_t st_dev;
594     char st_devnam[256]; /* Cache the (short) VMS name */
595 };
596 
597 #define st_mode crtl_stat.st_mode
598 #define st_nlink crtl_stat.st_nlink
599 #define st_uid crtl_stat.st_uid
600 #define st_gid crtl_stat.st_gid
601 #define st_rdev crtl_stat.st_rdev
602 #define st_size crtl_stat.st_size
603 #define st_atime crtl_stat.st_atime
604 #define st_mtime crtl_stat.st_mtime
605 #define st_ctime crtl_stat.st_ctime
606 #define st_fab_rfm crtl_stat.st_fab_rfm
607 #define st_fab_rat crtl_stat.st_fab_rat
608 #define st_fab_fsz crtl_stat.st_fab_fsz
609 #define st_fab_mrs crtl_stat.st_fab_mrs
610 
611 #if defined(_USE_STD_STAT) || defined(_LARGEFILE)
612 #define VMS_INO_T_COMPARE(__a, __b) (__a != __b)
613 #define VMS_INO_T_COPY(__a, __b) __a = __b
614 #else
615 #define VMS_INO_T_COMPARE(__a, __b) memcmp(&__a, &__b, 6)
616 #define VMS_INO_T_COPY(__a, __b) memcpy(&__a, &__b, 6)
617 #endif
618 
619 #if defined(__DECC) || defined(__DECCXX)
620 #  pragma __member_alignment __restore
621 #endif
622 
623 #ifndef DONT_MASK_RTL_CALLS  /* defined for vms.c so we can see RTL calls */
624 #  ifdef stat
625 #    undef stat
626 #  endif
627 #  define stat mystat
628 #  define dev_t mydev_t
629 #  define ino_t myino_t
630 #endif
631 /* Cons up a 'delete' bit for testing access */
632 #define S_IDUSR (S_IWUSR | S_IXUSR)
633 #define S_IDGRP (S_IWGRP | S_IXGRP)
634 #define S_IDOTH (S_IWOTH | S_IXOTH)
635 
636 
637 #ifndef PERL_FOR_X2P
638 /* Prototypes for functions unique to vms.c.  Don't include replacements
639  * for routines in the mainline source files excluded by #ifndef VMS;
640  * their prototypes are already in proto.h.
641  */
642 
643 #ifdef __cplusplus
644 extern "C" {
645 #endif
646 
647 void	prime_env_iter (void);
648 void	init_os_extras (void);
649 int	Perl_vms_status_to_unix(int vms_status, int child_flag);
650 int	Perl_unix_status_to_vms(int unix_status);
651 int	Perl_vmstrnenv (const char *, char *, unsigned long int, struct dsc$descriptor_s **, unsigned long int);
652 char *	Perl_vms_realpath (pTHX_ const char *, char *, int *);
653 char *	Perl_my_getenv (pTHX_ const char *, bool);
654 int	Perl_my_trnlnm (pTHX_ const char *, char *, unsigned long int);
655 char *	Perl_tounixspec (pTHX_ const char *, char *);
656 char *	Perl_tounixspec_ts (pTHX_ const char *, char *);
657 char *	Perl_tounixspec_utf8 (pTHX_ const char *, char *, int *);
658 char *	Perl_tounixspec_utf8_ts (pTHX_ const char *, char *, int *);
659 char *	Perl_tovmsspec (pTHX_ const char *, char *);
660 char *	Perl_tovmsspec_ts (pTHX_ const char *, char *);
661 char *	Perl_tovmsspec_utf8 (pTHX_ const char *, char *, int *);
662 char *	Perl_tovmsspec_utf8_ts (pTHX_ const char *, char *, int *);
663 char *	Perl_tounixpath (pTHX_ const char *, char *);
664 char *	Perl_tounixpath_ts (pTHX_ const char *, char *);
665 char *	Perl_tounixpath_utf8 (pTHX_ const char *, char *, int *);
666 char *	Perl_tounixpath_utf8_ts (pTHX_ const char *, char *, int *);
667 char *	Perl_tovmspath (pTHX_ const char *, char *);
668 char *	Perl_tovmspath_ts (pTHX_ const char *, char *);
669 char *	Perl_tovmspath_utf8 (pTHX_ const char *, char *, int *);
670 char *	Perl_tovmspath_utf8_ts (pTHX_ const char *, char *, int *);
671 int	Perl_do_rmdir (pTHX_ const char *);
672 char *	Perl_fileify_dirspec (pTHX_ const char *, char *);
673 char *	Perl_fileify_dirspec_ts (pTHX_ const char *, char *);
674 char *	Perl_fileify_dirspec_utf8 (pTHX_ const char *, char *, int *);
675 char *	Perl_fileify_dirspec_utf8_ts (pTHX_ const char *, char *, int *);
676 char *	Perl_pathify_dirspec (pTHX_ const char *, char *);
677 char *	Perl_pathify_dirspec_ts (pTHX_ const char *, char *);
678 char *	Perl_pathify_dirspec_utf8 (pTHX_ const char *, char *, int *);
679 char *	Perl_pathify_dirspec_utf8_ts (pTHX_ const char *, char *, int *);
680 char *	Perl_rmsexpand (pTHX_ const char *, char *, const char *, unsigned);
681 char *	Perl_rmsexpand_ts (pTHX_ const char *, char *, const char *, unsigned);
682 char *	Perl_rmsexpand_utf8 (pTHX_ const char *, char *, const char *, unsigned, int *, int *);
683 char *	Perl_rmsexpand_utf8_ts (pTHX_ const char *, char *, const char *, unsigned, int *, int *);
684 int	Perl_trim_unixpath (pTHX_ char *, const char*, int);
685 DIR * Perl_opendir (pTHX_ const char *);
686 int	Perl_rename (pTHX_ const char *, const char *);
687 int	Perl_rmscopy (pTHX_ const char *, const char *, int);
688 int	Perl_my_mkdir (pTHX_ const char *, Mode_t);
689 bool	Perl_vms_do_aexec (pTHX_ SV *, SV **, SV **);
690 int	Perl_vms_case_tolerant(void);
691 char *	Perl_my_getenv_len (pTHX_ const char *, unsigned long *, bool);
692 int	Perl_vmssetenv (pTHX_ const char *, const char *, struct dsc$descriptor_s **);
693 void	Perl_vmssetuserlnm(const char *name, const char *eqv);
694 char *	Perl_my_crypt (pTHX_ const char *, const char *);
695 Pid_t	Perl_my_waitpid (pTHX_ Pid_t, int *, int);
696 char *	my_gconvert (double, int, int, char *);
697 int	Perl_kill_file (pTHX_ const char *);
698 int	Perl_my_chdir (pTHX_ const char *);
699 int	Perl_my_chmod(pTHX_ const char *, mode_t);
700 FILE *	Perl_my_tmpfile (void);
701 int	Perl_my_sigaction (pTHX_ int, const struct sigaction*, struct sigaction*);
702 #ifdef KILL_BY_SIGPRC
703 unsigned int	Perl_sig_to_vmscondition (int);
704 int	Perl_my_kill (int, int);
705 int	Perl_my_killpg (int, int);
706 void	Perl_csighandler_init (void);
707 #endif
708 int	Perl_my_utime (pTHX_ const char *, const struct utimbuf *);
709 void	Perl_vms_image_init (int *, char ***);
710 struct dirent *	Perl_readdir (pTHX_ DIR *);
711 int	Perl_readdir_r(pTHX_ DIR *, struct dirent *, struct dirent **);
712 long	Perl_telldir (DIR *);
713 void	Perl_seekdir (pTHX_ DIR *, long);
714 void	Perl_closedir (DIR *);
715 void	vmsreaddirversions (DIR *, int);
716 struct tm *	Perl_my_gmtime (pTHX_ const time_t *);
717 struct tm *	Perl_my_localtime (pTHX_ const time_t *);
718 time_t	Perl_my_time (pTHX_ time_t *);
719 I32	Perl_cando_by_name (pTHX_ I32, bool, const char *);
720 int	Perl_flex_fstat (pTHX_ int, Stat_t *);
721 int	Perl_flex_lstat (pTHX_ const char *, Stat_t *);
722 int	Perl_flex_stat (pTHX_ const char *, Stat_t *);
723 int	my_vfork (void);
724 bool	Perl_vms_do_exec (pTHX_ const char *);
725 FILE *  my_fdopen (int, const char *);
726 int     my_fclose (FILE *);
727 int     my_fwrite (const void *, size_t, size_t, FILE *);
728 char *  Perl_my_fgetname (FILE *fp, char *buf);
729 #ifdef HAS_SYMLINK
730 int     Perl_my_symlink(pTHX_ const char *path1, const char *path2);
731 #endif
732 int	Perl_my_flush (pTHX_ FILE *);
733 struct passwd *	Perl_my_getpwnam (pTHX_ const char *name);
734 struct passwd *	Perl_my_getpwuid (pTHX_ Uid_t uid);
735 void	Perl_my_endpwent (pTHX);
736 
737 /*
738  * The following prototypes are in math.h but for some reason they
739  * are ifdefed out for C++.  So we have to repeat them here in order
740  * to build the POSIX extension.
741  */
742 
743 #ifdef __DECCXX
744 
745 double exp2(double __x);
746 double fdim(double __x, double __y);
747 double fma(double __x, double __y, double __z);
748 double fmax(double __x, double __y);
749 double fmin(double __x, double __y);
750 double nexttoward(double __x, long double __y);
751 double remainder(double __x, double __y);
752 double remquo(double __x, double __y, int *__quo);
753 double tgamma(double __x);
754 float exp2f(float __x);
755 float fdimf(float __x, float __y);
756 float fmaf(float __x, float __y, float __z);
757 float fmaxf(float __x, float __y);
758 float fminf(float __x, float __y);
759 float nexttowardf(float __x, long double __y);
760 float remainderf(float __x, float __y);
761 float remquof(float __x, float __y, int *__quo);
762 float tgammaf(float __x);
763 long double exp2l(long double __x);
764 long double fdiml(long double __x, long double __y);
765 long double fmal(long double __x, long double __y, long double __z);
766 long double fmaxl(long double __x, long double __y);
767 long double fminl(long double __x, long double __y);
768 long double nexttowardl(long double __x, long double __y);
769 long double remainderl(long double __x, long double __y);
770 long double remquol(long double __x, long double __y, int *__quo);
771 long double tgammal(long double __x);
772 int ilogb(double __x);
773 int ilogbf(float __x);
774 int ilogbl(long double __x);
775 long int lrint(double __x);
776 long int lrintf(float __x);
777 long int lrintl(long double __x);
778 long int lround(double __x);
779 long int lroundf(float __x);
780 long int lroundl(long double __x);
781 
782 #endif
783 
784 
785 #ifdef __cplusplus
786 }
787 #endif
788 
789 #endif
790 
791 #ifndef VMS_DO_SOCKETS
792 /* This relies on tricks in perl.h to pick up that these manifest constants
793  * are undefined and set up conversion routines.  It will then redefine
794  * these manifest constants, so the actual values will match config.h
795  */
796 #undef HAS_HTONS
797 #undef HAS_NTOHS
798 #undef HAS_HTONL
799 #undef HAS_NTOHL
800 #endif
801 
802 /* The C RTL manual says to undef the macro for DEC C 5.2 and lower. */
803 #if defined(fileno) && defined(__DECC_VER) && __DECC_VER < 50300000
804 #  undef fileno
805 #endif
806 
807 #define NO_ENVIRON_ARRAY
808 
809 /* RMSEXPAND options */
810 #define PERL_RMSEXPAND_M_VMS		0x02 /* Force output to VMS format */
811 #define PERL_RMSEXPAND_M_LONG		0x04 /* Expand to long name format */
812 #define PERL_RMSEXPAND_M_VMS_IN		0x08 /* Assume input is VMS already */
813 #define PERL_RMSEXPAND_M_SYMLINK	0x20 /* Use symbolic link, not target */
814 
815 /* With long doubles, NaN == NaN, which it shouldn't. */
816 #ifdef USE_LONG_DOUBLE
817 #  define NAN_COMPARE_BROKEN 1
818 #endif
819 #endif  /* __vmsish_h_included */
820