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 (run-time) VMS version string.
23 *----------------------------------------------------------------------
27 * Sets a global flag ("ods5_dest") according to the file system type
28 * of the destination device.
30 *----------------------------------------------------------------------
34 * Simplifies a fancy URL-derived file name into an ODS2- or
35 * ODS5-compatible file name.
37 *----------------------------------------------------------------------
41 * VMS C RTL before V7.3 lacks utime(). In V7.3, utime() sets only
42 * the modified (revised) date, not the created date of a file.
44 * UNIX "ls -l" reports the modified time. VMS "DIRECTORY /DATE"
45 * reports the creation time. Reconciling these in FTP DIR reports
48 * UNIX utime() sets revision and access times. VMS does not always
49 * maintain access times, so this utime() replacement sets the
50 * creation and revision times to the specified revision (or
51 * creation?) time. Any access time is ignored.
53 *----------------------------------------------------------------------
57 * VMS C RTL before V7.0 lacks getpwuid().
59 *----------------------------------------------------------------------
81 #include <lib$routines.h>
84 /* Use <iosbdef.h> if available. Otherwise declare IOSB here. */
86 #if !defined( __VAX) && (__CRTL_VER >= 70000000)
88 #else /* __CRTL_VER >= 70000000 */
89 typedef struct _iosb {
90 unsigned short int iosb$w_status; /* Final I/O status */
91 unsigned short int iosb$w_bcnt; /* 16-bit byte count */
92 unsigned int iosb$l_dev_depend; /* 32-bit dev dependent */
94 #endif /* !defined( __VAX) && (__CRTL_VER >= 70000000) */
96 /* Ugly work-around for bad type in VAX <atrdef.h>. */
99 #define UWA (unsigned int)
100 #else /* def __VAX */
102 #endif /* def __VAX */
108 /*--------------------------------------------------------------------*/
110 /* Global storage. */
112 /* Flag for an ODS5 destination directory. */
116 /* Flag to sense if vms_init() was called. */
118 int vms_init_done = -1;
120 /*--------------------------------------------------------------------*/
122 #if !defined( __VAX) && (__CRTL_VER >= 70301000)
126 Uses LIB$INITIALIZE to set a collection of C RTL features without
127 requiring the user to define the corresponding logical names.
130 /* Structure to hold a DECC$* feature name and its desired value. */
138 /* Array of DECC$* feature names and their desired values. */
140 decc_feat_t decc_feat_array[] = {
141 /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
142 { "DECC$ARGV_PARSE_STYLE", 1 },
143 /* Preserve case for file names on ODS5 disks. */
144 { "DECC$EFS_CASE_PRESERVE", 1 },
145 /* Enable multiple dots (and most characters) in ODS5 file names,
146 while preserving VMS-ness of ";version". */
147 { "DECC$EFS_CHARSET", 1 },
148 /* List terminator. */
149 { (char *)NULL, 0 } };
151 /* LIB$INITIALIZE initialization function. */
153 static void vms_init( void)
162 /* Set the global flag to indicate that LIB$INITIALIZE worked. */
166 /* Loop through all items in the decc_feat_array[]. */
168 for (i = 0; decc_feat_array[ i].name != NULL; i++)
170 /* Get the feature index. */
171 feat_index = decc$feature_get_index( decc_feat_array[ i].name);
174 /* Valid item. Collect its properties. */
175 feat_value = decc$feature_get_value( feat_index, 1);
176 feat_value_min = decc$feature_get_value( feat_index, 2);
177 feat_value_max = decc$feature_get_value( feat_index, 3);
179 if ((decc_feat_array[ i].value >= feat_value_min) &&
180 (decc_feat_array[ i].value <= feat_value_max))
182 /* Valid value. Set it if necessary. */
183 if (feat_value != decc_feat_array[ i].value)
185 sts = decc$feature_set_value( feat_index,
187 decc_feat_array[ i].value);
192 /* Invalid DECC feature value. */
193 printf( " INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n",
195 feat_value_min, decc_feat_array[ i].name, feat_value_max);
200 /* Invalid DECC feature name. */
201 printf( " UNKNOWN DECC FEATURE: %s.\n", decc_feat_array[ i].name);
206 /* Get "vms_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
210 /* Establish the LIB$INITIALIZE PSECTs, with proper alignment and
211 other attributes. Note that "nopic" is significant only on VAX.
213 #pragma extern_model save
215 #pragma extern_model strict_refdef "LIB$INITIALIZE" 2, nopic, nowrt
216 void (*const x_vms_init)() = vms_init;
218 #pragma extern_model strict_refdef "LIB$INITIALIZ" 2, nopic, nowrt
219 const int spare[ 8] = { 0 };
221 #pragma extern_model restore
223 /* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
225 #pragma extern_model save
226 int lib$initialize(void);
227 #pragma extern_model strict_refdef
228 int dmy_lib$initialize = (int) lib$initialize;
229 #pragma extern_model restore
233 #endif /* !defined( __VAX) && (__CRTL_VER >= 70301000) */
235 /*--------------------------------------------------------------------*/
239 Returns (run-time) VMS architecture string.
242 char *vms_arch( void)
247 static char arch[ ARCH_SIZE+ 1] = "VAX"; /* Only VAX could fail. */
248 unsigned short arch_len;
250 struct dsc$descriptor_s arch_descr =
251 { ARCH_SIZE, DSC$K_DTYPE_T, DSC$K_CLASS_S, arch };
255 sts = lib$getsyi( &SYI$_ARCH_NAME, 0, &arch_descr, &arch_len, 0, 0);
256 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
258 arch[ arch_len] = '\0';
260 /* Trim trailing spaces. */
261 while ((arch_len > 0) && (arch[ arch_len- 1] == ' '))
263 arch[ --arch_len] = '\0';
270 /*--------------------------------------------------------------------*/
274 Returns (run-time) VMS version string.
277 char *vms_vers( void)
282 static char vers[ VERS_SIZE+ 1] = "";
283 unsigned short vers_len;
285 struct dsc$descriptor_s vers_descr =
286 { VERS_SIZE, DSC$K_DTYPE_T, DSC$K_CLASS_S, vers };
290 sts = lib$getsyi( &SYI$_VERSION, 0, &vers_descr, &vers_len, 0, 0);
291 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
293 vers[ vers_len] = '\0';
295 /* Trim trailing spaces. */
296 while ((vers_len > 0) && (vers[ vers_len- 1] == ' '))
298 vers[ --vers_len] = '\0';
305 /*--------------------------------------------------------------------*/
309 Sets global "ods5_dest" according to the file system type of the
310 argument: 0 for ODS2, 1 for ODS5. (No change if other/unknown or
313 Return value: Status from sys$getdvi().
316 int set_ods5_dest( char *path)
318 #ifdef DVI$C_ACP_F11V5
320 /* Should know about ODS5 file system. Do actual check.
321 (This should be non-VAX with __CRTL_VER >= 70200000.)
324 struct dsc$descriptor_s dev_descr =
325 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
330 /* Load path argument into device descriptor.
331 Default to current default device.
335 dev_descr.dsc$a_pointer = "SYS$DISK";
339 dev_descr.dsc$a_pointer = path;
341 dev_descr.dsc$w_length = strlen( dev_descr.dsc$a_pointer);
343 /* Get filesystem type code.
344 (Text results for this item code have been unreliable.)
346 sts = lib$getdvi( &((int) DVI$_ACPTYPE),
353 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
355 if (acp_code == DVI$C_ACP_F11V2)
359 else if (acp_code == DVI$C_ACP_F11V5)
367 #else /* def DVI$C_ACP_F11V5 */
369 /* Too old for ODS5 file system. Do nothing. */
371 return STS$K_SUCCESS;
373 #endif /* def DVI$C_ACP_F11V5 */
376 /*--------------------------------------------------------------------*/
380 Replace ODS2-troublesome characters in the argument, overwriting the
381 original string. Replace "~" with "-", "@" with "$", and invalid
382 dots and other characters with "_". (Invalid dots are any in a
383 directory name, and all but the last in a file name.)
385 Return value: path. (Someday this function could be written to leave
386 the original string unchanged, and to return a freshly allocated
387 string, possibly of a dfferent length.)
390 Changed to use char_prop[] look-up table, and to convert more invalid
395 char *ods2_conform( char *path)
404 /* Locate the last slash. */
405 prs = rindex( path, '/');
411 /* Locate the last dot after the last slash. */
412 prd = rindex( prs, '.');
418 /* Locate the version (after the last slash and dot). */
419 for (prv = prs+ strlen( prs) ; (--prv > prs) && isdigit( *prv); );
420 if ((*prv != ';') || (*(prv- 1) == '^'))
422 prv = prs+ strlen( prs);
425 for (p = path ; p < prv; p++)
427 prop = char_prop[ uchr = *p];
431 { /* Before last dot in name. */
432 *p = '_'; /* Convert to "_". */
435 else if ((prop& (32+ 16)) == 0)
436 { /* ODS2-invalid. */
439 *p = '-'; /* Convert to "-". */
441 else if (uchr == '@')
443 *p = '$'; /* Convert to "$". */
445 else if (uchr != '/') /* Leave "/" as-is. */
447 *p = '_'; /* Convert to "_". */
454 /*--------------------------------------------------------------------*/
458 Replace troublesome characters for the destination file system (ODS2
459 or ODS5) with more legal characters.
461 For ODS5, this is simply "?" -> "!" and "*" -> "#".
463 For ODS2, see ods2_conform().
465 Return value: path. (Someday this function could be written to leave
466 the original string unchanged, and to return a freshly allocated
467 string, possibly of a dfferent length.)
470 char *ods_conform( char *path)
474 /* Replacements for invalid (printing) ODS5 characters. */
475 #define ODS5_QUESTION '!'
476 #define ODS5_ASTERISK '#'
480 /* Return ODS2-conformant file name. */
481 return ods2_conform( path);
485 /* Return ODS5-conformant file name. ("?" -> "!", "*" -> "#".) */
486 for (p = path; *p != '\0'; p++)
501 /*--------------------------------------------------------------------*/
503 /* Wget-private utime() code. */
505 /* Use long name (NAML) structure only where available.
506 (This should be non-VAX with __CRTL_VER >= 70200000.)
511 /* Use long name (NAML) structure. */
513 #define FAB$L_NAMX fab$l_naml
515 #define NAMX$C_MAXRSS NAML$C_MAXRSS
516 #define NAMX$B_DEV naml$l_long_dev_size
517 #define NAMX$L_DEV naml$l_long_dev
518 #define NAMX$L_ESA naml$l_long_expand
519 #define NAMX$B_ESL naml$l_long_expand_size
520 #define NAMX$B_ESS naml$l_long_expand_alloc
521 #define NAMX$W_FID naml$w_fid
522 #define NAMX$L_RSA naml$l_long_result
523 #define NAMX$B_RSL naml$l_long_result_size
524 #define NAMX$B_RSS naml$l_long_result_alloc
525 #define CC$RMS_NAMX cc$rms_naml
527 #else /* def NAML$C_BID */
529 /* Use short name (NAM) structure. */
531 #define FAB$L_NAMX fab$l_nam
533 #define NAMX$C_MAXRSS NAM$C_MAXRSS
534 #define NAMX$B_DEV nam$b_dev
535 #define NAMX$L_DEV nam$l_dev
536 #define NAMX$L_ESA nam$l_esa
537 #define NAMX$B_ESL nam$b_esl
538 #define NAMX$B_ESS nam$b_ess
539 #define NAMX$W_FID nam$w_fid
540 #define NAMX$L_RSA nam$l_rsa
541 #define NAMX$B_RSL nam$b_rsl
542 #define NAMX$B_RSS nam$b_rss
543 #define CC$RMS_NAMX cc$rms_nam
545 #endif /* def NAML$C_BID */
547 /*--------------------------------------------------------------------*/
549 /* Wget-private utime() code. */
551 /* Action routine for decc$to_vms(), in utime(). */
553 char vms_path[ NAMX$C_MAXRSS+ 1];
555 int set_vms_name( char *name, int type)
557 strncpy( vms_path, name, NAMX$C_MAXRSS);
558 vms_path[ NAMX$C_MAXRSS] = '\0';
562 /*--------------------------------------------------------------------*/
564 /* utime() replacement. */
566 int utime( const char *path, const struct utimbuf *times)
573 unsigned short int vms_num_vec_time[ 7];
574 static unsigned int vms_abs_time[ 2];
578 /* QIOW item list used to set creation and revision dates. */
580 struct atrdef ut_atr[ 3] = {
581 {sizeof( vms_abs_time), ATR$C_CREDATE, UWA vms_abs_time},
582 {sizeof( vms_abs_time), ATR$C_REVDATE, UWA vms_abs_time},
585 /* Various RMS structures used for file access. */
587 struct FAB ut_fab = cc$rms_fab;
588 struct RAB ut_rab = cc$rms_rab;
589 struct NAMX ut_namx = CC$RMS_NAMX;
590 static struct fibdef ut_fib;
592 /* Device and file name buffers and their descriptors. */
594 static char dev_namx[ NAMX$C_MAXRSS+ 1];
595 char esa_namx[ NAMX$C_MAXRSS+ 1];
596 char rsa_namx[ NAMX$C_MAXRSS+ 1];
598 struct dsc$descriptor dev_dsc =
599 {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, dev_namx};
601 struct dsc$descriptor fib_dsc =
602 {sizeof( ut_fib), DSC$K_DTYPE_T, DSC$K_CLASS_S, (char *) &ut_fib};
604 /* "wget" provides a UNIX-like path name. With "-O", a user may provide
605 a VMS-like path name. If a slash is found in the name, assume that
606 it's UNIX-like, and convert it to VMS form. Otherwise, use it as-is.
609 if (strchr( path, '/') != NULL)
611 sts = decc$to_vms( path, set_vms_name, 0, 0);
615 /* Install the VMS file specification into the FAB. */
617 ut_fab.fab$l_fna = (char *) path;
618 ut_fab.fab$b_fns = (unsigned char) strlen( path);
620 ut_fab.fab$l_dna = "";
621 ut_fab.fab$b_dns = 0;
623 /* Point the FAB to the NAMX. */
625 ut_fab.FAB$L_NAMX = &ut_namx;
627 /* Install the name buffers into the NAM. */
629 ut_namx.NAMX$L_ESA = esa_namx;
630 ut_namx.NAMX$B_ESL = 0;
631 ut_namx.NAMX$B_ESS = sizeof( esa_namx)- 1;
633 ut_namx.NAMX$L_RSA = rsa_namx;
634 ut_namx.NAMX$B_RSL = 0;
635 ut_namx.NAMX$B_RSS = sizeof( rsa_namx)- 1;
637 /* Convert the modification time (UTC time_t) to local "tm" time. */
639 tms = localtime( &(times-> modtime));
641 /* Move (translate) "tm" structure local time to VMS vector time. */
645 vms_num_vec_time[ 0] = tms-> tm_year+ 1900;
646 vms_num_vec_time[ 1] = tms-> tm_mon+ 1;
647 vms_num_vec_time[ 2] = tms-> tm_mday;
648 vms_num_vec_time[ 3] = tms-> tm_hour;
649 vms_num_vec_time[ 4] = tms-> tm_min;
650 vms_num_vec_time[ 5] = tms-> tm_sec;
651 vms_num_vec_time[ 6] = 0; /* centiseconds */
653 /* Convert VMS vector time to VMS absolute time (quadword). */
655 sts = lib$cvt_vectim( vms_num_vec_time, vms_abs_time);
657 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
659 /* Parse the file specification. */
661 sts = sys$parse( &ut_fab, 0, 0);
663 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
665 /* Locate the file. (Gets the FID.) */
667 sts = sys$search( &ut_fab, 0, 0);
669 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
671 /* Form the device name descriptor. */
673 dev_dsc.dsc$w_length = ut_namx.NAMX$B_DEV;
674 dev_dsc.dsc$a_pointer = (char *) ut_namx.NAMX$L_DEV;
676 /* Assign a channel to the disk device. */
678 sts = sys$assign( &dev_dsc, &chan, 0, 0);
680 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
682 /* Move the FID (and not the DID) into the FIB. */
684 memset( (void *) &ut_fib, 0, sizeof( ut_fib));
686 for (i = 0; i < 3; i++)
688 ut_fib.fib$w_fid[ i] = ut_namx.NAMX$W_FID[ i];
689 ut_fib.fib$w_did[ i] = 0;
692 /* Prevent this QIOW from setting the revision time to now. */
694 ut_fib.fib$l_acctl = FIB$M_NORECORD;
696 /* Set the file dates. */
711 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
713 sts = iosb_q.iosb$w_status;
715 sts2 = sys$dassgn( chan);
717 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
727 /* Convert successful VMS status to zero = success status.
728 If failure, set errno and vaxc$errno, and return -1 = failure status.
731 if ((sts& STS$M_SEVERITY) == STS$K_SUCCESS)
745 /*--------------------------------------------------------------------*/
751 * Get Wget debug option value.
754 int vms_init_diag( void)
757 return (opt.debug > 0);
758 #else /* def ENABLE_DEBUG */
760 #endif /* def ENABLE_DEBUG */
763 /*--------------------------------------------------------------------*/
767 * get_rms_defaults().
769 * Get user-specified values from (DCL) SET RMS_DEFAULT. FAB/RAB
770 * items of particular interest are:
772 * fab$w_deq default extension quantity (blocks) (write).
773 * rab$b_mbc multi-block count.
774 * rab$b_mbf multi-buffer count (used with rah and wbh).
777 /* Default RMS parameter values. */
779 #define RMS_DEQ_DEFAULT 16384 /* About 1/4 the max (65535 blocks). */
780 #define RMS_MBC_DEFAULT 127 /* The max, */
781 #define RMS_MBF_DEFAULT 2 /* Enough to enable rah and wbh. */
783 /* GETJPI item descriptor structure. */
792 /* Durable storage */
794 static int rms_defaults_known = 0;
796 /* JPI item buffers. */
797 static unsigned short rms_ext;
799 static unsigned char rms_mbf;
801 /* Active RMS item values. */
802 unsigned short rms_ext_active;
804 unsigned char rms_mbf_active;
806 /* GETJPI item lengths. */
807 static int rms_ext_len; /* Should come back 2. */
808 static int rms_mbc_len; /* Should come back 1. */
809 static int rms_mbf_len; /* Should come back 1. */
811 /* Desperation attempts to define unknown macros. Probably doomed.
812 * If these get used, expect sys$getjpiw() to return %x00000014 =
813 * %SYSTEM-F-BADPARAM, bad parameter value.
814 * They keep compilers with old header files quiet, though.
816 #ifndef JPI$_RMS_EXTEND_SIZE
817 # define JPI$_RMS_EXTEND_SIZE 542
818 #endif /* ndef JPI$_RMS_EXTEND_SIZE */
820 #ifndef JPI$_RMS_DFMBC
821 # define JPI$_RMS_DFMBC 535
822 #endif /* ndef JPI$_RMS_DFMBC */
824 #ifndef JPI$_RMS_DFMBFSDK
825 # define JPI$_RMS_DFMBFSDK 536
826 #endif /* ndef JPI$_RMS_DFMBFSDK */
828 /* GETJPI item descriptor set. */
832 jpi_item_t rms_ext_itm;
833 jpi_item_t rms_mbc_itm;
834 jpi_item_t rms_mbf_itm;
837 { { 2, JPI$_RMS_EXTEND_SIZE, &rms_ext, &rms_ext_len },
838 { 1, JPI$_RMS_DFMBC, &rms_mbc, &rms_mbc_len },
839 { 1, JPI$_RMS_DFMBFSDK, &rms_mbf, &rms_mbf_len },
843 int get_rms_defaults()
847 /* Get process RMS_DEFAULT values. */
849 sts = sys$getjpiw( 0, 0, 0, &jpi_itm_lst, 0, 0, 0);
850 if ((sts& STS$M_SEVERITY) != STS$M_SUCCESS)
852 /* Failed. Don't try again. */
853 rms_defaults_known = -1;
857 /* Fine, but don't come back. */
858 rms_defaults_known = 1;
861 /* Limit the active values according to the RMS_DEFAULT values. */
863 if (rms_defaults_known > 0)
865 /* Set the default values. */
867 rms_ext_active = RMS_DEQ_DEFAULT;
868 rms_mbc_active = RMS_MBC_DEFAULT;
869 rms_mbf_active = RMS_MBF_DEFAULT;
871 /* Default extend quantity. Use the user value, if set. */
874 rms_ext_active = rms_ext;
877 /* Default multi-block count. Use the user value, if set. */
880 rms_mbc_active = rms_mbc;
883 /* Default multi-buffer count. Use the user value, if set. */
886 rms_mbf_active = rms_mbf;
890 if (vms_init_diag() > 0)
893 "Get RMS defaults. getjpi sts = %%x%08x.\n",
896 if (rms_defaults_known > 0)
899 " Default: deq = %6d, mbc = %3d, mbf = %3d.\n",
900 rms_ext, rms_mbc, rms_mbf);
906 /*--------------------------------------------------------------------*/
910 * acc_cb(), access callback function for DEC C [f]open().
912 * Set some RMS FAB/RAB items, with consideration of user-specified
913 * values from (DCL) SET RMS_DEFAULT. Items of particular interest are:
915 * fab$w_deq default extension quantity (blocks).
916 * rab$b_mbc multi-block count.
917 * rab$b_mbf multi-buffer count (used with rah and wbh).
919 * See also the FOP* macros in OSDEP.H. Currently, no notice is
920 * taken of the caller-ID value, but options could be set differently
921 * for read versus write access. (I assume that specifying fab$w_deq,
922 * for example, for a read-only file has no ill effects.)
927 int acc_cb( int *id_arg, struct FAB *fab, struct RAB *rab)
931 /* Get process RMS_DEFAULT values, if not already done. */
932 if (rms_defaults_known == 0)
937 /* If RMS_DEFAULT (and adjusted active) values are available, then set
938 * the FAB/RAB parameters. If RMS_DEFAULT values are not available,
939 * suffer with the default parameters.
941 if (rms_defaults_known > 0)
943 /* Set the FAB/RAB parameters accordingly. */
944 fab-> fab$w_deq = rms_ext_active;
945 rab-> rab$b_mbc = rms_mbc_active;
946 rab-> rab$b_mbf = rms_mbf_active;
948 /* Truncate at EOF on close, as we'll probably over-extend. */
951 /* If using multiple buffers, enable read-ahead and write-behind. */
952 if (rms_mbf_active > 1)
958 if (vms_init_diag() > 0)
961 "Open callback. ID = %d, deq = %6d, mbc = %3d, mbf = %3d.\n",
962 *id_arg, fab-> fab$w_deq, rab-> rab$b_mbc, rab-> rab$b_mbf);
966 /* Declare success. */
970 /*--------------------------------------------------------------------*/
972 /* Added J.Lauret 05-Dec-1999 . Copied from Mosaic distribution */
975 * Here is a replacement for getpwuid for VMS. It returns pointers
976 * to userid (*pw_name) and owner (*pw_gecos) only. Other fields
977 * may be added later.
978 * Note that sys$getuai returns owner as a counted string.
981 #if __CRTL_VER < 70000000
985 static struct passwd vms_passwd;
986 static char vms_userid[16];
987 static char vms_owner[40];
989 struct passwd *getpwuid()
991 struct dsc$descriptor_s
993 unsigned short dsc$w_length;
994 unsigned char dsc$b_dtype;
995 unsigned char dsc$b_class;
997 } user_desc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
999 char *t_userid, owner[40];
1002 short buffer_length;
1005 int return_length_address;
1010 (int)t_userid = cuserid((char *) NULL);
1012 t_userid = cuserid((char *) NULL);
1013 #endif /* GNU C is strange, GEC */
1014 user_desc.dsc$w_length = strlen(t_userid);
1015 user_desc.dsc$a_pointer = t_userid;
1016 itmlst.buffer_length = sizeof(owner);
1017 itmlst.item_code = UAI$_OWNER;
1018 itmlst.buffer_address = (int)owner;
1019 itmlst.return_length_address = (int)&length;
1020 itmlst.terminator = 0;
1021 status = sys$getuai(0, 0, &user_desc, &itmlst, 0, 0, 0);
1022 if ((stats& STS$M_SEVERITY) == STS$K_SUCCESS) {
1023 length = (int)owner[0];
1024 owner[length+1] = '\0';
1025 strcpy(vms_userid, t_userid);
1026 strcpy(vms_owner, &owner[1]);
1028 vms_userid[0] = '\0';
1029 vms_owner[0] = '\0';
1031 vms_passwd.pw_name = vms_userid;
1032 vms_passwd.pw_gecos = vms_owner;
1033 return (&vms_passwd);
1036 /* Approximate localtime_r as best we can in its absence. */
1042 struct tm *l = localtime (t);
1049 #endif /* __CRTL_VER < 70000000 */