AbstractOperatingSystem.st
changeset 4852 ac51b47d8768
parent 4849 439d9f52ad93
child 5026 6406b4765e48
equal deleted inserted replaced
4851:ff6ecefce66f 4852:ac51b47d8768
     1 "
     1 "
     2  COPYRIGHT (c) 1988 by Claus Gittinger
     2  COPYRIGHT (c) 1988 by Claus Gittinger
     3 	      All Rights Reserved
     3               All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 Object subclass:#AbstractOperatingSystem
    13 Object subclass:#AbstractOperatingSystem
    14 	instanceVariableNames:''
    14         instanceVariableNames:''
    15 	classVariableNames:'ConcreteClass LastErrorNumber LocaleInfo OSSignals PipeFailed
    15         classVariableNames:'ConcreteClass LastErrorNumber LocaleInfo OSSignals PipeFailed
    16 		ErrorSignal AccessDeniedErrorSignal FileNotFoundErrorSignal
    16                 ErrorSignal AccessDeniedErrorSignal FileNotFoundErrorSignal
    17 		InvalidArgumentsSignal UnsupportedOperationSignal'
    17                 InvalidArgumentsSignal UnsupportedOperationSignal'
    18 	poolDictionaries:''
    18         poolDictionaries:''
    19 	category:'System-Support'
    19         category:'System-Support'
    20 !
    20 !
    21 
    21 
    22 !AbstractOperatingSystem class methodsFor:'documentation'!
    22 !AbstractOperatingSystem class methodsFor:'documentation'!
    23 
    23 
    24 copyright
    24 copyright
    25 "
    25 "
    26  COPYRIGHT (c) 1988 by Claus Gittinger
    26  COPYRIGHT (c) 1988 by Claus Gittinger
    27 	      All Rights Reserved
    27               All Rights Reserved
    28 
    28 
    29  This software is furnished under a license and may be used
    29  This software is furnished under a license and may be used
    30  only in accordance with the terms of that license and with the
    30  only in accordance with the terms of that license and with the
    31  inclusion of the above copyright notice.   This software may not
    31  inclusion of the above copyright notice.   This software may not
    32  be provided or otherwise made available to, or used by, any
    32  be provided or otherwise made available to, or used by, any
    41     typically, services which can be implemented based upon more primitive
    41     typically, services which can be implemented based upon more primitive
    42     functions, or which can be implemented in a portable way (but probably
    42     functions, or which can be implemented in a portable way (but probably
    43     less performant) are implemented here.
    43     less performant) are implemented here.
    44 
    44 
    45     [Class variables:]
    45     [Class variables:]
    46 	ConcreteClass   <Class>         the real OS class
    46         ConcreteClass   <Class>         the real OS class
    47 
    47 
    48 	LocaleInfo      <Dictionary>    if non nil, that is taken instead of the operating
    48         LocaleInfo      <Dictionary>    if non nil, that is taken instead of the operating
    49 					systems locale definitions (allows for overwriting
    49                                         systems locale definitions (allows for overwriting
    50 					these, or provide a compatible info on systems which do
    50                                         these, or provide a compatible info on systems which do
    51 					not support locales)
    51                                         not support locales)
    52 
    52 
    53 	LastErrorNumber <Integer>       the last value of errno
    53         LastErrorNumber <Integer>       the last value of errno
    54 
    54 
    55 	OSSignals       <Array>         Array of signals to be raised for corresponding
    55         OSSignals       <Array>         Array of signals to be raised for corresponding
    56 					OperatingSystem signals.
    56                                         OperatingSystem signals.
    57 
    57 
    58 	PipeFailed      <Boolean>       set if a fork (or popen) has failed;
    58         PipeFailed      <Boolean>       set if a fork (or popen) has failed;
    59 					ST/X will avoid doing more forks/popens
    59                                         ST/X will avoid doing more forks/popens
    60 					if this flag is set, for a slightly
    60                                         if this flag is set, for a slightly
    61 					smoother operation.
    61                                         smoother operation.
    62 
    62 
    63 	ErrorSignal     <Signal>        Parentsignal of all OS error signals.
    63         ErrorSignal     <Signal>        Parentsignal of all OS error signals.
    64 					not directly raised.
    64                                         not directly raised.
    65 
    65 
    66 	AccessDeniedErrorSignal         misc concrete error reporting signals
    66         AccessDeniedErrorSignal         misc concrete error reporting signals
    67 	FileNotFoundErrorSignal
    67         FileNotFoundErrorSignal
    68 	UnsupportedOperationSignal
    68         UnsupportedOperationSignal
    69 	InvalidArgumentsSignal
    69         InvalidArgumentsSignal
    70 
    70 
    71     [author:]
    71     [author:]
    72 	Claus Gittinger
    72         Claus Gittinger
    73 
    73 
    74     [see also:]
    74     [see also:]
    75 	OSProcessStatus
    75         OSProcessStatus
    76 	Filename Date Time
    76         Filename Date Time
    77 	ExternalStream FileStream PipeStream Socket
    77         ExternalStream FileStream PipeStream Socket
    78 "
    78 "
    79 !
    79 !
    80 
    80 
    81 examples
    81 examples
    82 "
    82 "
    83   various queries
    83   various queries
    84 								[exBegin]
    84                                                                 [exBegin]
    85     Transcript 
    85     Transcript 
    86 	showCR:'hello ' , (OperatingSystem getLoginName)
    86         showCR:'hello ' , (OperatingSystem getLoginName)
    87 								[exEnd]
    87                                                                 [exEnd]
    88 
    88 
    89 								[exBegin]
    89                                                                 [exBegin]
    90     OperatingSystem isUNIXlike ifTrue:[
    90     OperatingSystem isUNIXlike ifTrue:[
    91 	Transcript showCR:'this is some UNIX-like OS'
    91         Transcript showCR:'this is some UNIX-like OS'
    92     ] ifFalse:[
    92     ] ifFalse:[
    93 	Transcript showCR:'this OS is not UNIX-like'
    93         Transcript showCR:'this OS is not UNIX-like'
    94     ]
    94     ]
    95 								[exEnd]
    95                                                                 [exEnd]
    96 
    96 
    97 								[exBegin]
    97                                                                 [exBegin]
    98     Transcript 
    98     Transcript 
    99 	showCR:'this machine is called ' , OperatingSystem getHostName
    99         showCR:'this machine is called ' , OperatingSystem getHostName
   100 								[exEnd]
   100                                                                 [exEnd]
   101 
   101 
   102 								[exBegin]
   102                                                                 [exBegin]
   103     Transcript 
   103     Transcript 
   104 	showCR:('this machine is in the '
   104         showCR:('this machine is in the '
   105 	       , OperatingSystem getDomainName
   105                , OperatingSystem getDomainName
   106 	       , ' domain')
   106                , ' domain')
   107 								[exEnd]
   107                                                                 [exEnd]
   108 
   108 
   109 								[exBegin]
   109                                                                 [exBegin]
   110     Transcript 
   110     Transcript 
   111 	showCR:('this machine''s CPU is a '
   111         showCR:('this machine''s CPU is a '
   112 	       , OperatingSystem getCPUType
   112                , OperatingSystem getCPUType
   113 	       )
   113                )
   114 								[exEnd]
   114                                                                 [exEnd]
   115 
   115 
   116 								[exBegin]
   116                                                                 [exBegin]
   117     Transcript showCR:'executing ls command ...'.
   117     Transcript showCR:'executing ls command ...'.
   118     OperatingSystem executeCommand:'ls'.
   118     OperatingSystem executeCommand:'ls'.
   119     Transcript showCR:'... done.'.
   119     Transcript showCR:'... done.'.
   120 								[exEnd]
   120                                                                 [exEnd]
   121 
   121 
   122   locking a file 
   122   locking a file 
   123   (should be executed on two running smalltalks - not in two threads):
   123   (should be executed on two running smalltalks - not in two threads):
   124 								[exBegin]
   124                                                                 [exBegin]
   125     |f|
   125     |f|
   126 
   126 
   127     f := 'testFile' asFilename readWriteStream.
   127     f := 'testFile' asFilename readWriteStream.
   128 
   128 
   129     10 timesRepeat:[
   129     10 timesRepeat:[
   130 	'about to lock ...' printCR.
   130         'about to lock ...' printCR.
   131 	[
   131         [
   132 	  OperatingSystem 
   132           OperatingSystem 
   133 	    lockFD:(f fileDescriptor)
   133             lockFD:(f fileDescriptor)
   134 	    shared:false
   134             shared:false
   135 	    blocking:false
   135             blocking:false
   136 	] whileFalse:[
   136         ] whileFalse:[
   137 	    'process ' print. OperatingSystem getProcessId print. ' is waiting' printCR.
   137             'process ' print. OperatingSystem getProcessId print. ' is waiting' printCR.
   138 	    Delay waitForSeconds:1
   138             Delay waitForSeconds:1
   139 	].
   139         ].
   140 	'LOCKED ...' printCR.
   140         'LOCKED ...' printCR.
   141 	Delay waitForSeconds:10.
   141         Delay waitForSeconds:10.
   142 	'unlock ...' printCR.
   142         'unlock ...' printCR.
   143 	(OperatingSystem 
   143         (OperatingSystem 
   144 	    unlockFD:(f fileDescriptor)) printCR.
   144             unlockFD:(f fileDescriptor)) printCR.
   145 	Delay waitForSeconds:3.
   145         Delay waitForSeconds:3.
   146     ]
   146     ]
   147 								[exBegin]
   147                                                                 [exBegin]
   148 "
   148 "
   149 ! !
   149 ! !
   150 
   150 
   151 !AbstractOperatingSystem class methodsFor:'initialization'!
   151 !AbstractOperatingSystem class methodsFor:'initialization'!
   152 
   152 
   154     "initialize the class"
   154     "initialize the class"
   155 
   155 
   156     self initializeConcreteClass.
   156     self initializeConcreteClass.
   157 
   157 
   158     ErrorSignal isNil ifTrue:[
   158     ErrorSignal isNil ifTrue:[
   159 	ErrorSignal := Object errorSignal newSignalMayProceed:true.
   159         ErrorSignal := Object errorSignal newSignalMayProceed:true.
   160 	ErrorSignal nameClass:self message:#errorSignal.
   160         ErrorSignal nameClass:self message:#errorSignal.
   161 	ErrorSignal notifierString:'OS error encountered'.
   161         ErrorSignal notifierString:'OS error encountered'.
   162 
   162 
   163 	AccessDeniedErrorSignal := ErrorSignal newSignalMayProceed:true.
   163         AccessDeniedErrorSignal := ErrorSignal newSignalMayProceed:true.
   164 	AccessDeniedErrorSignal nameClass:self message:#accessDeniedError.
   164         AccessDeniedErrorSignal nameClass:self message:#accessDeniedError.
   165 	AccessDeniedErrorSignal notifierString:'OS access denied'.
   165         AccessDeniedErrorSignal notifierString:'OS access denied'.
   166 
   166 
   167 	FileNotFoundErrorSignal := ErrorSignal newSignalMayProceed:true.
   167         FileNotFoundErrorSignal := ErrorSignal newSignalMayProceed:true.
   168 	FileNotFoundErrorSignal nameClass:self message:#fileNotFoundErrorSignal.
   168         FileNotFoundErrorSignal nameClass:self message:#fileNotFoundErrorSignal.
   169 	FileNotFoundErrorSignal notifierString:'OS file not found'.
   169         FileNotFoundErrorSignal notifierString:'OS file not found'.
   170 
   170 
   171 	InvalidArgumentsSignal := ErrorSignal newSignalMayProceed:true.
   171         InvalidArgumentsSignal := ErrorSignal newSignalMayProceed:true.
   172 	InvalidArgumentsSignal nameClass:self message:#invalidArgumentsSignal.
   172         InvalidArgumentsSignal nameClass:self message:#invalidArgumentsSignal.
   173 	InvalidArgumentsSignal notifierString:'bad arg to OS call'.
   173         InvalidArgumentsSignal notifierString:'bad arg to OS call'.
   174 
   174 
   175 	UnsupportedOperationSignal := ErrorSignal newSignalMayProceed:true.
   175         UnsupportedOperationSignal := ErrorSignal newSignalMayProceed:true.
   176 	UnsupportedOperationSignal nameClass:self message:#unsupportedOperationSignal.
   176         UnsupportedOperationSignal nameClass:self message:#unsupportedOperationSignal.
   177 	UnsupportedOperationSignal notifierString:'operation not supported by this OS'.
   177         UnsupportedOperationSignal notifierString:'operation not supported by this OS'.
   178     ]
   178     ]
   179 
   179 
   180     "Modified: / 19.5.1999 / 14:21:28 / cg"
   180     "Modified: / 19.5.1999 / 14:21:28 / cg"
   181 !
   181 !
   182 
   182 
   183 initializeConcreteClass
   183 initializeConcreteClass
   184     |osType cls|
   184     |osType cls|
   185 
   185 
   186     osType := self getSystemType.
   186     osType := self getSystemType.
   187     osType = 'win32' ifTrue:[
   187     osType = 'win32' ifTrue:[
   188 	cls := Win32OperatingSystem
   188         cls := Win32OperatingSystem
   189     ] ifFalse:[
   189     ] ifFalse:[
   190 	osType = 'os2' ifTrue:[
   190         osType = 'os2' ifTrue:[
   191 	    cls := OS2OperatingSystem
   191             cls := OS2OperatingSystem
   192 	] ifFalse:[
   192         ] ifFalse:[
   193 	    osType = 'macos' ifTrue:[
   193             osType = 'macos' ifTrue:[
   194 		cls := MacOperatingSystem
   194                 cls := MacOperatingSystem
   195 	    ] ifFalse:[
   195             ] ifFalse:[
   196 		((osType = 'VMS') or:[osType = 'openVMS']) ifTrue:[
   196                 ((osType = 'VMS') or:[osType = 'openVMS']) ifTrue:[
   197 		    cls := OpenVMSOperatingSystem
   197                     cls := OpenVMSOperatingSystem
   198 		] ifFalse:[
   198                 ] ifFalse:[
   199 		    cls := UnixOperatingSystem
   199                     cls := UnixOperatingSystem
   200 		]
   200                 ]
   201 	    ]
   201             ]
   202 	]
   202         ]
   203     ].
   203     ].
   204     OperatingSystem := ConcreteClass := cls.
   204     OperatingSystem := ConcreteClass := cls.
   205 ! !
   205 ! !
   206 
   206 
   207 !AbstractOperatingSystem class methodsFor:'OS signal constants'!
   207 !AbstractOperatingSystem class methodsFor:'OS signal constants'!
   551 
   551 
   552 clearLastErrorNumber
   552 clearLastErrorNumber
   553     "return the last errors number.
   553     "return the last errors number.
   554      See also: #lastErrorSymbol and #lastErrorString.
   554      See also: #lastErrorSymbol and #lastErrorString.
   555      Notice: having a single error number is a bad idea in a multithreaded
   555      Notice: having a single error number is a bad idea in a multithreaded
   556 	     environment - this interface will change."
   556              environment - this interface will change."
   557 
   557 
   558     LastErrorNumber := nil.
   558     LastErrorNumber := nil.
   559 
   559 
   560      "
   560      "
   561       AbstractOperatingSystem clearLastErrorNumber
   561       AbstractOperatingSystem clearLastErrorNumber
   593      (as returned by a system call). 
   593      (as returned by a system call). 
   594      The returned message is in english (as found in /usr/include/errno.h)
   594      The returned message is in english (as found in /usr/include/errno.h)
   595      and should be replaced by a resource lookup before being presented to the user."
   595      and should be replaced by a resource lookup before being presented to the user."
   596 
   596 
   597     ^ Array 
   597     ^ Array 
   598 	with:#'ERROR_OTHER' 
   598         with:#'ERROR_OTHER' 
   599 	with:('ErrorNr: ' , errNr printString)
   599         with:('ErrorNr: ' , errNr printString)
   600 
   600 
   601     "
   601     "
   602      OperatingSystem errorSymbolAndTextForNumber:4
   602      OperatingSystem errorSymbolAndTextForNumber:4
   603     "
   603     "
   604 !
   604 !
   633 
   633 
   634 lastErrorNumber
   634 lastErrorNumber
   635     "return the last errors number.
   635     "return the last errors number.
   636      See also: #lastErrorSymbol and #lastErrorString.
   636      See also: #lastErrorSymbol and #lastErrorString.
   637      Notice: having a single error number is a bad idea in a multithreaded
   637      Notice: having a single error number is a bad idea in a multithreaded
   638 	     environment - this interface will change."
   638              environment - this interface will change."
   639 
   639 
   640     ^ LastErrorNumber
   640     ^ LastErrorNumber
   641 
   641 
   642      "
   642      "
   643       OperatingSystem lastErrorNumber
   643       OperatingSystem lastErrorNumber
   646 
   646 
   647 lastErrorString
   647 lastErrorString
   648     "return a message string describing the last error.
   648     "return a message string describing the last error.
   649      See also: #lastErrorNumber and #lastErrorSymbol.
   649      See also: #lastErrorNumber and #lastErrorSymbol.
   650      Notice: having a single error number is a bad idea in a multithreaded
   650      Notice: having a single error number is a bad idea in a multithreaded
   651 	     environment - this interface will change."
   651              environment - this interface will change."
   652 
   652 
   653     LastErrorNumber isNil ifTrue:[^ nil].
   653     LastErrorNumber isNil ifTrue:[^ nil].
   654     ^ self errorTextForNumber:LastErrorNumber
   654     ^ self errorTextForNumber:LastErrorNumber
   655 
   655 
   656     "
   656     "
   660 
   660 
   661 lastErrorSymbol
   661 lastErrorSymbol
   662     "return a symbol (such as #EBADF or #EACCESS) describing the last error.
   662     "return a symbol (such as #EBADF or #EACCESS) describing the last error.
   663      See also: #lastErrorNumber and #lastErrorString.
   663      See also: #lastErrorNumber and #lastErrorString.
   664      Notice: having a single error number is a bad idea in a multithreaded
   664      Notice: having a single error number is a bad idea in a multithreaded
   665 	     environment - this interface will change."
   665              environment - this interface will change."
   666 
   666 
   667     LastErrorNumber isNil ifTrue:[^ nil].
   667     LastErrorNumber isNil ifTrue:[^ nil].
   668     ^ self errorSymbolForNumber:LastErrorNumber
   668     ^ self errorSymbolForNumber:LastErrorNumber
   669 
   669 
   670     "
   670     "
   704      If successful, this method does NOT return and smalltalk is gone.
   704      If successful, this method does NOT return and smalltalk is gone.
   705      If not successful, it does return. 
   705      If not successful, it does return. 
   706      Can be used on UNIX with fork or on other systems to chain to another program."
   706      Can be used on UNIX with fork or on other systems to chain to another program."
   707 
   707 
   708     ^ self 
   708     ^ self 
   709 	exec:aCommandPath 
   709         exec:aCommandPath 
   710 	withArguments:argArray
   710         withArguments:argArray
   711 	environment:nil
   711         environment:nil
   712 	fileDescriptors:nil
   712         fileDescriptors:nil
   713 	closeDescriptors:nil 
   713         closeDescriptors:nil 
   714 	fork:false 
   714         fork:false 
   715 	newPgrp:false
   715         newPgrp:false
   716 	inDirectory:nil
   716         inDirectory:nil
   717 
   717 
   718     "/ never reached ...
   718     "/ never reached ...
   719 
   719 
   720     "Modified: / 12.11.1998 / 14:44:26 / cg"
   720     "Modified: / 12.11.1998 / 14:44:26 / cg"
   721 !
   721 !
   722 
   722 
   723 exec:aCommandPath withArguments:argColl environment:env fileDescriptors:fdColl closeDescriptors:closeFdColl fork:doFork newPgrp:newPgrp 
   723 exec:aCommandPath withArguments:argColl environment:env fileDescriptors:fdColl closeDescriptors:closeFdColl fork:doFork newPgrp:newPgrp 
   724     "Internal lowLevel entry for combined fork & exec;
   724     "Internal lowLevel entry for combined fork & exec;
   725 
   725 
   726      If fork is false (chain a command):
   726      If fork is false (chain a command):
   727 	 execute the OS command specified by the argument, aCommandPath, with
   727          execute the OS command specified by the argument, aCommandPath, with
   728 	 arguments in argArray (no arguments, if nil).
   728          arguments in argArray (no arguments, if nil).
   729 	 If successful, this method does not return and smalltalk is gone.
   729          If successful, this method does not return and smalltalk is gone.
   730 	 If not successful, it does return.
   730          If not successful, it does return.
   731 	 Normal use is with forkForCommand.
   731          Normal use is with forkForCommand.
   732 
   732 
   733      If fork is true (subprocess command execution):
   733      If fork is true (subprocess command execution):
   734 	fork a child to do the above.
   734         fork a child to do the above.
   735 	The process id of the child process is returned; nil if the fork failed.
   735         The process id of the child process is returned; nil if the fork failed.
   736 
   736 
   737      fdArray contains the filedescriptors, to be used for the child (if fork is true).
   737      fdArray contains the filedescriptors, to be used for the child (if fork is true).
   738 	fdArray[1] = 15 -> use fd 15 as stdin.
   738         fdArray[1] = 15 -> use fd 15 as stdin.
   739 	If an element of the array is set to nil, the corresponding filedescriptor
   739         If an element of the array is set to nil, the corresponding filedescriptor
   740 	will be closed for the child.
   740         will be closed for the child.
   741 	fdArray[0] == StdIn for child
   741         fdArray[0] == StdIn for child
   742 	fdArray[1] == StdOut for child
   742         fdArray[1] == StdOut for child
   743 	fdArray[2] == StdErr for child
   743         fdArray[2] == StdErr for child
   744 	on VMS, these must be channels as returned by createMailBox.
   744         on VMS, these must be channels as returned by createMailBox.
   745 
   745 
   746      closeFdArray contains descriptors that will be closed in the subprocess.
   746      closeFdArray contains descriptors that will be closed in the subprocess.
   747 	closeDescriptors are ignored in the WIN32 & VMS versions.
   747         closeDescriptors are ignored in the WIN32 & VMS versions.
   748 
   748 
   749      If newPgrp is true, the subprocess will be established in a new process group.
   749      If newPgrp is true, the subprocess will be established in a new process group.
   750 	The processgroup will be equal to id.
   750         The processgroup will be equal to id.
   751 	newPgrp is not used on WIN32 and VMS systems.
   751         newPgrp is not used on WIN32 and VMS systems.
   752 
   752 
   753      env specifies environment variables which are passed differently from
   753      env specifies environment variables which are passed differently from
   754      the current environment. If non-nil, it must be a dictionary providing
   754      the current environment. If non-nil, it must be a dictionary providing
   755      key-value pairs for changed/added environment variables.
   755      key-value pairs for changed/added environment variables.
   756      To pass a variable as empty (i.e. unset), pass a nil value.
   756      To pass a variable as empty (i.e. unset), pass a nil value.
   757 
   757 
   758      Notice: this used to be two separate ST-methods; however, in order to use
   758      Notice: this used to be two separate ST-methods; however, in order to use
   759 	    vfork on some machines, it had to be merged into one, to avoid write
   759             vfork on some machines, it had to be merged into one, to avoid write
   760 	    accesses to ST/X memory from the vforked-child.
   760             accesses to ST/X memory from the vforked-child.
   761 	    The code below only does read accesses."
   761             The code below only does read accesses."
   762 
   762 
   763     ^ self
   763     ^ self
   764 	exec:aCommandPath 
   764         exec:aCommandPath 
   765 	withArguments:argColl 
   765         withArguments:argColl 
   766 	environment:env 
   766         environment:env 
   767 	fileDescriptors:fdColl 
   767         fileDescriptors:fdColl 
   768 	closeDescriptors:closeFdColl 
   768         closeDescriptors:closeFdColl 
   769 	fork:doFork
   769         fork:doFork
   770 	newPgrp:newPgrp 
   770         newPgrp:newPgrp 
   771 	inDirectory:nil
   771         inDirectory:nil
   772 
   772 
   773     "
   773     "
   774      |id|
   774      |id|
   775 
   775 
   776      id := OperatingSystem fork.
   776      id := OperatingSystem fork.
   777      id == 0 ifTrue:[
   777      id == 0 ifTrue:[
   778 	'I am the child'.
   778         'I am the child'.
   779 	OperatingSystem exec:'/bin/ls' withArguments:#('ls' '/tmp').
   779         OperatingSystem exec:'/bin/ls' withArguments:#('ls' '/tmp').
   780 	'not reached'.
   780         'not reached'.
   781      ]
   781      ]
   782     "
   782     "
   783     "
   783     "
   784      |id|
   784      |id|
   785 
   785 
   786      id := OperatingSystem fork.
   786      id := OperatingSystem fork.
   787      id == 0 ifTrue:[
   787      id == 0 ifTrue:[
   788 	'I am the child'.
   788         'I am the child'.
   789 	OperatingSystem
   789         OperatingSystem
   790 	   exec:'/bin/sh'
   790            exec:'/bin/sh'
   791 	   withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2').
   791            withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2').
   792 	'not reached'.
   792         'not reached'.
   793      ].
   793      ].
   794      id printNL.
   794      id printNL.
   795      (Delay forSeconds:3.5) wait.
   795      (Delay forSeconds:3.5) wait.
   796      'killing ...' printNL.
   796      'killing ...' printNL.
   797      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
   797      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
   811 !
   811 !
   812 
   812 
   813 exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp
   813 exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp
   814     "combined fork & exec;
   814     "combined fork & exec;
   815      If fork is false (chain a command):
   815      If fork is false (chain a command):
   816 	 execute the OS command specified by the argument, aCommandPath, with
   816          execute the OS command specified by the argument, aCommandPath, with
   817 	 arguments in argArray (no arguments, if nil).
   817          arguments in argArray (no arguments, if nil).
   818 	 If successful, this method does not return and smalltalk is gone.
   818          If successful, this method does not return and smalltalk is gone.
   819 	 If not successful, it does return.
   819          If not successful, it does return.
   820 	 Normal use is with forkForCommand.
   820          Normal use is with forkForCommand.
   821 
   821 
   822      If fork is true (subprocess command execution):
   822      If fork is true (subprocess command execution):
   823 	fork a child to do the above.
   823         fork a child to do the above.
   824 	The process id of the child process is returned; nil if the fork failed.
   824         The process id of the child process is returned; nil if the fork failed.
   825 
   825 
   826      fdArray contains the filedescriptors, to be used for the child (if fork is true).
   826      fdArray contains the filedescriptors, to be used for the child (if fork is true).
   827 	fdArray[1] = 15 -> use fd 15 as stdin.
   827         fdArray[1] = 15 -> use fd 15 as stdin.
   828 	If an element of the array is set to nil, the corresponding filedescriptor
   828         If an element of the array is set to nil, the corresponding filedescriptor
   829 	will be closed for the child.
   829         will be closed for the child.
   830 	fdArray[0] == StdIn for child
   830         fdArray[0] == StdIn for child
   831 	fdArray[1] == StdOut for child
   831         fdArray[1] == StdOut for child
   832 	fdArray[2] == StdErr for child
   832         fdArray[2] == StdErr for child
   833 	on VMS, these must be channels as returned by createMailBox.
   833         on VMS, these must be channels as returned by createMailBox.
   834 
   834 
   835      closeFdArray contains descriptors that will be closed in the subprocess.
   835      closeFdArray contains descriptors that will be closed in the subprocess.
   836 	closeDescriptors are ignored in the WIN32 & VMS versions.
   836         closeDescriptors are ignored in the WIN32 & VMS versions.
   837 
   837 
   838      NOTE that in WIN32 the fds are HANDLES!!
   838      NOTE that in WIN32 the fds are HANDLES!!
   839 
   839 
   840      If newPgrp is true, the subprocess will be established in a new process group.
   840      If newPgrp is true, the subprocess will be established in a new process group.
   841 	The processgroup will be equal to id.
   841         The processgroup will be equal to id.
   842 	newPgrp is not used on WIN32 and VMS systems.
   842         newPgrp is not used on WIN32 and VMS systems.
   843 
   843 
   844      Notice: this used to be two separate ST-methods; however, in order to use
   844      Notice: this used to be two separate ST-methods; however, in order to use
   845 	    vfork on some machines, it had to be merged into one, to avoid write
   845             vfork on some machines, it had to be merged into one, to avoid write
   846 	    accesses to ST/X memory from the vforked-child.
   846             accesses to ST/X memory from the vforked-child.
   847 	    The code below only does read accesses."
   847             The code below only does read accesses."
   848 
   848 
   849     ^ self
   849     ^ self
   850 	exec:aCommandPath 
   850         exec:aCommandPath 
   851 	withArguments:argArray
   851         withArguments:argArray
   852 	environment:nil 
   852         environment:nil 
   853 	fileDescriptors:fdArray 
   853         fileDescriptors:fdArray 
   854 	closeDescriptors:closeFdArray
   854         closeDescriptors:closeFdArray
   855 	fork:doFork 
   855         fork:doFork 
   856 	newPgrp:newPgrp
   856         newPgrp:newPgrp
   857 	inDirectory:nil
   857         inDirectory:nil
   858 
   858 
   859     "
   859     "
   860      |id|
   860      |id|
   861 
   861 
   862      id := OperatingSystem fork.
   862      id := OperatingSystem fork.
   863      id == 0 ifTrue:[
   863      id == 0 ifTrue:[
   864 	'I am the child'.
   864         'I am the child'.
   865 	OperatingSystem exec:'/bin/ls' withArguments:#('ls' '/tmp').
   865         OperatingSystem exec:'/bin/ls' withArguments:#('ls' '/tmp').
   866 	'not reached'.
   866         'not reached'.
   867      ]
   867      ]
   868     "
   868     "
   869     "
   869     "
   870      |id|
   870      |id|
   871 
   871 
   872      id := OperatingSystem fork.
   872      id := OperatingSystem fork.
   873      id == 0 ifTrue:[
   873      id == 0 ifTrue:[
   874 	'I am the child'.
   874         'I am the child'.
   875 	OperatingSystem
   875         OperatingSystem
   876 	   exec:'/bin/sh'
   876            exec:'/bin/sh'
   877 	   withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2').
   877            withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2').
   878 	'not reached'.
   878         'not reached'.
   879      ].
   879      ].
   880      id printNL.
   880      id printNL.
   881      (Delay forSeconds:3.5) wait.
   881      (Delay forSeconds:3.5) wait.
   882      'killing ...' printNL.
   882      'killing ...' printNL.
   883      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
   883      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
   891 exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp inDirectory:aDirectory
   891 exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp inDirectory:aDirectory
   892     "Internal lowLevel entry for combined fork & exec for WIN32.
   892     "Internal lowLevel entry for combined fork & exec for WIN32.
   893      Not needed with Unix"
   893      Not needed with Unix"
   894 
   894 
   895     ^ self
   895     ^ self
   896 	exec:aCommandPath 
   896         exec:aCommandPath 
   897 	withArguments:argArray 
   897         withArguments:argArray 
   898 	environment:nil
   898         environment:nil
   899 	fileDescriptors:fdArray
   899         fileDescriptors:fdArray
   900 	closeDescriptors:closeFdArray 
   900         closeDescriptors:closeFdArray 
   901 	fork:doFork 
   901         fork:doFork 
   902 	newPgrp:newPgrp
   902         newPgrp:newPgrp
   903 	inDirectory:aDirectory
   903         inDirectory:aDirectory
   904 
   904 
   905     "Modified: / 12.11.1998 / 14:47:58 / cg"
   905     "Modified: / 12.11.1998 / 14:47:58 / cg"
   906     "Created: / 12.11.1998 / 14:49:18 / cg"
   906     "Created: / 12.11.1998 / 14:49:18 / cg"
   907 !
   907 !
   908 
   908 
   911      The command reads its input and writes its output
   911      The command reads its input and writes its output
   912      from/to whatever terminal device ST/X was started
   912      from/to whatever terminal device ST/X was started
   913      (typically, the xterm window)"
   913      (typically, the xterm window)"
   914 
   914 
   915     ^ self 
   915     ^ self 
   916 	exec:aCommandPath 
   916         exec:aCommandPath 
   917 	withArguments:argArray 
   917         withArguments:argArray 
   918 	environment:nil
   918         environment:nil
   919 	fileDescriptors:nil
   919         fileDescriptors:nil
   920 	closeDescriptors:nil 
   920         closeDescriptors:nil 
   921 	fork:doFork 
   921         fork:doFork 
   922 	newPgrp:false
   922         newPgrp:false
   923 	inDirectory:nil
   923         inDirectory:nil
   924 
   924 
   925     "
   925     "
   926      |id|
   926      |id|
   927 
   927 
   928      id := OperatingSystem fork.
   928      id := OperatingSystem fork.
   929      id == 0 ifTrue:[
   929      id == 0 ifTrue:[
   930 	'I am the child'.
   930         'I am the child'.
   931 	OperatingSystem 
   931         OperatingSystem 
   932 	    exec:'/bin/ls' 
   932             exec:'/bin/ls' 
   933 	    withArguments:#('ls' '/tmp')
   933             withArguments:#('ls' '/tmp')
   934 	    fork:false.
   934             fork:false.
   935 	'not reached'.
   935         'not reached'.
   936      ]
   936      ]
   937     "
   937     "
   938 
   938 
   939     "
   939     "
   940      |id|
   940      |id|
   941 
   941 
   942      id := OperatingSystem fork.
   942      id := OperatingSystem fork.
   943      id == 0 ifTrue:[
   943      id == 0 ifTrue:[
   944 	'I am the child'.
   944         'I am the child'.
   945 	OperatingSystem 
   945         OperatingSystem 
   946 	    exec:'/bin/sh' 
   946             exec:'/bin/sh' 
   947 	    withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
   947             withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
   948 	    fork:false.
   948             fork:false.
   949 	'not reached'.
   949         'not reached'.
   950      ].
   950      ].
   951      id printNL.
   951      id printNL.
   952      (Delay forSeconds:3.5) wait.
   952      (Delay forSeconds:3.5) wait.
   953      'killing ...' printNL.
   953      'killing ...' printNL.
   954      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
   954      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
   964      The command reads its input and writes its output
   964      The command reads its input and writes its output
   965      from/to whatever terminal device ST/X was started
   965      from/to whatever terminal device ST/X was started
   966      (typically, the xterm window)"
   966      (typically, the xterm window)"
   967 
   967 
   968     ^ self 
   968     ^ self 
   969 	exec:aCommandPath
   969         exec:aCommandPath
   970 	withArguments:argArray
   970         withArguments:argArray
   971 	environment:nil
   971         environment:nil
   972 	fileDescriptors:nil
   972         fileDescriptors:nil
   973 	closeDescriptors:nil
   973         closeDescriptors:nil
   974 	fork:doFork 
   974         fork:doFork 
   975 	newPgrp:false
   975         newPgrp:false
   976 	inDirectory:aDirectory
   976         inDirectory:aDirectory
   977 
   977 
   978     "
   978     "
   979      |id|
   979      |id|
   980 
   980 
   981      id := OperatingSystem fork.
   981      id := OperatingSystem fork.
   982      id == 0 ifTrue:[
   982      id == 0 ifTrue:[
   983 	'I am the child'.
   983         'I am the child'.
   984 	OperatingSystem 
   984         OperatingSystem 
   985 	    exec:'/bin/ls' 
   985             exec:'/bin/ls' 
   986 	    withArguments:#('ls' '/tmp')
   986             withArguments:#('ls' '/tmp')
   987 	    fork:false.
   987             fork:false.
   988 	'not reached'.
   988         'not reached'.
   989      ]
   989      ]
   990     "
   990     "
   991 
   991 
   992     "
   992     "
   993      |id|
   993      |id|
   994 
   994 
   995      id := OperatingSystem fork.
   995      id := OperatingSystem fork.
   996      id == 0 ifTrue:[
   996      id == 0 ifTrue:[
   997 	'I am the child'.
   997         'I am the child'.
   998 	OperatingSystem 
   998         OperatingSystem 
   999 	    exec:'/bin/sh' 
   999             exec:'/bin/sh' 
  1000 	    withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
  1000             withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
  1001 	    fork:false.
  1001             fork:false.
  1002 	'not reached'.
  1002         'not reached'.
  1003      ].
  1003      ].
  1004      id printNL.
  1004      id printNL.
  1005      (Delay forSeconds:3.5) wait.
  1005      (Delay forSeconds:3.5) wait.
  1006      'killing ...' printNL.
  1006      'killing ...' printNL.
  1007      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
  1007      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
  1027      The commandString is passed to a shell for execution - see the description of
  1027      The commandString is passed to a shell for execution - see the description of
  1028      'sh -c' in your UNIX manual.
  1028      'sh -c' in your UNIX manual.
  1029      Return true if successful, false otherwise."
  1029      Return true if successful, false otherwise."
  1030 
  1030 
  1031      ^ self
  1031      ^ self
  1032 	executeCommand:aCommandString 
  1032         executeCommand:aCommandString 
  1033 	inputFrom:nil 
  1033         inputFrom:nil 
  1034 	outputTo:nil 
  1034         outputTo:nil 
  1035 	errorTo:nil 
  1035         errorTo:nil 
  1036 	inDirectory:nil
  1036         inDirectory:nil
  1037 	onError:[:status| false]
  1037         onError:[:status| false]
  1038 
  1038 
  1039     "unix:
  1039     "unix:
  1040 
  1040 
  1041      OperatingSystem executeCommand:'sleep 30'. 
  1041      OperatingSystem executeCommand:'sleep 30'. 
  1042      OperatingSystem executeCommand:'pwd'. 
  1042      OperatingSystem executeCommand:'pwd'. 
  1308      Return true if successful.
  1308      Return true if successful.
  1309      If not successfull, aBlock is called with an OsProcessStatus
  1309      If not successfull, aBlock is called with an OsProcessStatus
  1310      (containing the exit status) as argument."
  1310      (containing the exit status) as argument."
  1311 
  1311 
  1312     ^ self
  1312     ^ self
  1313 	executeCommand:aCommandString 
  1313         executeCommand:aCommandString 
  1314 	inputFrom:anExternalInStream 
  1314         inputFrom:anExternalInStream 
  1315 	outputTo:anExternalOutStream 
  1315         outputTo:anExternalOutStream 
  1316 	errorTo:anExternalErrStream 
  1316         errorTo:anExternalErrStream 
  1317 	inDirectory:nil
  1317         inDirectory:nil
  1318 	onError:aBlock
  1318         onError:aBlock
  1319 
  1319 
  1320     "
  1320     "
  1321 	OperatingSystem
  1321         OperatingSystem
  1322 	    executeCommand:'dir'
  1322             executeCommand:'dir'
  1323 	    inputFrom:nil
  1323             inputFrom:nil
  1324 	    outputTo:nil
  1324             outputTo:nil
  1325 	    errorTo:nil
  1325             errorTo:nil
  1326 	    onError:[:status | Transcript flash]
  1326             onError:[:status | Transcript flash]
  1327         
  1327         
  1328 	OperatingSystem
  1328         OperatingSystem
  1329 	    executeCommand:'foo'
  1329             executeCommand:'foo'
  1330 	    inputFrom:nil
  1330             inputFrom:nil
  1331 	    outputTo:nil
  1331             outputTo:nil
  1332 	    errorTo:nil
  1332             errorTo:nil
  1333 	    onError:[:status | Transcript flash]
  1333             onError:[:status | Transcript flash]
  1334     "
  1334     "
  1335 
  1335 
  1336     "Modified: / 10.11.1998 / 20:51:39 / cg"
  1336     "Modified: / 10.11.1998 / 20:51:39 / cg"
  1337 !
  1337 !
  1338 
  1338 
  1343      Return true if successful.
  1343      Return true if successful.
  1344      If not successfull, aBlock is called with an OsProcessStatus
  1344      If not successfull, aBlock is called with an OsProcessStatus
  1345      (containing the exit status) as argument."
  1345      (containing the exit status) as argument."
  1346 
  1346 
  1347     ^ self
  1347     ^ self
  1348 	executeCommand:aCommandString 
  1348         executeCommand:aCommandString 
  1349 	inputFrom:nil 
  1349         inputFrom:nil 
  1350 	outputTo:nil 
  1350         outputTo:nil 
  1351 	errorTo:nil 
  1351         errorTo:nil 
  1352 	inDirectory:nil
  1352         inDirectory:nil
  1353 	onError:aBlock
  1353         onError:aBlock
  1354 
  1354 
  1355     "unix:
  1355     "unix:
  1356 
  1356 
  1357      OperatingSystem executeCommand:'sleep 30' onError:[]. 
  1357      OperatingSystem executeCommand:'sleep 30' onError:[]. 
  1358      OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. 
  1358      OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. 
  1443      if the command fails, nil is returned."
  1443      if the command fails, nil is returned."
  1444 
  1444 
  1445     |result|
  1445     |result|
  1446 
  1446 
  1447     PipeFailed ~~ true ifTrue:[
  1447     PipeFailed ~~ true ifTrue:[
  1448 	PipeStream openErrorSignal handle:[:ex |
  1448         PipeStream openErrorSignal handle:[:ex |
  1449 	    PipeFailed := true.
  1449             PipeFailed := true.
  1450 	    'OperatingSystem [warning]: cannot fork/popen' errorPrintCR.
  1450             'OperatingSystem [warning]: cannot fork/popen' errorPrintCR.
  1451 	    ex return.
  1451             ex return.
  1452 	] do:[
  1452         ] do:[
  1453 	    |p|
  1453             |p|
  1454 
  1454 
  1455 	    p := PipeStream 
  1455             p := PipeStream 
  1456 		    readingFrom:aCommand
  1456                     readingFrom:aCommand
  1457 		    errorDisposition:#discard
  1457                     errorDisposition:#discard
  1458 		    inDirectory:nil.
  1458                     inDirectory:nil.
  1459 	    p notNil ifTrue:[
  1459             p notNil ifTrue:[
  1460 		p atEnd ifTrue:[
  1460                 p atEnd ifTrue:[
  1461 		    result := ''
  1461                     result := ''
  1462 		] ifFalse:[
  1462                 ] ifFalse:[
  1463 		    result := p nextLine.
  1463                     result := p nextLine.
  1464 		].
  1464                 ].
  1465 		p close
  1465                 p close
  1466 	    ].
  1466             ].
  1467 	].
  1467         ].
  1468     ].
  1468     ].
  1469     ^ result
  1469     ^ result
  1470 
  1470 
  1471     "
  1471     "
  1472      OperatingSystem getCommandOutputFrom:'hostname'
  1472      OperatingSystem getCommandOutputFrom:'hostname'
  1534      Return the processId if successful, nil otherwise.
  1534      Return the processId if successful, nil otherwise.
  1535      Use #waitForProcess: for synchronization and exec status return,
  1535      Use #waitForProcess: for synchronization and exec status return,
  1536      or #killProcess: to stop it."
  1536      or #killProcess: to stop it."
  1537 
  1537 
  1538     ^ self
  1538     ^ self
  1539 	startProcess:aCommandString 
  1539         startProcess:aCommandString 
  1540 	inputFrom:nil 
  1540         inputFrom:nil 
  1541 	outputTo:nil 
  1541         outputTo:nil 
  1542 	errorTo:nil 
  1542         errorTo:nil 
  1543 	inDirectory:nil
  1543         inDirectory:nil
  1544 
  1544 
  1545     "
  1545     "
  1546      |pid|
  1546      |pid|
  1547 
  1547 
  1548      pid := OperatingSystem startProcess:'sleep 2; echo 1; sleep 2; echo 2'.
  1548      pid := OperatingSystem startProcess:'sleep 2; echo 1; sleep 2; echo 2'.
  1558     "
  1558     "
  1559     "
  1559     "
  1560      |pid|
  1560      |pid|
  1561 
  1561 
  1562      pid := OperatingSystem 
  1562      pid := OperatingSystem 
  1563 		startProcess:'dir/l'
  1563                 startProcess:'dir/l'
  1564 		inputFrom:nil
  1564                 inputFrom:nil
  1565 		outputTo:Stdout
  1565                 outputTo:Stdout
  1566 		errorTo:nil
  1566                 errorTo:nil
  1567 		inDirectory:nil.
  1567                 inDirectory:nil.
  1568      (Delay forSeconds:2) wait.
  1568      (Delay forSeconds:2) wait.
  1569      OperatingSystem killProcess:pid.
  1569      OperatingSystem killProcess:pid.
  1570     "
  1570     "
  1571 
  1571 
  1572     "Modified: / 21.3.1997 / 10:04:35 / dq"
  1572     "Modified: / 21.3.1997 / 10:04:35 / dq"
  1581      Return the processId if successful, nil otherwise.
  1581      Return the processId if successful, nil otherwise.
  1582      Use #waitForProcess: for synchronization and exec status return,
  1582      Use #waitForProcess: for synchronization and exec status return,
  1583      or #killProcess: to stop it."
  1583      or #killProcess: to stop it."
  1584 
  1584 
  1585     ^ self
  1585     ^ self
  1586 	startProcess:aCommandString 
  1586         startProcess:aCommandString 
  1587 	inputFrom:nil 
  1587         inputFrom:nil 
  1588 	outputTo:nil 
  1588         outputTo:nil 
  1589 	errorTo:nil 
  1589         errorTo:nil 
  1590 	inDirectory:aDirectory
  1590         inDirectory:aDirectory
  1591     "
  1591     "
  1592      |pid|
  1592      |pid|
  1593 
  1593 
  1594      pid := OperatingSystem startProcess:'sleep 2; echo 1; sleep 2; echo 2'.
  1594      pid := OperatingSystem startProcess:'sleep 2; echo 1; sleep 2; echo 2'.
  1595      (Delay forSeconds:3) wait.
  1595      (Delay forSeconds:3) wait.
  1611      Return the processId if successful, nil otherwise.
  1611      Return the processId if successful, nil otherwise.
  1612      Use #monitorPid:action: for synchronization and exec status return,
  1612      Use #monitorPid:action: for synchronization and exec status return,
  1613      or #killProcess: to stop it."
  1613      or #killProcess: to stop it."
  1614 
  1614 
  1615      ^ self     
  1615      ^ self     
  1616 	startProcess:aCommandString 
  1616         startProcess:aCommandString 
  1617 	inputFrom:anExternalInStream 
  1617         inputFrom:anExternalInStream 
  1618 	outputTo:anExternalOutStream 
  1618         outputTo:anExternalOutStream 
  1619 	errorTo:anExternalErrStream 
  1619         errorTo:anExternalErrStream 
  1620 	inDirectory:nil
  1620         inDirectory:nil
  1621 
  1621 
  1622     "Modified: / 10.11.1998 / 20:59:05 / cg"
  1622     "Modified: / 10.11.1998 / 20:59:05 / cg"
  1623 !
  1623 !
  1624 
  1624 
  1625 startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream inDirectory:dir
  1625 startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream inDirectory:dir
  1704      files/directories recursively to destinationPathName.
  1704      files/directories recursively to destinationPathName.
  1705      Return true if successful.
  1705      Return true if successful.
  1706      Here, false is returned and the caller should be prepared
  1706      Here, false is returned and the caller should be prepared
  1707      for a fallBack solution.
  1707      for a fallBack solution.
  1708      Notice: 
  1708      Notice: 
  1709 	this is not a public interface; instead, it is used
  1709         this is not a public interface; instead, it is used
  1710 	internally by the Filename class, to try a fast copy
  1710         internally by the Filename class, to try a fast copy
  1711 	before doing things manually.
  1711         before doing things manually.
  1712 	Please use Filename recursiveCopyTo:"
  1712         Please use Filename recursiveCopyTo:"
  1713 
  1713 
  1714     ^ false
  1714     ^ false
  1715 
  1715 
  1716     "
  1716     "
  1717      OperatingSystem recursiveCopyDirectory:'.' to:'/tmp/foo'
  1717      OperatingSystem recursiveCopyDirectory:'.' to:'/tmp/foo'
  1727      is returned, a partial created tree may be left,
  1727      is returned, a partial created tree may be left,
  1728      which is not cleaned-up here."
  1728      which is not cleaned-up here."
  1729 
  1729 
  1730     self createDirectory:dirName.
  1730     self createDirectory:dirName.
  1731     (self isDirectory:dirName) ifFalse:[
  1731     (self isDirectory:dirName) ifFalse:[
  1732 	(self recursiveCreateDirectory:(dirName asFilename directoryName)) ifFalse:[^ false].
  1732         (self recursiveCreateDirectory:(dirName asFilename directoryName)) ifFalse:[^ false].
  1733 	^ self createDirectory:dirName
  1733         ^ self createDirectory:dirName
  1734     ].
  1734     ].
  1735     ^ true
  1735     ^ true
  1736 
  1736 
  1737     "
  1737     "
  1738      OperatingSystem recursiveCreateDirectory:'foo/bar/baz'
  1738      OperatingSystem recursiveCreateDirectory:'foo/bar/baz'
  1746     "remove the directory named 'fullPathName' and all contained files/directories.
  1746     "remove the directory named 'fullPathName' and all contained files/directories.
  1747      Return true if successful.
  1747      Return true if successful.
  1748      Here, false is returned and the caller should be prepared
  1748      Here, false is returned and the caller should be prepared
  1749      for a fallBack solution.
  1749      for a fallBack solution.
  1750      Notice: 
  1750      Notice: 
  1751 	this is not a public interface; instead, it is used
  1751         this is not a public interface; instead, it is used
  1752 	internally by the Filename class, to try a fast remove
  1752         internally by the Filename class, to try a fast remove
  1753 	before doing things manually.
  1753         before doing things manually.
  1754 	Please use Filename recursiveRemoveDirectory:"
  1754         Please use Filename recursiveRemoveDirectory:"
  1755 
  1755 
  1756     ^ false
  1756     ^ false
  1757 
  1757 
  1758     "
  1758     "
  1759      OperatingSystem recursiveCreateDirectory:'foo/bar/baz'
  1759      OperatingSystem recursiveCreateDirectory:'foo/bar/baz'
  1817      Notice that the returned number is OS dependent - use the 
  1817      Notice that the returned number is OS dependent - use the 
  1818      modeMasks as returned by OperatingSystem>>accessMaskFor:"
  1818      modeMasks as returned by OperatingSystem>>accessMaskFor:"
  1819 
  1819 
  1820     "
  1820     "
  1821      this could have been implemented as:
  1821      this could have been implemented as:
  1822 	(self infoOf:aPathName) at:#mode
  1822         (self infoOf:aPathName) at:#mode
  1823      but for huge directory searches the code below is faster
  1823      but for huge directory searches the code below is faster
  1824     "
  1824     "
  1825 
  1825 
  1826     ^ (self infoOf:aPathName) at:#mode
  1826     ^ (self infoOf:aPathName) at:#mode
  1827 
  1827 
  1995     "/
  1995     "/
  1996     "/ default: return an array filled with
  1996     "/ default: return an array filled with
  1997     "/ root, home and current directories.
  1997     "/ root, home and current directories.
  1998     "/
  1998     "/
  1999     ^ Array 
  1999     ^ Array 
  2000 	with:'/'
  2000         with:'/'
  2001 	with:(self getHomeDirectory)
  2001         with:(self getHomeDirectory)
  2002 	with:(Filename currentDirectory pathName)
  2002         with:(Filename currentDirectory pathName)
  2003 
  2003 
  2004     "Modified: / 5.5.1999 / 01:06:26 / cg"
  2004     "Modified: / 5.5.1999 / 01:06:26 / cg"
       
  2005 !
       
  2006 
       
  2007 getMountedVolumes
       
  2008     "return info about mounted volumes. 
       
  2009      The amount of information returned depends upon the OS, and is
       
  2010      not guaranteed to be consistent across architectures.
       
  2011      On unix, the information returned is (at least):
       
  2012         mountPoint - mount point
       
  2013         fileSystem - device or NFS-remotePath
       
  2014     "
       
  2015 
       
  2016     ^ #()
       
  2017 
       
  2018     "
       
  2019      OperatingSystem getMountedVolumes
       
  2020     "
       
  2021 
       
  2022     "Modified: / 22.5.1999 / 00:36:06 / cg"
  2005 !
  2023 !
  2006 
  2024 
  2007 getNullDevice
  2025 getNullDevice
  2008     "get the name of the null-device. Nil is returned if not supported"
  2026     "get the name of the null-device. Nil is returned if not supported"
  2009 
  2027 
  2037 
  2055 
  2038 infoOf:aPathName
  2056 infoOf:aPathName
  2039     "return some object filled with info for the file 'aPathName';
  2057     "return some object filled with info for the file 'aPathName';
  2040      the info (for which corresponding access methods are understood by
  2058      the info (for which corresponding access methods are understood by
  2041      the returned object) is:
  2059      the returned object) is:
  2042 	 type            - a symbol giving the files type
  2060          type            - a symbol giving the files type
  2043 	 mode            - numeric access mode 
  2061          mode            - numeric access mode 
  2044 	 uid             - owners user id
  2062          uid             - owners user id
  2045 	 gid             - owners group id
  2063          gid             - owners group id
  2046 	 size            - files size
  2064          size            - files size
  2047 	 id              - files number (i.e. inode number)
  2065          id              - files number (i.e. inode number)
  2048 	 accessed        - last access time (as Timestamp)
  2066          accessed        - last access time (as Timestamp)
  2049 	 modified        - last modification time (as Timestamp)
  2067          modified        - last modification time (as Timestamp)
  2050 	 statusChanged   - last status change time (as Timestamp)
  2068          statusChanged   - last status change time (as Timestamp)
  2051 	 alternativeName - (windows only: the MSDOS name of the file)
  2069          alternativeName - (windows only: the MSDOS name of the file)
  2052 
  2070 
  2053      Some of the fields may be returned as nil on systems which do not provide
  2071      Some of the fields may be returned as nil on systems which do not provide
  2054      all of the information.
  2072      all of the information.
  2055      Return nil if such a file does not exist. 
  2073      Return nil if such a file does not exist. 
  2056      For symbolic links (if supported by the OS), 
  2074      For symbolic links (if supported by the OS), 
  2306 !
  2324 !
  2307 
  2325 
  2308 disableTimer
  2326 disableTimer
  2309     "disable timer interrupts.
  2327     "disable timer interrupts.
  2310      WARNING: 
  2328      WARNING: 
  2311 	the system will not operate correctly with timer interrupts
  2329         the system will not operate correctly with timer interrupts
  2312 	disabled, because no scheduling or timeouts are possible."
  2330         disabled, because no scheduling or timeouts are possible."
  2313 
  2331 
  2314     self subclassResponsibility
  2332     self subclassResponsibility
  2315 !
  2333 !
  2316 
  2334 
  2317 disableUserInterrupts
  2335 disableUserInterrupts
  2318     "disable userInterrupt processing;
  2336     "disable userInterrupt processing;
  2319      when disabled, no ^C processing takes place.
  2337      when disabled, no ^C processing takes place.
  2320      WARNING:
  2338      WARNING:
  2321 	 If at all, use this only for debugged stand-alone applications, since
  2339          If at all, use this only for debugged stand-alone applications, since
  2322 	 no exit to the debugger is possible with user interrupts disabled.
  2340          no exit to the debugger is possible with user interrupts disabled.
  2323 	 We recommend setting up a handler for the signal instead of disabling it."
  2341          We recommend setting up a handler for the signal instead of disabling it."
  2324 
  2342 
  2325     self disableSignal:(self sigBREAK).
  2343     self disableSignal:(self sigBREAK).
  2326     self disableSignal:(self sigINT).
  2344     self disableSignal:(self sigINT).
  2327 !
  2345 !
  2328 
  2346 
  2441 killProcess:processId
  2459 killProcess:processId
  2442     "kill an OS process.
  2460     "kill an OS process.
  2443      The process has a no chance to do some cleanup.
  2461      The process has a no chance to do some cleanup.
  2444 
  2462 
  2445      WARNING: in order to avoid zombie processes (on unix),
  2463      WARNING: in order to avoid zombie processes (on unix),
  2446 	      you may have to fetch the processes exitstatus with
  2464               you may have to fetch the processes exitstatus with
  2447 	      OperatingSystem>>getStatusOfProcess:aProcessId."
  2465               OperatingSystem>>getStatusOfProcess:aProcessId."
  2448 
  2466 
  2449     self subclassResponsibility
  2467     self subclassResponsibility
  2450 
  2468 
  2451     "Modified: / 10.6.1998 / 12:00:07 / cg"
  2469     "Modified: / 10.6.1998 / 12:00:07 / cg"
  2452 !
  2470 !
  2454 killProcessGroup:processGroupId
  2472 killProcessGroup:processGroupId
  2455     "kill an OS process group.
  2473     "kill an OS process group.
  2456      The process has NO chance to do some cleanup.
  2474      The process has NO chance to do some cleanup.
  2457 
  2475 
  2458      WARNING: in order to avoid zombie processes (on unix),
  2476      WARNING: in order to avoid zombie processes (on unix),
  2459 	      you may have to fetch the processes exitstatus with
  2477               you may have to fetch the processes exitstatus with
  2460 	      OperatingSystem>>getStatusOfProcess:aProcessId."
  2478               OperatingSystem>>getStatusOfProcess:aProcessId."
  2461 
  2479 
  2462     self subclassResponsibility
  2480     self subclassResponsibility
  2463 
  2481 
  2464     "Created: / 10.6.1998 / 12:00:26 / cg"
  2482     "Created: / 10.6.1998 / 12:00:26 / cg"
  2465 !
  2483 !
  2505     aSignalNumber == self sigRETRACT ifTrue:[^ 'HFT access relinquish'].
  2523     aSignalNumber == self sigRETRACT ifTrue:[^ 'HFT access relinquish'].
  2506     aSignalNumber == self sigSOUND   ifTrue:[^ 'HFT sound complete'].
  2524     aSignalNumber == self sigSOUND   ifTrue:[^ 'HFT sound complete'].
  2507     aSignalNumber == self sigDANGER  ifTrue:[^ 'low on paging space'].
  2525     aSignalNumber == self sigDANGER  ifTrue:[^ 'low on paging space'].
  2508 
  2526 
  2509     "notice: many systems map SIGPOLL and/or SIGUSR onto SIGIO
  2527     "notice: many systems map SIGPOLL and/or SIGUSR onto SIGIO
  2510 	     therefore, keep SIGIO always above the two below" 
  2528              therefore, keep SIGIO always above the two below" 
  2511     aSignalNumber == self sigPOLL   ifTrue:[^ 'io available'].
  2529     aSignalNumber == self sigPOLL   ifTrue:[^ 'io available'].
  2512     aSignalNumber == self sigURG    ifTrue:[^ 'urgent'].
  2530     aSignalNumber == self sigURG    ifTrue:[^ 'urgent'].
  2513 
  2531 
  2514     ^ 'unknown signal'
  2532     ^ 'unknown signal'
  2515 
  2533 
  2522 operatingSystemSignal:signalNumber
  2540 operatingSystemSignal:signalNumber
  2523     "return the signal to be raised when an 
  2541     "return the signal to be raised when an 
  2524      operatingSystem-signal occurs, or nil"
  2542      operatingSystem-signal occurs, or nil"
  2525 
  2543 
  2526     OSSignals notNil ifTrue:[
  2544     OSSignals notNil ifTrue:[
  2527 	^ OSSignals at:signalNumber ifAbsent:[nil]
  2545         ^ OSSignals at:signalNumber ifAbsent:[nil]
  2528     ].
  2546     ].
  2529     ^ nil
  2547     ^ nil
  2530 !
  2548 !
  2531 
  2549 
  2532 operatingSystemSignal:signalNumber install:aSignal
  2550 operatingSystemSignal:signalNumber install:aSignal
  2533     "install a signal to be raised when an operatingSystem-signal occurs"
  2551     "install a signal to be raised when an operatingSystem-signal occurs"
  2534 
  2552 
  2535     OSSignals isNil ifTrue:[
  2553     OSSignals isNil ifTrue:[
  2536 	OSSignals := Array new:32
  2554         OSSignals := Array new:32
  2537     ].
  2555     ].
  2538     OSSignals at:signalNumber put:aSignal
  2556     OSSignals at:signalNumber put:aSignal
  2539 !
  2557 !
  2540 
  2558 
  2541 sendSignal:signalNumber to:processId
  2559 sendSignal:signalNumber to:processId
  2543      Returns false if any error occurred, true otherwise.
  2561      Returns false if any error occurred, true otherwise.
  2544 
  2562 
  2545      Do not confuse UNIX signals with Smalltalk-Signals.
  2563      Do not confuse UNIX signals with Smalltalk-Signals.
  2546 
  2564 
  2547      WARNING: in order to avoid zombie processes (on unix),
  2565      WARNING: in order to avoid zombie processes (on unix),
  2548 	      you may have to fetch the processes exitstatus with
  2566               you may have to fetch the processes exitstatus with
  2549 	      OperatingSystem>>getStatusOfProcess:aProcessId
  2567               OperatingSystem>>getStatusOfProcess:aProcessId
  2550 	      if the signal terminates that process."
  2568               if the signal terminates that process."
  2551 
  2569 
  2552     self subclassResponsibility
  2570     self subclassResponsibility
  2553 !
  2571 !
  2554 
  2572 
  2555 startSpyTimer
  2573 startSpyTimer
  2557      Return true, if the spy-timerInterrupt was enabled.
  2575      Return true, if the spy-timerInterrupt was enabled.
  2558      This was used by the old MessageTally for profiling.
  2576      This was used by the old MessageTally for profiling.
  2559      On systems, where no virtual timer is available, use the real timer
  2577      On systems, where no virtual timer is available, use the real timer
  2560      (which is of course less correct).
  2578      (which is of course less correct).
  2561      OBSOLETE: the new messageTally runs as a high prio process, not using 
  2579      OBSOLETE: the new messageTally runs as a high prio process, not using 
  2562 	       spy interrupts."
  2580                spy interrupts."
  2563 
  2581 
  2564     ^ false
  2582     ^ false
  2565 !
  2583 !
  2566 
  2584 
  2567 stopSpyTimer
  2585 stopSpyTimer
  2568     "stop spy timing - disable spy timer.
  2586     "stop spy timing - disable spy timer.
  2569      OBSOLETE: the new messageTally runs as a high prio process, not using 
  2587      OBSOLETE: the new messageTally runs as a high prio process, not using 
  2570 	       spy interrupts."
  2588                spy interrupts."
  2571 
  2589 
  2572     ^ false
  2590     ^ false
  2573 !
  2591 !
  2574 
  2592 
  2575 terminateProcess:processId
  2593 terminateProcess:processId
  2576     "terminate a unix process.
  2594     "terminate a unix process.
  2577      The process has a chance to do some cleanup.
  2595      The process has a chance to do some cleanup.
  2578 
  2596 
  2579      WARNING: in order to avoid zombie processes (on unix),
  2597      WARNING: in order to avoid zombie processes (on unix),
  2580 	      you may have to fetch the processes exitstatus with
  2598               you may have to fetch the processes exitstatus with
  2581 	      OperatingSystem>>getStatusOfProcess:aProcessId."
  2599               OperatingSystem>>getStatusOfProcess:aProcessId."
  2582 
  2600 
  2583     self subclassResponsibility
  2601     self subclassResponsibility
  2584 !
  2602 !
  2585 
  2603 
  2586 terminateProcessGroup:processGroupId
  2604 terminateProcessGroup:processGroupId
  2587     "terminate a unix process group.
  2605     "terminate a unix process group.
  2588      The process has a chance to do some cleanup.
  2606      The process has a chance to do some cleanup.
  2589 
  2607 
  2590      WARNING: in order to avoid zombie processes (on unix),
  2608      WARNING: in order to avoid zombie processes (on unix),
  2591 	      you may have to fetch the processes exitstatus with
  2609               you may have to fetch the processes exitstatus with
  2592 	      OperatingSystem>>getStatusOfProcess:aProcessId."
  2610               OperatingSystem>>getStatusOfProcess:aProcessId."
  2593 
  2611 
  2594     self subclassResponsibility
  2612     self subclassResponsibility
  2595 !
  2613 !
  2596 
  2614 
  2597 unblockInterrupts
  2615 unblockInterrupts
  2630 
  2648 
  2631 %{  /* NOCONTEXT */
  2649 %{  /* NOCONTEXT */
  2632     int code = 1;
  2650     int code = 1;
  2633 
  2651 
  2634     if (__isSmallInteger(exitCode)) {
  2652     if (__isSmallInteger(exitCode)) {
  2635 	code = __intVal(exitCode);
  2653         code = __intVal(exitCode);
  2636     }
  2654     }
  2637     __mainExit(code);
  2655     __mainExit(code);
  2638 %}
  2656 %}
  2639     "OperatingSystem exit:1 - dont evaluate this"
  2657     "OperatingSystem exit:1 - dont evaluate this"
  2640 !
  2658 !
  2784 !
  2802 !
  2785 
  2803 
  2786 getDomainName
  2804 getDomainName
  2787     "return the domain this host is in.
  2805     "return the domain this host is in.
  2788      Notice:
  2806      Notice:
  2789 	not all systems support this; on some, 'unknown' is returned."
  2807         not all systems support this; on some, 'unknown' is returned."
  2790 
  2808 
  2791     self subclassResponsibility
  2809     self subclassResponsibility
  2792 !
  2810 !
  2793 
  2811 
  2794 getEnvironment:aStringOrSymbol
  2812 getEnvironment:aStringOrSymbol
  2799 
  2817 
  2800 getHostName
  2818 getHostName
  2801     "return the hostname we are running on - if there is
  2819     "return the hostname we are running on - if there is
  2802      a HOST environment variable, we are much faster here ...
  2820      a HOST environment variable, we are much faster here ...
  2803      Notice:
  2821      Notice:
  2804 	not all systems support this; on some, 'unknown' is returned."
  2822         not all systems support this; on some, 'unknown' is returned."
  2805 
  2823 
  2806     self subclassResponsibility
  2824     self subclassResponsibility
  2807 !
  2825 !
  2808 
  2826 
  2809 getLocaleInfo
  2827 getLocaleInfo
  2810     "return a dictionary filled with values from the locale information;
  2828     "return a dictionary filled with values from the locale information;
  2811      Not all fields may be present, depending on the OS's setup and capabilities.
  2829      Not all fields may be present, depending on the OS's setup and capabilities.
  2812      Possible fields are:
  2830      Possible fields are:
  2813 	decimalPoint                    <String>
  2831         decimalPoint                    <String>
  2814 
  2832 
  2815 	thousandsSep                    <String>
  2833         thousandsSep                    <String>
  2816 
  2834 
  2817 	internationalCurrencySymbol     <String>
  2835         internationalCurrencySymbol     <String>
  2818 
  2836 
  2819 	currencySymbol                  <String>
  2837         currencySymbol                  <String>
  2820 
  2838 
  2821 	monetaryDecimalPoint            <String>
  2839         monetaryDecimalPoint            <String>
  2822 
  2840 
  2823 	monetaryThousandsSeparator      <String>
  2841         monetaryThousandsSeparator      <String>
  2824 
  2842 
  2825 	positiveSign                    <String>
  2843         positiveSign                    <String>
  2826 
  2844 
  2827 	negativeSign                    <String>
  2845         negativeSign                    <String>
  2828 
  2846 
  2829 	internationalFractionalDigits   <Integer>
  2847         internationalFractionalDigits   <Integer>
  2830 
  2848 
  2831 	fractionalDigits                <Integer>
  2849         fractionalDigits                <Integer>
  2832 
  2850 
  2833 	positiveSignPrecedesCurrencySymbol      <Boolean>
  2851         positiveSignPrecedesCurrencySymbol      <Boolean>
  2834 
  2852 
  2835 	negativeSignPrecedesCurrencySymbol      <Boolean>
  2853         negativeSignPrecedesCurrencySymbol      <Boolean>
  2836 
  2854 
  2837 	positiveSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  2855         positiveSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  2838 
  2856 
  2839 	negativeSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  2857         negativeSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
  2840 
  2858 
  2841 	positiveSignPosition                            <Symbol>
  2859         positiveSignPosition                            <Symbol>
  2842 							one of: #parenthesesAround, 
  2860                                                         one of: #parenthesesAround, 
  2843 								#signPrecedes, 
  2861                                                                 #signPrecedes, 
  2844 								#signSuceeds, 
  2862                                                                 #signSuceeds, 
  2845 								#signPrecedesCurrencySymbol,
  2863                                                                 #signPrecedesCurrencySymbol,
  2846 								#signSuceedsCurrencySymbol
  2864                                                                 #signSuceedsCurrencySymbol
  2847 
  2865 
  2848 	negativeSignPosition                            <like above>
  2866         negativeSignPosition                            <like above>
  2849 
  2867 
  2850      it is up to the application to deal with undefined values.
  2868      it is up to the application to deal with undefined values.
  2851 
  2869 
  2852      Notice, that (for now), the system does not use this information;
  2870      Notice, that (for now), the system does not use this information;
  2853      it should be used by applications as required.
  2871      it should be used by applications as required.
  3027 
  3045 
  3028 getSystemID
  3046 getSystemID
  3029     "if supported by the OS, return the systemID;
  3047     "if supported by the OS, return the systemID;
  3030      a unique per machine identification.
  3048      a unique per machine identification.
  3031      WARNING:
  3049      WARNING:
  3032 	not all systems support this; on some, 'unknown' is returned."
  3050         not all systems support this; on some, 'unknown' is returned."
  3033 
  3051 
  3034     ^ 'unknown'
  3052     ^ 'unknown'
  3035 
  3053 
  3036     "
  3054     "
  3037      OperatingSystem getSystemID
  3055      OperatingSystem getSystemID
  3049        OS, for example, linux returns 'ix86', while WIN32 returns 'x86'.
  3067        OS, for example, linux returns 'ix86', while WIN32 returns 'x86'.
  3050 
  3068 
  3051        This method is mainly provided to augment error reports with some system
  3069        This method is mainly provided to augment error reports with some system
  3052        information. 
  3070        information. 
  3053        (in case of system/version specific OS errors, conditional workarounds and patches
  3071        (in case of system/version specific OS errors, conditional workarounds and patches
  3054 	may be based upon this info).
  3072         may be based upon this info).
  3055        Your application should NOT depend upon this in any way.
  3073        Your application should NOT depend upon this in any way.
  3056 
  3074 
  3057      The returned info may (or may not) contain:
  3075      The returned info may (or may not) contain:
  3058 	#system -> some operating system identification (irix, Linux, nt, win32s ...) 
  3076         #system -> some operating system identification (irix, Linux, nt, win32s ...) 
  3059 	#version -> OS version (some os version identification)
  3077         #version -> OS version (some os version identification)
  3060 	#release -> OS release (3.5, 1.2.1 ...)
  3078         #release -> OS release (3.5, 1.2.1 ...)
  3061 	#node   -> some host identification (hostname)
  3079         #node   -> some host identification (hostname)
  3062 	#domain  -> domain name (hosts domain)
  3080         #domain  -> domain name (hosts domain)
  3063 	#machine -> type of machine (i586, mips ...)
  3081         #machine -> type of machine (i586, mips ...)
  3064     "
  3082     "
  3065 
  3083 
  3066     |info|
  3084     |info|
  3067 
  3085 
  3068     info := IdentityDictionary new.
  3086     info := IdentityDictionary new.
  3185 !
  3203 !
  3186 
  3204 
  3187 maxFileNameLength
  3205 maxFileNameLength
  3188     "return the max number of characters in a filename.
  3206     "return the max number of characters in a filename.
  3189      CAVEAT:
  3207      CAVEAT:
  3190 	 Actually, the following is somewhat wrong - some systems
  3208          Actually, the following is somewhat wrong - some systems
  3191 	 support different sizes, depending on the volume.
  3209          support different sizes, depending on the volume.
  3192 	 We return a somewhat conservative number here.
  3210          We return a somewhat conservative number here.
  3193 	 Another entry, to query for volume specific max
  3211          Another entry, to query for volume specific max
  3194 	 will be added in the future."
  3212          will be added in the future."
  3195 
  3213 
  3196     self subclassResponsibility
  3214     self subclassResponsibility
  3197 !
  3215 !
  3198 
  3216 
  3199 maxPathLength
  3217 maxPathLength
  3360     "/
  3378     "/
  3361     "/ the users home (login) directory
  3379     "/ the users home (login) directory
  3362     "/
  3380     "/
  3363     homePath := OperatingSystem getHomeDirectory.
  3381     homePath := OperatingSystem getHomeDirectory.
  3364     homePath notNil ifTrue:[
  3382     homePath notNil ifTrue:[
  3365 	sysPath add:homePath.
  3383         sysPath add:homePath.
  3366 
  3384 
  3367 	"/
  3385         "/
  3368 	"/ a users private smalltalk directory in its home (login) directory
  3386         "/ a users private smalltalk directory in its home (login) directory
  3369 	"/
  3387         "/
  3370 	OperatingSystem isUNIXlike ifTrue:[
  3388         OperatingSystem isUNIXlike ifTrue:[
  3371 	    priv := '.smalltalk'.
  3389             priv := '.smalltalk'.
  3372 	] ifFalse:[
  3390         ] ifFalse:[
  3373 	    priv := 'smalltalk'.
  3391             priv := 'smalltalk'.
  3374 	].
  3392         ].
  3375 	userPrivateSTXDir := homePath asFilename constructString:priv.
  3393         userPrivateSTXDir := homePath asFilename constructString:priv.
  3376 	(userPrivateSTXDir asFilename isDirectory) ifTrue:[
  3394         (userPrivateSTXDir asFilename isDirectory) ifTrue:[
  3377 	    sysPath add:userPrivateSTXDir
  3395             sysPath add:userPrivateSTXDir
  3378 	].
  3396         ].
  3379     ].
  3397     ].
  3380 
  3398 
  3381     "/
  3399     "/
  3382     "/ SMALLTALK_LIBDIR and/or STX_LIBDIR from the environment
  3400     "/ SMALLTALK_LIBDIR and/or STX_LIBDIR from the environment
  3383     "/
  3401     "/
  3384     p := OperatingSystem getEnvironment:'SMALLTALK_LIBDIR'.
  3402     p := OperatingSystem getEnvironment:'SMALLTALK_LIBDIR'.
  3385     p notNil ifTrue:[
  3403     p notNil ifTrue:[
  3386 	sysPath add:p
  3404         sysPath add:p
  3387     ].
  3405     ].
  3388     p := OperatingSystem getEnvironment:'STX_LIBDIR'.
  3406     p := OperatingSystem getEnvironment:'STX_LIBDIR'.
  3389     p notNil ifTrue:[
  3407     p notNil ifTrue:[
  3390 	sysPath add:p
  3408         sysPath add:p
  3391     ].
  3409     ].
  3392     ^ sysPath
  3410     ^ sysPath
  3393 ! !
  3411 ! !
  3394 
  3412 
  3395 !AbstractOperatingSystem class methodsFor:'private'!
  3413 !AbstractOperatingSystem class methodsFor:'private'!
  3514      Since this value is wrapping around in regular intervals, this can only be used for 
  3532      Since this value is wrapping around in regular intervals, this can only be used for 
  3515      short relative time deltas.
  3533      short relative time deltas.
  3516      Use the millisecondTimeXXX:-methods to compare and add time deltas - these know about the wrap.
  3534      Use the millisecondTimeXXX:-methods to compare and add time deltas - these know about the wrap.
  3517 
  3535 
  3518      BAD DESIGN:
  3536      BAD DESIGN:
  3519 	This should be changed to return some instance of RelativeTime,
  3537         This should be changed to return some instance of RelativeTime,
  3520 	and these computations moved there.
  3538         and these computations moved there.
  3521 
  3539 
  3522      Dont use this method in application code since it is an internal (private)
  3540      Dont use this method in application code since it is an internal (private)
  3523      interface. For compatibility with ST-80, use Time millisecondClockValue.
  3541      interface. For compatibility with ST-80, use Time millisecondClockValue.
  3524     "
  3542     "
  3525 
  3543 
  3564 
  3582 
  3565     now := self getMillisecondTime.
  3583     now := self getMillisecondTime.
  3566     then := self millisecondTimeAdd:now and:millis.
  3584     then := self millisecondTimeAdd:now and:millis.
  3567 
  3585 
  3568     [self millisecondTime:then isAfter:now] whileTrue:[
  3586     [self millisecondTime:then isAfter:now] whileTrue:[
  3569 	delta := self millisecondTimeDeltaBetween:then and:now.
  3587         delta := self millisecondTimeDeltaBetween:then and:now.
  3570 	self selectOnAnyReadable:nil writable:nil exception:nil withTimeOut:delta.
  3588         self selectOnAnyReadable:nil writable:nil exception:nil withTimeOut:delta.
  3571 	now := self getMillisecondTime.
  3589         now := self getMillisecondTime.
  3572     ]
  3590     ]
  3573 
  3591 
  3574     "
  3592     "
  3575      OperatingSystem millisecondDelay:2000
  3593      OperatingSystem millisecondDelay:2000
  3576     "
  3594     "
  3582      (such as returned getMillisecondTime) which wrap at 16r1FFFFFFF.
  3600      (such as returned getMillisecondTime) which wrap at 16r1FFFFFFF.
  3583 
  3601 
  3584      This should really be moved to some RelativeTime class."
  3602      This should really be moved to some RelativeTime class."
  3585 
  3603 
  3586     (msTime1 > msTime2) ifTrue:[
  3604     (msTime1 > msTime2) ifTrue:[
  3587 	((msTime1 - msTime2) >= 16r10000000) ifTrue:[
  3605         ((msTime1 - msTime2) >= 16r10000000) ifTrue:[
  3588 	    ^ false
  3606             ^ false
  3589 	].
  3607         ].
  3590 	^ true
  3608         ^ true
  3591     ].
  3609     ].
  3592     ((msTime2 - msTime1) > 16r10000000) ifTrue:[
  3610     ((msTime2 - msTime1) > 16r10000000) ifTrue:[
  3593 	^ true
  3611         ^ true
  3594     ].
  3612     ].
  3595     ^ false
  3613     ^ false
  3596 !
  3614 !
  3597 
  3615 
  3598 millisecondTimeAdd:msTime1 and:msTime2
  3616 millisecondTimeAdd:msTime1 and:msTime2
  3618 
  3636 
  3619      This should really be moved to some RelativeTime class;
  3637      This should really be moved to some RelativeTime class;
  3620      better yet: create a subclass of Integer named LimitedRangeInteger."
  3638      better yet: create a subclass of Integer named LimitedRangeInteger."
  3621 
  3639 
  3622     (msTime1 > msTime2) ifTrue:[
  3640     (msTime1 > msTime2) ifTrue:[
  3623 	^ msTime1 - msTime2
  3641         ^ msTime1 - msTime2
  3624     ].
  3642     ].
  3625     ^ msTime1 + 16r10000000 - msTime2
  3643     ^ msTime1 + 16r10000000 - msTime2
  3626 
  3644 
  3627     "
  3645     "
  3628      OperatingSystem millisecondTimeAdd:16r0FFFFFFF and:1   
  3646      OperatingSystem millisecondTimeAdd:16r0FFFFFFF and:1   
  3798      This is the login name, not the fullName."
  3816      This is the login name, not the fullName."
  3799 
  3817 
  3800     "/ fallBack dummy
  3818     "/ fallBack dummy
  3801 
  3819 
  3802     aNumber == self getUserID ifTrue:[
  3820     aNumber == self getUserID ifTrue:[
  3803 	^ self getLoginName
  3821         ^ self getLoginName
  3804     ].
  3822     ].
  3805 
  3823 
  3806     ^ '? (' , aNumber printString , ')'
  3824     ^ '? (' , aNumber printString , ')'
  3807 
  3825 
  3808     "
  3826     "
  3877     "return true, if data is available on a filedescriptor 
  3895     "return true, if data is available on a filedescriptor 
  3878      (i.e. read is possible without blocking).
  3896      (i.e. read is possible without blocking).
  3879      This depends on a working select or FIONREAD to be provided by the OS."
  3897      This depends on a working select or FIONREAD to be provided by the OS."
  3880 
  3898 
  3881     self supportsSelect ifFalse:[
  3899     self supportsSelect ifFalse:[
  3882 	"/ mhmh - what should we do then ?
  3900         "/ mhmh - what should we do then ?
  3883 	"/ For now, return true as if data was present,
  3901         "/ For now, return true as if data was present,
  3884 	"/ and let the thread fall into the read.
  3902         "/ and let the thread fall into the read.
  3885 	"/ It will then (hopefully) be desceduled there and
  3903         "/ It will then (hopefully) be desceduled there and
  3886 	"/ effectively polling for input.
  3904         "/ effectively polling for input.
  3887 
  3905 
  3888 	^ true
  3906         ^ true
  3889     ].
  3907     ].
  3890 
  3908 
  3891     (self selectOnAnyReadable:(Array with:fd)
  3909     (self selectOnAnyReadable:(Array with:fd)
  3892 		     writable:nil
  3910                      writable:nil
  3893 		    exception:nil
  3911                     exception:nil
  3894 		  withTimeOut:0) == fd
  3912                   withTimeOut:0) == fd
  3895 	ifTrue:[^ true].
  3913         ifTrue:[^ true].
  3896     ^ false
  3914     ^ false
  3897 !
  3915 !
  3898 
  3916 
  3899 readWriteCheck:fd
  3917 readWriteCheck:fd
  3900     "return true, if filedescriptor can be read or written without blocking.
  3918     "return true, if filedescriptor can be read or written without blocking.
  3901      This is actually only used with sockets, to wait for a connect to
  3919      This is actually only used with sockets, to wait for a connect to
  3902      be finished."
  3920      be finished."
  3903 
  3921 
  3904     self supportsSelect ifFalse:[
  3922     self supportsSelect ifFalse:[
  3905 	"/ mhmh - what should we do then ?
  3923         "/ mhmh - what should we do then ?
  3906 	"/ For now, return true as if data was present,
  3924         "/ For now, return true as if data was present,
  3907 	"/ and let the thread fall into the write.
  3925         "/ and let the thread fall into the write.
  3908 	"/ It will then (hopefully) be desceduled there and
  3926         "/ It will then (hopefully) be desceduled there and
  3909 	"/ effectively polling for output.
  3927         "/ effectively polling for output.
  3910 	^ true
  3928         ^ true
  3911     ].
  3929     ].
  3912 
  3930 
  3913     (self selectOnAnyReadable:(Array with:fd)
  3931     (self selectOnAnyReadable:(Array with:fd)
  3914 		     writable:(Array with:fd)
  3932                      writable:(Array with:fd)
  3915 		    exception:nil
  3933                     exception:nil
  3916 		  withTimeOut:0) == fd
  3934                   withTimeOut:0) == fd
  3917 	ifTrue:[^ true].
  3935         ifTrue:[^ true].
  3918     ^ false
  3936     ^ false
  3919 !
  3937 !
  3920 
  3938 
  3921 selectOn:fd1 and:fd2 withTimeOut:millis
  3939 selectOn:fd1 and:fd2 withTimeOut:millis
  3922     "wait for any fd to become ready; timeout after t milliseconds.
  3940     "wait for any fd to become ready; timeout after t milliseconds.
  3923      A zero timeout-time will immediately return (i.e. poll).
  3941      A zero timeout-time will immediately return (i.e. poll).
  3924      Return fd if i/o ok, nil if timed-out or interrupted.
  3942      Return fd if i/o ok, nil if timed-out or interrupted.
  3925      Obsolete:
  3943      Obsolete:
  3926 	This is a leftover method and will vanish."
  3944         This is a leftover method and will vanish."
  3927 
  3945 
  3928     ^ self selectOnAnyReadable:(Array with:fd1 with:fd2)
  3946     ^ self selectOnAnyReadable:(Array with:fd1 with:fd2)
  3929 		      writable:(Array with:fd1 with:fd2)
  3947                       writable:(Array with:fd1 with:fd2)
  3930 		     exception:nil
  3948                      exception:nil
  3931 		   withTimeOut:millis
  3949                    withTimeOut:millis
  3932 !
  3950 !
  3933 
  3951 
  3934 selectOn:fd withTimeOut:millis
  3952 selectOn:fd withTimeOut:millis
  3935     "wait for aFileDesriptor to become ready; timeout after t milliseconds.
  3953     "wait for aFileDesriptor to become ready; timeout after t milliseconds.
  3936      Return true, if i/o ok, false if timed-out or interrupted.
  3954      Return true, if i/o ok, false if timed-out or interrupted.
  3937      With 0 as timeout argument, this can be used to check for availability
  3955      With 0 as timeout argument, this can be used to check for availability
  3938      of read-data.
  3956      of read-data.
  3939      Experimental."
  3957      Experimental."
  3940 
  3958 
  3941     ^ self selectOnAnyReadable:(Array with:fd)
  3959     ^ self selectOnAnyReadable:(Array with:fd)
  3942 		      writable:(Array with:fd)
  3960                       writable:(Array with:fd)
  3943 		     exception:nil
  3961                      exception:nil
  3944 		   withTimeOut:millis
  3962                    withTimeOut:millis
  3945 !
  3963 !
  3946 
  3964 
  3947 selectOnAny:fdArray withTimeOut:millis
  3965 selectOnAny:fdArray withTimeOut:millis
  3948     "wait for any fd in fdArray (an Array of integers) to become ready;
  3966     "wait for any fd in fdArray (an Array of integers) to become ready;
  3949      timeout after t milliseconds. An empty set will always wait.
  3967      timeout after t milliseconds. An empty set will always wait.
  3950      Return first ready fd if i/o ok, nil if timed-out or interrupted.
  3968      Return first ready fd if i/o ok, nil if timed-out or interrupted.
  3951      Experimental."
  3969      Experimental."
  3952 
  3970 
  3953     ^ self selectOnAnyReadable:fdArray
  3971     ^ self selectOnAnyReadable:fdArray
  3954 		      writable:fdArray
  3972                       writable:fdArray
  3955 		     exception:nil
  3973                      exception:nil
  3956 		   withTimeOut:millis
  3974                    withTimeOut:millis
  3957 !
  3975 !
  3958 
  3976 
  3959 selectOnAnyReadable:fdArray withTimeOut:millis
  3977 selectOnAnyReadable:fdArray withTimeOut:millis
  3960     "wait for any fd in fdArray (an Array of integers) to become ready for 
  3978     "wait for any fd in fdArray (an Array of integers) to become ready for 
  3961      reading. Timeout after t milliseconds. An empty set will always wait.
  3979      reading. Timeout after t milliseconds. An empty set will always wait.
  3962      A zero timeout-time will immediately return (i.e. poll).
  3980      A zero timeout-time will immediately return (i.e. poll).
  3963      Return first ready fd if i/o ok, nil if timed-out or interrupted.
  3981      Return first ready fd if i/o ok, nil if timed-out or interrupted.
  3964      Experimental."
  3982      Experimental."
  3965 
  3983 
  3966     ^ self selectOnAnyReadable:fdArray 
  3984     ^ self selectOnAnyReadable:fdArray 
  3967 		      writable:nil 
  3985                       writable:nil 
  3968 		     exception:nil
  3986                      exception:nil
  3969 		   withTimeOut:millis
  3987                    withTimeOut:millis
  3970 !
  3988 !
  3971 
  3989 
  3972 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
  3990 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
  3973     "wait for any fd in readFdArray (an Array of integers) to become ready for 
  3991     "wait for any fd in readFdArray (an Array of integers) to become ready for 
  3974      reading, writeFdArray to become ready for writing, or exceptFdArray to 
  3992      reading, writeFdArray to become ready for writing, or exceptFdArray to 
  3994 
  4012 
  3995 writeCheck:fd
  4013 writeCheck:fd
  3996     "return true, if filedescriptor can be written without blocking"
  4014     "return true, if filedescriptor can be written without blocking"
  3997 
  4015 
  3998     self supportsSelect ifFalse:[
  4016     self supportsSelect ifFalse:[
  3999 	"/ mhmh - what should we do then ?
  4017         "/ mhmh - what should we do then ?
  4000 	"/ For now, return true as if data was present,
  4018         "/ For now, return true as if data was present,
  4001 	"/ and let the thread fall into the write.
  4019         "/ and let the thread fall into the write.
  4002 	"/ It will then (hopefully) be desceduled there and
  4020         "/ It will then (hopefully) be desceduled there and
  4003 	"/ effectively polling for output.
  4021         "/ effectively polling for output.
  4004 	^ true
  4022         ^ true
  4005     ].
  4023     ].
  4006 
  4024 
  4007     (self selectOnAnyReadable:nil
  4025     (self selectOnAnyReadable:nil
  4008 		     writable:(Array with:fd)
  4026                      writable:(Array with:fd)
  4009 		    exception:nil
  4027                     exception:nil
  4010 		  withTimeOut:0) == fd
  4028                   withTimeOut:0) == fd
  4011 	ifTrue:[^ true].
  4029         ifTrue:[^ true].
  4012     ^ false
  4030     ^ false
  4013 ! !
  4031 ! !
  4014 
  4032 
  4015 !AbstractOperatingSystem class methodsFor:'documentation'!
  4033 !AbstractOperatingSystem class methodsFor:'documentation'!
  4016 
  4034 
  4017 version
  4035 version
  4018     ^ '$Header: /cvs/stx/stx/libbasic/AbstractOperatingSystem.st,v 1.27 1999-10-06 12:10:22 cg Exp $'
  4036     ^ '$Header: /cvs/stx/stx/libbasic/AbstractOperatingSystem.st,v 1.28 1999-10-06 12:59:16 ca Exp $'
  4019 ! !
  4037 ! !
  4020 AbstractOperatingSystem initialize!
  4038 AbstractOperatingSystem initialize!