2 * VMS supplement for "wget".
4 *======================================================================
8 * On non-VAX systems, uses LIB$INITIALIZE to set a collection of C
9 * RTL features without using the DECC$* logical name method.
11 *----------------------------------------------------------------------
15 * Returns (run-time) VMS architecture string.
17 *----------------------------------------------------------------------
21 * Returns the basename from a VMS file spec.
23 *----------------------------------------------------------------------
27 * VMS-specific substitute for GNU getpass().
29 *----------------------------------------------------------------------
33 * Returns (run-time) VMS version string.
35 *----------------------------------------------------------------------
39 * Sets a global flag ("ods5_dest") according to the file system type
40 * of the destination device.
42 *----------------------------------------------------------------------
46 * Simplifies a fancy URL-derived file name into an ODS2- or
47 * ODS5-compatible file name.
49 *----------------------------------------------------------------------
53 * VMS C RTL before V7.3 lacks utime(). In V7.3, utime() sets only
54 * the modified (revised) date, not the created date of a file.
56 * UNIX "ls -l" reports the modified time. VMS "DIRECTORY /DATE"
57 * reports the creation time. Reconciling these in FTP DIR reports
60 * UNIX utime() sets revision and access times. VMS does not always
61 * maintain access times, so this utime() replacement sets the
62 * creation and revision times to the specified revision (or
63 * creation?) time. Any access time is ignored.
65 *----------------------------------------------------------------------
69 * VMS C RTL before V7.0 lacks getpwuid().
71 *----------------------------------------------------------------------
96 #include <lib$routines.h>
99 /* Use <iosbdef.h> if available. Otherwise declare IOSB here. */
101 #if !defined( __VAX) && (__CRTL_VER >= 70000000)
103 #else /* __CRTL_VER >= 70000000 */
104 typedef struct _iosb {
105 unsigned short int iosb$w_status; /* Final I/O status */
106 unsigned short int iosb$w_bcnt; /* 16-bit byte count */
107 unsigned int iosb$l_dev_depend; /* 32-bit dev dependent */
109 #endif /* !defined( __VAX) && (__CRTL_VER >= 70000000) */
111 /* Ugly work-around for bad type in VAX <atrdef.h>. */
114 #define UWA (unsigned int)
115 #else /* def __VAX */
117 #endif /* def __VAX */
124 /* Define macros for use with either NAM or NAML. */
126 #ifdef NAML$C_MAXRSS /* NAML is available. Use it. */
128 # define NAM_STRUCT NAML
130 # define FAB_OR_NAML( fab, nam) nam
131 # define FAB_OR_NAML_FNA naml$l_long_filename
132 # define FAB_OR_NAML_FNS naml$l_long_filename_size
134 # define CC_RMS_NAM cc$rms_naml
135 # define FAB_NAM fab$l_naml
136 # define NAM_ESA naml$l_long_expand
137 # define NAM_ESL naml$l_long_expand_size
138 # define NAM_ESS naml$l_long_expand_alloc
139 # define NAM_RSA naml$l_long_result
140 # define NAM_RSL naml$l_long_result_size
141 # define NAM_RSS naml$l_long_result_alloc
142 # define NAM_MAXRSS NAML$C_MAXRSS
143 # define NAM_NOP naml$b_nop
144 # define NAM_M_SYNCHK NAML$M_SYNCHK
145 # define NAM_B_NAME naml$l_long_name_size
146 # define NAM_L_NAME naml$l_long_name
148 #else /* def NAML$C_MAXRSS */ /* NAML is not available. Use NAM. */
150 # define NAM_STRUCT NAM
152 # define FAB_OR_NAML( fab, nam) fab
153 # define FAB_OR_NAML_FNA fab$l_fna
154 # define FAB_OR_NAML_FNS fab$b_fns
156 # define CC_RMS_NAM cc$rms_nam
157 # define FAB_NAM fab$l_nam
158 # define NAM_ESA nam$l_esa
159 # define NAM_ESL nam$b_esl
160 # define NAM_ESS nam$b_ess
161 # define NAM_RSA nam$l_rsa
162 # define NAM_RSL nam$b_rsl
163 # define NAM_RSS nam$b_rss
164 # define NAM_MAXRSS NAM$C_MAXRSS
165 # define NAM_NOP nam$b_nop
166 # define NAM_M_SYNCHK NAM$M_SYNCHK
167 # define NAM_B_NAME nam$b_name
168 # define NAM_L_NAME nam$l_name
170 #endif /* def NAML$C_MAXRSS */
172 /*--------------------------------------------------------------------*/
174 /* Global storage. */
176 /* Flag for an ODS5 destination directory. */
180 /* Flag to sense if vms_init() was called. */
182 int vms_init_done = -1;
184 /*--------------------------------------------------------------------*/
186 #if !defined( __VAX) && (__CRTL_VER >= 70301000)
190 Uses LIB$INITIALIZE to set a collection of C RTL features without
191 requiring the user to define the corresponding logical names.
194 /* Structure to hold a DECC$* feature name and its desired value. */
202 /* Array of DECC$* feature names and their desired values. */
204 decc_feat_t decc_feat_array[] = {
205 /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
206 { "DECC$ARGV_PARSE_STYLE", 1 },
207 /* Preserve case for file names on ODS5 disks. */
208 { "DECC$EFS_CASE_PRESERVE", 1 },
209 /* Enable multiple dots (and most characters) in ODS5 file names,
210 while preserving VMS-ness of ";version". */
211 { "DECC$EFS_CHARSET", 1 },
212 /* List terminator. */
213 { (char *)NULL, 0 } };
215 /* LIB$INITIALIZE initialization function. */
217 static void vms_init( void)
226 /* Set the global flag to indicate that LIB$INITIALIZE worked. */
230 /* Loop through all items in the decc_feat_array[]. */
232 for (i = 0; decc_feat_array[ i].name != NULL; i++)
234 /* Get the feature index. */
235 feat_index = decc$feature_get_index( decc_feat_array[ i].name);
238 /* Valid item. Collect its properties. */
239 feat_value = decc$feature_get_value( feat_index, 1);
240 feat_value_min = decc$feature_get_value( feat_index, 2);
241 feat_value_max = decc$feature_get_value( feat_index, 3);
243 if ((decc_feat_array[ i].value >= feat_value_min) &&
244 (decc_feat_array[ i].value <= feat_value_max))
246 /* Valid value. Set it if necessary. */
247 if (feat_value != decc_feat_array[ i].value)
249 sts = decc$feature_set_value( feat_index,
251 decc_feat_array[ i].value);
256 /* Invalid DECC feature value. */
257 printf( " INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n",
259 feat_value_min, decc_feat_array[ i].name, feat_value_max);
264 /* Invalid DECC feature name. */
265 printf( " UNKNOWN DECC FEATURE: %s.\n", decc_feat_array[ i].name);
270 /* Get "vms_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
274 /* Establish the LIB$INITIALIZE PSECTs, with proper alignment and
275 other attributes. Note that "nopic" is significant only on VAX.
277 #pragma extern_model save
279 #pragma extern_model strict_refdef "LIB$INITIALIZE" 2, nopic, nowrt
280 void (*const x_vms_init)() = vms_init;
282 #pragma extern_model strict_refdef "LIB$INITIALIZ" 2, nopic, nowrt
283 const int spare[ 8] = { 0 };
285 #pragma extern_model restore
287 /* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
289 #pragma extern_model save
290 int lib$initialize(void);
291 #pragma extern_model strict_refdef
292 int dmy_lib$initialize = (int) lib$initialize;
293 #pragma extern_model restore
297 #endif /* !defined( __VAX) && (__CRTL_VER >= 70301000) */
299 /*--------------------------------------------------------------------*/
303 Returns (run-time) VMS architecture string.
306 char *vms_arch( void)
311 static char arch[ ARCH_SIZE+ 1] = "VAX"; /* Only VAX could fail. */
312 unsigned short arch_len;
314 struct dsc$descriptor_s arch_descr =
315 { ARCH_SIZE, DSC$K_DTYPE_T, DSC$K_CLASS_S, arch };
319 sts = lib$getsyi( &SYI$_ARCH_NAME, 0, &arch_descr, &arch_len, 0, 0);
320 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
322 arch[ arch_len] = '\0';
324 /* Trim trailing spaces. */
325 while ((arch_len > 0) && (arch[ arch_len- 1] == ' '))
327 arch[ --arch_len] = '\0';
334 /*--------------------------------------------------------------------*/
338 * Extract the basename from a VMS file spec.
341 char *vms_basename( char *file_spec)
343 /* Static storage for NAM[L], and so on. */
345 static struct NAM_STRUCT nam;
346 static char exp_name[ NAM_MAXRSS+ 1];
347 static char res_name[ NAM_MAXRSS+ 1];
352 /* Set up the FAB and NAM[L] blocks. */
354 fab = cc$rms_fab; /* Initialize FAB. */
355 nam = CC_RMS_NAM; /* Initialize NAM[L]. */
357 fab.FAB_NAM = &nam; /* FAB -> NAM[L] */
361 fab.fab$l_dna = (char *) -1; /* Using NAML for default name. */
362 fab.fab$l_fna = (char *) -1; /* Using NAML for file name. */
364 #endif /* def NAML$C_MAXRSS */
366 /* Arg name and length. */
367 FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = file_spec;
368 FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( file_spec);
370 nam.NAM_ESA = exp_name; /* Expanded name. */
371 nam.NAM_ESS = NAM_MAXRSS; /* Max length. */
372 nam.NAM_RSA = res_name; /* Resulting name. */
373 nam.NAM_RSS = NAM_MAXRSS; /* Max length. */
375 nam.NAM_NOP = NAM_M_SYNCHK; /* Syntax-only analysis. */
377 /* Parse the file name. */
378 status = sys$parse( &fab); /* What could go wrong? */
380 nam.NAM_L_NAME[ nam.NAM_B_NAME] = '\0';
382 return nam.NAM_L_NAME;
385 /*--------------------------------------------------------------------*/
391 * VMS-specific substitute for GNU getpass().
393 * Returns passpord in locally allocated string.
396 /* Terminal characteristics buffer structure. */
402 int basic_chars; /* (The high eight bits are page length.) */
406 /* Enable/disable terminal echo. */
408 int vms_set_term_echo( int able)
413 $DESCRIPTOR( term_dscr, "SYS$COMMAND");
414 term_chars_t term_chars;
415 static int initial_echo = -1;
417 /* Open a channel to the terminal device. */
418 sts = sys$assign( &term_dscr, /* Terminal device name. */
419 &term_chan, /* Channel. */
420 0, /* Access mode. */
423 /* Return immediately on failure. */
424 if ((sts& STS$M_SEVERITY) != STS$K_SUCCESS)
431 /* Get the current terminal characteristics (mode). */
432 sts = sys$qiow( 0, /* Event flag. */
433 term_chan, /* Channel. */
434 IO$_SENSEMODE, /* Function. */
436 0, /* AST address. */
437 0, /* AST parameter. */
438 &term_chars, /* P1 = Buffer address. */
439 sizeof term_chars, /* P2 = Buffer size. */
440 0, 0, 0, 0); /* P3-P6 not used. */
442 if ((sts& STS$M_SEVERITY) != STS$K_SUCCESS)
447 else if (term_chars.class != DC$_TERM)
453 /* Save the initial echo state, to allow proper restoration. */
454 if (initial_echo < 0)
456 initial_echo = ((term_chars.basic_chars& TT$M_NOECHO) == 0);
463 /* Was initially enabled. */
468 /* Was initially disabled. */
475 /* Disable. Set the no-echo bit. */
476 term_chars.basic_chars |= TT$M_NOECHO;
480 /* Enable. Clear the no-echo bit. */
481 term_chars.basic_chars &= ~TT$M_NOECHO;
484 /* Set the terminal characteristics (mode). */
485 sts = sys$qiow( 0, /* Event flag. */
486 term_chan, /* Channel. */
487 IO$_SETMODE, /* Function. */
489 0, /* AST address. */
490 0, /* AST parameter. */
491 &term_chars, /* P1 = Buffer address. */
492 sizeof term_chars, /* P2 = Buffer size. */
493 0, 0, 0, 0); /* P3-P6 not used. */
495 if ((sts& STS$M_SEVERITY) != STS$K_SUCCESS)
507 /* Close the channel to the terminal device. */
508 sts2 = sys$dassgn( term_chan); /* Channel. */
509 if ((sts2& STS$M_SEVERITY) != STS$K_SUCCESS)
511 /* If all was not well, leave the old error codes as were. */
514 /* All was well, but DASSGN failed. */
523 static char pw_buf[ PASS_MAX+ 1];
525 char *vms_getpass( const char *prompt)
533 sdc = fopen( "SYS$COMMAND", "r");
536 sts = vms_set_term_echo( 0);
539 /* Read password string. */
542 fprintf( stdout, "%s", prompt);
543 sts = fread( pw_buf, 1, PASS_MAX, sdc);
544 if ((sts > 0) && (pw_buf[ sts- 1]) == '\n')
546 pw_buf[ --sts] = '\0';
554 sts = vms_set_term_echo( -1);
561 /*--------------------------------------------------------------------*/
565 Returns (run-time) VMS version string.
568 char *vms_vers( void)
573 static char vers[ VERS_SIZE+ 1] = "";
574 unsigned short vers_len;
576 struct dsc$descriptor_s vers_descr =
577 { VERS_SIZE, DSC$K_DTYPE_T, DSC$K_CLASS_S, vers };
581 sts = lib$getsyi( &SYI$_VERSION, 0, &vers_descr, &vers_len, 0, 0);
582 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
584 vers[ vers_len] = '\0';
586 /* Trim trailing spaces. */
587 while ((vers_len > 0) && (vers[ vers_len- 1] == ' '))
589 vers[ --vers_len] = '\0';
596 /*--------------------------------------------------------------------*/
600 Sets global "ods5_dest" according to the file system type of the
601 argument: 0 for ODS2, 1 for ODS5. (No change if other/unknown or
604 Return value: Status from sys$getdvi().
607 int set_ods5_dest( char *path)
609 #ifdef DVI$C_ACP_F11V5
611 /* Should know about ODS5 file system. Do actual check.
612 (This should be non-VAX with __CRTL_VER >= 70200000.)
615 struct dsc$descriptor_s dev_descr =
616 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
621 /* Load path argument into device descriptor.
622 Default to current default device.
626 dev_descr.dsc$a_pointer = "SYS$DISK";
630 dev_descr.dsc$a_pointer = path;
632 dev_descr.dsc$w_length = strlen( dev_descr.dsc$a_pointer);
634 /* Get filesystem type code.
635 (Text results for this item code have been unreliable.)
637 sts = lib$getdvi( &((int) DVI$_ACPTYPE),
644 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
646 if (acp_code == DVI$C_ACP_F11V2)
650 else if (acp_code == DVI$C_ACP_F11V5)
658 #else /* def DVI$C_ACP_F11V5 */
660 /* Too old for ODS5 file system. Do nothing. */
662 return STS$K_SUCCESS;
664 #endif /* def DVI$C_ACP_F11V5 */
667 /*--------------------------------------------------------------------*/
671 Replace ODS2-troublesome characters in the argument, overwriting the
672 original string. Replace "~" with "-", "@" with "$", and invalid
673 dots and other characters with "_". (Invalid dots are any in a
674 directory name, and all but the last in a file name.)
676 Return value: path. (Someday this function could be written to leave
677 the original string unchanged, and to return a freshly allocated
678 string, possibly of a dfferent length.)
681 Changed to use char_prop[] look-up table, and to convert more invalid
686 char *ods2_conform( char *path)
695 /* Locate the last slash. */
696 prs = rindex( path, '/');
702 /* Locate the last dot after the last slash. */
703 prd = rindex( prs, '.');
709 /* Locate the version (after the last slash and dot). */
710 for (prv = prs+ strlen( prs) ; (--prv > prs) && isdigit( *prv); );
711 if ((*prv != ';') || (*(prv- 1) == '^'))
713 prv = prs+ strlen( prs);
716 for (p = path ; p < prv; p++)
718 prop = char_prop[ uchr = *p];
722 { /* Before last dot in name. */
723 *p = '_'; /* Convert to "_". */
726 else if ((prop& (32+ 16)) == 0)
727 { /* ODS2-invalid. */
730 *p = '-'; /* Convert to "-". */
732 else if (uchr == '@')
734 *p = '$'; /* Convert to "$". */
736 else if (uchr != '/') /* Leave "/" as-is. */
738 *p = '_'; /* Convert to "_". */
745 /*--------------------------------------------------------------------*/
749 Replace troublesome characters for the destination file system (ODS2
750 or ODS5) with more legal characters.
752 For ODS5, this is simply "?" -> "!" and "*" -> "#".
754 For ODS2, see ods2_conform().
756 Return value: path. (Someday this function could be written to leave
757 the original string unchanged, and to return a freshly allocated
758 string, possibly of a dfferent length.)
761 char *ods_conform( char *path)
765 /* Replacements for invalid (printing) ODS5 characters. */
766 #define ODS5_QUESTION '!'
767 #define ODS5_ASTERISK '#'
771 /* Return ODS2-conformant file name. */
772 return ods2_conform( path);
776 /* Return ODS5-conformant file name. ("?" -> "!", "*" -> "#".) */
777 for (p = path; *p != '\0'; p++)
792 /*--------------------------------------------------------------------*/
794 /* Wget-private utime() code. */
796 /* Use long name (NAML) structure only where available.
797 (This should be non-VAX with __CRTL_VER >= 70200000.)
802 /* Use long name (NAML) structure. */
804 #define FAB$L_NAMX fab$l_naml
806 #define NAMX$C_MAXRSS NAML$C_MAXRSS
807 #define NAMX$B_DEV naml$l_long_dev_size
808 #define NAMX$L_DEV naml$l_long_dev
809 #define NAMX$L_ESA naml$l_long_expand
810 #define NAMX$B_ESL naml$l_long_expand_size
811 #define NAMX$B_ESS naml$l_long_expand_alloc
812 #define NAMX$W_FID naml$w_fid
813 #define NAMX$L_RSA naml$l_long_result
814 #define NAMX$B_RSL naml$l_long_result_size
815 #define NAMX$B_RSS naml$l_long_result_alloc
816 #define CC$RMS_NAMX cc$rms_naml
818 #else /* def NAML$C_BID */
820 /* Use short name (NAM) structure. */
822 #define FAB$L_NAMX fab$l_nam
824 #define NAMX$C_MAXRSS NAM$C_MAXRSS
825 #define NAMX$B_DEV nam$b_dev
826 #define NAMX$L_DEV nam$l_dev
827 #define NAMX$L_ESA nam$l_esa
828 #define NAMX$B_ESL nam$b_esl
829 #define NAMX$B_ESS nam$b_ess
830 #define NAMX$W_FID nam$w_fid
831 #define NAMX$L_RSA nam$l_rsa
832 #define NAMX$B_RSL nam$b_rsl
833 #define NAMX$B_RSS nam$b_rss
834 #define CC$RMS_NAMX cc$rms_nam
836 #endif /* def NAML$C_BID */
838 /*--------------------------------------------------------------------*/
840 /* Wget-private utime() code. */
842 /* Action routine for decc$to_vms(), in utime(). */
844 char vms_path[ NAMX$C_MAXRSS+ 1];
846 int set_vms_name( char *name, int type)
848 strncpy( vms_path, name, NAMX$C_MAXRSS);
849 vms_path[ NAMX$C_MAXRSS] = '\0';
853 /*--------------------------------------------------------------------*/
855 /* utime() replacement. */
857 int utime( const char *path, const struct utimbuf *times)
864 unsigned short int vms_num_vec_time[ 7];
865 static unsigned int vms_abs_time[ 2];
869 /* QIOW item list used to set creation and revision dates. */
871 struct atrdef ut_atr[ 3] = {
872 {sizeof( vms_abs_time), ATR$C_CREDATE, UWA vms_abs_time},
873 {sizeof( vms_abs_time), ATR$C_REVDATE, UWA vms_abs_time},
876 /* Various RMS structures used for file access. */
878 struct FAB ut_fab = cc$rms_fab;
879 struct RAB ut_rab = cc$rms_rab;
880 struct NAMX ut_namx = CC$RMS_NAMX;
881 static struct fibdef ut_fib;
883 /* Device and file name buffers and their descriptors. */
885 static char dev_namx[ NAMX$C_MAXRSS+ 1];
886 char esa_namx[ NAMX$C_MAXRSS+ 1];
887 char rsa_namx[ NAMX$C_MAXRSS+ 1];
889 struct dsc$descriptor dev_dsc =
890 {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, dev_namx};
892 struct dsc$descriptor fib_dsc =
893 {sizeof( ut_fib), DSC$K_DTYPE_T, DSC$K_CLASS_S, (char *) &ut_fib};
895 /* "wget" provides a UNIX-like path name. With "-O", a user may provide
896 a VMS-like path name. If a slash is found in the name, assume that
897 it's UNIX-like, and convert it to VMS form. Otherwise, use it as-is.
900 if (strchr( path, '/') != NULL)
902 sts = decc$to_vms( path, set_vms_name, 0, 0);
906 /* Install the VMS file specification into the FAB. */
908 ut_fab.fab$l_fna = (char *) path;
909 ut_fab.fab$b_fns = (unsigned char) strlen( path);
911 ut_fab.fab$l_dna = "";
912 ut_fab.fab$b_dns = 0;
914 /* Point the FAB to the NAMX. */
916 ut_fab.FAB$L_NAMX = &ut_namx;
918 /* Install the name buffers into the NAM. */
920 ut_namx.NAMX$L_ESA = esa_namx;
921 ut_namx.NAMX$B_ESL = 0;
922 ut_namx.NAMX$B_ESS = sizeof( esa_namx)- 1;
924 ut_namx.NAMX$L_RSA = rsa_namx;
925 ut_namx.NAMX$B_RSL = 0;
926 ut_namx.NAMX$B_RSS = sizeof( rsa_namx)- 1;
928 /* Convert the modification time (UTC time_t) to local "tm" time. */
930 tms = localtime( &(times-> modtime));
932 /* Move (translate) "tm" structure local time to VMS vector time. */
936 vms_num_vec_time[ 0] = tms-> tm_year+ 1900;
937 vms_num_vec_time[ 1] = tms-> tm_mon+ 1;
938 vms_num_vec_time[ 2] = tms-> tm_mday;
939 vms_num_vec_time[ 3] = tms-> tm_hour;
940 vms_num_vec_time[ 4] = tms-> tm_min;
941 vms_num_vec_time[ 5] = tms-> tm_sec;
942 vms_num_vec_time[ 6] = 0; /* centiseconds */
944 /* Convert VMS vector time to VMS absolute time (quadword). */
946 sts = lib$cvt_vectim( vms_num_vec_time, vms_abs_time);
948 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
950 /* Parse the file specification. */
952 sts = sys$parse( &ut_fab, 0, 0);
954 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
956 /* Locate the file. (Gets the FID.) */
958 sts = sys$search( &ut_fab, 0, 0);
960 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
962 /* Form the device name descriptor. */
964 dev_dsc.dsc$w_length = ut_namx.NAMX$B_DEV;
965 dev_dsc.dsc$a_pointer = (char *) ut_namx.NAMX$L_DEV;
967 /* Assign a channel to the disk device. */
969 sts = sys$assign( &dev_dsc, &chan, 0, 0);
971 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
973 /* Move the FID (and not the DID) into the FIB. */
975 memset( (void *) &ut_fib, 0, sizeof( ut_fib));
977 for (i = 0; i < 3; i++)
979 ut_fib.fib$w_fid[ i] = ut_namx.NAMX$W_FID[ i];
980 ut_fib.fib$w_did[ i] = 0;
983 /* Prevent this QIOW from setting the revision time to now. */
985 ut_fib.fib$l_acctl = FIB$M_NORECORD;
987 /* Set the file dates. */
1002 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
1004 sts = iosb_q.iosb$w_status;
1006 sts2 = sys$dassgn( chan);
1008 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
1018 /* Convert successful VMS status to zero = success status.
1019 If failure, set errno and vaxc$errno, and return -1 = failure status.
1022 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
1036 /*--------------------------------------------------------------------*/
1042 * Get Wget debug option value.
1045 int vms_init_diag( void)
1048 return (opt.debug > 0);
1049 #else /* def ENABLE_DEBUG */
1051 #endif /* def ENABLE_DEBUG */
1054 /*--------------------------------------------------------------------*/
1058 * get_rms_defaults().
1060 * Get user-specified values from (DCL) SET RMS_DEFAULT. FAB/RAB
1061 * items of particular interest are:
1063 * fab$w_deq default extension quantity (blocks) (write).
1064 * rab$b_mbc multi-block count.
1065 * rab$b_mbf multi-buffer count (used with rah and wbh).
1068 /* Default RMS parameter values. */
1070 #define RMS_DEQ_DEFAULT 16384 /* About 1/4 the max (65535 blocks). */
1071 #define RMS_MBC_DEFAULT 127 /* The max, */
1072 #define RMS_MBF_DEFAULT 2 /* Enough to enable rah and wbh. */
1074 /* GETJPI item descriptor structure. */
1083 /* Durable storage */
1085 static int rms_defaults_known = 0;
1087 /* JPI item buffers. */
1088 static unsigned short rms_ext;
1089 static char rms_mbc;
1090 static unsigned char rms_mbf;
1092 /* Active RMS item values. */
1093 unsigned short rms_ext_active;
1094 char rms_mbc_active;
1095 unsigned char rms_mbf_active;
1097 /* GETJPI item lengths. */
1098 static int rms_ext_len; /* Should come back 2. */
1099 static int rms_mbc_len; /* Should come back 1. */
1100 static int rms_mbf_len; /* Should come back 1. */
1102 /* Desperation attempts to define unknown macros. Probably doomed.
1103 * If these get used, expect sys$getjpiw() to return %x00000014 =
1104 * %SYSTEM-F-BADPARAM, bad parameter value.
1105 * They keep compilers with old header files quiet, though.
1107 #ifndef JPI$_RMS_EXTEND_SIZE
1108 # define JPI$_RMS_EXTEND_SIZE 542
1109 #endif /* ndef JPI$_RMS_EXTEND_SIZE */
1111 #ifndef JPI$_RMS_DFMBC
1112 # define JPI$_RMS_DFMBC 535
1113 #endif /* ndef JPI$_RMS_DFMBC */
1115 #ifndef JPI$_RMS_DFMBFSDK
1116 # define JPI$_RMS_DFMBFSDK 536
1117 #endif /* ndef JPI$_RMS_DFMBFSDK */
1119 /* GETJPI item descriptor set. */
1123 jpi_item_t rms_ext_itm;
1124 jpi_item_t rms_mbc_itm;
1125 jpi_item_t rms_mbf_itm;
1128 { { 2, JPI$_RMS_EXTEND_SIZE, &rms_ext, &rms_ext_len },
1129 { 1, JPI$_RMS_DFMBC, &rms_mbc, &rms_mbc_len },
1130 { 1, JPI$_RMS_DFMBFSDK, &rms_mbf, &rms_mbf_len },
1134 int get_rms_defaults()
1138 /* Get process RMS_DEFAULT values. */
1140 sts = sys$getjpiw( 0, 0, 0, &jpi_itm_lst, 0, 0, 0);
1141 if ((sts& STS$M_SEVERITY) != STS$M_SUCCESS)
1143 /* Failed. Don't try again. */
1144 rms_defaults_known = -1;
1148 /* Fine, but don't come back. */
1149 rms_defaults_known = 1;
1152 /* Limit the active values according to the RMS_DEFAULT values. */
1154 if (rms_defaults_known > 0)
1156 /* Set the default values. */
1158 rms_ext_active = RMS_DEQ_DEFAULT;
1159 rms_mbc_active = RMS_MBC_DEFAULT;
1160 rms_mbf_active = RMS_MBF_DEFAULT;
1162 /* Default extend quantity. Use the user value, if set. */
1165 rms_ext_active = rms_ext;
1168 /* Default multi-block count. Use the user value, if set. */
1171 rms_mbc_active = rms_mbc;
1174 /* Default multi-buffer count. Use the user value, if set. */
1177 rms_mbf_active = rms_mbf;
1181 if (vms_init_diag() > 0)
1184 "Get RMS defaults. getjpi sts = %%x%08x.\n",
1187 if (rms_defaults_known > 0)
1190 " Default: deq = %6d, mbc = %3d, mbf = %3d.\n",
1191 rms_ext, rms_mbc, rms_mbf);
1197 /*--------------------------------------------------------------------*/
1201 * acc_cb(), access callback function for DEC C [f]open().
1203 * Set some RMS FAB/RAB items, with consideration of user-specified
1204 * values from (DCL) SET RMS_DEFAULT. Items of particular interest are:
1206 * fab$w_deq default extension quantity (blocks).
1207 * rab$b_mbc multi-block count.
1208 * rab$b_mbf multi-buffer count (used with rah and wbh).
1210 * See also the FOP* macros in OSDEP.H. Currently, no notice is
1211 * taken of the caller-ID value, but options could be set differently
1212 * for read versus write access. (I assume that specifying fab$w_deq,
1213 * for example, for a read-only file has no ill effects.)
1218 int acc_cb( int *id_arg, struct FAB *fab, struct RAB *rab)
1222 /* Get process RMS_DEFAULT values, if not already done. */
1223 if (rms_defaults_known == 0)
1228 /* If RMS_DEFAULT (and adjusted active) values are available, then set
1229 * the FAB/RAB parameters. If RMS_DEFAULT values are not available,
1230 * suffer with the default parameters.
1232 if (rms_defaults_known > 0)
1234 /* Set the FAB/RAB parameters accordingly. */
1235 fab-> fab$w_deq = rms_ext_active;
1236 rab-> rab$b_mbc = rms_mbc_active;
1237 rab-> rab$b_mbf = rms_mbf_active;
1239 /* Truncate at EOF on close, as we'll probably over-extend. */
1240 fab-> fab$v_tef = 1;
1242 /* If using multiple buffers, enable read-ahead and write-behind. */
1243 if (rms_mbf_active > 1)
1245 rab-> rab$v_rah = 1;
1246 rab-> rab$v_wbh = 1;
1249 if (vms_init_diag() > 0)
1252 "Open callback. ID = %d, deq = %6d, mbc = %3d, mbf = %3d.\n",
1253 *id_arg, fab-> fab$w_deq, rab-> rab$b_mbc, rab-> rab$b_mbf);
1257 /* Declare success. */
1261 /*--------------------------------------------------------------------*/
1263 /* Added J.Lauret 05-Dec-1999 . Copied from Mosaic distribution */
1266 * Here is a replacement for getpwuid for VMS. It returns pointers
1267 * to userid (*pw_name) and owner (*pw_gecos) only. Other fields
1268 * may be added later.
1269 * Note that sys$getuai returns owner as a counted string.
1272 #if __CRTL_VER < 70000000
1276 static struct passwd vms_passwd;
1277 static char vms_userid[16];
1278 static char vms_owner[40];
1280 struct passwd *getpwuid()
1282 struct dsc$descriptor_s
1284 unsigned short dsc$w_length;
1285 unsigned char dsc$b_dtype;
1286 unsigned char dsc$b_class;
1287 char *dsc$a_pointer;
1288 } user_desc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
1290 char *t_userid, owner[40];
1293 short buffer_length;
1296 int return_length_address;
1301 (int)t_userid = cuserid((char *) NULL);
1303 t_userid = cuserid((char *) NULL);
1304 #endif /* GNU C is strange, GEC */
1305 user_desc.dsc$w_length = strlen(t_userid);
1306 user_desc.dsc$a_pointer = t_userid;
1307 itmlst.buffer_length = sizeof(owner);
1308 itmlst.item_code = UAI$_OWNER;
1309 itmlst.buffer_address = (int)owner;
1310 itmlst.return_length_address = (int)&length;
1311 itmlst.terminator = 0;
1312 status = sys$getuai(0, 0, &user_desc, &itmlst, 0, 0, 0);
1313 if ((stats& STS$M_SEVERITY) == STS$K_SUCCESS) {
1314 length = (int)owner[0];
1315 owner[length+1] = '\0';
1316 strcpy(vms_userid, t_userid);
1317 strcpy(vms_owner, &owner[1]);
1319 vms_userid[0] = '\0';
1320 vms_owner[0] = '\0';
1322 vms_passwd.pw_name = vms_userid;
1323 vms_passwd.pw_gecos = vms_owner;
1324 return (&vms_passwd);
1327 /* Approximate localtime_r as best we can in its absence. */
1333 struct tm *l = localtime (t);
1340 #endif /* __CRTL_VER < 70000000 */
1342 /*--------------------------------------------------------------------*/
1345 * "version.c" information.
1348 const char *compilation_string = NULL;
1349 const char *link_string = NULL;
1350 const char *version_string = VERSION;
1352 /*--------------------------------------------------------------------*/