OpenVMSOperatingSystem.st
changeset 8266 3dc78835e119
parent 7080 a82683bc1843
child 8901 824a89d0b5c7
equal deleted inserted replaced
8265:34418449c41c 8266:3dc78835e119
   109 };
   109 };
   110 
   110 
   111 /* ST/X maintained per-process information */
   111 /* ST/X maintained per-process information */
   112 
   112 
   113 struct procInfo {
   113 struct procInfo {
   114     long  returnStatus; 
   114     long  returnStatus;
   115     long  pid;
   115     long  pid;
   116     char  eventFlag;
   116     char  eventFlag;
   117     char  finished;
   117     char  finished;
   118     struct procInfo *nextProc;
   118     struct procInfo *nextProc;
   119 };
   119 };
   132 /*
   132 /*
   133  * notice: although many systems' include files
   133  * notice: although many systems' include files
   134  * already block against multiple inclusion, some
   134  * already block against multiple inclusion, some
   135  * do not. Therefore, this is done here again.
   135  * do not. Therefore, this is done here again.
   136  * (it does not hurt)
   136  * (it does not hurt)
   137  */ 
   137  */
   138 
   138 
   139 #ifdef WANT_SHM
   139 #ifdef WANT_SHM
   140 extern int shmctl(), shmget(), shmdt();
   140 extern int shmctl(), shmget(), shmdt();
   141 extern char * shmat();
   141 extern char * shmat();
   142 
   142 
   255 #  include <locale.h>
   255 #  include <locale.h>
   256 #  define _LOCALE_H_INCLUDED_
   256 #  define _LOCALE_H_INCLUDED_
   257 # endif
   257 # endif
   258 #endif
   258 #endif
   259 
   259 
   260 /* 
   260 /*
   261  * posix systems should define these ... 
   261  * posix systems should define these ...
   262  * but on some (older) systems, they are not.
   262  * but on some (older) systems, they are not.
   263  */
   263  */
   264 #ifndef S_IXUSR
   264 #ifndef S_IXUSR
   265 # ifdef S_IEXEC
   265 # ifdef S_IEXEC
   266 #  define S_IXUSR S_IEXEC
   266 #  define S_IXUSR S_IEXEC
   335 
   335 
   336 /*
   336 /*
   337  * some (old ?) systems do not define this ...
   337  * some (old ?) systems do not define this ...
   338  */
   338  */
   339 #if !defined(R_OK) && !defined(_AIX)
   339 #if !defined(R_OK) && !defined(_AIX)
   340 # define R_OK    4       /* Test for Read permission */ 
   340 # define R_OK    4       /* Test for Read permission */
   341 # define W_OK    2       /* Test for Write permission */
   341 # define W_OK    2       /* Test for Write permission */
   342 # define X_OK    1       /* Test for eXecute permission */
   342 # define X_OK    1       /* Test for eXecute permission */
   343 # define F_OK    0       /* Test for existence of File */
   343 # define F_OK    0       /* Test for existence of File */
   344 #endif
   344 #endif
   345 
   345 
   427 		printf("===> stat('%s') - retry\n", t);
   427 		printf("===> stat('%s') - retry\n", t);
   428 # endif
   428 # endif
   429 		do {
   429 		do {
   430 		    ret = stat(t, buffP);
   430 		    ret = stat(t, buffP);
   431 		} while ((ret < 0) && (errno == EINTR));
   431 		} while ((ret < 0) && (errno == EINTR));
   432 		if (ret >= 0) 
   432 		if (ret >= 0)
   433 		    return ret;
   433 		    return ret;
   434 	    }
   434 	    }
   435 
   435 
   436 	    /*
   436 	    /*
   437 	     * try with appended '.DIR';
   437 	     * try with appended '.DIR';
   469 # define stat(__path__, __buffP__)      __vms_stat__(__path__, __buffP__)
   469 # define stat(__path__, __buffP__)      __vms_stat__(__path__, __buffP__)
   470 
   470 
   471 /*
   471 /*
   472  * same for access
   472  * same for access
   473  */
   473  */
   474 int 
   474 int
   475 __vms_access__(path, mode)
   475 __vms_access__(path, mode)
   476     char *path;
   476     char *path;
   477     int mode;
   477     int mode;
   478 {
   478 {
   479 	int ret;
   479 	int ret;
   513 
   513 
   514 /* #define WAITDEBUG /* */
   514 /* #define WAITDEBUG /* */
   515 /* #define PROCESSDEBUG /* */
   515 /* #define PROCESSDEBUG /* */
   516 
   516 
   517 void
   517 void
   518 __vms_ASTChildWithInfo(pInfo) 
   518 __vms_ASTChildWithInfo(pInfo)
   519     struct procInfo *pInfo;
   519     struct procInfo *pInfo;
   520 {
   520 {
   521 #ifdef WAITDEBUG
   521 #ifdef WAITDEBUG
   522 	printf("__vms_ASTChildWithInfo pI=%x\n", pInfo);
   522 	printf("__vms_ASTChildWithInfo pI=%x\n", pInfo);
   523 #endif
   523 #endif
   603 
   603 
   604 documentation
   604 documentation
   605 "
   605 "
   606     this class realizes access to most (all ?) required operating system services;
   606     this class realizes access to most (all ?) required operating system services;
   607     some of it is very specific for unix, so do not depend on
   607     some of it is very specific for unix, so do not depend on
   608     things available here in your applications 
   608     things available here in your applications
   609     - some may not be found in other OS's or be slightly different ...
   609     - some may not be found in other OS's or be slightly different ...
   610 
   610 
   611     (On the other hand: I do not want to hide all features
   611     (On the other hand: I do not want to hide all features
   612      from you - in some situations it MAY be interesting to be
   612      from you - in some situations it MAY be interesting to be
   613      able to get down to a select or fork system call easily (at least on Unix systems).
   613      able to get down to a select or fork system call easily (at least on Unix systems).
   637 
   637 
   638 examples
   638 examples
   639 "
   639 "
   640   various queries
   640   various queries
   641 								[exBegin]
   641 								[exBegin]
   642     Transcript 
   642     Transcript
   643 	showCR:'hello ' , (OperatingSystem getLoginName)
   643 	showCR:'hello ' , (OperatingSystem getLoginName)
   644 								[exEnd]
   644 								[exEnd]
   645 
   645 
   646 								[exBegin]
   646 								[exBegin]
   647     OperatingSystem isUNIXlike ifTrue:[
   647     OperatingSystem isUNIXlike ifTrue:[
   650 	Transcript showCR:'this OS is not UNIX-like'
   650 	Transcript showCR:'this OS is not UNIX-like'
   651     ]
   651     ]
   652 								[exEnd]
   652 								[exEnd]
   653 
   653 
   654 								[exBegin]
   654 								[exBegin]
   655     Transcript 
   655     Transcript
   656 	showCR:'this machine is called ' , OperatingSystem getHostName
   656 	showCR:'this machine is called ' , OperatingSystem getHostName
   657 								[exEnd]
   657 								[exEnd]
   658 
   658 
   659 								[exBegin]
   659 								[exBegin]
   660     Transcript 
   660     Transcript
   661 	showCR:('this machine is in the '
   661 	showCR:('this machine is in the '
   662 	       , OperatingSystem getDomainName
   662 	       , OperatingSystem getDomainName
   663 	       , ' domain')
   663 	       , ' domain')
   664 								[exEnd]
   664 								[exEnd]
   665 
   665 
   666 								[exBegin]
   666 								[exBegin]
   667     Transcript 
   667     Transcript
   668 	showCR:('this machine''s CPU is a '
   668 	showCR:('this machine''s CPU is a '
   669 	       , OperatingSystem getCPUType
   669 	       , OperatingSystem getCPUType
   670 	       )
   670 	       )
   671 								[exEnd]
   671 								[exEnd]
   672 
   672 
   674     Transcript showCR:'executing ls command ...'.
   674     Transcript showCR:'executing ls command ...'.
   675     OperatingSystem executeCommand:'ls'.
   675     OperatingSystem executeCommand:'ls'.
   676     Transcript showCR:'... done.'.
   676     Transcript showCR:'... done.'.
   677 								[exEnd]
   677 								[exEnd]
   678 
   678 
   679   locking a file 
   679   locking a file
   680   (should be executed on two running smalltalks - not in two threads):
   680   (should be executed on two running smalltalks - not in two threads):
   681 								[exBegin]
   681 								[exBegin]
   682     |f|
   682     |f|
   683 
   683 
   684     f := 'testFile' asFilename readWriteStream.
   684     f := 'testFile' asFilename readWriteStream.
   685 
   685 
   686     10 timesRepeat:[
   686     10 timesRepeat:[
   687 	'about to lock ...' printCR.
   687 	'about to lock ...' printCR.
   688 	[
   688 	[
   689 	  OperatingSystem 
   689 	  OperatingSystem
   690 	    lockFD:(f fileDescriptor)
   690 	    lockFD:(f fileDescriptor)
   691 	    shared:false
   691 	    shared:false
   692 	    blocking:false
   692 	    blocking:false
   693 	] whileFalse:[
   693 	] whileFalse:[
   694 	    'process ' print. OperatingSystem getProcessId print. ' is waiting' printCR.
   694 	    'process ' print. OperatingSystem getProcessId print. ' is waiting' printCR.
   695 	    Delay waitForSeconds:1
   695 	    Delay waitForSeconds:1
   696 	].
   696 	].
   697 	'LOCKED ...' printCR.
   697 	'LOCKED ...' printCR.
   698 	Delay waitForSeconds:10.
   698 	Delay waitForSeconds:10.
   699 	'unlock ...' printCR.
   699 	'unlock ...' printCR.
   700 	(OperatingSystem 
   700 	(OperatingSystem
   701 	    unlockFD:(f fileDescriptor)) printCR.
   701 	    unlockFD:(f fileDescriptor)) printCR.
   702 	Delay waitForSeconds:3.
   702 	Delay waitForSeconds:3.
   703     ]
   703     ]
   704 								[exBegin]
   704 								[exBegin]
   705 "
   705 "
  1816 %}.
  1816 %}.
  1817     ^ -1
  1817     ^ -1
  1818 !
  1818 !
  1819 
  1819 
  1820 errorSymbolAndTextForNumber:errNr
  1820 errorSymbolAndTextForNumber:errNr
  1821     "return an array consisting of symbol &  message string from a unix errorNumber 
  1821     "return an array consisting of symbol &  message string from a unix errorNumber
  1822      (as returned by a system call). 
  1822      (as returned by a system call).
  1823      The returned message is in english (as found in /usr/include/errno.h)
  1823      The returned message is in english (as found in /usr/include/errno.h)
  1824      and should be replaced by a resource lookup before being presented to the user."
  1824      and should be replaced by a resource lookup before being presented to the user."
  1825 
  1825 
  1826     |sym text|
  1826     |sym text|
  1827 
  1827 
  2483 	    out_mbxdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  2483 	    out_mbxdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  2484 	    out_mbxdsc.dsc$b_class   = DSC$K_CLASS_S;
  2484 	    out_mbxdsc.dsc$b_class   = DSC$K_CLASS_S;
  2485 	    out_mbxdsc.dsc$a_pointer = out_mbxname.body;
  2485 	    out_mbxdsc.dsc$a_pointer = out_mbxname.body;
  2486 	}
  2486 	}
  2487 
  2487 
  2488 	/* 
  2488 	/*
  2489 	 * Build descriptor for command line
  2489 	 * Build descriptor for command line
  2490 	 */
  2490 	 */
  2491 	cmddsc.dsc$w_length  = strlen(fullCmdLine);
  2491 	cmddsc.dsc$w_length  = strlen(fullCmdLine);
  2492 	cmddsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  2492 	cmddsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  2493 	cmddsc.dsc$b_class   = DSC$K_CLASS_S;
  2493 	cmddsc.dsc$b_class   = DSC$K_CLASS_S;
  2505 
  2505 
  2506 	flags = CLI$M_NOWAIT;
  2506 	flags = CLI$M_NOWAIT;
  2507 
  2507 
  2508 	if (doFork == true) {
  2508 	if (doFork == true) {
  2509 # ifdef NOTDEF
  2509 # ifdef NOTDEF
  2510 	    /* 
  2510 	    /*
  2511 	     * Allocate an event flag to signal process termination
  2511 	     * Allocate an event flag to signal process termination
  2512 	     */
  2512 	     */
  2513 	    status = LIB$GET_EF(&siop->event_flag);
  2513 	    status = LIB$GET_EF(&siop->event_flag);
  2514 	    if (status != SS$_NORMAL) {
  2514 	    if (status != SS$_NORMAL) {
  2515 		vaxc$errno = status;
  2515 		vaxc$errno = status;
  2548 			       (in_channel ? &in_mbxdsc : 0),
  2548 			       (in_channel ? &in_mbxdsc : 0),
  2549 			       (out_channel ? &out_mbxdsc : 0),
  2549 			       (out_channel ? &out_mbxdsc : 0),
  2550 			       &flags,
  2550 			       &flags,
  2551 			       0,               /* process name */
  2551 			       0,               /* process name */
  2552 			       &(pInfo->pid),
  2552 			       &(pInfo->pid),
  2553 			       &(pInfo->returnStatus), 
  2553 			       &(pInfo->returnStatus),
  2554 			       &procEventFlag,
  2554 			       &procEventFlag,
  2555 			       __vms_ASTChildWithInfo,
  2555 			       __vms_ASTChildWithInfo,
  2556 			       pInfo,           /* AST argument */
  2556 			       pInfo,           /* AST argument */
  2557 			       0,               /* prompt */
  2557 			       0,               /* prompt */
  2558 			       (cli ? &clidsc : 0)
  2558 			       (cli ? &clidsc : 0)
  2633 
  2633 
  2634     |pid exitStatus sema|
  2634     |pid exitStatus sema|
  2635 
  2635 
  2636     sema := Semaphore new name:'OS command wait'.
  2636     sema := Semaphore new name:'OS command wait'.
  2637 
  2637 
  2638     pid := Processor 
  2638     pid := Processor
  2639 		monitor:[
  2639 		monitor:[
  2640 		    self 
  2640 		    self
  2641 			startProcess:aCommandString
  2641 			startProcess:aCommandString
  2642 			inputFrom:anExternalInStream 
  2642 			inputFrom:anExternalInStream
  2643 			outputTo:anExternalOutStream 
  2643 			outputTo:anExternalOutStream
  2644 			errorTo:anExternalErrStream.
  2644 			errorTo:anExternalErrStream.
  2645 		] 
  2645 		]
  2646 		action:[:status |
  2646 		action:[:status |
  2647 		    status stillAlive ifFalse:[
  2647 		    status stillAlive ifFalse:[
  2648 			exitStatus := status.
  2648 			exitStatus := status.
  2649 			self closePid:pid.
  2649 			self closePid:pid.
  2650 			sema signal
  2650 			sema signal
  2676 
  2676 
  2677     |pid exitStatus sema|
  2677     |pid exitStatus sema|
  2678 
  2678 
  2679     sema := Semaphore new name:'OS command wait'.
  2679     sema := Semaphore new name:'OS command wait'.
  2680 
  2680 
  2681     pid := Processor 
  2681     pid := Processor
  2682 		monitor:[self startProcess:aCommandString] 
  2682 		monitor:[self startProcess:aCommandString]
  2683 		action:[:status |
  2683 		action:[:status |
  2684 			status stillAlive ifFalse:[
  2684 			status stillAlive ifFalse:[
  2685 			    exitStatus := status.
  2685 			    exitStatus := status.
  2686 			    self closePid:pid.
  2686 			    self closePid:pid.
  2687 			    sema signal
  2687 			    sema signal
  2697 	^ aBlock value:exitStatus
  2697 	^ aBlock value:exitStatus
  2698     ].
  2698     ].
  2699     ^ true.
  2699     ^ true.
  2700 
  2700 
  2701     "
  2701     "
  2702      OperatingSystem executeCommand:'sleep 30' onError:[]. 
  2702      OperatingSystem executeCommand:'sleep 30' onError:[].
  2703      OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. 
  2703      OperatingSystem executeCommand:'pwd' onError:[:status|status inspect].
  2704      OperatingSystem executeCommand:'ls -l' onError:[]. 
  2704      OperatingSystem executeCommand:'ls -l' onError:[].
  2705      OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. 
  2705      OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect].
  2706      OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. 
  2706      OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect].
  2707     "
  2707     "
  2708 
  2708 
  2709     "Created: 22.12.1995 / 14:49:59 / stefan"
  2709     "Created: 22.12.1995 / 14:49:59 / stefan"
  2710     "Modified: 25.3.1997 / 11:06:43 / stefan"
  2710     "Modified: 25.3.1997 / 11:06:43 / stefan"
  2711     "Modified: 19.4.1997 / 18:14:41 / cg"
  2711     "Modified: 19.4.1997 / 18:14:41 / cg"
  2743 	^ aBlock value:exitStatus
  2743 	^ aBlock value:exitStatus
  2744     ].
  2744     ].
  2745     ^ true.
  2745     ^ true.
  2746 
  2746 
  2747     "
  2747     "
  2748      OperatingSystem executeCommand:'sleep 30' onError:[]. 
  2748      OperatingSystem executeCommand:'sleep 30' onError:[].
  2749      OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. 
  2749      OperatingSystem executeCommand:'pwd' onError:[:status|status inspect].
  2750      OperatingSystem executeCommand:'ls -l' onError:[]. 
  2750      OperatingSystem executeCommand:'ls -l' onError:[].
  2751      OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. 
  2751      OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect].
  2752      OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. 
  2752      OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect].
  2753     "
  2753     "
  2754 
  2754 
  2755     "Created: 28.1.1998 / 14:12:15 / md"
  2755     "Created: 28.1.1998 / 14:12:15 / md"
  2756 !
  2756 !
  2757 
  2757 
  2758 fork
  2758 fork
  2759     "fork a new (HEAVY-weight) unix process.
  2759     "fork a new (HEAVY-weight) unix process.
  2760      Not supported with MSDOS & VMS systems.
  2760      Not supported with MSDOS & VMS systems.
  2761      Dont confuse this with Block>>fork, which creates 
  2761      Dont confuse this with Block>>fork, which creates
  2762      lightweight smalltalk processes. This method will return
  2762      lightweight smalltalk processes. This method will return
  2763      0 to the child process, and a non-zero number (which is the childs
  2763      0 to the child process, and a non-zero number (which is the childs
  2764      unix-process-id) to the parent (original) process.
  2764      unix-process-id) to the parent (original) process.
  2765 
  2765 
  2766      In normal situations, you dont need to use this low level entry; see
  2766      In normal situations, you dont need to use this low level entry; see
  2917      err := 'err' asFilename writeStream.
  2917      err := 'err' asFilename writeStream.
  2918 
  2918 
  2919      sema := Semaphore new.
  2919      sema := Semaphore new.
  2920      pid := OperatingSystem startProcess:'sleep 10; grep drw' inputFrom:in outputTo:out errorTo:err.
  2920      pid := OperatingSystem startProcess:'sleep 10; grep drw' inputFrom:in outputTo:out errorTo:err.
  2921 
  2921 
  2922      The following will no longer work. monitorPid has disappeared 
  2922      The following will no longer work. monitorPid has disappeared
  2923 
  2923 
  2924      pid notNil ifTrue:[
  2924      pid notNil ifTrue:[
  2925 	 Processor monitorPid:pid action:[:OSstatus | sema signal ].
  2925 	 Processor monitorPid:pid action:[:OSstatus | sema signal ].
  2926      ].
  2926      ].
  2927      in close.
  2927      in close.
  2980 "/    ^ self executeCommand:('mkdir ', newPathName)
  2980 "/    ^ self executeCommand:('mkdir ', newPathName)
  2981 
  2981 
  2982     self primitiveFailed
  2982     self primitiveFailed
  2983 
  2983 
  2984     "
  2984     "
  2985      OperatingSystem createDirectory:'foo'  
  2985      OperatingSystem createDirectory:'foo'
  2986     "
  2986     "
  2987 
  2987 
  2988     "Modified: 20.12.1995 / 11:24:13 / stefan"
  2988     "Modified: 20.12.1995 / 11:24:13 / stefan"
  2989     "Modified: 29.6.1996 / 14:06:54 / cg"
  2989     "Modified: 29.6.1996 / 14:06:54 / cg"
  2990 !
  2990 !
  2995 
  2995 
  2996     (oldPath isString not or:[newPath isString not]) ifTrue:[
  2996     (oldPath isString not or:[newPath isString not]) ifTrue:[
  2997 	"/
  2997 	"/
  2998 	"/ bad argument(s) given
  2998 	"/ bad argument(s) given
  2999 	"/
  2999 	"/
  3000 	^ self primitiveFailed 
  3000 	^ self primitiveFailed
  3001     ].
  3001     ].
  3002 
  3002 
  3003     "/
  3003     "/
  3004     "/ this OperatingSystem does not support links
  3004     "/ this OperatingSystem does not support links
  3005     "/
  3005     "/
  3034 
  3034 
  3035     "Modified: 7.3.1996 / 15:26:30 / cg"
  3035     "Modified: 7.3.1996 / 15:26:30 / cg"
  3036 !
  3036 !
  3037 
  3037 
  3038 removeDirectory:fullPathName
  3038 removeDirectory:fullPathName
  3039     "remove the directory named 'fullPathName'. 
  3039     "remove the directory named 'fullPathName'.
  3040      The directory must be empty and you must have appropriate access rights.
  3040      The directory must be empty and you must have appropriate access rights.
  3041      Return true if successful, false if directory is not empty or no permission.
  3041      Return true if successful, false if directory is not empty or no permission.
  3042      This is a lowLevel entry - use Filename protocol for compatibility."
  3042      This is a lowLevel entry - use Filename protocol for compatibility."
  3043 
  3043 
  3044 %{
  3044 %{
  3097 %}.
  3097 %}.
  3098     ^ self primitiveFailed
  3098     ^ self primitiveFailed
  3099 !
  3099 !
  3100 
  3100 
  3101 renameFile:oldPath to:newPath
  3101 renameFile:oldPath to:newPath
  3102     "rename the file 'oldPath' to 'newPath'. 
  3102     "rename the file 'oldPath' to 'newPath'.
  3103      Someone else has to care for the names to be correct and 
  3103      Someone else has to care for the names to be correct and
  3104      correct for the OS used - therefore, this should not be called
  3104      correct for the OS used - therefore, this should not be called
  3105      directlt. Instead, use Filename protocol to rename; this cares for
  3105      directlt. Instead, use Filename protocol to rename; this cares for
  3106      any invalid names.
  3106      any invalid names.
  3107      Returns true if successful, false if not"
  3107      Returns true if successful, false if not"
  3108 
  3108 
  3168 	} while (fd < 0 && errno == EINTR);
  3168 	} while (fd < 0 && errno == EINTR);
  3169 	if (fd < 0) {
  3169 	if (fd < 0) {
  3170 	    @global(LastErrorNumber) = __MKSMALLINT(errno);
  3170 	    @global(LastErrorNumber) = __MKSMALLINT(errno);
  3171 	    RETURN ( false );
  3171 	    RETURN ( false );
  3172 	}
  3172 	}
  3173         
  3173 
  3174 	ret = ftruncate(fd, __intVal(newSize));
  3174 	ret = ftruncate(fd, __intVal(newSize));
  3175 	close(fd);
  3175 	close(fd);
  3176 	if (ret < 0) {
  3176 	if (ret < 0) {
  3177 	    @global(LastErrorNumber) = __MKSMALLINT(errno);
  3177 	    @global(LastErrorNumber) = __MKSMALLINT(errno);
  3178 	    RETURN ( false );
  3178 	    RETURN ( false );
  3179 	} 
  3179 	}
  3180 	RETURN (true);
  3180 	RETURN (true);
  3181     }
  3181     }
  3182 # endif /* using FTRUNCATE */
  3182 # endif /* using FTRUNCATE */
  3183 #endif
  3183 #endif
  3184 %}.
  3184 %}.
  3186 ! !
  3186 ! !
  3187 
  3187 
  3188 !OpenVMSOperatingSystem class methodsFor:'file access rights'!
  3188 !OpenVMSOperatingSystem class methodsFor:'file access rights'!
  3189 
  3189 
  3190 accessMaskFor:aSymbol
  3190 accessMaskFor:aSymbol
  3191     "return the access bits mask for numbers as returned by 
  3191     "return the access bits mask for numbers as returned by
  3192      OperatingSystem>>accessModeOf:
  3192      OperatingSystem>>accessModeOf:
  3193      and expected by OperatingSystem>>changeAccessModeOf:to:.
  3193      and expected by OperatingSystem>>changeAccessModeOf:to:.
  3194      Since these numbers are OS dependent, always use the mask
  3194      Since these numbers are OS dependent, always use the mask
  3195      (never hardcode 8rxxx into your code)."
  3195      (never hardcode 8rxxx into your code)."
  3196 
  3196 
  3245 !
  3245 !
  3246 
  3246 
  3247 accessModeOf:aPathName
  3247 accessModeOf:aPathName
  3248     "return a number representing access rights rwxrwxrwx for owner,
  3248     "return a number representing access rights rwxrwxrwx for owner,
  3249      group and others. Return nil if such a file does not exist.
  3249      group and others. Return nil if such a file does not exist.
  3250      Notice that the returned number is OS dependent - use the 
  3250      Notice that the returned number is OS dependent - use the
  3251      modeMasks as returned by OperatingSystem>>accessMaskFor:"
  3251      modeMasks as returned by OperatingSystem>>accessMaskFor:"
  3252 
  3252 
  3253     "
  3253     "
  3254      this could have been implemented as:
  3254      this could have been implemented as:
  3255 	(self infoOf:aPathName) at:#mode
  3255 	(self infoOf:aPathName) at:#mode
  3285 !
  3285 !
  3286 
  3286 
  3287 changeAccessModeOf:aPathName to:modeBits
  3287 changeAccessModeOf:aPathName to:modeBits
  3288     "change the access rights of aPathName to the OS dependent modeBits.
  3288     "change the access rights of aPathName to the OS dependent modeBits.
  3289      You should construct this mask using accessMaskFor, to be OS
  3289      You should construct this mask using accessMaskFor, to be OS
  3290      independent. Return true if changed, 
  3290      independent. Return true if changed,
  3291      false if such a file does not exist or change was not allowd."
  3291      false if such a file does not exist or change was not allowd."
  3292 
  3292 
  3293 %{
  3293 %{
  3294     int ret;
  3294     int ret;
  3295 
  3295 
  3314 lockFD:aFileDescriptor shared:isSharedReadLock blocking:blockIfLocked
  3314 lockFD:aFileDescriptor shared:isSharedReadLock blocking:blockIfLocked
  3315    "set a lock on the file represented by aFileDescriptor.
  3315    "set a lock on the file represented by aFileDescriptor.
  3316     (such as returned by ExternalStream>>fileDescriptor).
  3316     (such as returned by ExternalStream>>fileDescriptor).
  3317     On some systems, only advisory locks are available -
  3317     On some systems, only advisory locks are available -
  3318     these depends on other accessors to also perform the locking operation.
  3318     these depends on other accessors to also perform the locking operation.
  3319     If they do not, they may still access the file 
  3319     If they do not, they may still access the file
  3320     (on some systems, locks are mandatory, on others, they are advisory). 
  3320     (on some systems, locks are mandatory, on others, they are advisory).
  3321     The isSharedReadLock argument (if true) specifies if multiple readers
  3321     The isSharedReadLock argument (if true) specifies if multiple readers
  3322     are to be allowed - if false, they are not.
  3322     are to be allowed - if false, they are not.
  3323     On some systems, all locks are non-exclusive locks.
  3323     On some systems, all locks are non-exclusive locks.
  3324 
  3324 
  3325     Returns true, if the lock was aquired, false otherwise.
  3325     Returns true, if the lock was aquired, false otherwise.
  3326 
  3326 
  3327     Notice, that not all OS's support these locks; 
  3327     Notice, that not all OS's support these locks;
  3328     on some, this may simply be a no-op.
  3328     on some, this may simply be a no-op.
  3329     Also notice, that some systems block the process, to wait for the lock.
  3329     Also notice, that some systems block the process, to wait for the lock.
  3330     This can (again: on some systems) be avoided by passing a false blockIfLocked
  3330     This can (again: on some systems) be avoided by passing a false blockIfLocked
  3331     argument."
  3331     argument."
  3332 
  3332 
  3334     if (__isSmallInteger(aFileDescriptor)) {
  3334     if (__isSmallInteger(aFileDescriptor)) {
  3335 	int fd = __intVal(aFileDescriptor);
  3335 	int fd = __intVal(aFileDescriptor);
  3336 	int lockArg;
  3336 	int lockArg;
  3337 
  3337 
  3338 	/*
  3338 	/*
  3339 	 * claus: sigh - each one has a different interface ... 
  3339 	 * claus: sigh - each one has a different interface ...
  3340 	 */
  3340 	 */
  3341 #if defined(F_SETLK)
  3341 #if defined(F_SETLK)
  3342 	{
  3342 	{
  3343 	    /* 
  3343 	    /*
  3344 	     * new fcntl(SETLK) interface;
  3344 	     * new fcntl(SETLK) interface;
  3345 	     * available on SYSV4 and Linux
  3345 	     * available on SYSV4 and Linux
  3346 	     */
  3346 	     */
  3347 	    struct flock flock;
  3347 	    struct flock flock;
  3348 
  3348 
  3366 	}
  3366 	}
  3367 
  3367 
  3368 #else /* no F_SETLK available */
  3368 #else /* no F_SETLK available */
  3369 
  3369 
  3370 # if defined(LOCK_EX) && defined(LOCK_UN)
  3370 # if defined(LOCK_EX) && defined(LOCK_UN)
  3371 	/* 
  3371 	/*
  3372 	 * BSD 4.3 advisory locks
  3372 	 * BSD 4.3 advisory locks
  3373 	 */
  3373 	 */
  3374 	lockArg = LOCK_EX;
  3374 	lockArg = LOCK_EX;
  3375 #  if defined(LOCK_SH)
  3375 #  if defined(LOCK_SH)
  3376 	if (isSharedReadLock == true) {
  3376 	if (isSharedReadLock == true) {
  3387 	}
  3387 	}
  3388 
  3388 
  3389 # else /* no flock available */
  3389 # else /* no flock available */
  3390 
  3390 
  3391 #  if defined(F_LOCK) && defined(F_UNLOCK)
  3391 #  if defined(F_LOCK) && defined(F_UNLOCK)
  3392 	/* 
  3392 	/*
  3393 	 * SYSV3 advisory locks
  3393 	 * SYSV3 advisory locks
  3394 	 */
  3394 	 */
  3395 	if (lockf(fd, F_LOCK, 0) != -1) {
  3395 	if (lockf(fd, F_LOCK, 0) != -1) {
  3396 	    RETURN (true);
  3396 	    RETURN (true);
  3397 	}
  3397 	}
  3481 !
  3481 !
  3482 
  3482 
  3483 unlockFD:aFileDescriptor
  3483 unlockFD:aFileDescriptor
  3484     "clear a file lock on the file represented by aFileDescriptor,
  3484     "clear a file lock on the file represented by aFileDescriptor,
  3485      which was previously aquired by #lockFD:.
  3485      which was previously aquired by #lockFD:.
  3486      Return false, if the unlock failed 
  3486      Return false, if the unlock failed
  3487      (which may happens when a wrong fd is passed, 
  3487      (which may happens when a wrong fd is passed,
  3488       no lock was set previously, or the systsem does not support locks).
  3488       no lock was set previously, or the systsem does not support locks).
  3489      Notice, that not all OS's support file locks; 
  3489      Notice, that not all OS's support file locks;
  3490      on some, this may simply be a no-op."
  3490      on some, this may simply be a no-op."
  3491      
  3491 
  3492 %{
  3492 %{
  3493     if (__isSmallInteger(aFileDescriptor)) {
  3493     if (__isSmallInteger(aFileDescriptor)) {
  3494 	int fd = __intVal(aFileDescriptor);
  3494 	int fd = __intVal(aFileDescriptor);
  3495 
  3495 
  3496 	/*
  3496 	/*
  3524 	}
  3524 	}
  3525 
  3525 
  3526 # else /* no flock available */
  3526 # else /* no flock available */
  3527 
  3527 
  3528 #  if defined(F_LOCK) && defined(F_UNLOCK)
  3528 #  if defined(F_LOCK) && defined(F_UNLOCK)
  3529 	/* 
  3529 	/*
  3530 	 * SYSV3 advisory locks
  3530 	 * SYSV3 advisory locks
  3531 	 */
  3531 	 */
  3532 	if (lockf(fd, F_UNLOCK, 0) != -1) {
  3532 	if (lockf(fd, F_UNLOCK, 0) != -1) {
  3533 	    RETURN (true);
  3533 	    RETURN (true);
  3534 	}
  3534 	}
  3542 
  3542 
  3543 !OpenVMSOperatingSystem class methodsFor:'file queries'!
  3543 !OpenVMSOperatingSystem class methodsFor:'file queries'!
  3544 
  3544 
  3545 caseSensitiveFilenames
  3545 caseSensitiveFilenames
  3546     "return true, if the OS has caseSensitive file naming.
  3546     "return true, if the OS has caseSensitive file naming.
  3547      On MSDOS, this will return false; 
  3547      On MSDOS, this will return false;
  3548      on a real OS, we return true."
  3548      on a real OS, we return true."
  3549 
  3549 
  3550     ^ false
  3550     ^ false
  3551 !
  3551 !
  3552 
  3552 
  3556      return the true pathName and is therefore used as a fallback
  3556      return the true pathName and is therefore used as a fallback
  3557      if realPath and popen failed."
  3557      if realPath and popen failed."
  3558 
  3558 
  3559     |names n "{ Class: SmallInteger }" |
  3559     |names n "{ Class: SmallInteger }" |
  3560 
  3560 
  3561     names := pathName 
  3561     names := pathName
  3562 		asCollectionOfSubstringsSeparatedBy:self fileSeparator.
  3562 		asCollectionOfSubstringsSeparatedBy:self fileSeparator.
  3563     names := names asOrderedCollection.
  3563     names := names asOrderedCollection.
  3564     "
  3564     "
  3565      cut off initial double-slashes
  3565      cut off initial double-slashes
  3566     "
  3566     "
  3583     ].
  3583     ].
  3584 
  3584 
  3585     "
  3585     "
  3586      cut off parent-dirs at end
  3586      cut off parent-dirs at end
  3587     "
  3587     "
  3588     [(n > 2) 
  3588     [(n > 2)
  3589      and:[(names endsWith:#('..'))
  3589      and:[(names endsWith:#('..'))
  3590      and:[((names at:(n - 1)) startsWith:'.') not ]]] whileTrue:[
  3590      and:[((names at:(n - 1)) startsWith:'.') not ]]] whileTrue:[
  3591 	names removeLast; removeLast.
  3591 	names removeLast; removeLast.
  3592 	n := n - 2.
  3592 	n := n - 2.
  3593     ].
  3593     ].
  3594 
  3594 
  3595     ^ names asStringWith:self fileSeparator 
  3595     ^ names asStringWith:self fileSeparator
  3596 		    from:1
  3596 		    from:1
  3597 		    to:n
  3597 		    to:n
  3598 		    compressTabs:false final:nil 
  3598 		    compressTabs:false final:nil
  3599 
  3599 
  3600     "
  3600     "
  3601      OperatingSystem compressPath:'./..'    
  3601      OperatingSystem compressPath:'./..'
  3602      OperatingSystem compressPath:'/foo/bar/baz/..'  
  3602      OperatingSystem compressPath:'/foo/bar/baz/..'
  3603      OperatingSystem compressPath:'foo/bar/baz/..'  
  3603      OperatingSystem compressPath:'foo/bar/baz/..'
  3604      OperatingSystem compressPath:'foo/bar/baz/../'  
  3604      OperatingSystem compressPath:'foo/bar/baz/../'
  3605      OperatingSystem compressPath:'foo/bar/baz/..///' 
  3605      OperatingSystem compressPath:'foo/bar/baz/..///'
  3606      OperatingSystem compressPath:'///foo/bar/baz/..///' 
  3606      OperatingSystem compressPath:'///foo/bar/baz/..///'
  3607     "
  3607     "
  3608 
  3608 
  3609     "Modified: 1.11.1996 / 20:13:48 / cg"
  3609     "Modified: 1.11.1996 / 20:13:48 / cg"
  3610 !
  3610 !
  3611 
  3611 
  3617 
  3617 
  3618     ^ $/
  3618     ^ $/
  3619 !
  3619 !
  3620 
  3620 
  3621 getDriveList
  3621 getDriveList
  3622     "return a list of volumes in the system. 
  3622     "return a list of volumes in the system.
  3623      On unix, no such thing like a volume exists 
  3623      On unix, no such thing like a volume exists
  3624      - there, a syntetic list with root, home & current is returned. 
  3624      - there, a syntetic list with root, home & current is returned.
  3625      On MSDOS, a list of drive letters is (eventually) returned.
  3625      On MSDOS, a list of drive letters is (eventually) returned.
  3626      On VMS, a list of volumes is (eventually) returned."
  3626      On VMS, a list of volumes is (eventually) returned."
  3627 
  3627 
  3628     |list|
  3628     |list|
  3629 
  3629 
  3638 %}.
  3638 %}.
  3639     "/
  3639     "/
  3640     "/ default: retrurn array filled with
  3640     "/ default: retrurn array filled with
  3641     "/ root, home and current directories.
  3641     "/ root, home and current directories.
  3642     "/
  3642     "/
  3643     ^ Array 
  3643     ^ Array
  3644 	with:'/'
  3644 	with:'/'
  3645 	with:(self getHomeDirectory)
  3645 	with:(self getHomeDirectory)
  3646 	with:(Filename currentDirectory pathName)
  3646 	with:(Filename currentDirectory pathName)
  3647 !
  3647 !
  3648 
  3648 
  3649 infoOf:aPathName
  3649 infoOf:aPathName
  3650     "return some object filled with info for the file 'aPathName';
  3650     "return some object filled with info for the file 'aPathName';
  3651      the info (for which corresponding access methods are understood by
  3651      the info (for which corresponding access methods are understood by
  3652      the returned object) is:
  3652      the returned object) is:
  3653 	 type            - a symbol giving the files type
  3653 	 type            - a symbol giving the files type
  3654 	 mode            - numeric access mode 
  3654 	 mode            - numeric access mode
  3655 	 uid             - owners user id
  3655 	 uid             - owners user id
  3656 	 gid             - owners group id
  3656 	 gid             - owners group id
  3657 	 size            - files size
  3657 	 size            - files size
  3658 	 id              - files number (i.e. inode number)
  3658 	 id              - files number (i.e. inode number)
  3659 	 accessed        - last access time (as Timestamp)
  3659 	 accessed        - last access time (as Timestamp)
  3666 	 fixedHeaderSize     - (VMS only:) fixed header size in a variable record format
  3666 	 fixedHeaderSize     - (VMS only:) fixed header size in a variable record format
  3667 	 recordSize          - (VMS only:) record size.
  3667 	 recordSize          - (VMS only:) record size.
  3668 
  3668 
  3669      Some of the fields may be returned as nil on systems which do not provide
  3669      Some of the fields may be returned as nil on systems which do not provide
  3670      all of the information.
  3670      all of the information.
  3671      Return nil if such a file does not exist. 
  3671      Return nil if such a file does not exist.
  3672      For symbolic links (if supported by the OS), 
  3672      For symbolic links (if supported by the OS),
  3673      the info of the pointed-to-file (i.e. the target) is returned;
  3673      the info of the pointed-to-file (i.e. the target) is returned;
  3674      use #linkInfoOf: to get info about the link itself.
  3674      use #linkInfoOf: to get info about the link itself.
  3675     "
  3675     "
  3676 
  3676 
  3677     |info type mode uid gid size id 
  3677     |info type mode uid gid size id
  3678      atime mtime ctime 
  3678      atime mtime ctime
  3679      aOStime mOStime cOStime
  3679      aOStime mOStime cOStime
  3680      aYr aMon aDay aHr aMin aSec aMS
  3680      aYr aMon aDay aHr aMin aSec aMS
  3681      mYr mMon mDay mHr mMin mSec mMS
  3681      mYr mMon mDay mHr mMin mSec mMS
  3682      cYr cMon cDay cHr cMin cSec cMS
  3682      cYr cMon cDay cHr cMin cSec cMS
  3683      name2 
  3683      name2
  3684      recordFormat recordAttribs fixedHeaderSize recordSize
  3684      recordFormat recordAttribs fixedHeaderSize recordSize
  3685      recordFormatNumeric|
  3685      recordFormatNumeric|
  3686 
  3686 
  3687 %{
  3687 %{
  3688     struct stat buf;
  3688     struct stat buf;
  3823 	cOStime = __MKUINT(buf.st_ctime);
  3823 	cOStime = __MKUINT(buf.st_ctime);
  3824     }
  3824     }
  3825 %}.
  3825 %}.
  3826     mode notNil ifTrue:[
  3826     mode notNil ifTrue:[
  3827 	aOStime notNil ifTrue:[
  3827 	aOStime notNil ifTrue:[
  3828 	    atime := AbsoluteTime fromOSTime:(aOStime * 1000).
  3828 	    atime := Timestamp fromOSTime:(aOStime * 1000).
  3829 	    mtime := AbsoluteTime fromOSTime:(mOStime * 1000).
  3829 	    mtime := Timestamp fromOSTime:(mOStime * 1000).
  3830 	    ctime := AbsoluteTime fromOSTime:(cOStime * 1000).
  3830 	    ctime := Timestamp fromOSTime:(cOStime * 1000).
  3831 	] ifFalse:[
  3831 	] ifFalse:[
  3832 	    atime := AbsoluteTime day:aDay month:aMon year:aYr hour:aHr minutes:aMin seconds:aSec milliseconds:aMS.
  3832 	    atime := Timestamp day:aDay month:aMon year:aYr hour:aHr minutes:aMin seconds:aSec milliseconds:aMS.
  3833 	    mtime := AbsoluteTime day:mDay month:mMon year:mYr hour:mHr minutes:mMin seconds:mSec milliseconds:mMS.
  3833 	    mtime := Timestamp day:mDay month:mMon year:mYr hour:mHr minutes:mMin seconds:mSec milliseconds:mMS.
  3834 	    ctime := AbsoluteTime day:cDay month:cMon year:cYr hour:cHr minutes:cMin seconds:cSec milliseconds:cMS.
  3834 	    ctime := Timestamp day:cDay month:cMon year:cYr hour:cHr minutes:cMin seconds:cSec milliseconds:cMS.
  3835 	].
  3835 	].
  3836 
  3836 
  3837 	info := FileStatusInfo
  3837 	info := FileStatusInfo
  3838 		    type:type 
  3838 		    type:type
  3839 		    mode:mode 
  3839 		    mode:mode
  3840 		    uid:uid 
  3840 		    uid:uid
  3841 		    gid:gid 
  3841 		    gid:gid
  3842 		    size:size 
  3842 		    size:size
  3843 		    id:id 
  3843 		    id:id
  3844 		    accessed:atime 
  3844 		    accessed:atime
  3845 		    modified:mtime 
  3845 		    modified:mtime
  3846 		    statusChanged:ctime
  3846 		    statusChanged:ctime
  3847 		    path:nil.
  3847 		    path:nil.
  3848 
  3848 
  3849 	recordFormat notNil ifTrue:[
  3849 	recordFormat notNil ifTrue:[
  3850 	    "/ additional VMS info
  3850 	    "/ additional VMS info
  3955 
  3955 
  3956     ^ (self linkInfoOf:aPathName) notNil
  3956     ^ (self linkInfoOf:aPathName) notNil
  3957 
  3957 
  3958     "
  3958     "
  3959      OperatingSystem isSymbolicLink:'Make.proto'
  3959      OperatingSystem isSymbolicLink:'Make.proto'
  3960      OperatingSystem isSymbolicLink:'Makefile' 
  3960      OperatingSystem isSymbolicLink:'Makefile'
  3961     "
  3961     "
  3962 !
  3962 !
  3963 
  3963 
  3964 isValidPath:aPathName
  3964 isValidPath:aPathName
  3965     "return true, if 'aPathName' is a valid path name
  3965     "return true, if 'aPathName' is a valid path name
  4013     ^ self primitiveFailed
  4013     ^ self primitiveFailed
  4014 !
  4014 !
  4015 
  4015 
  4016 linkInfoOf:aPathName
  4016 linkInfoOf:aPathName
  4017     "return a dictionary filled with info for the file 'aPathName',
  4017     "return a dictionary filled with info for the file 'aPathName',
  4018      IFF aPathName is a symbolic link. 
  4018      IFF aPathName is a symbolic link.
  4019      If aPathName is invalid, or its NOT a symbolic link, nil is returned.
  4019      If aPathName is invalid, or its NOT a symbolic link, nil is returned.
  4020      (which means, that systems like VMS or MSDOS always return nil here.)
  4020      (which means, that systems like VMS or MSDOS always return nil here.)
  4021 
  4021 
  4022      The contents of the dictionary gives info about the link itself,
  4022      The contents of the dictionary gives info about the link itself,
  4023      on contrast to #infoOf:, which returns the info of the pointed to file
  4023      on contrast to #infoOf:, which returns the info of the pointed to file
  4024      in case of a symbolic link."
  4024      in case of a symbolic link."
  4025      
  4025 
  4026     ^ nil
  4026     ^ nil
  4027 !
  4027 !
  4028 
  4028 
  4029 parentDirectoryName
  4029 parentDirectoryName
  4030     "return the name used to refer to parent directories.
  4030     "return the name used to refer to parent directories.
  4073     "
  4073     "
  4074      OperatingSystem pathNameOf:'.'
  4074      OperatingSystem pathNameOf:'.'
  4075      OperatingSystem pathNameOf:'../smalltalk/../smalltalk'
  4075      OperatingSystem pathNameOf:'../smalltalk/../smalltalk'
  4076      OperatingSystem pathNameOf:'../../..'
  4076      OperatingSystem pathNameOf:'../../..'
  4077      OperatingSystem pathNameOf:'..'
  4077      OperatingSystem pathNameOf:'..'
  4078      OperatingSystem pathNameOf:'/tmp////' 
  4078      OperatingSystem pathNameOf:'/tmp////'
  4079      OperatingSystem pathNameOf:'/foo/bar' 
  4079      OperatingSystem pathNameOf:'/foo/bar'
  4080      OperatingSystem pathNameOf:'/foo/bar/'
  4080      OperatingSystem pathNameOf:'/foo/bar/'
  4081      OperatingSystem pathNameOf:'/foo/bar//'
  4081      OperatingSystem pathNameOf:'/foo/bar//'
  4082     "
  4082     "
  4083 
  4083 
  4084     "Modified: 29.11.1996 / 18:02:12 / stefan"
  4084     "Modified: 29.11.1996 / 18:02:12 / stefan"
  4146 %{  /* STACK: 16000 */
  4146 %{  /* STACK: 16000 */
  4147 
  4147 
  4148     if (__isString(pathName)) {
  4148     if (__isString(pathName)) {
  4149 
  4149 
  4150 #ifdef HAS_GETCWD
  4150 #ifdef HAS_GETCWD
  4151 	if (strcmp(__stringVal(pathName), "[]") == 0) 
  4151 	if (strcmp(__stringVal(pathName), "[]") == 0)
  4152 	{
  4152 	{
  4153 	    char nameBuffer[MAXPATHLEN + 1];
  4153 	    char nameBuffer[MAXPATHLEN + 1];
  4154 
  4154 
  4155 	    if (@global(CurrentDirectory) == nil) {
  4155 	    if (@global(CurrentDirectory) == nil) {
  4156 		if (getcwd(nameBuffer, MAXPATHLEN)) {
  4156 		if (getcwd(nameBuffer, MAXPATHLEN)) {
  4181 timeOfLastAccess:aPathName
  4181 timeOfLastAccess:aPathName
  4182     "return the time, when the file was last accessed.
  4182     "return the time, when the file was last accessed.
  4183      For nonexistent files, nil is returned."
  4183      For nonexistent files, nil is returned."
  4184 
  4184 
  4185     "could be implemented as:
  4185     "could be implemented as:
  4186 	(self infoOf:aPathName) accessed 
  4186 	(self infoOf:aPathName) accessed
  4187     "
  4187     "
  4188 
  4188 
  4189     |osSeconds i|
  4189     |osSeconds i|
  4190 %{
  4190 %{
  4191 #if !defined(WIN32) && !defined(__VMS__)
  4191 #if !defined(WIN32) && !defined(__VMS__)
  4208 	}
  4208 	}
  4209 	osSeconds = __MKUINT(buf.st_atime);
  4209 	osSeconds = __MKUINT(buf.st_atime);
  4210     }
  4210     }
  4211 #endif
  4211 #endif
  4212 %}.
  4212 %}.
  4213     osSeconds notNil ifTrue:[^ AbsoluteTime fromOSTime:(osSeconds * 1000)].
  4213     osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)].
  4214 
  4214 
  4215     i := self infoOf:aPathName.
  4215     i := self infoOf:aPathName.
  4216     i notNil ifTrue:[^ i accessed].
  4216     i notNil ifTrue:[^ i accessed].
  4217     ^ nil.
  4217     ^ nil.
  4218 
  4218 
  4220      OperatingSystem timeOfLastAccess:'/'
  4220      OperatingSystem timeOfLastAccess:'/'
  4221     "
  4221     "
  4222 !
  4222 !
  4223 
  4223 
  4224 timeOfLastChange:aPathName
  4224 timeOfLastChange:aPathName
  4225     "return the time, when the file was last changed. 
  4225     "return the time, when the file was last changed.
  4226      For nonexistent files, nil is returned."
  4226      For nonexistent files, nil is returned."
  4227 
  4227 
  4228     "could be implemented as:
  4228     "could be implemented as:
  4229 	(self infoOf:aPathName) modified
  4229 	(self infoOf:aPathName) modified
  4230     "
  4230     "
  4251 	}
  4251 	}
  4252 	osSeconds = __MKUINT(buf.st_mtime);
  4252 	osSeconds = __MKUINT(buf.st_mtime);
  4253     }
  4253     }
  4254 #endif
  4254 #endif
  4255 %}.
  4255 %}.
  4256     osSeconds notNil ifTrue:[^ AbsoluteTime fromOSTime:(osSeconds * 1000)].
  4256     osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)].
  4257 
  4257 
  4258     i := self infoOf:aPathName.
  4258     i := self infoOf:aPathName.
  4259     i notNil ifTrue:[^ i modified].
  4259     i notNil ifTrue:[^ i modified].
  4260     ^ nil.
  4260     ^ nil.
  4261 
  4261 
  4271 
  4271 
  4272     |i|
  4272     |i|
  4273 
  4273 
  4274     "
  4274     "
  4275      this could have been implemented as:
  4275      this could have been implemented as:
  4276 	(self infoOf:aPathName) type 
  4276 	(self infoOf:aPathName) type
  4277      but for huge directory searches the code below is faster
  4277      but for huge directory searches the code below is faster
  4278     "
  4278     "
  4279 
  4279 
  4280 %{
  4280 %{
  4281     struct stat buf;
  4281     struct stat buf;
  4327     i := self infoOf:aPathName.
  4327     i := self infoOf:aPathName.
  4328     i notNil ifTrue:[^ i type].
  4328     i notNil ifTrue:[^ i type].
  4329     ^ nil.
  4329     ^ nil.
  4330 
  4330 
  4331     "
  4331     "
  4332      OperatingSystem typeOf:'/'   
  4332      OperatingSystem typeOf:'/'
  4333      OperatingSystem typeOf:'.'   
  4333      OperatingSystem typeOf:'.'
  4334      OperatingSystem typeOf:'Make.proto' 
  4334      OperatingSystem typeOf:'Make.proto'
  4335      OperatingSystem typeOf:'resources/motif.style' 
  4335      OperatingSystem typeOf:'resources/motif.style'
  4336     "
  4336     "
  4337 !
  4337 !
  4338 
  4338 
  4339 volumeNameOf:aPathString
  4339 volumeNameOf:aPathString
  4340     "return the volumeName of the argument, aPath
  4340     "return the volumeName of the argument, aPath
  4461     "
  4461     "
  4462 !
  4462 !
  4463 
  4463 
  4464 disableTimer
  4464 disableTimer
  4465     "disable timer interrupts.
  4465     "disable timer interrupts.
  4466      WARNING: 
  4466      WARNING:
  4467 	the system will not operate correctly with timer interrupts
  4467 	the system will not operate correctly with timer interrupts
  4468 	disabled, because no scheduling or timeouts are possible."
  4468 	disabled, because no scheduling or timeouts are possible."
  4469 
  4469 
  4470 %{  /* NOCONTEXT */
  4470 %{  /* NOCONTEXT */
  4471 
  4471 
  4498 %}.
  4498 %}.
  4499     ^ false
  4499     ^ false
  4500 !
  4500 !
  4501 
  4501 
  4502 enableChildSignalInterrupts
  4502 enableChildSignalInterrupts
  4503     "enable childSignal interrupts 
  4503     "enable childSignal interrupts
  4504      (SIGCHLD, if the architecture supports it).
  4504      (SIGCHLD, if the architecture supports it).
  4505      After enabling, these signals will send the message 
  4505      After enabling, these signals will send the message
  4506      'childSignalInterrupt' to the ChildSignalInterruptHandler object."
  4506      'childSignalInterrupt' to the ChildSignalInterruptHandler object."
  4507 
  4507 
  4508 %{
  4508 %{
  4509     extern void __vmsEnableChildInterrupts();
  4509     extern void __vmsEnableChildInterrupts();
  4510 
  4510 
  4897 	struct itimerval dt;
  4897 	struct itimerval dt;
  4898 
  4898 
  4899 	dt.it_interval.tv_sec = 0;
  4899 	dt.it_interval.tv_sec = 0;
  4900 	dt.it_interval.tv_usec = 0;
  4900 	dt.it_interval.tv_usec = 0;
  4901 	dt.it_value.tv_sec = millis / 1000;
  4901 	dt.it_value.tv_sec = millis / 1000;
  4902 	dt.it_value.tv_usec = (millis % 1000) * 1000;  
  4902 	dt.it_value.tv_usec = (millis % 1000) * 1000;
  4903 	setitimer(ITIMER_REAL, &dt, 0);
  4903 	setitimer(ITIMER_REAL, &dt, 0);
  4904 	RETURN (true);
  4904 	RETURN (true);
  4905     }
  4905     }
  4906 #else /* no ITIMER_REAL */
  4906 #else /* no ITIMER_REAL */
  4907 
  4907 
  4975     "trigger a spyInterrupt, to be signalled after some short (virtual) time.
  4975     "trigger a spyInterrupt, to be signalled after some short (virtual) time.
  4976      This is used by the old MessageTally for profiling.
  4976      This is used by the old MessageTally for profiling.
  4977      Should be changed to use real profiling timer if available.
  4977      Should be changed to use real profiling timer if available.
  4978      On systems, where no virtual timer is available, use the real timer
  4978      On systems, where no virtual timer is available, use the real timer
  4979      (which is of course less correct).
  4979      (which is of course less correct).
  4980      OBSOLETE: the new messageTally runs as a high prio process, not using 
  4980      OBSOLETE: the new messageTally runs as a high prio process, not using
  4981 	       spy interrupts."
  4981 	       spy interrupts."
  4982 
  4982 
  4983 %{  /* NOCONTEXT */
  4983 %{  /* NOCONTEXT */
  4984 
  4984 
  4985 #ifndef __spyInterrupt
  4985 #ifndef __spyInterrupt
  5014     ^ false
  5014     ^ false
  5015 !
  5015 !
  5016 
  5016 
  5017 stopSpyTimer
  5017 stopSpyTimer
  5018     "stop spy timing - disable spy timer.
  5018     "stop spy timing - disable spy timer.
  5019      OBSOLETE: the new messageTally runs as a high prio process, not using 
  5019      OBSOLETE: the new messageTally runs as a high prio process, not using
  5020 	       spy interrupts."
  5020 	       spy interrupts."
  5021 
  5021 
  5022 %{  /* NOCONTEXT */
  5022 %{  /* NOCONTEXT */
  5023 
  5023 
  5024 #if defined(ITIMER_VIRTUAL) && !defined(NO_SETITIMER)
  5024 #if defined(ITIMER_VIRTUAL) && !defined(NO_SETITIMER)
  5167     in isNil ifTrue:[
  5167     in isNil ifTrue:[
  5168 	^ nil
  5168 	^ nil
  5169     ].
  5169     ].
  5170     out := self createMailBox.
  5170     out := self createMailBox.
  5171     out isNil ifTrue:[
  5171     out isNil ifTrue:[
  5172 	self destroyMailBox:in. 
  5172 	self destroyMailBox:in.
  5173 	^ nil
  5173 	^ nil
  5174     ].
  5174     ].
  5175     ^ Array with:in with:out
  5175     ^ Array with:in with:out
  5176 !
  5176 !
  5177 
  5177 
  5316 	hostName notNil ifTrue:[
  5316 	hostName notNil ifTrue:[
  5317 	    idx := hostName indexOf:$..
  5317 	    idx := hostName indexOf:$..
  5318 	    idx ~~ 0 ifTrue:[
  5318 	    idx ~~ 0 ifTrue:[
  5319 		name := hostName copyFrom:idx+1.
  5319 		name := hostName copyFrom:idx+1.
  5320 	    ]
  5320 	    ]
  5321 	]. 
  5321 	].
  5322 	name isNil ifTrue:[
  5322 	name isNil ifTrue:[
  5323 	    'OpenVMSOperatingSystem [warning]: cannot find out domainname' errorPrintCR.
  5323 	    'OpenVMSOperatingSystem [warning]: cannot find out domainname' errorPrintCR.
  5324 	    name := 'unknown'.
  5324 	    name := 'unknown'.
  5325 	]
  5325 	]
  5326     ].
  5326     ].
  5390     }
  5390     }
  5391 # else
  5391 # else
  5392 #  if defined(HAS_SYSINFO) && defined(SI_HOSTNAME)
  5392 #  if defined(HAS_SYSINFO) && defined(SI_HOSTNAME)
  5393     char buffer[256];
  5393     char buffer[256];
  5394     int ret;
  5394     int ret;
  5395  
  5395 
  5396     if ((ret = sysinfo(SI_HOSTNAME, buffer, sizeof(buffer))) >= 0 && ret <= sizeof(buffer)) {
  5396     if ((ret = sysinfo(SI_HOSTNAME, buffer, sizeof(buffer))) >= 0 && ret <= sizeof(buffer)) {
  5397 	name = __MKSTRING(buffer);
  5397 	name = __MKSTRING(buffer);
  5398     }
  5398     }
  5399 #  endif
  5399 #  endif
  5400 # endif
  5400 # endif
  5459 	positiveSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  5459 	positiveSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  5460 
  5460 
  5461 	negativeSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  5461 	negativeSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  5462 
  5462 
  5463 	positiveSignPosition                            <Symbol>
  5463 	positiveSignPosition                            <Symbol>
  5464 							one of: #parenthesesAround, 
  5464 							one of: #parenthesesAround,
  5465 								#signPrecedes, 
  5465 								#signPrecedes,
  5466 								#signSuceeds, 
  5466 								#signSuceeds,
  5467 								#signPrecedesCurrencySymbol,
  5467 								#signPrecedesCurrencySymbol,
  5468 								#signSuceedsCurrencySymbol
  5468 								#signSuceedsCurrencySymbol
  5469 
  5469 
  5470 	negativeSignPosition                            <like above>
  5470 	negativeSignPosition                            <like above>
  5471 
  5471 
  5518 	monThousandsSep = conf->mon_thousands_sep;
  5518 	monThousandsSep = conf->mon_thousands_sep;
  5519 	positiveSign = conf->positive_sign;
  5519 	positiveSign = conf->positive_sign;
  5520 	negativeSign = conf->negative_sign;
  5520 	negativeSign = conf->negative_sign;
  5521 	intFractDigits = conf->int_frac_digits;
  5521 	intFractDigits = conf->int_frac_digits;
  5522 	fractDigits = conf->frac_digits;
  5522 	fractDigits = conf->frac_digits;
  5523 	csPosPrecedes = conf->p_cs_precedes; 
  5523 	csPosPrecedes = conf->p_cs_precedes;
  5524 	csNegPrecedes = conf->n_cs_precedes; 
  5524 	csNegPrecedes = conf->n_cs_precedes;
  5525 	csPosSepBySpace = conf->p_sep_by_space; 
  5525 	csPosSepBySpace = conf->p_sep_by_space;
  5526 	csNegSepBySpace = conf->n_sep_by_space; 
  5526 	csNegSepBySpace = conf->n_sep_by_space;
  5527 	csPosSignPosition = conf->p_sign_posn;
  5527 	csPosSignPosition = conf->p_sign_posn;
  5528 	csNegSignPosition = conf->n_sign_posn;
  5528 	csNegSignPosition = conf->n_sign_posn;
  5529     }
  5529     }
  5530 #else
  5530 #else
  5531     decimalPoint = (char *)0;
  5531     decimalPoint = (char *)0;
  5536     monThousandsSep = (char *)0;
  5536     monThousandsSep = (char *)0;
  5537     positiveSign =  (char *)0;
  5537     positiveSign =  (char *)0;
  5538     negativeSign =(char *)0;
  5538     negativeSign =(char *)0;
  5539     intFractDigits = -1;
  5539     intFractDigits = -1;
  5540     fractDigits = -1;
  5540     fractDigits = -1;
  5541     csPosPrecedes = -1; 
  5541     csPosPrecedes = -1;
  5542     csNegPrecedes = -1; 
  5542     csNegPrecedes = -1;
  5543     csPosSepBySpace = -1; 
  5543     csPosSepBySpace = -1;
  5544     csNegSepBySpace = -1; 
  5544     csNegSepBySpace = -1;
  5545     csPosSignPosition = -1;
  5545     csPosSignPosition = -1;
  5546     csNegSignPosition = -1;
  5546     csNegSignPosition = -1;
  5547 #endif
  5547 #endif
  5548     if (decimalPoint) {
  5548     if (decimalPoint) {
  5549 	val = __MKSTRING(decimalPoint);
  5549 	val = __MKSTRING(decimalPoint);
  5735 
  5735 
  5736 getSystemInfo
  5736 getSystemInfo
  5737     "return info on the system weare running on.
  5737     "return info on the system weare running on.
  5738      If the system supports the uname system call, that info is returned;
  5738      If the system supports the uname system call, that info is returned;
  5739      otherwise, some simulated info is returned.
  5739      otherwise, some simulated info is returned.
  5740  
  5740 
  5741      WARNING:
  5741      WARNING:
  5742        Do not depend on the amount and contents of the returned information, some
  5742        Do not depend on the amount and contents of the returned information, some
  5743        systems may return more/less than others. Also, the contents depends on the
  5743        systems may return more/less than others. Also, the contents depends on the
  5744        OS, for example, linux returns 'ix86', while WIN32 returns 'x86'.
  5744        OS, for example, linux returns 'ix86', while WIN32 returns 'x86'.
  5745 
  5745 
  5746        This method is mainly provided to augment error reports with some system
  5746        This method is mainly provided to augment error reports with some system
  5747        information. 
  5747        information.
  5748        (in case of system/version specific OS errors, conditional workarounds and patches
  5748        (in case of system/version specific OS errors, conditional workarounds and patches
  5749 	may be based upon this info).
  5749 	may be based upon this info).
  5750        Your application should NOT depend upon this in any way.
  5750        Your application should NOT depend upon this in any way.
  5751 
  5751 
  5752      The returned info may (or may not) contain:
  5752      The returned info may (or may not) contain:
  5753 	#system -> some operating system identification (irix, Linux, nt, win32s ...) 
  5753 	#system -> some operating system identification (irix, Linux, nt, win32s ...)
  5754 	#version -> OS version (some os version identification)
  5754 	#version -> OS version (some os version identification)
  5755 	#release -> OS release (3.5, 1.2.1 ...)
  5755 	#release -> OS release (3.5, 1.2.1 ...)
  5756 	#node   -> some host identification (hostname)
  5756 	#node   -> some host identification (hostname)
  5757 	#domain  -> domain name (hosts domain)
  5757 	#domain  -> domain name (hosts domain)
  5758 	#machine -> type of machine (i586, mips ...)
  5758 	#machine -> type of machine (i586, mips ...)
  5849 	 We return a somewhat conservative number here.
  5849 	 We return a somewhat conservative number here.
  5850 	 Another entry, to query for volume specific max
  5850 	 Another entry, to query for volume specific max
  5851 	 will be added in the future."
  5851 	 will be added in the future."
  5852 
  5852 
  5853 %{  /* NOCONTEXT */
  5853 %{  /* NOCONTEXT */
  5854  
  5854 
  5855     /*
  5855     /*
  5856      * TODO: newer systems provide a query function for this ... use it
  5856      * TODO: newer systems provide a query function for this ... use it
  5857      */
  5857      */
  5858 
  5858 
  5859 #   ifdef __VMS__
  5859 #   ifdef __VMS__
  5870 
  5870 
  5871 %{  /* NOCONTEXT */
  5871 %{  /* NOCONTEXT */
  5872     RETURN ( __MKSMALLINT(MAXPATHLEN) );
  5872     RETURN ( __MKSMALLINT(MAXPATHLEN) );
  5873 %}
  5873 %}
  5874     "
  5874     "
  5875      OperatingSystem maxPathLength   
  5875      OperatingSystem maxPathLength
  5876     "
  5876     "
  5877 !
  5877 !
  5878 
  5878 
  5879 pathSeparator
  5879 pathSeparator
  5880     "return the character which separates items in the PATH variable"
  5880     "return the character which separates items in the PATH variable"
  5931      through interrupts (i.e. SIGCHILD)"
  5931      through interrupts (i.e. SIGCHILD)"
  5932 
  5932 
  5933     ^ true
  5933     ^ true
  5934 
  5934 
  5935     "
  5935     "
  5936      OperatingSystem supportsChildInterrupts 
  5936      OperatingSystem supportsChildInterrupts
  5937     "
  5937     "
  5938 !
  5938 !
  5939 
  5939 
  5940 supportsIOInterrupts
  5940 supportsIOInterrupts
  5941     "return true, if the OS supports IO availability interrupts 
  5941     "return true, if the OS supports IO availability interrupts
  5942      (i.e. SIGPOLL/SIGIO).
  5942      (i.e. SIGPOLL/SIGIO).
  5943 
  5943 
  5944      Currently, this mechanism does not work on all
  5944      Currently, this mechanism does not work on all
  5945      systems ...
  5945      systems ...
  5946     "
  5946     "
  5947 
  5947 
  5948     ^ false
  5948     ^ false
  5949 
  5949 
  5950     "
  5950     "
  5951      OperatingSystem supportsIOInterrupts 
  5951      OperatingSystem supportsIOInterrupts
  5952     "
  5952     "
  5953 !
  5953 !
  5954 
  5954 
  5955 supportsNonBlockingIO
  5955 supportsNonBlockingIO
  5956     "return true, if the OS supports nonblocking IO."
  5956     "return true, if the OS supports nonblocking IO."
  5961 #endif
  5961 #endif
  5962 %}.
  5962 %}.
  5963     ^ false
  5963     ^ false
  5964 
  5964 
  5965     "
  5965     "
  5966      OperatingSystem supportsNonBlockingIO  
  5966      OperatingSystem supportsNonBlockingIO
  5967     "
  5967     "
  5968 !
  5968 !
  5969 
  5969 
  5970 supportsSelect
  5970 supportsSelect
  5971     "return true, if the OS supports selecting on multiple
  5971     "return true, if the OS supports selecting on multiple
  5972      filedescriptors via select.
  5972      filedescriptors via select.
  5973      If false is returned, ProcessorScheduler will poll in 50ms
  5973      If false is returned, ProcessorScheduler will poll in 50ms
  5974      intervals for I/O becoming ready."
  5974      intervals for I/O becoming ready."
  5975 
  5975 
  5976     ^ false "/ for now ... 
  5976     ^ false "/ for now ...
  5977 
  5977 
  5978     "
  5978     "
  5979      OperatingSystem supportsSelect 
  5979      OperatingSystem supportsSelect
  5980     "
  5980     "
  5981 !
  5981 !
  5982 
  5982 
  5983 supportsVolumes
  5983 supportsVolumes
  5984     "return true, if the OS supports disk volumes.
  5984     "return true, if the OS supports disk volumes.
  6056      ]
  6056      ]
  6057     "
  6057     "
  6058 !
  6058 !
  6059 
  6059 
  6060 computeOSTimeFromYear:y month:m day:d hour:h minute:min seconds:s millis:millis
  6060 computeOSTimeFromYear:y month:m day:d hour:h minute:min seconds:s millis:millis
  6061     "return the OS-dependent time for the given time and day. 
  6061     "return the OS-dependent time for the given time and day.
  6062      The arguments are assumed to be in localtime including
  6062      The arguments are assumed to be in localtime including
  6063      any daylight saving adjustings."
  6063      any daylight saving adjustings."
  6064 
  6064 
  6065     |osSeconds|
  6065     |osSeconds|
  6066 
  6066 
  6067 %{
  6067 %{
  6068     struct tm tm;
  6068     struct tm tm;
  6069     TIME_T t;
  6069     TIME_T t;
  6070 
  6070 
  6071     if (__bothSmallInteger(y, m) 
  6071     if (__bothSmallInteger(y, m)
  6072      && __bothSmallInteger(d, h)
  6072      && __bothSmallInteger(d, h)
  6073      && __bothSmallInteger(min, s)) {
  6073      && __bothSmallInteger(min, s)) {
  6074 	tm.tm_hour = __intVal(h);
  6074 	tm.tm_hour = __intVal(h);
  6075 	tm.tm_min = __intVal(min);
  6075 	tm.tm_min = __intVal(min);
  6076 	tm.tm_sec = __intVal(s);
  6076 	tm.tm_sec = __intVal(s);
  6084 	osSeconds = __MKUINT((INT)t);
  6084 	osSeconds = __MKUINT((INT)t);
  6085     }
  6085     }
  6086 %}.
  6086 %}.
  6087     osSeconds notNil ifTrue:[
  6087     osSeconds notNil ifTrue:[
  6088 	^ osSeconds * 1000 + millis
  6088 	^ osSeconds * 1000 + millis
  6089     ].    
  6089     ].
  6090     ^ self primitiveFailed
  6090     ^ self primitiveFailed
  6091 
  6091 
  6092     "
  6092     "
  6093      OperatingSystem computeOSTimeFromYear:1970 month:1 day:1 hour:0 minute:0 seconds:0 millis:0
  6093      OperatingSystem computeOSTimeFromYear:1970 month:1 day:1 hour:0 minute:0 seconds:0 millis:0
  6094     "
  6094     "
  6100      containing (full-) year, month, day, hour, minute and seconds,
  6100      containing (full-) year, month, day, hour, minute and seconds,
  6101      offset to UTC, daylight savings time flag, milliseconds,
  6101      offset to UTC, daylight savings time flag, milliseconds,
  6102      dayInYear (1..) and dayInWeek (1..).
  6102      dayInYear (1..) and dayInWeek (1..).
  6103      Conversion is to localtime including any daylight saving adjustments."
  6103      Conversion is to localtime including any daylight saving adjustments."
  6104 
  6104 
  6105     |low hi year month day hours minutes seconds millis utcOffset 
  6105     |low hi year month day hours minutes seconds millis utcOffset
  6106      dst yDay wDay osSeconds ret|
  6106      dst yDay wDay osSeconds ret|
  6107 
  6107 
  6108     millis := osTime \\ 1000.
  6108     millis := osTime \\ 1000.
  6109     osSeconds := osTime // 1000.
  6109     osSeconds := osTime // 1000.
  6110 %{
  6110 %{
  6159      OperatingSystem computeTimeAndDateFrom:0
  6159      OperatingSystem computeTimeAndDateFrom:0
  6160     "
  6160     "
  6161 !
  6161 !
  6162 
  6162 
  6163 computeTimePartsOf:osTime for:aBlock
  6163 computeTimePartsOf:osTime for:aBlock
  6164     "compute hours, minutes, seconds and milliseconds from the osTime 
  6164     "compute hours, minutes, seconds and milliseconds from the osTime
  6165      and evaluate the argument, a 4-arg block with these.
  6165      and evaluate the argument, a 4-arg block with these.
  6166      Conversion is to localtime including any daylight saving adjustments."
  6166      Conversion is to localtime including any daylight saving adjustments."
  6167 
  6167 
  6168     |hours minutes seconds millis osSeconds|
  6168     |hours minutes seconds millis osSeconds|
  6169 
  6169 
  6196      containing year, month, day, hour, minute and seconds,
  6196      containing year, month, day, hour, minute and seconds,
  6197      offset to UTC, daylight savings time flag, milliseconds,
  6197      offset to UTC, daylight savings time flag, milliseconds,
  6198      dayInYear (1..) and dayInWeek (1..).
  6198      dayInYear (1..) and dayInWeek (1..).
  6199      Conversion is to UTC."
  6199      Conversion is to UTC."
  6200 
  6200 
  6201     |low hi year month day hours minutes seconds millis utcOffset 
  6201     |low hi year month day hours minutes seconds millis utcOffset
  6202      dst yDay wDay osSeconds ret|
  6202      dst yDay wDay osSeconds ret|
  6203 
  6203 
  6204     millis := osTime \\ 1000.
  6204     millis := osTime \\ 1000.
  6205     osSeconds := osTime // 1000.
  6205     osSeconds := osTime // 1000.
  6206 %{
  6206 %{
  6253      OperatingSystem computeUTCTimeAndDateFrom:0
  6253      OperatingSystem computeUTCTimeAndDateFrom:0
  6254     "
  6254     "
  6255 !
  6255 !
  6256 
  6256 
  6257 computeUTCTimePartsOf:osTime for:aBlock
  6257 computeUTCTimePartsOf:osTime for:aBlock
  6258     "compute hours, minutes, seconds and milliseconds from the osTime 
  6258     "compute hours, minutes, seconds and milliseconds from the osTime
  6259      and evaluate the argument, a 4-arg block with these.
  6259      and evaluate the argument, a 4-arg block with these.
  6260      Conversion is to UTC."
  6260      Conversion is to UTC."
  6261 
  6261 
  6262     |hours minutes seconds millis osSeconds|
  6262     |hours minutes seconds millis osSeconds|
  6263 
  6263 
  6282      ]
  6282      ]
  6283     "
  6283     "
  6284 !
  6284 !
  6285 
  6285 
  6286 getMillisecondTime
  6286 getMillisecondTime
  6287     "This returns the millisecond timers value. 
  6287     "This returns the millisecond timers value.
  6288      The range is limited to 0..1fffffff (i.e. the SmallInteger range) to avoid
  6288      The range is limited to 0..1fffffff (i.e. the SmallInteger range) to avoid
  6289      LargeInteger arithmetic when doing timeouts and delays.
  6289      LargeInteger arithmetic when doing timeouts and delays.
  6290      Since this value is wrapping around in regular intervals, this can only be used for 
  6290      Since this value is wrapping around in regular intervals, this can only be used for
  6291      short relative time deltas.
  6291      short relative time deltas.
  6292      Use the millisecondTimeXXX:-methods to compare and add time deltas - these know about the wrap.
  6292      Use the millisecondTimeXXX:-methods to compare and add time deltas - these know about the wrap.
  6293 
  6293 
  6294      BAD DESIGN:
  6294      BAD DESIGN:
  6295 	This should be changed to return some instance of RelativeTime,
  6295 	This should be changed to return some instance of RelativeTime,
  6312 #   define HAVE_TIME
  6312 #   define HAVE_TIME
  6313 # endif
  6313 # endif
  6314 
  6314 
  6315 # ifndef HAVE_TIME
  6315 # ifndef HAVE_TIME
  6316 #  if defined(SYSV) && defined(HZ)
  6316 #  if defined(SYSV) && defined(HZ)
  6317     /* 
  6317     /*
  6318      * sys5 time
  6318      * sys5 time
  6319      */
  6319      */
  6320     long ticks;
  6320     long ticks;
  6321     struct tms tb;
  6321     struct tms tb;
  6322 
  6322 
  6327 # endif
  6327 # endif
  6328 
  6328 
  6329 #endif
  6329 #endif
  6330 
  6330 
  6331 #ifndef HAVE_TIME
  6331 #ifndef HAVE_TIME
  6332     /* assume HAS_GETTIMEOFDAY 
  6332     /* assume HAS_GETTIMEOFDAY
  6333      * - will result in a linkage error
  6333      * - will result in a linkage error
  6334      * if not fixed.
  6334      * if not fixed.
  6335      */
  6335      */
  6336 
  6336 
  6337     /*
  6337     /*
  6352 
  6352 
  6353 getOSTime
  6353 getOSTime
  6354     "This returns the OS time.
  6354     "This returns the OS time.
  6355      The base of the returned value is not consistent across
  6355      The base of the returned value is not consistent across
  6356      different OS's - some return the number of millis since jan, 1st 1970;
  6356      different OS's - some return the number of millis since jan, 1st 1970;
  6357      others since 1900. The Time classes are prepared for this, and 
  6357      others since 1900. The Time classes are prepared for this, and
  6358      converts as appropriate (by using my fromOSTime: conversion methods).
  6358      converts as appropriate (by using my fromOSTime: conversion methods).
  6359 
  6359 
  6360      Dont use this method in application code since it is an internal (private)
  6360      Dont use this method in application code since it is an internal (private)
  6361      interface. For compatibility with ST-80, use Time>>millisecondClockValue.
  6361      interface. For compatibility with ST-80, use Time>>millisecondClockValue.
  6362      or use instances of Time, Date or AbsoluteTime to work with.
  6362      or use instances of Time, Date or Timestamp to work with.
  6363     "
  6363     "
  6364 
  6364 
  6365     |seconds millis|
  6365     |seconds millis|
  6366 
  6366 
  6367 %{
  6367 %{
  6368 
  6368 
  6369     long t;
  6369     long t;
  6370 
  6370 
  6371 #if !defined(HAS_GETTIMEOFDAY) 
  6371 #if !defined(HAS_GETTIMEOFDAY)
  6372 # if defined(HAS_FTIME)
  6372 # if defined(HAS_FTIME)
  6373     struct timeb timebuffer;
  6373     struct timeb timebuffer;
  6374 
  6374 
  6375     ftime(&timebuffer);
  6375     ftime(&timebuffer);
  6376     seconds = __MKUINT(timebuffer.time);
  6376     seconds = __MKUINT(timebuffer.time);
  6378 #   define HAVE_TIME
  6378 #   define HAVE_TIME
  6379 # endif
  6379 # endif
  6380 
  6380 
  6381 # ifndef HAVE_TIME
  6381 # ifndef HAVE_TIME
  6382 #  if defined(SYSV) && defined(HZ)
  6382 #  if defined(SYSV) && defined(HZ)
  6383     /* 
  6383     /*
  6384      * sys5 time; we have to fake the information
  6384      * sys5 time; we have to fake the information
  6385      * the returned value is inexact.
  6385      * the returned value is inexact.
  6386      */
  6386      */
  6387     int now;
  6387     int now;
  6388     long ticks;
  6388     long ticks;
  6409 #  endif
  6409 #  endif
  6410 # endif
  6410 # endif
  6411 #endif
  6411 #endif
  6412 
  6412 
  6413 #ifndef HAVE_TIME
  6413 #ifndef HAVE_TIME
  6414     /* assume HAS_GETTIMEOFDAY 
  6414     /* assume HAS_GETTIMEOFDAY
  6415      * - will result in a linkage error
  6415      * - will result in a linkage error
  6416      * if not fixed.
  6416      * if not fixed.
  6417      */
  6417      */
  6418     /*
  6418     /*
  6419      * bsd time
  6419      * bsd time
  6421     struct timeval tb;
  6421     struct timeval tb;
  6422     struct timezone tzb;
  6422     struct timezone tzb;
  6423 
  6423 
  6424     gettimeofday(&tb, &tzb);
  6424     gettimeofday(&tb, &tzb);
  6425 
  6425 
  6426     /* 
  6426     /*
  6427      * mhmh long-long stuff seems not to work correctly 
  6427      * mhmh long-long stuff seems not to work correctly
  6428      * on all machines (sparc)
  6428      * on all machines (sparc)
  6429      * being conservative here ...
  6429      * being conservative here ...
  6430      */
  6430      */
  6431 
  6431 
  6432 # if defined(__GNUC__) && (__GNUC__ >= 2) && defined(i386) && defined(LINUX)
  6432 # if defined(__GNUC__) && (__GNUC__ >= 2) && defined(i386) && defined(LINUX)
  6476 !
  6476 !
  6477 
  6477 
  6478 millisecondDelay:millis
  6478 millisecondDelay:millis
  6479     "delay execution for millis milliseconds or until the next event
  6479     "delay execution for millis milliseconds or until the next event
  6480      arrives.
  6480      arrives.
  6481      All lower priority threads will also sleep for the duration, 
  6481      All lower priority threads will also sleep for the duration,
  6482      interrupts (and therefore, higher prio processes) are
  6482      interrupts (and therefore, higher prio processes) are
  6483      still handled. 
  6483      still handled.
  6484      Better use a Delay, to only delay the calling thread.
  6484      Better use a Delay, to only delay the calling thread.
  6485      (however, a delay cannot be used in the event handler or scheduler)"
  6485      (however, a delay cannot be used in the event handler or scheduler)"
  6486 
  6486 
  6487     |now then delta|
  6487     |now then delta|
  6488 
  6488 
  6505     }
  6505     }
  6506     RETURN(self);
  6506     RETURN(self);
  6507 # endif
  6507 # endif
  6508 #endif
  6508 #endif
  6509 %}.
  6509 %}.
  6510  
  6510 
  6511     now := OpenVMSOperatingSystem getMillisecondTime.
  6511     now := OpenVMSOperatingSystem getMillisecondTime.
  6512     then := OpenVMSOperatingSystem millisecondTimeAdd:now and:millis.
  6512     then := OpenVMSOperatingSystem millisecondTimeAdd:now and:millis.
  6513 
  6513 
  6514     [OpenVMSOperatingSystem millisecondTime:then isAfter:now] whileTrue:[
  6514     [OpenVMSOperatingSystem millisecondTime:then isAfter:now] whileTrue:[
  6515 	delta := OpenVMSOperatingSystem millisecondTimeDeltaBetween:then and:now.
  6515 	delta := OpenVMSOperatingSystem millisecondTimeDeltaBetween:then and:now.
  6618 	^ gecos
  6618 	^ gecos
  6619     ].
  6619     ].
  6620     ^ self getUserNameFromID:userID
  6620     ^ self getUserNameFromID:userID
  6621 
  6621 
  6622     "
  6622     "
  6623      OperatingSystem getFullUserNameFromID:0 
  6623      OperatingSystem getFullUserNameFromID:0
  6624      OperatingSystem getFullUserNameFromID:(OperatingSystem getUserID)  
  6624      OperatingSystem getFullUserNameFromID:(OperatingSystem getUserID)
  6625 
  6625 
  6626      OperatingSystem getUserNameFromID:(OperatingSystem getUserID)  
  6626      OperatingSystem getUserNameFromID:(OperatingSystem getUserID)
  6627     "
  6627     "
  6628 
  6628 
  6629     "Modified: 15.7.1996 / 12:44:21 / cg"
  6629     "Modified: 15.7.1996 / 12:44:21 / cg"
  6630 !
  6630 !
  6631 
  6631 
  6809     ^ '? (' , aNumber printString , ')'
  6809     ^ '? (' , aNumber printString , ')'
  6810 
  6810 
  6811     "
  6811     "
  6812      OperatingSystem getUserNameFromID:0
  6812      OperatingSystem getUserNameFromID:0
  6813      OperatingSystem getUserNameFromID:100
  6813      OperatingSystem getUserNameFromID:100
  6814      OperatingSystem getUserNameFromID:9991 
  6814      OperatingSystem getUserNameFromID:9991
  6815     "
  6815     "
  6816 !
  6816 !
  6817 
  6817 
  6818 userInfoOf:aNameOrID
  6818 userInfoOf:aNameOrID
  6819     "{ Pragma: +optSpace }"
  6819     "{ Pragma: +optSpace }"
  6820 
  6820 
  6821     "return a dictionary filled with userinfo. The argument can be either
  6821     "return a dictionary filled with userinfo. The argument can be either
  6822      a string with the users name or its numeric id.
  6822      a string with the users name or its numeric id.
  6823      Notice, that not all systems provide (all of) this info;
  6823      Notice, that not all systems provide (all of) this info;
  6824      DOS systems return nothing; 
  6824      DOS systems return nothing;
  6825      non-SYSV4 systems have no age/comment.
  6825      non-SYSV4 systems have no age/comment.
  6826      Portable applications may want to check the systemType and NOT depend
  6826      Portable applications may want to check the systemType and NOT depend
  6827      on all keys to be present in the returned dictionary.
  6827      on all keys to be present in the returned dictionary.
  6828      Another notice: on some systems (SYSV4), the gecos field includes multiple
  6828      Another notice: on some systems (SYSV4), the gecos field includes multiple
  6829      entries (i.e. not just the name), separated by commas. You may want to
  6829      entries (i.e. not just the name), separated by commas. You may want to
  6893     ^ info
  6893     ^ info
  6894 
  6894 
  6895     "
  6895     "
  6896      OperatingSystem userInfoOf:'root'
  6896      OperatingSystem userInfoOf:'root'
  6897      OperatingSystem userInfoOf:1
  6897      OperatingSystem userInfoOf:1
  6898      OperatingSystem userInfoOf:'claus' 
  6898      OperatingSystem userInfoOf:'claus'
  6899      OperatingSystem userInfoOf:'fooBar' 
  6899      OperatingSystem userInfoOf:'fooBar'
  6900      OperatingSystem userInfoOf:(OperatingSystem getUserID)
  6900      OperatingSystem userInfoOf:(OperatingSystem getUserID)
  6901     "
  6901     "
  6902 ! !
  6902 ! !
  6903 
  6903 
  6904 !OpenVMSOperatingSystem class methodsFor:'waiting for events'!
  6904 !OpenVMSOperatingSystem class methodsFor:'waiting for events'!
  6920 childProcessWait:blocking pid:pidToWait
  6920 childProcessWait:blocking pid:pidToWait
  6921     "{ Pragma: +optSpace }"
  6921     "{ Pragma: +optSpace }"
  6922 
  6922 
  6923     "get status changes from child processes.
  6923     "get status changes from child processes.
  6924      Return an OSProcessStatus or nil, if no process has terminated.
  6924      Return an OSProcessStatus or nil, if no process has terminated.
  6925      If blocking is true, we wait until a process changed state, 
  6925      If blocking is true, we wait until a process changed state,
  6926      otherwise we return immediately.
  6926      otherwise we return immediately.
  6927      Note that win32 needs to know the HANDLE of the process on which 
  6927      Note that win32 needs to know the HANDLE of the process on which
  6928      it waits.  In case of an error, THIS ALWAYS WAITS and then times out."
  6928      it waits.  In case of an error, THIS ALWAYS WAITS and then times out."
  6929 
  6929 
  6930     |pid status code core|
  6930     |pid status code core|
  6931 %{
  6931 %{
  6932 #ifdef __VMS__
  6932 #ifdef __VMS__
  6986 %}.
  6986 %}.
  6987     ^ (self readCheck:fd) ifTrue:[1] ifFalse:[0]
  6987     ^ (self readCheck:fd) ifTrue:[1] ifFalse:[0]
  6988 !
  6988 !
  6989 
  6989 
  6990 readCheck:fd
  6990 readCheck:fd
  6991     "return true, if data is available on a filedescriptor 
  6991     "return true, if data is available on a filedescriptor
  6992      (i.e. read is possible without blocking).
  6992      (i.e. read is possible without blocking).
  6993      This depends on a working select or FIONREAD to be provided by the OS."
  6993      This depends on a working select or FIONREAD to be provided by the OS."
  6994 
  6994 
  6995 %{
  6995 %{
  6996 #ifdef NOTDEF   /* does not work ... */
  6996 #ifdef NOTDEF   /* does not work ... */
  7046 
  7046 
  7047     ^ super readCheck:fd
  7047     ^ super readCheck:fd
  7048 !
  7048 !
  7049 
  7049 
  7050 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
  7050 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
  7051     "wait for any fd in readFdArray (an Array of integers) to become ready for 
  7051     "wait for any fd in readFdArray (an Array of integers) to become ready for
  7052      reading, writeFdArray to become ready for writing, or exceptFdArray to 
  7052      reading, writeFdArray to become ready for writing, or exceptFdArray to
  7053      arrive exceptional data (i.e. out-of-band data).
  7053      arrive exceptional data (i.e. out-of-band data).
  7054      Timeout after t milliseconds or, if the timeout time is 0, immediately..
  7054      Timeout after t milliseconds or, if the timeout time is 0, immediately..
  7055      Empty fd-sets will always wait. Zero time can be used to poll file-
  7055      Empty fd-sets will always wait. Zero time can be used to poll file-
  7056      descriptors (i.e. to check if I/O possible without blocking).
  7056      descriptors (i.e. to check if I/O possible without blocking).
  7057      Return first ready fd if I/O ok, nil if timed-out or interrupted."
  7057      Return first ready fd if I/O ok, nil if timed-out or interrupted."
  7075 	FD_ZERO(&eset);
  7075 	FD_ZERO(&eset);
  7076 
  7076 
  7077 	maxF = -1;
  7077 	maxF = -1;
  7078 	if (__isNonNilObject(readFdArray)) {
  7078 	if (__isNonNilObject(readFdArray)) {
  7079 	    if (! __isArrayLike(readFdArray)) {
  7079 	    if (! __isArrayLike(readFdArray)) {
  7080 		goto fail;    
  7080 		goto fail;
  7081 	    }
  7081 	    }
  7082 	    count = __arraySize(readFdArray);
  7082 	    count = __arraySize(readFdArray);
  7083 
  7083 
  7084 	    for (i=0; i<count;i++) {
  7084 	    for (i=0; i<count;i++) {
  7085 		fd = __ArrayInstPtr(readFdArray)->a_element[i];
  7085 		fd = __ArrayInstPtr(readFdArray)->a_element[i];
  7094 	    }
  7094 	    }
  7095 	}
  7095 	}
  7096 
  7096 
  7097 	if (__isNonNilObject(writeFdArray)) {
  7097 	if (__isNonNilObject(writeFdArray)) {
  7098 	    if (! __isArrayLike(writeFdArray)) {
  7098 	    if (! __isArrayLike(writeFdArray)) {
  7099 		goto fail;    
  7099 		goto fail;
  7100 	    }
  7100 	    }
  7101 	    count = __arraySize(writeFdArray);
  7101 	    count = __arraySize(writeFdArray);
  7102 	    for (i=0; i<count;i++) {
  7102 	    for (i=0; i<count;i++) {
  7103 		fd = __ArrayInstPtr(writeFdArray)->a_element[i];
  7103 		fd = __ArrayInstPtr(writeFdArray)->a_element[i];
  7104 		if (fd != nil) {
  7104 		if (fd != nil) {
  7105 		    f = __intVal(fd);
  7105 		    f = __intVal(fd);
  7106 		    if ((unsigned)f < FD_SETSIZE) {
  7106 		    if ((unsigned)f < FD_SETSIZE) {
  7107 			FD_SET(f, &wset);       
  7107 			FD_SET(f, &wset);
  7108 			if (f > maxF) maxF = f;
  7108 			if (f > maxF) maxF = f;
  7109 			numFds++;
  7109 			numFds++;
  7110 		    }
  7110 		    }
  7111 		}
  7111 		}
  7112 	    }
  7112 	    }
  7113 	}
  7113 	}
  7114 
  7114 
  7115 	if (__isNonNilObject(exceptFdArray)) {
  7115 	if (__isNonNilObject(exceptFdArray)) {
  7116 	    if (! __isArrayLike(exceptFdArray)) {
  7116 	    if (! __isArrayLike(exceptFdArray)) {
  7117 		goto fail;    
  7117 		goto fail;
  7118 	    }
  7118 	    }
  7119 	    count = __arraySize(exceptFdArray);
  7119 	    count = __arraySize(exceptFdArray);
  7120 	    for (i=0; i<count;i++) {
  7120 	    for (i=0; i<count;i++) {
  7121 		fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
  7121 		fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
  7122 		if (fd != nil) {
  7122 		if (fd != nil) {
  7123 		    f = __intVal(fd);
  7123 		    f = __intVal(fd);
  7124 		    if ((unsigned)f < FD_SETSIZE) {
  7124 		    if ((unsigned)f < FD_SETSIZE) {
  7125 			FD_SET(f, &eset);       
  7125 			FD_SET(f, &eset);
  7126 			if (f > maxF) maxF = f;
  7126 			if (f > maxF) maxF = f;
  7127 			numFds++;
  7127 			numFds++;
  7128 		    }
  7128 		    }
  7129 		}
  7129 		}
  7130 	    }
  7130 	    }
  7144 	 */
  7144 	 */
  7145 	__BEGIN_INTERRUPTABLE__
  7145 	__BEGIN_INTERRUPTABLE__
  7146 	errno = 0;
  7146 	errno = 0;
  7147 
  7147 
  7148 	if (t == 0) {
  7148 	if (t == 0) {
  7149 	    /* 
  7149 	    /*
  7150 	     * if there is no timeout time, we can stay here interruptable.
  7150 	     * if there is no timeout time, we can stay here interruptable.
  7151 	     */
  7151 	     */
  7152 	    do {
  7152 	    do {
  7153 		ret = select(maxF+1, &rset, &wset, &eset, &wt);
  7153 		ret = select(maxF+1, &rset, &wset, &eset, &wt);
  7154 	    } while ((ret < 0) && (errno == EINTR));
  7154 	    } while ((ret < 0) && (errno == EINTR));
  7155 	} else {
  7155 	} else {
  7156 	    do {
  7156 	    do {
  7157 		ret = select(maxF+1, &rset, &wset, &eset, &wt);
  7157 		ret = select(maxF+1, &rset, &wset, &eset, &wt);
  7158 		/* 
  7158 		/*
  7159 		 * for now: dont loop; if we did, we had to adjust the vt-timeval;
  7159 		 * for now: dont loop; if we did, we had to adjust the vt-timeval;
  7160 		 * could otherwise stay in this loop forever ...
  7160 		 * could otherwise stay in this loop forever ...
  7161 		 * Premature return (before the time expired) must be handled by the caller.
  7161 		 * Premature return (before the time expired) must be handled by the caller.
  7162 		 * A good solution is to update the wt-timeval and redo the select.
  7162 		 * A good solution is to update the wt-timeval and redo the select.
  7163 		 */
  7163 		 */
  7240     ^ self primitiveFailed
  7240     ^ self primitiveFailed
  7241 ! !
  7241 ! !
  7242 
  7242 
  7243 !OpenVMSOperatingSystem::FileStatusInfo class methodsFor:'instance creation'!
  7243 !OpenVMSOperatingSystem::FileStatusInfo class methodsFor:'instance creation'!
  7244 
  7244 
  7245 type:t mode:m uid:u gid:g size:s id:i accessed:aT modified:mT statusChanged:sT path:lP 
  7245 type:t mode:m uid:u gid:g size:s id:i accessed:aT modified:mT statusChanged:sT path:lP
  7246     ^ self basicNew
  7246     ^ self basicNew
  7247 	type:t mode:m uid:u gid:g size:s id:i accessed:aT modified:mT statusChanged:sT path:lP 
  7247 	type:t mode:m uid:u gid:g size:s id:i accessed:aT modified:mT statusChanged:sT path:lP
  7248 ! !
  7248 ! !
  7249 
  7249 
  7250 !OpenVMSOperatingSystem::FileStatusInfo methodsFor:'accessing'!
  7250 !OpenVMSOperatingSystem::FileStatusInfo methodsFor:'accessing'!
  7251 
  7251 
  7252 accessed
  7252 accessed
  7357     recordAttributes := ra.
  7357     recordAttributes := ra.
  7358     fixedHeaderSize := hs.
  7358     fixedHeaderSize := hs.
  7359     recordSize := rs
  7359     recordSize := rs
  7360 !
  7360 !
  7361 
  7361 
  7362 type:t mode:m uid:u gid:g size:s id:i accessed:aT modified:mT statusChanged:sT path:lP 
  7362 type:t mode:m uid:u gid:g size:s id:i accessed:aT modified:mT statusChanged:sT path:lP
  7363     type := t.
  7363     type := t.
  7364     mode := m.
  7364     mode := m.
  7365     uid := u.
  7365     uid := u.
  7366     gid := g.
  7366     gid := g.
  7367     size := s.
  7367     size := s.
  7531 ! !
  7531 ! !
  7532 
  7532 
  7533 !OpenVMSOperatingSystem class methodsFor:'documentation'!
  7533 !OpenVMSOperatingSystem class methodsFor:'documentation'!
  7534 
  7534 
  7535 version
  7535 version
  7536     ^ '$Header: /cvs/stx/stx/libbasic/OpenVMSOperatingSystem.st,v 1.12 2003-02-27 14:49:24 stefan Exp $'
  7536     ^ '$Header: /cvs/stx/stx/libbasic/OpenVMSOperatingSystem.st,v 1.13 2004-03-20 19:23:29 stefan Exp $'
  7537 ! !
  7537 ! !
  7538 OpenVMSOperatingSystem initialize!
  7538 OpenVMSOperatingSystem initialize!