AbstractOperatingSystem.st
changeset 3576 9287c054ac83
child 3689 f3351f92641e
equal deleted inserted replaced
3575:39723f691a0e 3576:9287c054ac83
       
     1 "
       
     2  COPYRIGHT (c) 1988 by Claus Gittinger
       
     3 	      All Rights Reserved
       
     4 
       
     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
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 
       
    13 Object subclass:#AbstractOperatingSystem
       
    14 	instanceVariableNames:''
       
    15 	classVariableNames:'ConcreteClass LastErrorNumber LocaleInfo OSSignals PipeFailed
       
    16 		ErrorSignal AccessDeniedErrorSignal FileNotFoundErrorSignal
       
    17 		InvalidArgumentsSignal UnsupportedOperationSignal'
       
    18 	poolDictionaries:''
       
    19 	category:'System-Support'
       
    20 !
       
    21 
       
    22 !AbstractOperatingSystem primitiveDefinitions!
       
    23 %{
       
    24 
       
    25 #define UNIX_LIKE       /* assumption: a real operatingSystem */
       
    26 
       
    27 #if defined(MSWINDOWS) || defined(OS2) || defined(MSDOS) || defined(WIN32)
       
    28 # ifndef MSDOS_LIKE
       
    29 #  define MSDOS_LIKE
       
    30 # endif
       
    31 # undef UNIX_LIKE       /* oops - we were too optimistic - no OS */
       
    32 # ifdef i386
       
    33 #  ifndef _X86_
       
    34 #   define _X86_
       
    35 #  endif
       
    36 # endif
       
    37 #endif /* any MS-non-OS */
       
    38 
       
    39 #if defined(transputer)
       
    40 # undef MSDOS_LIKE
       
    41 # undef UNIX_LIKE       /* oops - we were too optimistic - no OS */
       
    42 #endif
       
    43 %}
       
    44 ! !
       
    45 
       
    46 !AbstractOperatingSystem class methodsFor:'documentation'!
       
    47 
       
    48 copyright
       
    49 "
       
    50  COPYRIGHT (c) 1988 by Claus Gittinger
       
    51 	      All Rights Reserved
       
    52 
       
    53  This software is furnished under a license and may be used
       
    54  only in accordance with the terms of that license and with the
       
    55  inclusion of the above copyright notice.   This software may not
       
    56  be provided or otherwise made available to, or used by, any
       
    57  other person.  No title to or ownership of the software is
       
    58  hereby transferred.
       
    59 "
       
    60 !
       
    61 
       
    62 documentation
       
    63 "
       
    64     this class realizes access to most (all ?) required operating system services;
       
    65     some of it is very specific for unix, so do not depend on
       
    66     things available here in your applications 
       
    67     - some may not be found in other OS's or be slightly different ...
       
    68 
       
    69     (On the other hand: I do not want to hide all features
       
    70      from you - in some situations it MAY be interesting to be
       
    71      able to get down to a select or fork system call easily (at least on Unix systems).
       
    72      You decide - portability vs. functionality)
       
    73 
       
    74     [Class variables:]
       
    75 
       
    76 	HostName        <String>        remembered hostname
       
    77 
       
    78 	DomainName      <String>        remembered domainname
       
    79 
       
    80 	LastErrorNumber <Integer>       the last value of errno
       
    81 
       
    82 	OSSignals       <Array>         Array of signals to be raised for corresponding
       
    83 					OperatingSystem signals.
       
    84 
       
    85        PipeFailed      <Boolean>       set if a fork (or popen) has failed;
       
    86                                         ST/X will avoid doing more forks/popens
       
    87                                         if this flag is set, for a slightly
       
    88                                         smoother operation.
       
    89 
       
    90 	SlowFork        <Boolean>       if set, fork and popen are avoided;
       
    91 					(more or less obsolete now)
       
    92 
       
    93 
       
    94 	ErrorSignal     <Signal>        Parentsignal of all OS error signals.
       
    95 					not directly raised.
       
    96 
       
    97 	AccessDeniedErrorSignal
       
    98 
       
    99 	FileNotFoundErrorSignal
       
   100 
       
   101 	UnsupportedOperationSignal
       
   102 
       
   103 	LocaleInfo      <Dictionary>    if non nil, that is taken instead of the operating
       
   104 					systems locale definitions (allows for overwriting
       
   105 					these, or provide a compatible info on systems which do
       
   106 					not support locales)
       
   107 
       
   108 	CurrentDirectory <String>       remembered currentDirectories path
       
   109 
       
   110     [author:]
       
   111 	Claus Gittinger
       
   112 
       
   113     [see also:]
       
   114 	OSProcessStatus
       
   115 	Filename Date Time
       
   116 	ExternalStream FileStream PipeStream Socket
       
   117 "
       
   118 !
       
   119 
       
   120 examples
       
   121 "
       
   122   various queries
       
   123 								[exBegin]
       
   124     Transcript 
       
   125 	showCR:'hello ' , (OperatingSystem getLoginName)
       
   126 								[exEnd]
       
   127 
       
   128 								[exBegin]
       
   129     OperatingSystem isUNIXlike ifTrue:[
       
   130 	Transcript showCR:'this is some UNIX-like OS'
       
   131     ] ifFalse:[
       
   132 	Transcript showCR:'this OS is not UNIX-like'
       
   133     ]
       
   134 								[exEnd]
       
   135 
       
   136 								[exBegin]
       
   137     Transcript 
       
   138 	showCR:'this machine is called ' , OperatingSystem getHostName
       
   139 								[exEnd]
       
   140 
       
   141 								[exBegin]
       
   142     Transcript 
       
   143 	showCR:('this machine is in the '
       
   144 	       , OperatingSystem getDomainName
       
   145 	       , ' domain')
       
   146 								[exEnd]
       
   147 
       
   148 								[exBegin]
       
   149     Transcript 
       
   150 	showCR:('this machine''s CPU is a '
       
   151 	       , OperatingSystem getCPUType
       
   152 	       )
       
   153 								[exEnd]
       
   154 
       
   155 								[exBegin]
       
   156     Transcript showCR:'executing ls command ...'.
       
   157     OperatingSystem executeCommand:'ls'.
       
   158     Transcript showCR:'... done.'.
       
   159 								[exEnd]
       
   160 
       
   161   locking a file 
       
   162   (should be executed on two running smalltalks - not in two threads):
       
   163 								[exBegin]
       
   164     |f|
       
   165 
       
   166     f := 'testFile' asFilename readWriteStream.
       
   167 
       
   168     10 timesRepeat:[
       
   169 	'about to lock ...' printCR.
       
   170 	[
       
   171 	  OperatingSystem 
       
   172 	    lockFD:(f fileDescriptor)
       
   173 	    shared:false
       
   174 	    blocking:false
       
   175 	] whileFalse:[
       
   176 	    'process ' print. OperatingSystem getProcessId print. ' is waiting' printCR.
       
   177 	    Delay waitForSeconds:1
       
   178 	].
       
   179 	'LOCKED ...' printCR.
       
   180 	Delay waitForSeconds:10.
       
   181 	'unlock ...' printCR.
       
   182 	(OperatingSystem 
       
   183 	    unlockFD:(f fileDescriptor)) printCR.
       
   184 	Delay waitForSeconds:3.
       
   185     ]
       
   186 								[exBegin]
       
   187 "
       
   188 ! !
       
   189 
       
   190 !AbstractOperatingSystem class methodsFor:'initialization'!
       
   191 
       
   192 initialize
       
   193     "initialize the class"
       
   194 
       
   195     self initializeConcreteClass.
       
   196 
       
   197     ErrorSignal isNil ifTrue:[
       
   198         ErrorSignal := Object errorSignal newSignalMayProceed:true.
       
   199         ErrorSignal nameClass:self message:#errorSignal.
       
   200         ErrorSignal notifierString:'OS error encountered'.
       
   201 
       
   202         AccessDeniedErrorSignal := ErrorSignal newSignalMayProceed:true.
       
   203         AccessDeniedErrorSignal nameClass:self message:#accessDeniedError.
       
   204         AccessDeniedErrorSignal notifierString:'OS access denied'.
       
   205 
       
   206         FileNotFoundErrorSignal := ErrorSignal newSignalMayProceed:true.
       
   207         FileNotFoundErrorSignal nameClass:self message:#fileNotFoundErrorSignal.
       
   208         FileNotFoundErrorSignal notifierString:'OS file not found'.
       
   209 
       
   210         InvalidArgumentsSignal := ErrorSignal newSignalMayProceed:true.
       
   211         InvalidArgumentsSignal nameClass:self message:#invalidArgumentsSignal.
       
   212         InvalidArgumentsSignal notifierString:'bad arg to OS call'.
       
   213 
       
   214         UnsupportedOperationSignal := ErrorSignal newSignalMayProceed:true.
       
   215         UnsupportedOperationSignal nameClass:self message:#unsupportedOperationSignal.
       
   216         UnsupportedOperationSignal notifierString:'operation not supported by OS'.
       
   217     ]
       
   218 !
       
   219 
       
   220 initializeConcreteClass
       
   221     |osType cls|
       
   222 
       
   223     osType := self getSystemType.
       
   224     osType = 'win32' ifTrue:[
       
   225 	cls := Win32OperatingSystem
       
   226     ] ifFalse:[
       
   227         osType = 'os2' ifTrue:[
       
   228 	    cls := OS2OperatingSystem
       
   229 	] ifFalse:[
       
   230             osType = 'macos' ifTrue:[
       
   231 		cls := MacOperatingSystem
       
   232 	    ] ifFalse:[
       
   233                 ((osType = 'VMS') or:[osType = 'openVMS']) ifTrue:[
       
   234 		    cls := OpenVMSOperatingSystem
       
   235 		] ifFalse:[
       
   236 		    cls := UnixOperatingSystem
       
   237 	        ]
       
   238 	    ]
       
   239 	]
       
   240     ].
       
   241     OperatingSystem := ConcreteClass := cls.
       
   242 ! !
       
   243 
       
   244 !AbstractOperatingSystem class methodsFor:'OS signal constants'!
       
   245 
       
   246 sigABRT
       
   247     "return the signal number for SIGABRT - 0 if not supported by OS
       
   248      (the numeric value is not the same across unix-systems)"
       
   249 
       
   250     ^ 0
       
   251 !
       
   252 
       
   253 sigALRM
       
   254     "return the signal number for SIGALRM - 0 if not supported
       
   255      (the numeric value is not the same across unix-systems)"
       
   256 
       
   257     ^ 0
       
   258 !
       
   259 
       
   260 sigBREAK
       
   261     "return the signal number for SIGBREAK - 0 if not supported.
       
   262      This is an MSDOS specific signal"
       
   263 
       
   264     ^ 0
       
   265 !
       
   266 
       
   267 sigBUS
       
   268     "return the signal number for SIGBUS - 0 if not supported
       
   269      (the numeric value is not the same across unix-systems)"
       
   270 
       
   271     ^ 0
       
   272 !
       
   273 
       
   274 sigCHLD
       
   275     "return the signal number for SIGCHLD - 0 if not supported
       
   276      (the numeric value is not the same across unix-systems)"
       
   277 
       
   278     ^ 0
       
   279 !
       
   280 
       
   281 sigCONT
       
   282     "return the signal number for SIGCONT - 0 if not supported
       
   283      (the numeric value is not the same across unix-systems)"
       
   284 
       
   285     ^ 0
       
   286 !
       
   287 
       
   288 sigDANGER
       
   289     "return the signal number for SIGDANGER - 0 if not supported
       
   290      (seems to be an AIX special)"
       
   291 
       
   292     ^ 0
       
   293 !
       
   294 
       
   295 sigEMT
       
   296     "return the signal number for SIGEMT - 0 if not supported by OS
       
   297      (the numeric value is not the same across unix-systems)"
       
   298 
       
   299     ^ 0
       
   300 !
       
   301 
       
   302 sigFP
       
   303     "return the signal number for SIGFP - 0 if not supported by OS
       
   304      (the numeric value is not the same across unix-systems)"
       
   305 
       
   306     ^ 0
       
   307 !
       
   308 
       
   309 sigGRANT
       
   310     "return the signal number for SIGGRANT - 0 if not supported
       
   311      (seems to be an AIX special)"
       
   312 
       
   313     ^ 0
       
   314 !
       
   315 
       
   316 sigHUP
       
   317     "return the signal number for SIGHUP
       
   318      (the numeric value is not the same across unix-systems)"
       
   319 
       
   320     ^ 0
       
   321 !
       
   322 
       
   323 sigILL
       
   324     "return the signal number for SIGILL - 0 if not supported by OS
       
   325      (the numeric value is not the same across unix-systems)"
       
   326 
       
   327     ^ 0
       
   328 !
       
   329 
       
   330 sigINT
       
   331     "return the signal number for SIGINT
       
   332      (the numeric value is not the same across unix-systems)"
       
   333 
       
   334     ^ 0
       
   335 !
       
   336 
       
   337 sigIO
       
   338     "return the signal number for SIGIO - 0 if not supported
       
   339      (the numeric value is not the same across unix-systems)"
       
   340 
       
   341     ^ 0
       
   342 !
       
   343 
       
   344 sigIOT
       
   345     "return the signal number for SIGIOT - 0 if not supported by OS
       
   346      (the numeric value is not the same across unix-systems)"
       
   347 
       
   348     ^ 0
       
   349 !
       
   350 
       
   351 sigKILL
       
   352     "return the signal number for SIGKILL
       
   353      (the numeric value is not the same across unix-systems)"
       
   354 
       
   355     ^ 0
       
   356 !
       
   357 
       
   358 sigLOST
       
   359     "return the signal number for SIGLOST - 0 if not supported
       
   360      (the numeric value is not the same across unix-systems)"
       
   361 
       
   362     ^ 0
       
   363 !
       
   364 
       
   365 sigMIGRATE
       
   366     "return the signal number for SIGMIGRATE - 0 if not supported
       
   367      (seems to be an AIX special)"
       
   368 
       
   369     ^ 0
       
   370 !
       
   371 
       
   372 sigMSG
       
   373     "return the signal number for SIGMSG - 0 if not supported
       
   374      (seems to be an AIX special)"
       
   375 
       
   376     ^ 0
       
   377 !
       
   378 
       
   379 sigPIPE
       
   380     "return the signal number for SIGPIPE - 0 if not supported
       
   381      (the numeric value is not the same across unix-systems)"
       
   382 
       
   383     ^ 0
       
   384 !
       
   385 
       
   386 sigPOLL
       
   387     "return the signal number for SIGPOLL - 0 if not supported
       
   388      (the numeric value is not the same across unix-systems)"
       
   389 
       
   390     ^ 0
       
   391 !
       
   392 
       
   393 sigPRE
       
   394     "return the signal number for SIGPRE - 0 if not supported
       
   395      (seems to be an AIX special)"
       
   396 
       
   397     ^ 0
       
   398 !
       
   399 
       
   400 sigPROF
       
   401     "return the signal number for SIGPROF - 0 if not supported
       
   402      (the numeric value is not the same across unix-systems)"
       
   403 
       
   404     ^ 0
       
   405 !
       
   406 
       
   407 sigPWR
       
   408     "return the signal number for SIGPWR - 0 if not supported
       
   409      (not available on all systems)"
       
   410 
       
   411     ^ 0
       
   412 !
       
   413 
       
   414 sigQUIT
       
   415     "return the signal number for SIGQUIT
       
   416      (the numeric value is not the same across unix-systems)"
       
   417 
       
   418     ^ 0
       
   419 !
       
   420 
       
   421 sigRETRACT
       
   422     "return the signal number for SIGRETRACT - 0 if not supported
       
   423      (seems to be an AIX special)"
       
   424 
       
   425     ^ 0
       
   426 !
       
   427 
       
   428 sigSAK
       
   429     "return the signal number for SIGSAK - 0 if not supported
       
   430      (seems to be an AIX special)"
       
   431 
       
   432     ^ 0
       
   433 !
       
   434 
       
   435 sigSEGV
       
   436     "return the signal number for SIGSEGV - 0 if not supported
       
   437      (the numeric value is not the same across unix-systems)"
       
   438 
       
   439     ^ 0
       
   440 !
       
   441 
       
   442 sigSOUND
       
   443     "return the signal number for SIGSOUND - 0 if not supported
       
   444      (seems to be an AIX special)"
       
   445 
       
   446     ^ 0
       
   447 !
       
   448 
       
   449 sigSTOP
       
   450     "return the signal number for SIGSTOP - 0 if not supported
       
   451      (the numeric value is not the same across unix-systems)"
       
   452 
       
   453     ^ 0
       
   454 !
       
   455 
       
   456 sigSYS
       
   457     "return the signal number for SIGSYS - 0 if not supported
       
   458      (the numeric value is not the same across unix-systems)"
       
   459 
       
   460     ^ 0
       
   461 !
       
   462 
       
   463 sigTERM
       
   464     "return the signal number for SIGTERM - 0 if not supported
       
   465      (the numeric value is not the same across unix-systems)"
       
   466 
       
   467     ^ 0
       
   468 !
       
   469 
       
   470 sigTRAP
       
   471     "return the signal number for SIGTRAP - 0 if not supported by OS
       
   472      (the numeric value is not the same across unix-systems)"
       
   473 
       
   474     ^ 0
       
   475 !
       
   476 
       
   477 sigTSTP
       
   478     "return the signal number for SIGTSTP - 0 if not supported
       
   479      (the numeric value is not the same across unix-systems)"
       
   480 
       
   481     ^ 0
       
   482 !
       
   483 
       
   484 sigTTIN
       
   485     "return the signal number for SIGTTIN - 0 if not supported
       
   486      (the numeric value is not the same across unix-systems)"
       
   487 
       
   488     ^ 0
       
   489 !
       
   490 
       
   491 sigTTOU
       
   492     "return the signal number for SIGTTOU - 0 if not supported
       
   493      (the numeric value is not the same across unix-systems)"
       
   494 
       
   495     ^ 0
       
   496 !
       
   497 
       
   498 sigURG
       
   499     "return the signal number for SIGURG - 0 if not supported
       
   500      (the numeric value is not the same across unix-systems)"
       
   501 
       
   502     ^ 0
       
   503 !
       
   504 
       
   505 sigUSR1
       
   506     "return the signal number for SIGUSR1 - 0 if not supported
       
   507      (the numeric value is not the same across unix-systems)"
       
   508 
       
   509     ^ 0
       
   510 !
       
   511 
       
   512 sigUSR2
       
   513     "return the signal number for SIGUSR2 - 0 if not supported
       
   514      (the numeric value is not the same across unix-systems)"
       
   515 
       
   516     ^ 0
       
   517 !
       
   518 
       
   519 sigVTALRM
       
   520     "return the signal number for SIGVTALRM - 0 if not supported
       
   521      (the numeric value is not the same across unix-systems)"
       
   522 
       
   523     ^ 0
       
   524 !
       
   525 
       
   526 sigWINCH
       
   527     "return the signal number for SIGWINCH - 0 if not supported
       
   528      (the numeric value is not the same across unix-systems)"
       
   529 
       
   530     ^ 0
       
   531 !
       
   532 
       
   533 sigXCPU
       
   534     "return the signal number for SIGXCPU - 0 if not supported
       
   535      (the numeric value is not the same across unix-systems)"
       
   536 
       
   537     ^ 0
       
   538 !
       
   539 
       
   540 sigXFSZ
       
   541     "return the signal number for SIGXFSZ - 0 if not supported
       
   542      (the numeric value is not the same across unix-systems)"
       
   543 
       
   544     ^ 0
       
   545 ! !
       
   546 
       
   547 !AbstractOperatingSystem class methodsFor:'Signal constants'!
       
   548 
       
   549 accessDeniedErrorSignal
       
   550     "return the signal raised when a (file-) access is denied."
       
   551 
       
   552     ^ AccessDeniedErrorSignal
       
   553 !
       
   554 
       
   555 errorSignal
       
   556     "return the parent signal of all OS signals."
       
   557 
       
   558     ^ ErrorSignal
       
   559 
       
   560     "Modified: 22.4.1996 / 13:11:31 / cg"
       
   561 !
       
   562 
       
   563 fileNotFoundErrorSignal
       
   564     "return the signal raised when a file was not found."
       
   565 
       
   566     ^ FileNotFoundErrorSignal
       
   567 !
       
   568 
       
   569 invalidArgumentsSignal
       
   570     "return the signal which is raised for invalid arguments.
       
   571      Currently, this is never raised."
       
   572 
       
   573     ^ InvalidArgumentsSignal
       
   574 
       
   575     "Created: 13.9.1997 / 10:46:47 / cg"
       
   576     "Modified: 13.9.1997 / 10:47:03 / cg"
       
   577 !
       
   578 
       
   579 unsupportedOperationSignal
       
   580     "return the signal which is raised when an operation
       
   581      is attempted, which is not supported by the OS.
       
   582      (For example, creating a link on VMS or MSDOS)"
       
   583 
       
   584     ^ UnsupportedOperationSignal
       
   585 ! !
       
   586 
       
   587 !AbstractOperatingSystem class methodsFor:'error messages'!
       
   588 
       
   589 clearLastErrorNumber
       
   590     "return the last errors number.
       
   591      See also: #lastErrorSymbol and #lastErrorString.
       
   592      Notice: having a single error number is a bad idea in a multithreaded
       
   593 	     environment - this interface will change."
       
   594 
       
   595     LastErrorNumber := nil.
       
   596 
       
   597      "
       
   598       AbstractOperatingSystem clearLastErrorNumber
       
   599      "
       
   600 
       
   601     "Created: 12.4.1996 / 09:28:58 / stefan"
       
   602     "Modified: 12.4.1996 / 09:38:51 / stefan"
       
   603 !
       
   604 
       
   605 currentErrorNumber
       
   606     "returns the OS's last error nr (i.e. the value of errno).
       
   607      Notice, that the value of this flag is only valid immediately
       
   608      after the error occurred - it gets updated with every other
       
   609      request to the OS.
       
   610      Use lastErrorNumber - currentErrorNumber is invalidated by
       
   611      many, many internal calls."
       
   612 
       
   613     ^ self lastErrorNumber
       
   614 
       
   615      "
       
   616       OperatingSystem currentErrorNumber
       
   617      "
       
   618 !
       
   619 
       
   620 errorNumberFor:aSymbol
       
   621     "given a symbolic error, return the numeric;
       
   622      (i.e. errorNumberFor:#EBADF returns EBADF's value).
       
   623      Use this, since error numbers are really not standard across unix systems."
       
   624 
       
   625     ^ -1
       
   626 !
       
   627 
       
   628 errorSymbolAndTextForNumber:errNr
       
   629     "return an array consisting of symbol &  message string from a unix errorNumber 
       
   630      (as returned by a system call). 
       
   631      The returned message is in english (as found in /usr/include/errno.h)
       
   632      and should be replaced by a resource lookup before being presented to the user."
       
   633 
       
   634     ^ Array 
       
   635 	with:#'ERROR_OTHER' 
       
   636 	with:('ErrorNr: ' , errNr printString)
       
   637 
       
   638     "
       
   639      OperatingSystem errorSymbolAndTextForNumber:4
       
   640     "
       
   641 !
       
   642 
       
   643 errorSymbolForNumber:errNr
       
   644     "return a symbol for a unix errorNumber
       
   645      (as returned by a system call)."
       
   646 
       
   647     ^ (self errorSymbolAndTextForNumber:errNr) at:1
       
   648 
       
   649     "
       
   650      OperatingSystem errorSymbolForNumber:4
       
   651      OperatingSystem errorSymbolForNumber:2
       
   652     "
       
   653 
       
   654     "Modified: 12.4.1996 / 09:16:29 / stefan"
       
   655     "Modified: 13.9.1996 / 16:23:35 / cg"
       
   656 !
       
   657 
       
   658 errorTextForNumber:errNr
       
   659     "return a message string from a unix errorNumber 
       
   660      (as returned by a system call). 
       
   661      The returned message is in english (as found in /usr/include/errno.h)
       
   662      and should be replaced by a resource lookup before being presented to the user."
       
   663 
       
   664     ^ (self errorSymbolAndTextForNumber:errNr) at:2
       
   665 
       
   666     "
       
   667      OperatingSystem errorTextForNumber:4
       
   668     "
       
   669 !
       
   670 
       
   671 lastErrorNumber
       
   672     "return the last errors number.
       
   673      See also: #lastErrorSymbol and #lastErrorString.
       
   674      Notice: having a single error number is a bad idea in a multithreaded
       
   675 	     environment - this interface will change."
       
   676 
       
   677     ^ LastErrorNumber
       
   678 
       
   679      "
       
   680       OperatingSystem lastErrorNumber
       
   681      "
       
   682 !
       
   683 
       
   684 lastErrorString
       
   685     "return a message string describing the last error.
       
   686      See also: #lastErrorNumber and #lastErrorSymbol.
       
   687      Notice: having a single error number is a bad idea in a multithreaded
       
   688 	     environment - this interface will change."
       
   689 
       
   690     LastErrorNumber isNil ifTrue:[^ nil].
       
   691     ^ self errorTextForNumber:LastErrorNumber
       
   692 
       
   693     "
       
   694      OperatingSystem lastErrorString
       
   695     "
       
   696 !
       
   697 
       
   698 lastErrorSymbol
       
   699     "return a symbol (such as #EBADF or #EACCESS) describing the last error.
       
   700      See also: #lastErrorNumber and #lastErrorString.
       
   701      Notice: having a single error number is a bad idea in a multithreaded
       
   702 	     environment - this interface will change."
       
   703 
       
   704     LastErrorNumber isNil ifTrue:[^ nil].
       
   705     ^ self errorSymbolForNumber:LastErrorNumber
       
   706 
       
   707     "
       
   708      OperatingSystem lastErrorSymbol
       
   709     "
       
   710 ! !
       
   711 
       
   712 !AbstractOperatingSystem class methodsFor:'executing OS commands'!
       
   713 
       
   714 canExecuteCommand:aCommandString
       
   715     "return true, if the OS can execute aCommand.
       
   716      For now, this only works with UNIX."
       
   717 
       
   718     |cmd|
       
   719 
       
   720     cmd := aCommandString asCollectionOfWords first.
       
   721     ^ (self pathOfCommand:cmd) notNil
       
   722 
       
   723     "
       
   724      OperatingSystem canExecuteCommand:'fooBar'  
       
   725      OperatingSystem canExecuteCommand:'ls'  
       
   726      OperatingSystem canExecuteCommand:'cvs'  
       
   727     "
       
   728 
       
   729     "Created: 4.11.1995 / 19:13:54 / cg"
       
   730 !
       
   731 
       
   732 commandAndArgsForOSCommand:aCommandString
       
   733     "get a shell and shell arguments for command execution"
       
   734 
       
   735     self subclassResponsibility
       
   736 !
       
   737 
       
   738 exec:aCommandPath withArguments:argArray
       
   739     "execute the unix command specified by the argument, aCommandPath, with
       
   740      arguments in argArray (no arguments, if nil).
       
   741      If successful, this method does NOT return and smalltalk is gone.
       
   742      If not successful, it does return. 
       
   743      Can be used on UNIX with fork or on other systems to chain to another program."
       
   744 
       
   745     self exec:aCommandPath withArguments:argArray fork:false
       
   746 !
       
   747 
       
   748 exec:aCommandPath withArguments:argArray fork:doFork
       
   749     "execute an OS command without I/O redirection.
       
   750      The command reads its input and writes its output
       
   751      from/to whatever terminal device ST/X was started
       
   752      (typically, the xterm window)"
       
   753 
       
   754     ^ self exec:aCommandPath 
       
   755 	   withArguments:argArray 
       
   756 	   fileDescriptors:nil
       
   757 	   closeDescriptors:nil 
       
   758 	   fork:doFork 
       
   759 	   newPgrp:false
       
   760 
       
   761     "
       
   762      |id|
       
   763 
       
   764      id := OperatingSystem fork.
       
   765      id == 0 ifTrue:[
       
   766 	'I am the child'.
       
   767 	OperatingSystem 
       
   768 	    exec:'/bin/ls' 
       
   769 	    withArguments:#('ls' '/tmp')
       
   770 	    fork:false.
       
   771 	'not reached'.
       
   772      ]
       
   773     "
       
   774 
       
   775     "
       
   776      |id|
       
   777 
       
   778      id := OperatingSystem fork.
       
   779      id == 0 ifTrue:[
       
   780 	'I am the child'.
       
   781 	OperatingSystem 
       
   782 	    exec:'/bin/sh' 
       
   783 	    withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
       
   784 	    fork:false.
       
   785 	'not reached'.
       
   786      ].
       
   787      id printNL.
       
   788      (Delay forSeconds:3.5) wait.
       
   789      'killing ...' printNL.
       
   790      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
       
   791      OperatingSystem sendSignal:(OperatingSystem sigKILL) to:id
       
   792     "
       
   793 
       
   794     "Modified: 15.7.1997 / 15:54:32 / stefan"
       
   795 !
       
   796 
       
   797 exec:aCommandPath withArguments:argArray fork:doFork inDirectory:aDirectory
       
   798     "execute an OS command without I/O redirection.
       
   799      The command reads its input and writes its output
       
   800      from/to whatever terminal device ST/X was started
       
   801      (typically, the xterm window)"
       
   802 
       
   803     ^ self exec:aCommandPath
       
   804 	   withArguments:argArray
       
   805 	   fileDescriptors:nil
       
   806 	   closeDescriptors:nil
       
   807 	   fork:doFork 
       
   808 	   newPgrp:false
       
   809 	   inDirectory:aDirectory
       
   810     "
       
   811      |id|
       
   812 
       
   813      id := OperatingSystem fork.
       
   814      id == 0 ifTrue:[
       
   815 	'I am the child'.
       
   816 	OperatingSystem 
       
   817 	    exec:'/bin/ls' 
       
   818 	    withArguments:#('ls' '/tmp')
       
   819 	    fork:false.
       
   820 	'not reached'.
       
   821      ]
       
   822     "
       
   823 
       
   824     "
       
   825      |id|
       
   826 
       
   827      id := OperatingSystem fork.
       
   828      id == 0 ifTrue:[
       
   829 	'I am the child'.
       
   830 	OperatingSystem 
       
   831 	    exec:'/bin/sh' 
       
   832 	    withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
       
   833 	    fork:false.
       
   834 	'not reached'.
       
   835      ].
       
   836      id printNL.
       
   837      (Delay forSeconds:3.5) wait.
       
   838      'killing ...' printNL.
       
   839      OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
       
   840      OperatingSystem sendSignal:(OperatingSystem sigKILL) to:id
       
   841     "
       
   842 
       
   843     "Created: 28.1.1998 / 14:14:03 / md"
       
   844     "Modified: 28.1.1998 / 14:14:45 / md"
       
   845 !
       
   846 
       
   847 executableFileExtensions
       
   848     "return a collection of extensions for executable program files.
       
   849      Only req'd for msdos & vms like systems ..."
       
   850 
       
   851     ^ #('')
       
   852 
       
   853     "Created: 2.5.1997 / 11:42:29 / cg"
       
   854 !
       
   855 
       
   856 executeCommand:aCommandString
       
   857     "execute the unix command specified by the argument, aCommandString.
       
   858      The commandString is passed to a shell for execution - see the description of
       
   859      'sh -c' in your UNIX manual.
       
   860      Return true if successful, false otherwise."
       
   861 
       
   862      ^ self
       
   863 	executeCommand:aCommandString
       
   864 	onError:[:status| false]
       
   865 
       
   866     "unix:
       
   867 
       
   868      OperatingSystem executeCommand:'sleep 30'. 
       
   869      OperatingSystem executeCommand:'pwd'. 
       
   870      OperatingSystem executeCommand:'ls -l'. 
       
   871      OperatingSystem executeCommand:'invalidCommand'. 
       
   872      OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'. 
       
   873     "
       
   874 
       
   875     "msdos:
       
   876 
       
   877      OperatingSystem executeCommand:'dir' 
       
   878      OperatingSystem executeCommand:'dir /w'
       
   879     "
       
   880 
       
   881     "vms:
       
   882 
       
   883      OperatingSystem executeCommand:'dir'
       
   884      OperatingSystem executeCommand:'purge'
       
   885      OperatingSystem executeCommand:'cc foo.c'
       
   886     "
       
   887 
       
   888     "Modified: 7.1.1997 / 19:29:55 / stefan"
       
   889     "Modified: 2.5.1997 / 12:27:39 / cg"
       
   890 !
       
   891 
       
   892 executeCommand:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream onError:aBlock
       
   893     "execute the unix command specified by the argument, aCommandString.
       
   894      The commandString is passed to a shell for execution - see the description of
       
   895      'sh -c' in your UNIX manual.
       
   896      Return true if successful.
       
   897      If not successfull, aBlock is called with an OsProcessStatus
       
   898      (containing the exit status) as argument."
       
   899 
       
   900     |pid exitStatus sema|
       
   901 
       
   902     sema := Semaphore new name:'OS command wait'.
       
   903 
       
   904     pid := Processor 
       
   905                 monitor:[
       
   906                     self 
       
   907                         startProcess:aCommandString
       
   908                         inputFrom:anExternalInStream 
       
   909                         outputTo:anExternalOutStream 
       
   910                         errorTo:anExternalErrStream.
       
   911                 ] 
       
   912                 action:[:status |
       
   913                     status stillAlive ifFalse:[
       
   914                         exitStatus := status.
       
   915                         self closePid:pid.
       
   916                         sema signal
       
   917                     ].
       
   918                 ].
       
   919     pid notNil ifTrue:[
       
   920         sema wait.
       
   921     ] ifFalse:[
       
   922         exitStatus := self osProcessStatusClass processCreationFailure.
       
   923     ].
       
   924 
       
   925     exitStatus success ifFalse:[
       
   926         ^ aBlock value:exitStatus
       
   927     ].
       
   928     ^ true.
       
   929 
       
   930     "Modified: / 25.3.1997 / 11:02:02 / stefan"
       
   931     "Modified: / 28.1.1998 / 14:46:36 / md"
       
   932     "Created: / 5.6.1998 / 19:01:57 / cg"
       
   933     "Modified: / 12.6.1998 / 16:30:08 / cg"
       
   934 !
       
   935 
       
   936 executeCommand:aCommandString onError:aBlock
       
   937     "execute the unix command specified by the argument, aCommandString.
       
   938      The commandString is passed to a shell for execution - see the description of
       
   939      'sh -c' in your UNIX manual.
       
   940      Return true if successful.
       
   941      If not successfull, aBlock is called with an OsProcessStatus
       
   942      (containing the exit status) as argument."
       
   943 
       
   944     |pid exitStatus sema|
       
   945 
       
   946     sema := Semaphore new name:'OS command wait'.
       
   947 
       
   948     pid := Processor 
       
   949                 monitor:[self startProcess:aCommandString] 
       
   950                 action:[:status |
       
   951                         status stillAlive ifFalse:[
       
   952                             exitStatus := status.
       
   953                             self closePid:pid.
       
   954                             sema signal
       
   955                         ].
       
   956                 ].
       
   957     pid notNil ifTrue:[
       
   958         sema wait.
       
   959     ] ifFalse:[
       
   960         exitStatus := self osProcessStatusClass processCreationFailure.
       
   961     ].
       
   962 
       
   963     exitStatus success ifFalse:[
       
   964         ^ aBlock value:exitStatus
       
   965     ].
       
   966     ^ true.
       
   967 
       
   968 
       
   969     "
       
   970      UnixOperatingSystem executeCommand:'sleep 30' onError:[]. 
       
   971      UnixOperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. 
       
   972      UnixOperatingSystem executeCommand:'ls -l' onError:[]. 
       
   973      UnixOperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. 
       
   974      UnixOperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. 
       
   975     "
       
   976 
       
   977     "Modified: / 25.3.1997 / 11:06:43 / stefan"
       
   978     "Modified: / 28.1.1998 / 14:46:56 / md"
       
   979     "Created: / 5.6.1998 / 19:02:09 / cg"
       
   980     "Modified: / 12.6.1998 / 16:30:12 / cg"
       
   981 !
       
   982 
       
   983 executeCommand:aCommandString onError:aBlock inDirectory:aDirectory
       
   984     "execute the unix command specified by the argument, aCommandString.
       
   985      The commandString is passed to a shell for execution - see the description of
       
   986      'sh -c' in your UNIX manual.
       
   987      Return true if successful.
       
   988      If not successfull, aBlock is called with an OsProcessStatus
       
   989      (containing the exit status) as argument."
       
   990 
       
   991     |pid exitStatus sema|
       
   992 
       
   993     sema := Semaphore new name:'OS command wait'.
       
   994 
       
   995     pid := Processor
       
   996                 monitor:[self startProcess:aCommandString inDirectory:aDirectory]
       
   997                 action:[:status |
       
   998                         status stillAlive ifFalse:[
       
   999                             exitStatus := status.
       
  1000                             self closePid:pid.
       
  1001                             sema signal
       
  1002                         ].
       
  1003                 ].
       
  1004     pid notNil ifTrue:[
       
  1005         sema wait.
       
  1006     ] ifFalse:[
       
  1007         exitStatus := self osProcessStatusClass processCreationFailure.
       
  1008     ].
       
  1009 
       
  1010     exitStatus success ifFalse:[
       
  1011         ^ aBlock value:exitStatus
       
  1012     ].
       
  1013     ^ true.
       
  1014 
       
  1015 
       
  1016     "
       
  1017      UnixOperatingSystem executeCommand:'sleep 30' onError:[]. 
       
  1018      UnixOperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. 
       
  1019      UnixOperatingSystem executeCommand:'ls -l' onError:[]. 
       
  1020      UnixOperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. 
       
  1021      UnixOperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. 
       
  1022     "
       
  1023 
       
  1024     "Created: / 5.6.1998 / 19:02:22 / cg"
       
  1025     "Modified: / 12.6.1998 / 16:30:14 / cg"
       
  1026 !
       
  1027 
       
  1028 getCommandOutputFrom:aCommand
       
  1029     "execute a simple command (such as hostname) and
       
  1030      return the commands output as a string"
       
  1031 
       
  1032     |result|
       
  1033 
       
  1034     PipeFailed ifFalse:[
       
  1035         PipeStream openErrorSignal handle:[:ex |
       
  1036 	    PipeFailed := true.
       
  1037 	    'OperatingSystem [warning]: cannot fork/popen' errorPrintCR.
       
  1038 	    ex return.
       
  1039         ] do:[
       
  1040 	    |p|
       
  1041 
       
  1042 	    p := PipeStream readingFrom:aCommand.
       
  1043 	    p notNil ifTrue:[
       
  1044 	        result := p nextLine.
       
  1045 	        p close
       
  1046 	    ].
       
  1047         ].
       
  1048     ].
       
  1049     ^ result
       
  1050 
       
  1051     "Modified: 10.1.1997 / 18:00:07 / cg"
       
  1052 !
       
  1053 
       
  1054 getVMSSymbol:aSymbolString
       
  1055     "get a symbols value, or nil if there is none"
       
  1056 
       
  1057     ^ nil
       
  1058 
       
  1059     "Created: / 5.6.1998 / 19:02:50 / cg"
       
  1060     "Modified: / 5.6.1998 / 19:03:15 / cg"
       
  1061 !
       
  1062 
       
  1063 nameOfSTXExecutable
       
  1064     "return the name of the running ST/X executable program.
       
  1065      Usually, 'stx' is returned - but may be different for
       
  1066      standAlone apps."
       
  1067 
       
  1068 %{
       
  1069     extern char *__stxExecutableName__();
       
  1070 
       
  1071     RETURN (__MKSTRING(__stxExecutableName__()));
       
  1072 %}
       
  1073     "
       
  1074      OperatingSystem nameOfSTXExecutable
       
  1075     "
       
  1076 !
       
  1077 
       
  1078 pathOfCommand:aCommand
       
  1079     "find where aCommand's executable file is;
       
  1080      return its full pathName if there is such a command, otherwise
       
  1081      return nil."
       
  1082 
       
  1083     ^ self subclassResponsibility
       
  1084 !
       
  1085 
       
  1086 pathOfSTXExecutable
       
  1087     "return the full path of the running ST/X executable program.
       
  1088      Usually, '/../../stx' is returned - but may be different for
       
  1089      standAlone apps."
       
  1090 
       
  1091     ^ self pathOfCommand:(self nameOfSTXExecutable)
       
  1092 
       
  1093     "
       
  1094      OperatingSystem pathOfSTXExecutable
       
  1095     "
       
  1096 !
       
  1097 
       
  1098 primExec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp inPath:dirName
       
  1099     "Internal lowLevel entry for combined fork & exec"
       
  1100 
       
  1101     self subclassResponsibility
       
  1102 !
       
  1103 
       
  1104 startProcess:aCommandString
       
  1105     "start executing the OS command as specified by the argument, aCommandString
       
  1106      as a separate process; do not wait for the command to finish.
       
  1107      The commandString is passed to a shell for execution - see the description of
       
  1108      'sh -c' in your UNIX manual.
       
  1109      Return the processId if successful, nil otherwise.
       
  1110      Use #waitForProcess: for synchronization and exec status return,
       
  1111      or #killProcess: to stop it."
       
  1112 
       
  1113     |shellAndArgs|
       
  1114 
       
  1115     shellAndArgs := self commandAndArgsForOSCommand:aCommandString.
       
  1116     ^ self
       
  1117 	exec:(shellAndArgs at:1)
       
  1118 	withArguments:(shellAndArgs at:2)
       
  1119 	fork:true.
       
  1120 
       
  1121     "
       
  1122      |pid|
       
  1123 
       
  1124      pid := OperatingSystem startProcess:'sleep 2; echo 1; sleep 2; echo 2'.
       
  1125      (Delay forSeconds:3) wait.
       
  1126      OperatingSystem killProcess:pid.
       
  1127     "
       
  1128 
       
  1129     "Modified: 21.3.1997 / 10:04:35 / dq"
       
  1130     "Modified: 2.5.1997 / 11:55:44 / cg"
       
  1131 !
       
  1132 
       
  1133 startProcess:aCommandString inDirectory:aDirectory
       
  1134     "start executing the OS command as specified by the argument, aCommandString
       
  1135      as a separate process; do not wait for the command to finish.
       
  1136      The commandString is passed to a shell for execution - see the description of
       
  1137      'sh -c' in your UNIX manual.
       
  1138      Return the processId if successful, nil otherwise.
       
  1139      Use #waitForProcess: for synchronization and exec status return,
       
  1140      or #killProcess: to stop it."
       
  1141 
       
  1142     |shellAndArgs|
       
  1143 
       
  1144     shellAndArgs := self commandAndArgsForOSCommand:aCommandString.
       
  1145     ^ self
       
  1146 	exec:(shellAndArgs at:1)
       
  1147 	withArguments:(shellAndArgs at:2)
       
  1148 	fork:true
       
  1149 	inDirectory:aDirectory.
       
  1150     "
       
  1151      |pid|
       
  1152 
       
  1153      pid := OperatingSystem startProcess:'sleep 2; echo 1; sleep 2; echo 2'.
       
  1154      (Delay forSeconds:3) wait.
       
  1155      OperatingSystem killProcess:pid.
       
  1156     "
       
  1157 
       
  1158     "Modified: 21.3.1997 / 10:04:35 / dq"
       
  1159     "Modified: 2.5.1997 / 11:55:44 / cg"
       
  1160     "Modified: 28.1.1998 / 14:13:33 / md"
       
  1161 !
       
  1162 
       
  1163 startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream
       
  1164     "start executing the OS command as specified by the argument, aCommandString
       
  1165      as a separate process; do not wait for the command to finish.
       
  1166      The commandString is passed to a shell for execution - see the description of
       
  1167      'sh -c' in your UNIX manual ('cmd.com' in your MSDOS manual).
       
  1168      The command gets stdIn, stdOut and stdErr assigned from the arguments;
       
  1169      each may be nil.
       
  1170      Return the processId if successful, nil otherwise.
       
  1171      Use #monitorPid:action: for synchronization and exec status return,
       
  1172      or #killProcess: to stop it."
       
  1173 
       
  1174      self subclassResponsibility
       
  1175 ! !
       
  1176 
       
  1177 !AbstractOperatingSystem class methodsFor:'file access'!
       
  1178 
       
  1179 closeFd:anInteger
       
  1180     "low level close of a filedescriptor"
       
  1181 
       
  1182     self subclassResponsibility
       
  1183 !
       
  1184 
       
  1185 createDirectory:aPathName
       
  1186     "create a new directory with name 'aPathName', which may be an absolute
       
  1187      path, or relative to the current directory.
       
  1188      Return true if successful (or the directory existed already), false if failed.
       
  1189      This is a low-level entry - use Filename protocol for compatibility."
       
  1190 
       
  1191     "/ if it already exists this is ok
       
  1192 
       
  1193     self subclassResponsibility
       
  1194 !
       
  1195 
       
  1196 linkFile:oldPath to:newPath
       
  1197     "link the file 'oldPath' to 'newPath'. The link will be a hard link.
       
  1198      Return true if successful, false if not."
       
  1199 
       
  1200     self subclassResponsibility
       
  1201 !
       
  1202 
       
  1203 recursiveCopyDirectory:sourcePathName to:destination
       
  1204     "copy the directory named 'sourcePathName' and all contained files/directories to 'destination'.
       
  1205      Return true if successful."
       
  1206 
       
  1207     self subclassResponsibility
       
  1208 
       
  1209     "Modified: 7.3.1996 / 15:26:30 / cg"
       
  1210 !
       
  1211 
       
  1212 recursiveCreateDirectory:dirName
       
  1213     "create a directory - with all parent dirs if needed.
       
  1214      Return true if successful, false otherwise. If false
       
  1215      is returned, a partial created tree may be left,
       
  1216      which is not cleaned-up here."
       
  1217 
       
  1218     self createDirectory:dirName.
       
  1219     (self isDirectory:dirName) ifFalse:[
       
  1220 	(self recursiveCreateDirectory:(dirName asFilename directoryName)) ifFalse:[^ false].
       
  1221 	^ self createDirectory:dirName
       
  1222     ].
       
  1223     ^ true
       
  1224 
       
  1225     "
       
  1226      OperatingSystem recursiveCreateDirectory:'foo/bar/baz'
       
  1227      OperatingSystem recursiveRemoveDirectory:'foo'
       
  1228     "
       
  1229 
       
  1230     "Modified: 7.3.1996 / 15:26:22 / cg"
       
  1231 !
       
  1232 
       
  1233 recursiveRemoveDirectory:fullPathName
       
  1234     "remove the directory named 'fullPathName' and all contained files/directories.
       
  1235      Return true if successful."
       
  1236 
       
  1237     self subclassResponsibility
       
  1238 
       
  1239     "
       
  1240      OperatingSystem recursiveCreateDirectory:'foo/bar/baz'
       
  1241      OperatingSystem recursiveRemoveDirectory:'foo'
       
  1242     "
       
  1243 
       
  1244     "Modified: 7.3.1996 / 15:26:30 / cg"
       
  1245 !
       
  1246 
       
  1247 removeDirectory:fullPathName
       
  1248     "remove the directory named 'fullPathName'. 
       
  1249      The directory must be empty and you must have appropriate access rights.
       
  1250      Return true if successful, false if directory is not empty or no permission.
       
  1251      This is a lowLevel entry - use Filename protocol for compatibility."
       
  1252 
       
  1253     self subclassResponsibility
       
  1254 !
       
  1255 
       
  1256 removeFile:fullPathName
       
  1257     "remove the file named 'fullPathName'; return true if successful.
       
  1258      This is a lowLevel entry - use Filename protocol for compatibility."
       
  1259 
       
  1260     self subclassResponsibility
       
  1261 !
       
  1262 
       
  1263 renameFile:oldPath to:newPath
       
  1264     "rename the file 'oldPath' to 'newPath'. 
       
  1265      Someone else has to care for the names to be correct and 
       
  1266      correct for the OS used - therefore, this should not be called
       
  1267      directlt. Instead, use Filename protocol to rename; this cares for
       
  1268      any invalid names.
       
  1269      Returns true if successful, false if not"
       
  1270 
       
  1271     self subclassResponsibility
       
  1272 !
       
  1273 
       
  1274 truncateFile:aPathName to:newSize
       
  1275     "change a files size return true on success, false on failure.
       
  1276      This may not be supported on all architectures.
       
  1277 
       
  1278      This is a low-level entry - use Filename protocol."
       
  1279 
       
  1280     self subclassResponsibility
       
  1281 ! !
       
  1282 
       
  1283 !AbstractOperatingSystem class methodsFor:'file access rights'!
       
  1284 
       
  1285 accessMaskFor:aSymbol
       
  1286     "return the access bits mask for numbers as returned by 
       
  1287      OperatingSystem>>accessModeOf:
       
  1288      and expected by OperatingSystem>>changeAccessModeOf:to:.
       
  1289      Since these numbers are OS dependent, always use the mask
       
  1290      (never hardcode 8rxxx into your code)."
       
  1291 
       
  1292     self subclassResponsibility
       
  1293 !
       
  1294 
       
  1295 accessModeOf:aPathName
       
  1296     "return a number representing access rights rwxrwxrwx for owner,
       
  1297      group and others. Return nil if such a file does not exist.
       
  1298      Notice that the returned number is OS dependent - use the 
       
  1299      modeMasks as returned by OperatingSystem>>accessMaskFor:"
       
  1300 
       
  1301     "
       
  1302      this could have been implemented as:
       
  1303 	(self infoOf:aPathName) at:#mode
       
  1304      but for huge directory searches the code below is faster
       
  1305     "
       
  1306 
       
  1307     ^ (self infoOf:aPathName) at:#mode
       
  1308 
       
  1309    "
       
  1310     (OperatingSystem accessModeOf:'/') printStringRadix:8
       
  1311    "
       
  1312 !
       
  1313 
       
  1314 changeAccessModeOf:aPathName to:modeBits
       
  1315     "change the access rights of aPathName to the OS dependent modeBits.
       
  1316      You should construct this mask using accessMaskFor, to be OS
       
  1317      independent. Return true if changed, 
       
  1318      false if such a file does not exist or change was not allowd."
       
  1319 
       
  1320     self subclassResponsibility
       
  1321 ! !
       
  1322 
       
  1323 !AbstractOperatingSystem class methodsFor:'file locking'!
       
  1324 
       
  1325 lockFD:aFileDescriptor shared:isSharedReadLock blocking:blockIfLocked
       
  1326    "set a lock on the file represented by aFileDescriptor.
       
  1327     (such as returned by ExternalStream>>fileDescriptor).
       
  1328     On some systems, only advisory locks are available -
       
  1329     these depends on other accessors to also perform the locking operation.
       
  1330     If they do not, they may still access the file 
       
  1331     (on some systems, locks are mandatory, on others, they are advisory). 
       
  1332     The isSharedReadLock argument (if true) specifies if multiple readers
       
  1333     are to be allowed - if false, they are not.
       
  1334     On some systems, all locks are non-exclusive locks.
       
  1335 
       
  1336     Returns true, if the lock was aquired, false otherwise.
       
  1337 
       
  1338     Notice, that not all OS's support these locks; 
       
  1339     on some, this may simply be a no-op.
       
  1340     Also notice, that some systems block the process, to wait for the lock.
       
  1341     This can (again: on some systems) be avoided by passing a false blockIfLocked
       
  1342     argument."
       
  1343 
       
  1344     ^ false
       
  1345 !
       
  1346 
       
  1347 supportsFileLinks
       
  1348     "return true, if the OS supports file links (hard links).
       
  1349      Typically, only unix returns true here."
       
  1350 
       
  1351     ^ false
       
  1352 !
       
  1353 
       
  1354 supportsFileLocks
       
  1355     "return true, if the OS supports file locking"
       
  1356 
       
  1357     ^ false
       
  1358 
       
  1359     "
       
  1360      OperatingSystem supportsFileLocks
       
  1361     "
       
  1362 !
       
  1363 
       
  1364 supportsNonBlockingFileLocks
       
  1365     "return true, if the OS supports nonBlocking file locking
       
  1366      (i.e. with immediate return instead of waiting for the lock)"
       
  1367 
       
  1368     ^ false
       
  1369 
       
  1370     "
       
  1371      OperatingSystem supportsNonBlockingFileLocks
       
  1372     "
       
  1373 !
       
  1374 
       
  1375 supportsSharedLocks
       
  1376     "return true, if the OS supports shared (i.e. multiple reader)
       
  1377      file locking."
       
  1378 
       
  1379     ^ false
       
  1380 
       
  1381     "
       
  1382      OperatingSystem supportsNonBlockingFileLocks
       
  1383     "
       
  1384 !
       
  1385 
       
  1386 supportsSymbolicLinks
       
  1387     "return true, if the OS supports symbolic links on files/directories.
       
  1388      Typically, only Unix returns true here"
       
  1389 
       
  1390     ^ false
       
  1391 !
       
  1392 
       
  1393 unlockFD:aFileDescriptor
       
  1394     "clear a file lock on the file represented by aFileDescriptor,
       
  1395      which was previously aquired by #lockFD:.
       
  1396      Return false, if the unlock failed 
       
  1397      (which may happens when a wrong fd is passed, 
       
  1398       no lock was set previously, or the systsem does not support locks).
       
  1399      Notice, that not all OS's support file locks; 
       
  1400      on some, this may simply be a no-op."
       
  1401      
       
  1402     self subclassResponsibility
       
  1403 ! !
       
  1404 
       
  1405 !AbstractOperatingSystem class methodsFor:'file queries'!
       
  1406 
       
  1407 baseNameOf:aPath
       
  1408     self obsoleteMethodWarning:'use asFilename baseName'.
       
  1409     ^ aPath asFilename baseName
       
  1410 !
       
  1411 
       
  1412 caseSensitiveFilenames
       
  1413     "return true, if the OS has caseSensitive file naming.
       
  1414      On MSDOS, this will return false; 
       
  1415      on a real OS, we return true."
       
  1416 
       
  1417     self subclassResponsibility
       
  1418 !
       
  1419 
       
  1420 compressPath:pathName
       
  1421     "return the pathName compressed - that is, remove all ..-entries
       
  1422      and . entries. This does not always (in case of symbolic links)
       
  1423      return the true pathName and is therefore used as a fallback
       
  1424      if realPath and popen failed."
       
  1425 
       
  1426     self subclassResponsibility
       
  1427 !
       
  1428 
       
  1429 directoryNameOf:aPath
       
  1430     self obsoleteMethodWarning:'use asFilename directoryName'.
       
  1431     ^ aPath asFilename directoryName
       
  1432 !
       
  1433 
       
  1434 fileSeparator
       
  1435     "return the character used to separate names in a path.
       
  1436      This character differs for MSDOS and other systems,
       
  1437      (but those are currently not supported - so this is some
       
  1438       preparation for the future)"
       
  1439 
       
  1440     self isMSDOSlike ifTrue:[
       
  1441 	^ $\
       
  1442     ].
       
  1443     ^ $/
       
  1444 !
       
  1445 
       
  1446 getDriveList
       
  1447     "return a list of volumes in the system. 
       
  1448      On unix, no such thing like a volume exists 
       
  1449      - there, a syntetic list with root, home & current is returned. 
       
  1450      On MSDOS, a list of drive letters is (eventually) returned.
       
  1451      On VMS, a list of volumes is (eventually) returned."
       
  1452 
       
  1453     "/
       
  1454     "/ default: retrurn array filled with
       
  1455     "/ root, home and current directories.
       
  1456     "/
       
  1457     ^ Array 
       
  1458 	with:'/'
       
  1459 	with:(self getHomeDirectory)
       
  1460 	with:(Filename currentDirectory pathName)
       
  1461 !
       
  1462 
       
  1463 idOf:aPathName
       
  1464     "return the fileNumber (i.e. inode number) of a file.
       
  1465 
       
  1466      Not all operatingSystems may provide this - on those that do not,
       
  1467      some dummy id will be returned.
       
  1468      On unix, this information can be used to check for two files being 
       
  1469      physically identical, even if found in different directories 
       
  1470      (i.e. if they are hardLinked)."
       
  1471 
       
  1472     |i id|
       
  1473 
       
  1474     id := self primIdOf:aPathName.
       
  1475     id notNil ifTrue:[^ id].
       
  1476 
       
  1477     i := self infoOf:aPathName.
       
  1478     i notNil ifTrue:[^ i id].
       
  1479     ^ nil.
       
  1480 
       
  1481     "
       
  1482      OperatingSystem idOf:'/'
       
  1483     "
       
  1484 !
       
  1485 
       
  1486 infoOf:aPathName
       
  1487     "return some object filled with info for the file 'aPathName';
       
  1488      the info (for which corresponding access methods are understood by
       
  1489      the returned object) is:
       
  1490 	 type            - a symbol giving the files type
       
  1491 	 mode            - numeric access mode 
       
  1492 	 uid             - owners user id
       
  1493 	 gid             - owners group id
       
  1494 	 size            - files size
       
  1495 	 id              - files number (i.e. inode number)
       
  1496 	 accessed        - last access time (as Timestamp)
       
  1497 	 modified        - last modification time (as Timestamp)
       
  1498 	 statusChanged   - last status change time (as Timestamp)
       
  1499 	 alternativeName - (windows only: the MSDOS name of the file)
       
  1500 
       
  1501      Some of the fields may be returned as nil on systems which do not provide
       
  1502      all of the information.
       
  1503      Return nil if such a file does not exist. 
       
  1504      For symbolic links (if supported by the OS), 
       
  1505      the info of the pointed-to-file (i.e. the target) is returned;
       
  1506      use #linkInfoOf: to get info about the link itself.
       
  1507     "
       
  1508 
       
  1509     self subclassResponsibility
       
  1510 !
       
  1511 
       
  1512 isDirectory:aPathName
       
  1513     "return true, if 'aPathName' is a valid directory path name.
       
  1514      (i.e. exists and is a directory).
       
  1515      This also returns true for symbolic links pointing to a directory;
       
  1516      if you need to check for this, use #linkInfo:."
       
  1517 
       
  1518     ^ (self infoOf:aPathName) type == #directory
       
  1519 !
       
  1520 
       
  1521 isExecutable:aPathName
       
  1522     "return true, if the given file is executable.
       
  1523      For symbolic links, the pointed-to-file is checked."
       
  1524 
       
  1525     self subclassResponsibility
       
  1526 !
       
  1527 
       
  1528 isReadable:aPathName
       
  1529     "return true, if the file/dir 'aPathName' is readable.
       
  1530      For symbolic links, the pointed-to-file is checked."
       
  1531 
       
  1532     self subclassResponsibility
       
  1533 !
       
  1534 
       
  1535 isSymbolicLink:aPathName
       
  1536     "return true, if the given file is a symbolic link"
       
  1537 
       
  1538     ^ (self linkInfoOf:aPathName) notNil
       
  1539 
       
  1540     "
       
  1541      OperatingSystem isSymbolicLink:'Make.proto'
       
  1542      OperatingSystem isSymbolicLink:'Makefile' 
       
  1543     "
       
  1544 !
       
  1545 
       
  1546 isValidPath:aPathName
       
  1547     "return true, if 'aPathName' is a valid path name
       
  1548      (i.e. the file or directory exists)"
       
  1549 
       
  1550     self subclassResponsibility
       
  1551 !
       
  1552 
       
  1553 isWritable:aPathName
       
  1554     "return true, if the given file is writable.
       
  1555      For symbolic links, the pointed-to-file is checked."
       
  1556 
       
  1557     self subclassResponsibility
       
  1558 !
       
  1559 
       
  1560 linkInfoOf:aPathName
       
  1561     "return a dictionary filled with info for the file 'aPathName',
       
  1562      IFF aPathName is a symbolic link. 
       
  1563      If aPathName is invalid, or its NOT a symbolic link, nil is returned.
       
  1564      (which means, that systems like VMS or MSDOS always return nil here.)
       
  1565 
       
  1566      The contents of the dictionary gives info about the link itself,
       
  1567      on contrast to #infoOf:, which returns the info of the pointed to file
       
  1568      in case of a symbolic link."
       
  1569      
       
  1570     self subclassResponsibility
       
  1571 !
       
  1572 
       
  1573 parentDirectoryName
       
  1574     "return the name used to refer to parent directories.
       
  1575      In MSDOS, Unix and other systems this is '..', but maybe different
       
  1576      for other systems.
       
  1577      (but those are currently not supported - so this is some
       
  1578       preparation for the future)"
       
  1579 
       
  1580     ^ '..'
       
  1581 !
       
  1582 
       
  1583 pathNameOf:pathName
       
  1584     "return the pathName of the argument, aPathString,
       
  1585      - thats the full pathname of the directory, starting at '/'.
       
  1586      This method needs the path to be valid
       
  1587      (i.e. all directories must exist, be readable and executable).
       
  1588      Notice: if symbolic links are involved, the result may look different
       
  1589      from what you expect."
       
  1590 
       
  1591     self subclassResponsibility
       
  1592 !
       
  1593 
       
  1594 primIdOf:aPathName
       
  1595     "the actual code to return the fileNumber (i.e. inode number) of a file."
       
  1596 
       
  1597     self subclassResponsibility
       
  1598 !
       
  1599 
       
  1600 primPathNameOf:pathName
       
  1601     "return the pathName of the argument, aPathString,
       
  1602      - thats the full pathname of the directory, starting at '/'.
       
  1603      This method here returns nil, if the OS does not provide a
       
  1604      realPath library function.
       
  1605      Notice: if symbolic links are involved, the result may look different
       
  1606      from what you expect."
       
  1607 
       
  1608     self subclassResponsibility
       
  1609 !
       
  1610 
       
  1611 timeOfLastAccess:aPathName
       
  1612     "return the time, when the file was last accessed.
       
  1613      For nonexistent files, nil is returned."
       
  1614 
       
  1615     ^ (self infoOf:aPathName) accessed 
       
  1616 !
       
  1617 
       
  1618 timeOfLastChange:aPathName
       
  1619     "return the time, when the file was last changed. 
       
  1620      For nonexistent files, nil is returned."
       
  1621 
       
  1622     ^ (self infoOf:aPathName) modified
       
  1623 !
       
  1624 
       
  1625 typeOf:aPathName
       
  1626     "return the type of a file as a symbol; for nonexistent files,
       
  1627      nil is returned.
       
  1628      Notice: for symbolic links, the type of the pointed-to file is returned."
       
  1629 
       
  1630     ^ (self infoOf:aPathName) type 
       
  1631 !
       
  1632 
       
  1633 volumeNameOf:aPathString
       
  1634     "return the volumeName of the argument, aPath
       
  1635      - thats the name of the volume where aPath is.
       
  1636      Not all OperatingSystems support/use volumes; on unix,
       
  1637      this always returns an empty string."
       
  1638 
       
  1639     ^ ''
       
  1640 ! !
       
  1641 
       
  1642 !AbstractOperatingSystem class methodsFor:'interrupts & signals'!
       
  1643 
       
  1644 blockInterrupts
       
  1645     "disable interrupt processing - if disabled, incoming
       
  1646      interrupts will be registered and handled as soon as
       
  1647      interrupts are reenabled by OperatingSystemclass>>unblockInterrupts.
       
  1648      Returns the previous blocking status i.e. true if interrupts
       
  1649      where already blocked. You need this information for proper
       
  1650      unblocking, in case of nested block/unblock calls."
       
  1651 
       
  1652 %{  /* NOCONTEXT */
       
  1653     RETURN ( __BLOCKINTERRUPTS() );
       
  1654 %}
       
  1655 !
       
  1656 
       
  1657 defaultSignal:signalNumber
       
  1658     "revert to the default action on arrival of a (Unix-)signal.
       
  1659      Dont confuse Unix signals with smalltalk signals.
       
  1660      WARNING: for some signals, it is no good idea to revert to default;
       
  1661      for example, the default for SIGINT (i.e. ^C) is to exit; while the
       
  1662      default for SIGQUIT (^ \) is to dump core.
       
  1663      Also, NOTICE that signal numbers are not portable between unix
       
  1664      systems - use OperatingSystem sigXXX to get the numeric value for
       
  1665      a signal."
       
  1666 
       
  1667     self subclassResponsibility
       
  1668 !
       
  1669 
       
  1670 disableChildSignalInterrupts
       
  1671     "disable childSignal interrupts 
       
  1672      (SIGCHLD, if the architecture supports it).
       
  1673      We have to set the signal back to default, because ignoring 
       
  1674      SIGCHLD breaks wait & co"
       
  1675 
       
  1676     ^ self defaultSignal:(self sigCHLD)
       
  1677 
       
  1678     "Created: 5.1.1996 / 15:45:28 / stefan"
       
  1679 !
       
  1680 
       
  1681 disableIOInterruptsOn:fd
       
  1682     "turn off IO interrupts for a filedescriptor"
       
  1683 
       
  1684     self subclassResponsibility
       
  1685 !
       
  1686 
       
  1687 disableSignal:signalNumber
       
  1688     "disable (Unix-) signal processing for signalNumber.
       
  1689      Dont confuse Unix signals with smalltalk signals.
       
  1690      WARNING: for some signals, it is no good idea to disable
       
  1691      them; for example, disabling the SIGINT signal turns off ^C
       
  1692      handling.
       
  1693      Also, NOTICE that signal numbers are not portable between unix
       
  1694      systems - use OperatingSystem sigXXX to get the numeric value for
       
  1695      a signal.
       
  1696      Use only for fully debugged stand alone applications."
       
  1697 
       
  1698     self subclassResponsibility
       
  1699 !
       
  1700 
       
  1701 disableTimer
       
  1702     "disable timer interrupts.
       
  1703      WARNING: 
       
  1704 	the system will not operate correctly with timer interrupts
       
  1705 	disabled, because no scheduling or timeouts are possible."
       
  1706 
       
  1707     self subclassResponsibility
       
  1708 !
       
  1709 
       
  1710 disableUserInterrupts
       
  1711     "disable userInterrupt processing;
       
  1712      when disabled, no ^C processing takes place.
       
  1713      WARNING:
       
  1714 	 If at all, use this only for debugged stand-alone applications, since
       
  1715 	 no exit to the debugger is possible with user interrupts disabled.
       
  1716 	 We recommend setting up a handler for the signal instead of disabling it."
       
  1717 
       
  1718     self disableSignal:(self sigBREAK).
       
  1719     self disableSignal:(self sigINT).
       
  1720 !
       
  1721 
       
  1722 enableAbortInterrupts
       
  1723     "enable abort signalhandling, and make it a regular signalInterrupt.
       
  1724      (the default will dump core and exit - which is not a good idea for
       
  1725       end-user applications ...).
       
  1726      This is especially useful, if linked-in C-libraries call abort() ..."
       
  1727 
       
  1728     self enableSignal:(self sigABRT)
       
  1729 !
       
  1730 
       
  1731 enableChildSignalInterrupts
       
  1732     "enable childSignal interrupts 
       
  1733      (SIGCHLD, if the architecture supports it).
       
  1734      After enabling, these signals will send the message 
       
  1735      'childSignalInterrupt' to the ChildSignalInterruptHandler object."
       
  1736 
       
  1737     self enableSignal:(self sigCHLD)
       
  1738 !
       
  1739 
       
  1740 enableFpExceptionInterrupts
       
  1741     "enable floating point exception interrupts (if the
       
  1742      architecture supports it).
       
  1743      After enabling, fpu-exceptions will send the message 
       
  1744      'fpuExceptionInterrupt' to the FPUExceptionInterruptHandler object."
       
  1745 
       
  1746     self enableSignal:(self sigFP)
       
  1747 !
       
  1748 
       
  1749 enableHardSignalInterrupts
       
  1750     "enable hard signal exception interrupts (trap, buserror & segm. violation).
       
  1751      After enabling, these exceptions will send the message 
       
  1752      'signalInterrupt' to the SignalInterruptHandler object."
       
  1753 
       
  1754     "/ leads to trouble ...
       
  1755 "/    self enableSignal:(self sigPIPE).
       
  1756 
       
  1757     "/ ... better to ignore them, and let it be handled as a writeErrorSignal.
       
  1758     self disableSignal:(self sigPIPE).
       
  1759 
       
  1760     self enableSignal:(self sigILL).
       
  1761     self enableSignal:(self sigBUS).
       
  1762     self enableSignal:(self sigSEGV).
       
  1763     self enableSignal:(self sigFP).
       
  1764     self enableSignal:(self sigEMT).
       
  1765 !
       
  1766 
       
  1767 enableIOInterruptsOn:fd
       
  1768     "turn on IO interrupts for a filedescriptor"
       
  1769 
       
  1770     self subclassResonsibility
       
  1771 !
       
  1772 
       
  1773 enableQuitInterrupts
       
  1774     "enable quitInterrupt (usually ^\) handling, and make it a userInterrupt.
       
  1775      (the default will dump core and exit - which is not a good idea for
       
  1776       end-user applications ...)"
       
  1777 
       
  1778     self enableSignal:(self sigQUIT)
       
  1779 !
       
  1780 
       
  1781 enableSignal:signalNumber
       
  1782     "enable (Unix-)signal processing for signalNumber.
       
  1783      Dont confuse Unix signals with smalltalk signals.
       
  1784      The signal will be delivered to one of the standard handlers
       
  1785      (SIGINT, SIGQUIT, etc) or to a general handler, which
       
  1786      sends #signalInterrupt:.
       
  1787 
       
  1788      NOTICE that signal numbers are not portable between unix
       
  1789      systems - use OperatingSystem sigXXX to get the numeric value for
       
  1790      a signal."
       
  1791 
       
  1792     self subclassResonsibility
       
  1793 !
       
  1794 
       
  1795 enableTimer:milliSeconds
       
  1796     "setup for a timerInterrupt, to be signalled after some (real) time."
       
  1797 
       
  1798     self subclassResonsibility
       
  1799 !
       
  1800 
       
  1801 enableUserInterrupts
       
  1802     "enable userInterrupt (^C) handling;
       
  1803      when enabled, ^C in the terminal window will send the message
       
  1804      'userInterrupt' to the UserInterruptHandler object."
       
  1805 
       
  1806     self enableSignal:(self sigINT).
       
  1807     self enableSignal:(self sigBREAK).
       
  1808 !
       
  1809 
       
  1810 interruptPending
       
  1811     "return true, if an interrupt is pending. The returned value is
       
  1812      invalid if interrupts are not currently blocked, since otherwise 
       
  1813      the interrupt is usually already handled before arriving here,
       
  1814      or may be served while returning from here."
       
  1815 
       
  1816 %{  /* NOCONTEXT */
       
  1817     extern OBJ __INTERRUPTPENDING();
       
  1818 
       
  1819     RETURN ( __INTERRUPTPENDING() );
       
  1820 %}        
       
  1821 !
       
  1822 
       
  1823 interruptsBlocked
       
  1824     "return true, if interrupt handling is currently disabled;
       
  1825      false otherwise."
       
  1826 
       
  1827 %{  /* NOCONTEXT */
       
  1828     extern OBJ __INTERRUPTS_BLOCKED();
       
  1829 
       
  1830     RETURN ( __INTERRUPTS_BLOCKED() );
       
  1831 %}
       
  1832 !
       
  1833 
       
  1834 killProcess:processId
       
  1835     "kill an OS process.
       
  1836      The process has a no chance to do some cleanup.
       
  1837 
       
  1838      WARNING: in order to avoid zombie processes (on unix),
       
  1839               you may have to fetch the processes exitstatus with
       
  1840               OperatingSystem>>getStatusOfProcess:aProcessId."
       
  1841 
       
  1842     self subclassResponsibility
       
  1843 
       
  1844     "Modified: / 10.6.1998 / 12:00:07 / cg"
       
  1845 !
       
  1846 
       
  1847 killProcessGroup:processGroupId
       
  1848     "kill an OS process group.
       
  1849      The process has NO chance to do some cleanup.
       
  1850 
       
  1851      WARNING: in order to avoid zombie processes (on unix),
       
  1852               you may have to fetch the processes exitstatus with
       
  1853               OperatingSystem>>getStatusOfProcess:aProcessId."
       
  1854 
       
  1855     self subclassResponsibility
       
  1856 
       
  1857     "Created: / 10.6.1998 / 12:00:26 / cg"
       
  1858 !
       
  1859 
       
  1860 nameForSignal:aSignalNumber
       
  1861     "for a given Unix signalnumber, return a descriptive string"
       
  1862 
       
  1863     aSignalNumber == self sigHUP    ifTrue:[^ 'hangup'].
       
  1864     aSignalNumber == self sigINT    ifTrue:[^ 'interrupt'].
       
  1865     aSignalNumber == self sigKILL   ifTrue:[^ 'kill'].
       
  1866     aSignalNumber == self sigQUIT   ifTrue:[^ 'quit'].
       
  1867     aSignalNumber == self sigILL    ifTrue:[^ 'illegal instruction'].
       
  1868     aSignalNumber == self sigTRAP   ifTrue:[^ 'trap'].
       
  1869     aSignalNumber == self sigABRT   ifTrue:[^ 'abort'].
       
  1870     aSignalNumber == self sigIOT    ifTrue:[^ 'iot trap'].
       
  1871     aSignalNumber == self sigEMT    ifTrue:[^ 'emt trap'].
       
  1872     aSignalNumber == self sigFP     ifTrue:[^ 'fp exception'].
       
  1873     aSignalNumber == self sigBUS    ifTrue:[^ 'bus error'].
       
  1874     aSignalNumber == self sigSEGV   ifTrue:[^ 'segmentation violation'].
       
  1875     aSignalNumber == self sigSYS    ifTrue:[^ 'bad system call'].
       
  1876     aSignalNumber == self sigPIPE   ifTrue:[^ 'broken pipe'].
       
  1877     aSignalNumber == self sigALRM   ifTrue:[^ 'alarm timer'].
       
  1878     aSignalNumber == self sigTERM   ifTrue:[^ 'termination'].
       
  1879     aSignalNumber == self sigSTOP   ifTrue:[^ 'stop'].
       
  1880     aSignalNumber == self sigTSTP   ifTrue:[^ 'tty stop'].
       
  1881     aSignalNumber == self sigCONT   ifTrue:[^ 'continue'].
       
  1882     aSignalNumber == self sigCHLD   ifTrue:[^ 'child death'].
       
  1883     aSignalNumber == self sigTTIN   ifTrue:[^ 'background tty input'].
       
  1884     aSignalNumber == self sigTTOU   ifTrue:[^ 'background tty output'].
       
  1885     aSignalNumber == self sigIO     ifTrue:[^ 'io available'].
       
  1886     aSignalNumber == self sigXCPU   ifTrue:[^ 'cpu time expired'].
       
  1887     aSignalNumber == self sigXFSZ   ifTrue:[^ 'file size limit'].
       
  1888     aSignalNumber == self sigVTALRM ifTrue:[^ 'virtual alarm timer'].
       
  1889     aSignalNumber == self sigPROF   ifTrue:[^ 'profiling timer'].
       
  1890     aSignalNumber == self sigWINCH  ifTrue:[^ 'winsize changed'].
       
  1891     aSignalNumber == self sigLOST   ifTrue:[^ 'resource lost'].
       
  1892     aSignalNumber == self sigUSR1   ifTrue:[^ 'user signal 1'].
       
  1893     aSignalNumber == self sigUSR2   ifTrue:[^ 'user signal 2'].
       
  1894     aSignalNumber == self sigMSG    ifTrue:[^ 'HFT message'].
       
  1895     aSignalNumber == self sigPWR    ifTrue:[^ 'power-fail'].
       
  1896     aSignalNumber == self sigPRE    ifTrue:[^ 'programming exception'].
       
  1897     aSignalNumber == self sigGRANT  ifTrue:[^ 'HFT access wanted'].
       
  1898     aSignalNumber == self sigRETRACT ifTrue:[^ 'HFT access relinquish'].
       
  1899     aSignalNumber == self sigSOUND   ifTrue:[^ 'HFT sound complete'].
       
  1900     aSignalNumber == self sigDANGER  ifTrue:[^ 'low on paging space'].
       
  1901 
       
  1902     "notice: many systems map SIGPOLL and/or SIGUSR onto SIGIO
       
  1903 	     therefore, keep SIGIO always above the two below" 
       
  1904     aSignalNumber == self sigPOLL   ifTrue:[^ 'io available'].
       
  1905     aSignalNumber == self sigURG    ifTrue:[^ 'urgent'].
       
  1906 
       
  1907     ^ 'unknown signal'
       
  1908 
       
  1909     "
       
  1910      OperatingSystem nameForSignal:9
       
  1911      OperatingSystem nameForSignal:(OperatingSystem sigPOLL) 
       
  1912     "
       
  1913 !
       
  1914 
       
  1915 operatingSystemSignal:signalNumber
       
  1916     "return the signal to be raised when an 
       
  1917      operatingSystem-signal occurs, or nil"
       
  1918 
       
  1919     OSSignals notNil ifTrue:[
       
  1920 	^ OSSignals at:signalNumber ifAbsent:[nil]
       
  1921     ].
       
  1922     ^ nil
       
  1923 !
       
  1924 
       
  1925 operatingSystemSignal:signalNumber install:aSignal
       
  1926     "install a signal to be raised when an operatingSystem-signal occurs"
       
  1927 
       
  1928     OSSignals isNil ifTrue:[
       
  1929 	OSSignals := Array new:32
       
  1930     ].
       
  1931     OSSignals at:signalNumber put:aSignal
       
  1932 !
       
  1933 
       
  1934 sendSignal:signalNumber to:processId
       
  1935     "send a unix signal to some process (maybe myself).
       
  1936      Returns false if any error occurred, true otherwise.
       
  1937 
       
  1938      Do not confuse UNIX signals with Smalltalk-Signals.
       
  1939 
       
  1940      WARNING: in order to avoid zombie processes (on unix),
       
  1941 	      you may have to fetch the processes exitstatus with
       
  1942 	      OperatingSystem>>getStatusOfProcess:aProcessId
       
  1943 	      if the signal terminates that process."
       
  1944 
       
  1945     self subclassResponsibility
       
  1946 !
       
  1947 
       
  1948 startSpyTimer
       
  1949     "trigger a spyInterrupt, to be signalled after some short (virtual) time.
       
  1950      This is used by the old MessageTally for profiling.
       
  1951      Should be changed to use real profiling timer if available.
       
  1952      On systems, where no virtual timer is available, use the real timer
       
  1953      (which is of course less correct).
       
  1954      OBSOLETE: the new messageTally runs as a high prio process, not using 
       
  1955 	       spy interrupts."
       
  1956 
       
  1957     self subclassResponsibility
       
  1958 !
       
  1959 
       
  1960 stopSpyTimer
       
  1961     "stop spy timing - disable spy timer.
       
  1962      OBSOLETE: the new messageTally runs as a high prio process, not using 
       
  1963 	       spy interrupts."
       
  1964 
       
  1965     self subclassResponsibility
       
  1966 !
       
  1967 
       
  1968 terminateProcess:processId
       
  1969     "terminate a unix process.
       
  1970      The process has a chance to do some cleanup.
       
  1971 
       
  1972      WARNING: in order to avoid zombie processes (on unix),
       
  1973 	      you may have to fetch the processes exitstatus with
       
  1974 	      OperatingSystem>>getStatusOfProcess:aProcessId."
       
  1975 
       
  1976     self subclassResponsibility
       
  1977 !
       
  1978 
       
  1979 terminateProcessGroup:processGroupId
       
  1980     "terminate a unix process group.
       
  1981      The process has a chance to do some cleanup.
       
  1982 
       
  1983      WARNING: in order to avoid zombie processes (on unix),
       
  1984 	      you may have to fetch the processes exitstatus with
       
  1985 	      OperatingSystem>>getStatusOfProcess:aProcessId."
       
  1986 
       
  1987     self subclassResponsibility
       
  1988 !
       
  1989 
       
  1990 unblockInterrupts
       
  1991     "enable interrupt processing - if any interrupts are pending,
       
  1992      these will be handled immediately.
       
  1993      When unblocking interrupts, take care of nested block/unblock
       
  1994      calls - you must only unblock after a blockcall if they where
       
  1995      really not blocked before. See OperatingSystemclass>>blockInterrupts."
       
  1996 %{
       
  1997     __UNBLOCKINTERRUPTS();
       
  1998     RETURN (nil);
       
  1999 %}
       
  2000 ! !
       
  2001 
       
  2002 !AbstractOperatingSystem class methodsFor:'misc'!
       
  2003 
       
  2004 closePid:pid
       
  2005     "free pid resource"
       
  2006 
       
  2007     self subclassResponsibility
       
  2008 !
       
  2009 
       
  2010 exit
       
  2011     "shutdown smalltalk immediately - this method does not return.
       
  2012      Return 'good'-status (0) to the parent unix process."
       
  2013 
       
  2014 %{  /* NOCONTEXT */
       
  2015     __mainExit(0);
       
  2016 %}
       
  2017     "OperatingSystem exit - dont evaluate this"
       
  2018 !
       
  2019 
       
  2020 exit:exitCode
       
  2021     "shutdown smalltalk immediately -
       
  2022      returning an exit-code to the parent unix process."
       
  2023 
       
  2024 %{  /* NOCONTEXT */
       
  2025     int code = 1;
       
  2026 
       
  2027     if (__isSmallInteger(exitCode)) {
       
  2028 	code = __intVal(exitCode);
       
  2029     }
       
  2030     __mainExit(code);
       
  2031 %}
       
  2032     "OperatingSystem exit:1 - dont evaluate this"
       
  2033 !
       
  2034 
       
  2035 exitWithCoreDump
       
  2036     "shutdown smalltalk immediately - dumping core.
       
  2037      This always returns 'bad'-status to the parent unix process.
       
  2038      Notice, that no cleanup is performed at all - you may have to
       
  2039      manually remove any tempfiles.
       
  2040      Use this only for debugging ST/X itself"
       
  2041 
       
  2042 %{  /* NOCONTEXT */
       
  2043     abort();
       
  2044 %}
       
  2045     "
       
  2046      OperatingSystem exitWithCoreDump - dont evaluate this
       
  2047     "
       
  2048 ! !
       
  2049 
       
  2050 !AbstractOperatingSystem class methodsFor:'os queries'!
       
  2051 
       
  2052 getCPUDefine
       
  2053     "return a string which was used to identify this CPU type when STX was
       
  2054      compiled, and which should be passed down when compiling methods.
       
  2055      For example, on linux, this may be '-Di386'; on a vax, this would be '-Dvax'.
       
  2056      This is normally not of interest to 'normal' users; however, it is passed
       
  2057      down to the c-compiler when methods are incrementally compiled to machine code."
       
  2058 
       
  2059 %{  /* NOCONTEXT */
       
  2060 #   ifndef CPU_DEFINE
       
  2061 #       define CPU_DEFINE "-DunknownCPU"
       
  2062 #   endif
       
  2063 
       
  2064     RETURN ( __MKSTRING(CPU_DEFINE));
       
  2065 %}
       
  2066     "
       
  2067      OperatingSystem getCPUDefine
       
  2068     "
       
  2069 !
       
  2070 
       
  2071 getCPUType
       
  2072     "return a string giving the type of machine we're running on.
       
  2073      Here, the machine for which ST/X was compiled is returned
       
  2074      (i.e. for all x86's, the same i386 is returned).
       
  2075      This may normally not be of any interest to you ..."
       
  2076 
       
  2077     |cpu|
       
  2078     
       
  2079 %{  /* NOCONTEXT */
       
  2080 
       
  2081 #   ifdef vax
       
  2082 #    define CPU_STRING "vax"
       
  2083 #   endif
       
  2084 #   ifdef mips
       
  2085 #    define CPU_STRING "mips"
       
  2086 #   endif
       
  2087 #   ifdef i386
       
  2088 #    define CPU_STRING "i386"
       
  2089 #   endif
       
  2090 #   ifdef i860
       
  2091 #    define CPU_STRING "i860"
       
  2092 #   endif
       
  2093 #   ifdef ns32k
       
  2094 #    define CPU_STRING "ns32k"
       
  2095 #   endif
       
  2096 #   ifdef mc68k
       
  2097 #    define CPU_STRING "mc68k"
       
  2098 #   endif
       
  2099 #   ifdef mc88k
       
  2100 #    define CPU_STRING "mc88k"
       
  2101 #   endif
       
  2102 #   ifdef sparc
       
  2103 #    define CPU_STRING "sparc"
       
  2104 #   endif
       
  2105 #   ifdef hppa
       
  2106 #    define CPU_STRING "hppa"
       
  2107 #   endif
       
  2108 #   ifdef rs6000
       
  2109 #    define CPU_STRING "rs6000"
       
  2110 #   endif
       
  2111 #   ifdef powerPC
       
  2112 #    define CPU_STRING "powerPC"
       
  2113 #   endif
       
  2114 #   ifdef alpha
       
  2115 #    define CPU_STRING "alpha"
       
  2116 #   endif
       
  2117 #   ifdef transputer
       
  2118 #    define CPU_STRING "transputer"
       
  2119 #   endif
       
  2120 #   ifdef ibm370
       
  2121 #    define CPU_STRING "ibm370"
       
  2122 #   endif
       
  2123 
       
  2124 #   ifndef CPU_STRING
       
  2125 #    define CPU_STRING "unknown"
       
  2126 #   endif
       
  2127 
       
  2128     cpu = __MKSTRING(CPU_STRING);
       
  2129 #   undef CPU_STRING
       
  2130 %}.
       
  2131     ^ cpu
       
  2132 
       
  2133     "
       
  2134      OperatingSystem getCPUType
       
  2135     "
       
  2136 
       
  2137     "examples: are we running on a ss-10/solaris ?"
       
  2138     "
       
  2139      (OperatingSystem getCPUType = 'sparc') 
       
  2140      and:[OperatingSystem getOSType = 'solaris']
       
  2141     "
       
  2142 
       
  2143     "or on a pc/solaris ?"
       
  2144     "
       
  2145      (OperatingSystem getCPUType = 'i386')
       
  2146      and:[OperatingSystem getOSType = 'solaris']
       
  2147     "
       
  2148 !
       
  2149 
       
  2150 getDomainName
       
  2151     "return the domain this host is in.
       
  2152      Notice:
       
  2153 	not all systems support this; on some, 'unknown' is returned."
       
  2154 
       
  2155     self subclassResponsibility
       
  2156 !
       
  2157 
       
  2158 getEnvironment:aStringOrSymbol
       
  2159     "get an environment string"
       
  2160 
       
  2161     self subclassResponsibility
       
  2162 !
       
  2163 
       
  2164 getHostName
       
  2165     "return the hostname we are running on - if there is
       
  2166      a HOST environment variable, we are much faster here ...
       
  2167      Notice:
       
  2168 	not all systems support this; on some, 'unknown' is returned."
       
  2169 
       
  2170     self subclassResponsibility
       
  2171 !
       
  2172 
       
  2173 getLocaleInfo
       
  2174     "return a dictionary filled with values from the locale information;
       
  2175      Not all fields may be present, depending on the OS's setup and capabilities.
       
  2176      Possible fields are:
       
  2177 	decimalPoint                    <String>
       
  2178 
       
  2179 	thousandsSep                    <String>
       
  2180 
       
  2181 	internationalCurrencySymbol     <String>
       
  2182 
       
  2183 	currencySymbol                  <String>
       
  2184 
       
  2185 	monetaryDecimalPoint            <String>
       
  2186 
       
  2187 	monetaryThousandsSeparator      <String>
       
  2188 
       
  2189 	positiveSign                    <String>
       
  2190 
       
  2191 	negativeSign                    <String>
       
  2192 
       
  2193 	internationalFractionalDigits   <Integer>
       
  2194 
       
  2195 	fractionalDigits                <Integer>
       
  2196 
       
  2197 	positiveSignPrecedesCurrencySymbol      <Boolean>
       
  2198 
       
  2199 	negativeSignPrecedesCurrencySymbol      <Boolean>
       
  2200 
       
  2201 	positiveSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
       
  2202 
       
  2203 	negativeSignSeparatedBySpaceFromCurrencySymbol  <Boolean>
       
  2204 
       
  2205 	positiveSignPosition                            <Symbol>
       
  2206 							one of: #parenthesesAround, 
       
  2207 								#signPrecedes, 
       
  2208 								#signSuceeds, 
       
  2209 								#signPrecedesCurrencySymbol,
       
  2210 								#signSuceedsCurrencySymbol
       
  2211 
       
  2212 	negativeSignPosition                            <like above>
       
  2213 
       
  2214      it is up to the application to deal with undefined values.
       
  2215 
       
  2216      Notice, that (for now), the system does not use this information;
       
  2217      it should be used by applications as required.
       
  2218     "
       
  2219 
       
  2220     self subclassResponsibility
       
  2221 !
       
  2222 
       
  2223 getOSDefine
       
  2224     "return a string which was used to identify this machine when stx was
       
  2225      compiled, and which should be passed down when compiling methods.
       
  2226      For example, on linux, this is '-DLINUX'."
       
  2227 
       
  2228 %{  /* NOCONTEXT */
       
  2229 
       
  2230 #ifndef OS_DEFINE
       
  2231 # ifdef WIN32
       
  2232 #  define OS_DEFINE "-DWIN32"
       
  2233 # endif
       
  2234 
       
  2235 # ifndef OS_DEFINE
       
  2236 #  define OS_DEFINE "-DunknownOS"
       
  2237 # endif
       
  2238 #endif
       
  2239 
       
  2240     RETURN ( __MKSTRING(OS_DEFINE));
       
  2241 
       
  2242 #undef OS_DEFINE
       
  2243 %}
       
  2244     "
       
  2245      OperatingSystem getOSDefine
       
  2246     "
       
  2247 !
       
  2248 
       
  2249 getOSType
       
  2250     "return a string giving the type of OS we're running on.
       
  2251      This can be used to adapt programs to certain environment
       
  2252      differences (for example: mail-lock strategy ...)"
       
  2253 
       
  2254     |os|
       
  2255 
       
  2256 %{  /* NOCONTEXT */
       
  2257 
       
  2258 #   ifdef MSDOS
       
  2259 #    define OS_STRING "msdos"
       
  2260 #   endif
       
  2261 
       
  2262 #   ifdef WIN32
       
  2263 #    define OS_STRING "win32"
       
  2264 #   endif
       
  2265 
       
  2266 #   ifdef MSWINDOWS
       
  2267 #    define OS_STRING "mswindows"
       
  2268 #   endif
       
  2269 
       
  2270 #   ifdef VMS
       
  2271 #    ifdef __openVMS__
       
  2272 #     define OS_STRING "openVMS"
       
  2273 #    else
       
  2274 #     define OS_STRING "VMS"
       
  2275 #    endif
       
  2276 #   endif
       
  2277 
       
  2278 #   ifdef MVS /* ;-) */
       
  2279 #    define OS_STRING "mvs"
       
  2280 #   endif
       
  2281 
       
  2282 #   ifdef OS2
       
  2283 #    define OS_STRING "os2"
       
  2284 #   endif
       
  2285 
       
  2286 #   ifdef sinix
       
  2287 #    define OS_STRING "sinix"
       
  2288 #   endif
       
  2289 
       
  2290 #   ifdef ultrix
       
  2291 #    define OS_STRING "ultrix"
       
  2292 #   endif
       
  2293 
       
  2294 #   ifdef sco
       
  2295 #    define OS_STRING "sco"
       
  2296 #   endif
       
  2297 
       
  2298 #   ifdef hpux
       
  2299 #    define OS_STRING "hpux"
       
  2300 #   endif
       
  2301 
       
  2302 #   ifdef LINUX
       
  2303 #    define OS_STRING "linux"
       
  2304 #   endif
       
  2305 
       
  2306 #   ifdef sunos
       
  2307 #    define OS_STRING "sunos"
       
  2308 #   endif
       
  2309 
       
  2310 #   ifdef solaris
       
  2311 #    define OS_STRING "solaris"
       
  2312 #   endif
       
  2313 
       
  2314 #   ifdef IRIS
       
  2315 #    define OS_STRING "irix"
       
  2316 #   endif
       
  2317 
       
  2318 #   ifdef aix
       
  2319 #    define OS_STRING "aix"
       
  2320 #   endif
       
  2321 
       
  2322 #   ifdef realIX
       
  2323 #    define OS_STRING "realIX"
       
  2324 #   endif
       
  2325 
       
  2326 #   ifdef __osf__
       
  2327 #    define OS_STRING "osf"
       
  2328 #   endif
       
  2329 
       
  2330     /*
       
  2331      * no concrete info; become somewhat vague ...
       
  2332      */
       
  2333 #   ifndef OS_STRING
       
  2334 #    ifdef MACH
       
  2335 #     define OS_STRING "mach"
       
  2336 #    endif
       
  2337 #   endif
       
  2338 
       
  2339 #   ifndef OS_STRING
       
  2340 #    ifdef BSD
       
  2341 #     define OS_STRING "bsd"
       
  2342 #    endif
       
  2343 
       
  2344 #    ifdef SYSV
       
  2345 #     ifdef SYSV3
       
  2346 #      define OS_STRING "sys5_3"
       
  2347 #     else
       
  2348 #      ifdef SYSV4
       
  2349 #       define OS_STRING "sys5_4"
       
  2350 #      else
       
  2351 #       define OS_STRING "sys5"
       
  2352 #      endif
       
  2353 #     endif
       
  2354 #    endif
       
  2355 #   endif
       
  2356 
       
  2357     /*
       
  2358      * become very vague ...
       
  2359      */
       
  2360 #   ifndef OS_STRING
       
  2361 #    ifdef POSIX
       
  2362 #     define OS_STRING "posix"
       
  2363 #    endif
       
  2364 #   endif
       
  2365 #   ifndef OS_STRING
       
  2366 #    ifdef UNIX
       
  2367 #     define OS_STRING "unix"
       
  2368 #    endif
       
  2369 #   endif
       
  2370 
       
  2371 #   ifndef OS_STRING
       
  2372 #    define OS_STRING "unknown"
       
  2373 #   endif
       
  2374 
       
  2375     os = __MKSTRING(OS_STRING);
       
  2376 
       
  2377 #   undef OS_STRING
       
  2378 %}.
       
  2379     ^ os
       
  2380 
       
  2381     "
       
  2382      OperatingSystem getOSType
       
  2383     "
       
  2384 !
       
  2385 
       
  2386 getProcessId
       
  2387     "return the (unix-)processId"
       
  2388 
       
  2389     self subclassResponsibility
       
  2390 !
       
  2391 
       
  2392 getSystemID
       
  2393     "if supported by the OS, return the systemID;
       
  2394      a unique per machine identification.
       
  2395      WARNING:
       
  2396 	not all systems support this; on some, 'unknown' is returned."
       
  2397 
       
  2398     ^ 'unknown'
       
  2399 
       
  2400     "
       
  2401      OperatingSystem getSystemID
       
  2402     "
       
  2403 !
       
  2404 
       
  2405 getSystemInfo
       
  2406     "return info on the system weare running on.
       
  2407      If the system supports the uname system call, that info is returned;
       
  2408      otherwise, some simulated info is returned.
       
  2409  
       
  2410      WARNING:
       
  2411        Do not depend on the amount and contents of the returned information, some
       
  2412        systems may return more/less than others. Also, the contents depends on the
       
  2413        OS, for example, linux returns 'ix86', while WIN32 returns 'x86'.
       
  2414 
       
  2415        This method is mainly provided to augment error reports with some system
       
  2416        information. 
       
  2417        (in case of system/version specific OS errors, conditional workarounds and patches
       
  2418 	may be based upon this info).
       
  2419        Your application should NOT depend upon this in any way.
       
  2420 
       
  2421      The returned info may (or may not) contain:
       
  2422 	#system -> some operating system identification (irix, Linux, nt, win32s ...) 
       
  2423 	#version -> OS version (some os version identification)
       
  2424 	#release -> OS release (3.5, 1.2.1 ...)
       
  2425 	#node   -> some host identification (hostname)
       
  2426 	#domain  -> domain name (hosts domain)
       
  2427 	#machine -> type of machine (i586, mips ...)
       
  2428     "
       
  2429 
       
  2430     |info|
       
  2431 
       
  2432     info := IdentityDictionary new.
       
  2433     info at:#system put:(self getSystemType).
       
  2434     info at:#node put:(self getHostName).
       
  2435     info at:#machine put:(self getCPUType).
       
  2436     info at:#architecture put:'unknown'.
       
  2437     info at:#domain put:self getDomainName.
       
  2438     info at:#osType put:(self getOSType).
       
  2439     ^ info
       
  2440 
       
  2441     "
       
  2442      OperatingSystem getSystemInfo
       
  2443     "
       
  2444 !
       
  2445 
       
  2446 getSystemType
       
  2447     "return a string giving the type of system we're running on.
       
  2448      This is almost the same as getOSType, but the returned string
       
  2449      is slightly different for some systems (i.e. iris vs. irix).
       
  2450      Dont depend on this - use getOSType. I dont really see a point
       
  2451      here ... 
       
  2452      (except for slight differences between next/mach and other machs)"
       
  2453 
       
  2454     ^ self getOSType
       
  2455 
       
  2456     "
       
  2457      OperatingSystem getSystemType
       
  2458     "
       
  2459 !
       
  2460 
       
  2461 getWindowsDirectory
       
  2462     "internal interface - only for Windows based systems.
       
  2463      Return the windows directory 
       
  2464      (which - depending on the system - may be \WINNT, \WINDOWS or whatever)
       
  2465      On non-windows systems, nil is returned."
       
  2466 
       
  2467     ^ nil
       
  2468 
       
  2469     "
       
  2470      OperatingSystem getWindowsDirectory
       
  2471     "
       
  2472 !
       
  2473 
       
  2474 getWindowsSystemDirectory
       
  2475     "internal interface - only for Windows based systems.
       
  2476      Return the windows system directory 
       
  2477      (which - depending on the system - may be \WINNT\SYSTEM32, 
       
  2478       \WINDOWS\SYSTEM or whatever)
       
  2479      On non-windows systems, nil is returned."
       
  2480 
       
  2481     ^ nil
       
  2482 
       
  2483     "
       
  2484      OperatingSystem getWindowsSystemDirectory
       
  2485     "
       
  2486 !
       
  2487 
       
  2488 isBSDlike
       
  2489     "return true, if the OS we're running on is a 'real' unix."
       
  2490 
       
  2491     ^ false
       
  2492 !
       
  2493 
       
  2494 isMAClike
       
  2495     "return true, if running on a macOS (but not on A/UX)"
       
  2496 
       
  2497     ^ false
       
  2498 !
       
  2499 
       
  2500 isMSDOSlike
       
  2501     "return true, if the OS we're running on is msdos like 
       
  2502      (in contrast to unix-like).
       
  2503      This returns true for any of msdos, win32s, win95,
       
  2504      winNT and os/2."
       
  2505 
       
  2506     ^ false
       
  2507 !
       
  2508 
       
  2509 isMSWINDOWSlike
       
  2510     "return true, if running on a MS-Windows like system.
       
  2511      This returns true for any of win32s, win95 and winNT."
       
  2512 
       
  2513     ^ false
       
  2514 !
       
  2515 
       
  2516 isOS2like
       
  2517     "return true, if the OS we're running on is OS2 like.
       
  2518      Only returns true for a plain OS/2 system."
       
  2519 
       
  2520     ^ false
       
  2521 !
       
  2522 
       
  2523 isUNIXlike
       
  2524     "return true, if the OS we're running on is a unix like."
       
  2525 
       
  2526     ^ false
       
  2527 !
       
  2528 
       
  2529 isVMSlike
       
  2530     "return true, if the OS we're running in is VMS (or openVMS)."
       
  2531 
       
  2532     ^ false
       
  2533 !
       
  2534 
       
  2535 maxFileNameLength
       
  2536     "return the max number of characters in a filename.
       
  2537      CAVEAT:
       
  2538 	 Actually, the following is somewhat wrong - some systems
       
  2539 	 support different sizes, depending on the volume.
       
  2540 	 We return a somewhat conservative number here.
       
  2541 	 Another entry, to query for volume specific max
       
  2542 	 will be added in the future."
       
  2543 
       
  2544     self subclassResponsibility
       
  2545 !
       
  2546 
       
  2547 maxPathLength
       
  2548     "return the max number of characters in a pathName."
       
  2549 
       
  2550     self subclassResponsibility
       
  2551 !
       
  2552 
       
  2553 pathSeparator
       
  2554     "return the character which separates items in the PATH variable"
       
  2555 
       
  2556     self subclassResponsibility
       
  2557 !
       
  2558 
       
  2559 platformName
       
  2560     "return a string describing the OS platform very we're running on.
       
  2561      This returns #unix for all unix derivatives.
       
  2562      I.e. it is much less specific than getOSType or getSystemType."
       
  2563 
       
  2564     |os|
       
  2565 
       
  2566     os := self getSystemType.
       
  2567     os = 'win32' ifTrue:[ ^ #win32].
       
  2568     os = 'os2' ifTrue:[ ^ #os2].
       
  2569     os = 'macos' ifTrue:[ ^ #mac].
       
  2570     os = 'VMS' ifTrue:[ ^ #vms].
       
  2571     os = 'openVMS' ifTrue:[ ^ #vms].
       
  2572     ^ #unix
       
  2573 
       
  2574     "
       
  2575      OperatingSystem platformName
       
  2576     "
       
  2577 
       
  2578     "Modified: 20.6.1997 / 17:37:26 / cg"
       
  2579 !
       
  2580 
       
  2581 setLocaleInfo:anInfoDictionary
       
  2582     "set the locale information; if set, this oerrides the OS's settings.
       
  2583      (internal in ST/X only - the OS's settings remain unaffected)
       
  2584      See description of fields in #getLocaleInfo.
       
  2585 
       
  2586      Notice, that (for now), the system does not use this information;
       
  2587      it should be used by applications as required."
       
  2588 
       
  2589     LocaleInfo := anInfoDictionary
       
  2590 
       
  2591     "
       
  2592      |d|
       
  2593 
       
  2594      d := IdentityDictionary new.
       
  2595      d at:#decimalPoint                 put:'.'         .
       
  2596      d at:#thousandsSeparator           put:','         .
       
  2597      d at:#currencySymbol               put:'USD'       .
       
  2598      d at:#monetaryDecimalPoint         put:'.'         .
       
  2599      d at:#monetaryThousandsSeparator   put:'.'         .
       
  2600      d at:#fractionalDigits             put:2           .
       
  2601      d at:#positiveSign                 put:'+'         .
       
  2602      d at:#negativeSign                 put:'-'         .
       
  2603      d at:#positiveSignPrecedesCurrencySymbol put:true          .
       
  2604      d at:#negativeSignPrecedesCurrencySymbol put:false         .
       
  2605      OperatingSystem setLocaleInfo:d
       
  2606     "
       
  2607 !
       
  2608 
       
  2609 supportsChildInterrupts
       
  2610     "return true, if the OS supports childProcess termination signalling
       
  2611      through interrupts (i.e. SIGCHILD)"
       
  2612 
       
  2613     ^ false
       
  2614 
       
  2615     "
       
  2616      OperatingSystem supportsChildInterrupts 
       
  2617     "
       
  2618 !
       
  2619 
       
  2620 supportsIOInterrupts
       
  2621     "return true, if the OS supports IO availability interrupts 
       
  2622      (i.e. SIGPOLL/SIGIO)."
       
  2623 
       
  2624     ^ false
       
  2625 
       
  2626     "
       
  2627      OperatingSystem supportsIOInterrupts 
       
  2628     "
       
  2629 !
       
  2630 
       
  2631 supportsNonBlockingIO
       
  2632     "return true, if the OS supports nonblocking IO."
       
  2633 
       
  2634     ^ false
       
  2635 
       
  2636     "
       
  2637      OperatingSystem supportsNonBlockingIO  
       
  2638     "
       
  2639 !
       
  2640 
       
  2641 supportsSelect
       
  2642     "return true, if the OS supports selecting on multiple
       
  2643      filedescriptors via select.
       
  2644      If false is returned, ProcessorScheduler will poll in 50ms
       
  2645      intervals for I/O becoming ready."
       
  2646 
       
  2647     ^ true
       
  2648 
       
  2649     "
       
  2650      OperatingSystem supportsSelect 
       
  2651     "
       
  2652 ! !
       
  2653 
       
  2654 !AbstractOperatingSystem class methodsFor:'private'!
       
  2655 
       
  2656 osProcessStatusClass
       
  2657     ^ self subclassResponsibility
       
  2658 
       
  2659     "Created: / 12.6.1998 / 16:30:29 / cg"
       
  2660 ! !
       
  2661 
       
  2662 !AbstractOperatingSystem class methodsFor:'shared memory access'!
       
  2663 
       
  2664 shmAttach:id address:addr flags:flags
       
  2665     "low level entry to shmat()-system call.
       
  2666      Not supported on all operatingSystems"
       
  2667 
       
  2668     self subclassResponsibility
       
  2669 
       
  2670     "Modified: 22.4.1996 / 13:15:12 / cg"
       
  2671 !
       
  2672 
       
  2673 shmDetach:addr
       
  2674     "low level entry to shmdt()-system call.
       
  2675      Not supported on all operatingSystems"
       
  2676 
       
  2677     self subclassResponsibility
       
  2678 
       
  2679     "Modified: 22.4.1996 / 13:15:03 / cg"
       
  2680 !
       
  2681 
       
  2682 shmGet:key size:size flags:flags
       
  2683     "low level entry to shmget()-system call.
       
  2684      This is not for public use and not supported with all operatingSystems.
       
  2685      - use the provided wrapper class SharedExternalBytes instead."
       
  2686 
       
  2687     self subclassResponsibility
       
  2688 ! !
       
  2689 
       
  2690 !AbstractOperatingSystem class methodsFor:'time and date'!
       
  2691 
       
  2692 computeDatePartsOf:osTime for:aBlock
       
  2693     "compute year, month and day from the OS time, osTime
       
  2694      and evaluate the argument, a 3-arg block with these.
       
  2695      Conversion is to localtime including any daylight saving adjustments."
       
  2696 
       
  2697     self subclassResponsibility
       
  2698 !
       
  2699 
       
  2700 computeOSTimeFromYear:y month:m day:d hour:h minute:min seconds:s millis:millis
       
  2701     "return the OS-dependent time for the given time and day. 
       
  2702      The arguments are assumed to be in localtime including
       
  2703      any daylight saving adjustings."
       
  2704 
       
  2705     self subclassResponsibility
       
  2706 !
       
  2707 
       
  2708 computeTimeAndDateFrom:osTime
       
  2709     "given an OS-dependent time in osTime, return an Array
       
  2710      containing (full-) year, month, day, hour, minute and seconds,
       
  2711      offset to UTC, daylight savings time flag, milliseconds,
       
  2712      dayInYear (1..) and dayInWeek (1..).
       
  2713      Conversion is to localtime including any daylight saving adjustments."
       
  2714 
       
  2715     self subclassResponsibility
       
  2716 !
       
  2717 
       
  2718 computeTimePartsOf:osTime for:aBlock
       
  2719     "compute hours, minutes, seconds and milliseconds from the osTime 
       
  2720      and evaluate the argument, a 4-arg block with these.
       
  2721      Conversion is to localtime including any daylight saving adjustments."
       
  2722 
       
  2723     self subclassResponsibility
       
  2724 !
       
  2725 
       
  2726 computeUTCTimeAndDateFrom:osTime
       
  2727     "given an OS-dependent time in osTime, return an Array
       
  2728      containing year, month, day, hour, minute and seconds,
       
  2729      offset to UTC, daylight savings time flag, milliseconds,
       
  2730      dayInYear (1..) and dayInWeek (1..).
       
  2731      Conversion is to UTC."
       
  2732 
       
  2733     self subclassResponsibility
       
  2734 !
       
  2735 
       
  2736 computeUTCTimePartsOf:osTime for:aBlock
       
  2737     "compute hours, minutes, seconds and milliseconds from the osTime 
       
  2738      and evaluate the argument, a 4-arg block with these.
       
  2739      Conversion is to UTC."
       
  2740 
       
  2741     self subclassResponsibility
       
  2742 !
       
  2743 
       
  2744 getMillisecondTime
       
  2745     "This returns the millisecond timers value. 
       
  2746      The range is limited to 0..1fffffff (i.e. the SmallInteger range) to avoid
       
  2747      LargeInteger arithmetic when doing timeouts and delays.
       
  2748      Since this value is wrapping around in regular intervals, this can only be used for 
       
  2749      short relative time deltas.
       
  2750      Use the millisecondTimeXXX:-methods to compare and add time deltas - these know about the wrap.
       
  2751 
       
  2752      BAD DESIGN:
       
  2753 	This should be changed to return some instance of RelativeTime,
       
  2754 	and these computations moved there.
       
  2755 
       
  2756      Dont use this method in application code since it is an internal (private)
       
  2757      interface. For compatibility with ST-80, use Time millisecondClockValue.
       
  2758     "
       
  2759 
       
  2760     self subclassResponsibility
       
  2761 !
       
  2762 
       
  2763 getOSTime
       
  2764     "This returns the OS time.
       
  2765      The base of the returned value is not consistent across
       
  2766      different OS's - some return the number of millis since jan, 1st 1970;
       
  2767      others since 1900. The Time classes are prepared for this, and 
       
  2768      converts as appropriate (by using my fromOSTime: conversion methods).
       
  2769 
       
  2770      Dont use this method in application code since it is an internal (private)
       
  2771      interface. For compatibility with ST-80, use Time>>millisecondClockValue.
       
  2772      or use instances of Time, Date or AbsoluteTime to work with.
       
  2773     "
       
  2774 
       
  2775     self subclassResponsibility
       
  2776 !
       
  2777 
       
  2778 maximumMillisecondTimeDelta
       
  2779     "this returns the maximum delta supported by millisecondCounter
       
  2780      based methods. The returned value is half the value at which the
       
  2781      timer wraps."
       
  2782 
       
  2783 %{  /* NOCONTEXT */
       
  2784     RETURN ( __MKSMALLINT(0x0FFFFFFF) );
       
  2785 %}
       
  2786 !
       
  2787 
       
  2788 millisecondDelay:millis
       
  2789     "delay execution for millis milliseconds or until the next event
       
  2790      arrives.
       
  2791      All lower priority threads will also sleep for the duration, 
       
  2792      interrupts (and therefore, higher prio processes) are
       
  2793      still handled. 
       
  2794      Better use a Delay, to only delay the calling thread.
       
  2795      (however, a delay cannot be used in the event handler or scheduler)"
       
  2796 
       
  2797     |now then delta|
       
  2798 
       
  2799     now := self getMillisecondTime.
       
  2800     then := self millisecondTimeAdd:now and:millis.
       
  2801 
       
  2802     [self millisecondTime:then isAfter:now] whileTrue:[
       
  2803 	delta := self millisecondTimeDeltaBetween:then and:now.
       
  2804 	self selectOnAnyReadable:nil writable:nil exception:nil withTimeOut:delta.
       
  2805 	now := self getMillisecondTime.
       
  2806     ]
       
  2807 
       
  2808     "
       
  2809      OperatingSystem millisecondDelay:2000
       
  2810     "
       
  2811 !
       
  2812 
       
  2813 millisecondTime:msTime1 isAfter:msTime2
       
  2814     "return true if msTime1 is after msTime2, false if not.
       
  2815      The two arguments are supposed to be millisecond times 
       
  2816      (such as returned getMillisecondTime) which wrap at 16r1FFFFFFF.
       
  2817 
       
  2818      This should really be moved to some RelativeTime class."
       
  2819 
       
  2820     (msTime1 > msTime2) ifTrue:[
       
  2821 	((msTime1 - msTime2) >= 16r10000000) ifTrue:[
       
  2822 	    ^ false
       
  2823 	].
       
  2824 	^ true
       
  2825     ].
       
  2826     ((msTime2 - msTime1) > 16r10000000) ifTrue:[
       
  2827 	^ true
       
  2828     ].
       
  2829     ^ false
       
  2830 !
       
  2831 
       
  2832 millisecondTimeAdd:msTime1 and:msTime2
       
  2833     "Add two millisecond times (such as returned getMillisecondTime).
       
  2834      The returned value is msTime1 + msTime2 where a wrap occurs at:16r1FFFFFFF.
       
  2835 
       
  2836      This should really be moved to some RelativeTime class."
       
  2837 
       
  2838     |sum|
       
  2839 
       
  2840     sum := msTime1 + msTime2.
       
  2841     (sum > 16r1FFFFFFF) ifTrue:[^ sum - 16r20000000].
       
  2842     (sum < 0) ifTrue:[^ sum + 16r20000000].
       
  2843     ^ sum
       
  2844 !
       
  2845 
       
  2846 millisecondTimeDeltaBetween:msTime1 and:msTime2
       
  2847     "subtract two millisecond times (such as returned getMillisecondTime)
       
  2848      and return the difference. Since milli-times wrap (at 16r01FFFFFFF), 
       
  2849      some special handling is built-in here.
       
  2850      The returned value is msTime1 - msTime2. The returned value is invalid
       
  2851      if the delta is >= 0x10000000.
       
  2852 
       
  2853      This should really be moved to some RelativeTime class;
       
  2854      better yet: create a subclass of Integer named LimitedRangeInteger."
       
  2855 
       
  2856     (msTime1 > msTime2) ifTrue:[
       
  2857 	^ msTime1 - msTime2
       
  2858     ].
       
  2859     ^ msTime1 + 16r10000000 - msTime2
       
  2860 
       
  2861     "
       
  2862      OperatingSystem millisecondTimeAdd:16r0FFFFFFF and:1   
       
  2863      OperatingSystem millisecondTimeAdd:16r0FFFFFFF and:(16 / 3)  
       
  2864      OperatingSystem millisecondTimeAdd:16r0FFFFFFF and:1000   
       
  2865 
       
  2866      OperatingSystem millisecondTimeDeltaBetween:0 and:16r0FFFFFFF  
       
  2867      OperatingSystem millisecondTimeDeltaBetween:(13/3) and:16r0FFFFFFF     
       
  2868      OperatingSystem millisecondTimeDeltaBetween:999 and:16r0FFFFFFF       
       
  2869 
       
  2870      OperatingSystem millisecondTime:0 isAfter:16r0FFFFFFF    
       
  2871      OperatingSystem millisecondTime:(13/3) isAfter:16r0FFFFFFF   
       
  2872      OperatingSystem millisecondTime:999 isAfter:16r0FFFFFFF       
       
  2873 
       
  2874      OperatingSystem millisecondTime:0 isAfter:0          
       
  2875      OperatingSystem millisecondTime:(13/3) isAfter:0  
       
  2876      OperatingSystem millisecondTime:999 isAfter:0       
       
  2877 
       
  2878      OperatingSystem millisecondTime:1 isAfter:0        
       
  2879      OperatingSystem millisecondTime:(13/3) isAfter:2
       
  2880      OperatingSystem millisecondTime:999 isAfter:900       
       
  2881 
       
  2882      |t1 t2|
       
  2883 
       
  2884      t1 := Time millisecondClockValue.
       
  2885      (Delay forMilliseconds:1) wait.   
       
  2886      t2 := Time millisecondClockValue.
       
  2887      OperatingSystem millisecondTimeDeltaBetween:t2 and:t1 
       
  2888     "
       
  2889 !
       
  2890 
       
  2891 sleep:numberOfSeconds
       
  2892     "{ Pragma: +optSpace }"
       
  2893 
       
  2894     "cease ANY action for some time. This suspends the whole smalltalk
       
  2895      (unix-) process for some time.
       
  2896      Not really useful since not even low-prio processes and interrupt
       
  2897      handling will run during the sleep.
       
  2898      Use either OperatingSystem>>millisecondDelay: (which makes all
       
  2899      threads sleep, but handles interrupts) or use a Delay (which makes
       
  2900      only the calling thread sleep)."
       
  2901 
       
  2902     self subclassResponsibility
       
  2903 ! !
       
  2904 
       
  2905 !AbstractOperatingSystem class methodsFor:'users & groups'!
       
  2906 
       
  2907 getEffectiveGroupID
       
  2908     "{ Pragma: +optSpace }"
       
  2909 
       
  2910     "return the current users (thats you) effective numeric group id.
       
  2911      This is only different from getGroupID, if you have ST/X running
       
  2912      as a setuid program (of which you should think about twice)."
       
  2913 
       
  2914     ^ self getGroupID
       
  2915 
       
  2916     "
       
  2917      OperatingSystem getEffectiveGroupID
       
  2918     "
       
  2919 !
       
  2920 
       
  2921 getEffectiveUserID
       
  2922     "{ Pragma: +optSpace }"
       
  2923 
       
  2924     "return the current users (thats you) effective numeric user id.
       
  2925      This is only different from getUserID, if you have ST/X running
       
  2926      as a setuid program (of which you should think about twice)."
       
  2927 
       
  2928     ^ self getUserID
       
  2929 
       
  2930     "
       
  2931      OperatingSystem getEffectiveUserID
       
  2932     "
       
  2933 !
       
  2934 
       
  2935 getFullUserName
       
  2936     "{ Pragma: +optSpace }"
       
  2937 
       
  2938     "return a string with the users full name (thats you) - if available.
       
  2939      If not, return the login name as a fallBack."
       
  2940 
       
  2941     ^ self getFullUserNameFromID:(self getUserID)
       
  2942 
       
  2943     "
       
  2944      OperatingSystem getFullUserName 
       
  2945     "
       
  2946 
       
  2947     "Modified: 24.1.1997 / 11:31:55 / cg"
       
  2948 !
       
  2949 
       
  2950 getFullUserNameFromID:userID
       
  2951     "{ Pragma: +optSpace }"
       
  2952 
       
  2953     "return a string with the users full name - if available.
       
  2954      If not, return the login name as a fallBack."
       
  2955 
       
  2956     ^ self getUserNameFromID:userID
       
  2957 
       
  2958     "
       
  2959      OperatingSystem getFullUserNameFromID:0 
       
  2960      OperatingSystem getFullUserNameFromID:(OperatingSystem getUserID)  
       
  2961 
       
  2962      OperatingSystem getUserNameFromID:(OperatingSystem getUserID)  
       
  2963     "
       
  2964 
       
  2965     "Modified: 15.7.1996 / 12:44:21 / cg"
       
  2966 !
       
  2967 
       
  2968 getGroupID
       
  2969     "{ Pragma: +optSpace }"
       
  2970 
       
  2971     "return the current users (thats you) numeric group id"
       
  2972 
       
  2973     ^ 1 "/ just a dummy for systems which do not have userIDs
       
  2974 
       
  2975     "
       
  2976      OperatingSystem getGroupID
       
  2977     "
       
  2978 !
       
  2979 
       
  2980 getGroupNameFromID:aNumber
       
  2981     "{ Pragma: +optSpace }"
       
  2982 
       
  2983     "return the group-name-string for a given numeric group-id"
       
  2984 
       
  2985     ^ '???' "/ just a dummy for systems which do not have groups
       
  2986 
       
  2987     "
       
  2988      OperatingSystem getGroupNameFromID:0
       
  2989      OperatingSystem getGroupNameFromID:10
       
  2990     "
       
  2991 !
       
  2992 
       
  2993 getHomeDirectory
       
  2994     "{ Pragma: +optSpace }"
       
  2995 
       
  2996     "return the name of the users home directory
       
  2997      (i.e. yours)"
       
  2998 
       
  2999     ^ self getEnvironment:'HOME'
       
  3000 
       
  3001     "
       
  3002      OperatingSystem getHomeDirectory
       
  3003     "
       
  3004 
       
  3005     "Modified: 24.1.1997 / 11:32:13 / cg"
       
  3006 !
       
  3007 
       
  3008 getLoginName
       
  3009     "{ Pragma: +optSpace }"
       
  3010 
       
  3011     "return a string with the users login name (thats yours)"
       
  3012 
       
  3013     self subclassResponsibility
       
  3014 !
       
  3015 
       
  3016 getUserID
       
  3017     "{ Pragma: +optSpace }"
       
  3018 
       
  3019     "return the current users (thats you) numeric user id"
       
  3020 
       
  3021     ^ 1 "just a dummy for systems which do not have userIDs"
       
  3022 
       
  3023     "
       
  3024      OperatingSystem getUserID
       
  3025     "
       
  3026 !
       
  3027 
       
  3028 getUserNameFromID:aNumber
       
  3029     "{ Pragma: +optSpace }"
       
  3030 
       
  3031     "return the user-name-string for a given numeric user-id.
       
  3032      This is the login name, not the fullName."
       
  3033 
       
  3034     "/ fallBack dummy
       
  3035 
       
  3036     aNumber == self getUserID ifTrue:[
       
  3037 	^ self getLoginName
       
  3038     ].
       
  3039 
       
  3040     ^ '? (' , aNumber printString , ')'
       
  3041 
       
  3042     "
       
  3043      OperatingSystem getUserNameFromID:0
       
  3044      OperatingSystem getUserNameFromID:100
       
  3045      OperatingSystem getUserNameFromID:9991 
       
  3046     "
       
  3047 !
       
  3048 
       
  3049 userInfoOf:aNameOrID
       
  3050     "{ Pragma: +optSpace }"
       
  3051 
       
  3052     "return a dictionary filled with userinfo. The argument can be either
       
  3053      a string with the users name or its numeric id.
       
  3054      Notice, that not all systems provide (all of) this info;
       
  3055      DOS systems return nothing; 
       
  3056      non-SYSV4 systems have no age/comment.
       
  3057      Portable applications may want to check the systemType and NOT depend
       
  3058      on all keys to be present in the returned dictionary.
       
  3059      Another notice: on some systems (SYSV4), the gecos field includes multiple
       
  3060      entries (i.e. not just the name), separated by commas. You may want to
       
  3061      extract any substring, up to the first comma to get the real life name."
       
  3062 
       
  3063     |info|
       
  3064 
       
  3065     "/ fallBack dummy
       
  3066     info := IdentityDictionary new.
       
  3067     info at:#name put:(self getLoginName).
       
  3068     info at:#dir put:(self getHomeDirectory).
       
  3069     ^ info
       
  3070 
       
  3071     "
       
  3072      OperatingSystem userInfoOf:'root'
       
  3073      OperatingSystem userInfoOf:1
       
  3074      OperatingSystem userInfoOf:'claus' 
       
  3075      OperatingSystem userInfoOf:'fooBar' 
       
  3076      OperatingSystem userInfoOf:(OperatingSystem getUserID)
       
  3077     "
       
  3078 ! !
       
  3079 
       
  3080 !AbstractOperatingSystem class methodsFor:'waiting for events'!
       
  3081 
       
  3082 blockingChildProcessWait
       
  3083      "return true, if childProcessWait: blocks, if no children are ready.
       
  3084       On those systems, we must be somewhat careful when looking out for
       
  3085       a subprocesses status (to avoid blocking)."
       
  3086 
       
  3087     ^ true
       
  3088 !
       
  3089 
       
  3090 childProcessWait:blocking pid:pidToWait
       
  3091     "{ Pragma: +optSpace }"
       
  3092 
       
  3093     "get status changes from child processes.
       
  3094      Return an OSProcessStatus or nil, if no process has terminated.
       
  3095      If blocking is true, we wait until a process changed state, 
       
  3096      otherwise we return immediately.
       
  3097      Note that win32 needs to know the HANDLE of the process on which 
       
  3098      it waits.  In case of an error, THIS ALWAYS WAITS and then times out."
       
  3099 
       
  3100     self subclassResponsibility
       
  3101 !
       
  3102 
       
  3103 numAvailableForReadOn:fd
       
  3104     "return the number of bytes available for reading, without blocking."
       
  3105 
       
  3106     "/ fallBack for systems which do not provide this info
       
  3107     ^ (self readCheck:fd) ifTrue:[1] ifFalse:[0]
       
  3108 !
       
  3109 
       
  3110 readCheck:fd
       
  3111     "return true, if data is available on a filedescriptor 
       
  3112      (i.e. read is possible without blocking).
       
  3113      This depends on a working select or FIONREAD to be provided by the OS."
       
  3114 
       
  3115     self supportsSelect ifFalse:[
       
  3116 	"/ mhmh - what should we do then ?
       
  3117 	"/ For now, return true as if data was present,
       
  3118 	"/ and let the thread fall into the read.
       
  3119 	"/ It will then (hopefully) be desceduled there and
       
  3120 	"/ effectively polling for input.
       
  3121 
       
  3122 	^ true
       
  3123     ].
       
  3124 
       
  3125     (self selectOnAnyReadable:(Array with:fd)
       
  3126 		     writable:nil
       
  3127 		    exception:nil
       
  3128 		  withTimeOut:0) == fd
       
  3129 	ifTrue:[^ true].
       
  3130     ^ false
       
  3131 !
       
  3132 
       
  3133 readWriteCheck:fd
       
  3134     "return true, if filedescriptor can be read or written without blocking.
       
  3135      This is actually only used with sockets, to wait for a connect to
       
  3136      be finished."
       
  3137 
       
  3138     self supportsSelect ifFalse:[
       
  3139         "/ mhmh - what should we do then ?
       
  3140         "/ For now, return true as if data was present,
       
  3141         "/ and let the thread fall into the write.
       
  3142         "/ It will then (hopefully) be desceduled there and
       
  3143         "/ effectively polling for output.
       
  3144         ^ true
       
  3145     ].
       
  3146 
       
  3147     (self selectOnAnyReadable:(Array with:fd)
       
  3148                      writable:(Array with:fd)
       
  3149                     exception:nil
       
  3150                   withTimeOut:0) == fd
       
  3151         ifTrue:[^ true].
       
  3152     ^ false
       
  3153 !
       
  3154 
       
  3155 selectOn:fd1 and:fd2 withTimeOut:millis
       
  3156     "wait for any fd to become ready; timeout after t milliseconds.
       
  3157      A zero timeout-time will immediately return (i.e. poll).
       
  3158      Return fd if i/o ok, nil if timed-out or interrupted.
       
  3159      Obsolete:
       
  3160 	This is a leftover method and will vanish."
       
  3161 
       
  3162     ^ self selectOnAnyReadable:(Array with:fd1 with:fd2)
       
  3163 		      writable:(Array with:fd1 with:fd2)
       
  3164 		     exception:nil
       
  3165 		   withTimeOut:millis
       
  3166 !
       
  3167 
       
  3168 selectOn:fd withTimeOut:millis
       
  3169     "wait for aFileDesriptor to become ready; timeout after t milliseconds.
       
  3170      Return true, if i/o ok, false if timed-out or interrupted.
       
  3171      With 0 as timeout argument, this can be used to check for availability
       
  3172      of read-data.
       
  3173      Experimental."
       
  3174 
       
  3175     ^ self selectOnAnyReadable:(Array with:fd)
       
  3176 		      writable:(Array with:fd)
       
  3177 		     exception:nil
       
  3178 		   withTimeOut:millis
       
  3179 !
       
  3180 
       
  3181 selectOnAny:fdArray withTimeOut:millis
       
  3182     "wait for any fd in fdArray (an Array of integers) to become ready;
       
  3183      timeout after t milliseconds. An empty set will always wait.
       
  3184      Return first ready fd if i/o ok, nil if timed-out or interrupted.
       
  3185      Experimental."
       
  3186 
       
  3187     ^ self selectOnAnyReadable:fdArray
       
  3188 		      writable:fdArray
       
  3189 		     exception:nil
       
  3190 		   withTimeOut:millis
       
  3191 !
       
  3192 
       
  3193 selectOnAnyReadable:fdArray withTimeOut:millis
       
  3194     "wait for any fd in fdArray (an Array of integers) to become ready for 
       
  3195      reading. Timeout after t milliseconds. An empty set will always wait.
       
  3196      A zero timeout-time will immediately return (i.e. poll).
       
  3197      Return first ready fd if i/o ok, nil if timed-out or interrupted.
       
  3198      Experimental."
       
  3199 
       
  3200     ^ self selectOnAnyReadable:fdArray 
       
  3201 		      writable:nil 
       
  3202 		     exception:nil
       
  3203 		   withTimeOut:millis
       
  3204 !
       
  3205 
       
  3206 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
       
  3207     "wait for any fd in readFdArray (an Array of integers) to become ready for 
       
  3208      reading, writeFdArray to become ready for writing, or exceptFdArray to 
       
  3209      arrive exceptional data (i.e. out-of-band data).
       
  3210      Timeout after t milliseconds or, if the timeout time is 0, immediately..
       
  3211      Empty fd-sets will always wait. Zero time can be used to poll file-
       
  3212      descriptors (i.e. to check if I/O possible without blocking).
       
  3213      Return first ready fd if I/O ok, nil if timed-out or interrupted."
       
  3214 
       
  3215     self subclassResponsibility
       
  3216 !
       
  3217 
       
  3218 setBlocking:aBoolean on:fd
       
  3219     "{ Pragma: +optSpace }"
       
  3220 
       
  3221     "set/clear the blocking attribute - if set (which is the default)
       
  3222      a read on the fileDescriptor will block until data is available.
       
  3223      If cleared, a read operation will immediately return with a value of
       
  3224      nil."
       
  3225 
       
  3226     self subclassResponsibility
       
  3227 !
       
  3228 
       
  3229 writeCheck:fd
       
  3230     "return true, if filedescriptor can be written without blocking"
       
  3231 
       
  3232     self supportsSelect ifFalse:[
       
  3233 	"/ mhmh - what should we do then ?
       
  3234 	"/ For now, return true as if data was present,
       
  3235 	"/ and let the thread fall into the write.
       
  3236 	"/ It will then (hopefully) be desceduled there and
       
  3237 	"/ effectively polling for output.
       
  3238 	^ true
       
  3239     ].
       
  3240 
       
  3241     (self selectOnAnyReadable:nil
       
  3242 		     writable:(Array with:fd)
       
  3243 		    exception:nil
       
  3244 		  withTimeOut:0) == fd
       
  3245 	ifTrue:[^ true].
       
  3246     ^ false
       
  3247 ! !
       
  3248 
       
  3249 !AbstractOperatingSystem class methodsFor:'documentation'!
       
  3250 
       
  3251 version
       
  3252     ^ '$Header: /cvs/stx/stx/libbasic/AbstractOperatingSystem.st,v 1.1 1998-06-15 14:52:33 cg Exp $'
       
  3253 ! !
       
  3254 AbstractOperatingSystem initialize!