1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <acedef.h>
26#include <acldef.h>
27#include <armdef.h>
28#include <atrdef.h>
29#include <chpdef.h>
30#include <clidef.h>
31#include <climsgdef.h>
32#include <dcdef.h>
33#include <descrip.h>
34#include <devdef.h>
35#include <dvidef.h>
36#include <fibdef.h>
37#include <float.h>
38#include <fscndef.h>
39#include <iodef.h>
40#include <jpidef.h>
41#include <kgbdef.h>
42#include <libclidef.h>
43#include <libdef.h>
44#include <lib$routines.h>
45#include <lnmdef.h>
46#include <msgdef.h>
47#include <ossdef.h>
48#if __CRTL_VER >= 70301000 && !defined(__VAX)
49#include <ppropdef.h>
50#endif
51#include <prvdef.h>
52#include <psldef.h>
53#include <rms.h>
54#include <shrdef.h>
55#include <ssdef.h>
56#include <starlet.h>
57#include <strdef.h>
58#include <str$routines.h>
59#include <syidef.h>
60#include <uaidef.h>
61#include <uicdef.h>
62#include <stsdef.h>
63#include <rmsdef.h>
64#include <smgdef.h>
65#if __CRTL_VER >= 70000000
66#include <efndef.h>
67#define NO_EFN EFN$C_ENF
68#else
69#define NO_EFN 0;
70#endif
71
72#if __CRTL_VER < 70301000 && __CRTL_VER >= 70300000
73int decc$feature_get_index(const char *name);
74char* decc$feature_get_name(int index);
75int decc$feature_get_value(int index, int mode);
76int decc$feature_set_value(int index, int mode, int value);
77#else
78#include <unixlib.h>
79#endif
80
81#pragma member_alignment save
82#pragma nomember_alignment longword
83struct item_list_3 {
84 unsigned short len;
85 unsigned short code;
86 void * bufadr;
87 unsigned short * retadr;
88};
89#pragma member_alignment restore
90
91
92
93
94#ifdef sys$getdviw
95#undef sys$getdviw
96int sys$getdviw
97 (unsigned long efn,
98 unsigned short chan,
99 const struct dsc$descriptor_s * devnam,
100 const struct item_list_3 * itmlst,
101 void * iosb,
102 void * (astadr)(unsigned long),
103 void * astprm,
104 void * nullarg);
105#endif
106
107#ifdef sys$get_security
108#undef sys$get_security
109int sys$get_security
110 (const struct dsc$descriptor_s * clsnam,
111 const struct dsc$descriptor_s * objnam,
112 const unsigned int *objhan,
113 unsigned int flags,
114 const struct item_list_3 * itmlst,
115 unsigned int * contxt,
116 const unsigned int * acmode);
117#endif
118
119#ifdef sys$set_security
120#undef sys$set_security
121int sys$set_security
122 (const struct dsc$descriptor_s * clsnam,
123 const struct dsc$descriptor_s * objnam,
124 const unsigned int *objhan,
125 unsigned int flags,
126 const struct item_list_3 * itmlst,
127 unsigned int * contxt,
128 const unsigned int * acmode);
129#endif
130
131#ifdef lib$find_image_symbol
132#undef lib$find_image_symbol
133int lib$find_image_symbol
134 (const struct dsc$descriptor_s * imgname,
135 const struct dsc$descriptor_s * symname,
136 void * symval,
137 const struct dsc$descriptor_s * defspec,
138 unsigned long flag);
139#endif
140
141#ifdef lib$rename_file
142#undef lib$rename_file
143int lib$rename_file
144 (const struct dsc$descriptor_s * old_file_dsc,
145 const struct dsc$descriptor_s * new_file_dsc,
146 const struct dsc$descriptor_s * default_file_dsc,
147 const struct dsc$descriptor_s * related_file_dsc,
148 const unsigned long * flags,
149 void * (success)(const struct dsc$descriptor_s * old_dsc,
150 const struct dsc$descriptor_s * new_dsc,
151 const void *),
152 void * (error)(const struct dsc$descriptor_s * old_dsc,
153 const struct dsc$descriptor_s * new_dsc,
154 const int * rms_sts,
155 const int * rms_stv,
156 const int * error_src,
157 const void * usr_arg),
158 int (confirm)(const struct dsc$descriptor_s * old_dsc,
159 const struct dsc$descriptor_s * new_dsc,
160 const void * old_fab,
161 const void * usr_arg),
162 void * user_arg,
163 struct dsc$descriptor_s * old_result_name_dsc,
164 struct dsc$descriptor_s * new_result_name_dsc,
165 unsigned long * file_scan_context);
166#endif
167
168#if __CRTL_VER >= 70300000 && !defined(__VAX)
169
170static int set_feature_default(const char *name, int value)
171{
172 int status;
173 int index;
174
175 index = decc$feature_get_index(name);
176
177 status = decc$feature_set_value(index, 1, value);
178 if (index == -1 || (status == -1)) {
179 return -1;
180 }
181
182 status = decc$feature_get_value(index, 1);
183 if (status != value) {
184 return -1;
185 }
186
187return 0;
188}
189#endif
190
191
192#ifndef SS$_INVFILFOROP
193# define SS$_INVFILFOROP 3930
194#endif
195#ifndef SS$_NOSUCHOBJECT
196# define SS$_NOSUCHOBJECT 2696
197#endif
198
199
200#define PERLIO_NOT_STDIO 0
201
202
203
204#define DONT_MASK_RTL_CALLS
205#include "EXTERN.h"
206#include "perl.h"
207#include "XSUB.h"
208
209#ifndef WARN_INTERNAL
210# define WARN_INTERNAL WARN_MISC
211#endif
212
213#ifdef VMS_LONGNAME_SUPPORT
214#include <libfildef.h>
215#endif
216
217#if defined(__VMS_VER) && __VMS_VER >= 70000000 && __DECC_VER >= 50200000
218# define RTL_USES_UTC 1
219#endif
220
221
222
223
224static int (*decw_term_port)
225 (const struct dsc$descriptor_s * display,
226 const struct dsc$descriptor_s * setup_file,
227 const struct dsc$descriptor_s * customization,
228 struct dsc$descriptor_s * result_device_name,
229 unsigned short * result_device_name_length,
230 void * controller,
231 void * char_buffer,
232 void * char_change_buffer) = 0;
233
234
235
236#ifdef __GNUC__
237# define uic$v_format uic$r_uic_form.uic$v_format
238# define uic$v_group uic$r_uic_form.uic$v_group
239# define uic$v_member uic$r_uic_form.uic$v_member
240# define prv$v_bypass prv$r_prvdef_bits0.prv$v_bypass
241# define prv$v_grpprv prv$r_prvdef_bits0.prv$v_grpprv
242# define prv$v_readall prv$r_prvdef_bits0.prv$v_readall
243# define prv$v_sysprv prv$r_prvdef_bits0.prv$v_sysprv
244#endif
245
246#if defined(NEED_AN_H_ERRNO)
247dEXT int h_errno;
248#endif
249
250#ifdef __DECC
251#pragma message disable pragma
252#pragma member_alignment save
253#pragma nomember_alignment longword
254#pragma message save
255#pragma message disable misalgndmem
256#endif
257struct itmlst_3 {
258 unsigned short int buflen;
259 unsigned short int itmcode;
260 void *bufadr;
261 unsigned short int *retlen;
262};
263
264struct filescan_itmlst_2 {
265 unsigned short length;
266 unsigned short itmcode;
267 char * component;
268};
269
270struct vs_str_st {
271 unsigned short length;
272 char str[65536];
273};
274
275#ifdef __DECC
276#pragma message restore
277#pragma member_alignment restore
278#endif
279
280#define do_fileify_dirspec(a,b,c,d) mp_do_fileify_dirspec(aTHX_ a,b,c,d)
281#define do_pathify_dirspec(a,b,c,d) mp_do_pathify_dirspec(aTHX_ a,b,c,d)
282#define do_tovmsspec(a,b,c,d) mp_do_tovmsspec(aTHX_ a,b,c,0,d)
283#define do_tovmspath(a,b,c,d) mp_do_tovmspath(aTHX_ a,b,c,d)
284#define do_rmsexpand(a,b,c,d,e,f,g) mp_do_rmsexpand(aTHX_ a,b,c,d,e,f,g)
285#define do_vms_realpath(a,b,c) mp_do_vms_realpath(aTHX_ a,b,c)
286#define do_vms_realname(a,b,c) mp_do_vms_realname(aTHX_ a,b,c)
287#define do_tounixspec(a,b,c,d) mp_do_tounixspec(aTHX_ a,b,c,d)
288#define do_tounixpath(a,b,c,d) mp_do_tounixpath(aTHX_ a,b,c,d)
289#define do_vms_case_tolerant(a) mp_do_vms_case_tolerant(a)
290#define expand_wild_cards(a,b,c,d) mp_expand_wild_cards(aTHX_ a,b,c,d)
291#define getredirection(a,b) mp_getredirection(aTHX_ a,b)
292
293static char *mp_do_tovmspath(pTHX_ const char *path, char *buf, int ts, int *);
294static char *mp_do_tounixpath(pTHX_ const char *path, char *buf, int ts, int *);
295static char *mp_do_tounixspec(pTHX_ const char *, char *, int, int *);
296static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts, int *);
297
298
299#define PERL_LNM_MAX_ALLOWED_INDEX 127
300
301
302
303
304
305#define PERL_LNM_MAX_ITER 10
306
307
308#if __CRTL_VER >= 70302000 && !defined(__VAX)
309#define MAX_DCL_SYMBOL (8192)
310#define MAX_DCL_LINE_LENGTH (4096 - 4)
311#else
312#define MAX_DCL_SYMBOL (1024)
313#define MAX_DCL_LINE_LENGTH (1024 - 4)
314#endif
315
316static char *__mystrtolower(char *str)
317{
318 if (str) for (; *str; ++str) *str= tolower(*str);
319 return str;
320}
321
322static struct dsc$descriptor_s fildevdsc =
323 { 12, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$FILE_DEV" };
324static struct dsc$descriptor_s crtlenvdsc =
325 { 8, DSC$K_DTYPE_T, DSC$K_CLASS_S, "CRTL_ENV" };
326static struct dsc$descriptor_s *fildev[] = { &fildevdsc, NULL };
327static struct dsc$descriptor_s *defenv[] = { &fildevdsc, &crtlenvdsc, NULL };
328static struct dsc$descriptor_s **env_tables = defenv;
329static bool will_taint = FALSE;
330
331
332
333static int no_translate_barewords;
334
335#ifndef RTL_USES_UTC
336static int tz_updated = 1;
337#endif
338
339
340
341
342static int decc_disable_to_vms_logname_translation = 1;
343static int decc_disable_posix_root = 1;
344int decc_efs_case_preserve = 0;
345static int decc_efs_charset = 0;
346static int decc_filename_unix_no_version = 0;
347static int decc_filename_unix_only = 0;
348int decc_filename_unix_report = 0;
349int decc_posix_compliant_pathnames = 0;
350int decc_readdir_dropdotnotype = 0;
351static int vms_process_case_tolerant = 1;
352int vms_vtf7_filenames = 0;
353int gnv_unix_shell = 0;
354static int vms_unlink_all_versions = 0;
355
356
357int decc_bug_readdir_efs1 = 0;
358int decc_bug_devnull = 1;
359int decc_bug_fgetname = 0;
360int decc_dir_barename = 0;
361
362static int vms_debug_on_exception = 0;
363
364
365
366
367
368
369
370
371
372static int is_unix_filespec(const char *path)
373{
374int ret_val;
375const char * pch1;
376
377 ret_val = 0;
378 if (strncmp(path,"\"^UP^",5) != 0) {
379 pch1 = strchr(path, '/');
380 if (pch1 != NULL)
381 ret_val = 1;
382 else {
383
384
385 if (decc_filename_unix_report || decc_filename_unix_only) {
386 if (strcmp(path,".") == 0)
387 ret_val = 1;
388 }
389 }
390 }
391 return ret_val;
392}
393
394
395
396
397static void ucs2_to_vtf7
398 (char *outspec,
399 unsigned long ucs2_char,
400 int * output_cnt)
401{
402unsigned char * ucs_ptr;
403int hex;
404
405 ucs_ptr = (unsigned char *)&ucs2_char;
406
407 outspec[0] = '^';
408 outspec[1] = 'U';
409 hex = (ucs_ptr[1] >> 4) & 0xf;
410 if (hex < 0xA)
411 outspec[2] = hex + '0';
412 else
413 outspec[2] = (hex - 9) + 'A';
414 hex = ucs_ptr[1] & 0xF;
415 if (hex < 0xA)
416 outspec[3] = hex + '0';
417 else {
418 outspec[3] = (hex - 9) + 'A';
419 }
420 hex = (ucs_ptr[0] >> 4) & 0xf;
421 if (hex < 0xA)
422 outspec[4] = hex + '0';
423 else
424 outspec[4] = (hex - 9) + 'A';
425 hex = ucs_ptr[1] & 0xF;
426 if (hex < 0xA)
427 outspec[5] = hex + '0';
428 else {
429 outspec[5] = (hex - 9) + 'A';
430 }
431 *output_cnt = 6;
432}
433
434
435
436
437
438
439
440
441
442
443
444static int copy_expand_unix_filename_escape
445 (char *outspec, const char *inspec, int *output_cnt, const int * utf8_fl)
446{
447int count;
448int scnt;
449int utf8_flag;
450
451 utf8_flag = 0;
452 if (utf8_fl)
453 utf8_flag = *utf8_fl;
454
455 count = 0;
456 *output_cnt = 0;
457 if (*inspec >= 0x80) {
458 if (utf8_fl && vms_vtf7_filenames) {
459 unsigned long ucs_char;
460
461 ucs_char = 0;
462
463 if ((*inspec & 0xE0) == 0xC0) {
464
465 ucs_char = ((inspec[0] & 0x1F) << 6) + (inspec[1] & 0x3f);
466 if (ucs_char >= 0x80) {
467 ucs2_to_vtf7(outspec, ucs_char, output_cnt);
468 return 2;
469 }
470 } else if ((*inspec & 0xF0) == 0xE0) {
471
472 ucs_char = ((inspec[0] & 0xF) << 12) +
473 ((inspec[1] & 0x3f) << 6) +
474 (inspec[2] & 0x3f);
475 if (ucs_char >= 0x800) {
476 ucs2_to_vtf7(outspec, ucs_char, output_cnt);
477 return 3;
478 }
479
480#if 0
481
482 } else if ((*inspec & 0xF8) == 0xF0) {
483
484
485 } else if ((*inspec & 0xFC) == 0xF8) {
486
487
488 } else if ((*inspec & 0xFE) == 0xFC) {
489
490
491#endif
492 }
493 }
494
495
496
497
498 if (*inspec <= 0x9F) {
499 int hex;
500 outspec[0] = '^';
501 outspec++;
502 hex = (*inspec >> 4) & 0xF;
503 if (hex < 0xA)
504 outspec[1] = hex + '0';
505 else {
506 outspec[1] = (hex - 9) + 'A';
507 }
508 hex = *inspec & 0xF;
509 if (hex < 0xA)
510 outspec[2] = hex + '0';
511 else {
512 outspec[2] = (hex - 9) + 'A';
513 }
514 *output_cnt = 3;
515 return 1;
516 } else if (*inspec == 0xA0) {
517 outspec[0] = '^';
518 outspec[1] = 'A';
519 outspec[2] = '0';
520 *output_cnt = 3;
521 return 1;
522 } else if (*inspec == 0xFF) {
523 outspec[0] = '^';
524 outspec[1] = 'F';
525 outspec[2] = 'F';
526 *output_cnt = 3;
527 return 1;
528 }
529 *outspec = *inspec;
530 *output_cnt = 1;
531 return 1;
532 }
533
534
535
536
537
538
539 if ((inspec[0] == '$') && (inspec[1] == '(')) {
540 int tcnt;
541
542 if (isalnum(inspec[2]) || (inspec[2] == '.') || (inspec[2] == '_')) {
543 tcnt = 3;
544 outspec[0] = inspec[0];
545 outspec[1] = inspec[1];
546 outspec[2] = inspec[2];
547
548 while(isalnum(inspec[tcnt]) ||
549 (inspec[2] == '.') || (inspec[2] == '_')) {
550 outspec[tcnt] = inspec[tcnt];
551 tcnt++;
552 }
553 if (inspec[tcnt] == ')') {
554 outspec[tcnt] = inspec[tcnt];
555 tcnt++;
556 *output_cnt = tcnt;
557 return tcnt;
558 }
559 }
560 }
561
562 switch (*inspec) {
563 case 0x7f:
564 outspec[0] = '^';
565 outspec[1] = '7';
566 outspec[2] = 'F';
567 *output_cnt = 3;
568 return 1;
569 break;
570 case '?':
571 if (decc_efs_charset == 0)
572 outspec[0] = '%';
573 else
574 outspec[0] = '?';
575 *output_cnt = 1;
576 return 1;
577 break;
578 case '.':
579 case '~':
580 case '!':
581 case '#':
582 case '&':
583 case '\'':
584 case '`':
585 case '(':
586 case ')':
587 case '+':
588 case '@':
589 case '{':
590 case '}':
591 case ',':
592 case ';':
593 case '[':
594 case ']':
595 case '%':
596 case '^':
597
598
599
600 if (strchr(".~!#&\'`()+@{},;[]%^=_", *(inspec+1))) {
601 *outspec = *inspec;
602 *output_cnt = 1;
603 return 1;
604 break;
605 }
606
607 case '=':
608
609 outspec[0] = '^';
610 outspec[1] = *inspec;
611 *output_cnt = 2;
612 return 1;
613 break;
614 case ' ':
615
616 outspec[0] = '^';
617 outspec[1] = '_';
618 *output_cnt = 2;
619 return 1;
620 break;
621 default:
622 *outspec = *inspec;
623 *output_cnt = 1;
624 return 1;
625 break;
626 }
627}
628
629
630
631
632
633
634
635
636
637
638
639static int copy_expand_vms_filename_escape
640 (char *outspec, const char *inspec, int *output_cnt)
641{
642int count;
643int scnt;
644
645 count = 0;
646 *output_cnt = 0;
647 if (*inspec == '^') {
648 inspec++;
649 switch (*inspec) {
650
651
652
653 case '.':
654 *outspec = *inspec;
655 count += 2;
656 (*output_cnt)++;
657 break;
658 case '_':
659 *outspec = ' ';
660 count += 2;
661 (*output_cnt)++;
662 break;
663 case '^':
664
665 outspec[0] = '^';
666 outspec[1] = '^';
667 count += 2;
668 (*output_cnt) += 2;
669 break;
670 case 'U':
671 inspec++;
672 count++;
673 scnt = strspn(inspec, "0123456789ABCDEFabcdef");
674 if (scnt == 4) {
675 unsigned int c1, c2;
676 scnt = sscanf(inspec, "%2x%2x", &c1, &c2);
677 outspec[0] == c1 & 0xff;
678 outspec[1] == c2 & 0xff;
679 if (scnt > 1) {
680 (*output_cnt) += 2;
681 count += 4;
682 }
683 }
684 else {
685
686 *outspec = 'U';
687 outspec++;
688 (*output_cnt++);
689 *outspec = *inspec;
690 count++;
691 (*output_cnt++);
692 }
693 break;
694 default:
695 scnt = strspn(inspec, "0123456789ABCDEFabcdef");
696 if (scnt == 2) {
697
698 unsigned int c1;
699 scnt = sscanf(inspec, "%2x", &c1);
700 outspec[0] = c1 & 0xff;
701 if (scnt > 0) {
702 (*output_cnt++);
703 count += 2;
704 }
705 }
706 else {
707 *outspec = *inspec;
708 count++;
709 (*output_cnt++);
710 }
711 }
712 }
713 else {
714 *outspec = *inspec;
715 count++;
716 (*output_cnt)++;
717 }
718 return count;
719}
720
721#ifdef sys$filescan
722#undef sys$filescan
723int sys$filescan
724 (const struct dsc$descriptor_s * srcstr,
725 struct filescan_itmlst_2 * valuelist,
726 unsigned long * fldflags,
727 struct dsc$descriptor_s *auxout,
728 unsigned short * retlen);
729#endif
730
731
732
733
734
735
736
737
738
739
740static int vms_split_path
741 (const char * path,
742 char * * volume,
743 int * vol_len,
744 char * * root,
745 int * root_len,
746 char * * dir,
747 int * dir_len,
748 char * * name,
749 int * name_len,
750 char * * ext,
751 int * ext_len,
752 char * * version,
753 int * ver_len)
754{
755struct dsc$descriptor path_desc;
756int status;
757unsigned long flags;
758int ret_stat;
759struct filescan_itmlst_2 item_list[9];
760const int filespec = 0;
761const int nodespec = 1;
762const int devspec = 2;
763const int rootspec = 3;
764const int dirspec = 4;
765const int namespec = 5;
766const int typespec = 6;
767const int verspec = 7;
768
769
770 ret_stat = -1;
771 *volume = NULL;
772 *vol_len = 0;
773 *root = NULL;
774 *root_len = 0;
775 *dir = NULL;
776 *dir_len;
777 *name = NULL;
778 *name_len = 0;
779 *ext = NULL;
780 *ext_len = 0;
781 *version = NULL;
782 *ver_len = 0;
783
784 path_desc.dsc$a_pointer = (char *)path;
785 path_desc.dsc$w_length = strlen(path);
786 path_desc.dsc$b_dtype = DSC$K_DTYPE_T;
787 path_desc.dsc$b_class = DSC$K_CLASS_S;
788
789
790
791
792 item_list[filespec].itmcode = FSCN$_FILESPEC;
793 item_list[filespec].length = 0;
794 item_list[filespec].component = NULL;
795
796
797
798
799 item_list[nodespec].itmcode = FSCN$_NODE;
800 item_list[nodespec].length = 0;
801 item_list[nodespec].component = NULL;
802
803 item_list[devspec].itmcode = FSCN$_DEVICE;
804 item_list[devspec].length = 0;
805 item_list[devspec].component = NULL;
806
807
808
809
810
811 item_list[rootspec].itmcode = FSCN$_ROOT;
812 item_list[rootspec].length = 0;
813 item_list[rootspec].component = NULL;
814
815 item_list[dirspec].itmcode = FSCN$_DIRECTORY;
816 item_list[dirspec].length = 0;
817 item_list[dirspec].component = NULL;
818
819 item_list[namespec].itmcode = FSCN$_NAME;
820 item_list[namespec].length = 0;
821 item_list[namespec].component = NULL;
822
823 item_list[typespec].itmcode = FSCN$_TYPE;
824 item_list[typespec].length = 0;
825 item_list[typespec].component = NULL;
826
827 item_list[verspec].itmcode = FSCN$_VERSION;
828 item_list[verspec].length = 0;
829 item_list[verspec].component = NULL;
830
831 item_list[8].itmcode = 0;
832 item_list[8].length = 0;
833 item_list[8].component = NULL;
834
835 status = sys$filescan
836 ((const struct dsc$descriptor_s *)&path_desc, item_list,
837 &flags, NULL, NULL);
838 _ckvmssts_noperl(status);
839
840
841 if (path_desc.dsc$w_length != item_list[filespec].length)
842 return ret_stat;
843
844
845 ret_stat = 0;
846
847
848 if (item_list[nodespec].length > 0) {
849 *volume = item_list[nodespec].component;
850 *vol_len = item_list[nodespec].length + item_list[devspec].length;
851 }
852 else {
853 *volume = item_list[devspec].component;
854 *vol_len = item_list[devspec].length;
855 }
856
857 *root = item_list[rootspec].component;
858 *root_len = item_list[rootspec].length;
859
860 *dir = item_list[dirspec].component;
861 *dir_len = item_list[dirspec].length;
862
863
864
865
866
867 if ((decc_efs_charset) &&
868 (item_list[verspec].length > 0) &&
869 (item_list[verspec].component[0] == '.')) {
870 *name = item_list[namespec].component;
871 *name_len = item_list[namespec].length + item_list[typespec].length;
872 *ext = item_list[verspec].component;
873 *ext_len = item_list[verspec].length;
874 *version = NULL;
875 *ver_len = 0;
876 }
877 else {
878 *name = item_list[namespec].component;
879 *name_len = item_list[namespec].length;
880 *ext = item_list[typespec].component;
881 *ext_len = item_list[typespec].length;
882 *version = item_list[verspec].component;
883 *ver_len = item_list[verspec].length;
884 }
885 return ret_stat;
886}
887
888
889
890
891
892
893
894
895
896static int
897my_maxidx(const char *lnm)
898{
899 int status;
900 int midx;
901 int attr = LNM$M_CASE_BLIND;
902 struct dsc$descriptor lnmdsc;
903 struct itmlst_3 itlst[2] = {{sizeof(midx), LNM$_MAX_INDEX, &midx, 0},
904 {0, 0, 0, 0}};
905
906 lnmdsc.dsc$w_length = strlen(lnm);
907 lnmdsc.dsc$b_dtype = DSC$K_DTYPE_T;
908 lnmdsc.dsc$b_class = DSC$K_CLASS_S;
909 lnmdsc.dsc$a_pointer = (char *) lnm;
910
911 status = sys$trnlnm(&attr, &fildevdsc, &lnmdsc, 0, itlst);
912 if ((status & 1) == 0)
913 midx = 0;
914
915 return (midx);
916}
917
918
919
920int
921Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
922 struct dsc$descriptor_s **tabvec, unsigned long int flags)
923{
924 const char *cp1;
925 char uplnm[LNM$C_NAMLENGTH+1], *cp2;
926 unsigned short int eqvlen, curtab, ivlnm = 0, ivsym = 0, ivenv = 0, secure;
927 unsigned long int retsts, attr = LNM$M_CASE_BLIND;
928 int midx;
929 unsigned char acmode;
930 struct dsc$descriptor_s lnmdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0},
931 tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
932 struct itmlst_3 lnmlst[3] = {{sizeof idx, LNM$_INDEX, &idx, 0},
933 {LNM$C_NAMLENGTH, LNM$_STRING, eqv, &eqvlen},
934 {0, 0, 0, 0}};
935 $DESCRIPTOR(crtlenv,"CRTL_ENV"); $DESCRIPTOR(clisym,"CLISYM");
936#if defined(PERL_IMPLICIT_CONTEXT)
937 pTHX = NULL;
938 if (PL_curinterp) {
939 aTHX = PERL_GET_INTERP;
940 } else {
941 aTHX = NULL;
942 }
943#endif
944
945 if (!lnm || !eqv || ((idx != 0) && ((idx-1) > PERL_LNM_MAX_ALLOWED_INDEX))) {
946 set_errno(EINVAL); set_vaxc_errno(SS$_BADPARAM); return 0;
947 }
948 for (cp1 = lnm, cp2 = uplnm; *cp1; cp1++, cp2++) {
949 *cp2 = _toupper(*cp1);
950 if (cp1 - lnm > LNM$C_NAMLENGTH) {
951 set_errno(EINVAL); set_vaxc_errno(SS$_IVLOGNAM);
952 return 0;
953 }
954 }
955 lnmdsc.dsc$w_length = cp1 - lnm;
956 lnmdsc.dsc$a_pointer = uplnm;
957 uplnm[lnmdsc.dsc$w_length] = '\0';
958 secure = flags & PERL__TRNENV_SECURE;
959 acmode = secure ? PSL$C_EXEC : PSL$C_USER;
960 if (!tabvec || !*tabvec) tabvec = env_tables;
961
962 for (curtab = 0; tabvec[curtab]; curtab++) {
963 if (!str$case_blind_compare(tabvec[curtab],&crtlenv)) {
964 if (!ivenv && !secure) {
965 char *eq, *end;
966 int i;
967 if (!environ) {
968 ivenv = 1;
969 Perl_warn(aTHX_ "Can't read CRTL environ\n");
970 continue;
971 }
972 retsts = SS$_NOLOGNAM;
973 for (i = 0; environ[i]; i++) {
974 if ((eq = strchr(environ[i],'=')) &&
975 lnmdsc.dsc$w_length == (eq - environ[i]) &&
976 !strncmp(environ[i],uplnm,eq - environ[i])) {
977 eq++;
978 for (eqvlen = 0; eq[eqvlen]; eqvlen++) eqv[eqvlen] = eq[eqvlen];
979 if (!eqvlen) continue;
980 retsts = SS$_NORMAL;
981 break;
982 }
983 }
984 if (retsts != SS$_NOLOGNAM) break;
985 }
986 }
987 else if ((tmpdsc.dsc$a_pointer = tabvec[curtab]->dsc$a_pointer) &&
988 !str$case_blind_compare(&tmpdsc,&clisym)) {
989 if (!ivsym && !secure) {
990 unsigned short int deflen = LNM$C_NAMLENGTH;
991 struct dsc$descriptor_d eqvdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
992
993 _ckvmssts(lib$sget1_dd(&deflen,&eqvdsc));
994 retsts = lib$get_symbol(&lnmdsc,&eqvdsc,&eqvlen,0);
995 if (retsts & 1) {
996 if (eqvlen > MAX_DCL_SYMBOL) {
997 set_errno(EVMSERR); set_vaxc_errno(LIB$_STRTRU);
998 eqvlen = MAX_DCL_SYMBOL;
999
1000
1001
1002
1003 if (ckWARN(WARN_MISC)) {
1004 Perl_warner(aTHX_ packWARN(WARN_MISC),"Value of CLI symbol \"%s\" too long",lnm);
1005 }
1006 }
1007 strncpy(eqv,eqvdsc.dsc$a_pointer,eqvlen);
1008 }
1009 _ckvmssts(lib$sfree1_dd(&eqvdsc));
1010 if (retsts == LIB$_INVSYMNAM) { ivsym = 1; continue; }
1011 if (retsts == LIB$_NOSUCHSYM) continue;
1012 break;
1013 }
1014 }
1015 else if (!ivlnm) {
1016 if ( (idx == 0) && (flags & PERL__TRNENV_JOIN_SEARCHLIST) ) {
1017 midx = my_maxidx(lnm);
1018 for (idx = 0, cp2 = eqv; idx <= midx; idx++) {
1019 lnmlst[1].bufadr = cp2;
1020 eqvlen = 0;
1021 retsts = sys$trnlnm(&attr,tabvec[curtab],&lnmdsc,&acmode,lnmlst);
1022 if (retsts == SS$_IVLOGNAM) { ivlnm = 1; break; }
1023 if (retsts == SS$_NOLOGNAM) break;
1024
1025 if (
1026#if INTSIZE == 4
1027 *((int *)uplnm) == *((int *)"SYS$") &&
1028#endif
1029 eqvlen >= 4 && eqv[0] == 0x1b && eqv[1] == 0x00 &&
1030 ( (uplnm[4] == 'O' && !strcmp(uplnm,"SYS$OUTPUT")) ||
1031 (uplnm[4] == 'I' && !strcmp(uplnm,"SYS$INPUT")) ||
1032 (uplnm[4] == 'E' && !strcmp(uplnm,"SYS$ERROR")) ||
1033 (uplnm[4] == 'C' && !strcmp(uplnm,"SYS$COMMAND")) ) ) {
1034 memmove(eqv,eqv+4,eqvlen-4);
1035 eqvlen -= 4;
1036 }
1037 cp2 += eqvlen;
1038 *cp2 = '\0';
1039 }
1040 if ((retsts == SS$_IVLOGNAM) ||
1041 (retsts == SS$_NOLOGNAM)) { continue; }
1042 }
1043 else {
1044 retsts = sys$trnlnm(&attr,tabvec[curtab],&lnmdsc,&acmode,lnmlst);
1045 if (retsts == SS$_IVLOGNAM) { ivlnm = 1; continue; }
1046 if (retsts == SS$_NOLOGNAM) continue;
1047 eqv[eqvlen] = '\0';
1048 }
1049 eqvlen = strlen(eqv);
1050 break;
1051 }
1052 }
1053 if (retsts & 1) { eqv[eqvlen] = '\0'; return eqvlen; }
1054 else if (retsts == LIB$_NOSUCHSYM || retsts == LIB$_INVSYMNAM ||
1055 retsts == SS$_IVLOGNAM || retsts == SS$_IVLOGTAB ||
1056 retsts == SS$_NOLOGNAM) {
1057 set_errno(EINVAL); set_vaxc_errno(retsts);
1058 }
1059 else _ckvmssts(retsts);
1060 return 0;
1061}
1062
1063
1064
1065
1066int Perl_my_trnlnm(pTHX_ const char *lnm, char *eqv, unsigned long int idx)
1067{
1068 return vmstrnenv(lnm,eqv,idx,fildev,
1069#ifdef SECURE_INTERNAL_GETENV
1070 (PL_curinterp ? PL_tainting : will_taint) ? PERL__TRNENV_SECURE : 0
1071#else
1072 0
1073#endif
1074 );
1075}
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087char *
1088Perl_my_getenv(pTHX_ const char *lnm, bool sys)
1089{
1090 const char *cp1;
1091 static char *__my_getenv_eqv = NULL;
1092 char uplnm[LNM$C_NAMLENGTH+1], *cp2, *eqv;
1093 unsigned long int idx = 0;
1094 int trnsuccess, success, secure, saverr, savvmserr;
1095 int midx, flags;
1096 SV *tmpsv;
1097
1098 midx = my_maxidx(lnm) + 1;
1099
1100 if (PL_curinterp) {
1101
1102
1103 tmpsv = sv_2mortal(newSVpv("",(LNM$C_NAMLENGTH*midx)+1));
1104 if (!tmpsv) return NULL;
1105 eqv = SvPVX(tmpsv);
1106 }
1107 else {
1108
1109 if (__my_getenv_eqv != NULL) {
1110 Renew(__my_getenv_eqv,LNM$C_NAMLENGTH*midx+1,char);
1111 }
1112 else {
1113 Newx(__my_getenv_eqv,LNM$C_NAMLENGTH*midx+1,char);
1114 }
1115 eqv = __my_getenv_eqv;
1116 }
1117
1118 for (cp1 = lnm, cp2 = eqv; *cp1; cp1++,cp2++) *cp2 = _toupper(*cp1);
1119 if (cp1 - lnm == 7 && !strncmp(eqv,"DEFAULT",7)) {
1120 int len;
1121 getcwd(eqv,LNM$C_NAMLENGTH);
1122
1123 len = strlen(eqv);
1124
1125
1126 if (len > 7) {
1127 char * zeros;
1128 zeros = strstr(eqv, "/000000/");
1129 if (zeros != NULL) {
1130 int mlen;
1131 mlen = len - (zeros - eqv) - 7;
1132 memmove(zeros, &zeros[7], mlen);
1133 len = len - 7;
1134 eqv[len] = '\0';
1135 }
1136 }
1137 return eqv;
1138 }
1139 else {
1140
1141 if (sys) {
1142
1143 secure = PL_curinterp ? PL_tainting : will_taint;
1144 saverr = errno; savvmserr = vaxc$errno;
1145 }
1146 else {
1147 secure = 0;
1148 }
1149
1150 flags =
1151#ifdef SECURE_INTERNAL_GETENV
1152 secure ? PERL__TRNENV_SECURE : 0
1153#else
1154 0
1155#endif
1156 ;
1157
1158
1159
1160
1161
1162 flags |= PERL__TRNENV_JOIN_SEARCHLIST;
1163
1164
1165
1166
1167 if ((cp2 = strchr(lnm,';')) != NULL) {
1168 strcpy(uplnm,lnm);
1169 uplnm[cp2-lnm] = '\0';
1170 idx = strtoul(cp2+1,NULL,0);
1171 lnm = uplnm;
1172 flags &= ~PERL__TRNENV_JOIN_SEARCHLIST;
1173 }
1174
1175 success = vmstrnenv(lnm,eqv,idx,secure ? fildev : NULL,flags);
1176
1177
1178
1179
1180 if (sys && vaxc$errno == SS$_NOLOGNAM) SETERRNO(saverr,savvmserr);
1181 return success ? eqv : Nullch;
1182 }
1183
1184}
1185
1186
1187
1188
1189char *
1190Perl_my_getenv_len(pTHX_ const char *lnm, unsigned long *len, bool sys)
1191{
1192 const char *cp1;
1193 char *buf, *cp2;
1194 unsigned long idx = 0;
1195 int midx, flags;
1196 static char *__my_getenv_len_eqv = NULL;
1197 int secure, saverr, savvmserr;
1198 SV *tmpsv;
1199
1200 midx = my_maxidx(lnm) + 1;
1201
1202 if (PL_curinterp) {
1203
1204
1205 tmpsv = sv_2mortal(newSVpv("",(LNM$C_NAMLENGTH*midx)+1));
1206 if (!tmpsv) return NULL;
1207 buf = SvPVX(tmpsv);
1208 }
1209 else {
1210
1211 if (__my_getenv_len_eqv != NULL) {
1212 Renew(__my_getenv_len_eqv,LNM$C_NAMLENGTH*midx+1,char);
1213 }
1214 else {
1215 Newx(__my_getenv_len_eqv,LNM$C_NAMLENGTH*midx+1,char);
1216 }
1217 buf = __my_getenv_len_eqv;
1218 }
1219
1220 for (cp1 = lnm, cp2 = buf; *cp1; cp1++,cp2++) *cp2 = _toupper(*cp1);
1221 if (cp1 - lnm == 7 && !strncmp(buf,"DEFAULT",7)) {
1222 char * zeros;
1223
1224 getcwd(buf,LNM$C_NAMLENGTH);
1225 *len = strlen(buf);
1226
1227
1228 if (*len > 7) {
1229 zeros = strstr(buf, "/000000/");
1230 if (zeros != NULL) {
1231 int mlen;
1232 mlen = *len - (zeros - buf) - 7;
1233 memmove(zeros, &zeros[7], mlen);
1234 *len = *len - 7;
1235 buf[*len] = '\0';
1236 }
1237 }
1238 return buf;
1239 }
1240 else {
1241 if (sys) {
1242
1243 secure = PL_curinterp ? PL_tainting : will_taint;
1244 saverr = errno; savvmserr = vaxc$errno;
1245 }
1246 else {
1247 secure = 0;
1248 }
1249
1250 flags =
1251#ifdef SECURE_INTERNAL_GETENV
1252 secure ? PERL__TRNENV_SECURE : 0
1253#else
1254 0
1255#endif
1256 ;
1257
1258 flags |= PERL__TRNENV_JOIN_SEARCHLIST;
1259
1260 if ((cp2 = strchr(lnm,';')) != NULL) {
1261 strcpy(buf,lnm);
1262 buf[cp2-lnm] = '\0';
1263 idx = strtoul(cp2+1,NULL,0);
1264 lnm = buf;
1265 flags &= ~PERL__TRNENV_JOIN_SEARCHLIST;
1266 }
1267
1268 *len = vmstrnenv(lnm,buf,idx,secure ? fildev : NULL,flags);
1269
1270
1271 if (*len > 7) {
1272 char * zeros;
1273 zeros = strstr(buf, "/000000/");
1274 if (zeros != NULL) {
1275 int mlen;
1276 mlen = *len - (zeros - buf) - 7;
1277 memmove(zeros, &zeros[7], mlen);
1278 *len = *len - 7;
1279 buf[*len] = '\0';
1280 }
1281 }
1282
1283
1284
1285
1286 if (sys && vaxc$errno == SS$_NOLOGNAM) SETERRNO(saverr,savvmserr);
1287 return *len ? buf : Nullch;
1288 }
1289
1290}
1291
1292
1293static void create_mbx(pTHX_ unsigned short int *, struct dsc$descriptor_s *);
1294
1295static void riseandshine(unsigned long int dummy) { sys$wake(0,0); }
1296
1297
1298void
1299prime_env_iter(void)
1300
1301
1302
1303{
1304 static int primed = 0;
1305 HV *seenhv = NULL, *envhv;
1306 SV *sv = NULL;
1307 char cmd[LNM$C_NAMLENGTH+24], mbxnam[LNM$C_NAMLENGTH], *buf = Nullch;
1308 unsigned short int chan;
1309#ifndef CLI$M_TRUSTED
1310# define CLI$M_TRUSTED 0x40
1311#endif
1312 unsigned long int defflags = CLI$M_NOWAIT | CLI$M_NOKEYPAD | CLI$M_TRUSTED;
1313 unsigned long int mbxbufsiz, flags, retsts, subpid = 0, substs = 0, wakect = 0;
1314 long int i;
1315 bool have_sym = FALSE, have_lnm = FALSE;
1316 struct dsc$descriptor_s tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
1317 $DESCRIPTOR(cmddsc,cmd); $DESCRIPTOR(nldsc,"_NLA0:");
1318 $DESCRIPTOR(clidsc,"DCL"); $DESCRIPTOR(clitabdsc,"DCLTABLES");
1319 $DESCRIPTOR(crtlenv,"CRTL_ENV"); $DESCRIPTOR(clisym,"CLISYM");
1320 $DESCRIPTOR(local,"_LOCAL"); $DESCRIPTOR(mbxdsc,mbxnam);
1321#if defined(PERL_IMPLICIT_CONTEXT)
1322 pTHX;
1323#endif
1324#if defined(USE_ITHREADS)
1325 static perl_mutex primenv_mutex;
1326 MUTEX_INIT(&primenv_mutex);
1327#endif
1328
1329#if defined(PERL_IMPLICIT_CONTEXT)
1330
1331
1332
1333
1334 if (PL_curinterp) {
1335 aTHX = PERL_GET_INTERP;
1336 } else {
1337 aTHX = NULL;
1338 }
1339#endif
1340
1341 if (primed || !PL_envgv) return;
1342 MUTEX_LOCK(&primenv_mutex);
1343 if (primed) { MUTEX_UNLOCK(&primenv_mutex); return; }
1344 envhv = GvHVn(PL_envgv);
1345
1346
1347 (void) hv_fetch(envhv,"DEFAULT",7,TRUE);
1348
1349 for (i = 0; env_tables[i]; i++) {
1350 if (!have_sym && (tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer) &&
1351 !str$case_blind_compare(&tmpdsc,&clisym)) have_sym = 1;
1352 if (!have_lnm && str$case_blind_compare(env_tables[i],&crtlenv)) have_lnm = 1;
1353 }
1354 if (have_sym || have_lnm) {
1355 long int syiitm = SYI$_MAXBUF, dviitm = DVI$_DEVNAM;
1356 _ckvmssts(lib$getsyi(&syiitm, &mbxbufsiz, 0, 0, 0, 0));
1357 _ckvmssts(sys$crembx(0,&chan,mbxbufsiz,mbxbufsiz,0xff0f,0,0));
1358 _ckvmssts(lib$getdvi(&dviitm, &chan, NULL, NULL, &mbxdsc, &mbxdsc.dsc$w_length));
1359 }
1360
1361 for (i--; i >= 0; i--) {
1362 if (!str$case_blind_compare(env_tables[i],&crtlenv)) {
1363 char *start;
1364 int j;
1365 for (j = 0; environ[j]; j++) {
1366 if (!(start = strchr(environ[j],'='))) {
1367 if (ckWARN(WARN_INTERNAL))
1368 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"Ill-formed CRTL environ value \"%s\"\n",environ[j]);
1369 }
1370 else {
1371 start++;
1372 sv = newSVpv(start,0);
1373 SvTAINTED_on(sv);
1374 (void) hv_store(envhv,environ[j],start - environ[j] - 1,sv,0);
1375 }
1376 }
1377 continue;
1378 }
1379 else if ((tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer) &&
1380 !str$case_blind_compare(&tmpdsc,&clisym)) {
1381 strcpy(cmd,"Show Symbol/Global *");
1382 cmddsc.dsc$w_length = 20;
1383 if (env_tables[i]->dsc$w_length == 12 &&
1384 (tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer + 6) &&
1385 !str$case_blind_compare(&tmpdsc,&local)) strcpy(cmd+12,"Local *");
1386 flags = defflags | CLI$M_NOLOGNAM;
1387 }
1388 else {
1389 strcpy(cmd,"Show Logical *");
1390 if (str$case_blind_compare(env_tables[i],&fildevdsc)) {
1391 strcat(cmd," /Table=");
1392 strncat(cmd,env_tables[i]->dsc$a_pointer,env_tables[i]->dsc$w_length);
1393 cmddsc.dsc$w_length = strlen(cmd);
1394 }
1395 else cmddsc.dsc$w_length = 14;
1396 flags = defflags | CLI$M_NOCLISYM;
1397 }
1398
1399
1400
1401
1402
1403 do {
1404 retsts = lib$spawn(&cmddsc,&nldsc,&mbxdsc,&flags,0,&subpid,&substs,
1405 0,&riseandshine,0,0,&clidsc,&clitabdsc);
1406 flags &= ~CLI$M_TRUSTED;
1407 defflags &= ~CLI$M_TRUSTED;
1408 } while (retsts == LIB$_INVARG && (flags | CLI$M_TRUSTED));
1409 _ckvmssts(retsts);
1410 if (!buf) Newx(buf,mbxbufsiz + 1,char);
1411 if (seenhv) SvREFCNT_dec(seenhv);
1412 seenhv = newHV();
1413 while (1) {
1414 char *cp1, *cp2, *key;
1415 unsigned long int sts, iosb[2], retlen, keylen;
1416 register U32 hash;
1417
1418 sts = sys$qiow(0,chan,IO$_READVBLK,iosb,0,0,buf,mbxbufsiz,0,0,0,0);
1419 if (sts & 1) sts = iosb[0] & 0xffff;
1420 if (sts == SS$_ENDOFFILE) {
1421 int wakect = 0;
1422 while (substs == 0) { sys$hiber(); wakect++;}
1423 if (wakect > 1) sys$wake(0,0);
1424 _ckvmssts(substs);
1425 break;
1426 }
1427 _ckvmssts(sts);
1428 retlen = iosb[0] >> 16;
1429 if (!retlen) continue;
1430 buf[retlen] = '\0';
1431 if (iosb[1] != subpid) {
1432 if (iosb[1]) {
1433 Perl_croak(aTHX_ "Unknown process %x sent message to prime_env_iter: %s",buf);
1434 }
1435 continue;
1436 }
1437 if (sts == SS$_BUFFEROVF && ckWARN(WARN_INTERNAL))
1438 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"Buffer overflow in prime_env_iter: %s",buf);
1439
1440 for (cp1 = buf; *cp1 && isspace(*cp1); cp1++) ;
1441 if (*cp1 == '(' ||
1442 *cp1 == '=' ) continue;
1443 if (*cp1 == '"') cp1++;
1444 for (cp2 = cp1; *cp2 && *cp2 != '"' && *cp2 != ' '; cp2++) ;
1445 key = cp1; keylen = cp2 - cp1;
1446 if (keylen && hv_exists(seenhv,key,keylen)) continue;
1447 while (*cp2 && *cp2 != '=') cp2++;
1448 while (*cp2 && *cp2 == '=') cp2++;
1449 while (*cp2 && *cp2 == ' ') cp2++;
1450 if (*cp2 == '"') {
1451 for (cp1 = buf + retlen; *cp1 != '"'; cp1--) ;
1452 cp2++; cp1--;
1453 }
1454 else {
1455 for (cp1 = cp2; *cp1 && *cp1 != ' '; cp1++) ;
1456 cp1--;
1457 }
1458 if ((!keylen || (cp1 - cp2 < -1)) && ckWARN(WARN_INTERNAL)) {
1459 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"Ill-formed message in prime_env_iter: |%s|",buf);
1460 continue;
1461 }
1462 PERL_HASH(hash,key,keylen);
1463
1464 if (cp1 == cp2 && *cp2 == '.') {
1465
1466
1467
1468 char lnm[LNM$C_NAMLENGTH+1];
1469 char eqv[MAX_DCL_SYMBOL+1];
1470 int trnlen;
1471 strncpy(lnm, key, keylen);
1472 trnlen = vmstrnenv(lnm, eqv, 0, fildev, 0);
1473 sv = newSVpvn(eqv, strlen(eqv));
1474 }
1475 else {
1476 sv = newSVpvn(cp2,cp1 - cp2 + 1);
1477 }
1478
1479 SvTAINTED_on(sv);
1480 hv_store(envhv,key,keylen,sv,hash);
1481 hv_store(seenhv,key,keylen,&PL_sv_yes,hash);
1482 }
1483 if (cmddsc.dsc$w_length == 14) {
1484
1485 const char *ppfs[] = {"SYS$COMMAND", "SYS$INPUT", "SYS$OUTPUT", "SYS$ERROR", NULL};
1486 char eqv[LNM$C_NAMLENGTH+1];
1487 int trnlen, i;
1488 for (i = 0; ppfs[i]; i++) {
1489 trnlen = vmstrnenv(ppfs[i],eqv,0,fildev,0);
1490 sv = newSVpv(eqv,trnlen);
1491 SvTAINTED_on(sv);
1492 hv_store(envhv,ppfs[i],strlen(ppfs[i]),sv,0);
1493 }
1494 }
1495 }
1496 primed = 1;
1497 if (have_sym || have_lnm) _ckvmssts(sys$dassgn(chan));
1498 if (buf) Safefree(buf);
1499 if (seenhv) SvREFCNT_dec(seenhv);
1500 MUTEX_UNLOCK(&primenv_mutex);
1501 return;
1502
1503}
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514int
1515Perl_vmssetenv(pTHX_ const char *lnm, const char *eqv, struct dsc$descriptor_s **tabvec)
1516{
1517 const char *cp1;
1518 char uplnm[LNM$C_NAMLENGTH], *cp2, *c;
1519 unsigned short int curtab, ivlnm = 0, ivsym = 0, ivenv = 0;
1520 int nseg = 0, j;
1521 unsigned long int retsts, usermode = PSL$C_USER;
1522 struct itmlst_3 *ile, *ilist;
1523 struct dsc$descriptor_s lnmdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,uplnm},
1524 eqvdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0},
1525 tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
1526 $DESCRIPTOR(crtlenv,"CRTL_ENV"); $DESCRIPTOR(clisym,"CLISYM");
1527 $DESCRIPTOR(local,"_LOCAL");
1528
1529 if (!lnm) {
1530 set_errno(EINVAL); set_vaxc_errno(SS$_IVLOGNAM);
1531 return SS$_IVLOGNAM;
1532 }
1533
1534 for (cp1 = lnm, cp2 = uplnm; *cp1; cp1++, cp2++) {
1535 *cp2 = _toupper(*cp1);
1536 if (cp1 - lnm > LNM$C_NAMLENGTH) {
1537 set_errno(EINVAL); set_vaxc_errno(SS$_IVLOGNAM);
1538 return SS$_IVLOGNAM;
1539 }
1540 }
1541 lnmdsc.dsc$w_length = cp1 - lnm;
1542 if (!tabvec || !*tabvec) tabvec = env_tables;
1543
1544 if (!eqv) {
1545 for (curtab = 0; tabvec[curtab]; curtab++) {
1546 if (!ivenv && !str$case_blind_compare(tabvec[curtab],&crtlenv)) {
1547 int i;
1548 for (i = 0; environ[i]; i++) {
1549 if ((cp1 = strchr(environ[i],'=')) &&
1550 lnmdsc.dsc$w_length == (cp1 - environ[i]) &&
1551 !strncmp(environ[i],lnm,cp1 - environ[i])) {
1552#ifdef HAS_SETENV
1553 return setenv(lnm,"",1) ? vaxc$errno : 0;
1554 }
1555 }
1556 ivenv = 1; retsts = SS$_NOLOGNAM;
1557#else
1558 if (ckWARN(WARN_INTERNAL))
1559 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"This Perl can't reset CRTL environ elements (%s)",lnm);
1560 ivenv = 1; retsts = SS$_NOSUCHPGM;
1561 break;
1562 }
1563 }
1564#endif
1565 }
1566 else if ((tmpdsc.dsc$a_pointer = tabvec[curtab]->dsc$a_pointer) &&
1567 !str$case_blind_compare(&tmpdsc,&clisym)) {
1568 unsigned int symtype;
1569 if (tabvec[curtab]->dsc$w_length == 12 &&
1570 (tmpdsc.dsc$a_pointer = tabvec[curtab]->dsc$a_pointer + 6) &&
1571 !str$case_blind_compare(&tmpdsc,&local))
1572 symtype = LIB$K_CLI_LOCAL_SYM;
1573 else symtype = LIB$K_CLI_GLOBAL_SYM;
1574 retsts = lib$delete_symbol(&lnmdsc,&symtype);
1575 if (retsts == LIB$_INVSYMNAM) { ivsym = 1; continue; }
1576 if (retsts == LIB$_NOSUCHSYM) continue;
1577 break;
1578 }
1579 else if (!ivlnm) {
1580 retsts = sys$dellnm(tabvec[curtab],&lnmdsc,&usermode);
1581 if (retsts == SS$_IVLOGNAM) { ivlnm = 1; continue; }
1582 if (retsts != SS$_NOLOGNAM && retsts != SS$_NOLOGTAB) break;
1583 retsts = lib$delete_logical(&lnmdsc,tabvec[curtab]);
1584 if (retsts != SS$_NOLOGNAM && retsts != SS$_NOLOGTAB) break;
1585 }
1586 }
1587 }
1588 else {
1589 if (!ivenv && !str$case_blind_compare(tabvec[0],&crtlenv)) {
1590#ifdef HAS_SETENV
1591 return setenv(lnm,eqv,1) ? vaxc$errno : 0;
1592#else
1593 if (ckWARN(WARN_INTERNAL))
1594 Perl_warner(aTHX_ packWARN(WARN_INTERNAL),"This Perl can't set CRTL environ elements (%s=%s)",lnm,eqv);
1595 retsts = SS$_NOSUCHPGM;
1596#endif
1597 }
1598 else {
1599 eqvdsc.dsc$a_pointer = (char *) eqv;
1600 eqvdsc.dsc$w_length = strlen(eqv);
1601 if ((tmpdsc.dsc$a_pointer = tabvec[0]->dsc$a_pointer) &&
1602 !str$case_blind_compare(&tmpdsc,&clisym)) {
1603 unsigned int symtype;
1604 if (tabvec[0]->dsc$w_length == 12 &&
1605 (tmpdsc.dsc$a_pointer = tabvec[0]->dsc$a_pointer + 6) &&
1606 !str$case_blind_compare(&tmpdsc,&local))
1607 symtype = LIB$K_CLI_LOCAL_SYM;
1608 else symtype = LIB$K_CLI_GLOBAL_SYM;
1609 retsts = lib$set_symbol(&lnmdsc,&eqvdsc,&symtype);
1610 }
1611 else {
1612 if (!*eqv) eqvdsc.dsc$w_length = 1;
1613 if (eqvdsc.dsc$w_length > LNM$C_NAMLENGTH) {
1614
1615 nseg = (eqvdsc.dsc$w_length + LNM$C_NAMLENGTH - 1) / LNM$C_NAMLENGTH;
1616 if (nseg > PERL_LNM_MAX_ALLOWED_INDEX + 1) {
1617 Perl_warner(aTHX_ packWARN(WARN_MISC),"Value of logical \"%s\" too long. Truncating to %i bytes",
1618 lnm, LNM$C_NAMLENGTH * (PERL_LNM_MAX_ALLOWED_INDEX+1));
1619 eqvdsc.dsc$w_length = LNM$C_NAMLENGTH * (PERL_LNM_MAX_ALLOWED_INDEX+1);
1620 nseg = PERL_LNM_MAX_ALLOWED_INDEX + 1;
1621 }
1622
1623 Newx(ilist,nseg+1,struct itmlst_3);
1624 ile = ilist;
1625 if (!ile) {
1626 set_errno(ENOMEM); set_vaxc_errno(SS$_INSFMEM);
1627 return SS$_INSFMEM;
1628 }
1629 memset(ilist, 0, (sizeof(struct itmlst_3) * (nseg+1)));
1630
1631 for (j = 0, c = eqvdsc.dsc$a_pointer; j < nseg; j++, ile++, c += LNM$C_NAMLENGTH) {
1632 ile->itmcode = LNM$_STRING;
1633 ile->bufadr = c;
1634 if ((j+1) == nseg) {
1635 ile->buflen = strlen(c);
1636
1637 if (ile->buflen > LNM$C_NAMLENGTH) ile->buflen = LNM$C_NAMLENGTH;
1638 }
1639 else {
1640 ile->buflen = LNM$C_NAMLENGTH;
1641 }
1642 }
1643
1644 retsts = lib$set_logical(&lnmdsc,0,tabvec[0],0,ilist);
1645 Safefree (ilist);
1646 }
1647 else {
1648 retsts = lib$set_logical(&lnmdsc,&eqvdsc,tabvec[0],0,0);
1649 }
1650 }
1651 }
1652 }
1653 if (!(retsts & 1)) {
1654 switch (retsts) {
1655 case LIB$_AMBSYMDEF: case LIB$_INSCLIMEM:
1656 case SS$_NOLOGTAB: case SS$_TOOMANYLNAM: case SS$_IVLOGTAB:
1657 set_errno(EVMSERR); break;
1658 case LIB$_INVARG: case LIB$_INVSYMNAM: case SS$_IVLOGNAM:
1659 case LIB$_NOSUCHSYM: case SS$_NOLOGNAM:
1660 set_errno(EINVAL); break;
1661 case SS$_NOPRIV:
1662 set_errno(EACCES); break;
1663 default:
1664 _ckvmssts(retsts);
1665 set_errno(EVMSERR);
1666 }
1667 set_vaxc_errno(retsts);
1668 return (int) retsts || 44;
1669 }
1670 else {
1671
1672
1673
1674
1675
1676
1677
1678
1679 set_errno(0); set_vaxc_errno(retsts);
1680 return 0;
1681 }
1682
1683}
1684
1685
1686
1687
1688void
1689Perl_my_setenv(pTHX_ const char *lnm, const char *eqv)
1690{
1691 if (lnm && *lnm) {
1692 int len = strlen(lnm);
1693 if (len == 7) {
1694 char uplnm[8];
1695 int i;
1696 for (i = 0; lnm[i]; i++) uplnm[i] = _toupper(lnm[i]);
1697 if (!strcmp(uplnm,"DEFAULT")) {
1698 if (eqv && *eqv) my_chdir(eqv);
1699 return;
1700 }
1701 }
1702#ifndef RTL_USES_UTC
1703 if (len == 6 || len == 2) {
1704 char uplnm[7];
1705 int i;
1706 for (i = 0; lnm[i]; i++) uplnm[i] = _toupper(lnm[i]);
1707 uplnm[len] = '\0';
1708 if (!strcmp(uplnm,"UCX$TZ")) tz_updated = 1;
1709 if (!strcmp(uplnm,"TZ")) tz_updated = 1;
1710 }
1711#endif
1712 }
1713 (void) vmssetenv(lnm,eqv,NULL);
1714}
1715
1716
1717
1718
1719
1720
1721
1722void
1723Perl_vmssetuserlnm(pTHX_ const char *name, const char *eqv)
1724{
1725 $DESCRIPTOR(d_tab, "LNM$PROCESS");
1726 struct dsc$descriptor_d d_name = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
1727 unsigned long int iss, attr = LNM$M_CONFINE;
1728 unsigned char acmode = PSL$C_USER;
1729 struct itmlst_3 lnmlst[2] = {{0, LNM$_STRING, 0, 0},
1730 {0, 0, 0, 0}};
1731 d_name.dsc$a_pointer = (char *)name;
1732 d_name.dsc$w_length = strlen(name);
1733
1734 lnmlst[0].buflen = strlen(eqv);
1735 lnmlst[0].bufadr = (char *)eqv;
1736
1737 iss = sys$crelnm(&attr,&d_tab,&d_name,&acmode,lnmlst);
1738 if (!(iss&1)) lib$signal(iss);
1739}
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755char *
1756Perl_my_crypt(pTHX_ const char *textpasswd, const char *usrname)
1757{
1758# ifndef UAI$C_PREFERRED_ALGORITHM
1759# define UAI$C_PREFERRED_ALGORITHM 127
1760# endif
1761 unsigned char alg = UAI$C_PREFERRED_ALGORITHM;
1762 unsigned short int salt = 0;
1763 unsigned long int sts;
1764 struct const_dsc {
1765 unsigned short int dsc$w_length;
1766 unsigned char dsc$b_type;
1767 unsigned char dsc$b_class;
1768 const char * dsc$a_pointer;
1769 } usrdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0},
1770 txtdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
1771 struct itmlst_3 uailst[3] = {
1772 { sizeof alg, UAI$_ENCRYPT, &alg, 0},
1773 { sizeof salt, UAI$_SALT, &salt, 0},
1774 { 0, 0, NULL, NULL}};
1775 static char hash[9];
1776
1777 usrdsc.dsc$w_length = strlen(usrname);
1778 usrdsc.dsc$a_pointer = usrname;
1779 if (!((sts = sys$getuai(0, 0, &usrdsc, uailst, 0, 0, 0)) & 1)) {
1780 switch (sts) {
1781 case SS$_NOGRPPRV: case SS$_NOSYSPRV:
1782 set_errno(EACCES);
1783 break;
1784 case RMS$_RNF:
1785 set_errno(ESRCH);
1786 break;
1787 default:
1788 set_errno(EVMSERR);
1789 }
1790 set_vaxc_errno(sts);
1791 if (sts != RMS$_RNF) return NULL;
1792 }
1793
1794 txtdsc.dsc$w_length = strlen(textpasswd);
1795 txtdsc.dsc$a_pointer = textpasswd;
1796 if (!((sts = sys$hash_password(&txtdsc, alg, salt, &usrdsc, &hash)) & 1)) {
1797 set_errno(EVMSERR); set_vaxc_errno(sts); return NULL;
1798 }
1799
1800 return (char *) hash;
1801
1802}
1803
1804
1805
1806static char *mp_do_rmsexpand(pTHX_ const char *, char *, int, const char *, unsigned, int *, int *);
1807static char *mp_do_fileify_dirspec(pTHX_ const char *, char *, int, int *);
1808static char *mp_do_tovmsspec(pTHX_ const char *, char *, int, int, int *);
1809
1810
1811
1812
1813
1814
1815
1816static char * fixup_bare_dirnames(const char * name)
1817{
1818 if (decc_disable_to_vms_logname_translation) {
1819
1820 }
1821 return NULL;
1822}
1823
1824
1825static int rms_erase(const char * vmsname);
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840static int
1841mp_do_kill_file(pTHX_ const char *name, int dirflag)
1842{
1843 char *vmsname;
1844 char *rslt;
1845 unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE;
1846 unsigned long int cxt = 0, aclsts, fndsts, rmsts = -1;
1847 struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
1848 struct myacedef {
1849 unsigned char myace$b_length;
1850 unsigned char myace$b_type;
1851 unsigned short int myace$w_flags;
1852 unsigned long int myace$l_access;
1853 unsigned long int myace$l_ident;
1854 } newace = { sizeof(struct myacedef), ACE$C_KEYID, 0,
1855 ACE$M_READ | ACE$M_WRITE | ACE$M_DELETE | ACE$M_CONTROL, 0},
1856 oldace = { sizeof(struct myacedef), ACE$C_KEYID, 0, 0, 0};
1857 struct itmlst_3
1858 findlst[3] = {{sizeof oldace, ACL$C_FNDACLENT, &oldace, 0},
1859 {sizeof oldace, ACL$C_READACE, &oldace, 0},{0,0,0,0}},
1860 addlst[2] = {{sizeof newace, ACL$C_ADDACLENT, &newace, 0},{0,0,0,0}},
1861 dellst[2] = {{sizeof newace, ACL$C_DELACLENT, &newace, 0},{0,0,0,0}},
1862 lcklst[2] = {{sizeof newace, ACL$C_WLOCK_ACL, &newace, 0},{0,0,0,0}},
1863 ulklst[2] = {{sizeof newace, ACL$C_UNLOCK_ACL, &newace, 0},{0,0,0,0}};
1864
1865
1866
1867
1868 vmsname = PerlMem_malloc(NAM$C_MAXRSS+1);
1869 if (vmsname == NULL) _ckvmssts(SS$_INSFMEM);
1870
1871 rslt = do_rmsexpand(name,
1872 vmsname,
1873 0,
1874 NULL,
1875 PERL_RMSEXPAND_M_VMS | PERL_RMSEXPAND_M_SYMLINK,
1876 NULL,
1877 NULL);
1878 if (rslt == NULL) {
1879 PerlMem_free(vmsname);
1880 return -1;
1881 }
1882
1883
1884 rmsts = rms_erase(vmsname);
1885
1886
1887 if ($VMS_STATUS_SUCCESS(rmsts)) {
1888 PerlMem_free(vmsname);
1889 return 0;
1890 }
1891
1892
1893 if (rmsts != RMS$_PRV) {
1894 set_vaxc_errno(rmsts);
1895 PerlMem_free(vmsname);
1896 return -1;
1897 }
1898
1899
1900
1901
1902
1903 _ckvmssts(lib$getjpi(&jpicode,0,0,&(oldace.myace$l_ident),0,0));
1904 fildsc.dsc$w_length = strlen(vmsname);
1905 fildsc.dsc$a_pointer = vmsname;
1906 cxt = 0;
1907 newace.myace$l_ident = oldace.myace$l_ident;
1908 rmsts = -1;
1909 if (!((aclsts = sys$change_acl(0,&type,&fildsc,lcklst,0,0,0)) & 1)) {
1910 switch (aclsts) {
1911 case RMS$_FNF: case RMS$_DNF: case SS$_NOSUCHOBJECT:
1912 set_errno(ENOENT); break;
1913 case RMS$_DIR:
1914 set_errno(ENOTDIR); break;
1915 case RMS$_DEV:
1916 set_errno(ENODEV); break;
1917 case RMS$_SYN: case SS$_INVFILFOROP:
1918 set_errno(EINVAL); break;
1919 case RMS$_PRV:
1920 set_errno(EACCES); break;
1921 default:
1922 _ckvmssts(aclsts);
1923 }
1924 set_vaxc_errno(aclsts);
1925 PerlMem_free(vmsname);
1926 return -1;
1927 }
1928
1929 aclsts = fndsts = sys$change_acl(0,&type,&fildsc,findlst,0,0,&cxt);
1930 if ( fndsts & 1 || fndsts == SS$_ACLEMPTY || fndsts == SS$_NOENTRY
1931 || fndsts == SS$_NOMOREACE ) {
1932
1933 if (!((aclsts = sys$change_acl(0,&type,&fildsc,addlst,0,0,0)) & 1))
1934 goto yourroom;
1935
1936 rmsts = rms_erase(vmsname);
1937 if ($VMS_STATUS_SUCCESS(rmsts)) {
1938 rmsts = 0;
1939 }
1940 else {
1941 rmsts = -1;
1942
1943
1944 if (!((aclsts = sys$change_acl(0,&type,&fildsc,dellst,0,0,0)) & 1))
1945 goto yourroom;
1946 if (fndsts & 1) {
1947 addlst[0].bufadr = &oldace;
1948 if (!((aclsts = sys$change_acl(0,&type,&fildsc,addlst,0,0,&cxt)) & 1))
1949 goto yourroom;
1950 }
1951 }
1952 }
1953
1954 yourroom:
1955 fndsts = sys$change_acl(0,&type,&fildsc,ulklst,0,0,0);
1956
1957
1958
1959
1960 if (fndsts == RMS$_FNF || fndsts == SS$_NOSUCHOBJECT) fndsts = SS$_NORMAL;
1961 if (aclsts & 1) aclsts = fndsts;
1962 if (!(aclsts & 1)) {
1963 set_errno(EVMSERR);
1964 set_vaxc_errno(aclsts);
1965 }
1966
1967 PerlMem_free(vmsname);
1968 return rmsts;
1969
1970}
1971
1972
1973
1974
1975int
1976Perl_do_rmdir(pTHX_ const char *name)
1977{
1978 char * dirfile;
1979 int retval;
1980 Stat_t st;
1981
1982 dirfile = PerlMem_malloc(VMS_MAXRSS + 1);
1983 if (dirfile == NULL)
1984 _ckvmssts(SS$_INSFMEM);
1985
1986
1987 if (do_fileify_dirspec(name, dirfile, 0, NULL) == NULL) {
1988 PerlMem_free(dirfile);
1989 return -1;
1990 }
1991 if (Perl_flex_lstat(aTHX_ dirfile, &st) || !S_ISDIR(st.st_mode)) {
1992 errno = ENOTDIR;
1993 retval = -1;
1994 }
1995 else
1996 retval = mp_do_kill_file(aTHX_ dirfile, 1);
1997
1998 PerlMem_free(dirfile);
1999 return retval;
2000
2001}
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013int
2014Perl_kill_file(pTHX_ const char *name)
2015{
2016 char rspec[NAM$C_MAXRSS+1];
2017 char *tspec;
2018 Stat_t st;
2019 int rmsts;
2020
2021
2022
2023
2024
2025 if ((flex_lstat(name, &st) == 0) && S_ISDIR(st.st_mode)) {
2026 rmsts = Perl_do_rmdir(aTHX_ name);
2027 return rmsts;
2028 }
2029
2030 rmsts = mp_do_kill_file(aTHX_ name, 0);
2031
2032 return rmsts;
2033
2034}
2035
2036
2037
2038
2039int
2040Perl_my_mkdir(pTHX_ const char *dir, Mode_t mode)
2041{
2042 STRLEN dirlen = strlen(dir);
2043
2044
2045 if (dirlen == 0) return -1;
2046
2047
2048
2049
2050
2051 if (dir[dirlen-1] == '/') {
2052 char *newdir = savepvn(dir,dirlen-1);
2053 int ret = mkdir(newdir,mode);
2054 Safefree(newdir);
2055 return ret;
2056 }
2057 else return mkdir(dir,mode);
2058}
2059
2060
2061
2062int
2063Perl_my_chdir(pTHX_ const char *dir)
2064{
2065 STRLEN dirlen = strlen(dir);
2066
2067
2068 if (dirlen == 0) return -1;
2069 const char *dir1;
2070
2071
2072
2073
2074
2075 dir1 = dir;
2076 while ((dirlen > 0) && (*dir1 == ' ')) {
2077 dir1++;
2078 dirlen--;
2079 }
2080
2081
2082
2083
2084
2085
2086
2087
2088 if ((dirlen > 1) && (dir1[dirlen-1] == '/')) {
2089 char *newdir = savepvn(dir1,dirlen-1);
2090 int ret = chdir(newdir);
2091 Safefree(newdir);
2092 return ret;
2093 }
2094 else return chdir(dir1);
2095}
2096
2097
2098
2099
2100int
2101Perl_my_chmod(pTHX_ const char *file_spec, mode_t mode)
2102{
2103 STRLEN speclen = strlen(file_spec);
2104
2105
2106 if (speclen == 0) return -1;
2107
2108
2109
2110
2111
2112
2113
2114
2115 if ((speclen > 1) && (file_spec[speclen-1] == '/')) {
2116 char *vms_src, *vms_dir, *rslt;
2117 int ret = -1;
2118 errno = EIO;
2119
2120
2121 vms_src = PerlMem_malloc(VMS_MAXRSS);
2122 if (vms_src == NULL)
2123 _ckvmssts(SS$_INSFMEM);
2124
2125 rslt = do_tovmsspec(file_spec, vms_src, 0, NULL);
2126 if (rslt == NULL) {
2127
2128 PerlMem_free(vms_src);
2129 errno = EIO;
2130 return -1;
2131 }
2132
2133
2134 vms_dir = PerlMem_malloc(VMS_MAXRSS + 1);
2135 if (vms_dir == NULL)
2136 _ckvmssts(SS$_INSFMEM);
2137 rslt = do_fileify_dirspec(vms_src, vms_dir, 0, NULL);
2138 PerlMem_free(vms_src);
2139
2140
2141 if (rslt != NULL) {
2142 ret = chmod(vms_dir, mode);
2143 } else {
2144 errno = EIO;
2145 }
2146 PerlMem_free(vms_dir);
2147 return ret;
2148 }
2149 else return chmod(file_spec, mode);
2150}
2151
2152
2153
2154
2155FILE *
2156my_tmpfile(void)
2157{
2158 FILE *fp;
2159 char *cp;
2160
2161 if ((fp = tmpfile())) return fp;
2162
2163 cp = PerlMem_malloc(L_tmpnam+24);
2164 if (cp == NULL) _ckvmssts_noperl(SS$_INSFMEM);
2165
2166 if (decc_filename_unix_only == 0)
2167 strcpy(cp,"Sys$Scratch:");
2168 else
2169 strcpy(cp,"/tmp/");
2170 tmpnam(cp+strlen(cp));
2171 strcat(cp,".Perltmp");
2172 fp = fopen(cp,"w+","fop=dlt");
2173 PerlMem_free(cp);
2174 return fp;
2175}
2176
2177
2178
2179#ifndef HOMEGROWN_POSIX_SIGNALS
2180
2181
2182
2183
2184
2185
2186int
2187Perl_my_sigaction (pTHX_ int sig, const struct sigaction* act,
2188 struct sigaction* oact)
2189{
2190 if (sig == SIGKILL || sig == SIGSTOP || sig == SIGCONT) {
2191 SETERRNO(EINVAL, SS$_INVARG);
2192 return -1;
2193 }
2194 return sigaction(sig, act, oact);
2195}
2196
2197#endif
2198
2199#ifdef KILL_BY_SIGPRC
2200#include <errnodef.h>
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234#define _MY_SIG_MAX 28
2235
2236static unsigned int
2237Perl_sig_to_vmscondition_int(int sig)
2238{
2239 static unsigned int sig_code[_MY_SIG_MAX+1] =
2240 {
2241 0,
2242 SS$_HANGUP,
2243 SS$_CONTROLC,
2244 SS$_CONTROLY,
2245 SS$_RADRMOD,
2246 SS$_BREAK,
2247 SS$_OPCCUS,
2248 SS$_COMPAT,
2249#ifdef __VAX
2250 SS$_FLTOVF,
2251#else
2252 SS$_HPARITH,
2253#endif
2254 SS$_ABORT,
2255 SS$_ACCVIO,
2256 SS$_ACCVIO,
2257 SS$_BADPARAM,
2258 SS$_NOMBX,
2259 SS$_ASTFLT,
2260 4,
2261 0,
2262 0,
2263 0,
2264 0,
2265 0,
2266 0,
2267 0,
2268 0,
2269 0,
2270 0,
2271 0,
2272 0,
2273 0
2274 };
2275
2276#if __VMS_VER >= 60200000
2277 static int initted = 0;
2278 if (!initted) {
2279 initted = 1;
2280 sig_code[16] = C$_SIGUSR1;
2281 sig_code[17] = C$_SIGUSR2;
2282#if __CRTL_VER >= 70000000
2283 sig_code[20] = C$_SIGCHLD;
2284#endif
2285#if __CRTL_VER >= 70300000
2286 sig_code[28] = C$_SIGWINCH;
2287#endif
2288 }
2289#endif
2290
2291 if (sig < _SIG_MIN) return 0;
2292 if (sig > _MY_SIG_MAX) return 0;
2293 return sig_code[sig];
2294}
2295
2296unsigned int
2297Perl_sig_to_vmscondition(int sig)
2298{
2299#ifdef SS$_DEBUG
2300 if (vms_debug_on_exception != 0)
2301 lib$signal(SS$_DEBUG);
2302#endif
2303 return Perl_sig_to_vmscondition_int(sig);
2304}
2305
2306
2307int
2308Perl_my_kill(int pid, int sig)
2309{
2310 dTHX;
2311 int iss;
2312 unsigned int code;
2313 int sys$sigprc(unsigned int *pidadr,
2314 struct dsc$descriptor_s *prcname,
2315 unsigned int code);
2316
2317
2318
2319 if (sig == 0) {
2320 const unsigned long int jpicode = JPI$_PID;
2321 pid_t ret_pid;
2322 int status;
2323 status = lib$getjpi(&jpicode, &pid, NULL, &ret_pid, NULL, NULL);
2324 if ($VMS_STATUS_SUCCESS(status))
2325 return 0;
2326 switch (status) {
2327 case SS$_NOSUCHNODE:
2328 case SS$_UNREACHABLE:
2329 case SS$_NONEXPR:
2330 errno = ESRCH;
2331 break;
2332 case SS$_NOPRIV:
2333 errno = EPERM;
2334 break;
2335 default:
2336 errno = EVMSERR;
2337 }
2338 vaxc$errno=status;
2339 return -1;
2340 }
2341
2342 code = Perl_sig_to_vmscondition_int(sig);
2343
2344 if (!code) {
2345 SETERRNO(EINVAL, SS$_BADPARAM);
2346 return -1;
2347 }
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357 if (pid <= 0) {
2358 SETERRNO(ENOTSUP, SS$_UNSUPPORTED);
2359 return -1;
2360 }
2361
2362 iss = sys$sigprc((unsigned int *)&pid,0,code);
2363 if (iss&1) return 0;
2364
2365 switch (iss) {
2366 case SS$_NOPRIV:
2367 set_errno(EPERM); break;
2368 case SS$_NONEXPR:
2369 case SS$_NOSUCHNODE:
2370 case SS$_UNREACHABLE:
2371 set_errno(ESRCH); break;
2372 case SS$_INSFMEM:
2373 set_errno(ENOMEM); break;
2374 default:
2375 _ckvmssts(iss);
2376 set_errno(EVMSERR);
2377 }
2378 set_vaxc_errno(iss);
2379
2380 return -1;
2381}
2382#endif
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398#ifndef C_FACILITY_NO
2399#define C_FACILITY_NO 0x350000
2400#endif
2401#ifndef DCL_IVVERB
2402#define DCL_IVVERB 0x38090
2403#endif
2404
2405int Perl_vms_status_to_unix(int vms_status, int child_flag)
2406{
2407int facility;
2408int fac_sp;
2409int msg_no;
2410int msg_status;
2411int unix_status;
2412
2413
2414 if (vms_status & STS$M_SUCCESS)
2415 unix_status = 0;
2416 else
2417 unix_status = EVMSERR;
2418
2419 msg_status = vms_status & ~STS$M_CONTROL;
2420
2421 facility = vms_status & STS$M_FAC_NO;
2422 fac_sp = vms_status & STS$M_FAC_SP;
2423 msg_no = vms_status & (STS$M_MSG_NO | STS$M_SEVERITY);
2424
2425 if (((facility == 0) || (fac_sp == 0)) && (child_flag == 0)) {
2426 switch(msg_no) {
2427 case SS$_NORMAL:
2428 unix_status = 0;
2429 break;
2430 case SS$_ACCVIO:
2431 unix_status = EFAULT;
2432 break;
2433 case SS$_DEVOFFLINE:
2434 unix_status = EBUSY;
2435 break;
2436 case SS$_CLEARED:
2437 unix_status = ENOTCONN;
2438 break;
2439 case SS$_IVCHAN:
2440 case SS$_IVLOGNAM:
2441 case SS$_BADPARAM:
2442 case SS$_IVLOGTAB:
2443 case SS$_NOLOGNAM:
2444 case SS$_NOLOGTAB:
2445 case SS$_INVFILFOROP:
2446 case SS$_INVARG:
2447 case SS$_NOSUCHID:
2448 case SS$_IVIDENT:
2449 unix_status = EINVAL;
2450 break;
2451 case SS$_UNSUPPORTED:
2452 unix_status = ENOTSUP;
2453 break;
2454 case SS$_FILACCERR:
2455 case SS$_NOGRPPRV:
2456 case SS$_NOSYSPRV:
2457 unix_status = EACCES;
2458 break;
2459 case SS$_DEVICEFULL:
2460 unix_status = ENOSPC;
2461 break;
2462 case SS$_NOSUCHDEV:
2463 unix_status = ENODEV;
2464 break;
2465 case SS$_NOSUCHFILE:
2466 case SS$_NOSUCHOBJECT:
2467 unix_status = ENOENT;
2468 break;
2469 case SS$_ABORT:
2470 case ((SS$_ABORT & STS$M_COND_ID) | STS$K_ERROR):
2471 case ((SS$_ABORT & STS$M_COND_ID) | STS$K_WARNING):
2472 unix_status = EINTR;
2473 break;
2474 case SS$_BUFFEROVF:
2475 unix_status = E2BIG;
2476 break;
2477 case SS$_INSFMEM:
2478 unix_status = ENOMEM;
2479 break;
2480 case SS$_NOPRIV:
2481 unix_status = EPERM;
2482 break;
2483 case SS$_NOSUCHNODE:
2484 case SS$_UNREACHABLE:
2485 unix_status = ESRCH;
2486 break;
2487 case SS$_NONEXPR:
2488 unix_status = ECHILD;
2489 break;
2490 default:
2491 if ((facility == 0) && (msg_no < 8)) {
2492
2493
2494
2495 unix_status = msg_no;
2496 break;
2497 }
2498 }
2499 }
2500 else {
2501
2502 if ((facility == C_FACILITY_NO) && ((msg_no & 0xA000) == 0xA000)) {
2503 unix_status = (msg_no & 0x07F8) >> 3;
2504 }
2505 else {
2506
2507
2508
2509 if (child_flag != 0) {
2510
2511
2512
2513 if (msg_no & STS$K_SUCCESS)
2514 return 0;
2515
2516
2517
2518 if ((msg_no & (STS$K_ERROR | STS$K_SEVERE)) == 0)
2519 return 1;
2520
2521
2522
2523 return (msg_no & STS$M_SEVERITY);
2524 }
2525
2526
2527
2528 switch(msg_status) {
2529
2530 case RMS$_FNF:
2531 case RMS$_DNF:
2532 unix_status = ENOENT;
2533 break;
2534 case RMS$_RNF:
2535 unix_status = ESRCH;
2536 break;
2537 case RMS$_DIR:
2538 unix_status = ENOTDIR;
2539 break;
2540 case RMS$_DEV:
2541 unix_status = ENODEV;
2542 break;
2543 case RMS$_IFI:
2544 case RMS$_FAC:
2545 case RMS$_ISI:
2546 unix_status = EBADF;
2547 break;
2548 case RMS$_FEX:
2549 unix_status = EEXIST;
2550 break;
2551 case RMS$_SYN:
2552 case RMS$_FNM:
2553 case LIB$_INVSTRDES:
2554 case LIB$_INVARG:
2555 case LIB$_NOSUCHSYM:
2556 case LIB$_INVSYMNAM:
2557 case DCL_IVVERB:
2558 unix_status = EINVAL;
2559 break;
2560 case CLI$_BUFOVF:
2561 case RMS$_RTB:
2562 case CLI$_TKNOVF:
2563 case CLI$_RSLOVF:
2564 unix_status = E2BIG;
2565 break;
2566 case RMS$_PRV:
2567 case RMS$_ACC:
2568 case RMS$_WLK:
2569 unix_status = EACCES;
2570 break;
2571
2572 }
2573 }
2574 }
2575
2576 return unix_status;
2577}
2578
2579
2580
2581
2582
2583
2584int Perl_unix_status_to_vms(int unix_status)
2585{
2586int test_unix_status;
2587
2588
2589
2590 if (unix_status == EVMSERR)
2591 return vaxc$errno;
2592
2593
2594
2595 test_unix_status = Perl_vms_status_to_unix(vaxc$errno, 0);
2596 if (test_unix_status == unix_status)
2597 return vaxc$errno;
2598
2599
2600
2601 if (unix_status > EVMSERR)
2602 return unix_status;
2603
2604
2605
2606 if (unix_status > __ERRNO_MAX)
2607 return SS$_ABORT;
2608
2609
2610
2611
2612 switch(unix_status) {
2613 case 0: return SS$_NORMAL;
2614 case EPERM: return SS$_NOPRIV;
2615 case ENOENT: return SS$_NOSUCHOBJECT;
2616 case ESRCH: return SS$_UNREACHABLE;
2617 case EINTR: return SS$_ABORT;
2618
2619
2620 case E2BIG: return SS$_BUFFEROVF;
2621
2622 case EBADF: return RMS$_IFI;
2623 case ECHILD: return SS$_NONEXPR;
2624
2625 case ENOMEM: return SS$_INSFMEM;
2626 case EACCES: return SS$_FILACCERR;
2627 case EFAULT: return SS$_ACCVIO;
2628
2629 case EBUSY: return SS$_DEVOFFLINE;
2630 case EEXIST: return RMS$_FEX;
2631
2632 case ENODEV: return SS$_NOSUCHDEV;
2633 case ENOTDIR: return RMS$_DIR;
2634
2635 case EINVAL: return SS$_INVARG;
2636
2637
2638
2639
2640
2641 case ENOSPC: return SS$_DEVICEFULL;
2642 case ESPIPE: return LIB$_INVARG;
2643
2644
2645
2646
2647 case ERANGE: return LIB$_INVARG;
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670 case ENOTCONN: return SS$_CLEARED;
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694 case ENOTSUP:
2695 return SS$_UNSUPPORTED;
2696
2697
2698
2699
2700
2701
2702 default:
2703 return SS$_ABORT;
2704 }
2705
2706 return SS$_ABORT;
2707}
2708
2709
2710
2711#define PERL_BUFSIZ 512
2712
2713
2714static void
2715create_mbx(pTHX_ unsigned short int *chan, struct dsc$descriptor_s *namdsc)
2716{
2717 unsigned long int mbxbufsiz;
2718 static unsigned long int syssize = 0;
2719 unsigned long int dviitm = DVI$_DEVNAM;
2720 char csize[LNM$C_NAMLENGTH+1];
2721 int sts;
2722
2723 if (!syssize) {
2724 unsigned long syiitm = SYI$_MAXBUF;
2725
2726
2727
2728
2729
2730
2731
2732
2733 _ckvmssts(lib$getsyi(&syiitm, &syssize, 0, 0, 0, 0));
2734 }
2735
2736 if (vmstrnenv("PERL_MBX_SIZE", csize, 0, fildev, 0)) {
2737 mbxbufsiz = atoi(csize);
2738 } else {
2739 mbxbufsiz = PERL_BUFSIZ;
2740 }
2741 if (mbxbufsiz < 128) mbxbufsiz = 128;
2742 if (mbxbufsiz > syssize) mbxbufsiz = syssize;
2743
2744 _ckvmssts(sts = sys$crembx(0,chan,mbxbufsiz,mbxbufsiz,0,0,0));
2745
2746 _ckvmssts(sts = lib$getdvi(&dviitm, chan, NULL, NULL, namdsc, &namdsc->dsc$w_length));
2747 namdsc->dsc$a_pointer[namdsc->dsc$w_length] = '\0';
2748
2749}
2750
2751
2752
2753
2754typedef struct _iosb IOSB;
2755typedef struct _iosb* pIOSB;
2756typedef struct _pipe Pipe;
2757typedef struct _pipe* pPipe;
2758typedef struct pipe_details Info;
2759typedef struct pipe_details* pInfo;
2760typedef struct _srqp RQE;
2761typedef struct _srqp* pRQE;
2762typedef struct _tochildbuf CBuf;
2763typedef struct _tochildbuf* pCBuf;
2764
2765struct _iosb {
2766 unsigned short status;
2767 unsigned short count;
2768 unsigned long dvispec;
2769};
2770
2771#pragma member_alignment save
2772#pragma nomember_alignment quadword
2773struct _srqp {
2774 unsigned long qptr[2];
2775};
2776#pragma member_alignment restore
2777static RQE RQE_ZERO = {0,0};
2778
2779struct _tochildbuf {
2780 RQE q;
2781 int eof;
2782 unsigned short size;
2783 char *buf;
2784};
2785
2786struct _pipe {
2787 RQE free;
2788 RQE wait;
2789 int fd_out;
2790 unsigned short chan_in;
2791 unsigned short chan_out;
2792 char *buf;
2793 unsigned int bufsize;
2794 IOSB iosb;
2795 IOSB iosb2;
2796 int *pipe_done;
2797 int retry;
2798 int type;
2799 int shut_on_empty;
2800 int need_wake;
2801 pPipe *home;
2802 pInfo info;
2803 pCBuf curr;
2804 pCBuf curr2;
2805#if defined(PERL_IMPLICIT_CONTEXT)
2806 void *thx;
2807
2808#endif
2809};
2810
2811
2812struct pipe_details
2813{
2814 pInfo next;
2815 PerlIO *fp;
2816 int useFILE;
2817 int pid;
2818 int mode;
2819 int done;
2820 int waiting;
2821 int closing;
2822 unsigned long completion;
2823 pPipe in;
2824 pPipe out;
2825 pPipe err;
2826 int in_done;
2827 int out_done;
2828 int err_done;
2829 unsigned short xchan;
2830 unsigned short xchan_valid;
2831};
2832
2833struct exit_control_block
2834{
2835 struct exit_control_block *flink;
2836 unsigned long int (*exit_routine)();
2837 unsigned long int arg_count;
2838 unsigned long int *status_address;
2839 unsigned long int exit_status;
2840};
2841
2842typedef struct _closed_pipes Xpipe;
2843typedef struct _closed_pipes* pXpipe;
2844
2845struct _closed_pipes {
2846 int pid;
2847 unsigned long completion;
2848};
2849#define NKEEPCLOSED 50
2850static Xpipe closed_list[NKEEPCLOSED];
2851static int closed_index = 0;
2852static int closed_num = 0;
2853
2854#define RETRY_DELAY "0 ::0.20"
2855#define MAX_RETRY 50
2856
2857static int pipe_ef = 0;
2858static unsigned long mypid;
2859static unsigned long delaytime[2];
2860
2861static pInfo open_pipes = NULL;
2862static $DESCRIPTOR(nl_desc, "NL:");
2863
2864#define PIPE_COMPLETION_WAIT 30
2865
2866
2867
2868static unsigned long int
2869pipe_exit_routine(pTHX)
2870{
2871 pInfo info;
2872 unsigned long int retsts = SS$_NORMAL, abort = SS$_TIMEOUT;
2873 int sts, did_stuff, need_eof, j;
2874
2875
2876
2877
2878
2879
2880 info = open_pipes;
2881 while (info) {
2882 if (info->fp) {
2883 if (!info->useFILE
2884#if defined(USE_ITHREADS)
2885 && my_perl
2886#endif
2887 && PL_perlio_fd_refcnt)
2888 PerlIO_flush(info->fp);
2889 else
2890 fflush((FILE *)info->fp);
2891 }
2892 info = info->next;
2893 }
2894
2895
2896
2897
2898
2899 did_stuff = 0;
2900 info = open_pipes;
2901
2902 while (info) {
2903 int need_eof;
2904 _ckvmssts_noperl(sys$setast(0));
2905 if (info->in && !info->in->shut_on_empty) {
2906 _ckvmssts_noperl(sys$qio(0,info->in->chan_in,IO$_WRITEOF,0,0,0,
2907 0, 0, 0, 0, 0, 0));
2908 info->waiting = 1;
2909 did_stuff = 1;
2910 }
2911 _ckvmssts_noperl(sys$setast(1));
2912 info = info->next;
2913 }
2914
2915
2916
2917 for (j = 0; did_stuff && j < PIPE_COMPLETION_WAIT; j++) {
2918 int nwait = 0;
2919
2920 info = open_pipes;
2921 while (info) {
2922 _ckvmssts_noperl(sys$setast(0));
2923 if (info->waiting && info->done)
2924 info->waiting = 0;
2925 nwait += info->waiting;
2926 _ckvmssts_noperl(sys$setast(1));
2927 info = info->next;
2928 }
2929 if (!nwait) break;
2930 sleep(1);
2931 }
2932
2933 did_stuff = 0;
2934 info = open_pipes;
2935 while (info) {
2936 _ckvmssts_noperl(sys$setast(0));
2937 if (!info->done) {
2938 sts = sys$forcex(&info->pid,0,&abort);
2939 if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts_noperl(sts);
2940 did_stuff = 1;
2941 }
2942 _ckvmssts_noperl(sys$setast(1));
2943 info = info->next;
2944 }
2945
2946
2947
2948 for (j = 0; did_stuff && j < PIPE_COMPLETION_WAIT; j++) {
2949 int nwait = 0;
2950
2951 info = open_pipes;
2952 while (info) {
2953 _ckvmssts_noperl(sys$setast(0));
2954 if (info->waiting && info->done)
2955 info->waiting = 0;
2956 nwait += info->waiting;
2957 _ckvmssts_noperl(sys$setast(1));
2958 info = info->next;
2959 }
2960 if (!nwait) break;
2961 sleep(1);
2962 }
2963
2964 info = open_pipes;
2965 while (info) {
2966 _ckvmssts_noperl(sys$setast(0));
2967 if (!info->done) {
2968 sts = sys$delprc(&info->pid,0);
2969 if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts_noperl(sts);
2970 info->done = 1;
2971 }
2972 _ckvmssts_noperl(sys$setast(1));
2973 info = info->next;
2974 }
2975
2976 while(open_pipes) {
2977 if ((sts = my_pclose(open_pipes->fp)) == -1) retsts = vaxc$errno;
2978 else if (!(sts & 1)) retsts = sts;
2979 }
2980 return retsts;
2981}
2982
2983static struct exit_control_block pipe_exitblock =
2984 {(struct exit_control_block *) 0,
2985 pipe_exit_routine, 0, &pipe_exitblock.exit_status, 0};
2986
2987static void pipe_mbxtofd_ast(pPipe p);
2988static void pipe_tochild1_ast(pPipe p);
2989static void pipe_tochild2_ast(pPipe p);
2990
2991static void
2992popen_completion_ast(pInfo info)
2993{
2994 pInfo i = open_pipes;
2995 int iss;
2996 int sts;
2997 pXpipe x;
2998
2999 info->completion &= 0x0FFFFFFF;
3000 closed_list[closed_index].pid = info->pid;
3001 closed_list[closed_index].completion = info->completion;
3002 closed_index++;
3003 if (closed_index == NKEEPCLOSED)
3004 closed_index = 0;
3005 closed_num++;
3006
3007 while (i) {
3008 if (i == info) break;
3009 i = i->next;
3010 }
3011 if (!i) return;
3012
3013 info->done = TRUE;
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031 if (info->in && !info->in_done) {
3032 if (info->in->shut_on_empty && info->in->need_wake) {
3033 info->in->need_wake = FALSE;
3034 _ckvmssts_noperl(sys$dclast(pipe_tochild2_ast,info->in,0));
3035 } else {
3036 _ckvmssts_noperl(sys$cancel(info->in->chan_out));
3037 }
3038 }
3039
3040 if (info->out && !info->out_done) {
3041 info->out->shut_on_empty = TRUE;
3042 iss = sys$qio(0,info->out->chan_in,IO$_WRITEOF|IO$M_NORSWAIT, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3043 if (iss == SS$_MBFULL) iss = SS$_NORMAL;
3044 _ckvmssts_noperl(iss);
3045 }
3046
3047 if (info->err && !info->err_done) {
3048 info->err->shut_on_empty = TRUE;
3049 iss = sys$qio(0,info->err->chan_in,IO$_WRITEOF|IO$M_NORSWAIT, 0, 0, 0, 0, 0, 0, 0, 0, 0);
3050 if (iss == SS$_MBFULL) iss = SS$_NORMAL;
3051 _ckvmssts_noperl(iss);
3052 }
3053 _ckvmssts_noperl(sys$setef(pipe_ef));
3054
3055}
3056
3057static unsigned long int setup_cmddsc(pTHX_ const char *cmd, int check_img, int *suggest_quote, struct dsc$descriptor_s **pvmscmd);
3058static void vms_execfree(struct dsc$descriptor_s *vmscmd);
3059
3060
3061
3062
3063
3064
3065
3066static unsigned short
3067popen_translate(pTHX_ char *logical, char *result)
3068{
3069 int iss;
3070 $DESCRIPTOR(d_table,"LNM$PROCESS_TABLE");
3071 $DESCRIPTOR(d_log,"");
3072 struct _il3 {
3073 unsigned short length;
3074 unsigned short code;
3075 char * buffer_addr;
3076 unsigned short *retlenaddr;
3077 } itmlst[2];
3078 unsigned short l, ifi;
3079
3080 d_log.dsc$a_pointer = logical;
3081 d_log.dsc$w_length = strlen(logical);
3082
3083 itmlst[0].code = LNM$_STRING;
3084 itmlst[0].length = 255;
3085 itmlst[0].buffer_addr = result;
3086 itmlst[0].retlenaddr = &l;
3087
3088 itmlst[1].code = 0;
3089 itmlst[1].length = 0;
3090 itmlst[1].buffer_addr = 0;
3091 itmlst[1].retlenaddr = 0;
3092
3093 iss = sys$trnlnm(0, &d_table, &d_log, 0, itmlst);
3094 if (iss == SS$_NOLOGNAM) {
3095 iss = SS$_NORMAL;
3096 l = 0;
3097 }
3098 if (!(iss&1)) lib$signal(iss);
3099 result[l] = '\0';
3100
3101
3102
3103
3104 ifi = 0;
3105 if (result[0] == 0x1b && result[1] == 0x00) {
3106 memmove(&ifi,result+2,2);
3107 strcpy(result,result+4);
3108 }
3109 return ifi;
3110}
3111
3112static void pipe_infromchild_ast(pPipe p);
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123#define INITIAL_TOCHILDQUEUE 2
3124
3125static pPipe
3126pipe_tochild_setup(pTHX_ char *rmbx, char *wmbx)
3127{
3128 pPipe p;
3129 pCBuf b;
3130 char mbx1[64], mbx2[64];
3131 struct dsc$descriptor_s d_mbx1 = {sizeof mbx1, DSC$K_DTYPE_T,
3132 DSC$K_CLASS_S, mbx1},
3133 d_mbx2 = {sizeof mbx2, DSC$K_DTYPE_T,
3134 DSC$K_CLASS_S, mbx2};
3135 unsigned int dviitm = DVI$_DEVBUFSIZ;
3136 int j, n;
3137
3138 n = sizeof(Pipe);
3139 _ckvmssts(lib$get_vm(&n, &p));
3140
3141 create_mbx(aTHX_ &p->chan_in , &d_mbx1);
3142 create_mbx(aTHX_ &p->chan_out, &d_mbx2);
3143 _ckvmssts(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
3144
3145 p->buf = 0;
3146 p->shut_on_empty = FALSE;
3147 p->need_wake = FALSE;
3148 p->type = 0;
3149 p->retry = 0;
3150 p->iosb.status = SS$_NORMAL;
3151 p->iosb2.status = SS$_NORMAL;
3152 p->free = RQE_ZERO;
3153 p->wait = RQE_ZERO;
3154 p->curr = 0;
3155 p->curr2 = 0;
3156 p->info = 0;
3157#ifdef PERL_IMPLICIT_CONTEXT
3158 p->thx = aTHX;
3159#endif
3160
3161 n = sizeof(CBuf) + p->bufsize;
3162
3163 for (j = 0; j < INITIAL_TOCHILDQUEUE; j++) {
3164 _ckvmssts(lib$get_vm(&n, &b));
3165 b->buf = (char *) b + sizeof(CBuf);
3166 _ckvmssts(lib$insqhi(b, &p->free));
3167 }
3168
3169 pipe_tochild2_ast(p);
3170 pipe_tochild1_ast(p);
3171 strcpy(wmbx, mbx1);
3172 strcpy(rmbx, mbx2);
3173 return p;
3174}
3175
3176
3177
3178static void
3179pipe_tochild1_ast(pPipe p)
3180{
3181 pCBuf b = p->curr;
3182 int iss = p->iosb.status;
3183 int eof = (iss == SS$_ENDOFFILE);
3184 int sts;
3185#ifdef PERL_IMPLICIT_CONTEXT
3186 pTHX = p->thx;
3187#endif
3188
3189 if (p->retry) {
3190 if (eof) {
3191 p->shut_on_empty = TRUE;
3192 b->eof = TRUE;
3193 _ckvmssts(sys$dassgn(p->chan_in));
3194 } else {
3195 _ckvmssts(iss);
3196 }
3197
3198 b->eof = eof;
3199 b->size = p->iosb.count;
3200 _ckvmssts(sts = lib$insqhi(b, &p->wait));
3201 if (p->need_wake) {
3202 p->need_wake = FALSE;
3203 _ckvmssts(sys$dclast(pipe_tochild2_ast,p,0));
3204 }
3205 } else {
3206 p->retry = 1;
3207 }
3208
3209 if (eof) {
3210 int n = sizeof(CBuf) + p->bufsize;
3211 while (1) {
3212 iss = lib$remqti(&p->free, &b);
3213 if (iss == LIB$_QUEWASEMP) return;
3214 _ckvmssts(iss);
3215 _ckvmssts(lib$free_vm(&n, &b));
3216 }
3217 }
3218
3219 iss = lib$remqti(&p->free, &b);
3220 if (iss == LIB$_QUEWASEMP) {
3221 int n = sizeof(CBuf) + p->bufsize;
3222 _ckvmssts(lib$get_vm(&n, &b));
3223 b->buf = (char *) b + sizeof(CBuf);
3224 } else {
3225 _ckvmssts(iss);
3226 }
3227
3228 p->curr = b;
3229 iss = sys$qio(0,p->chan_in,
3230 IO$_READVBLK|(p->shut_on_empty ? IO$M_NOWAIT : 0),
3231 &p->iosb,
3232 pipe_tochild1_ast, p, b->buf, p->bufsize, 0, 0, 0, 0);
3233 if (iss == SS$_ENDOFFILE && p->shut_on_empty) iss = SS$_NORMAL;
3234 _ckvmssts(iss);
3235}
3236
3237
3238
3239
3240
3241static void
3242pipe_tochild2_ast(pPipe p)
3243{
3244 pCBuf b = p->curr2;
3245 int iss = p->iosb2.status;
3246 int n = sizeof(CBuf) + p->bufsize;
3247 int done = (p->info && p->info->done) ||
3248 iss == SS$_CANCEL || iss == SS$_ABORT;
3249#if defined(PERL_IMPLICIT_CONTEXT)
3250 pTHX = p->thx;
3251#endif
3252
3253 do {
3254 if (p->type) {
3255 if (p->shut_on_empty) {
3256 _ckvmssts(lib$free_vm(&n, &b));
3257 } else {
3258 _ckvmssts(lib$insqhi(b, &p->free));
3259 }
3260 p->type = 0;
3261 }
3262
3263 iss = lib$remqti(&p->wait, &b);
3264 if (iss == LIB$_QUEWASEMP) {
3265 if (p->shut_on_empty) {
3266 if (done) {
3267 _ckvmssts(sys$dassgn(p->chan_out));
3268 *p->pipe_done = TRUE;
3269 _ckvmssts(sys$setef(pipe_ef));
3270 } else {
3271 _ckvmssts(sys$qio(0,p->chan_out,IO$_WRITEOF,
3272 &p->iosb2, pipe_tochild2_ast, p, 0, 0, 0, 0, 0, 0));
3273 }
3274 return;
3275 }
3276 p->need_wake = TRUE;
3277 return;
3278 }
3279 _ckvmssts(iss);
3280 p->type = 1;
3281 } while (done);
3282
3283
3284 p->curr2 = b;
3285 if (b->eof) {
3286 _ckvmssts(sys$qio(0,p->chan_out,IO$_WRITEOF,
3287 &p->iosb2, pipe_tochild2_ast, p, 0, 0, 0, 0, 0, 0));
3288 } else {
3289 _ckvmssts(sys$qio(0,p->chan_out,IO$_WRITEVBLK,
3290 &p->iosb2, pipe_tochild2_ast, p, b->buf, b->size, 0, 0, 0, 0));
3291 }
3292
3293 return;
3294
3295}
3296
3297
3298static pPipe
3299pipe_infromchild_setup(pTHX_ char *rmbx, char *wmbx)
3300{
3301 pPipe p;
3302 char mbx1[64], mbx2[64];
3303 struct dsc$descriptor_s d_mbx1 = {sizeof mbx1, DSC$K_DTYPE_T,
3304 DSC$K_CLASS_S, mbx1},
3305 d_mbx2 = {sizeof mbx2, DSC$K_DTYPE_T,
3306 DSC$K_CLASS_S, mbx2};
3307 unsigned int dviitm = DVI$_DEVBUFSIZ;
3308
3309 int n = sizeof(Pipe);
3310 _ckvmssts(lib$get_vm(&n, &p));
3311 create_mbx(aTHX_ &p->chan_in , &d_mbx1);
3312 create_mbx(aTHX_ &p->chan_out, &d_mbx2);
3313
3314 _ckvmssts(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
3315 n = p->bufsize * sizeof(char);
3316 _ckvmssts(lib$get_vm(&n, &p->buf));
3317 p->shut_on_empty = FALSE;
3318 p->info = 0;
3319 p->type = 0;
3320 p->iosb.status = SS$_NORMAL;
3321#if defined(PERL_IMPLICIT_CONTEXT)
3322 p->thx = aTHX;
3323#endif
3324 pipe_infromchild_ast(p);
3325
3326 strcpy(wmbx, mbx1);
3327 strcpy(rmbx, mbx2);
3328 return p;
3329}
3330
3331static void
3332pipe_infromchild_ast(pPipe p)
3333{
3334 int iss = p->iosb.status;
3335 int eof = (iss == SS$_ENDOFFILE);
3336 int myeof = (eof && (p->iosb.dvispec == mypid || p->iosb.dvispec == 0));
3337 int kideof = (eof && (p->iosb.dvispec == p->info->pid));
3338#if defined(PERL_IMPLICIT_CONTEXT)
3339 pTHX = p->thx;
3340#endif
3341
3342 if (p->info && p->info->closing && p->chan_out) {
3343 _ckvmssts(sys$dassgn(p->chan_out));
3344 p->chan_out = 0;
3345 }
3346
3347
3348
3349
3350
3351
3352
3353
3354 if (p->type == 1) {
3355 p->type = 0;
3356 if (myeof && p->chan_in) {
3357 _ckvmssts(sys$dassgn(p->chan_in));
3358 p->chan_in = 0;
3359 }
3360
3361 if (p->chan_out) {
3362 if (myeof || kideof) {
3363 _ckvmssts(sys$qio(0,p->chan_out,IO$_WRITEOF, &p->iosb,
3364 pipe_infromchild_ast, p,
3365 0, 0, 0, 0, 0, 0));
3366 return;
3367 } else if (eof) {
3368
3369 } else {
3370 _ckvmssts(sys$qio(0,p->chan_out,IO$_WRITEVBLK,&p->iosb,
3371 pipe_infromchild_ast,p,
3372 p->buf, p->iosb.count, 0, 0, 0, 0));
3373 return;
3374 }
3375 }
3376 }
3377
3378
3379
3380 if (!p->chan_in && !p->chan_out) {
3381 *p->pipe_done = TRUE;
3382 _ckvmssts(sys$setef(pipe_ef));
3383 return;
3384 }
3385
3386
3387
3388
3389
3390
3391
3392
3393 if (p->type == 0) {
3394 p->type = 1;
3395 if (p->chan_in) {
3396 iss = sys$qio(0,p->chan_in,IO$_READVBLK|(p->shut_on_empty ? IO$M_NOW : 0),&p->iosb,
3397 pipe_infromchild_ast,p,
3398 p->buf, p->bufsize, 0, 0, 0, 0);
3399 if (p->shut_on_empty && iss == SS$_ENDOFFILE) iss = SS$_NORMAL;
3400 _ckvmssts(iss);
3401 } else {
3402 p->iosb.status = SS$_ENDOFFILE;
3403 p->iosb.dvispec = 0;
3404 _ckvmssts(sys$qio(0,p->chan_out,IO$_SETMODE|IO$M_READATTN,
3405 0, 0, 0,
3406 pipe_infromchild_ast, p, 0, 0, 0, 0));
3407 }
3408 }
3409}
3410
3411static pPipe
3412pipe_mbxtofd_setup(pTHX_ int fd, char *out)
3413{
3414 pPipe p;
3415 char mbx[64];
3416 unsigned long dviitm = DVI$_DEVBUFSIZ;
3417 struct stat s;
3418 struct dsc$descriptor_s d_mbx = {sizeof mbx, DSC$K_DTYPE_T,
3419 DSC$K_CLASS_S, mbx};
3420 int n = sizeof(Pipe);
3421
3422
3423 if (fd && fstat(fd,&s) == 0) {
3424 unsigned long dviitm = DVI$_DEVCHAR, devchar;
3425 char device[65];
3426 unsigned short dev_len;
3427 struct dsc$descriptor_s d_dev;
3428 char * cptr;
3429 struct item_list_3 items[3];
3430 int status;
3431 unsigned short dvi_iosb[4];
3432
3433 cptr = getname(fd, out, 1);
3434 if (cptr == NULL) _ckvmssts(SS$_NOSUCHDEV);
3435 d_dev.dsc$a_pointer = out;
3436 d_dev.dsc$w_length = strlen(out);
3437 d_dev.dsc$b_dtype = DSC$K_DTYPE_T;
3438 d_dev.dsc$b_class = DSC$K_CLASS_S;
3439
3440 items[0].len = 4;
3441 items[0].code = DVI$_DEVCHAR;
3442 items[0].bufadr = &devchar;
3443 items[0].retadr = NULL;
3444 items[1].len = 64;
3445 items[1].code = DVI$_FULLDEVNAM;
3446 items[1].bufadr = device;
3447 items[1].retadr = &dev_len;
3448 items[2].len = 0;
3449 items[2].code = 0;
3450
3451 status = sys$getdviw
3452 (NO_EFN, 0, &d_dev, items, dvi_iosb, NULL, NULL, NULL);
3453 _ckvmssts(status);
3454 if ($VMS_STATUS_SUCCESS(dvi_iosb[0])) {
3455 device[dev_len] = 0;
3456
3457 if (!(devchar & DEV$M_DIR)) {
3458 strcpy(out, device);
3459 return 0;
3460 }
3461 }
3462 }
3463
3464 _ckvmssts(lib$get_vm(&n, &p));
3465 p->fd_out = dup(fd);
3466 create_mbx(aTHX_ &p->chan_in, &d_mbx);
3467 _ckvmssts(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
3468 n = (p->bufsize+1) * sizeof(char);
3469 _ckvmssts(lib$get_vm(&n, &p->buf));
3470 p->shut_on_empty = FALSE;
3471 p->retry = 0;
3472 p->info = 0;
3473 strcpy(out, mbx);
3474
3475 _ckvmssts(sys$qio(0, p->chan_in, IO$_READVBLK, &p->iosb,
3476 pipe_mbxtofd_ast, p,
3477 p->buf, p->bufsize, 0, 0, 0, 0));
3478
3479 return p;
3480}
3481
3482static void
3483pipe_mbxtofd_ast(pPipe p)
3484{
3485 int iss = p->iosb.status;
3486 int done = p->info->done;
3487 int iss2;
3488 int eof = (iss == SS$_ENDOFFILE);
3489 int myeof = eof && ((p->iosb.dvispec == mypid)||(p->iosb.dvispec == 0));
3490 int err = !(iss&1) && !eof;
3491#if defined(PERL_IMPLICIT_CONTEXT)
3492 pTHX = p->thx;
3493#endif
3494
3495 if (done && myeof) {
3496 close(p->fd_out);
3497 sys$dassgn(p->chan_in);
3498 *p->pipe_done = TRUE;
3499 _ckvmssts(sys$setef(pipe_ef));
3500 return;
3501 }
3502
3503 if (!err && !eof) {
3504 p->buf[p->iosb.count] = '\n';
3505 iss2 = write(p->fd_out, p->buf, p->iosb.count+1);
3506 if (iss2 < 0) {
3507 p->retry++;
3508 if (p->retry < MAX_RETRY) {
3509 _ckvmssts(sys$setimr(0,delaytime,pipe_mbxtofd_ast,p));
3510 return;
3511 }
3512 }
3513 p->retry = 0;
3514 } else if (err) {
3515 _ckvmssts(iss);
3516 }
3517
3518
3519 iss = sys$qio(0, p->chan_in, IO$_READVBLK|(p->shut_on_empty ? IO$M_NOW : 0), &p->iosb,
3520 pipe_mbxtofd_ast, p,
3521 p->buf, p->bufsize, 0, 0, 0, 0);
3522 if (p->shut_on_empty && (iss == SS$_ENDOFFILE)) iss = SS$_NORMAL;
3523 _ckvmssts(iss);
3524}
3525
3526
3527typedef struct _pipeloc PLOC;
3528typedef struct _pipeloc* pPLOC;
3529
3530struct _pipeloc {
3531 pPLOC next;
3532 char dir[NAM$C_MAXRSS+1];
3533};
3534static pPLOC head_PLOC = 0;
3535
3536void
3537free_pipelocs(pTHX_ void *head)
3538{
3539 pPLOC p, pnext;
3540 pPLOC *pHead = (pPLOC *)head;
3541
3542 p = *pHead;
3543 while (p) {
3544 pnext = p->next;
3545 PerlMem_free(p);
3546 p = pnext;
3547 }
3548 *pHead = 0;
3549}
3550
3551static void
3552store_pipelocs(pTHX)
3553{
3554 int i;
3555 pPLOC p;
3556 AV *av = 0;
3557 SV *dirsv;
3558 GV *gv;
3559 char *dir, *x;
3560 char *unixdir;
3561 char temp[NAM$C_MAXRSS+1];
3562 STRLEN n_a;
3563
3564 if (head_PLOC)
3565 free_pipelocs(aTHX_ &head_PLOC);
3566
3567
3568
3569 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3570 if (p == NULL) _ckvmssts(SS$_INSFMEM);
3571 p->next = head_PLOC;
3572 head_PLOC = p;
3573 strcpy(p->dir,"./");
3574
3575
3576
3577 unixdir = PerlMem_malloc(VMS_MAXRSS);
3578 if (unixdir == NULL) _ckvmssts(SS$_INSFMEM);
3579
3580#ifdef PERL_IMPLICIT_CONTEXT
3581 if (aTHX && PL_origargv && PL_origargv[0]) {
3582#else
3583 if (PL_origargv && PL_origargv[0]) {
3584#endif
3585 strcpy(temp, PL_origargv[0]);
3586 x = strrchr(temp,']');
3587 if (x == NULL) {
3588 x = strrchr(temp,'>');
3589 if (x == NULL) {
3590
3591 x = strrchr(temp,'/');
3592 }
3593 }
3594 if (x)
3595 x[1] = '\0';
3596 else {
3597
3598 temp[0] = '.';
3599 temp[1] = '\0';
3600 }
3601
3602 if ((tounixpath_utf8(temp, unixdir, NULL)) != Nullch) {
3603 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3604 if (p == NULL) _ckvmssts(SS$_INSFMEM);
3605 p->next = head_PLOC;
3606 head_PLOC = p;
3607 strncpy(p->dir,unixdir,sizeof(p->dir)-1);
3608 p->dir[NAM$C_MAXRSS] = '\0';
3609 }
3610 }
3611
3612
3613
3614#ifdef PERL_IMPLICIT_CONTEXT
3615 if (aTHX)
3616#endif
3617 if (PL_incgv) av = GvAVn(PL_incgv);
3618
3619 for (i = 0; av && i <= AvFILL(av); i++) {
3620 dirsv = *av_fetch(av,i,TRUE);
3621
3622 if (SvROK(dirsv)) continue;
3623 dir = SvPVx(dirsv,n_a);
3624 if (strcmp(dir,".") == 0) continue;
3625 if ((tounixpath_utf8(dir, unixdir, NULL)) == Nullch)
3626 continue;
3627
3628 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3629 p->next = head_PLOC;
3630 head_PLOC = p;
3631 strncpy(p->dir,unixdir,sizeof(p->dir)-1);
3632 p->dir[NAM$C_MAXRSS] = '\0';
3633 }
3634
3635
3636
3637#ifdef ARCHLIB_EXP
3638 if ((tounixpath_utf8(ARCHLIB_EXP, unixdir, NULL)) != Nullch) {
3639 p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
3640 if (p == NULL) _ckvmssts(SS$_INSFMEM);
3641 p->next = head_PLOC;
3642 head_PLOC = p;
3643 strncpy(p->dir,unixdir,sizeof(p->dir)-1);
3644 p->dir[NAM$C_MAXRSS] = '\0';
3645 }
3646#endif
3647 PerlMem_free(unixdir);
3648}
3649
3650static I32
3651Perl_cando_by_name_int
3652 (pTHX_ I32 bit, bool effective, const char *fname, int opts);
3653#if !defined(PERL_IMPLICIT_CONTEXT)
3654#define cando_by_name_int Perl_cando_by_name_int
3655#else
3656#define cando_by_name_int(a,b,c,d) Perl_cando_by_name_int(aTHX_ a,b,c,d)
3657#endif
3658
3659static char *
3660find_vmspipe(pTHX)
3661{
3662 static int vmspipe_file_status = 0;
3663 static char vmspipe_file[NAM$C_MAXRSS+1];
3664
3665
3666
3667 if (vmspipe_file_status == 1) {
3668 if (cando_by_name_int(S_IRUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)
3669 && cando_by_name_int
3670 (S_IXUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)) {
3671 return vmspipe_file;
3672 }
3673 vmspipe_file_status = 0;
3674 }
3675
3676
3677
3678 if (vmspipe_file_status == 0) {
3679 char file[NAM$C_MAXRSS+1];
3680 pPLOC p = head_PLOC;
3681
3682 while (p) {
3683 char * exp_res;
3684 int dirlen;
3685 strcpy(file, p->dir);
3686 dirlen = strlen(file);
3687 strncat(file, "vmspipe.com",NAM$C_MAXRSS - dirlen);
3688 file[NAM$C_MAXRSS] = '\0';
3689 p = p->next;
3690
3691 exp_res = do_rmsexpand
3692 (file, vmspipe_file, 0, NULL, PERL_RMSEXPAND_M_VMS, NULL, NULL);
3693 if (!exp_res) continue;
3694
3695 if (cando_by_name_int
3696 (S_IRUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)
3697 && cando_by_name_int
3698 (S_IXUSR, 0, vmspipe_file, PERL_RMSEXPAND_M_VMS_IN)) {
3699 vmspipe_file_status = 1;
3700 return vmspipe_file;
3701 }
3702 }
3703 vmspipe_file_status = -1;
3704 }
3705
3706 return 0;
3707}
3708
3709static FILE *
3710vmspipe_tempfile(pTHX)
3711{
3712 char file[NAM$C_MAXRSS+1];
3713 FILE *fp;
3714 static int index = 0;
3715 Stat_t s0, s1;
3716 int cmp_result;
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730 index++;
3731 if (!decc_filename_unix_only) {
3732 sprintf(file,"sys$scratch:perlpipe_%08.8x_%d.com",mypid,index);
3733 fp = fopen(file,"w");
3734 if (!fp) {
3735 sprintf(file,"sys$login:perlpipe_%08.8x_%d.com",mypid,index);
3736 fp = fopen(file,"w");
3737 if (!fp) {
3738 sprintf(file,"sys$disk:[]perlpipe_%08.8x_%d.com",mypid,index);
3739 fp = fopen(file,"w");
3740 }
3741 }
3742 }
3743 else {
3744 sprintf(file,"/tmp/perlpipe_%08.8x_%d.com",mypid,index);
3745 fp = fopen(file,"w");
3746 if (!fp) {
3747 sprintf(file,"/sys$login/perlpipe_%08.8x_%d.com",mypid,index);
3748 fp = fopen(file,"w");
3749 if (!fp) {
3750 sprintf(file,"./perlpipe_%08.8x_%d.com",mypid,index);
3751 fp = fopen(file,"w");
3752 }
3753 }
3754 }
3755 if (!fp) return 0;
3756
3757 fprintf(fp,"$! 'f$verify(0)'\n");
3758 fprintf(fp,"$! --- protect against nonstandard definitions ---\n");
3759 fprintf(fp,"$ perl_cfile = f$environment(\"procedure\")\n");
3760 fprintf(fp,"$ perl_define = \"define/nolog\"\n");
3761 fprintf(fp,"$ perl_on = \"set noon\"\n");
3762 fprintf(fp,"$ perl_exit = \"exit\"\n");
3763 fprintf(fp,"$ perl_del = \"delete\"\n");
3764 fprintf(fp,"$ pif = \"if\"\n");
3765 fprintf(fp,"$! --- define i/o redirection (sys$output set by lib$spawn)\n");
3766 fprintf(fp,"$ pif perl_popen_in .nes. \"\" then perl_define/user/name_attributes=confine sys$input 'perl_popen_in'\n");
3767 fprintf(fp,"$ pif perl_popen_err .nes. \"\" then perl_define/user/name_attributes=confine sys$error 'perl_popen_err'\n");
3768 fprintf(fp,"$ pif perl_popen_out .nes. \"\" then perl_define sys$output 'perl_popen_out'\n");
3769 fprintf(fp,"$! --- build command line to get max possible length\n");
3770 fprintf(fp,"$c=perl_popen_cmd0\n");
3771 fprintf(fp,"$c=c+perl_popen_cmd1\n");
3772 fprintf(fp,"$c=c+perl_popen_cmd2\n");
3773 fprintf(fp,"$x=perl_popen_cmd3\n");
3774 fprintf(fp,"$c=c+x\n");
3775 fprintf(fp,"$ perl_on\n");
3776 fprintf(fp,"$ 'c'\n");
3777 fprintf(fp,"$ perl_status = $STATUS\n");
3778 fprintf(fp,"$ perl_del 'perl_cfile'\n");
3779 fprintf(fp,"$ perl_exit 'perl_status'\n");
3780 fsync(fileno(fp));
3781
3782 fgetname(fp, file, 1);
3783 fstat(fileno(fp), (struct stat *)&s0);
3784 fclose(fp);
3785
3786 if (decc_filename_unix_only)
3787 do_tounixspec(file, file, 0, NULL);
3788 fp = fopen(file,"r","shr=get");
3789 if (!fp) return 0;
3790 fstat(fileno(fp), (struct stat *)&s1);
3791
3792 cmp_result = VMS_INO_T_COMPARE(s0.crtl_stat.st_ino, s1.crtl_stat.st_ino);
3793 if ((cmp_result != 0) && (s0.st_ctime != s1.st_ctime)) {
3794 fclose(fp);
3795 return 0;
3796 }
3797
3798 return fp;
3799}
3800
3801
3802static int vms_is_syscommand_xterm(void)
3803{
3804 const static struct dsc$descriptor_s syscommand_dsc =
3805 { 11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND" };
3806
3807 const static struct dsc$descriptor_s decwdisplay_dsc =
3808 { 12, DSC$K_DTYPE_T, DSC$K_CLASS_S, "DECW$DISPLAY" };
3809
3810 struct item_list_3 items[2];
3811 unsigned short dvi_iosb[4];
3812 unsigned long devchar;
3813 unsigned long devclass;
3814 int status;
3815
3816
3817
3818 items[0].len = 4;
3819 items[0].code = DVI$_DEVCHAR;
3820 items[0].bufadr = &devchar;
3821 items[0].retadr = NULL;
3822 items[1].len = 0;
3823 items[1].code = 0;
3824
3825 status = sys$getdviw
3826 (NO_EFN, 0, &decwdisplay_dsc, items, dvi_iosb, NULL, NULL, NULL);
3827
3828 if ($VMS_STATUS_SUCCESS(status)) {
3829 status = dvi_iosb[0];
3830 }
3831
3832 if (!$VMS_STATUS_SUCCESS(status)) {
3833 SETERRNO(EVMSERR, status);
3834 return -1;
3835 }
3836
3837
3838
3839
3840
3841 items[0].len = 4;
3842 items[0].code = DVI$_DEVCLASS;
3843 items[0].bufadr = &devclass;
3844 items[0].retadr = NULL;
3845 items[1].len = 0;
3846 items[1].code = 0;
3847
3848 status = sys$getdviw
3849 (NO_EFN, 0, &syscommand_dsc, items, dvi_iosb, NULL, NULL, NULL);
3850
3851 if ($VMS_STATUS_SUCCESS(status)) {
3852 status = dvi_iosb[0];
3853 }
3854
3855 if (!$VMS_STATUS_SUCCESS(status)) {
3856 SETERRNO(EVMSERR, status);
3857 return -1;
3858 }
3859 else {
3860 if (devclass == DC$_TERM) {
3861 return 0;
3862 }
3863 }
3864 return -1;
3865}
3866
3867
3868static PerlIO * create_forked_xterm(pTHX_ const char *cmd, const char *mode)
3869{
3870 int status;
3871 int ret_stat;
3872 char * ret_char;
3873 char device_name[65];
3874 unsigned short device_name_len;
3875 struct dsc$descriptor_s customization_dsc;
3876 struct dsc$descriptor_s device_name_dsc;
3877 const char * cptr;
3878 char * tptr;
3879 char customization[200];
3880 char title[40];
3881 pInfo info = NULL;
3882 char mbx1[64];
3883 unsigned short p_chan;
3884 int n;
3885 unsigned short iosb[4];
3886 struct item_list_3 items[2];
3887 const char * cust_str =
3888 "DECW$TERMINAL.iconName:\tPerl Dbg\nDECW$TERMINAL.title:\t%40s\n";
3889 struct dsc$descriptor_s d_mbx1 = {sizeof mbx1, DSC$K_DTYPE_T,
3890 DSC$K_CLASS_S, mbx1};
3891
3892
3893
3894 VAXC$ESTABLISH((__vms_handler)lib$sig_to_ret);
3895
3896
3897
3898 ret_char = strstr(cmd," xterm ");
3899 if (ret_char == NULL)
3900 return NULL;
3901 cptr = ret_char + 7;
3902 ret_char = strstr(cmd,"tty");
3903 if (ret_char == NULL)
3904 return NULL;
3905 ret_char = strstr(cmd,"sleep");
3906 if (ret_char == NULL)
3907 return NULL;
3908
3909 if (decw_term_port == 0) {
3910 $DESCRIPTOR(filename1_dsc, "DECW$TERMINALSHR12");
3911 $DESCRIPTOR(filename2_dsc, "DECW$TERMINALSHR");
3912 $DESCRIPTOR(decw_term_port_dsc, "DECW$TERM_PORT");
3913
3914 status = lib$find_image_symbol
3915 (&filename1_dsc,
3916 &decw_term_port_dsc,
3917 (void *)&decw_term_port,
3918 NULL,
3919 0);
3920
3921
3922 if (!$VMS_STATUS_SUCCESS(status)) {
3923
3924 status = lib$find_image_symbol
3925 (&filename2_dsc,
3926 &decw_term_port_dsc,
3927 (void *)&decw_term_port,
3928 NULL,
3929 0);
3930
3931 }
3932
3933 }
3934
3935
3936
3937 if (!$VMS_STATUS_SUCCESS(status))
3938 return NULL;
3939
3940
3941
3942 ret_stat = vms_is_syscommand_xterm();
3943 if (ret_stat < 0)
3944 return NULL;
3945
3946
3947 ret_char = strstr(cptr,"-title");
3948 if (ret_char != NULL) {
3949 while ((*cptr != 0) && (*cptr != '\"')) {
3950 cptr++;
3951 }
3952 if (*cptr == '\"')
3953 cptr++;
3954 n = 0;
3955 while ((*cptr != 0) && (*cptr != '\"')) {
3956 title[n] = *cptr;
3957 n++;
3958 if (n == 39) {
3959 title[39] == 0;
3960 break;
3961 }
3962 cptr++;
3963 }
3964 title[n] = 0;
3965 }
3966 else {
3967
3968 strcpy(title,"Perl Debug DECTerm");
3969 }
3970 sprintf(customization, cust_str, title);
3971
3972 customization_dsc.dsc$a_pointer = customization;
3973 customization_dsc.dsc$w_length = strlen(customization);
3974 customization_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
3975 customization_dsc.dsc$b_class = DSC$K_CLASS_S;
3976
3977 device_name_dsc.dsc$a_pointer = device_name;
3978 device_name_dsc.dsc$w_length = sizeof device_name -1;
3979 device_name_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
3980 device_name_dsc.dsc$b_class = DSC$K_CLASS_S;
3981
3982 device_name_len = 0;
3983
3984
3985 status = (*decw_term_port)
3986 (NULL,
3987 NULL,
3988 &customization_dsc,
3989 &device_name_dsc,
3990 &device_name_len,
3991 NULL,
3992 NULL,
3993 NULL);
3994 if (!$VMS_STATUS_SUCCESS(status)) {
3995 SETERRNO(EVMSERR, status);
3996 return NULL;
3997 }
3998
3999 device_name[device_name_len] = '\0';
4000
4001
4002 n = sizeof(Info);
4003 status = lib$get_vm(&n, &info);
4004 if (!$VMS_STATUS_SUCCESS(status)) {
4005 SETERRNO(ENOMEM, status);
4006 return NULL;
4007 }
4008
4009 info->mode = *mode;
4010 info->done = FALSE;
4011 info->completion = 0;
4012 info->closing = FALSE;
4013 info->in = 0;
4014 info->out = 0;
4015 info->err = 0;
4016 info->fp = Nullfp;
4017 info->useFILE = 0;
4018 info->waiting = 0;
4019 info->in_done = TRUE;
4020 info->out_done = TRUE;
4021 info->err_done = TRUE;
4022
4023
4024
4025
4026
4027
4028 device_name_dsc.dsc$w_length = device_name_len;
4029 status = sys$assign(&device_name_dsc,&info->xchan,0,0);
4030 if (!$VMS_STATUS_SUCCESS(status)) {
4031 SETERRNO(EVMSERR, status);
4032 return NULL;
4033 }
4034 info->xchan_valid = 1;
4035
4036
4037
4038 create_mbx(aTHX_ &p_chan, &d_mbx1);
4039
4040
4041 status = sys$qiow(NO_EFN, p_chan, IO$_WRITEVBLK|IO$M_NOW,
4042 iosb, NULL, NULL, device_name, device_name_len, 0, 0, 0, 0);
4043
4044 if (!$VMS_STATUS_SUCCESS(status)) {
4045 SETERRNO(EVMSERR, status);
4046 return NULL;
4047 }
4048
4049 info->fp = PerlIO_open(mbx1, mode);
4050
4051
4052 sys$dassgn(p_chan);
4053
4054
4055 if (!info->fp) {
4056 n = sizeof(Info);
4057 _ckvmssts(lib$free_vm(&n, &info));
4058 return NULL;
4059 }
4060
4061
4062 return info->fp;
4063}
4064
4065static PerlIO *
4066safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
4067{
4068 static int handler_set_up = FALSE;
4069 unsigned long int sts, flags = CLI$M_NOWAIT;
4070
4071
4072
4073
4074 unsigned int table = LIB$K_CLI_LOCAL_SYM;
4075 int j, wait = 0, n;
4076 char *p, mode[10], symbol[MAX_DCL_SYMBOL+1], *vmspipe;
4077 char *in, *out, *err, mbx[512];
4078 FILE *tpipe = 0;
4079 char tfilebuf[NAM$C_MAXRSS+1];
4080 pInfo info = NULL;
4081 char cmd_sym_name[20];
4082 struct dsc$descriptor_s d_symbol= {0, DSC$K_DTYPE_T,
4083 DSC$K_CLASS_S, symbol};
4084 struct dsc$descriptor_s vmspipedsc = {0, DSC$K_DTYPE_T,
4085 DSC$K_CLASS_S, 0};
4086 struct dsc$descriptor_s d_sym_cmd = {0, DSC$K_DTYPE_T,
4087 DSC$K_CLASS_S, cmd_sym_name};
4088 struct dsc$descriptor_s *vmscmd;
4089 $DESCRIPTOR(d_sym_in ,"PERL_POPEN_IN");
4090 $DESCRIPTOR(d_sym_out,"PERL_POPEN_OUT");
4091 $DESCRIPTOR(d_sym_err,"PERL_POPEN_ERR");
4092
4093
4094
4095
4096
4097 if (*in_mode == 'r') {
4098 PerlIO * xterm_fd;
4099
4100 xterm_fd = create_forked_xterm(aTHX_ cmd, in_mode);
4101 if (xterm_fd != Nullfp)
4102 return xterm_fd;
4103 }
4104
4105 if (!head_PLOC) store_pipelocs(aTHX);
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117 if (!pipe_ef) {
4118 _ckvmssts(sys$setast(0));
4119 if (!pipe_ef) {
4120 unsigned long int pidcode = JPI$_PID;
4121 $DESCRIPTOR(d_delay, RETRY_DELAY);
4122 _ckvmssts(lib$get_ef(&pipe_ef));
4123 _ckvmssts(lib$getjpi(&pidcode,0,0,&mypid,0,0));
4124 _ckvmssts(sys$bintim(&d_delay, delaytime));
4125 }
4126 if (!handler_set_up) {
4127 _ckvmssts(sys$dclexh(&pipe_exitblock));
4128 handler_set_up = TRUE;
4129 }
4130 _ckvmssts(sys$setast(1));
4131 }
4132
4133
4134
4135 tfilebuf[0] = '@';
4136 vmspipe = find_vmspipe(aTHX);
4137 if (vmspipe) {
4138 strcpy(tfilebuf+1,vmspipe);
4139 } else {
4140 tpipe = vmspipe_tempfile(aTHX);
4141 if (!tpipe) {
4142 if (ckWARN(WARN_PIPE)) {
4143 Perl_warner(aTHX_ packWARN(WARN_PIPE),"unable to find VMSPIPE.COM for i/o piping");
4144 }
4145 return Nullfp;
4146 }
4147 fgetname(tpipe,tfilebuf+1,1);
4148 }
4149 vmspipedsc.dsc$a_pointer = tfilebuf;
4150 vmspipedsc.dsc$w_length = strlen(tfilebuf);
4151
4152 sts = setup_cmddsc(aTHX_ cmd,0,0,&vmscmd);
4153 if (!(sts & 1)) {
4154 switch (sts) {
4155 case RMS$_FNF: case RMS$_DNF:
4156 set_errno(ENOENT); break;
4157 case RMS$_DIR:
4158 set_errno(ENOTDIR); break;
4159 case RMS$_DEV:
4160 set_errno(ENODEV); break;
4161 case RMS$_PRV:
4162 set_errno(EACCES); break;
4163 case RMS$_SYN:
4164 set_errno(EINVAL); break;
4165 case CLI$_BUFOVF: case RMS$_RTB: case CLI$_TKNOVF: case CLI$_RSLOVF:
4166 set_errno(E2BIG); break;
4167 case LIB$_INVARG: case LIB$_INVSTRDES: case SS$_ACCVIO:
4168 _ckvmssts(sts);
4169 default:
4170 set_errno(EVMSERR);
4171 }
4172 set_vaxc_errno(sts);
4173 if (*in_mode != 'n' && ckWARN(WARN_PIPE)) {
4174 Perl_warner(aTHX_ packWARN(WARN_PIPE),"Can't pipe \"%*s\": %s", strlen(cmd), cmd, Strerror(errno));
4175 }
4176 *psts = sts;
4177 return Nullfp;
4178 }
4179 n = sizeof(Info);
4180 _ckvmssts(lib$get_vm(&n, &info));
4181
4182 strcpy(mode,in_mode);
4183 info->mode = *mode;
4184 info->done = FALSE;
4185 info->completion = 0;
4186 info->closing = FALSE;
4187 info->in = 0;
4188 info->out = 0;
4189 info->err = 0;
4190 info->fp = Nullfp;
4191 info->useFILE = 0;
4192 info->waiting = 0;
4193 info->in_done = TRUE;
4194 info->out_done = TRUE;
4195 info->err_done = TRUE;
4196 info->xchan = 0;
4197 info->xchan_valid = 0;
4198
4199 in = PerlMem_malloc(VMS_MAXRSS);
4200 if (in == NULL) _ckvmssts(SS$_INSFMEM);
4201 out = PerlMem_malloc(VMS_MAXRSS);
4202 if (out == NULL) _ckvmssts(SS$_INSFMEM);
4203 err = PerlMem_malloc(VMS_MAXRSS);
4204 if (err == NULL) _ckvmssts(SS$_INSFMEM);
4205
4206 in[0] = out[0] = err[0] = '\0';
4207
4208 if ((p = strchr(mode,'F')) != NULL) {
4209 info->useFILE = 1;
4210 strcpy(p,p+1);
4211 }
4212 if ((p = strchr(mode,'W')) != NULL) {
4213 wait = 1;
4214 strcpy(p,p+1);
4215 }
4216
4217 if (*mode == 'r') {
4218
4219 info->out = pipe_infromchild_setup(aTHX_ mbx,out);
4220 if (info->out) {
4221 info->out->pipe_done = &info->out_done;
4222 info->out_done = FALSE;
4223 info->out->info = info;
4224 }
4225 if (!info->useFILE) {
4226 info->fp = PerlIO_open(mbx, mode);
4227 } else {
4228 info->fp = (PerlIO *) freopen(mbx, mode, stdin);
4229 Perl_vmssetuserlnm(aTHX_ "SYS$INPUT",mbx);
4230 }
4231
4232 if (!info->fp && info->out) {
4233 sys$cancel(info->out->chan_out);
4234
4235 while (!info->out_done) {
4236 int done;
4237 _ckvmssts(sys$setast(0));
4238 done = info->out_done;
4239 if (!done) _ckvmssts(sys$clref(pipe_ef));
4240 _ckvmssts(sys$setast(1));
4241 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
4242 }
4243
4244 if (info->out->buf) {
4245 n = info->out->bufsize * sizeof(char);
4246 _ckvmssts(lib$free_vm(&n, &info->out->buf));
4247 }
4248 n = sizeof(Pipe);
4249 _ckvmssts(lib$free_vm(&n, &info->out));
4250 n = sizeof(Info);
4251 _ckvmssts(lib$free_vm(&n, &info));
4252 *psts = RMS$_FNF;
4253 return Nullfp;
4254 }
4255
4256 info->err = pipe_mbxtofd_setup(aTHX_ fileno(stderr), err);
4257 if (info->err) {
4258 info->err->pipe_done = &info->err_done;
4259 info->err_done = FALSE;
4260 info->err->info = info;
4261 }
4262
4263 } else if (*mode == 'w') {
4264
4265 info->out = pipe_mbxtofd_setup(aTHX_ fileno(stdout), out);
4266 if (info->out) {
4267 info->out->pipe_done = &info->out_done;
4268 info->out_done = FALSE;
4269 info->out->info = info;
4270 }
4271
4272 info->err = pipe_mbxtofd_setup(aTHX_ fileno(stderr), err);
4273 if (info->err) {
4274 info->err->pipe_done = &info->err_done;
4275 info->err_done = FALSE;
4276 info->err->info = info;
4277 }
4278
4279 info->in = pipe_tochild_setup(aTHX_ in,mbx);
4280 if (!info->useFILE) {
4281 info->fp = PerlIO_open(mbx, mode);
4282 } else {
4283 info->fp = (PerlIO *) freopen(mbx, mode, stdout);
4284 Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT",mbx);
4285 }
4286
4287 if (info->in) {
4288 info->in->pipe_done = &info->in_done;
4289 info->in_done = FALSE;
4290 info->in->info = info;
4291 }
4292
4293
4294 if (!info->fp && info->in) {
4295 info->done = TRUE;
4296 _ckvmssts(sys$qiow(0,info->in->chan_in, IO$_WRITEOF, 0,
4297 0, 0, 0, 0, 0, 0, 0, 0));
4298
4299 while (!info->in_done) {
4300 int done;
4301 _ckvmssts(sys$setast(0));
4302 done = info->in_done;
4303 if (!done) _ckvmssts(sys$clref(pipe_ef));
4304 _ckvmssts(sys$setast(1));
4305 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
4306 }
4307
4308 if (info->in->buf) {
4309 n = info->in->bufsize * sizeof(char);
4310 _ckvmssts(lib$free_vm(&n, &info->in->buf));
4311 }
4312 n = sizeof(Pipe);
4313 _ckvmssts(lib$free_vm(&n, &info->in));
4314 n = sizeof(Info);
4315 _ckvmssts(lib$free_vm(&n, &info));
4316 *psts = RMS$_FNF;
4317 return Nullfp;
4318 }
4319
4320
4321 } else if (*mode == 'n') {
4322 info->out = pipe_mbxtofd_setup(aTHX_ fileno(stdout), out);
4323 if (info->out) {
4324 info->out->pipe_done = &info->out_done;
4325 info->out_done = FALSE;
4326 info->out->info = info;
4327 }
4328
4329 info->err = pipe_mbxtofd_setup(aTHX_ fileno(stderr), err);
4330 if (info->err) {
4331 info->err->pipe_done = &info->err_done;
4332 info->err_done = FALSE;
4333 info->err->info = info;
4334 }
4335 }
4336
4337 symbol[MAX_DCL_SYMBOL] = '\0';
4338
4339 strncpy(symbol, in, MAX_DCL_SYMBOL);
4340 d_symbol.dsc$w_length = strlen(symbol);
4341 _ckvmssts(lib$set_symbol(&d_sym_in, &d_symbol, &table));
4342
4343 strncpy(symbol, err, MAX_DCL_SYMBOL);
4344 d_symbol.dsc$w_length = strlen(symbol);
4345 _ckvmssts(lib$set_symbol(&d_sym_err, &d_symbol, &table));
4346
4347 strncpy(symbol, out, MAX_DCL_SYMBOL);
4348 d_symbol.dsc$w_length = strlen(symbol);
4349 _ckvmssts(lib$set_symbol(&d_sym_out, &d_symbol, &table));
4350
4351
4352 PerlMem_free(err);
4353 PerlMem_free(out);
4354 PerlMem_free(in);
4355
4356 p = vmscmd->dsc$a_pointer;
4357 while (*p == ' ' || *p == '\t') p++;
4358 if (*p == '$') p++;
4359 while (*p == ' ' || *p == '\t') p++;
4360
4361 for (j = 0; j < 4; j++) {
4362 sprintf(cmd_sym_name,"PERL_POPEN_CMD%d",j);
4363 d_sym_cmd.dsc$w_length = strlen(cmd_sym_name);
4364
4365 strncpy(symbol, p, MAX_DCL_SYMBOL);
4366 d_symbol.dsc$w_length = strlen(symbol);
4367 _ckvmssts(lib$set_symbol(&d_sym_cmd, &d_symbol, &table));
4368
4369 if (strlen(p) > MAX_DCL_SYMBOL) {
4370 p += MAX_DCL_SYMBOL;
4371 } else {
4372 p += strlen(p);
4373 }
4374 }
4375 _ckvmssts(sys$setast(0));
4376 info->next=open_pipes;
4377 open_pipes=info;
4378 _ckvmssts(sys$setast(1));
4379
4380
4381
4382
4383 _ckvmssts(lib$spawn(&vmspipedsc, 0, &nl_desc, &flags,
4384 0, &info->pid, &info->completion,
4385 0, popen_completion_ast,info,0,0,0));
4386
4387
4388
4389 if (tpipe) fclose(tpipe);
4390
4391
4392
4393
4394 for (j = 0; j < 4; j++) {
4395 sprintf(cmd_sym_name,"PERL_POPEN_CMD%d",j);
4396 d_sym_cmd.dsc$w_length = strlen(cmd_sym_name);
4397 _ckvmssts(lib$delete_symbol(&d_sym_cmd, &table));
4398 }
4399 _ckvmssts(lib$delete_symbol(&d_sym_in, &table));
4400 _ckvmssts(lib$delete_symbol(&d_sym_err, &table));
4401 _ckvmssts(lib$delete_symbol(&d_sym_out, &table));
4402 vms_execfree(vmscmd);
4403
4404#ifdef PERL_IMPLICIT_CONTEXT
4405 if (aTHX)
4406#endif
4407 PL_forkprocess = info->pid;
4408
4409 if (wait) {
4410 int done = 0;
4411 while (!done) {
4412 _ckvmssts(sys$setast(0));
4413 done = info->done;
4414 if (!done) _ckvmssts(sys$clref(pipe_ef));
4415 _ckvmssts(sys$setast(1));
4416 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
4417 }
4418 *psts = info->completion;
4419
4420
4421
4422 } else {
4423 *psts = info->pid;
4424 }
4425 return info->fp;
4426}
4427
4428
4429
4430PerlIO *
4431Perl_my_popen(pTHX_ const char *cmd, const char *mode)
4432{
4433 int sts;
4434 TAINT_ENV();
4435 TAINT_PROPER("popen");
4436 PERL_FLUSHALL_FOR_CHILD;
4437 return safe_popen(aTHX_ cmd,mode,&sts);
4438}
4439
4440
4441
4442
4443I32 Perl_my_pclose(pTHX_ PerlIO *fp)
4444{
4445 pInfo info, last = NULL;
4446 unsigned long int retsts;
4447 int done, iss, n;
4448 int status;
4449
4450 for (info = open_pipes; info != NULL; last = info, info = info->next)
4451 if (info->fp == fp) break;
4452
4453 if (info == NULL) {
4454 set_errno(ECHILD);
4455 set_vaxc_errno(SS$_NONEXPR);
4456 return -1;
4457 }
4458
4459
4460
4461
4462
4463
4464
4465
4466 if (info->fp) {
4467 if (!info->useFILE
4468#if defined(USE_ITHREADS)
4469 && my_perl
4470#endif
4471 && PL_perlio_fd_refcnt)
4472 PerlIO_flush(info->fp);
4473 else
4474 fflush((FILE *)info->fp);
4475 }
4476
4477 _ckvmssts(sys$setast(0));
4478 info->closing = TRUE;
4479 done = info->done && info->in_done && info->out_done && info->err_done;
4480
4481 if (info->mode == 'r' && info->out && !info->out_done) {
4482 if (info->out->chan_out) {
4483 _ckvmssts(sys$cancel(info->out->chan_out));
4484 if (!info->out->chan_in) {
4485 _ckvmssts(sys$dclast(pipe_infromchild_ast,info->out,0));
4486 }
4487 }
4488 }
4489 if (info->in && !info->in_done && !info->in->shut_on_empty)
4490 _ckvmssts(sys$qio(0,info->in->chan_in,IO$_WRITEOF,0,0,0,
4491 0, 0, 0, 0, 0, 0));
4492 _ckvmssts(sys$setast(1));
4493 if (info->fp) {
4494 if (!info->useFILE
4495#if defined(USE_ITHREADS)
4496 && my_perl
4497#endif
4498 && PL_perlio_fd_refcnt)
4499 PerlIO_close(info->fp);
4500 else
4501 fclose((FILE *)info->fp);
4502 }
4503
4504
4505
4506
4507
4508
4509 while (!done) {
4510 _ckvmssts(sys$setast(0));
4511 done = info->done && info->in_done && info->out_done && info->err_done;
4512 if (!done) _ckvmssts(sys$clref(pipe_ef));
4513 _ckvmssts(sys$setast(1));
4514 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
4515 }
4516 retsts = info->completion;
4517
4518
4519 _ckvmssts(sys$setast(0));
4520 if (last) last->next = info->next;
4521 else open_pipes = info->next;
4522 _ckvmssts(sys$setast(1));
4523
4524
4525
4526 if (info->in) {
4527 if (info->in->buf) {
4528 n = info->in->bufsize * sizeof(char);
4529 _ckvmssts(lib$free_vm(&n, &info->in->buf));
4530 }
4531 n = sizeof(Pipe);
4532 _ckvmssts(lib$free_vm(&n, &info->in));
4533 }
4534 if (info->out) {
4535 if (info->out->buf) {
4536 n = info->out->bufsize * sizeof(char);
4537 _ckvmssts(lib$free_vm(&n, &info->out->buf));
4538 }
4539 n = sizeof(Pipe);
4540 _ckvmssts(lib$free_vm(&n, &info->out));
4541 }
4542 if (info->err) {
4543 if (info->err->buf) {
4544 n = info->err->bufsize * sizeof(char);
4545 _ckvmssts(lib$free_vm(&n, &info->err->buf));
4546 }
4547 n = sizeof(Pipe);
4548 _ckvmssts(lib$free_vm(&n, &info->err));
4549 }
4550 n = sizeof(Info);
4551 _ckvmssts(lib$free_vm(&n, &info));
4552
4553 return retsts;
4554
4555}
4556
4557#if defined(__CRTL_VER) && __CRTL_VER >= 70200000
4558
4559
4560
4561 __pid_t __vms_waitpid( __pid_t __pid, int *__stat_loc, int __options );
4562#endif
4563
4564
4565
4566
4567
4568
4569Pid_t
4570Perl_my_waitpid(pTHX_ Pid_t pid, int *statusp, int flags)
4571{
4572 pInfo info;
4573 int done;
4574 int sts;
4575 int j;
4576
4577 if (statusp) *statusp = 0;
4578
4579 for (info = open_pipes; info != NULL; info = info->next)
4580 if (info->pid == pid) break;
4581
4582 if (info != NULL) {
4583 while (!info->done) {
4584 _ckvmssts(sys$setast(0));
4585 done = info->done;
4586 if (!done) _ckvmssts(sys$clref(pipe_ef));
4587 _ckvmssts(sys$setast(1));
4588 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
4589 }
4590
4591 if (statusp) *statusp = info->completion;
4592 return pid;
4593 }
4594
4595
4596
4597 for (j = 0; j < NKEEPCLOSED && j < closed_num; j++) {
4598 if (closed_list[j].pid == pid) {
4599 if (statusp) *statusp = closed_list[j].completion;
4600 return pid;
4601 }
4602 }
4603
4604
4605
4606#if defined(__CRTL_VER) && __CRTL_VER >= 70200000
4607
4608
4609
4610
4611
4612
4613 sts = __vms_waitpid( pid, statusp, flags );
4614
4615 if ( sts == 0 || !(sts == -1 && errno == ECHILD) )
4616 return sts;
4617
4618
4619
4620
4621
4622
4623
4624
4625#endif
4626
4627 {
4628 $DESCRIPTOR(intdsc,"0 00:00:01");
4629 unsigned long int ownercode = JPI$_OWNER, ownerpid;
4630 unsigned long int pidcode = JPI$_PID, mypid;
4631 unsigned long int interval[2];
4632 unsigned int jpi_iosb[2];
4633 struct itmlst_3 jpilist[2] = {
4634 {sizeof(ownerpid), JPI$_OWNER, &ownerpid, 0},
4635 { 0, 0, 0, 0}
4636 };
4637
4638 if (pid <= 0) {
4639
4640
4641
4642
4643 set_errno(ENOTSUP);
4644 return -1;
4645 }
4646
4647
4648
4649
4650
4651 sts = sys$getjpiw(0,&pid,NULL,&jpilist,&jpi_iosb,NULL,NULL);
4652 if (sts & 1) sts = jpi_iosb[0];
4653 if (!(sts & 1)) {
4654 switch (sts) {
4655 case SS$_NONEXPR:
4656 set_errno(ECHILD);
4657 break;
4658 case SS$_NOPRIV:
4659 set_errno(EACCES);
4660 break;
4661 default:
4662 _ckvmssts(sts);
4663 }
4664 set_vaxc_errno(sts);
4665 return -1;
4666 }
4667
4668 if (ckWARN(WARN_EXEC)) {
4669
4670 _ckvmssts(lib$getjpi(&pidcode,0,0,&mypid,0,0));
4671 if (ownerpid != mypid)
4672 Perl_warner(aTHX_ packWARN(WARN_EXEC),
4673 "waitpid: process %x is not a child of process %x",
4674 pid,mypid);
4675 }
4676
4677
4678
4679 _ckvmssts(sys$bintim(&intdsc,interval));
4680 while ((sts=lib$getjpi(&ownercode,&pid,0,&ownerpid,0,0)) & 1) {
4681 _ckvmssts(sys$schdwk(0,0,interval,0));
4682 _ckvmssts(sys$hiber());
4683 }
4684 if (sts == SS$_NONEXPR) sts = SS$_NORMAL;
4685
4686 _ckvmssts(sts);
4687 return pid;
4688 }
4689}
4690
4691
4692
4693
4694
4695char *
4696my_gconvert(double val, int ndig, int trail, char *buf)
4697{
4698 static char __gcvtbuf[DBL_DIG+1];
4699 char *loc;
4700
4701 loc = buf ? buf : __gcvtbuf;
4702
4703#ifndef __DECC
4704 if (val < 1) {
4705 sprintf(loc,"%.*g",ndig,val);
4706 return loc;
4707 }
4708#endif
4709
4710 if (val) {
4711 if (!buf && ndig > DBL_DIG) ndig = DBL_DIG;
4712 return gcvt(val,ndig,loc);
4713 }
4714 else {
4715 loc[0] = '0'; loc[1] = '\0';
4716 return loc;
4717 }
4718
4719}
4720
4721
4722#if defined(__VAX) || !defined(NAML$C_MAXRSS)
4723static int rms_free_search_context(struct FAB * fab)
4724{
4725struct NAM * nam;
4726
4727 nam = fab->fab$l_nam;
4728 nam->nam$b_nop |= NAM$M_SYNCHK;
4729 nam->nam$l_rlf = NULL;
4730 fab->fab$b_dns = 0;
4731 return sys$parse(fab, NULL, NULL);
4732}
4733
4734#define rms_setup_nam(nam) struct NAM nam = cc$rms_nam
4735#define rms_clear_nam_nop(nam) nam.nam$b_nop = 0;
4736#define rms_set_nam_nop(nam, opt) nam.nam$b_nop |= (opt)
4737#define rms_set_nam_fnb(nam, opt) nam.nam$l_fnb |= (opt)
4738#define rms_is_nam_fnb(nam, opt) (nam.nam$l_fnb & (opt))
4739#define rms_nam_esll(nam) nam.nam$b_esl
4740#define rms_nam_esl(nam) nam.nam$b_esl
4741#define rms_nam_name(nam) nam.nam$l_name
4742#define rms_nam_namel(nam) nam.nam$l_name
4743#define rms_nam_type(nam) nam.nam$l_type
4744#define rms_nam_typel(nam) nam.nam$l_type
4745#define rms_nam_ver(nam) nam.nam$l_ver
4746#define rms_nam_verl(nam) nam.nam$l_ver
4747#define rms_nam_rsll(nam) nam.nam$b_rsl
4748#define rms_nam_rsl(nam) nam.nam$b_rsl
4749#define rms_bind_fab_nam(fab, nam) fab.fab$l_nam = &nam
4750#define rms_set_fna(fab, nam, name, size) \
4751 { fab.fab$b_fns = size; fab.fab$l_fna = name; }
4752#define rms_get_fna(fab, nam) fab.fab$l_fna
4753#define rms_set_dna(fab, nam, name, size) \
4754 { fab.fab$b_dns = size; fab.fab$l_dna = name; }
4755#define rms_nam_dns(fab, nam) fab.fab$b_dns
4756#define rms_set_esa(nam, name, size) \
4757 { nam.nam$b_ess = size; nam.nam$l_esa = name; }
4758#define rms_set_esal(nam, s_name, s_size, l_name, l_size) \
4759 { nam.nam$l_esa = s_name; nam.nam$b_ess = s_size;}
4760#define rms_set_rsa(nam, name, size) \
4761 { nam.nam$l_rsa = name; nam.nam$b_rss = size; }
4762#define rms_set_rsal(nam, s_name, s_size, l_name, l_size) \
4763 { nam.nam$l_rsa = s_name; nam.nam$b_rss = s_size; }
4764#define rms_nam_name_type_l_size(nam) \
4765 (nam.nam$b_name + nam.nam$b_type)
4766#else
4767static int rms_free_search_context(struct FAB * fab)
4768{
4769struct NAML * nam;
4770
4771 nam = fab->fab$l_naml;
4772 nam->naml$b_nop |= NAM$M_SYNCHK;
4773 nam->naml$l_rlf = NULL;
4774 nam->naml$l_long_defname_size = 0;
4775
4776 fab->fab$b_dns = 0;
4777 return sys$parse(fab, NULL, NULL);
4778}
4779
4780#define rms_setup_nam(nam) struct NAML nam = cc$rms_naml
4781#define rms_clear_nam_nop(nam) nam.naml$b_nop = 0;
4782#define rms_set_nam_nop(nam, opt) nam.naml$b_nop |= (opt)
4783#define rms_set_nam_fnb(nam, opt) nam.naml$l_fnb |= (opt)
4784#define rms_is_nam_fnb(nam, opt) (nam.naml$l_fnb & (opt))
4785#define rms_nam_esll(nam) nam.naml$l_long_expand_size
4786#define rms_nam_esl(nam) nam.naml$b_esl
4787#define rms_nam_name(nam) nam.naml$l_name
4788#define rms_nam_namel(nam) nam.naml$l_long_name
4789#define rms_nam_type(nam) nam.naml$l_type
4790#define rms_nam_typel(nam) nam.naml$l_long_type
4791#define rms_nam_ver(nam) nam.naml$l_ver
4792#define rms_nam_verl(nam) nam.naml$l_long_ver
4793#define rms_nam_rsll(nam) nam.naml$l_long_result_size
4794#define rms_nam_rsl(nam) nam.naml$b_rsl
4795#define rms_bind_fab_nam(fab, nam) fab.fab$l_naml = &nam
4796#define rms_set_fna(fab, nam, name, size) \
4797 { fab.fab$b_fns = 0; fab.fab$l_fna = (char *) -1; \
4798 nam.naml$l_long_filename_size = size; \
4799 nam.naml$l_long_filename = name;}
4800#define rms_get_fna(fab, nam) nam.naml$l_long_filename
4801#define rms_set_dna(fab, nam, name, size) \
4802 { fab.fab$b_dns = 0; fab.fab$l_dna = (char *) -1; \
4803 nam.naml$l_long_defname_size = size; \
4804 nam.naml$l_long_defname = name; }
4805#define rms_nam_dns(fab, nam) nam.naml$l_long_defname_size
4806#define rms_set_esa(nam, name, size) \
4807 { nam.naml$b_ess = 0; nam.naml$l_esa = (char *) -1; \
4808 nam.naml$l_long_expand_alloc = size; \
4809 nam.naml$l_long_expand = name; }
4810#define rms_set_esal(nam, s_name, s_size, l_name, l_size) \
4811 { nam.naml$l_esa = s_name; nam.naml$b_ess = s_size; \
4812 nam.naml$l_long_expand = l_name; \
4813 nam.naml$l_long_expand_alloc = l_size; }
4814#define rms_set_rsa(nam, name, size) \
4815 { nam.naml$l_rsa = NULL; nam.naml$b_rss = 0; \
4816 nam.naml$l_long_result = name; \
4817 nam.naml$l_long_result_alloc = size; }
4818#define rms_set_rsal(nam, s_name, s_size, l_name, l_size) \
4819 { nam.naml$l_rsa = s_name; nam.naml$b_rss = s_size; \
4820 nam.naml$l_long_result = l_name; \
4821 nam.naml$l_long_result_alloc = l_size; }
4822#define rms_nam_name_type_l_size(nam) \
4823 (nam.naml$l_long_name_size + nam.naml$l_long_type_size)
4824#endif
4825
4826
4827
4828
4829
4830
4831
4832static int rms_erase(const char * vmsname)
4833{
4834 int status;
4835 struct FAB myfab = cc$rms_fab;
4836 rms_setup_nam(mynam);
4837
4838 rms_set_fna(myfab, mynam, (char *)vmsname, strlen(vmsname));
4839 rms_bind_fab_nam(myfab, mynam);
4840
4841
4842 if (vms_unlink_all_versions == 1) {
4843 const char * defspec = ";*";
4844 rms_set_dna(myfab, mynam, (char *)defspec, strlen(defspec));
4845 }
4846
4847#ifdef NAML$M_OPEN_SPECIAL
4848 rms_set_nam_nop(mynam, NAML$M_OPEN_SPECIAL);
4849#endif
4850
4851 status = sys$erase(&myfab, 0, 0);
4852
4853 return status;
4854}
4855
4856
4857static int
4858vms_rename_with_acl(pTHX_ const struct dsc$descriptor_s * vms_src_dsc,
4859 const struct dsc$descriptor_s * vms_dst_dsc,
4860 unsigned long flags)
4861{
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871const unsigned int access_mode = 0;
4872$DESCRIPTOR(obj_file_dsc,"FILE");
4873char *vmsname;
4874char *rslt;
4875unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE;
4876int aclsts, fndsts, rnsts = -1;
4877unsigned int ctx = 0;
4878struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
4879struct dsc$descriptor_s * clean_dsc;
4880
4881struct myacedef {
4882 unsigned char myace$b_length;
4883 unsigned char myace$b_type;
4884 unsigned short int myace$w_flags;
4885 unsigned long int myace$l_access;
4886 unsigned long int myace$l_ident;
4887} newace = { sizeof(struct myacedef), ACE$C_KEYID, 0,
4888 ACE$M_READ | ACE$M_WRITE | ACE$M_DELETE | ACE$M_CONTROL,
4889 0},
4890 oldace = { sizeof(struct myacedef), ACE$C_KEYID, 0, 0, 0};
4891
4892struct item_list_3
4893 findlst[3] = {{sizeof oldace, OSS$_ACL_FIND_ENTRY, &oldace, 0},
4894 {sizeof oldace, OSS$_ACL_READ_ENTRY, &oldace, 0},
4895 {0,0,0,0}},
4896 addlst[2] = {{sizeof newace, OSS$_ACL_ADD_ENTRY, &newace, 0},{0,0,0,0}},
4897 dellst[2] = {{sizeof newace, OSS$_ACL_DELETE_ENTRY, &newace, 0},
4898 {0,0,0,0}};
4899
4900
4901
4902
4903 vmsname = PerlMem_malloc(NAM$C_MAXRSS+1);
4904 if (vmsname == NULL)
4905 return SS$_INSFMEM;
4906
4907 rslt = do_rmsexpand(vms_src_dsc->dsc$a_pointer,
4908 vmsname,
4909 0,
4910 NULL,
4911 PERL_RMSEXPAND_M_VMS | PERL_RMSEXPAND_M_SYMLINK,
4912 NULL,
4913 NULL);
4914 if (rslt == NULL) {
4915 PerlMem_free(vmsname);
4916 return SS$_INSFMEM;
4917 }
4918
4919
4920
4921
4922
4923 _ckvmssts(lib$getjpi(&jpicode,0,0,&(oldace.myace$l_ident),0,0));
4924
4925 fildsc.dsc$w_length = strlen(vmsname);
4926 fildsc.dsc$a_pointer = vmsname;
4927 ctx = 0;
4928 newace.myace$l_ident = oldace.myace$l_ident;
4929 rnsts = SS$_ABORT;
4930
4931
4932 clean_dsc = &fildsc;
4933 aclsts = fndsts = sys$get_security(&obj_file_dsc,
4934 &fildsc,
4935 NULL,
4936 OSS$M_WLOCK,
4937 findlst,
4938 &ctx,
4939 &access_mode);
4940
4941 if ($VMS_STATUS_SUCCESS(fndsts) || (fndsts == SS$_ACLEMPTY)) {
4942
4943
4944
4945
4946
4947
4948 aclsts = sys$set_security(&obj_file_dsc, &fildsc, NULL,
4949 OSS$M_RELCTX, addlst, &ctx, &access_mode);
4950 if (!$VMS_STATUS_SUCCESS(aclsts) && (aclsts != SS$_NOCLASS)) {
4951 set_errno(EVMSERR);
4952 set_vaxc_errno(aclsts);
4953 PerlMem_free(vmsname);
4954 return aclsts;
4955 }
4956
4957 rnsts = lib$rename_file(vms_src_dsc, vms_dst_dsc,
4958 NULL, NULL,
4959 &flags,
4960 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
4961
4962 if ($VMS_STATUS_SUCCESS(rnsts)) {
4963 clean_dsc = (struct dsc$descriptor_s *)vms_dst_dsc;
4964 }
4965
4966
4967 ctx = 0;
4968 aclsts = sys$get_security(&obj_file_dsc,
4969 clean_dsc,
4970 NULL,
4971 OSS$M_WLOCK,
4972 findlst,
4973 &ctx,
4974 &access_mode);
4975
4976 if ($VMS_STATUS_SUCCESS(aclsts)) {
4977 int sec_flags;
4978
4979 sec_flags = 0;
4980 if (!$VMS_STATUS_SUCCESS(fndsts))
4981 sec_flags = OSS$M_RELCTX;
4982
4983
4984 aclsts = sys$set_security(NULL, NULL, NULL,
4985 sec_flags, dellst, &ctx, &access_mode);
4986
4987
4988 if ($VMS_STATUS_SUCCESS(aclsts) && $VMS_STATUS_SUCCESS(fndsts)) {
4989 addlst[0].bufadr = &oldace;
4990 aclsts = sys$set_security(NULL, NULL, NULL,
4991 OSS$M_RELCTX, addlst, &ctx, &access_mode);
4992 if (!$VMS_STATUS_SUCCESS(aclsts) && (aclsts != SS$_NOCLASS)) {
4993 set_errno(EVMSERR);
4994 set_vaxc_errno(aclsts);
4995 rnsts = aclsts;
4996 }
4997 } else {
4998 int aclsts2;
4999
5000
5001 aclsts2 = sys$set_security(NULL, NULL, NULL,
5002 OSS$M_RELCTX, NULL, &ctx, &access_mode);
5003
5004
5005 if (!$VMS_STATUS_SUCCESS(rnsts))
5006 aclsts = rnsts;
5007 set_errno(EVMSERR);
5008 set_vaxc_errno(aclsts);
5009 rnsts = aclsts;
5010 }
5011 }
5012 else {
5013 if (aclsts != SS$_ACLEMPTY)
5014 rnsts = aclsts;
5015 }
5016 }
5017 else
5018 rnsts = fndsts;
5019
5020 PerlMem_free(vmsname);
5021 return rnsts;
5022}
5023
5024
5025
5026
5027
5028
5029
5030int
5031Perl_rename(pTHX_ const char *src, const char * dst)
5032{
5033int retval;
5034int pre_delete = 0;
5035int src_sts;
5036int dst_sts;
5037Stat_t src_st;
5038Stat_t dst_st;
5039
5040
5041 src_sts = flex_lstat(src, &src_st);
5042 if (src_sts != 0) {
5043
5044
5045 return src_sts;
5046 }
5047
5048 dst_sts = flex_lstat(dst, &dst_st);
5049 if (dst_sts == 0) {
5050
5051 if (dst_st.st_dev != src_st.st_dev) {
5052
5053 errno = EXDEV;
5054 return -1;
5055 }
5056
5057
5058
5059
5060
5061 if (!VMS_INO_T_COMPARE(src_st.st_ino, dst_st.st_ino)) {
5062
5063 return 0;
5064 }
5065
5066 if (S_ISDIR(src_st.st_mode) && !S_ISDIR(dst_st.st_mode)) {
5067
5068 errno = EISDIR;
5069 return -1;
5070 }
5071
5072 }
5073
5074
5075 if ((dst_sts == 0) &&
5076 (vms_unlink_all_versions || S_ISDIR(dst_st.st_mode))) {
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090 if (!S_ISDIR(dst_st.st_mode) || S_ISDIR(src_st.st_mode)) {
5091 int d_sts;
5092 d_sts = mp_do_kill_file(aTHX_ dst, S_ISDIR(dst_st.st_mode));
5093 if (d_sts != 0)
5094 return d_sts;
5095
5096
5097 pre_delete = 1;
5098 }
5099 }
5100
5101
5102
5103
5104
5105
5106 retval = -1;
5107
5108 {
5109
5110
5111
5112
5113 char * vms_src;
5114 char * vms_dst;
5115 int sts;
5116 char * ret_str;
5117 unsigned long flags;
5118 struct dsc$descriptor_s old_file_dsc;
5119 struct dsc$descriptor_s new_file_dsc;
5120
5121
5122
5123
5124
5125 vms_src = PerlMem_malloc(VMS_MAXRSS);
5126 if (vms_src == NULL)
5127 _ckvmssts(SS$_INSFMEM);
5128
5129
5130 ret_str = do_tovmsspec(src, vms_src, 0, NULL);
5131 if (ret_str == NULL) {
5132 PerlMem_free(vms_src);
5133 errno = EIO;
5134 return -1;
5135 }
5136
5137 vms_dst = PerlMem_malloc(VMS_MAXRSS);
5138 if (vms_dst == NULL)
5139 _ckvmssts(SS$_INSFMEM);
5140
5141 if (S_ISDIR(src_st.st_mode)) {
5142 char * ret_str;
5143 char * vms_dir_file;
5144
5145 vms_dir_file = PerlMem_malloc(VMS_MAXRSS);
5146 if (vms_dir_file == NULL)
5147 _ckvmssts(SS$_INSFMEM);
5148
5149
5150 ret_str = do_fileify_dirspec(vms_src, vms_dir_file, 0, NULL);
5151 if (ret_str == NULL) {
5152 PerlMem_free(vms_src);
5153 PerlMem_free(vms_dst);
5154 PerlMem_free(vms_dir_file);
5155 errno = EIO;
5156 return -1;
5157 }
5158 PerlMem_free(vms_src);
5159 vms_src = vms_dir_file;
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176 ret_str = do_tovmsspec(dst, vms_dst, 0, NULL);
5177 if (ret_str == NULL) {
5178 PerlMem_free(vms_src);
5179 PerlMem_free(vms_dst);
5180 errno = EIO;
5181 return -1;
5182 }
5183
5184
5185 vms_dir_file = PerlMem_malloc(VMS_MAXRSS);
5186 if (vms_dir_file == NULL)
5187 _ckvmssts(SS$_INSFMEM);
5188
5189 ret_str = do_fileify_dirspec(vms_dst, vms_dir_file, 0, NULL);
5190 if (ret_str == NULL) {
5191 PerlMem_free(vms_src);
5192 PerlMem_free(vms_dst);
5193 PerlMem_free(vms_dir_file);
5194 errno = EIO;
5195 return -1;
5196 }
5197 PerlMem_free(vms_dst);
5198 vms_dst = vms_dir_file;
5199
5200 } else {
5201
5202
5203 if ((dst_sts == 0) && S_ISDIR(dst_st.st_mode)) {
5204
5205 ret_str = do_tovmspath(dst, vms_dst, 0, NULL);
5206 if (ret_str == NULL) {
5207 PerlMem_free(vms_src);
5208 PerlMem_free(vms_dst);
5209 errno = EIO;
5210 return -1;
5211 }
5212 } else {
5213
5214
5215 ret_str = do_tovmsspec(dst, vms_dst, 0, NULL);
5216 if (ret_str == NULL) {
5217 PerlMem_free(vms_src);
5218 PerlMem_free(vms_dst);
5219 errno = EIO;
5220 return -1;
5221 }
5222 }
5223 }
5224
5225 old_file_dsc.dsc$a_pointer = vms_src;
5226 old_file_dsc.dsc$w_length = strlen(vms_src);
5227 old_file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
5228 old_file_dsc.dsc$b_class = DSC$K_CLASS_S;
5229
5230 new_file_dsc.dsc$a_pointer = vms_dst;
5231 new_file_dsc.dsc$w_length = strlen(vms_dst);
5232 new_file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
5233 new_file_dsc.dsc$b_class = DSC$K_CLASS_S;
5234
5235 flags = 0;
5236#if !defined(__VAX) && defined(NAML$C_MAXRSS)
5237 flags |= 2;
5238#endif
5239
5240 sts = lib$rename_file(&old_file_dsc,
5241 &new_file_dsc,
5242 NULL, NULL,
5243 &flags,
5244 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
5245 if (!$VMS_STATUS_SUCCESS(sts)) {
5246
5247
5248
5249
5250
5251 sts = vms_rename_with_acl(aTHX_ &old_file_dsc, &new_file_dsc, flags);
5252 }
5253
5254 PerlMem_free(vms_src);
5255 PerlMem_free(vms_dst);
5256 if (!$VMS_STATUS_SUCCESS(sts)) {
5257 errno = EIO;
5258 return -1;
5259 }
5260 retval = 0;
5261 }
5262
5263 if (vms_unlink_all_versions) {
5264
5265
5266
5267 int save_errno;
5268 save_errno = errno;
5269 src_sts = mp_do_kill_file(aTHX_ src, S_ISDIR(src_st.st_mode));
5270 errno = save_errno;
5271 }
5272
5273
5274 if ((retval != 0) && (pre_delete != 0))
5275 errno = EIO;
5276
5277 return retval;
5278}
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300static char *mp_do_tounixspec(pTHX_ const char *, char *, int, int *);
5301
5302static char *
5303mp_do_rmsexpand
5304 (pTHX_ const char *filespec,
5305 char *outbuf,
5306 int ts,
5307 const char *defspec,
5308 unsigned opts,
5309 int * fs_utf8,
5310 int * dfs_utf8)
5311{
5312 static char __rmsexpand_retbuf[VMS_MAXRSS];
5313 char * vmsfspec, *tmpfspec;
5314 char * esa, *cp, *out = NULL;
5315 char * tbuf;
5316 char * esal = NULL;
5317 char * outbufl;
5318 struct FAB myfab = cc$rms_fab;
5319 rms_setup_nam(mynam);
5320 STRLEN speclen;
5321 unsigned long int retsts, trimver, trimtype, haslower = 0, isunix = 0;
5322 int sts;
5323
5324
5325 if (fs_utf8 != NULL)
5326 *fs_utf8 = 0;
5327
5328 if (!filespec || !*filespec) {
5329 set_vaxc_errno(LIB$_INVARG); set_errno(EINVAL);
5330 return NULL;
5331 }
5332 if (!outbuf) {
5333 if (ts) out = Newx(outbuf,VMS_MAXRSS,char);
5334 else outbuf = __rmsexpand_retbuf;
5335 }
5336
5337 vmsfspec = NULL;
5338 tmpfspec = NULL;
5339 outbufl = NULL;
5340
5341 isunix = 0;
5342 if ((opts & PERL_RMSEXPAND_M_VMS_IN) == 0) {
5343 isunix = is_unix_filespec(filespec);
5344 if (isunix) {
5345 vmsfspec = PerlMem_malloc(VMS_MAXRSS);
5346 if (vmsfspec == NULL) _ckvmssts(SS$_INSFMEM);
5347 if (do_tovmsspec(filespec,vmsfspec,0,fs_utf8) == NULL) {
5348 PerlMem_free(vmsfspec);
5349 if (out)
5350 Safefree(out);
5351 return NULL;
5352 }
5353 filespec = vmsfspec;
5354
5355
5356
5357
5358#if !defined(__VAX) && defined(NAML$C_MAXRSS)
5359 if ((opts & PERL_RMSEXPAND_M_VMS) == 0)
5360 opts |= PERL_RMSEXPAND_M_LONG;
5361 else
5362#endif
5363 isunix = 0;
5364 }
5365 }
5366
5367 rms_set_fna(myfab, mynam, (char *)filespec, strlen(filespec));
5368 rms_bind_fab_nam(myfab, mynam);
5369
5370 if (defspec && *defspec) {
5371 int t_isunix;
5372 t_isunix = is_unix_filespec(defspec);
5373 if (t_isunix) {
5374 tmpfspec = PerlMem_malloc(VMS_MAXRSS);
5375 if (tmpfspec == NULL) _ckvmssts(SS$_INSFMEM);
5376 if (do_tovmsspec(defspec,tmpfspec,0,dfs_utf8) == NULL) {
5377 PerlMem_free(tmpfspec);
5378 if (vmsfspec != NULL)
5379 PerlMem_free(vmsfspec);
5380 if (out)
5381 Safefree(out);
5382 return NULL;
5383 }
5384 defspec = tmpfspec;
5385 }
5386 rms_set_dna(myfab, mynam, (char *)defspec, strlen(defspec));
5387 }
5388
5389 esa = PerlMem_malloc(NAM$C_MAXRSS + 1);
5390 if (esa == NULL) _ckvmssts(SS$_INSFMEM);
5391#if !defined(__VAX) && defined(NAML$C_MAXRSS)
5392 esal = PerlMem_malloc(VMS_MAXRSS);
5393 if (esal == NULL) _ckvmssts(SS$_INSFMEM);
5394#endif
5395 rms_set_esal(mynam, esa, NAM$C_MAXRSS, esal, VMS_MAXRSS-1);
5396
5397
5398
5399
5400#if !defined(__VAX) && defined(NAML$C_MAXRSS)
5401 outbufl = PerlMem_malloc(VMS_MAXRSS);
5402 if (outbufl == NULL) _ckvmssts(SS$_INSFMEM);
5403#endif
5404 rms_set_rsal(mynam, outbuf, NAM$C_MAXRSS, outbufl, (VMS_MAXRSS - 1));
5405
5406#ifdef NAM$M_NO_SHORT_UPCASE
5407 if (decc_efs_case_preserve)
5408 rms_set_nam_nop(mynam, NAM$M_NO_SHORT_UPCASE);
5409#endif
5410
5411
5412#ifdef NAML$M_OPEN_SPECIAL
5413 if ((opts & PERL_RMSEXPAND_M_SYMLINK) != 0)
5414 rms_set_nam_nop(mynam, NAML$M_OPEN_SPECIAL);
5415#endif
5416
5417
5418 retsts = sys$parse(&myfab,0,0);
5419 if (!(retsts & STS$K_SUCCESS)) {
5420
5421
5422 rms_set_nam_nop(mynam, NAM$M_SYNCHK);
5423 if (retsts == RMS$_DNF || retsts == RMS$_DIR || retsts == RMS$_DEV) {
5424 retsts = sys$parse(&myfab,0,0);
5425 if (retsts & STS$K_SUCCESS) goto expanded;
5426 }
5427
5428
5429
5430 sts = rms_free_search_context(&myfab);
5431 if (out) Safefree(out);
5432 if (tmpfspec != NULL)
5433 PerlMem_free(tmpfspec);
5434 if (vmsfspec != NULL)
5435 PerlMem_free(vmsfspec);
5436 if (outbufl != NULL)
5437 PerlMem_free(outbufl);
5438 PerlMem_free(esa);
5439 if (esal != NULL)
5440 PerlMem_free(esal);
5441 set_vaxc_errno(retsts);
5442 if (retsts == RMS$_PRV) set_errno(EACCES);
5443 else if (retsts == RMS$_DEV) set_errno(ENODEV);
5444 else if (retsts == RMS$_DIR) set_errno(ENOTDIR);
5445 else set_errno(EVMSERR);
5446 return NULL;
5447 }
5448 retsts = sys$search(&myfab,0,0);
5449 if (!(retsts & STS$K_SUCCESS) && retsts != RMS$_FNF) {
5450 sts = rms_free_search_context(&myfab);
5451 if (out) Safefree(out);
5452 if (tmpfspec != NULL)
5453 PerlMem_free(tmpfspec);
5454 if (vmsfspec != NULL)
5455 PerlMem_free(vmsfspec);
5456 if (outbufl != NULL)
5457 PerlMem_free(outbufl);
5458 PerlMem_free(esa);
5459 if (esal != NULL)
5460 PerlMem_free(esal);
5461 set_vaxc_errno(retsts);
5462 if (retsts == RMS$_PRV) set_errno(EACCES);
5463 else set_errno(EVMSERR);
5464 return NULL;
5465 }
5466
5467
5468
5469 expanded:
5470 if (!decc_efs_case_preserve) {
5471 for (tbuf = rms_get_fna(myfab, mynam); *tbuf; tbuf++)
5472 if (islower(*tbuf)) { haslower = 1; break; }
5473 }
5474
5475
5476
5477 if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
5478 if (rms_nam_rsll(mynam)) {
5479 tbuf = outbufl;
5480 speclen = rms_nam_rsll(mynam);
5481 }
5482 else {
5483 tbuf = esal;
5484 speclen = rms_nam_esll(mynam);
5485 }
5486 }
5487 else {
5488 if (rms_nam_rsl(mynam)) {
5489 tbuf = outbuf;
5490 speclen = rms_nam_rsl(mynam);
5491 }
5492 else {
5493 tbuf = esa;
5494 speclen = rms_nam_esl(mynam);
5495 }
5496 }
5497 tbuf[speclen] = '\0';
5498
5499
5500
5501
5502
5503 trimver = !rms_is_nam_fnb(mynam, NAM$M_EXP_VER);
5504 if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
5505 trimtype = !rms_is_nam_fnb(mynam, NAM$M_EXP_TYPE) &&
5506 ((rms_nam_verl(mynam) - rms_nam_typel(mynam)) == 1);
5507 }
5508 else {
5509 trimtype = !rms_is_nam_fnb(mynam, NAM$M_EXP_TYPE) &&
5510 ((rms_nam_ver(mynam) - rms_nam_type(mynam)) == 1);
5511 }
5512 if (trimver || trimtype) {
5513 if (defspec && *defspec) {
5514 char *defesal = NULL;
5515 char *defesa = NULL;
5516 defesa = PerlMem_malloc(VMS_MAXRSS + 1);
5517 if (defesa != NULL) {
5518#if !defined(__VAX) && defined(NAML$C_MAXRSS)
5519 defesal = PerlMem_malloc(VMS_MAXRSS + 1);
5520 if (defesal == NULL) _ckvmssts(SS$_INSFMEM);
5521#endif
5522 struct FAB deffab = cc$rms_fab;
5523 rms_setup_nam(defnam);
5524
5525 rms_bind_fab_nam(deffab, defnam);
5526
5527
5528 rms_set_fna
5529 (deffab, defnam, (char *)defspec, rms_nam_dns(myfab, mynam));
5530
5531
5532 rms_set_esal(defnam, defesa, NAM$C_MAXRSS, defesal, VMS_MAXRSS - 1);
5533
5534 rms_clear_nam_nop(defnam);
5535 rms_set_nam_nop(defnam, NAM$M_SYNCHK);
5536#ifdef NAM$M_NO_SHORT_UPCASE
5537 if (decc_efs_case_preserve)
5538 rms_set_nam_nop(defnam, NAM$M_NO_SHORT_UPCASE);
5539#endif
5540#ifdef NAML$M_OPEN_SPECIAL
5541 if ((opts & PERL_RMSEXPAND_M_SYMLINK) != 0)
5542 rms_set_nam_nop(mynam, NAML$M_OPEN_SPECIAL);
5543#endif
5544 if (sys$parse(&deffab,0,0) & STS$K_SUCCESS) {
5545 if (trimver) {
5546 trimver = !rms_is_nam_fnb(defnam, NAM$M_EXP_VER);
5547 }
5548 if (trimtype) {
5549 trimtype = !rms_is_nam_fnb(defnam, NAM$M_EXP_TYPE);
5550 }
5551 }
5552 if (defesal != NULL)
5553 PerlMem_free(defesal);
5554 PerlMem_free(defesa);
5555 }
5556 }
5557 if (trimver) {
5558 if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
5559 if (*(rms_nam_verl(mynam)) != '\"')
5560 speclen = rms_nam_verl(mynam) - tbuf;
5561 }
5562 else {
5563 if (*(rms_nam_ver(mynam)) != '\"')
5564 speclen = rms_nam_ver(mynam) - tbuf;
5565 }
5566 }
5567 if (trimtype) {
5568
5569 if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
5570 if (speclen > rms_nam_verl(mynam) - tbuf)
5571 memmove
5572 (rms_nam_typel(mynam),
5573 rms_nam_verl(mynam),
5574 speclen - (rms_nam_verl(mynam) - tbuf));
5575 speclen -= rms_nam_verl(mynam) - rms_nam_typel(mynam);
5576 }
5577 else {
5578 if (speclen > rms_nam_ver(mynam) - tbuf)
5579 memmove
5580 (rms_nam_type(mynam),
5581 rms_nam_ver(mynam),
5582 speclen - (rms_nam_ver(mynam) - tbuf));
5583 speclen -= rms_nam_ver(mynam) - rms_nam_type(mynam);
5584 }
5585 }
5586 }
5587
5588
5589
5590 if (vmsfspec != NULL)
5591 PerlMem_free(vmsfspec);
5592 if (tmpfspec != NULL)
5593 PerlMem_free(tmpfspec);
5594
5595
5596
5597#if !defined(__VAX) && defined(NAML$C_MAXRSS)
5598 if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
5599 if (rms_nam_namel(mynam) == rms_nam_typel(mynam) &&
5600 rms_nam_verl(mynam) == rms_nam_typel(mynam) + 1 &&
5601 !(rms_is_nam_fnb(mynam, NAM$M_EXP_NAME)))
5602 speclen = rms_nam_namel(mynam) - tbuf;
5603 }
5604 else
5605#endif
5606 {
5607 if (rms_nam_name(mynam) == rms_nam_type(mynam) &&
5608 rms_nam_ver(mynam) == rms_nam_ver(mynam) + 1 &&
5609 !(rms_is_nam_fnb(mynam, NAM$M_EXP_NAME)))
5610 speclen = rms_nam_name(mynam) - tbuf;
5611 }
5612
5613
5614 if (speclen < (VMS_MAXRSS - 1)) {
5615 if (decc_posix_compliant_pathnames && (tbuf[0] == '\"')) {
5616 if ((speclen > 1) && (tbuf[speclen-1] != '\"')) {
5617 tbuf[speclen] = '\"';
5618 speclen++;
5619 }
5620 }
5621 }
5622 tbuf[speclen] = '\0';
5623 if (haslower && !decc_efs_case_preserve) __mystrtolower(tbuf);
5624
5625
5626
5627 {
5628 int rsl;
5629
5630#if !defined(__VAX) && defined(NAML$C_MAXRSS)
5631 if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
5632 rsl = rms_nam_rsll(mynam);
5633 } else
5634#endif
5635 {
5636 rsl = rms_nam_rsl(mynam);
5637 }
5638 if (!rsl) {
5639 if (isunix) {
5640 if (do_tounixspec(tbuf, outbuf ,0 , fs_utf8) == NULL) {
5641 if (out) Safefree(out);
5642 if (esal != NULL)
5643 PerlMem_free(esal);
5644 PerlMem_free(esa);
5645 if (outbufl != NULL)
5646 PerlMem_free(outbufl);
5647 return NULL;
5648 }
5649 }
5650 else strcpy(outbuf, tbuf);
5651 }
5652 else if (isunix) {
5653 tmpfspec = PerlMem_malloc(VMS_MAXRSS);
5654 if (tmpfspec == NULL) _ckvmssts(SS$_INSFMEM);
5655 if (do_tounixspec(tbuf,tmpfspec,0,fs_utf8) == NULL) {
5656 if (out) Safefree(out);
5657 PerlMem_free(esa);
5658 if (esal != NULL)
5659 PerlMem_free(esal);
5660 PerlMem_free(tmpfspec);
5661 if (outbufl != NULL)
5662 PerlMem_free(outbufl);
5663 return NULL;
5664 }
5665 strcpy(outbuf,tmpfspec);
5666 PerlMem_free(tmpfspec);
5667 }
5668 }
5669 rms_set_rsal(mynam, NULL, 0, NULL, 0);
5670 sts = rms_free_search_context(&myfab);
5671 PerlMem_free(esa);
5672 if (esal != NULL)
5673 PerlMem_free(esal);
5674 if (outbufl != NULL)
5675 PerlMem_free(outbufl);
5676 return outbuf;
5677}
5678
5679
5680char *Perl_rmsexpand(pTHX_ const char *spec, char *buf, const char *def, unsigned opt)
5681{ return do_rmsexpand(spec,buf,0,def,opt,NULL,NULL); }
5682char *Perl_rmsexpand_ts(pTHX_ const char *spec, char *buf, const char *def, unsigned opt)
5683{ return do_rmsexpand(spec,buf,1,def,opt,NULL,NULL); }
5684char *Perl_rmsexpand_utf8
5685 (pTHX_ const char *spec, char *buf, const char *def,
5686 unsigned opt, int * fs_utf8, int * dfs_utf8)
5687{ return do_rmsexpand(spec,buf,0,def,opt, fs_utf8, dfs_utf8); }
5688char *Perl_rmsexpand_utf8_ts
5689 (pTHX_ const char *spec, char *buf, const char *def,
5690 unsigned opt, int * fs_utf8, int * dfs_utf8)
5691{ return do_rmsexpand(spec,buf,1,def,opt, fs_utf8, dfs_utf8); }
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts, int *utf8_fl)
5731{
5732 static char __fileify_retbuf[VMS_MAXRSS];
5733 unsigned long int dirlen, retlen, addmfd = 0, hasfilename = 0;
5734 char *retspec, *cp1, *cp2, *lastdir;
5735 char *trndir, *vmsdir;
5736 unsigned short int trnlnm_iter_count;
5737 int sts;
5738 if (utf8_fl != NULL)
5739 *utf8_fl = 0;
5740
5741 if (!dir || !*dir) {
5742 set_errno(EINVAL); set_vaxc_errno(SS$_BADPARAM); return NULL;
5743 }
5744 dirlen = strlen(dir);
5745 while (dirlen && dir[dirlen-1] == '/') --dirlen;
5746 if (!dirlen) {
5747 if (!decc_posix_compliant_pathnames && decc_disable_posix_root) {
5748 dir = "/sys$disk";
5749 dirlen = 9;
5750 }
5751 else
5752 dirlen = 1;
5753 }
5754 if (dirlen > (VMS_MAXRSS - 1)) {
5755 set_errno(ENAMETOOLONG); set_vaxc_errno(RMS$_SYN);
5756 return NULL;
5757 }
5758 trndir = PerlMem_malloc(VMS_MAXRSS + 1);
5759 if (trndir == NULL) _ckvmssts(SS$_INSFMEM);
5760 if (!strpbrk(dir+1,"/]>:") &&
5761 (!decc_posix_compliant_pathnames && decc_disable_posix_root)) {
5762 strcpy(trndir,*dir == '/' ? dir + 1: dir);
5763 trnlnm_iter_count = 0;
5764 while (!strpbrk(trndir,"/]>:") && my_trnlnm(trndir,trndir,0)) {
5765 trnlnm_iter_count++;
5766 if (trnlnm_iter_count >= PERL_LNM_MAX_ITER) break;
5767 }
5768 dirlen = strlen(trndir);
5769 }
5770 else {
5771 strncpy(trndir,dir,dirlen);
5772 trndir[dirlen] = '\0';
5773 }
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785 if (dirlen >= 2 && !strcmp(trndir+dirlen-2,".]")) {
5786 trndir[--dirlen] = '\0';
5787 trndir[dirlen-1] = ']';
5788 }
5789 if (dirlen >= 2 && !strcmp(trndir+dirlen-2,".>")) {
5790 trndir[--dirlen] = '\0';
5791 trndir[dirlen-1] = '>';
5792 }
5793
5794 if ((cp1 = strrchr(trndir,']')) != NULL || (cp1 = strrchr(trndir,'>')) != NULL) {
5795
5796 if (*(cp1+1)) hasfilename = 1;
5797
5798
5799 else {
5800 for (cp2 = cp1; cp2 > trndir; cp2--) {
5801 if (*cp2 == '.') {
5802 if ((cp2 - 1 > trndir) && (*(cp2 - 1) != '^')) {
5803
5804 *cp2 = *cp1; *cp1 = '\0';
5805 hasfilename = 1;
5806 break;
5807 }
5808 }
5809 if (*cp2 == '[' || *cp2 == '<') break;
5810 }
5811 }
5812 }
5813
5814 vmsdir = PerlMem_malloc(VMS_MAXRSS + 1);
5815 if (vmsdir == NULL) _ckvmssts(SS$_INSFMEM);
5816 cp1 = strpbrk(trndir,"]:>");
5817 if (hasfilename || !cp1) {
5818 if (trndir[0] == '.') {
5819 if (trndir[1] == '\0' || (trndir[1] == '/' && trndir[2] == '\0')) {
5820 PerlMem_free(trndir);
5821 PerlMem_free(vmsdir);
5822 return do_fileify_dirspec("[]",buf,ts,NULL);
5823 }
5824 else if (trndir[1] == '.' &&
5825 (trndir[2] == '\0' || (trndir[2] == '/' && trndir[3] == '\0'))) {
5826 PerlMem_free(trndir);
5827 PerlMem_free(vmsdir);
5828 return do_fileify_dirspec("[-]",buf,ts,NULL);
5829 }
5830 }
5831 if (dirlen && trndir[dirlen-1] == '/') {
5832 dirlen -= 1;
5833 lastdir = strrchr(trndir,'/');
5834 }
5835 else if ((cp1 = strstr(trndir,"/.")) != NULL) {
5836
5837
5838
5839 do {
5840 if (*(cp1+2) == '.') cp1++;
5841 if (*(cp1+2) == '/' || *(cp1+2) == '\0') {
5842 char * ret_chr;
5843 if (do_tovmsspec(trndir,vmsdir,0,NULL) == NULL) {
5844 PerlMem_free(trndir);
5845 PerlMem_free(vmsdir);
5846 return NULL;
5847 }
5848 if (strchr(vmsdir,'/') != NULL) {
5849
5850
5851
5852
5853
5854 PerlMem_free(trndir);
5855 PerlMem_free(vmsdir);
5856 set_errno(EINVAL); set_vaxc_errno(RMS$_SYN);
5857 return NULL;
5858 }
5859 if (do_fileify_dirspec(vmsdir,trndir,0,NULL) == NULL) {
5860 PerlMem_free(trndir);
5861 PerlMem_free(vmsdir);
5862 return NULL;
5863 }
5864 ret_chr = do_tounixspec(trndir,buf,ts,NULL);
5865 PerlMem_free(trndir);
5866 PerlMem_free(vmsdir);
5867 return ret_chr;
5868 }
5869 cp1++;
5870 } while ((cp1 = strstr(cp1,"/.")) != NULL);
5871 lastdir = strrchr(trndir,'/');
5872 }
5873 else if (dirlen >= 7 && !strcmp(&trndir[dirlen-7],"/000000")) {
5874 char * ret_chr;
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884 trndir[dirlen] = '/'; trndir[dirlen+1] = '\0';
5885 if (do_tovmsspec(trndir,