3 * VMS-specific routines for perl5
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
6 * 2002, 2003, 2004, 2005, 2006, 2007 by Charles Bailey and others.
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.
11 * Please see Changes*.* or the Perl Repository Browser for revision history.
15 * Yet small as was their hunted band
16 * still fell and fearless was each hand,
17 * and strong deeds they wrought yet oft,
18 * and loved the woods, whose ways more soft
19 * them seemed than thralls of that black throne
20 * to live and languish in halls of stone.
21 * "The Lay of Leithian", Canto II, lines 135-40
23 * [p.162 of _The Lays of Beleriand_]
32 #include <climsgdef.h>
43 #include <libclidef.h>
45 #include <lib$routines.h>
49 #if __CRTL_VER >= 70301000 && !defined(__VAX)
59 #include <str$routines.h>
66 #if __CRTL_VER >= 70000000 /* FIXME to earliest version */
68 #define NO_EFN EFN$C_ENF
73 #if __CRTL_VER < 70301000 && __CRTL_VER >= 70300000
74 int decc$feature_get_index(const char *name);
75 char* decc$feature_get_name(int index);
76 int decc$feature_get_value(int index, int mode);
77 int decc$feature_set_value(int index, int mode, int value);
82 #pragma member_alignment save
83 #pragma nomember_alignment longword
88 unsigned short * retadr;
90 #pragma member_alignment restore
92 /* More specific prototype than in starlet_c.h makes programming errors
100 const struct dsc$descriptor_s * devnam,
101 const struct item_list_3 * itmlst,
103 void * (astadr)(unsigned long),
108 #ifdef sys$get_security
109 #undef sys$get_security
111 (const struct dsc$descriptor_s * clsnam,
112 const struct dsc$descriptor_s * objnam,
113 const unsigned int *objhan,
115 const struct item_list_3 * itmlst,
116 unsigned int * contxt,
117 const unsigned int * acmode);
120 #ifdef sys$set_security
121 #undef sys$set_security
123 (const struct dsc$descriptor_s * clsnam,
124 const struct dsc$descriptor_s * objnam,
125 const unsigned int *objhan,
127 const struct item_list_3 * itmlst,
128 unsigned int * contxt,
129 const unsigned int * acmode);
132 #ifdef lib$find_image_symbol
133 #undef lib$find_image_symbol
134 int lib$find_image_symbol
135 (const struct dsc$descriptor_s * imgname,
136 const struct dsc$descriptor_s * symname,
138 const struct dsc$descriptor_s * defspec,
142 #ifdef lib$rename_file
143 #undef lib$rename_file
145 (const struct dsc$descriptor_s * old_file_dsc,
146 const struct dsc$descriptor_s * new_file_dsc,
147 const struct dsc$descriptor_s * default_file_dsc,
148 const struct dsc$descriptor_s * related_file_dsc,
149 const unsigned long * flags,
150 void * (success)(const struct dsc$descriptor_s * old_dsc,
151 const struct dsc$descriptor_s * new_dsc,
153 void * (error)(const struct dsc$descriptor_s * old_dsc,
154 const struct dsc$descriptor_s * new_dsc,
157 const int * error_src,
158 const void * usr_arg),
159 int (confirm)(const struct dsc$descriptor_s * old_dsc,
160 const struct dsc$descriptor_s * new_dsc,
161 const void * old_fab,
162 const void * usr_arg),
164 struct dsc$descriptor_s * old_result_name_dsc,
165 struct dsc$descriptor_s * new_result_name_dsc,
166 unsigned long * file_scan_context);
169 #if __CRTL_VER >= 70300000 && !defined(__VAX)
171 static int set_feature_default(const char *name, int value)
176 index = decc$feature_get_index(name);
178 status = decc$feature_set_value(index, 1, value);
179 if (index == -1 || (status == -1)) {
183 status = decc$feature_get_value(index, 1);
184 if (status != value) {
192 /* Older versions of ssdef.h don't have these */
193 #ifndef SS$_INVFILFOROP
194 # define SS$_INVFILFOROP 3930
196 #ifndef SS$_NOSUCHOBJECT
197 # define SS$_NOSUCHOBJECT 2696
200 /* We implement I/O here, so we will be mixing PerlIO and stdio calls. */
201 #define PERLIO_NOT_STDIO 0
203 /* Don't replace system definitions of vfork, getenv, lstat, and stat,
204 * code below needs to get to the underlying CRTL routines. */
205 #define DONT_MASK_RTL_CALLS
209 /* Anticipating future expansion in lexical warnings . . . */
210 #ifndef WARN_INTERNAL
211 # define WARN_INTERNAL WARN_MISC
214 #ifdef VMS_LONGNAME_SUPPORT
215 #include <libfildef.h>
218 #if defined(__VMS_VER) && __VMS_VER >= 70000000 && __DECC_VER >= 50200000
219 # define RTL_USES_UTC 1
222 /* Routine to create a decterm for use with the Perl debugger */
223 /* No headers, this information was found in the Programming Concepts Manual */
225 static int (*decw_term_port)
226 (const struct dsc$descriptor_s * display,
227 const struct dsc$descriptor_s * setup_file,
228 const struct dsc$descriptor_s * customization,
229 struct dsc$descriptor_s * result_device_name,
230 unsigned short * result_device_name_length,
233 void * char_change_buffer) = 0;
235 /* gcc's header files don't #define direct access macros
236 * corresponding to VAXC's variant structs */
238 # define uic$v_format uic$r_uic_form.uic$v_format
239 # define uic$v_group uic$r_uic_form.uic$v_group
240 # define uic$v_member uic$r_uic_form.uic$v_member
241 # define prv$v_bypass prv$r_prvdef_bits0.prv$v_bypass
242 # define prv$v_grpprv prv$r_prvdef_bits0.prv$v_grpprv
243 # define prv$v_readall prv$r_prvdef_bits0.prv$v_readall
244 # define prv$v_sysprv prv$r_prvdef_bits0.prv$v_sysprv
247 #if defined(NEED_AN_H_ERRNO)
252 #pragma message disable pragma
253 #pragma member_alignment save
254 #pragma nomember_alignment longword
256 #pragma message disable misalgndmem
259 unsigned short int buflen;
260 unsigned short int itmcode;
262 unsigned short int *retlen;
265 struct filescan_itmlst_2 {
266 unsigned short length;
267 unsigned short itmcode;
272 unsigned short length;
277 #pragma message restore
278 #pragma member_alignment restore
281 #define do_fileify_dirspec(a,b,c,d) mp_do_fileify_dirspec(aTHX_ a,b,c,d)
282 #define do_pathify_dirspec(a,b,c,d) mp_do_pathify_dirspec(aTHX_ a,b,c,d)
283 #define do_tovmsspec(a,b,c,d) mp_do_tovmsspec(aTHX_ a,b,c,0,d)
284 #define do_tovmspath(a,b,c,d) mp_do_tovmspath(aTHX_ a,b,c,d)
285 #define do_rmsexpand(a,b,c,d,e,f,g) mp_do_rmsexpand(aTHX_ a,b,c,d,e,f,g)
286 #define do_vms_realpath(a,b,c) mp_do_vms_realpath(aTHX_ a,b,c)
287 #define do_vms_realname(a,b,c) mp_do_vms_realname(aTHX_ a,b,c)
288 #define do_tounixspec(a,b,c,d) mp_do_tounixspec(aTHX_ a,b,c,d)
289 #define do_tounixpath(a,b,c,d) mp_do_tounixpath(aTHX_ a,b,c,d)
290 #define do_vms_case_tolerant(a) mp_do_vms_case_tolerant(a)
291 #define expand_wild_cards(a,b,c,d) mp_expand_wild_cards(aTHX_ a,b,c,d)
292 #define getredirection(a,b) mp_getredirection(aTHX_ a,b)
294 static char *mp_do_tovmspath(pTHX_ const char *path, char *buf, int ts, int *);
295 static char *mp_do_tounixpath(pTHX_ const char *path, char *buf, int ts, int *);
296 static char *mp_do_tounixspec(pTHX_ const char *, char *, int, int *);
297 static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts, int *);
299 static char *int_tovmsspec
300 (const char *path, char *buf, int dir_flag, int * utf8_flag);
302 /* see system service docs for $TRNLNM -- NOT the same as LNM$_MAX_INDEX */
303 #define PERL_LNM_MAX_ALLOWED_INDEX 127
305 /* OpenVMS User's Guide says at least 9 iterative translations will be performed,
306 * depending on the facility. SHOW LOGICAL does 10, so we'll imitate that for
309 #define PERL_LNM_MAX_ITER 10
311 /* New values with 7.3-2*/ /* why does max DCL have 4 byte subtracted from it? */
312 #if __CRTL_VER >= 70302000 && !defined(__VAX)
313 #define MAX_DCL_SYMBOL (8192)
314 #define MAX_DCL_LINE_LENGTH (4096 - 4)
316 #define MAX_DCL_SYMBOL (1024)
317 #define MAX_DCL_LINE_LENGTH (1024 - 4)
320 static char *__mystrtolower(char *str)
322 if (str) for (; *str; ++str) *str= tolower(*str);
326 static struct dsc$descriptor_s fildevdsc =
327 { 12, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$FILE_DEV" };
328 static struct dsc$descriptor_s crtlenvdsc =
329 { 8, DSC$K_DTYPE_T, DSC$K_CLASS_S, "CRTL_ENV" };
330 static struct dsc$descriptor_s *fildev[] = { &fildevdsc, NULL };
331 static struct dsc$descriptor_s *defenv[] = { &fildevdsc, &crtlenvdsc, NULL };
332 static struct dsc$descriptor_s **env_tables = defenv;
333 static bool will_taint = FALSE; /* tainting active, but no PL_curinterp yet */
335 /* True if we shouldn't treat barewords as logicals during directory */
337 static int no_translate_barewords;
340 static int tz_updated = 1;
343 /* DECC Features that may need to affect how Perl interprets
344 * displays filename information
346 static int decc_disable_to_vms_logname_translation = 1;
347 static int decc_disable_posix_root = 1;
348 int decc_efs_case_preserve = 0;
349 static int decc_efs_charset = 0;
350 static int decc_efs_charset_index = -1;
351 static int decc_filename_unix_no_version = 0;
352 static int decc_filename_unix_only = 0;
353 int decc_filename_unix_report = 0;
354 int decc_posix_compliant_pathnames = 0;
355 int decc_readdir_dropdotnotype = 0;
356 static int vms_process_case_tolerant = 1;
357 int vms_vtf7_filenames = 0;
358 int gnv_unix_shell = 0;
359 static int vms_unlink_all_versions = 0;
360 static int vms_posix_exit = 0;
362 /* bug workarounds if needed */
363 int decc_bug_devnull = 1;
364 int decc_dir_barename = 0;
365 int vms_bug_stat_filename = 0;
367 static int vms_debug_on_exception = 0;
368 static int vms_debug_fileify = 0;
370 /* Simple logical name translation */
371 static int simple_trnlnm
372 (const char * logname,
376 const $DESCRIPTOR(table_dsc, "LNM$FILE_DEV");
377 const unsigned long attr = LNM$M_CASE_BLIND;
378 struct dsc$descriptor_s name_dsc;
380 unsigned short result;
381 struct itmlst_3 itlst[2] = {{value_len, LNM$_STRING, value, &result},
384 name_dsc.dsc$w_length = strlen(logname);
385 name_dsc.dsc$a_pointer = (char *)logname;
386 name_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
387 name_dsc.dsc$b_class = DSC$K_CLASS_S;
389 status = sys$trnlnm(&attr, &table_dsc, &name_dsc, 0, itlst);
391 if ($VMS_STATUS_SUCCESS(status)) {
393 /* Null terminate and return the string */
394 /*--------------------------------------*/
403 /* Is this a UNIX file specification?
404 * No longer a simple check with EFS file specs
405 * For now, not a full check, but need to
406 * handle POSIX ^UP^ specifications
407 * Fixing to handle ^/ cases would require
408 * changes to many other conversion routines.
411 static int is_unix_filespec(const char *path)
417 if (strncmp(path,"\"^UP^",5) != 0) {
418 pch1 = strchr(path, '/');
423 /* If the user wants UNIX files, "." needs to be treated as in UNIX */
424 if (decc_filename_unix_report || decc_filename_unix_only) {
425 if (strcmp(path,".") == 0)
433 /* This routine converts a UCS-2 character to be VTF-7 encoded.
436 static void ucs2_to_vtf7
438 unsigned long ucs2_char,
441 unsigned char * ucs_ptr;
444 ucs_ptr = (unsigned char *)&ucs2_char;
448 hex = (ucs_ptr[1] >> 4) & 0xf;
450 outspec[2] = hex + '0';
452 outspec[2] = (hex - 9) + 'A';
453 hex = ucs_ptr[1] & 0xF;
455 outspec[3] = hex + '0';
457 outspec[3] = (hex - 9) + 'A';
459 hex = (ucs_ptr[0] >> 4) & 0xf;
461 outspec[4] = hex + '0';
463 outspec[4] = (hex - 9) + 'A';
464 hex = ucs_ptr[1] & 0xF;
466 outspec[5] = hex + '0';
468 outspec[5] = (hex - 9) + 'A';
474 /* This handles the conversion of a UNIX extended character set to a ^
475 * escaped VMS character.
476 * in a UNIX file specification.
478 * The output count variable contains the number of characters added
479 * to the output string.
481 * The return value is the number of characters read from the input string
483 static int copy_expand_unix_filename_escape
484 (char *outspec, const char *inspec, int *output_cnt, const int * utf8_fl)
492 utf8_flag = *utf8_fl;
496 if (*inspec >= 0x80) {
497 if (utf8_fl && vms_vtf7_filenames) {
498 unsigned long ucs_char;
502 if ((*inspec & 0xE0) == 0xC0) {
504 ucs_char = ((inspec[0] & 0x1F) << 6) + (inspec[1] & 0x3f);
505 if (ucs_char >= 0x80) {
506 ucs2_to_vtf7(outspec, ucs_char, output_cnt);
509 } else if ((*inspec & 0xF0) == 0xE0) {
511 ucs_char = ((inspec[0] & 0xF) << 12) +
512 ((inspec[1] & 0x3f) << 6) +
514 if (ucs_char >= 0x800) {
515 ucs2_to_vtf7(outspec, ucs_char, output_cnt);
519 #if 0 /* I do not see longer sequences supported by OpenVMS */
520 /* Maybe some one can fix this later */
521 } else if ((*inspec & 0xF8) == 0xF0) {
524 } else if ((*inspec & 0xFC) == 0xF8) {
527 } else if ((*inspec & 0xFE) == 0xFC) {
534 /* High bit set, but not a Unicode character! */
536 /* Non printing DECMCS or ISO Latin-1 character? */
537 if (*inspec <= 0x9F) {
541 hex = (*inspec >> 4) & 0xF;
543 outspec[1] = hex + '0';
545 outspec[1] = (hex - 9) + 'A';
549 outspec[2] = hex + '0';
551 outspec[2] = (hex - 9) + 'A';
555 } else if (*inspec == 0xA0) {
561 } else if (*inspec == 0xFF) {
573 /* Is this a macro that needs to be passed through?
574 * Macros start with $( and an alpha character, followed
575 * by a string of alpha numeric characters ending with a )
576 * If this does not match, then encode it as ODS-5.
578 if ((inspec[0] == '$') && (inspec[1] == '(')) {
581 if (isalnum(inspec[2]) || (inspec[2] == '.') || (inspec[2] == '_')) {
583 outspec[0] = inspec[0];
584 outspec[1] = inspec[1];
585 outspec[2] = inspec[2];
587 while(isalnum(inspec[tcnt]) ||
588 (inspec[2] == '.') || (inspec[2] == '_')) {
589 outspec[tcnt] = inspec[tcnt];
592 if (inspec[tcnt] == ')') {
593 outspec[tcnt] = inspec[tcnt];
610 if (decc_efs_charset == 0)
637 /* Don't escape again if following character is
638 * already something we escape.
640 if (strchr(".~!#&\'`()+@{},;[]%^=_\\", *(inspec+1))) {
646 /* But otherwise fall through and escape it. */
648 /* Assume that this is to be escaped */
650 outspec[1] = *inspec;
654 case ' ': /* space */
655 /* Assume that this is to be escaped */
670 /* This handles the expansion of a '^' prefix to the proper character
671 * in a UNIX file specification.
673 * The output count variable contains the number of characters added
674 * to the output string.
676 * The return value is the number of characters read from the input
679 static int copy_expand_vms_filename_escape
680 (char *outspec, const char *inspec, int *output_cnt)
687 if (*inspec == '^') {
690 /* Spaces and non-trailing dots should just be passed through,
691 * but eat the escape character.
698 case '_': /* space */
704 /* Hmm. Better leave the escape escaped. */
710 case 'U': /* Unicode - FIX-ME this is wrong. */
713 scnt = strspn(inspec, "0123456789ABCDEFabcdef");
716 scnt = sscanf(inspec, "%2x%2x", &c1, &c2);
717 outspec[0] == c1 & 0xff;
718 outspec[1] == c2 & 0xff;
725 /* Error - do best we can to continue */
735 scnt = strspn(inspec, "0123456789ABCDEFabcdef");
739 scnt = sscanf(inspec, "%2x", &c1);
740 outspec[0] = c1 & 0xff;
764 (const struct dsc$descriptor_s * srcstr,
765 struct filescan_itmlst_2 * valuelist,
766 unsigned long * fldflags,
767 struct dsc$descriptor_s *auxout,
768 unsigned short * retlen);
771 /* vms_split_path - Verify that the input file specification is a
772 * VMS format file specification, and provide pointers to the components of
773 * it. With EFS format filenames, this is virtually the only way to
774 * parse a VMS path specification into components.
776 * If the sum of the components do not add up to the length of the
777 * string, then the passed file specification is probably a UNIX style
780 static int vms_split_path
795 struct dsc$descriptor path_desc;
799 struct filescan_itmlst_2 item_list[9];
800 const int filespec = 0;
801 const int nodespec = 1;
802 const int devspec = 2;
803 const int rootspec = 3;
804 const int dirspec = 4;
805 const int namespec = 5;
806 const int typespec = 6;
807 const int verspec = 7;
809 /* Assume the worst for an easy exit */
824 path_desc.dsc$a_pointer = (char *)path; /* cast ok */
825 path_desc.dsc$w_length = strlen(path);
826 path_desc.dsc$b_dtype = DSC$K_DTYPE_T;
827 path_desc.dsc$b_class = DSC$K_CLASS_S;
829 /* Get the total length, if it is shorter than the string passed
830 * then this was probably not a VMS formatted file specification
832 item_list[filespec].itmcode = FSCN$_FILESPEC;
833 item_list[filespec].length = 0;
834 item_list[filespec].component = NULL;
836 /* If the node is present, then it gets considered as part of the
837 * volume name to hopefully make things simple.
839 item_list[nodespec].itmcode = FSCN$_NODE;
840 item_list[nodespec].length = 0;
841 item_list[nodespec].component = NULL;
843 item_list[devspec].itmcode = FSCN$_DEVICE;
844 item_list[devspec].length = 0;
845 item_list[devspec].component = NULL;
847 /* root is a special case, adding it to either the directory or
848 * the device components will probalby complicate things for the
849 * callers of this routine, so leave it separate.
851 item_list[rootspec].itmcode = FSCN$_ROOT;
852 item_list[rootspec].length = 0;
853 item_list[rootspec].component = NULL;
855 item_list[dirspec].itmcode = FSCN$_DIRECTORY;
856 item_list[dirspec].length = 0;
857 item_list[dirspec].component = NULL;
859 item_list[namespec].itmcode = FSCN$_NAME;
860 item_list[namespec].length = 0;
861 item_list[namespec].component = NULL;
863 item_list[typespec].itmcode = FSCN$_TYPE;
864 item_list[typespec].length = 0;
865 item_list[typespec].component = NULL;
867 item_list[verspec].itmcode = FSCN$_VERSION;
868 item_list[verspec].length = 0;
869 item_list[verspec].component = NULL;
871 item_list[8].itmcode = 0;
872 item_list[8].length = 0;
873 item_list[8].component = NULL;
875 status = sys$filescan
876 ((const struct dsc$descriptor_s *)&path_desc, item_list,
878 _ckvmssts_noperl(status); /* All failure status values indicate a coding error */
880 /* If we parsed it successfully these two lengths should be the same */
881 if (path_desc.dsc$w_length != item_list[filespec].length)
884 /* If we got here, then it is a VMS file specification */
887 /* set the volume name */
888 if (item_list[nodespec].length > 0) {
889 *volume = item_list[nodespec].component;
890 *vol_len = item_list[nodespec].length + item_list[devspec].length;
893 *volume = item_list[devspec].component;
894 *vol_len = item_list[devspec].length;
897 *root = item_list[rootspec].component;
898 *root_len = item_list[rootspec].length;
900 *dir = item_list[dirspec].component;
901 *dir_len = item_list[dirspec].length;
903 /* Now fun with versions and EFS file specifications
904 * The parser can not tell the difference when a "." is a version
905 * delimiter or a part of the file specification.
907 if ((decc_efs_charset) &&
908 (item_list[verspec].length > 0) &&
909 (item_list[verspec].component[0] == '.')) {
910 *name = item_list[namespec].component;
911 *name_len = item_list[namespec].length + item_list[typespec].length;
912 *ext = item_list[verspec].component;
913 *ext_len = item_list[verspec].length;
918 *name = item_list[namespec].component;
919 *name_len = item_list[namespec].length;
920 *ext = item_list[typespec].component;
921 *ext_len = item_list[typespec].length;
922 *version = item_list[verspec].component;
923 *ver_len = item_list[verspec].length;
928 /* Routine to determine if the file specification ends with .dir */
929 static int is_dir_ext(char * e_spec, int e_len, char * vs_spec, int vs_len) {
931 /* e_len must be 4, and version must be <= 2 characters */
932 if (e_len != 4 || vs_len > 2)
935 /* If a version number is present, it needs to be one */
936 if ((vs_len == 2) && (vs_spec[1] != '1'))
939 /* Look for the DIR on the extension */
940 if (vms_process_case_tolerant) {
941 if ((toupper(e_spec[1]) == 'D') &&
942 (toupper(e_spec[2]) == 'I') &&
943 (toupper(e_spec[3]) == 'R')) {
947 /* Directory extensions are supposed to be in upper case only */
948 /* I would not be surprised if this rule can not be enforced */
949 /* if and when someone fully debugs the case sensitive mode */
950 if ((e_spec[1] == 'D') &&
951 (e_spec[2] == 'I') &&
952 (e_spec[3] == 'R')) {
961 * Routine to retrieve the maximum equivalence index for an input
962 * logical name. Some calls to this routine have no knowledge if
963 * the variable is a logical or not. So on error we return a max
966 /*{{{int my_maxidx(const char *lnm) */
968 my_maxidx(const char *lnm)
972 int attr = LNM$M_CASE_BLIND;
973 struct dsc$descriptor lnmdsc;
974 struct itmlst_3 itlst[2] = {{sizeof(midx), LNM$_MAX_INDEX, &midx, 0},
977 lnmdsc.dsc$w_length = strlen(lnm);
978 lnmdsc.dsc$b_dtype = DSC$K_DTYPE_T;
979 lnmdsc.dsc$b_class = DSC$K_CLASS_S;
980 lnmdsc.dsc$a_pointer = (char *) lnm; /* Cast ok for read only parameter */
982 status = sys$trnlnm(&attr, &fildevdsc, &lnmdsc, 0, itlst);
983 if ((status & 1) == 0)
990 /*{{{int vmstrnenv(const char *lnm, char *eqv, unsigned long int idx, struct dsc$descriptor_s **tabvec, unsigned long int flags) */
992 Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
993 struct dsc$descriptor_s **tabvec, unsigned long int flags)
996 char uplnm[LNM$C_NAMLENGTH+1], *cp2;
997 unsigned short int eqvlen, curtab, ivlnm = 0, ivsym = 0, ivenv = 0, secure;
998 unsigned long int retsts, attr = LNM$M_CASE_BLIND;
1000 unsigned char acmode;
1001 struct dsc$descriptor_s lnmdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0},
1002 tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
1003 struct itmlst_3 lnmlst[3] = {{sizeof idx, LNM$_INDEX, &idx, 0},
1004 {LNM$C_NAMLENGTH, LNM$_STRING, eqv, &eqvlen},
1006 $DESCRIPTOR(crtlenv,"CRTL_ENV"); $DESCRIPTOR(clisym,"CLISYM");
1007 #if defined(PERL_IMPLICIT_CONTEXT)
1010 aTHX = PERL_GET_INTERP;
1016 if (!lnm || !eqv || ((idx != 0) && ((idx-1) > PERL_LNM_MAX_ALLOWED_INDEX))) {
1017 set_errno(EINVAL); set_vaxc_errno(SS$_BADPARAM); return 0;
1019 for (cp1 = lnm, cp2 = uplnm; *cp1; cp1++, cp2++) {
1020 *cp2 = _toupper(*cp1);
1021 if (cp1 - lnm > LNM$C_NAMLENGTH) {
1022 set_errno(EINVAL); set_vaxc_errno(SS$_IVLOGNAM);
1026 lnmdsc.dsc$w_length = cp1 - lnm;
1027 lnmdsc.dsc$a_pointer = uplnm;
1028 uplnm[lnmdsc.dsc$w_length] = '\0';
1029 secure = flags & PERL__TRNENV_SECURE;
1030 acmode = secure ? PSL$C_EXEC : PSL$C_USER;
1031 if (!tabvec || !*tabvec) tabvec = env_tables;
1033 for (curtab = 0; tabvec[curtab]; curtab++) {
1034 if (!str$case_blind_compare(tabvec[curtab],&crtlenv)) {
1035 if (!ivenv && !secure) {
1040 #if defined(PERL_IMPLICIT_CONTEXT)
1043 "%%PERL-W-VMS_INIT Can't read CRTL environ\n");
1046 Perl_warn(aTHX_ "Can't read CRTL environ\n");
1049 retsts = SS$_NOLOGNAM;
1050 for (i = 0; environ[i]; i++) {
1051 if ((eq = strchr(environ[i],'=')) &&
1052 lnmdsc.dsc$w_length == (eq - environ[i]) &&
1053 !strncmp(environ[i],uplnm,eq - environ[i])) {
1055 for (eqvlen = 0; eq[eqvlen]; eqvlen++) eqv[eqvlen] = eq[eqvlen];
1056 if (!eqvlen) continue;
1057 retsts = SS$_NORMAL;
1061 if (retsts != SS$_NOLOGNAM) break;
1064 else if ((tmpdsc.dsc$a_pointer = tabvec[curtab]->dsc$a_pointer) &&
1065 !str$case_blind_compare(&tmpdsc,&clisym)) {
1066 if (!ivsym && !secure) {
1067 unsigned short int deflen = LNM$C_NAMLENGTH;
1068 struct dsc$descriptor_d eqvdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
1069 /* dynamic dsc to accomodate possible long value */
1070 _ckvmssts_noperl(lib$sget1_dd(&deflen,&eqvdsc));
1071 retsts = lib$get_symbol(&lnmdsc,&eqvdsc,&eqvlen,0);
1073 if (eqvlen > MAX_DCL_SYMBOL) {
1074 set_errno(EVMSERR); set_vaxc_errno(LIB$_STRTRU);
1075 eqvlen = MAX_DCL_SYMBOL;
1076 /* Special hack--we might be called before the interpreter's */
1077 /* fully initialized, in which case either thr or PL_curcop */
1078 /* might be bogus. We have to check, since ckWARN needs them */
1079 /* both to be valid if running threaded */
1080 #if defined(PERL_IMPLICIT_CONTEXT)
1083 "%Perl-VMS-Init, Value of CLI symbol \"%s\" too long",lnm);
1086 if (ckWARN(WARN_MISC)) {
1087 Perl_warner(aTHX_ packWARN(WARN_MISC),"Value of CLI symbol \"%s\" too long",lnm);
1090 strncpy(eqv,eqvdsc.dsc$a_pointer,eqvlen);
1092 _ckvmssts_noperl(lib$sfree1_dd(&eqvdsc));
1093 if (retsts == LIB$_INVSYMNAM) { ivsym = 1; continue; }
1094 if (retsts == LIB$_NOSUCHSYM) continue;
1099 if ( (idx == 0) && (flags & PERL__TRNENV_JOIN_SEARCHLIST) ) {
1100 midx = my_maxidx(lnm);
1101 for (idx = 0, cp2 = eqv; idx <= midx; idx++) {
1102 lnmlst[1].bufadr = cp2;
1104 retsts = sys$trnlnm(&attr,tabvec[curtab],&lnmdsc,&acmode,lnmlst);
1105 if (retsts == SS$_IVLOGNAM) { ivlnm = 1; break; }
1106 if (retsts == SS$_NOLOGNAM) break;
1107 /* PPFs have a prefix */
1110 *((int *)uplnm) == *((int *)"SYS$") &&
1112 eqvlen >= 4 && eqv[0] == 0x1b && eqv[1] == 0x00 &&
1113 ( (uplnm[4] == 'O' && !strcmp(uplnm,"SYS$OUTPUT")) ||
1114 (uplnm[4] == 'I' && !strcmp(uplnm,"SYS$INPUT")) ||
1115 (uplnm[4] == 'E' && !strcmp(uplnm,"SYS$ERROR")) ||
1116 (uplnm[4] == 'C' && !strcmp(uplnm,"SYS$COMMAND")) ) ) {
1117 memmove(eqv,eqv+4,eqvlen-4);
1123 if ((retsts == SS$_IVLOGNAM) ||
1124 (retsts == SS$_NOLOGNAM)) { continue; }
1127 retsts = sys$trnlnm(&attr,tabvec[curtab],&lnmdsc,&acmode,lnmlst);
1128 if (retsts == SS$_IVLOGNAM) { ivlnm = 1; continue; }
1129 if (retsts == SS$_NOLOGNAM) continue;
1132 eqvlen = strlen(eqv);
1136 if (retsts & 1) { eqv[eqvlen] = '\0'; return eqvlen; }
1137 else if (retsts == LIB$_NOSUCHSYM || retsts == LIB$_INVSYMNAM ||
1138 retsts == SS$_IVLOGNAM || retsts == SS$_IVLOGTAB ||
1139 retsts == SS$_NOLOGNAM) {
1140 set_errno(EINVAL); set_vaxc_errno(retsts);
1142 else _ckvmssts_noperl(retsts);
1144 } /* end of vmstrnenv */
1147 /*{{{ int my_trnlnm(const char *lnm, char *eqv, unsigned long int idx)*/
1148 /* Define as a function so we can access statics. */
1149 int Perl_my_trnlnm(pTHX_ const char *lnm, char *eqv, unsigned long int idx)
1153 #if defined(PERL_IMPLICIT_CONTEXT)
1156 #ifdef SECURE_INTERNAL_GETENV
1157 flags = (PL_curinterp ? PL_tainting : will_taint) ?
1158 PERL__TRNENV_SECURE : 0;
1161 return vmstrnenv(lnm, eqv, idx, fildev, flags);
1166 * Note: Uses Perl temp to store result so char * can be returned to
1167 * caller; this pointer will be invalidated at next Perl statement
1169 * We define this as a function rather than a macro in terms of my_getenv_len()
1170 * so that it'll work when PL_curinterp is undefined (and we therefore can't
1173 /*{{{ char *my_getenv(const char *lnm, bool sys)*/
1175 Perl_my_getenv(pTHX_ const char *lnm, bool sys)
1178 static char *__my_getenv_eqv = NULL;
1179 char uplnm[LNM$C_NAMLENGTH+1], *cp2, *eqv;
1180 unsigned long int idx = 0;
1181 int trnsuccess, success, secure, saverr, savvmserr;
1185 midx = my_maxidx(lnm) + 1;
1187 if (PL_curinterp) { /* Perl interpreter running -- may be threaded */
1188 /* Set up a temporary buffer for the return value; Perl will
1189 * clean it up at the next statement transition */
1190 tmpsv = sv_2mortal(newSVpv("",(LNM$C_NAMLENGTH*midx)+1));
1191 if (!tmpsv) return NULL;
1195 /* Assume no interpreter ==> single thread */
1196 if (__my_getenv_eqv != NULL) {
1197 Renew(__my_getenv_eqv,LNM$C_NAMLENGTH*midx+1,char);
1200 Newx(__my_getenv_eqv,LNM$C_NAMLENGTH*midx+1,char);
1202 eqv = __my_getenv_eqv;
1205 for (cp1 = lnm, cp2 = eqv; *cp1; cp1++,cp2++) *cp2 = _toupper(*cp1);
1206 if (cp1 - lnm == 7 && !strncmp(eqv,"DEFAULT",7)) {
1208 getcwd(eqv,LNM$C_NAMLENGTH);
1212 /* Get rid of "000000/ in rooted filespecs */
1215 zeros = strstr(eqv, "/000000/");
1216 if (zeros != NULL) {
1218 mlen = len - (zeros - eqv) - 7;
1219 memmove(zeros, &zeros[7], mlen);
1227 /* Impose security constraints only if tainting */
1229 /* Impose security constraints only if tainting */
1230 secure = PL_curinterp ? PL_tainting : will_taint;
1231 saverr = errno; savvmserr = vaxc$errno;
1238 #ifdef SECURE_INTERNAL_GETENV
1239 secure ? PERL__TRNENV_SECURE : 0
1245 /* For the getenv interface we combine all the equivalence names
1246 * of a search list logical into one value to acquire a maximum
1247 * value length of 255*128 (assuming %ENV is using logicals).
1249 flags |= PERL__TRNENV_JOIN_SEARCHLIST;
1251 /* If the name contains a semicolon-delimited index, parse it
1252 * off and make sure we only retrieve the equivalence name for
1254 if ((cp2 = strchr(lnm,';')) != NULL) {
1256 uplnm[cp2-lnm] = '\0';
1257 idx = strtoul(cp2+1,NULL,0);
1259 flags &= ~PERL__TRNENV_JOIN_SEARCHLIST;
1262 success = vmstrnenv(lnm,eqv,idx,secure ? fildev : NULL,flags);
1264 /* Discard NOLOGNAM on internal calls since we're often looking
1265 * for an optional name, and this "error" often shows up as the
1266 * (bogus) exit status for a die() call later on. */
1267 if (sys && vaxc$errno == SS$_NOLOGNAM) SETERRNO(saverr,savvmserr);
1268 return success ? eqv : NULL;
1271 } /* end of my_getenv() */
1275 /*{{{ SV *my_getenv_len(const char *lnm, bool sys)*/
1277 Perl_my_getenv_len(pTHX_ const char *lnm, unsigned long *len, bool sys)
1281 unsigned long idx = 0;
1283 static char *__my_getenv_len_eqv = NULL;
1284 int secure, saverr, savvmserr;
1287 midx = my_maxidx(lnm) + 1;
1289 if (PL_curinterp) { /* Perl interpreter running -- may be threaded */
1290 /* Set up a temporary buffer for the return value; Perl will
1291 * clean it up at the next statement transition */
1292 tmpsv = sv_2mortal(newSVpv("",(LNM$C_NAMLENGTH*midx)+1));
1293 if (!tmpsv) return NULL;
1297 /* Assume no interpreter ==> single thread */
1298 if (__my_getenv_len_eqv != NULL) {
1299 Renew(__my_getenv_len_eqv,LNM$C_NAMLENGTH*midx+1,char);
1302 Newx(__my_getenv_len_eqv,LNM$C_NAMLENGTH*midx+1,char);
1304 buf = __my_getenv_len_eqv;
1307 for (cp1 = lnm, cp2 = buf; *cp1; cp1++,cp2++) *cp2 = _toupper(*cp1);
1308 if (cp1 - lnm == 7 && !strncmp(buf,"DEFAULT",7)) {
1311 getcwd(buf,LNM$C_NAMLENGTH);
1314 /* Get rid of "000000/ in rooted filespecs */
1316 zeros = strstr(buf, "/000000/");
1317 if (zeros != NULL) {
1319 mlen = *len - (zeros - buf) - 7;
1320 memmove(zeros, &zeros[7], mlen);
1329 /* Impose security constraints only if tainting */
1330 secure = PL_curinterp ? PL_tainting : will_taint;
1331 saverr = errno; savvmserr = vaxc$errno;
1338 #ifdef SECURE_INTERNAL_GETENV
1339 secure ? PERL__TRNENV_SECURE : 0
1345 flags |= PERL__TRNENV_JOIN_SEARCHLIST;
1347 if ((cp2 = strchr(lnm,';')) != NULL) {
1349 buf[cp2-lnm] = '\0';
1350 idx = strtoul(cp2+1,NULL,0);
1352 flags &= ~PERL__TRNENV_JOIN_SEARCHLIST;
1355 *len = vmstrnenv(lnm,buf,idx,secure ? fildev : NULL,flags);
1357 /* Get rid of "000000/ in rooted filespecs */
1360 zeros = strstr(buf, "/000000/");
1361 if (zeros != NULL) {
1363 mlen = *len - (zeros - buf) - 7;
1364 memmove(zeros, &zeros[7], mlen);
1370 /* Discard NOLOGNAM on internal calls since we're often looking
1371 * for an optional name, and this "error" often shows up as the
1372 * (bogus) exit status for a die() call later on. */
1373 if (sys && vaxc$errno == SS$_NOLOGNAM) SETERRNO(saverr,savvmserr);
1374 return *len ? buf : NULL;
1377 } /* end of my_getenv_len() */
1380 static void create_mbx(unsigned short int *, struct dsc$descriptor_s *);
1382 static void riseandshine(unsigned long int dummy) { sys$wake(0,0); }
1384 /*{{{ void prime_env_iter() */
1386 prime_env_iter(void)
1387 /* Fill the %ENV associative array with all logical names we can
1388 * find, in preparation for iterating over it.
1391 static int primed = 0;
1392 HV *seenhv = NULL, *envhv;
1394 char cmd[LNM$C_NAMLENGTH+24], mbxnam[LNM$C_NAMLENGTH], *buf = NULL;
1395 unsigned short int chan;
1396 #ifndef CLI$M_TRUSTED
1397 # define CLI$M_TRUSTED 0x40 /* Missing from VAXC headers */
1399 unsigned long int defflags = CLI$M_NOWAIT | CLI$M_NOKEYPAD | CLI$M_TRUSTED;
1400 unsigned long int mbxbufsiz, flags, retsts, subpid = 0, substs = 0, wakect = 0;
1402 bool have_sym = FALSE, have_lnm = FALSE;
1403 struct dsc$descriptor_s tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
1404 $DESCRIPTOR(cmddsc,cmd); $DESCRIPTOR(nldsc,"_NLA0:");
1405 $DESCRIPTOR(clidsc,"DCL"); $DESCRIPTOR(clitabdsc,"DCLTABLES");
1406 $DESCRIPTOR(crtlenv,"CRTL_ENV"); $DESCRIPTOR(clisym,"CLISYM");
1407 $DESCRIPTOR(local,"_LOCAL"); $DESCRIPTOR(mbxdsc,mbxnam);
1408 #if defined(PERL_IMPLICIT_CONTEXT)
1411 #if defined(USE_ITHREADS)
1412 static perl_mutex primenv_mutex;
1413 MUTEX_INIT(&primenv_mutex);
1416 #if defined(PERL_IMPLICIT_CONTEXT)
1417 /* We jump through these hoops because we can be called at */
1418 /* platform-specific initialization time, which is before anything is */
1419 /* set up--we can't even do a plain dTHX since that relies on the */
1420 /* interpreter structure to be initialized */
1422 aTHX = PERL_GET_INTERP;
1424 /* we never get here because the NULL pointer will cause the */
1425 /* several of the routines called by this routine to access violate */
1427 /* This routine is only called by hv.c/hv_iterinit which has a */
1428 /* context, so the real fix may be to pass it through instead of */
1429 /* the hoops above */
1434 if (primed || !PL_envgv) return;
1435 MUTEX_LOCK(&primenv_mutex);
1436 if (primed) { MUTEX_UNLOCK(&primenv_mutex); return; }
1437 envhv = GvHVn(PL_envgv);
1438 /* Perform a dummy fetch as an lval to insure that the hash table is
1439 * set up. Otherwise, the hv_store() will turn into a nullop. */
1440 (void) hv_fetch(envhv,"DEFAULT",7,TRUE);
1442 for (i = 0; env_tables[i]; i++) {
1443 if (!have_sym && (tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer) &&
1444 !str$case_blind_compare(&tmpdsc,&clisym)) have_sym = 1;
1445 if (!have_lnm && str$case_blind_compare(env_tables[i],&crtlenv)) have_lnm = 1;
1447 if (have_sym || have_lnm) {
1448 long int syiitm = SYI$_MAXBUF, dviitm = DVI$_DEVNAM;
1449 _ckvmssts(lib$getsyi(&syiitm, &mbxbufsiz, 0, 0, 0, 0));
1450 _ckvmssts(sys$crembx(0,&chan,mbxbufsiz,mbxbufsiz,0xff0f,0,0));
1451 _ckvmssts(lib$getdvi(&dviitm, &chan, NULL, NULL, &mbxdsc, &mbxdsc.dsc$w_length));
1454 for (i--; i >= 0; i--) {
1455 if (!str$case_blind_compare(env_tables[i],&crtlenv)) {
1458 for (j = 0; environ[j]; j++) {
1459 if (!(start = strchr(environ[j],'='))) {
1460 if (ckWARN(WARN_INTERNAL))
1461 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"Ill-formed CRTL environ value \"%s\"\n",environ[j]);
1465 sv = newSVpv(start,0);
1467 (void) hv_store(envhv,environ[j],start - environ[j] - 1,sv,0);
1472 else if ((tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer) &&
1473 !str$case_blind_compare(&tmpdsc,&clisym)) {
1474 strcpy(cmd,"Show Symbol/Global *");
1475 cmddsc.dsc$w_length = 20;
1476 if (env_tables[i]->dsc$w_length == 12 &&
1477 (tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer + 6) &&
1478 !str$case_blind_compare(&tmpdsc,&local)) strcpy(cmd+12,"Local *");
1479 flags = defflags | CLI$M_NOLOGNAM;
1482 strcpy(cmd,"Show Logical *");
1483 if (str$case_blind_compare(env_tables[i],&fildevdsc)) {
1484 strcat(cmd," /Table=");
1485 strncat(cmd,env_tables[i]->dsc$a_pointer,env_tables[i]->dsc$w_length);
1486 cmddsc.dsc$w_length = strlen(cmd);
1488 else cmddsc.dsc$w_length = 14; /* N.B. We test this below */
1489 flags = defflags | CLI$M_NOCLISYM;
1492 /* Create a new subprocess to execute each command, to exclude the
1493 * remote possibility that someone could subvert a mbx or file used
1494 * to write multiple commands to a single subprocess.
1497 retsts = lib$spawn(&cmddsc,&nldsc,&mbxdsc,&flags,0,&subpid,&substs,
1498 0,&riseandshine,0,0,&clidsc,&clitabdsc);
1499 flags &= ~CLI$M_TRUSTED; /* Just in case we hit a really old version */
1500 defflags &= ~CLI$M_TRUSTED;
1501 } while (retsts == LIB$_INVARG && (flags | CLI$M_TRUSTED));
1503 if (!buf) Newx(buf,mbxbufsiz + 1,char);
1504 if (seenhv) SvREFCNT_dec(seenhv);
1507 char *cp1, *cp2, *key;
1508 unsigned long int sts, iosb[2], retlen, keylen;
1511 sts = sys$qiow(0,chan,IO$_READVBLK,iosb,0,0,buf,mbxbufsiz,0,0,0,0);
1512 if (sts & 1) sts = iosb[0] & 0xffff;
1513 if (sts == SS$_ENDOFFILE) {
1515 while (substs == 0) { sys$hiber(); wakect++;}
1516 if (wakect > 1) sys$wake(0,0); /* Stole someone else's wake */
1521 retlen = iosb[0] >> 16;
1522 if (!retlen) continue; /* blank line */
1524 if (iosb[1] != subpid) {
1526 Perl_croak(aTHX_ "Unknown process %x sent message to prime_env_iter: %s",buf);
1530 if (sts == SS$_BUFFEROVF && ckWARN(WARN_INTERNAL))
1531 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"Buffer overflow in prime_env_iter: %s",buf);
1533 for (cp1 = buf; *cp1 && isspace(*cp1); cp1++) ;
1534 if (*cp1 == '(' || /* Logical name table name */
1535 *cp1 == '=' /* Next eqv of searchlist */) continue;
1536 if (*cp1 == '"') cp1++;
1537 for (cp2 = cp1; *cp2 && *cp2 != '"' && *cp2 != ' '; cp2++) ;
1538 key = cp1; keylen = cp2 - cp1;
1539 if (keylen && hv_exists(seenhv,key,keylen)) continue;
1540 while (*cp2 && *cp2 != '=') cp2++;
1541 while (*cp2 && *cp2 == '=') cp2++;
1542 while (*cp2 && *cp2 == ' ') cp2++;
1543 if (*cp2 == '"') { /* String translation; may embed "" */
1544 for (cp1 = buf + retlen; *cp1 != '"'; cp1--) ;
1545 cp2++; cp1--; /* Skip "" surrounding translation */
1547 else { /* Numeric translation */
1548 for (cp1 = cp2; *cp1 && *cp1 != ' '; cp1++) ;
1549 cp1--; /* stop on last non-space char */
1551 if ((!keylen || (cp1 - cp2 < -1)) && ckWARN(WARN_INTERNAL)) {
1552 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"Ill-formed message in prime_env_iter: |%s|",buf);
1555 PERL_HASH(hash,key,keylen);
1557 if (cp1 == cp2 && *cp2 == '.') {
1558 /* A single dot usually means an unprintable character, such as a null
1559 * to indicate a zero-length value. Get the actual value to make sure.
1561 char lnm[LNM$C_NAMLENGTH+1];
1562 char eqv[MAX_DCL_SYMBOL+1];
1564 strncpy(lnm, key, keylen);
1565 trnlen = vmstrnenv(lnm, eqv, 0, fildev, 0);
1566 sv = newSVpvn(eqv, strlen(eqv));
1569 sv = newSVpvn(cp2,cp1 - cp2 + 1);
1573 hv_store(envhv,key,keylen,sv,hash);
1574 hv_store(seenhv,key,keylen,&PL_sv_yes,hash);
1576 if (cmddsc.dsc$w_length == 14) { /* We just read LNM$FILE_DEV */
1577 /* get the PPFs for this process, not the subprocess */
1578 const char *ppfs[] = {"SYS$COMMAND", "SYS$INPUT", "SYS$OUTPUT", "SYS$ERROR", NULL};
1579 char eqv[LNM$C_NAMLENGTH+1];
1581 for (i = 0; ppfs[i]; i++) {
1582 trnlen = vmstrnenv(ppfs[i],eqv,0,fildev,0);
1583 sv = newSVpv(eqv,trnlen);
1585 hv_store(envhv,ppfs[i],strlen(ppfs[i]),sv,0);
1590 if (have_sym || have_lnm) _ckvmssts(sys$dassgn(chan));
1591 if (buf) Safefree(buf);
1592 if (seenhv) SvREFCNT_dec(seenhv);
1593 MUTEX_UNLOCK(&primenv_mutex);
1596 } /* end of prime_env_iter */
1600 /*{{{ int vmssetenv(const char *lnm, const char *eqv)*/
1601 /* Define or delete an element in the same "environment" as
1602 * vmstrnenv(). If an element is to be deleted, it's removed from
1603 * the first place it's found. If it's to be set, it's set in the
1604 * place designated by the first element of the table vector.
1605 * Like setenv() returns 0 for success, non-zero on error.
1608 Perl_vmssetenv(pTHX_ const char *lnm, const char *eqv, struct dsc$descriptor_s **tabvec)
1611 char uplnm[LNM$C_NAMLENGTH], *cp2, *c;
1612 unsigned short int curtab, ivlnm = 0, ivsym = 0, ivenv = 0;
1614 unsigned long int retsts, usermode = PSL$C_USER;
1615 struct itmlst_3 *ile, *ilist;
1616 struct dsc$descriptor_s lnmdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,uplnm},
1617 eqvdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0},
1618 tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
1619 $DESCRIPTOR(crtlenv,"CRTL_ENV"); $DESCRIPTOR(clisym,"CLISYM");
1620 $DESCRIPTOR(local,"_LOCAL");
1623 set_errno(EINVAL); set_vaxc_errno(SS$_IVLOGNAM);
1624 return SS$_IVLOGNAM;
1627 for (cp1 = lnm, cp2 = uplnm; *cp1; cp1++, cp2++) {
1628 *cp2 = _toupper(*cp1);
1629 if (cp1 - lnm > LNM$C_NAMLENGTH) {
1630 set_errno(EINVAL); set_vaxc_errno(SS$_IVLOGNAM);
1631 return SS$_IVLOGNAM;
1634 lnmdsc.dsc$w_length = cp1 - lnm;
1635 if (!tabvec || !*tabvec) tabvec = env_tables;
1637 if (!eqv) { /* we're deleting n element */
1638 for (curtab = 0; tabvec[curtab]; curtab++) {
1639 if (!ivenv && !str$case_blind_compare(tabvec[curtab],&crtlenv)) {
1641 for (i = 0; environ[i]; i++) { /* If it's an environ elt, reset */
1642 if ((cp1 = strchr(environ[i],'=')) &&
1643 lnmdsc.dsc$w_length == (cp1 - environ[i]) &&
1644 !strncmp(environ[i],lnm,cp1 - environ[i])) {
1646 return setenv(lnm,"",1) ? vaxc$errno : 0;
1649 ivenv = 1; retsts = SS$_NOLOGNAM;
1651 if (ckWARN(WARN_INTERNAL))
1652 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"This Perl can't reset CRTL environ elements (%s)",lnm);
1653 ivenv = 1; retsts = SS$_NOSUCHPGM;
1659 else if ((tmpdsc.dsc$a_pointer = tabvec[curtab]->dsc$a_pointer) &&
1660 !str$case_blind_compare(&tmpdsc,&clisym)) {
1661 unsigned int symtype;
1662 if (tabvec[curtab]->dsc$w_length == 12 &&
1663 (tmpdsc.dsc$a_pointer = tabvec[curtab]->dsc$a_pointer + 6) &&
1664 !str$case_blind_compare(&tmpdsc,&local))
1665 symtype = LIB$K_CLI_LOCAL_SYM;
1666 else symtype = LIB$K_CLI_GLOBAL_SYM;
1667 retsts = lib$delete_symbol(&lnmdsc,&symtype);
1668 if (retsts == LIB$_INVSYMNAM) { ivsym = 1; continue; }
1669 if (retsts == LIB$_NOSUCHSYM) continue;
1673 retsts = sys$dellnm(tabvec[curtab],&lnmdsc,&usermode); /* try user mode first */
1674 if (retsts == SS$_IVLOGNAM) { ivlnm = 1; continue; }
1675 if (retsts != SS$_NOLOGNAM && retsts != SS$_NOLOGTAB) break;
1676 retsts = lib$delete_logical(&lnmdsc,tabvec[curtab]); /* then supervisor mode */
1677 if (retsts != SS$_NOLOGNAM && retsts != SS$_NOLOGTAB) break;
1681 else { /* we're defining a value */
1682 if (!ivenv && !str$case_blind_compare(tabvec[0],&crtlenv)) {
1684 return setenv(lnm,eqv,1) ? vaxc$errno : 0;
1686 if (ckWARN(WARN_INTERNAL))
1687 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"This Perl can't set CRTL environ elements (%s=%s)",lnm,eqv);
1688 retsts = SS$_NOSUCHPGM;
1692 eqvdsc.dsc$a_pointer = (char *) eqv; /* cast ok to readonly parameter */
1693 eqvdsc.dsc$w_length = strlen(eqv);
1694 if ((tmpdsc.dsc$a_pointer = tabvec[0]->dsc$a_pointer) &&
1695 !str$case_blind_compare(&tmpdsc,&clisym)) {
1696 unsigned int symtype;
1697 if (tabvec[0]->dsc$w_length == 12 &&
1698 (tmpdsc.dsc$a_pointer = tabvec[0]->dsc$a_pointer + 6) &&
1699 !str$case_blind_compare(&tmpdsc,&local))
1700 symtype = LIB$K_CLI_LOCAL_SYM;
1701 else symtype = LIB$K_CLI_GLOBAL_SYM;
1702 retsts = lib$set_symbol(&lnmdsc,&eqvdsc,&symtype);
1705 if (!*eqv) eqvdsc.dsc$w_length = 1;
1706 if (eqvdsc.dsc$w_length > LNM$C_NAMLENGTH) {
1708 nseg = (eqvdsc.dsc$w_length + LNM$C_NAMLENGTH - 1) / LNM$C_NAMLENGTH;
1709 if (nseg > PERL_LNM_MAX_ALLOWED_INDEX + 1) {
1710 Perl_warner(aTHX_ packWARN(WARN_MISC),"Value of logical \"%s\" too long. Truncating to %i bytes",
1711 lnm, LNM$C_NAMLENGTH * (PERL_LNM_MAX_ALLOWED_INDEX+1));
1712 eqvdsc.dsc$w_length = LNM$C_NAMLENGTH * (PERL_LNM_MAX_ALLOWED_INDEX+1);
1713 nseg = PERL_LNM_MAX_ALLOWED_INDEX + 1;
1716 Newx(ilist,nseg+1,struct itmlst_3);
1719 set_errno(ENOMEM); set_vaxc_errno(SS$_INSFMEM);
1722 memset(ilist, 0, (sizeof(struct itmlst_3) * (nseg+1)));
1724 for (j = 0, c = eqvdsc.dsc$a_pointer; j < nseg; j++, ile++, c += LNM$C_NAMLENGTH) {
1725 ile->itmcode = LNM$_STRING;
1727 if ((j+1) == nseg) {
1728 ile->buflen = strlen(c);
1729 /* in case we are truncating one that's too long */
1730 if (ile->buflen > LNM$C_NAMLENGTH) ile->buflen = LNM$C_NAMLENGTH;
1733 ile->buflen = LNM$C_NAMLENGTH;
1737 retsts = lib$set_logical(&lnmdsc,0,tabvec[0],0,ilist);
1741 retsts = lib$set_logical(&lnmdsc,&eqvdsc,tabvec[0],0,0);
1746 if (!(retsts & 1)) {
1748 case LIB$_AMBSYMDEF: case LIB$_INSCLIMEM:
1749 case SS$_NOLOGTAB: case SS$_TOOMANYLNAM: case SS$_IVLOGTAB:
1750 set_errno(EVMSERR); break;
1751 case LIB$_INVARG: case LIB$_INVSYMNAM: case SS$_IVLOGNAM:
1752 case LIB$_NOSUCHSYM: case SS$_NOLOGNAM:
1753 set_errno(EINVAL); break;
1755 set_errno(EACCES); break;
1760 set_vaxc_errno(retsts);
1761 return (int) retsts || 44; /* retsts should never be 0, but just in case */
1764 /* We reset error values on success because Perl does an hv_fetch()
1765 * before each hv_store(), and if the thing we're setting didn't
1766 * previously exist, we've got a leftover error message. (Of course,
1767 * this fails in the face of
1768 * $foo = $ENV{nonexistent}; $ENV{existent} = 'foo';
1769 * in that the error reported in $! isn't spurious,
1770 * but it's right more often than not.)
1772 set_errno(0); set_vaxc_errno(retsts);
1776 } /* end of vmssetenv() */
1779 /*{{{ void my_setenv(const char *lnm, const char *eqv)*/
1780 /* This has to be a function since there's a prototype for it in proto.h */
1782 Perl_my_setenv(pTHX_ const char *lnm, const char *eqv)
1785 int len = strlen(lnm);
1789 for (i = 0; lnm[i]; i++) uplnm[i] = _toupper(lnm[i]);
1790 if (!strcmp(uplnm,"DEFAULT")) {
1791 if (eqv && *eqv) my_chdir(eqv);
1795 #ifndef RTL_USES_UTC
1796 if (len == 6 || len == 2) {
1799 for (i = 0; lnm[i]; i++) uplnm[i] = _toupper(lnm[i]);
1801 if (!strcmp(uplnm,"UCX$TZ")) tz_updated = 1;
1802 if (!strcmp(uplnm,"TZ")) tz_updated = 1;
1806 (void) vmssetenv(lnm,eqv,NULL);
1810 /*{{{static void vmssetuserlnm(char *name, char *eqv); */
1812 * sets a user-mode logical in the process logical name table
1813 * used for redirection of sys$error
1816 Perl_vmssetuserlnm(pTHX_ const char *name, const char *eqv)
1818 $DESCRIPTOR(d_tab, "LNM$PROCESS");
1819 struct dsc$descriptor_d d_name = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
1820 unsigned long int iss, attr = LNM$M_CONFINE;
1821 unsigned char acmode = PSL$C_USER;
1822 struct itmlst_3 lnmlst[2] = {{0, LNM$_STRING, 0, 0},
1824 d_name.dsc$a_pointer = (char *)name; /* Cast OK for read only parameter */
1825 d_name.dsc$w_length = strlen(name);
1827 lnmlst[0].buflen = strlen(eqv);
1828 lnmlst[0].bufadr = (char *)eqv; /* Cast OK for read only parameter */
1830 iss = sys$crelnm(&attr,&d_tab,&d_name,&acmode,lnmlst);
1831 if (!(iss&1)) lib$signal(iss);
1836 /*{{{ char *my_crypt(const char *textpasswd, const char *usrname)*/
1837 /* my_crypt - VMS password hashing
1838 * my_crypt() provides an interface compatible with the Unix crypt()
1839 * C library function, and uses sys$hash_password() to perform VMS
1840 * password hashing. The quadword hashed password value is returned
1841 * as a NUL-terminated 8 character string. my_crypt() does not change
1842 * the case of its string arguments; in order to match the behavior
1843 * of LOGINOUT et al., alphabetic characters in both arguments must
1844 * be upcased by the caller.
1846 * - fix me to call ACM services when available
1849 Perl_my_crypt(pTHX_ const char *textpasswd, const char *usrname)
1851 # ifndef UAI$C_PREFERRED_ALGORITHM
1852 # define UAI$C_PREFERRED_ALGORITHM 127
1854 unsigned char alg = UAI$C_PREFERRED_ALGORITHM;
1855 unsigned short int salt = 0;
1856 unsigned long int sts;
1858 unsigned short int dsc$w_length;
1859 unsigned char dsc$b_type;
1860 unsigned char dsc$b_class;
1861 const char * dsc$a_pointer;
1862 } usrdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0},
1863 txtdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
1864 struct itmlst_3 uailst[3] = {
1865 { sizeof alg, UAI$_ENCRYPT, &alg, 0},
1866 { sizeof salt, UAI$_SALT, &salt, 0},
1867 { 0, 0, NULL, NULL}};
1868 static char hash[9];
1870 usrdsc.dsc$w_length = strlen(usrname);
1871 usrdsc.dsc$a_pointer = usrname;
1872 if (!((sts = sys$getuai(0, 0, &usrdsc, uailst, 0, 0, 0)) & 1)) {
1874 case SS$_NOGRPPRV: case SS$_NOSYSPRV:
1878 set_errno(ESRCH); /* There isn't a Unix no-such-user error */
1883 set_vaxc_errno(sts);
1884 if (sts != RMS$_RNF) return NULL;
1887 txtdsc.dsc$w_length = strlen(textpasswd);
1888 txtdsc.dsc$a_pointer = textpasswd;
1889 if (!((sts = sys$hash_password(&txtdsc, alg, salt, &usrdsc, &hash)) & 1)) {
1890 set_errno(EVMSERR); set_vaxc_errno(sts); return NULL;
1893 return (char *) hash;
1895 } /* end of my_crypt() */
1899 static char *mp_do_rmsexpand(pTHX_ const char *, char *, int, const char *, unsigned, int *, int *);
1900 static char *mp_do_fileify_dirspec(pTHX_ const char *, char *, int, int *);
1901 static char *mp_do_tovmsspec(pTHX_ const char *, char *, int, int, int *);
1903 /* fixup barenames that are directories for internal use.
1904 * There have been problems with the consistent handling of UNIX
1905 * style directory names when routines are presented with a name that
1906 * has no directory delimitors at all. So this routine will eventually
1909 static char * fixup_bare_dirnames(const char * name)
1911 if (decc_disable_to_vms_logname_translation) {
1917 /* 8.3, remove() is now broken on symbolic links */
1918 static int rms_erase(const char * vmsname);
1922 * A little hack to get around a bug in some implemenation of remove()
1923 * that do not know how to delete a directory
1925 * Delete any file to which user has control access, regardless of whether
1926 * delete access is explicitly allowed.
1927 * Limitations: User must have write access to parent directory.
1928 * Does not block signals or ASTs; if interrupted in midstream
1929 * may leave file with an altered ACL.
1932 /*{{{int mp_do_kill_file(const char *name, int dirflag)*/
1934 mp_do_kill_file(pTHX_ const char *name, int dirflag)
1938 unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE;
1939 unsigned long int cxt = 0, aclsts, fndsts, rmsts = -1;
1940 struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
1942 unsigned char myace$b_length;
1943 unsigned char myace$b_type;
1944 unsigned short int myace$w_flags;
1945 unsigned long int myace$l_access;
1946 unsigned long int myace$l_ident;
1947 } newace = { sizeof(struct myacedef), ACE$C_KEYID, 0,
1948 ACE$M_READ | ACE$M_WRITE | ACE$M_DELETE | ACE$M_CONTROL, 0},
1949 oldace = { sizeof(struct myacedef), ACE$C_KEYID, 0, 0, 0};
1951 findlst[3] = {{sizeof oldace, ACL$C_FNDACLENT, &oldace, 0},
1952 {sizeof oldace, ACL$C_READACE, &oldace, 0},{0,0,0,0}},
1953 addlst[2] = {{sizeof newace, ACL$C_ADDACLENT, &newace, 0},{0,0,0,0}},
1954 dellst[2] = {{sizeof newace, ACL$C_DELACLENT, &newace, 0},{0,0,0,0}},
1955 lcklst[2] = {{sizeof newace, ACL$C_WLOCK_ACL, &newace, 0},{0,0,0,0}},
1956 ulklst[2] = {{sizeof newace, ACL$C_UNLOCK_ACL, &newace, 0},{0,0,0,0}};
1958 /* Expand the input spec using RMS, since the CRTL remove() and
1959 * system services won't do this by themselves, so we may miss
1960 * a file "hiding" behind a logical name or search list. */
1961 vmsname = PerlMem_malloc(NAM$C_MAXRSS+1);
1962 if (vmsname == NULL) _ckvmssts_noperl(SS$_INSFMEM);
1964 rslt = do_rmsexpand(name,
1968 PERL_RMSEXPAND_M_VMS | PERL_RMSEXPAND_M_SYMLINK,
1972 PerlMem_free(vmsname);
1976 /* Erase the file */
1977 rmsts = rms_erase(vmsname);
1979 /* Did it succeed */
1980 if ($VMS_STATUS_SUCCESS(rmsts)) {
1981 PerlMem_free(vmsname);
1985 /* If not, can changing protections help? */
1986 if (rmsts != RMS$_PRV) {
1987 set_vaxc_errno(rmsts);
1988 PerlMem_free(vmsname);
1992 /* No, so we get our own UIC to use as a rights identifier,
1993 * and the insert an ACE at the head of the ACL which allows us
1994 * to delete the file.
1996 _ckvmssts_noperl(lib$getjpi(&jpicode,0,0,&(oldace.myace$l_ident),0,0));
1997 fildsc.dsc$w_length = strlen(vmsname);
1998 fildsc.dsc$a_pointer = vmsname;
2000 newace.myace$l_ident = oldace.myace$l_ident;
2002 if (!((aclsts = sys$change_acl(0,&type,&fildsc,lcklst,0,0,0)) & 1)) {
2004 case RMS$_FNF: case RMS$_DNF: case SS$_NOSUCHOBJECT:
2005 set_errno(ENOENT); break;
2007 set_errno(ENOTDIR); break;
2009 set_errno(ENODEV); break;
2010 case RMS$_SYN: case SS$_INVFILFOROP:
2011 set_errno(EINVAL); break;
2013 set_errno(EACCES); break;
2015 _ckvmssts_noperl(aclsts);
2017 set_vaxc_errno(aclsts);
2018 PerlMem_free(vmsname);
2021 /* Grab any existing ACEs with this identifier in case we fail */
2022 aclsts = fndsts = sys$change_acl(0,&type,&fildsc,findlst,0,0,&cxt);
2023 if ( fndsts & 1 || fndsts == SS$_ACLEMPTY || fndsts == SS$_NOENTRY
2024 || fndsts == SS$_NOMOREACE ) {
2025 /* Add the new ACE . . . */
2026 if (!((aclsts = sys$change_acl(0,&type,&fildsc,addlst,0,0,0)) & 1))
2029 rmsts = rms_erase(vmsname);
2030 if ($VMS_STATUS_SUCCESS(rmsts)) {
2035 /* We blew it - dir with files in it, no write priv for
2036 * parent directory, etc. Put things back the way they were. */
2037 if (!((aclsts = sys$change_acl(0,&type,&fildsc,dellst,0,0,0)) & 1))
2040 addlst[0].bufadr = &oldace;
2041 if (!((aclsts = sys$change_acl(0,&type,&fildsc,addlst,0,0,&cxt)) & 1))
2048 fndsts = sys$change_acl(0,&type,&fildsc,ulklst,0,0,0);
2049 /* We just deleted it, so of course it's not there. Some versions of
2050 * VMS seem to return success on the unlock operation anyhow (after all
2051 * the unlock is successful), but others don't.
2053 if (fndsts == RMS$_FNF || fndsts == SS$_NOSUCHOBJECT) fndsts = SS$_NORMAL;
2054 if (aclsts & 1) aclsts = fndsts;
2055 if (!(aclsts & 1)) {
2057 set_vaxc_errno(aclsts);
2060 PerlMem_free(vmsname);
2063 } /* end of kill_file() */
2067 /*{{{int do_rmdir(char *name)*/
2069 Perl_do_rmdir(pTHX_ const char *name)
2075 dirfile = PerlMem_malloc(VMS_MAXRSS + 1);
2076 if (dirfile == NULL)
2077 _ckvmssts(SS$_INSFMEM);
2079 /* Force to a directory specification */
2080 if (do_fileify_dirspec(name, dirfile, 0, NULL) == NULL) {
2081 PerlMem_free(dirfile);
2084 if (Perl_flex_lstat(aTHX_ dirfile, &st) || !S_ISDIR(st.st_mode)) {
2089 retval = mp_do_kill_file(aTHX_ dirfile, 1);
2091 PerlMem_free(dirfile);
2094 } /* end of do_rmdir */
2098 * Delete any file to which user has control access, regardless of whether
2099 * delete access is explicitly allowed.
2100 * Limitations: User must have write access to parent directory.
2101 * Does not block signals or ASTs; if interrupted in midstream
2102 * may leave file with an altered ACL.
2105 /*{{{int kill_file(char *name)*/
2107 Perl_kill_file(pTHX_ const char *name)
2109 char rspec[NAM$C_MAXRSS+1];
2114 /* Remove() is allowed to delete directories, according to the X/Open
2116 * This may need special handling to work with the ACL hacks.
2118 if ((flex_lstat(name, &st) == 0) && S_ISDIR(st.st_mode)) {
2119 rmsts = Perl_do_rmdir(aTHX_ name);
2123 rmsts = mp_do_kill_file(aTHX_ name, 0);
2127 } /* end of kill_file() */
2131 /*{{{int my_mkdir(char *,Mode_t)*/
2133 Perl_my_mkdir(pTHX_ const char *dir, Mode_t mode)
2135 STRLEN dirlen = strlen(dir);
2137 /* zero length string sometimes gives ACCVIO */
2138 if (dirlen == 0) return -1;
2140 /* CRTL mkdir() doesn't tolerate trailing /, since that implies
2141 * null file name/type. However, it's commonplace under Unix,
2142 * so we'll allow it for a gain in portability.
2144 if (dir[dirlen-1] == '/') {
2145 char *newdir = savepvn(dir,dirlen-1);
2146 int ret = mkdir(newdir,mode);
2150 else return mkdir(dir,mode);
2151 } /* end of my_mkdir */
2154 /*{{{int my_chdir(char *)*/
2156 Perl_my_chdir(pTHX_ const char *dir)
2158 STRLEN dirlen = strlen(dir);
2160 /* zero length string sometimes gives ACCVIO */
2161 if (dirlen == 0) return -1;
2164 /* Perl is passing the output of the DCL SHOW DEFAULT with leading spaces.
2165 * This does not work if DECC$EFS_CHARSET is active. Hack it here
2166 * so that existing scripts do not need to be changed.
2169 while ((dirlen > 0) && (*dir1 == ' ')) {
2174 /* some versions of CRTL chdir() doesn't tolerate trailing /, since
2176 * null file name/type. However, it's commonplace under Unix,
2177 * so we'll allow it for a gain in portability.
2179 * - Preview- '/' will be valid soon on VMS
2181 if ((dirlen > 1) && (dir1[dirlen-1] == '/')) {
2182 char *newdir = savepvn(dir1,dirlen-1);
2183 int ret = chdir(newdir);
2187 else return chdir(dir1);
2188 } /* end of my_chdir */
2192 /*{{{int my_chmod(char *, mode_t)*/
2194 Perl_my_chmod(pTHX_ const char *file_spec, mode_t mode)
2196 STRLEN speclen = strlen(file_spec);
2198 /* zero length string sometimes gives ACCVIO */
2199 if (speclen == 0) return -1;
2201 /* some versions of CRTL chmod() doesn't tolerate trailing /, since
2202 * that implies null file name/type. However, it's commonplace under Unix,
2203 * so we'll allow it for a gain in portability.
2205 * Tests are showing that chmod() on VMS 8.3 is only accepting directories
2206 * in VMS file.dir notation.
2208 if ((speclen > 1) && (file_spec[speclen-1] == '/')) {
2209 char *vms_src, *vms_dir, *rslt;
2213 /* First convert this to a VMS format specification */
2214 vms_src = PerlMem_malloc(VMS_MAXRSS);
2215 if (vms_src == NULL)
2216 _ckvmssts_noperl(SS$_INSFMEM);
2218 rslt = do_tovmsspec(file_spec, vms_src, 0, NULL);
2220 /* If we fail, then not a file specification */
2221 PerlMem_free(vms_src);
2226 /* Now make it a directory spec so chmod is happy */
2227 vms_dir = PerlMem_malloc(VMS_MAXRSS + 1);
2228 if (vms_dir == NULL)
2229 _ckvmssts_noperl(SS$_INSFMEM);
2230 rslt = do_fileify_dirspec(vms_src, vms_dir, 0, NULL);
2231 PerlMem_free(vms_src);
2235 ret = chmod(vms_dir, mode);
2239 PerlMem_free(vms_dir);
2242 else return chmod(file_spec, mode);
2243 } /* end of my_chmod */
2247 /*{{{FILE *my_tmpfile()*/
2254 if ((fp = tmpfile())) return fp;
2256 cp = PerlMem_malloc(L_tmpnam+24);
2257 if (cp == NULL) _ckvmssts_noperl(SS$_INSFMEM);
2259 if (decc_filename_unix_only == 0)
2260 strcpy(cp,"Sys$Scratch:");
2263 tmpnam(cp+strlen(cp));
2264 strcat(cp,".Perltmp");
2265 fp = fopen(cp,"w+","fop=dlt");
2272 #ifndef HOMEGROWN_POSIX_SIGNALS
2274 * The C RTL's sigaction fails to check for invalid signal numbers so we
2275 * help it out a bit. The docs are correct, but the actual routine doesn't
2276 * do what the docs say it will.
2278 /*{{{int Perl_my_sigaction (pTHX_ int, const struct sigaction*, struct sigaction*);*/
2280 Perl_my_sigaction (pTHX_ int sig, const struct sigaction* act,
2281 struct sigaction* oact)
2283 if (sig == SIGKILL || sig == SIGSTOP || sig == SIGCONT) {
2284 SETERRNO(EINVAL, SS$_INVARG);
2287 return sigaction(sig, act, oact);
2292 #ifdef KILL_BY_SIGPRC
2293 #include <errnodef.h>
2295 /* We implement our own kill() using the undocumented system service
2296 sys$sigprc for one of two reasons:
2298 1.) If the kill() in an older CRTL uses sys$forcex, causing the
2299 target process to do a sys$exit, which usually can't be handled
2300 gracefully...certainly not by Perl and the %SIG{} mechanism.
2302 2.) If the kill() in the CRTL can't be called from a signal
2303 handler without disappearing into the ether, i.e., the signal
2304 it purportedly sends is never trapped. Still true as of VMS 7.3.
2306 sys$sigprc has the same parameters as sys$forcex, but throws an exception
2307 in the target process rather than calling sys$exit.
2309 Note that distinguishing SIGSEGV from SIGBUS requires an extra arg
2310 on the ACCVIO condition, which sys$sigprc (and sys$forcex) don't
2311 provide. On VMS 7.0+ this is taken care of by doing sys$sigprc
2312 with condition codes C$_SIG0+nsig*8, catching the exception on the
2313 target process and resignaling with appropriate arguments.
2315 But we don't have that VMS 7.0+ exception handler, so if you
2316 Perl_my_kill(.., SIGSEGV) it will show up as a SIGBUS. Oh well.
2318 Also note that SIGTERM is listed in the docs as being "unimplemented",
2319 yet always seems to be signaled with a VMS condition code of 4 (and
2320 correctly handled for that code). So we hardwire it in.
2322 Unlike the VMS 7.0+ CRTL kill() function, we actually check the signal
2323 number to see if it's valid. So Perl_my_kill(pid,0) returns -1 rather
2324 than signalling with an unrecognized (and unhandled by CRTL) code.
2327 #define _MY_SIG_MAX 28
2330 Perl_sig_to_vmscondition_int(int sig)
2332 static unsigned int sig_code[_MY_SIG_MAX+1] =
2335 SS$_HANGUP, /* 1 SIGHUP */
2336 SS$_CONTROLC, /* 2 SIGINT */
2337 SS$_CONTROLY, /* 3 SIGQUIT */
2338 SS$_RADRMOD, /* 4 SIGILL */
2339 SS$_BREAK, /* 5 SIGTRAP */
2340 SS$_OPCCUS, /* 6 SIGABRT */
2341 SS$_COMPAT, /* 7 SIGEMT */
2343 SS$_FLTOVF, /* 8 SIGFPE VAX */
2345 SS$_HPARITH, /* 8 SIGFPE AXP */
2347 SS$_ABORT, /* 9 SIGKILL */
2348 SS$_ACCVIO, /* 10 SIGBUS */
2349 SS$_ACCVIO, /* 11 SIGSEGV */
2350 SS$_BADPARAM, /* 12 SIGSYS */
2351 SS$_NOMBX, /* 13 SIGPIPE */
2352 SS$_ASTFLT, /* 14 SIGALRM */
2369 #if __VMS_VER >= 60200000
2370 static int initted = 0;
2373 sig_code[16] = C$_SIGUSR1;
2374 sig_code[17] = C$_SIGUSR2;
2375 #if __CRTL_VER >= 70000000
2376 sig_code[20] = C$_SIGCHLD;
2378 #if __CRTL_VER >= 70300000
2379 sig_code[28] = C$_SIGWINCH;
2384 if (sig < _SIG_MIN) return 0;
2385 if (sig > _MY_SIG_MAX) return 0;
2386 return sig_code[sig];
2390 Perl_sig_to_vmscondition(int sig)
2393 if (vms_debug_on_exception != 0)
2394 lib$signal(SS$_DEBUG);
2396 return Perl_sig_to_vmscondition_int(sig);
2401 Perl_my_kill(int pid, int sig)
2406 int sys$sigprc(unsigned int *pidadr,
2407 struct dsc$descriptor_s *prcname,
2410 /* sig 0 means validate the PID */
2411 /*------------------------------*/
2413 const unsigned long int jpicode = JPI$_PID;
2416 status = lib$getjpi(&jpicode, &pid, NULL, &ret_pid, NULL, NULL);
2417 if ($VMS_STATUS_SUCCESS(status))
2420 case SS$_NOSUCHNODE:
2421 case SS$_UNREACHABLE:
2435 code = Perl_sig_to_vmscondition_int(sig);
2438 SETERRNO(EINVAL, SS$_BADPARAM);
2442 /* Fixme: Per official UNIX specification: If pid = 0, or negative then
2443 * signals are to be sent to multiple processes.
2444 * pid = 0 - all processes in group except ones that the system exempts
2445 * pid = -1 - all processes except ones that the system exempts
2446 * pid = -n - all processes in group (abs(n)) except ...
2447 * For now, just report as not supported.
2451 SETERRNO(ENOTSUP, SS$_UNSUPPORTED);
2455 iss = sys$sigprc((unsigned int *)&pid,0,code);
2456 if (iss&1) return 0;
2460 set_errno(EPERM); break;
2462 case SS$_NOSUCHNODE:
2463 case SS$_UNREACHABLE:
2464 set_errno(ESRCH); break;
2466 set_errno(ENOMEM); break;
2468 _ckvmssts_noperl(iss);
2471 set_vaxc_errno(iss);
2477 /* Routine to convert a VMS status code to a UNIX status code.
2478 ** More tricky than it appears because of conflicting conventions with
2481 ** VMS status codes are a bit mask, with the least significant bit set for
2484 ** Special UNIX status of EVMSERR indicates that no translation is currently
2485 ** available, and programs should check the VMS status code.
2487 ** Programs compiled with _POSIX_EXIT have a special encoding that requires
2491 #ifndef C_FACILITY_NO
2492 #define C_FACILITY_NO 0x350000
2495 #define DCL_IVVERB 0x38090
2498 int Perl_vms_status_to_unix(int vms_status, int child_flag)
2506 /* Assume the best or the worst */
2507 if (vms_status & STS$M_SUCCESS)
2510 unix_status = EVMSERR;
2512 msg_status = vms_status & ~STS$M_CONTROL;
2514 facility = vms_status & STS$M_FAC_NO;
2515 fac_sp = vms_status & STS$M_FAC_SP;
2516 msg_no = vms_status & (STS$M_MSG_NO | STS$M_SEVERITY);
2518 if (((facility == 0) || (fac_sp == 0)) && (child_flag == 0)) {
2524 unix_status = EFAULT;
2526 case SS$_DEVOFFLINE:
2527 unix_status = EBUSY;
2530 unix_status = ENOTCONN;
2538 case SS$_INVFILFOROP:
2542 unix_status = EINVAL;
2544 case SS$_UNSUPPORTED:
2545 unix_status = ENOTSUP;
2550 unix_status = EACCES;
2552 case SS$_DEVICEFULL:
2553 unix_status = ENOSPC;
2556 unix_status = ENODEV;
2558 case SS$_NOSUCHFILE:
2559 case SS$_NOSUCHOBJECT:
2560 unix_status = ENOENT;
2562 case SS$_ABORT: /* Fatal case */
2563 case ((SS$_ABORT & STS$M_COND_ID) | STS$K_ERROR): /* Error case */
2564 case ((SS$_ABORT & STS$M_COND_ID) | STS$K_WARNING): /* Warning case */
2565 unix_status = EINTR;
2568 unix_status = E2BIG;
2571 unix_status = ENOMEM;
2574 unix_status = EPERM;
2576 case SS$_NOSUCHNODE:
2577 case SS$_UNREACHABLE:
2578 unix_status = ESRCH;
2581 unix_status = ECHILD;
2584 if ((facility == 0) && (msg_no < 8)) {
2585 /* These are not real VMS status codes so assume that they are
2586 ** already UNIX status codes
2588 unix_status = msg_no;
2594 /* Translate a POSIX exit code to a UNIX exit code */
2595 if ((facility == C_FACILITY_NO) && ((msg_no & 0xA000) == 0xA000)) {
2596 unix_status = (msg_no & 0x07F8) >> 3;
2600 /* Documented traditional behavior for handling VMS child exits */
2601 /*--------------------------------------------------------------*/
2602 if (child_flag != 0) {
2604 /* Success / Informational return 0 */
2605 /*----------------------------------*/
2606 if (msg_no & STS$K_SUCCESS)
2609 /* Warning returns 1 */
2610 /*-------------------*/
2611 if ((msg_no & (STS$K_ERROR | STS$K_SEVERE)) == 0)
2614 /* Everything else pass through the severity bits */
2615 /*------------------------------------------------*/
2616 return (msg_no & STS$M_SEVERITY);
2619 /* Normal VMS status to ERRNO mapping attempt */
2620 /*--------------------------------------------*/
2621 switch(msg_status) {
2622 /* case RMS$_EOF: */ /* End of File */
2623 case RMS$_FNF: /* File Not Found */
2624 case RMS$_DNF: /* Dir Not Found */
2625 unix_status = ENOENT;
2627 case RMS$_RNF: /* Record Not Found */
2628 unix_status = ESRCH;
2631 unix_status = ENOTDIR;
2634 unix_status = ENODEV;
2639 unix_status = EBADF;
2642 unix_status = EEXIST;
2646 case LIB$_INVSTRDES:
2648 case LIB$_NOSUCHSYM:
2649 case LIB$_INVSYMNAM:
2651 unix_status = EINVAL;
2657 unix_status = E2BIG;
2659 case RMS$_PRV: /* No privilege */
2660 case RMS$_ACC: /* ACP file access failed */
2661 case RMS$_WLK: /* Device write locked */
2662 unix_status = EACCES;
2664 case RMS$_MKD: /* Failed to mark for delete */
2665 unix_status = EPERM;
2667 /* case RMS$_NMF: */ /* No more files */
2675 /* Try to guess at what VMS error status should go with a UNIX errno
2676 * value. This is hard to do as there could be many possible VMS
2677 * error statuses that caused the errno value to be set.
2680 int Perl_unix_status_to_vms(int unix_status)
2682 int test_unix_status;
2684 /* Trivial cases first */
2685 /*---------------------*/
2686 if (unix_status == EVMSERR)
2689 /* Is vaxc$errno sane? */
2690 /*---------------------*/
2691 test_unix_status = Perl_vms_status_to_unix(vaxc$errno, 0);
2692 if (test_unix_status == unix_status)
2695 /* If way out of range, must be VMS code already */
2696 /*-----------------------------------------------*/
2697 if (unix_status > EVMSERR)
2700 /* If out of range, punt */
2701 /*-----------------------*/
2702 if (unix_status > __ERRNO_MAX)
2706 /* Ok, now we have to do it the hard way. */
2707 /*----------------------------------------*/
2708 switch(unix_status) {
2709 case 0: return SS$_NORMAL;
2710 case EPERM: return SS$_NOPRIV;
2711 case ENOENT: return SS$_NOSUCHOBJECT;
2712 case ESRCH: return SS$_UNREACHABLE;
2713 case EINTR: return SS$_ABORT;
2716 case E2BIG: return SS$_BUFFEROVF;
2718 case EBADF: return RMS$_IFI;
2719 case ECHILD: return SS$_NONEXPR;
2721 case ENOMEM: return SS$_INSFMEM;
2722 case EACCES: return SS$_FILACCERR;
2723 case EFAULT: return SS$_ACCVIO;
2725 case EBUSY: return SS$_DEVOFFLINE;
2726 case EEXIST: return RMS$_FEX;
2728 case ENODEV: return SS$_NOSUCHDEV;
2729 case ENOTDIR: return RMS$_DIR;
2731 case EINVAL: return SS$_INVARG;
2737 case ENOSPC: return SS$_DEVICEFULL;
2738 case ESPIPE: return LIB$_INVARG;
2743 case ERANGE: return LIB$_INVARG;
2744 /* case EWOULDBLOCK */
2745 /* case EINPROGRESS */
2748 /* case EDESTADDRREQ */
2750 /* case EPROTOTYPE */
2751 /* case ENOPROTOOPT */
2752 /* case EPROTONOSUPPORT */
2753 /* case ESOCKTNOSUPPORT */
2754 /* case EOPNOTSUPP */
2755 /* case EPFNOSUPPORT */
2756 /* case EAFNOSUPPORT */
2757 /* case EADDRINUSE */
2758 /* case EADDRNOTAVAIL */
2760 /* case ENETUNREACH */
2761 /* case ENETRESET */
2762 /* case ECONNABORTED */
2763 /* case ECONNRESET */
2766 case ENOTCONN: return SS$_CLEARED;
2767 /* case ESHUTDOWN */
2768 /* case ETOOMANYREFS */
2769 /* case ETIMEDOUT */
2770 /* case ECONNREFUSED */
2772 /* case ENAMETOOLONG */
2773 /* case EHOSTDOWN */
2774 /* case EHOSTUNREACH */
2775 /* case ENOTEMPTY */
2787 /* case ECANCELED */
2791 return SS$_UNSUPPORTED;
2797 /* case EABANDONED */
2799 return SS$_ABORT; /* punt */
2802 return SS$_ABORT; /* Should not get here */
2806 /* default piping mailbox size */
2807 #define PERL_BUFSIZ 512
2811 create_mbx(unsigned short int *chan, struct dsc$descriptor_s *namdsc)
2813 unsigned long int mbxbufsiz;
2814 static unsigned long int syssize = 0;
2815 unsigned long int dviitm = DVI$_DEVNAM;
2816 char csize[LNM$C_NAMLENGTH+1];
2820 unsigned long syiitm = SYI$_MAXBUF;
2822 * Get the SYSGEN parameter MAXBUF
2824 * If the logical 'PERL_MBX_SIZE' is defined
2825 * use the value of the logical instead of PERL_BUFSIZ, but
2826 * keep the size between 128 and MAXBUF.
2829 _ckvmssts_noperl(lib$getsyi(&syiitm, &syssize, 0, 0, 0, 0));
2832 if (vmstrnenv("PERL_MBX_SIZE", csize, 0, fildev, 0)) {
2833 mbxbufsiz = atoi(csize);
2835 mbxbufsiz = PERL_BUFSIZ;
2837 if (mbxbufsiz < 128) mbxbufsiz = 128;
2838 if (mbxbufsiz > syssize) mbxbufsiz = syssize;
2840 _ckvmssts_noperl(sts = sys$crembx(0,chan,mbxbufsiz,mbxbufsiz,0,0,0));
2842 sts = lib$getdvi(&dviitm, chan, NULL, NULL, namdsc, &namdsc->dsc$w_length);
2843 _ckvmssts_noperl(sts);
2844 namdsc->dsc$a_pointer[namdsc->dsc$w_length] = '\0';
2846 } /* end of create_mbx() */
2849 /*{{{ my_popen and my_pclose*/
2851 typedef struct _iosb IOSB;
2852 typedef struct _iosb* pIOSB;
2853 typedef struct _pipe Pipe;
2854 typedef struct _pipe* pPipe;
2855 typedef struct pipe_details Info;
2856 typedef struct pipe_details* pInfo;
2857 typedef struct _srqp RQE;
2858 typedef struct _srqp* pRQE;
2859 typedef struct _tochildbuf CBuf;
2860 typedef struct _tochildbuf* pCBuf;
2863 unsigned short status;
2864 unsigned short count;
2865 unsigned long dvispec;
2868 #pragma member_alignment save
2869 #pragma nomember_alignment quadword
2870 struct _srqp { /* VMS self-relative queue entry */
2871 unsigned long qptr[2];
2873 #pragma member_alignment restore
2874 static RQE RQE_ZERO = {0,0};
2876 struct _tochildbuf {
2879 unsigned short size;
2887 unsigned short chan_in;
2888 unsigned short chan_out;
2890 unsigned int bufsize;
2902 #if defined(PERL_IMPLICIT_CONTEXT)
2903 void *thx; /* Either a thread or an interpreter */
2904 /* pointer, depending on how we're built */
2912 PerlIO *fp; /* file pointer to pipe mailbox */
2913 int useFILE; /* using stdio, not perlio */
2914 int pid; /* PID of subprocess */
2915 int mode; /* == 'r' if pipe open for reading */
2916 int done; /* subprocess has completed */
2917 int waiting; /* waiting for completion/closure */
2918 int closing; /* my_pclose is closing this pipe */
2919 unsigned long completion; /* termination status of subprocess */
2920 pPipe in; /* pipe in to sub */
2921 pPipe out; /* pipe out of sub */
2922 pPipe err; /* pipe of sub's sys$error */
2923 int in_done; /* true when in pipe finished */
2926 unsigned short xchan; /* channel to debug xterm */
2927 unsigned short xchan_valid; /* channel is assigned */
2930 struct exit_control_block
2932 struct exit_control_block *flink;
2933 unsigned long int (*exit_routine)();
2934 unsigned long int arg_count;
2935 unsigned long int *status_address;
2936 unsigned long int exit_status;
2939 typedef struct _closed_pipes Xpipe;
2940 typedef struct _closed_pipes* pXpipe;
2942 struct _closed_pipes {
2943 int pid; /* PID of subprocess */
2944 unsigned long completion; /* termination status of subprocess */
2946 #define NKEEPCLOSED 50
2947 static Xpipe closed_list[NKEEPCLOSED];
2948 static int closed_index = 0;
2949 static int closed_num = 0;
2951 #define RETRY_DELAY "0 ::0.20"
2952 #define MAX_RETRY 50
2954 static int pipe_ef = 0; /* first call to safe_popen inits these*/
2955 static unsigned long mypid;
2956 static unsigned long delaytime[2];
2958 static pInfo open_pipes = NULL;
2959 static $DESCRIPTOR(nl_desc, "NL:");
2961 #define PIPE_COMPLETION_WAIT 30 /* seconds, for EOF/FORCEX wait */
2965 static unsigned long int
2969 unsigned long int retsts = SS$_NORMAL, abort = SS$_TIMEOUT;
2970 int sts, did_stuff, need_eof, j;
2973 * Flush any pending i/o, but since we are in process run-down, be
2974 * careful about referencing PerlIO structures that may already have
2975 * been deallocated. We may not even have an interpreter anymore.
2980 #if defined(PERL_IMPLICIT_CONTEXT)
2981 /* We need to use the Perl context of the thread that created */
2985 aTHX = info->err->thx;
2987 aTHX = info->out->thx;
2989 aTHX = info->in->thx;
2992 #if defined(USE_ITHREADS)
2995 && PL_perlio_fd_refcnt)
2996 PerlIO_flush(info->fp);
2998 fflush((FILE *)info->fp);
3004 next we try sending an EOF...ignore if doesn't work, make sure we
3012 _ckvmssts_noperl(sys$setast(0));
3013 if (info->in && !info->in->shut_on_empty) {
3014 _ckvmssts_noperl(sys$qio(0,info->in->chan_in,IO$_WRITEOF,0,0,0,
3019 _ckvmssts_noperl(sys$setast(1));
3023 /* wait for EOF to have effect, up to ~ 30 sec [default] */
3025 for (j = 0; did_stuff && j < PIPE_COMPLETION_WAIT; j++) {
3030 _ckvmssts_noperl(sys$setast(0));
3031 if (info->waiting && info->done)
3033 nwait += info->waiting;
3034 _ckvmssts_noperl(sys$setast(1));
3044 _ckvmssts_noperl(sys$setast(0));
3045 if (!info->done) { /* Tap them gently on the shoulder . . .*/
3046 sts = sys$forcex(&info->pid,0,&abort);
3047 if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts_noperl(sts);
3050 _ckvmssts_noperl(sys$setast(1));
3054 /* again, wait for effect */
3056 for (j = 0; did_stuff && j < PIPE_COMPLETION_WAIT; j++) {
3061 _ckvmssts_noperl(sys$setast(0));
3062 if (info->waiting && info->done)
3064 nwait += info->waiting;
3065 _ckvmssts_noperl(sys$setast(1));
3074 _ckvmssts_noperl(sys$setast(0));
3075 if (!info->done) { /* We tried to be nice . . . */
3076 sts = sys$delprc(&info->pid,0);
3077 if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts_noperl(sts);
3078 info->done = 1; /* sys$delprc is as done as we're going to get. */
3080 _ckvmssts_noperl(sys$setast(1));
3086 #if defined(PERL_IMPLICIT_CONTEXT)
3087 /* We need to use the Perl context of the thread that created */
3090 if (open_pipes->err)
3091 aTHX = open_pipes->err->thx;
3092 else if (open_pipes->out)
3093 aTHX = open_pipes->out->thx;
3094 else if (open_pipes->in)
3095 aTHX = open_pipes->in->thx;
3097 if ((sts = my_pclose(open_pipes->fp)) == -1) retsts = vaxc$errno;
3098 else if (!(sts & 1)) retsts = sts;
3103 static struct exit_control_block pipe_exitblock =
3104 {(struct exit_control_block *) 0,
3105 pipe_exit_routine, 0, &pipe_exitblock.exit_status, 0};
3107 static void pipe_mbxtofd_ast(pPipe p);
3108 static void pipe_tochild1_ast(pPipe p);
3109 static void pipe_tochild2_ast(pPipe p);
3112 popen_completion_ast(pInfo info)
3114 pInfo i = open_pipes;
3119 info->completion &= 0x0FFFFFFF; /* strip off "control" field */
3120 closed_list[closed_index].pid = info->pid;
3121 closed_list[closed_index].completion = info->completion;
3123 if (closed_index == NKEEPCLOSED)
3128 if (i == info) break;
3131 if (!i) return; /* unlinked, probably freed too */
3136 Writing to subprocess ...
3137 if my_pclose'd: EOF already sent, should shutdown chan_in part of pipe
3139 chan_out may be waiting for "done" flag, or hung waiting
3140 for i/o completion to child...cancel the i/o. This will
3141 put it into "snarf mode" (done but no EOF yet) that discards
3144 Output from subprocess (stdout, stderr) needs to be flushed and
3145 shut down. We try sending an EOF, but if the mbx is full the pipe
3146 routine should still catch the "shut_on_empty" flag, telling it to
3147 use immediate-style reads so that "mbx empty" -> EOF.
3151 if (info->in && !info->in_done) { /* only for mode=w */
3152 if (info->in->shut_on_empty && info->in->need_wake) {
3153 info->in->need_wake = FALSE;
3154 _ckvmssts_noperl(sys$dclast(pipe_tochild2_ast,info->in,0));
3156 _ckvmssts_noperl(sys$cancel(info->in->chan_out));
3160 if (info->out && !info->out_done) { /* were we also piping output? */
3161 info->out->shut_on_empty = TRUE;
3162 iss = sys$qio(0,info->out->chan_in,IO$_WRITEOF|IO$M_NORSWAIT, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3163 if (iss == SS$_MBFULL) iss = SS$_NORMAL;
3164 _ckvmssts_noperl(iss);
3167 if (info->err && !info->err_done) { /* we were piping stderr */
3168 info->err->shut_on_empty = TRUE;
3169 iss = sys$qio(0,info->err->chan_in,IO$_WRITEOF|IO$M_NORSWAIT, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3170 if (iss == SS$_MBFULL) iss = SS$_NORMAL;
3171 _ckvmssts_noperl(iss);
3173 _ckvmssts_noperl(sys$setef(pipe_ef));
3177 static unsigned long int setup_cmddsc(pTHX_ const char *cmd, int check_img, int *suggest_quote, struct dsc$descriptor_s **pvmscmd);
3178 static void vms_execfree(struct dsc$descriptor_s *vmscmd);
3181 we actually differ from vmstrnenv since we use this to
3182 get the RMS IFI to check if SYS$OUTPUT and SYS$ERROR *really*
3183 are pointing to the same thing
3186 static unsigned short
3187 popen_translate(pTHX_ char *logical, char *result)
3190 $DESCRIPTOR(d_table,"LNM$PROCESS_TABLE");
3191 $DESCRIPTOR(d_log,"");
3193 unsigned short length;
3194 unsigned short code;
3196 unsigned short *retlenaddr;
3198 unsigned short l, ifi;
3200 d_log.dsc$a_pointer = logical;
3201 d_log.dsc$w_length = strlen(logical);
3203 itmlst[0].code = LNM$_STRING;
3204 itmlst[0].length = 255;
3205 itmlst[0].buffer_addr = result;
3206 itmlst[0].retlenaddr = &l;
3209 itmlst[1].length = 0;
3210 itmlst[1].buffer_addr = 0;
3211 itmlst[1].retlenaddr = 0;
3213 iss = sys$trnlnm(0, &d_table, &d_log, 0, itmlst);
3214 if (iss == SS$_NOLOGNAM) {
3218 if (!(iss&1)) lib$signal(iss);
3221 logicals for PPFs have a 4 byte prefix ESC+NUL+(RMS IFI)
3222 strip it off and return the ifi, if any
3225 if (result[0] == 0x1b && result[1] == 0x00) {
3226 memmove(&ifi,result+2,2);
3227 strcpy(result,result+4);
3229 return ifi; /* this is the RMS internal file id */
3232 static void pipe_infromchild_ast(pPipe p);
3235 I'm using LIB$(GET|FREE)_VM here so that we can allocate and deallocate
3236 inside an AST routine without worrying about reentrancy and which Perl
3237 memory allocator is being used.
3239 We read data and queue up the buffers, then spit them out one at a
3240 time to the output mailbox when the output mailbox is ready for one.
3243 #define INITIAL_TOCHILDQUEUE 2
3246 pipe_tochild_setup(pTHX_ char *rmbx, char *wmbx)
3250 char mbx1[64], mbx2[64];
3251 struct dsc$descriptor_s d_mbx1 = {sizeof mbx1, DSC$K_DTYPE_T,
3252 DSC$K_CLASS_S, mbx1},
3253 d_mbx2 = {sizeof mbx2, DSC$K_DTYPE_T,
3254 DSC$K_CLASS_S, mbx2};
3255 unsigned int dviitm = DVI$_DEVBUFSIZ;
3259 _ckvmssts_noperl(lib$get_vm(&n, &p));
3261 create_mbx(&p->chan_in , &d_mbx1);
3262 create_mbx(&p->chan_out, &d_mbx2);
3263 _ckvmssts_noperl(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
3266 p->shut_on_empty = FALSE;
3267 p->need_wake = FALSE;
3270 p->iosb.status = SS$_NORMAL;
3271 p->iosb2.status = SS$_NORMAL;
3277 #ifdef PERL_IMPLICIT_CONTEXT
3281 n = sizeof(CBuf) + p->bufsize;
3283 for (j = 0; j < INITIAL_TOCHILDQUEUE; j++) {
3284 _ckvmssts_noperl(lib$get_vm(&n, &b));
3285 b->buf = (char *) b + sizeof(CBuf);
3286 _ckvmssts_noperl(lib$insqhi(b, &p->free));
3289 pipe_tochild2_ast(p);
3290 pipe_tochild1_ast(p);
3296 /* reads the MBX Perl is writing, and queues */
3299 pipe_tochild1_ast(pPipe p)
3302 int iss = p->iosb.status;
3303 int eof = (iss == SS$_ENDOFFILE);
3305 #ifdef PERL_IMPLICIT_CONTEXT
3311 p->shut_on_empty = TRUE;
3313 _ckvmssts_noperl(sys$dassgn(p->chan_in));
3315 _ckvmssts_noperl(iss);
3319 b->size = p->iosb.count;
3320 _ckvmssts_noperl(sts = lib$insqhi(b, &p->wait));
3322 p->need_wake = FALSE;
3323 _ckvmssts_noperl(sys$dclast(pipe_tochild2_ast,p,0));
3326 p->retry = 1; /* initial call */
3329 if (eof) { /* flush the free queue, return when done */
3330 int n = sizeof(CBuf) + p->bufsize;
3332 iss = lib$remqti(&p->free, &b);
3333 if (iss == LIB$_QUEWASEMP) return;
3334 _ckvmssts_noperl(iss);
3335 _ckvmssts_noperl(lib$free_vm(&n, &b));
3339 iss = lib$remqti(&p->free, &b);
3340 if (iss == LIB$_QUEWASEMP) {
3341 int n = sizeof(CBuf) + p->bufsize;
3342 _ckvmssts_noperl(lib$get_vm(&n, &b));
3343 b->buf = (char *) b + sizeof(CBuf);
3345 _ckvmssts_noperl(iss);
3349 iss = sys$qio(0,p->chan_in,
3350 IO$_READVBLK|(p->shut_on_empty ? IO$M_NOWAIT : 0),
3352 pipe_tochild1_ast, p, b->buf, p->bufsize, 0, 0, 0, 0);
3353 if (iss == SS$_ENDOFFILE && p->shut_on_empty) iss = SS$_NORMAL;
3354 _ckvmssts_noperl(iss);
3358 /* writes queued buffers to output, waits for each to complete before
3362 pipe_tochild2_ast(pPipe p)
3365 int iss = p->iosb2.status;
3366 int n = sizeof(CBuf) + p->bufsize;
3367 int done = (p->info && p->info->done) ||
3368 iss == SS$_CANCEL || iss == SS$_ABORT;
3369 #if defined(PERL_IMPLICIT_CONTEXT)
3374 if (p->type) { /* type=1 has old buffer, dispose */
3375 if (p->shut_on_empty) {
3376 _ckvmssts_noperl(lib$free_vm(&n, &b));
3378 _ckvmssts_noperl(lib$insqhi(b, &p->free));
3383 iss = lib$remqti(&p->wait, &b);
3384 if (iss == LIB$_QUEWASEMP) {
3385 if (p->shut_on_empty) {
3387 _ckvmssts_noperl(sys$dassgn(p->chan_out));
3388 *p->pipe_done = TRUE;
3389 _ckvmssts_noperl(sys$setef(pipe_ef));
3391 _ckvmssts_noperl(sys$qio(0,p->chan_out,IO$_WRITEOF,
3392 &p->iosb2, pipe_tochild2_ast, p, 0, 0, 0, 0, 0, 0));
3396 p->need_wake = TRUE;
3399 _ckvmssts_noperl(iss);
3406 _ckvmssts_noperl(sys$qio(0,p->chan_out,IO$_WRITEOF,
3407 &p->iosb2, pipe_tochild2_ast, p, 0, 0, 0, 0, 0, 0));
3409 _ckvmssts_noperl(sys$qio(0,p->chan_out,IO$_WRITEVBLK,
3410 &p->iosb2, pipe_tochild2_ast, p, b->buf, b->size, 0, 0, 0, 0));
3419 pipe_infromchild_setup(pTHX_ char *rmbx, char *wmbx)
3422 char mbx1[64], mbx2[64];
3423 struct dsc$descriptor_s d_mbx1 = {sizeof mbx1, DSC$K_DTYPE_T,
3424 DSC$K_CLASS_S, mbx1},
3425 d_mbx2 = {sizeof mbx2, DSC$K_DTYPE_T,
3426 DSC$K_CLASS_S, mbx2};
3427 unsigned int dviitm = DVI$_DEVBUFSIZ;
3429 int n = sizeof(Pipe);
3430 _ckvmssts_noperl(lib$get_vm(&n, &p));
3431 create_mbx(&p->chan_in , &d_mbx1);
3432 create_mbx(&p->chan_out, &d_mbx2);
3434 _ckvmssts_noperl(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
3435 n = p->bufsize * sizeof(char);
3436 _ckvmssts_noperl(lib$get_vm(&n, &p->buf));
3437 p->shut_on_empty = FALSE;
3440 p->iosb.status = SS$_NORMAL;
3441 #if defined(PERL_IMPLICIT_CONTEXT)
3444 pipe_infromchild_ast(p);
3452 pipe_infromchild_ast(pPipe p)
3454 int iss = p->iosb.status;
3455 int eof = (iss == SS$_ENDOFFILE);
3456 int myeof = (eof && (p->iosb.dvispec == mypid || p->iosb.dvispec == 0));
3457 int kideof = (eof && (p->iosb.dvispec == p->info->pid));
3458 #if defined(PERL_IMPLICIT_CONTEXT)
3462 if (p->info && p->info->closing && p->chan_out) { /* output shutdown */
3463 _ckvmssts_noperl(sys$dassgn(p->chan_out));
3468 input shutdown if EOF from self (done or shut_on_empty)
3469 output shutdown if closing flag set (my_pclose)
3470 send data/eof from child or eof from self
3471 otherwise, re-read (snarf of data from child)
3476 if (myeof && p->chan_in) { /* input shutdown */
3477 _ckvmssts_noperl(sys$dassgn(p->chan_in));
3482 if (myeof || kideof) { /* pass EOF to parent */
3483 _ckvmssts_noperl(sys$qio(0,p->chan_out,IO$_WRITEOF, &p->iosb,
3484 pipe_infromchild_ast, p,
3487 } else if (eof) { /* eat EOF --- fall through to read*/
3489 } else { /* transmit data */
3490 _ckvmssts_noperl(sys$qio(0,p->chan_out,IO$_WRITEVBLK,&p->iosb,
3491 pipe_infromchild_ast,p,
3492 p->buf, p->iosb.count, 0, 0, 0, 0));
3498 /* everything shut? flag as done */
3500 if (!p->chan_in && !p->chan_out) {
3501 *p->pipe_done = TRUE;
3502 _ckvmssts_noperl(sys$setef(pipe_ef));
3506 /* write completed (or read, if snarfing from child)
3507 if still have input active,
3508 queue read...immediate mode if shut_on_empty so we get EOF if empty
3510 check if Perl reading, generate EOFs as needed
3516 iss = sys$qio(0,p->chan_in,IO$_READVBLK|(p->shut_on_empty ? IO$M_NOW : 0),&p->iosb,
3517 pipe_infromchild_ast,p,
3518 p->buf, p->bufsize, 0, 0, 0, 0);
3519 if (p->shut_on_empty && iss == SS$_ENDOFFILE) iss = SS$_NORMAL;
3520 _ckvmssts_noperl(iss);
3521 } else { /* send EOFs for extra reads */
3522 p->iosb.status = SS$_ENDOFFILE;
3523 p->iosb.dvispec = 0;
3524 _ckvmssts_noperl(sys$qio(0,p->chan_out,IO$_SETMODE|IO$M_READATTN,
3526 pipe_infromchild_ast, p, 0, 0, 0, 0));
3532 pipe_mbxtofd_setup(pTHX_ int fd, char *out)
3536 unsigned long dviitm = DVI$_DEVBUFSIZ;
3538 struct dsc$descriptor_s d_mbx = {sizeof mbx, DSC$K_DTYPE_T,
3539 DSC$K_CLASS_S, mbx};
3540 int n = sizeof(Pipe);
3542 /* things like terminals and mbx's don't need this filter */
3543 if (fd && fstat(fd,&s) == 0) {
3544 unsigned long dviitm = DVI$_DEVCHAR, devchar;
3546 unsigned short dev_len;
3547 struct dsc$descriptor_s d_dev;
3549 struct item_list_3 items[3];
3551 unsigned short dvi_iosb[4];
3553 cptr = getname(fd, out, 1);
3554 if (cptr == NULL) _ckvmssts_noperl(SS$_NOSUCHDEV);
3555 d_dev.dsc$a_pointer = out;
3556 d_dev.dsc$w_length = strlen(out);
3557 d_dev.dsc$b_dtype = DSC$K_DTYPE_T;
3558 d_dev.dsc$b_class = DSC$K_CLASS_S;
3561 items[0].code = DVI$_DEVCHAR;
3562 items[0].bufadr = &devchar;
3563 items[0].retadr = NULL;
3565 items[1].code = DVI$_FULLDEVNAM;
3566 items[1].bufadr = device;
3567 items[1].retadr = &dev_len;
3571 status = sys$getdviw
3572 (NO_EFN, 0, &d_dev, items, dvi_iosb, NULL, NULL, NULL);
3573 _ckvmssts_noperl(status);
3574 if ($VMS_STATUS_SUCCESS(dvi_iosb[0])) {
3575 device[dev_len] = 0;
3577 if (!(devchar & DEV$M_DIR)) {
3578 strcpy(out, device);
3584 _ckvmssts_noperl(lib$get_vm(&n, &p));
3585 p->fd_out = dup(fd);
3586 create_mbx(&p->chan_in, &d_mbx);
3587 _ckvmssts_noperl(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
3588 n = (p->bufsize+1) * sizeof(char);
3589 _ckvmssts_noperl(lib$get_vm(&n, &p->buf));
3590 p->shut_on_empty = FALSE;
3595 _ckvmssts_noperl(sys$qio(0, p->chan_in, IO$_READVBLK, &p->iosb,
3596 pipe_mbxtofd_ast, p,
3597 p->buf, p->bufsize, 0, 0, 0, 0));
3603 pipe_mbxtofd_ast(pPipe p)
3605 int iss = p->iosb.status;
3606 int done = p->info->done;
3608 int eof = (iss == SS$_ENDOFFILE);
3609 int myeof = eof && ((p->iosb.dvispec == mypid)||(p->iosb.dvispec == 0));
3610 int err = !(iss&1) && !eof;
3611 #if defined(PERL_IMPLICIT_CONTEXT)
3615 if (done && myeof) { /* end piping */
3617 sys$dassgn(p->chan_in);
3618 *p->pipe_done = TRUE;
3619 _ckvmssts_noperl(sys$setef(pipe_ef));
3623 if (!err && !eof) { /* good data to send to file */
3624 p->buf[p->iosb.count] = '\n';
3625 iss2 = write(p->fd_out, p->buf, p->iosb.count+1);
3628 if (p->retry < MAX_RETRY) {
3629 _ckvmssts_noperl(sys$setimr(0,delaytime,pipe_mbxtofd_ast,p));
3635 _ckvmssts_noperl(iss);
3639 iss = sys$qio(0, p->chan_in, IO$_READVBLK|(p->shut_on_empty ? IO$M_NOW : 0), &p->iosb,
3640 pipe_mbxtofd_ast, p,
3641 p->buf, p->bufsize, 0, 0, 0, 0);
3642 if (p->shut_on_empty && (iss == SS$_ENDOFFILE)) iss = SS$_NORMAL;
3643 _ckvmssts_noperl(iss);
3647 typedef struct _pipeloc PLOC;
3648 typedef struct _pipeloc* pPLOC;
3652 char dir[NAM$C_MAXRSS+1];
3654 static pPLOC head_PLOC = 0;
3657 free_pipelocs(pTHX_ void *head)
3660 pPLOC *pHead = (pPLOC *)head;
3672 store_pipelocs(pTHX)
3681 char temp[NAM$C_MAXRSS+1];
3685 free_pipelocs(aTHX_ &head_PLOC);
3687 /* the . directory from @INC comes last */
3689 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3690 if (p == NULL) _ckvmssts_noperl(SS$_INSFMEM);
3691 p->next = head_PLOC;
3693 strcpy(p->dir,"./");
3695 /* get the directory from $^X */
3697 unixdir = PerlMem_malloc(VMS_MAXRSS);
3698 if (unixdir == NULL) _ckvmssts_noperl(SS$_INSFMEM);
3700 #ifdef PERL_IMPLICIT_CONTEXT
3701 if (aTHX && PL_origargv && PL_origargv[0]) { /* maybe nul if embedded Perl */
3703 if (PL_origargv && PL_origargv[0]) { /* maybe nul if embedded Perl */
3705 strcpy(temp, PL_origargv[0]);
3706 x = strrchr(temp,']');
3708 x = strrchr(temp,'>');
3710 /* It could be a UNIX path */
3711 x = strrchr(temp,'/');
3717 /* Got a bare name, so use default directory */
3722 if ((tounixpath_utf8(temp, unixdir, NULL)) != NULL) {
3723 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3724 if (p == NULL) _ckvmssts_noperl(SS$_INSFMEM);
3725 p->next = head_PLOC;
3727 strncpy(p->dir,unixdir,sizeof(p->dir)-1);
3728 p->dir[NAM$C_MAXRSS] = '\0';
3732 /* reverse order of @INC entries, skip "." since entered above */
3734 #ifdef PERL_IMPLICIT_CONTEXT
3737 if (PL_incgv) av = GvAVn(PL_incgv);
3739 for (i = 0; av && i <= AvFILL(av); i++) {
3740 dirsv = *av_fetch(av,i,TRUE);
3742 if (SvROK(dirsv)) continue;
3743 dir = SvPVx(dirsv,n_a);
3744 if (strcmp(dir,".") == 0) continue;
3745 if ((tounixpath_utf8(dir, unixdir, NULL)) == NULL)
3748 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3749 p->next = head_PLOC;
3751 strncpy(p->dir,unixdir,sizeof(p->dir)-1);
3752 p->dir[NAM$C_MAXRSS] = '\0';
3755 /* most likely spot (ARCHLIB) put first in the list */
3758 if ((tounixpath_utf8(ARCHLIB_EXP, unixdir, NULL)) != NULL) {
3759 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3760 if (p == NULL) _ckvmssts_noperl(SS$_INSFMEM);
3761 p->next = head_PLOC;
3763 strncpy(p->dir,unixdir,sizeof(p->dir)-1);
3764 p->dir[NAM$C_MAXRSS] = '\0';
3767 PerlMem_free(unixdir);
3771 Perl_cando_by_name_int
3772 (pTHX_ I32 bit, bool effective, const char *fname, int opts);
3773 #if !defined(PERL_IMPLICIT_CONTEXT)
3774 #define cando_by_name_int Perl_cando_by_name_int
3776 #define cando_by_name_int(a,b,c,d) Perl_cando_by_name_int(aTHX_ a,b,c,d)
3782 static int vmspipe_file_status = 0;
3783 static char vmspipe_file[NAM$C_MAXRSS+1];
3785 /* already found? Check and use ... need read+execute permission */
3787 if (vmspipe_file_status == 1) {
3788 if (cando_by_name_int(S_IRUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)
3789 && cando_by_name_int
3790 (S_IXUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)) {
3791 return vmspipe_file;
3793 vmspipe_file_status = 0;
3796 /* scan through stored @INC, $^X */
3798 if (vmspipe_file_status == 0) {
3799 char file[NAM$C_MAXRSS+1];
3800 pPLOC p = head_PLOC;
3805 strcpy(file, p->dir);
3806 dirlen = strlen(file);
3807 strncat(file, "vmspipe.com",NAM$C_MAXRSS - dirlen);
3808 file[NAM$C_MAXRSS] = '\0';
3811 exp_res = do_rmsexpand
3812 (file, vmspipe_file, 0, NULL, PERL_RMSEXPAND_M_VMS, NULL, NULL);
3813 if (!exp_res) continue;
3815 if (cando_by_name_int
3816 (S_IRUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)
3817 && cando_by_name_int
3818 (S_IXUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)) {
3819 vmspipe_file_status = 1;
3820 return vmspipe_file;
3823 vmspipe_file_status = -1; /* failed, use tempfiles */
3830 vmspipe_tempfile(pTHX)
3832 char file[NAM$C_MAXRSS+1];
3834 static int index = 0;
3838 /* create a tempfile */
3840 /* we can't go from W, shr=get to R, shr=get without
3841 an intermediate vulnerable state, so don't bother trying...
3843 and lib$spawn doesn't shr=put, so have to close the write
3845 So... match up the creation date/time and the FID to
3846 make sure we're dealing with the same file
3851 if (!decc_filename_unix_only) {
3852 sprintf(file,"sys$scratch:perlpipe_%08.8x_%d.com",mypid,index);
3853 fp = fopen(file,"w");
3855 sprintf(file,"sys$login:perlpipe_%08.8x_%d.com",mypid,index);
3856 fp = fopen(file,"w");
3858 sprintf(file,"sys$disk:[]perlpipe_%08.8x_%d.com",mypid,index);
3859 fp = fopen(file,"w");
3864 sprintf(file,"/tmp/perlpipe_%08.8x_%d.com",mypid,index);
3865 fp = fopen(file,"w");
3867 sprintf(file,"/sys$login/perlpipe_%08.8x_%d.com",mypid,index);
3868 fp = fopen(file,"w");
3870 sprintf(file,"./perlpipe_%08.8x_%d.com",mypid,index);
3871 fp = fopen(file,"w");
3875 if (!fp) return 0; /* we're hosed */
3877 fprintf(fp,"$! 'f$verify(0)'\n");
3878 fprintf(fp,"$! --- protect against nonstandard definitions ---\n");
3879 fprintf(fp,"$ perl_cfile = f$environment(\"procedure\")\n");
3880 fprintf(fp,"$ perl_define = \"define/nolog\"\n");
3881 fprintf(fp,"$ perl_on = \"set noon\"\n");
3882 fprintf(fp,"$ perl_exit = \"exit\"\n");
3883 fprintf(fp,"$ perl_del = \"delete\"\n");
3884 fprintf(fp,"$ pif = \"if\"\n");
3885 fprintf(fp,"$! --- define i/o redirection (sys$output set by lib$spawn)\n");
3886 fprintf(fp,"$ pif perl_popen_in .nes. \"\" then perl_define/user/name_attributes=confine sys$input 'perl_popen_in'\n");
3887 fprintf(fp,"$ pif perl_popen_err .nes. \"\" then perl_define/user/name_attributes=confine sys$error 'perl_popen_err'\n");
3888 fprintf(fp,"$ pif perl_popen_out .nes. \"\" then perl_define sys$output 'perl_popen_out'\n");
3889 fprintf(fp,"$! --- build command line to get max possible length\n");
3890 fprintf(fp,"$c=perl_popen_cmd0\n");
3891 fprintf(fp,"$c=c+perl_popen_cmd1\n");
3892 fprintf(fp,"$c=c+perl_popen_cmd2\n");
3893 fprintf(fp,"$x=perl_popen_cmd3\n");
3894 fprintf(fp,"$c=c+x\n");
3895 fprintf(fp,"$ perl_on\n");
3896 fprintf(fp,"$ 'c'\n");
3897 fprintf(fp,"$ perl_status = $STATUS\n");
3898 fprintf(fp,"$ perl_del 'perl_cfile'\n");
3899 fprintf(fp,"$ perl_exit 'perl_status'\n");
3902 fgetname(fp, file, 1);
3903 fstat(fileno(fp), (struct stat *)&s0);
3906 if (decc_filename_unix_only)
3907 do_tounixspec(file, file, 0, NULL);
3908 fp = fopen(file,"r","shr=get");
3910 fstat(fileno(fp), (struct stat *)&s1);
3912 cmp_result = VMS_INO_T_COMPARE(s0.crtl_stat.st_ino, s1.crtl_stat.st_ino);
3913 if ((cmp_result != 0) && (s0.st_ctime != s1.st_ctime)) {
3922 static int vms_is_syscommand_xterm(void)
3924 const static struct dsc$descriptor_s syscommand_dsc =
3925 { 11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND" };
3927 const static struct dsc$descriptor_s decwdisplay_dsc =
3928 { 12, DSC$K_DTYPE_T, DSC$K_CLASS_S, "DECW$DISPLAY" };
3930 struct item_list_3 items[2];
3931 unsigned short dvi_iosb[4];
3932 unsigned long devchar;
3933 unsigned long devclass;
3936 /* Very simple check to guess if sys$command is a decterm? */
3937 /* First see if the DECW$DISPLAY: device exists */
3939 items[0].code = DVI$_DEVCHAR;
3940 items[0].bufadr = &devchar;
3941 items[0].retadr = NULL;
3945 status = sys$getdviw
3946 (NO_EFN, 0, &decwdisplay_dsc, items, dvi_iosb, NULL, NULL, NULL);
3948 if ($VMS_STATUS_SUCCESS(status)) {
3949 status = dvi_iosb[0];
3952 if (!$VMS_STATUS_SUCCESS(status)) {
3953 SETERRNO(EVMSERR, status);
3957 /* If it does, then for now assume that we are on a workstation */
3958 /* Now verify that SYS$COMMAND is a terminal */
3959 /* for creating the debugger DECTerm */
3962 items[0].code = DVI$_DEVCLASS;
3963 items[0].bufadr = &devclass;
3964 items[0].retadr = NULL;
3968 status = sys$getdviw
3969 (NO_EFN, 0, &syscommand_dsc, items, dvi_iosb, NULL, NULL, NULL);
3971 if ($VMS_STATUS_SUCCESS(status)) {
3972 status = dvi_iosb[0];
3975 if (!$VMS_STATUS_SUCCESS(status)) {
3976 SETERRNO(EVMSERR, status);
3980 if (devclass == DC$_TERM) {
3987 /* If we are on a DECTerm, we can pretend to fork xterms when requested */
3988 static PerlIO * create_forked_xterm(pTHX_ const char *cmd, const char *mode)
3993 char device_name[65];
3994 unsigned short device_name_len;
3995 struct dsc$descriptor_s customization_dsc;
3996 struct dsc$descriptor_s device_name_dsc;
3999 char customization[200];
4003 unsigned short p_chan;
4005 unsigned short iosb[4];
4006 struct item_list_3 items[2];
4007 const char * cust_str =
4008 "DECW$TERMINAL.iconName:\tPerl Dbg\nDECW$TERMINAL.title:\t%40s\n";
4009 struct dsc$descriptor_s d_mbx1 = {sizeof mbx1, DSC$K_DTYPE_T,
4010 DSC$K_CLASS_S, mbx1};
4012 /* LIB$FIND_IMAGE_SIGNAL needs a handler */
4013 /*---------------------------------------*/
4014 VAXC$ESTABLISH((__vms_handler)lib$sig_to_ret);
4017 /* Make sure that this is from the Perl debugger */
4018 ret_char = strstr(cmd," xterm ");
4019 if (ret_char == NULL)
4021 cptr = ret_char + 7;
4022 ret_char = strstr(cmd,"tty");
4023 if (ret_char == NULL)
4025 ret_char = strstr(cmd,"sleep");
4026 if (ret_char == NULL)
4029 if (decw_term_port == 0) {
4030 $DESCRIPTOR(filename1_dsc, "DECW$TERMINALSHR12");
4031 $DESCRIPTOR(filename2_dsc, "DECW$TERMINALSHR");
4032 $DESCRIPTOR(decw_term_port_dsc, "DECW$TERM_PORT");
4034 status = lib$find_image_symbol
4036 &decw_term_port_dsc,
4037 (void *)&decw_term_port,
4041 /* Try again with the other image name */
4042 if (!$VMS_STATUS_SUCCESS(status)) {
4044 status = lib$find_image_symbol
4046 &decw_term_port_dsc,
4047 (void *)&decw_term_port,
4056 /* No decw$term_port, give it up */
4057 if (!$VMS_STATUS_SUCCESS(status))
4060 /* Are we on a workstation? */
4061 /* to do: capture the rows / columns and pass their properties */
4062 ret_stat = vms_is_syscommand_xterm();
4066 /* Make the title: */
4067 ret_char = strstr(cptr,"-title");
4068 if (ret_char != NULL) {
4069 while ((*cptr != 0) && (*cptr != '\"')) {
4075 while ((*cptr != 0) && (*cptr != '\"')) {
4088 strcpy(title,"Perl Debug DECTerm");
4090 sprintf(customization, cust_str, title);
4092 customization_dsc.dsc$a_pointer = customization;
4093 customization_dsc.dsc$w_length = strlen(customization);
4094 customization_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
4095 customization_dsc.dsc$b_class = DSC$K_CLASS_S;
4097 device_name_dsc.dsc$a_pointer = device_name;
4098 device_name_dsc.dsc$w_length = sizeof device_name -1;
4099 device_name_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
4100 device_name_dsc.dsc$b_class = DSC$K_CLASS_S;
4102 device_name_len = 0;
4104 /* Try to create the window */
4105 status = (*decw_term_port)
4114 if (!$VMS_STATUS_SUCCESS(status)) {
4115 SETERRNO(EVMSERR, status);
4119 device_name[device_name_len] = '\0';
4121 /* Need to set this up to look like a pipe for cleanup */
4123 status = lib$get_vm(&n, &info);
4124 if (!$VMS_STATUS_SUCCESS(status)) {
4125 SETERRNO(ENOMEM, status);
4131 info->completion = 0;
4132 info->closing = FALSE;
4139 info->in_done = TRUE;
4140 info->out_done = TRUE;
4141 info->err_done = TRUE;
4143 /* Assign a channel on this so that it will persist, and not login */
4144 /* We stash this channel in the info structure for reference. */
4145 /* The created xterm self destructs when the last channel is removed */
4146 /* and it appears that perl5db.pl (perl debugger) does this routinely */
4147 /* So leave this assigned. */
4148 device_name_dsc.dsc$w_length = device_name_len;
4149 status = sys$assign(&device_name_dsc,&info->xchan,0,0);
4150 if (!$VMS_STATUS_SUCCESS(status)) {
4151 SETERRNO(EVMSERR, status);
4154 info->xchan_valid = 1;
4156 /* Now create a mailbox to be read by the application */
4158 create_mbx(&p_chan, &d_mbx1);
4160 /* write the name of the created terminal to the mailbox */
4161 status = sys$qiow(NO_EFN, p_chan, IO$_WRITEVBLK|IO$M_NOW,
4162 iosb, NULL, NULL, device_name, device_name_len, 0, 0, 0, 0);
4164 if (!$VMS_STATUS_SUCCESS(status)) {
4165 SETERRNO(EVMSERR, status);
4169 info->fp = PerlIO_open(mbx1, mode);
4171 /* Done with this channel */
4174 /* If any errors, then clean up */
4177 _ckvmssts_noperl(lib$free_vm(&n, &info));
4185 static I32 my_pclose_pinfo(pTHX_ pInfo info);
4188 safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
4190 static int handler_set_up = FALSE;
4192 unsigned long int sts, flags = CLI$M_NOWAIT;
4193 /* The use of a GLOBAL table (as was done previously) rendered
4194 * Perl's qx() or `` unusable from a C<$ SET SYMBOL/SCOPE=NOGLOBAL> DCL
4195 * environment. Hence we've switched to LOCAL symbol table.
4197 unsigned int table = LIB$K_CLI_LOCAL_SYM;
4199 char *p, mode[10], symbol[MAX_DCL_SYMBOL+1], *vmspipe;
4200 char *in, *out, *err, mbx[512];
4202 char tfilebuf[NAM$C_MAXRSS+1];
4204 char cmd_sym_name[20];
4205 struct dsc$descriptor_s d_symbol= {0, DSC$K_DTYPE_T,
4206 DSC$K_CLASS_S, symbol};
4207 struct dsc$descriptor_s vmspipedsc = {0, DSC$K_DTYPE_T,
4209 struct dsc$descriptor_s d_sym_cmd = {0, DSC$K_DTYPE_T,
4210 DSC$K_CLASS_S, cmd_sym_name};
4211 struct dsc$descriptor_s *vmscmd;
4212 $DESCRIPTOR(d_sym_in ,"PERL_POPEN_IN");
4213 $DESCRIPTOR(d_sym_out,"PERL_POPEN_OUT");
4214 $DESCRIPTOR(d_sym_err,"PERL_POPEN_ERR");
4216 /* Check here for Xterm create request. This means looking for
4217 * "3>&1 xterm\b" and "\btty 1>&3\b$" in the command, and that it
4218 * is possible to create an xterm.
4220 if (*in_mode == 'r') {
4223 xterm_fd = create_forked_xterm(aTHX_ cmd, in_mode);
4224 if (xterm_fd != NULL)
4228 if (!head_PLOC) store_pipelocs(aTHX); /* at least TRY to use a static vmspipe file */
4230 /* once-per-program initialization...
4231 note that the SETAST calls and the dual test of pipe_ef
4232 makes sure that only the FIRST thread through here does
4233 the initialization...all other threads wait until it's
4236 Yeah, uglier than a pthread call, it's got all the stuff inline
4237 rather than in a separate routine.
4241 _ckvmssts_noperl(sys$setast(0));
4243 unsigned long int pidcode = JPI$_PID;
4244 $DESCRIPTOR(d_delay, RETRY_DELAY);
4245 _ckvmssts_noperl(lib$get_ef(&pipe_ef));
4246 _ckvmssts_noperl(lib$getjpi(&pidcode,0,0,&mypid,0,0));
4247 _ckvmssts_noperl(sys$bintim(&d_delay, delaytime));
4249 if (!handler_set_up) {
4250 _ckvmssts_noperl(sys$dclexh(&pipe_exitblock));
4251 handler_set_up = TRUE;
4253 _ckvmssts_noperl(sys$setast(1));
4256 /* see if we can find a VMSPIPE.COM */
4259 vmspipe = find_vmspipe(aTHX);
4261 strcpy(tfilebuf+1,vmspipe);
4262 } else { /* uh, oh...we're in tempfile hell */
4263 tpipe = vmspipe_tempfile(aTHX);
4264 if (!tpipe) { /* a fish popular in Boston */
4265 if (ckWARN(WARN_PIPE)) {
4266 Perl_warner(aTHX_ packWARN(WARN_PIPE),"unable to find VMSPIPE.COM for i/o piping");
4270 fgetname(tpipe,tfilebuf+1,1);
4272 vmspipedsc.dsc$a_pointer = tfilebuf;
4273 vmspipedsc.dsc$w_length = strlen(tfilebuf);
4275 sts = setup_cmddsc(aTHX_ cmd,0,0,&vmscmd);
4278 case RMS$_FNF: case RMS$_DNF:
4279 set_errno(ENOENT); break;
4281 set_errno(ENOTDIR); break;
4283 set_errno(ENODEV); break;
4285 set_errno(EACCES); break;
4287 set_errno(EINVAL); break;
4288 case CLI$_BUFOVF: case RMS$_RTB: case CLI$_TKNOVF: case CLI$_RSLOVF:
4289 set_errno(E2BIG); break;
4290 case LIB$_INVARG: case LIB$_INVSTRDES: case SS$_ACCVIO: /* shouldn't happen */
4291 _ckvmssts_noperl(sts); /* fall through */
4292 default: /* SS$_DUPLNAM, SS$_CLI, resource exhaustion, etc. */
4295 set_vaxc_errno(sts);
4296 if (*in_mode != 'n' && ckWARN(WARN_PIPE)) {
4297 Perl_warner(aTHX_ packWARN(WARN_PIPE),"Can't pipe \"%*s\": %s", strlen(cmd), cmd, Strerror(errno));
4303 _ckvmssts_noperl(lib$get_vm(&n, &info));
4305 strcpy(mode,in_mode);
4308 info->completion = 0;
4309 info->closing = FALSE;
4316 info->in_done = TRUE;
4317 info->out_done = TRUE;
4318 info->err_done = TRUE;
4320 info->xchan_valid = 0;
4322 in = PerlMem_malloc(VMS_MAXRSS);
4323 if (in == NULL) _ckvmssts_noperl(SS$_INSFMEM);
4324 out = PerlMem_malloc(VMS_MAXRSS);
4325 if (out == NULL) _ckvmssts_noperl(SS$_INSFMEM);
4326 err = PerlMem_malloc(VMS_MAXRSS);
4327 if (err == NULL) _ckvmssts_noperl(SS$_INSFMEM);
4329 in[0] = out[0] = err[0] = '\0';
4331 if ((p = strchr(mode,'F')) != NULL) { /* F -> use FILE* */
4335 if ((p = strchr(mode,'W')) != NULL) { /* W -> wait for completion */
4340 if (*mode == 'r') { /* piping from subroutine */
4342 info->out = pipe_infromchild_setup(aTHX_ mbx,out);
4344 info->out->pipe_done = &info->out_done;
4345 info->out_done = FALSE;
4346 info->out->info = info;
4348 if (!info->useFILE) {
4349 info->fp = PerlIO_open(mbx, mode);
4351 info->fp = (PerlIO *) freopen(mbx, mode, stdin);
4352 Perl_vmssetuserlnm(aTHX_ "SYS$INPUT",mbx);
4355 if (!info->fp && info->out) {
4356 sys$cancel(info->out->chan_out);
4358 while (!info->out_done) {
4360 _ckvmssts_noperl(sys$setast(0));
4361 done = info->out_done;
4362 if (!done) _ckvmssts_noperl(sys$clref(pipe_ef));
4363 _ckvmssts_noperl(sys$setast(1));
4364 if (!done) _ckvmssts_noperl(sys$waitfr(pipe_ef));
4367 if (info->out->buf) {
4368 n = info->out->bufsize * sizeof(char);
4369 _ckvmssts_noperl(lib$free_vm(&n, &info->out->buf));
4372 _ckvmssts_noperl(lib$free_vm(&n, &info->out));
4374 _ckvmssts_noperl(lib$free_vm(&n, &info));
4379 info->err = pipe_mbxtofd_setup(aTHX_ fileno(stderr), err);
4381 info->err->pipe_done = &info->err_done;
4382 info->err_done = FALSE;
4383 info->err->info = info;
4386 } else if (*mode == 'w') { /* piping to subroutine */
4388 info->out = pipe_mbxtofd_setup(aTHX_ fileno(stdout), out);
4390 info->out->pipe_done = &info->out_done;
4391 info->out_done = FALSE;
4392 info->out->info = info;
4395 info->err = pipe_mbxtofd_setup(aTHX_ fileno(stderr), err);
4397 info->err->pipe_done = &info->err_done;
4398 info->err_done = FALSE;
4399 info->err->info = info;
4402 info->in = pipe_tochild_setup(aTHX_ in,mbx);
4403 if (!info->useFILE) {
4404 info->fp = PerlIO_open(mbx, mode);
4406 info->fp = (PerlIO *) freopen(mbx, mode, stdout);
4407 Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT",mbx);
4411 info->in->pipe_done = &info->in_done;
4412 info->in_done = FALSE;
4413 info->in->info = info;
4417 if (!info->fp && info->in) {
4419 _ckvmssts_noperl(sys$qiow(0,info->in->chan_in, IO$_WRITEOF, 0,
4420 0, 0, 0, 0, 0, 0, 0, 0));
4422 while (!info->in_done) {
4424 _ckvmssts_noperl(sys$setast(0));
4425 done = info->in_done;
4426 if (!done) _ckvmssts_noperl(sys$clref(pipe_ef));
4427 _ckvmssts_noperl(sys$setast(1));
4428 if (!done) _ckvmssts_noperl(sys$waitfr(pipe_ef));
4431 if (info->in->buf) {
4432 n = info->in->bufsize * sizeof(char);
4433 _ckvmssts_noperl(lib$free_vm(&n, &info->in->buf));
4436 _ckvmssts_noperl(lib$free_vm(&n, &info->in));
4438 _ckvmssts_noperl(lib$free_vm(&n, &info));
4444 } else if (*mode == 'n') { /* separate subprocess, no Perl i/o */
4445 info->out = pipe_mbxtofd_setup(aTHX_ fileno(stdout), out);
4447 info->out->pipe_done = &info->out_done;
4448 info->out_done = FALSE;
4449 info->out->info = info;
4452 info->err = pipe_mbxtofd_setup(aTHX_ fileno(stderr), err);
4454 info->err->pipe_done = &info->err_done;
4455 info->err_done = FALSE;
4456 info->err->info = info;
4460 symbol[MAX_DCL_SYMBOL] = '\0';
4462 strncpy(symbol, in, MAX_DCL_SYMBOL);
4463 d_symbol.dsc$w_length = strlen(symbol);
4464 _ckvmssts_noperl(lib$set_symbol(&d_sym_in, &d_symbol, &table));
4466 strncpy(symbol, err, MAX_DCL_SYMBOL);
4467 d_symbol.dsc$w_length = strlen(symbol);
4468 _ckvmssts_noperl(lib$set_symbol(&d_sym_err, &d_symbol, &table));
4470 strncpy(symbol, out, MAX_DCL_SYMBOL);
4471 d_symbol.dsc$w_length = strlen(symbol);
4472 _ckvmssts_noperl(lib$set_symbol(&d_sym_out, &d_symbol, &table));
4474 /* Done with the names for the pipes */
4479 p = vmscmd->dsc$a_pointer;
4480 while (*p == ' ' || *p == '\t') p++; /* remove leading whitespace */
4481 if (*p == '$') p++; /* remove leading $ */
4482 while (*p == ' ' || *p == '\t') p++;
4484 for (j = 0; j < 4; j++) {
4485 sprintf(cmd_sym_name,"PERL_POPEN_CMD%d",j);
4486 d_sym_cmd.dsc$w_length = strlen(cmd_sym_name);
4488 strncpy(symbol, p, MAX_DCL_SYMBOL);
4489 d_symbol.dsc$w_length = strlen(symbol);
4490 _ckvmssts_noperl(lib$set_symbol(&d_sym_cmd, &d_symbol, &table));
4492 if (strlen(p) > MAX_DCL_SYMBOL) {
4493 p += MAX_DCL_SYMBOL;
4498 _ckvmssts_noperl(sys$setast(0));
4499 info->next=open_pipes; /* prepend to list */
4501 _ckvmssts_noperl(sys$setast(1));
4502 /* Omit arg 2 (input file) so the child will get the parent's SYS$INPUT
4503 * and SYS$COMMAND. vmspipe.com will redefine SYS$INPUT, but we'll still
4504 * have SYS$COMMAND if we need it.
4506 _ckvmssts_noperl(lib$spawn(&vmspipedsc, 0, &nl_desc, &flags,
4507 0, &info->pid, &info->completion,
4508 0, popen_completion_ast,info,0,0,0));
4510 /* if we were using a tempfile, close it now */
4512 if (tpipe) fclose(tpipe);
4514 /* once the subprocess is spawned, it has copied the symbols and
4515 we can get rid of ours */
4517 for (j = 0; j < 4; j++) {
4518 sprintf(cmd_sym_name,"PERL_POPEN_CMD%d",j);
4519 d_sym_cmd.dsc$w_length = strlen(cmd_sym_name);
4520 _ckvmssts_noperl(lib$delete_symbol(&d_sym_cmd, &table));
4522 _ckvmssts_noperl(lib$delete_symbol(&d_sym_in, &table));
4523 _ckvmssts_noperl(lib$delete_symbol(&d_sym_err, &table));
4524 _ckvmssts_noperl(lib$delete_symbol(&d_sym_out, &table));
4525 vms_execfree(vmscmd);
4527 #ifdef PERL_IMPLICIT_CONTEXT
4530 PL_forkprocess = info->pid;
4537 _ckvmssts_noperl(sys$setast(0));
4539 if (!done) _ckvmssts_noperl(sys$clref(pipe_ef));
4540 _ckvmssts_noperl(sys$setast(1));
4541 if (!done) _ckvmssts_noperl(sys$waitfr(pipe_ef));
4543 *psts = info->completion;
4544 /* Caller thinks it is open and tries to close it. */
4545 /* This causes some problems, as it changes the error status */
4546 /* my_pclose(info->fp); */
4548 /* If we did not have a file pointer open, then we have to */
4549 /* clean up here or eventually we will run out of something */
4551 if (info->fp == NULL) {
4552 my_pclose_pinfo(aTHX_ info);
4560 } /* end of safe_popen */
4563 /*{{{ PerlIO *my_popen(char *cmd, char *mode)*/
4565 Perl_my_popen(pTHX_ const char *cmd, const char *mode)
4569 TAINT_PROPER("popen");
4570 PERL_FLUSHALL_FOR_CHILD;
4571 return safe_popen(aTHX_ cmd,mode,&sts);
4577 /* Routine to close and cleanup a pipe info structure */
4579 static I32 my_pclose_pinfo(pTHX_ pInfo info) {
4581 unsigned long int retsts;
4586 /* If we were writing to a subprocess, insure that someone reading from
4587 * the mailbox gets an EOF. It looks like a simple fclose() doesn't
4588 * produce an EOF record in the mailbox.
4590 * well, at least sometimes it *does*, so we have to watch out for
4591 * the first EOF closing the pipe (and DASSGN'ing the channel)...
4595 #if defined(USE_ITHREADS)
4598 && PL_perlio_fd_refcnt)
4599 PerlIO_flush(info->fp);
4601 fflush((FILE *)info->fp);
4604 _ckvmssts(sys$setast(0));
4605 info->closing = TRUE;
4606 done = info->done && info->in_done && info->out_done && info->err_done;
4607 /* hanging on write to Perl's input? cancel it */
4608 if (info->mode == 'r' && info->out && !info->out_done) {
4609 if (info->out->chan_out) {
4610 _ckvmssts(sys$cancel(info->out->chan_out));
4611 if (!info->out->chan_in) { /* EOF generation, need AST */
4612 _ckvmssts(sys$dclast(pipe_infromchild_ast,info->out,0));
4616 if (info->in && !info->in_done && !info->in->shut_on_empty) /* EOF if hasn't had one yet */
4617 _ckvmssts(sys$qio(0,info->in->chan_in,IO$_WRITEOF,0,0,0,
4619 _ckvmssts(sys$setast(1));
4622 #if defined(USE_ITHREADS)
4625 && PL_perlio_fd_refcnt)
4626 PerlIO_close(info->fp);
4628 fclose((FILE *)info->fp);
4631 we have to wait until subprocess completes, but ALSO wait until all
4632 the i/o completes...otherwise we'll be freeing the "info" structure
4633 that the i/o ASTs could still be using...
4637 _ckvmssts(sys$setast(0));
4638 done = info->done && info->in_done && info->out_done && info->err_done;
4639 if (!done) _ckvmssts(sys$clref(pipe_ef));
4640 _ckvmssts(sys$setast(1));
4641 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
4643 retsts = info->completion;
4645 /* remove from list of open pipes */
4646 _ckvmssts(sys$setast(0));
4648 for (next = open_pipes; next != NULL; last = next, next = next->next) {
4654 last->next = info->next;
4656 open_pipes = info->next;
4657 _ckvmssts(sys$setast(1));
4659 /* free buffers and structures */
4662 if (info->in->buf) {
4663 n = info->in->bufsize * sizeof(char);
4664 _ckvmssts(lib$free_vm(&n, &info->in->buf));
4667 _ckvmssts(lib$free_vm(&n, &info->in));
4670 if (info->out->buf) {
4671 n = info->out->bufsize * sizeof(char);
4672 _ckvmssts(lib$free_vm(&n, &info->out->buf));
4675 _ckvmssts(lib$free_vm(&n, &info->out));
4678 if (info->err->buf) {
4679 n = info->err->bufsize * sizeof(char);
4680 _ckvmssts(lib$free_vm(&n, &info->err->buf));
4683 _ckvmssts(lib$free_vm(&n, &info->err));
4686 _ckvmssts(lib$free_vm(&n, &info));
4692 /*{{{ I32 my_pclose(PerlIO *fp)*/
4693 I32 Perl_my_pclose(pTHX_ PerlIO *fp)
4695 pInfo info, last = NULL;
4698 /* Fixme - need ast and mutex protection here */
4699 for (info = open_pipes; info != NULL; last = info, info = info->next)
4700 if (info->fp == fp) break;
4702 if (info == NULL) { /* no such pipe open */
4703 set_errno(ECHILD); /* quoth POSIX */
4704 set_vaxc_errno(SS$_NONEXPR);
4708 ret_status = my_pclose_pinfo(aTHX_ info);
4712 } /* end of my_pclose() */
4714 #if defined(__CRTL_VER) && __CRTL_VER >= 70200000
4715 /* Roll our own prototype because we want this regardless of whether
4716 * _VMS_WAIT is defined.
4718 __pid_t __vms_waitpid( __pid_t __pid, int *__stat_loc, int __options );
4720 /* sort-of waitpid; special handling of pipe clean-up for subprocesses
4721 created with popen(); otherwise partially emulate waitpid() unless
4722 we have a suitable one from the CRTL that came with VMS 7.2 and later.
4723 Also check processes not considered by the CRTL waitpid().
4725 /*{{{Pid_t my_waitpid(Pid_t pid, int *statusp, int flags)*/
4727 Perl_my_waitpid(pTHX_ Pid_t pid, int *statusp, int flags)
4734 if (statusp) *statusp = 0;
4736 for (info = open_pipes; info != NULL; info = info->next)
4737 if (info->pid == pid) break;
4739 if (info != NULL) { /* we know about this child */
4740 while (!info->done) {
4741 _ckvmssts(sys$setast(0));
4743 if (!done) _ckvmssts(sys$clref(pipe_ef));
4744 _ckvmssts(sys$setast(1));
4745 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
4748 if (statusp) *statusp = info->completion;
4752 /* child that already terminated? */
4754 for (j = 0; j < NKEEPCLOSED && j < closed_num; j++) {
4755 if (closed_list[j].pid == pid) {
4756 if (statusp) *statusp = closed_list[j].completion;
4761 /* fall through if this child is not one of our own pipe children */
4763 #if defined(__CRTL_VER) && __CRTL_VER >= 70200000
4765 /* waitpid() became available in the CRTL as of VMS 7.0, but only
4766 * in 7.2 did we get a version that fills in the VMS completion
4767 * status as Perl has always tried to do.
4770 sts = __vms_waitpid( pid, statusp, flags );
4772 if ( sts == 0 || !(sts == -1 && errno == ECHILD) )
4775 /* If the real waitpid tells us the child does not exist, we
4776 * fall through here to implement waiting for a child that
4777 * was created by some means other than exec() (say, spawned
4778 * from DCL) or to wait for a process that is not a subprocess
4779 * of the current process.
4782 #endif /* defined(__CRTL_VER) && __CRTL_VER >= 70200000 */
4785 $DESCRIPTOR(intdsc,"0 00:00:01");
4786 unsigned long int ownercode = JPI$_OWNER, ownerpid;
4787 unsigned long int pidcode = JPI$_PID, mypid;
4788 unsigned long int interval[2];
4789 unsigned int jpi_iosb[2];
4790 struct itmlst_3 jpilist[2] = {
4791 {sizeof(ownerpid), JPI$_OWNER, &ownerpid, 0},
4796 /* Sorry folks, we don't presently implement rooting around for
4797 the first child we can find, and we definitely don't want to
4798 pass a pid of -1 to $getjpi, where it is a wildcard operation.
4804 /* Get the owner of the child so I can warn if it's not mine. If the
4805 * process doesn't exist or I don't have the privs to look at it,
4806 * I can go home early.
4808 sts = sys$getjpiw(0,&pid,NULL,&jpilist,&jpi_iosb,NULL,NULL);
4809 if (sts & 1) sts = jpi_iosb[0];
4821 set_vaxc_errno(sts);
4825 if (ckWARN(WARN_EXEC)) {
4826 /* remind folks they are asking for non-standard waitpid behavior */
4827 _ckvmssts(lib$getjpi(&pidcode,0,0,&mypid,0,0));
4828 if (ownerpid != mypid)
4829 Perl_warner(aTHX_ packWARN(WARN_EXEC),
4830 "waitpid: process %x is not a child of process %x",
4834 /* simply check on it once a second until it's not there anymore. */
4836 _ckvmssts(sys$bintim(&intdsc,interval));
4837 while ((sts=lib$getjpi(&ownercode,&pid,0,&ownerpid,0,0)) & 1) {
4838 _ckvmssts(sys$schdwk(0,0,interval,0));
4839 _ckvmssts(sys$hiber());
4841 if (sts == SS$_NONEXPR) sts = SS$_NORMAL;
4846 } /* end of waitpid() */
4851 /*{{{ char *my_gconvert(double val, int ndig, int trail, char *buf) */
4853 my_gconvert(double val, int ndig, int trail, char *buf)
4855 static char __gcvtbuf[DBL_DIG+1];
4858 loc = buf ? buf : __gcvtbuf;
4860 #ifndef __DECC /* VAXCRTL gcvt uses E format for numbers < 1 */
4862 sprintf(loc,"%.*g",ndig,val);
4868 if (!buf && ndig > DBL_DIG) ndig = DBL_DIG;
4869 return gcvt(val,ndig,loc);
4872 loc[0] = '0'; loc[1] = '\0';
4879 #if defined(__VAX) || !defined(NAML$C_MAXRSS)
4880 static int rms_free_search_context(struct FAB * fab)
4884 nam = fab->fab$l_nam;
4885 nam->nam$b_nop |= NAM$M_SYNCHK;
4886 nam->nam$l_rlf = NULL;
4888 return sys$parse(fab, NULL, NULL);
4891 #define rms_setup_nam(nam) struct NAM nam = cc$rms_nam
4892 #define rms_clear_nam_nop(nam) nam.nam$b_nop = 0;
4893 #define rms_set_nam_nop(nam, opt) nam.nam$b_nop |= (opt)
4894 #define rms_set_nam_fnb(nam, opt) nam.nam$l_fnb |= (opt)
4895 #define rms_is_nam_fnb(nam, opt) (nam.nam$l_fnb & (opt))
4896 #define rms_nam_esll(nam) nam.nam$b_esl
4897 #define rms_nam_esl(nam) nam.nam$b_esl
4898 #define rms_nam_name(nam) nam.nam$l_name
4899 #define rms_nam_namel(nam) nam.nam$l_name
4900 #define rms_nam_type(nam) nam.nam$l_type
4901 #define rms_nam_typel(nam) nam.nam$l_type
4902 #define rms_nam_ver(nam) nam.nam$l_ver
4903 #define rms_nam_verl(nam) nam.nam$l_ver
4904 #define rms_nam_rsll(nam) nam.nam$b_rsl
4905 #define rms_nam_rsl(nam) nam.nam$b_rsl
4906 #define rms_bind_fab_nam(fab, nam) fab.fab$l_nam = &nam
4907 #define rms_set_fna(fab, nam, name, size) \
4908 { fab.fab$b_fns = size; fab.fab$l_fna = name; }
4909 #define rms_get_fna(fab, nam) fab.fab$l_fna
4910 #define rms_set_dna(fab, nam, name, size) \
4911 { fab.fab$b_dns = size; fab.fab$l_dna = name; }
4912 #define rms_nam_dns(fab, nam) fab.fab$b_dns
4913 #define rms_set_esa(nam, name, size) \
4914 { nam.nam$b_ess = size; nam.nam$l_esa = name; }
4915 #define rms_set_esal(nam, s_name, s_size, l_name, l_size) \
4916 { nam.nam$l_esa = s_name; nam.nam$b_ess = s_size;}
4917 #define rms_set_rsa(nam, name, size) \
4918 { nam.nam$l_rsa = name; nam.nam$b_rss = size; }
4919 #define rms_set_rsal(nam, s_name, s_size, l_name, l_size) \
4920 { nam.nam$l_rsa = s_name; nam.nam$b_rss = s_size; }
4921 #define rms_nam_name_type_l_size(nam) \
4922 (nam.nam$b_name + nam.nam$b_type)
4924 static int rms_free_search_context(struct FAB * fab)
4928 nam = fab->fab$l_naml;
4929 nam->naml$b_nop |= NAM$M_SYNCHK;
4930 nam->naml$l_rlf = NULL;
4931 nam->naml$l_long_defname_size = 0;
4934 return sys$parse(fab, NULL, NULL);
4937 #define rms_setup_nam(nam) struct NAML nam = cc$rms_naml
4938 #define rms_clear_nam_nop(nam) nam.naml$b_nop = 0;
4939 #define rms_set_nam_nop(nam, opt) nam.naml$b_nop |= (opt)
4940 #define rms_set_nam_fnb(nam, opt) nam.naml$l_fnb |= (opt)
4941 #define rms_is_nam_fnb(nam, opt) (nam.naml$l_fnb & (opt))
4942 #define rms_nam_esll(nam) nam.naml$l_long_expand_size
4943 #define rms_nam_esl(nam) nam.naml$b_esl
4944 #define rms_nam_name(nam) nam.naml$l_name
4945 #define rms_nam_namel(nam) nam.naml$l_long_name
4946 #define rms_nam_type(nam) nam.naml$l_type
4947 #define rms_nam_typel(nam) nam.naml$l_long_type
4948 #define rms_nam_ver(nam) nam.naml$l_ver
4949 #define rms_nam_verl(nam) nam.naml$l_long_ver
4950 #define rms_nam_rsll(nam) nam.naml$l_long_result_size
4951 #define rms_nam_rsl(nam) nam.naml$b_rsl
4952 #define rms_bind_fab_nam(fab, nam) fab.fab$l_naml = &nam
4953 #define rms_set_fna(fab, nam, name, size) \
4954 { fab.fab$b_fns = 0; fab.fab$l_fna = (char *) -1; \
4955 nam.naml$l_long_filename_size = size; \
4956 nam.naml$l_long_filename = name;}
4957 #define rms_get_fna(fab, nam) nam.naml$l_long_filename
4958 #define rms_set_dna(fab, nam, name, size) \
4959 { fab.fab$b_dns = 0; fab.fab$l_dna = (char *) -1; \
4960 nam.naml$l_long_defname_size = size; \
4961 nam.naml$l_long_defname = name; }
4962 #define rms_nam_dns(fab, nam) nam.naml$l_long_defname_size
4963 #define rms_set_esa(nam, name, size) \
4964 { nam.naml$b_ess = 0; nam.naml$l_esa = (char *) -1; \
4965 nam.naml$l_long_expand_alloc = size; \
4966 nam.naml$l_long_expand = name; }
4967 #define rms_set_esal(nam, s_name, s_size, l_name, l_size) \
4968 { nam.naml$l_esa = s_name; nam.naml$b_ess = s_size; \
4969 nam.naml$l_long_expand = l_name; \
4970 nam.naml$l_long_expand_alloc = l_size; }
4971 #define rms_set_rsa(nam, name, size) \
4972 { nam.naml$l_rsa = NULL; nam.naml$b_rss = 0; \
4973 nam.naml$l_long_result = name; \
4974 nam.naml$l_long_result_alloc = size; }
4975 #define rms_set_rsal(nam, s_name, s_size, l_name, l_size) \
4976 { nam.naml$l_rsa = s_name; nam.naml$b_rss = s_size; \
4977 nam.naml$l_long_result = l_name; \
4978 nam.naml$l_long_result_alloc = l_size; }
4979 #define rms_nam_name_type_l_size(nam) \
4980 (nam.naml$l_long_name_size + nam.naml$l_long_type_size)
4985 * The CRTL for 8.3 and later can create symbolic links in any mode,
4986 * however in 8.3 the unlink/remove/delete routines will only properly handle
4987 * them if one of the PCP modes is active.
4989 static int rms_erase(const char * vmsname)
4992 struct FAB myfab = cc$rms_fab;
4993 rms_setup_nam(mynam);
4995 rms_set_fna(myfab, mynam, (char *)vmsname, strlen(vmsname)); /* cast ok */
4996 rms_bind_fab_nam(myfab, mynam);
4998 /* Are we removing all versions? */
4999 if (vms_unlink_all_versions == 1) {
5000 const char * defspec = ";*";
5001 rms_set_dna(myfab, mynam, (char *)defspec, strlen(defspec)); /* cast ok */
5004 #ifdef NAML$M_OPEN_SPECIAL
5005 rms_set_nam_nop(mynam, NAML$M_OPEN_SPECIAL);
5008 status = sys$erase(&myfab, 0, 0);
5015 vms_rename_with_acl(pTHX_ const struct dsc$descriptor_s * vms_src_dsc,
5016 const struct dsc$descriptor_s * vms_dst_dsc,
5017 unsigned long flags)
5019 /* VMS and UNIX handle file permissions differently and the
5020 * the same ACL trick may be needed for renaming files,
5021 * especially if they are directories.
5024 /* todo: get kill_file and rename to share common code */
5025 /* I can not find online documentation for $change_acl
5026 * it appears to be replaced by $set_security some time ago */
5028 const unsigned int access_mode = 0;
5029 $DESCRIPTOR(obj_file_dsc,"FILE");
5032 unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE;
5033 int aclsts, fndsts, rnsts = -1;
5034 unsigned int ctx = 0;
5035 struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
5036 struct dsc$descriptor_s * clean_dsc;
5039 unsigned char myace$b_length;
5040 unsigned char myace$b_type;
5041 unsigned short int myace$w_flags;
5042 unsigned long int myace$l_access;
5043 unsigned long int myace$l_ident;
5044 } newace = { sizeof(struct myacedef), ACE$C_KEYID, 0,
5045 ACE$M_READ | ACE$M_WRITE | ACE$M_DELETE | ACE$M_CONTROL,
5047 oldace = { sizeof(struct myacedef), ACE$C_KEYID, 0, 0, 0};
5050 findlst[3] = {{sizeof oldace, OSS$_ACL_FIND_ENTRY, &oldace, 0},
5051 {sizeof oldace, OSS$_ACL_READ_ENTRY, &oldace, 0},
5053 addlst[2] = {{sizeof newace, OSS$_ACL_ADD_ENTRY, &newace, 0},{0,0,0,0}},
5054 dellst[2] = {{sizeof newace, OSS$_ACL_DELETE_ENTRY, &newace, 0},
5058 /* Expand the input spec using RMS, since we do not want to put
5059 * ACLs on the target of a symbolic link */
5060 vmsname = PerlMem_malloc(NAM$C_MAXRSS+1);
5061 if (vmsname == NULL)
5064 rslt = do_rmsexpand(vms_src_dsc->dsc$a_pointer,
5068 PERL_RMSEXPAND_M_VMS | PERL_RMSEXPAND_M_SYMLINK,
5072 PerlMem_free(vmsname);
5076 /* So we get our own UIC to use as a rights identifier,
5077 * and the insert an ACE at the head of the ACL which allows us
5078 * to delete the file.
5080 _ckvmssts_noperl(lib$getjpi(&jpicode,0,0,&(oldace.myace$l_ident),0,0));
5082 fildsc.dsc$w_length = strlen(vmsname);
5083 fildsc.dsc$a_pointer = vmsname;
5085 newace.myace$l_ident = oldace.myace$l_ident;
5088 /* Grab any existing ACEs with this identifier in case we fail */
5089 clean_dsc = &fildsc;
5090 aclsts = fndsts = sys$get_security(&obj_file_dsc,
5098 if ($VMS_STATUS_SUCCESS(fndsts) || (fndsts == SS$_ACLEMPTY)) {
5099 /* Add the new ACE . . . */
5101 /* if the sys$get_security succeeded, then ctx is valid, and the
5102 * object/file descriptors will be ignored. But otherwise they
5105 aclsts = sys$set_security(&obj_file_dsc, &fildsc, NULL,
5106 OSS$M_RELCTX, addlst, &ctx, &access_mode);
5107 if (!$VMS_STATUS_SUCCESS(aclsts) && (aclsts != SS$_NOCLASS)) {
5109 set_vaxc_errno(aclsts);
5110 PerlMem_free(vmsname);
5114 rnsts = lib$rename_file(vms_src_dsc, vms_dst_dsc,
5117 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
5119 if ($VMS_STATUS_SUCCESS(rnsts)) {
5120 clean_dsc = (struct dsc$descriptor_s *)vms_dst_dsc;
5123 /* Put things back the way they were. */
5125 aclsts = sys$get_security(&obj_file_dsc,
5133 if ($VMS_STATUS_SUCCESS(aclsts)) {
5137 if (!$VMS_STATUS_SUCCESS(fndsts))
5138 sec_flags = OSS$M_RELCTX;
5140 /* Get rid of the new ACE */
5141 aclsts = sys$set_security(NULL, NULL, NULL,
5142 sec_flags, dellst, &ctx, &access_mode);
5144 /* If there was an old ACE, put it back */
5145 if ($VMS_STATUS_SUCCESS(aclsts) && $VMS_STATUS_SUCCESS(fndsts)) {
5146 addlst[0].bufadr = &oldace;
5147 aclsts = sys$set_security(NULL, NULL, NULL,
5148 OSS$M_RELCTX, addlst, &ctx, &access_mode);
5149 if (!$VMS_STATUS_SUCCESS(aclsts) && (aclsts != SS$_NOCLASS)) {
5151 set_vaxc_errno(aclsts);
5157 /* Try to clear the lock on the ACL list */
5158 aclsts2 = sys$set_security(NULL, NULL, NULL,
5159 OSS$M_RELCTX, NULL, &ctx, &access_mode);
5161 /* Rename errors are most important */
5162 if (!$VMS_STATUS_SUCCESS(rnsts))
5165 set_vaxc_errno(aclsts);
5170 if (aclsts != SS$_ACLEMPTY)
5177 PerlMem_free(vmsname);
5182 /*{{{int rename(const char *, const char * */
5183 /* Not exactly what X/Open says to do, but doing it absolutely right
5184 * and efficiently would require a lot more work. This should be close
5185 * enough to pass all but the most strict X/Open compliance test.
5188 Perl_rename(pTHX_ const char *src, const char * dst)
5197 /* Validate the source file */
5198 src_sts = flex_lstat(src, &src_st);
5201 /* No source file or other problem */
5205 dst_sts = flex_lstat(dst, &dst_st);
5208 if (dst_st.st_dev != src_st.st_dev) {
5209 /* Must be on the same device */
5214 /* VMS_INO_T_COMPARE is true if the inodes are different
5215 * to match the output of memcmp
5218 if (!VMS_INO_T_COMPARE(src_st.st_ino, dst_st.st_ino)) {
5219 /* That was easy, the files are the same! */
5223 if (S_ISDIR(src_st.st_mode) && !S_ISDIR(dst_st.st_mode)) {
5224 /* If source is a directory, so must be dest */
5232 if ((dst_sts == 0) &&
5233 (vms_unlink_all_versions || S_ISDIR(dst_st.st_mode))) {
5235 /* We have issues here if vms_unlink_all_versions is set
5236 * If the destination exists, and is not a directory, then
5237 * we must delete in advance.
5239 * If the src is a directory, then we must always pre-delete
5242 * If we successfully delete the dst in advance, and the rename fails
5243 * X/Open requires that errno be EIO.
5247 if (!S_ISDIR(dst_st.st_mode) || S_ISDIR(src_st.st_mode)) {
5249 d_sts = mp_do_kill_file(aTHX_ dst, S_ISDIR(dst_st.st_mode));
5253 /* We killed the destination, so only errno now is EIO */
5258 /* Originally the idea was to call the CRTL rename() and only
5259 * try the lib$rename_file if it failed.
5260 * It turns out that there are too many variants in what the
5261 * the CRTL rename might do, so only use lib$rename_file
5266 /* Is the source and dest both in VMS format */
5267 /* if the source is a directory, then need to fileify */
5268 /* and dest must be a directory or non-existant. */
5274 unsigned long flags;
5275 struct dsc$descriptor_s old_file_dsc;
5276 struct dsc$descriptor_s new_file_dsc;
5278 /* We need to modify the src and dst depending
5279 * on if one or more of them are directories.
5282 vms_src = PerlMem_malloc(VMS_MAXRSS);
5283 if (vms_src == NULL)
5284 _ckvmssts_noperl(SS$_INSFMEM);
5286 /* Source is always a VMS format file */
5287 ret_str = do_tovmsspec(src, vms_src, 0, NULL);
5288 if (ret_str == NULL) {
5289 PerlMem_free(vms_src);
5294 vms_dst = PerlMem_malloc(VMS_MAXRSS);
5295 if (vms_dst == NULL)
5296 _ckvmssts_noperl(SS$_INSFMEM);
5298 if (S_ISDIR(src_st.st_mode)) {
5300 char * vms_dir_file;
5302 vms_dir_file = PerlMem_malloc(VMS_MAXRSS);
5303 if (vms_dir_file == NULL)
5304 _ckvmssts_noperl(SS$_INSFMEM);
5306 /* The source must be a file specification */
5307 ret_str = do_fileify_dirspec(vms_src, vms_dir_file, 0, NULL);
5308 if (ret_str == NULL) {
5309 PerlMem_free(vms_src);
5310 PerlMem_free(vms_dst);
5311 PerlMem_free(vms_dir_file);
5315 PerlMem_free(vms_src);
5316 vms_src = vms_dir_file;
5318 /* If the dest is a directory, we must remove it
5321 d_sts = mp_do_kill_file(aTHX_ dst, 1);
5323 PerlMem_free(vms_src);
5324 PerlMem_free(vms_dst);
5332 /* The dest must be a VMS file specification */
5333 ret_str = int_tovmsspec(dst, vms_dst, 0, NULL);
5334 if (ret_str == NULL) {
5335 PerlMem_free(vms_src);
5336 PerlMem_free(vms_dst);
5341 /* The source must be a file specification */
5342 vms_dir_file = PerlMem_malloc(VMS_MAXRSS);
5343 if (vms_dir_file == NULL)
5344 _ckvmssts_noperl(SS$_INSFMEM);
5346 ret_str = do_fileify_dirspec(vms_dst, vms_dir_file, 0, NULL);
5347 if (ret_str == NULL) {
5348 PerlMem_free(vms_src);
5349 PerlMem_free(vms_dst);
5350 PerlMem_free(vms_dir_file);
5354 PerlMem_free(vms_dst);
5355 vms_dst = vms_dir_file;
5358 /* File to file or file to new dir */
5360 if ((dst_sts == 0) && S_ISDIR(dst_st.st_mode)) {
5361 /* VMS pathify a dir target */
5362 ret_str = do_tovmspath(dst, vms_dst, 0, NULL);
5363 if (ret_str == NULL) {
5364 PerlMem_free(vms_src);
5365 PerlMem_free(vms_dst);
5371 /* fileify a target VMS file specification */
5372 ret_str = int_tovmsspec(dst, vms_dst, 0, NULL);
5373 if (ret_str == NULL) {
5374 PerlMem_free(vms_src);
5375 PerlMem_free(vms_dst);
5382 old_file_dsc.dsc$a_pointer = vms_src;
5383 old_file_dsc.dsc$w_length = strlen(vms_src);
5384 old_file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
5385 old_file_dsc.dsc$b_class = DSC$K_CLASS_S;
5387 new_file_dsc.dsc$a_pointer = vms_dst;
5388 new_file_dsc.dsc$w_length = strlen(vms_dst);
5389 new_file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
5390 new_file_dsc.dsc$b_class = DSC$K_CLASS_S;
5393 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
5394 flags |= 4; /* LIB$M_FIL_LONG_NAMES (bit 2) */
5397 sts = lib$rename_file(&old_file_dsc,
5401 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
5402 if (!$VMS_STATUS_SUCCESS(sts)) {
5404 /* We could have failed because VMS style permissions do not
5405 * permit renames that UNIX will allow. Just like the hack
5408 sts = vms_rename_with_acl(aTHX_ &old_file_dsc, &new_file_dsc, flags);
5411 PerlMem_free(vms_src);
5412 PerlMem_free(vms_dst);
5413 if (!$VMS_STATUS_SUCCESS(sts)) {
5420 if (vms_unlink_all_versions) {
5421 /* Now get rid of any previous versions of the source file that
5426 src_sts = mp_do_kill_file(aTHX_ src, S_ISDIR(src_st.st_mode));
5430 /* We deleted the destination, so must force the error to be EIO */
5431 if ((retval != 0) && (pre_delete != 0))
5439 /*{{{char *do_rmsexpand(char *fspec, char *out, int ts, char *def, unsigned opts)*/
5440 /* Shortcut for common case of simple calls to $PARSE and $SEARCH
5441 * to expand file specification. Allows for a single default file
5442 * specification and a simple mask of options. If outbuf is non-NULL,
5443 * it must point to a buffer at least NAM$C_MAXRSS bytes long, into which
5444 * the resultant file specification is placed. If outbuf is NULL, the
5445 * resultant file specification is placed into a static buffer.
5446 * The third argument, if non-NULL, is taken to be a default file
5447 * specification string. The fourth argument is unused at present.
5448 * rmesexpand() returns the address of the resultant string if
5449 * successful, and NULL on error.
5451 * New functionality for previously unused opts value:
5452 * PERL_RMSEXPAND_M_VMS - Force output file specification to VMS format.
5453 * PERL_RMSEXPAND_M_LONG - Want output in long formst
5454 * PERL_RMSEXPAND_M_VMS_IN - Input is already in VMS, so do not vmsify
5455 * PERL_RMSEXPAND_M_SYMLINK - Use symbolic link, not target
5457 static char *mp_do_tounixspec(pTHX_ const char *, char *, int, int *);
5461 (pTHX_ const char *filespec,
5464 const char *defspec,
5469 static char __rmsexpand_retbuf[VMS_MAXRSS];
5470 char * vmsfspec, *tmpfspec;
5471 char * esa, *cp, *out = NULL;
5475 struct FAB myfab = cc$rms_fab;
5476 rms_setup_nam(mynam);
5478 unsigned long int retsts, trimver, trimtype, haslower = 0, isunix = 0;
5481 /* temp hack until UTF8 is actually implemented */
5482 if (fs_utf8 != NULL)
5485 if (!filespec || !*filespec) {
5486 set_vaxc_errno(LIB$_INVARG); set_errno(EINVAL);
5490 if (ts) out = Newx(outbuf,VMS_MAXRSS,char);
5491 else outbuf = __rmsexpand_retbuf;
5499 if ((opts & PERL_RMSEXPAND_M_VMS_IN) == 0) {
5500 isunix = is_unix_filespec(filespec);
5502 vmsfspec = PerlMem_malloc(VMS_MAXRSS);
5503 if (vmsfspec == NULL) _ckvmssts_noperl(SS$_INSFMEM);
5504 if (int_tovmsspec(filespec, vmsfspec, 0, fs_utf8) == NULL) {
5505 PerlMem_free(vmsfspec);
5510 filespec = vmsfspec;
5512 /* Unless we are forcing to VMS format, a UNIX input means
5513 * UNIX output, and that requires long names to be used
5515 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
5516 if ((opts & PERL_RMSEXPAND_M_VMS) == 0)
5517 opts |= PERL_RMSEXPAND_M_LONG;
5524 rms_set_fna(myfab, mynam, (char *)filespec, strlen(filespec)); /* cast ok */
5525 rms_bind_fab_nam(myfab, mynam);
5527 if (defspec && *defspec) {
5529 t_isunix = is_unix_filespec(defspec);
5531 tmpfspec = PerlMem_malloc(VMS_MAXRSS);
5532 if (tmpfspec == NULL) _ckvmssts_noperl(SS$_INSFMEM);
5533 if (int_tovmsspec(defspec, tmpfspec, 0, dfs_utf8) == NULL) {
5534 PerlMem_free(tmpfspec);
5535 if (vmsfspec != NULL)
5536 PerlMem_free(vmsfspec);
5543 rms_set_dna(myfab, mynam, (char *)defspec, strlen(defspec)); /* cast ok */
5546 esa = PerlMem_malloc(NAM$C_MAXRSS + 1);
5547 if (esa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
5548 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
5549 esal = PerlMem_malloc(VMS_MAXRSS);
5550 if (esal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
5552 rms_set_esal(mynam, esa, NAM$C_MAXRSS, esal, VMS_MAXRSS-1);
5554 /* If a NAML block is used RMS always writes to the long and short
5555 * addresses unless you suppress the short name.
5557 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
5558 outbufl = PerlMem_malloc(VMS_MAXRSS);
5559 if (outbufl == NULL) _ckvmssts_noperl(SS$_INSFMEM);
5561 rms_set_rsal(mynam, outbuf, NAM$C_MAXRSS, outbufl, (VMS_MAXRSS - 1));
5563 #ifdef NAM$M_NO_SHORT_UPCASE
5564 if (decc_efs_case_preserve)
5565 rms_set_nam_nop(mynam, NAM$M_NO_SHORT_UPCASE);
5568 /* We may not want to follow symbolic links */
5569 #ifdef NAML$M_OPEN_SPECIAL
5570 if ((opts & PERL_RMSEXPAND_M_SYMLINK) != 0)
5571 rms_set_nam_nop(mynam, NAML$M_OPEN_SPECIAL);
5574 /* First attempt to parse as an existing file */
5575 retsts = sys$parse(&myfab,0,0);
5576 if (!(retsts & STS$K_SUCCESS)) {
5578 /* Could not find the file, try as syntax only if error is not fatal */
5579 rms_set_nam_nop(mynam, NAM$M_SYNCHK);
5580 if (retsts == RMS$_DNF || retsts == RMS$_DIR || retsts == RMS$_DEV) {
5581 retsts = sys$parse(&myfab,0,0);
5582 if (retsts & STS$K_SUCCESS) goto expanded;
5585 /* Still could not parse the file specification */
5586 /*----------------------------------------------*/
5587 sts = rms_free_search_context(&myfab); /* Free search context */
5588 if (out) Safefree(out);
5589 if (tmpfspec != NULL)
5590 PerlMem_free(tmpfspec);
5591 if (vmsfspec != NULL)
5592 PerlMem_free(vmsfspec);
5593 if (outbufl != NULL)
5594 PerlMem_free(outbufl);
5598 set_vaxc_errno(retsts);
5599 if (retsts == RMS$_PRV) set_errno(EACCES);
5600 else if (retsts == RMS$_DEV) set_errno(ENODEV);
5601 else if (retsts == RMS$_DIR) set_errno(ENOTDIR);
5602 else set_errno(EVMSERR);
5605 retsts = sys$search(&myfab,0,0);
5606 if (!(retsts & STS$K_SUCCESS) && retsts != RMS$_FNF) {
5607 sts = rms_free_search_context(&myfab); /* Free search context */
5608 if (out) Safefree(out);
5609 if (tmpfspec != NULL)
5610 PerlMem_free(tmpfspec);
5611 if (vmsfspec != NULL)
5612 PerlMem_free(vmsfspec);
5613 if (outbufl != NULL)
5614 PerlMem_free(outbufl);
5618 set_vaxc_errno(retsts);
5619 if (retsts == RMS$_PRV) set_errno(EACCES);
5620 else set_errno(EVMSERR);
5624 /* If the input filespec contained any lowercase characters,
5625 * downcase the result for compatibility with Unix-minded code. */
5627 if (!decc_efs_case_preserve) {
5628 for (tbuf = rms_get_fna(myfab, mynam); *tbuf; tbuf++)
5629 if (islower(*tbuf)) { haslower = 1; break; }
5632 /* Is a long or a short name expected */
5633 /*------------------------------------*/
5634 if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
5635 if (rms_nam_rsll(mynam)) {
5637 speclen = rms_nam_rsll(mynam);
5640 tbuf = esal; /* Not esa */
5641 speclen = rms_nam_esll(mynam);
5645 if (rms_nam_rsl(mynam)) {