--- a/UnixOperatingSystem.st Wed Oct 26 23:35:39 2016 +0100
+++ b/UnixOperatingSystem.st Fri Nov 18 20:48:04 2016 +0000
@@ -989,35 +989,51 @@
documentation
"
- this class realizes access to most (all?) required operating system services;
- some of it is very specific for unix, so do not depend on
- things available here in your applications
- - some may not be found in other OS's or be slightly different ...
-
- (On the other hand: I do not want to hide all features
- from you - in some situations it MAY be interesting to be
- able to get down to a select or fork system call easily (at least on Unix systems).
- You decide - portability vs. functionality)
-
+ This class realizes access to most (all?) required operating system services.
+ At startup, the global 'OperatingSystem' will be bound to either me, or one of
+ my sibling classes, Win32OperatingSystem, VMSOperatinSystem or OSXOperatingSystem.
+
+ Never access UnixOperatingSystem directly. Always only refer to OperatingSystem,
+ if at all. Most functionality is actually used indirectly, via the Filename, PipeStream
+ or Socket classes.
+
+ Some of the functions are specific for unix, some may not be found in other OS's
+ or behave slightly different, returning different data.
+
+ For portable programs, only rely on protocol which is found in my abstract
+ superclass, and will therefore also be found in my correspnding sibling os-classes
+ (i.e. Win32OperatingSystem).
+ If you need os-specific functionality, surround it by a condition, such as
+ OperatingSystem isUNIXlike or OperatingSystem isMSWINDOWSlike.
+
+ On the other hand: I do not want to hide all features
+ from you - in some situations it MAY be interesting to be
+ able to get down to a select or fork system call easily (at least on Unix systems).
+ You decide - portability vs. functionality.
+
+ Notice, that on Unix systems, the Win32OperatingSystem class is not even loaded,
+ and vice versa. So you may have to open a changes browser on the other class, to check
+ how the corresponding function operates in the other os.
+
[Class variables:]
- HostName <String> remembered hostname
-
- DomainName <String> remembered domainname
-
- SlowFork <Boolean> if set, fork and popen are avoided;
- (more or less obsolete now)
-
-
- CurrentDirectory <String> remembered currentDirectories path
+ HostName <String> remembered hostname
+
+ DomainName <String> remembered domainname
+
+ SlowFork <Boolean> if set, fork and popen are avoided;
+ (more or less obsolete now)
+
+
+ CurrentDirectory <String> remembered currentDirectories path
[author:]
- Claus Gittinger
+ Claus Gittinger
[see also:]
- OSProcessStatus
- Filename Date Time
- ExternalStream FileStream PipeStream Socket
+ OSProcessStatus
+ Filename Date Time
+ ExternalStream FileStream PipeStream Socket
"
!
@@ -3525,13 +3541,14 @@
fork
"fork a new (HEAVY-weight) unix process.
Not supported with MSDOS & VMS systems.
- Dont confuse this with Block>>fork, which creates
- lightweight smalltalk processes. This method will return
- 0 to the child process, and a non-zero number (which is the childs
- unix-process-id) to the parent (original) process.
-
- In normal situations, you dont need to use this low level entry; see
- #startProcess: and #executCommand: for higher level interfaces."
+ Don't confuse this with Block>>fork, which creates
+ lightweight smalltalk processes.
+ This method will return 0 to the child process,
+ and a non-zero number (which is the childs unix-process-id)
+ to the parent (original) process.
+
+ In normal situations, you don't need to use this low level entry;
+ see #startProcess: and #executeCommand: for higher level interfaces."
%{ /* NOCONTEXT */
int pid;
@@ -3545,13 +3562,16 @@
^ UnsupportedOperationSignal raise
"
- |id|
-
+ |id t1 t2 t3|
+
+ t1 := Timestamp now.
id := OperatingSystem fork.
id == 0 ifTrue:[
- 'I am the child process' printCR.
- OperatingSystem exit
- ]
+ 'Child t=' print. (Timestamp now - t1) printCR.
+ 'I am the child process' printCR.
+ OperatingSystem exit
+ ].
+ 'Parent t=' print. (Timestamp now - t1) printCR.
"
!
@@ -3632,6 +3652,127 @@
startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream
errorTo:anExternalErrStream auxFrom:anAuxiliaryStream
+ environment:anEvironmentDictionary inDirectory:dir newPgrp:newPgrp showWindow:ignoredHere
+
+ "start executing the OS command as specified by the argument, aCommandString
+ as a separate process; do not wait for the command to finish.
+ If aCommandString is a String, the commandString is passed to a shell for execution
+ - see the description of 'sh -c' in your UNIX manual ('cmd.com' in your MSDOS manual).
+ If aCommandString is an Array, the first element is the command to be executed,
+ and the other elements are the arguments to the command. No shell is invoked in this case.
+ The command gets stdIn, stdOut and stdErr assigned from the arguments;
+ each may be nil.
+ Return the processId if successful, nil otherwise.
+ Use #monitorPid:action: for synchronization and exec status return,
+ or #killProcess: to stop it."
+
+ |nullStream in out err shellAndArgs rslt auxFd|
+
+ aCommandString isNil ifTrue:[^ nil].
+
+ (in := anExternalInStream) isNil ifTrue:[
+ nullStream := Filename nullDevice readWriteStream.
+ in := nullStream.
+ ].
+ (out := anExternalOutStream) isNil ifTrue:[
+ nullStream isNil ifTrue:[nullStream := Filename nullDevice writeStream].
+ out := nullStream.
+ ].
+ (err := anExternalErrStream) isNil ifTrue:[
+ err := out
+ ].
+ anAuxiliaryStream notNil ifTrue:[
+ auxFd := anAuxiliaryStream fileDescriptor
+ ].
+
+ shellAndArgs := self commandAndArgsForOSCommand:aCommandString.
+
+ rslt := self
+ exec:(shellAndArgs at:1)
+ withArguments:(shellAndArgs at:2)
+ environment:anEvironmentDictionary
+ fileDescriptors:(Array with:in fileDescriptor
+ with:out fileDescriptor
+ with:err fileDescriptor
+ with:auxFd)
+ fork:true
+ newPgrp:newPgrp
+ inDirectory:dir.
+
+ nullStream notNil ifTrue:[
+ nullStream close.
+ ].
+
+ ^ rslt
+
+ "blocking at current prio (i.e. only higher prio threads execute):
+
+ OperatingSystem executeCommand:'ls -l > out'.
+ OperatingSystem executeCommand:#('/bin/ls' '-l') outputTo:Transcript.
+ "
+
+ "non-blocking (lower prio threads continue):
+
+ |in out err pid sema|
+
+ in := 'out' asFilename readStream.
+ out := 'out2' asFilename writeStream.
+ err := 'err' asFilename writeStream.
+
+ sema := Semaphore new.
+ pid := OperatingSystem startProcess:'sleep 10; grep drw' inputFrom:in outputTo:out errorTo:err.
+
+ The following will no longer work. monitorPid has disappeared
+
+ pid notNil ifTrue:[
+ Processor monitorPid:pid action:[:osStatus | sema signal ].
+ ].
+ in close.
+ out close.
+ err close.
+ sema wait.
+ Transcript showCR:'finished'
+ "
+
+ "
+ |pid sema|
+
+ sema := Semaphore new.
+
+ Processor
+ monitor:[
+ pid := OperatingSystem startProcess:'(sleep 2; ls -l) > out 2>err'
+ ]
+ action:[:osStatus | sema signal ].
+
+ sema wait.
+ Transcript showCR:'finished'
+ "
+
+ "
+ |pid sema|
+
+ sema := Semaphore new.
+
+ Processor
+ monitor:[
+ pid := OperatingSystem startProcess:'(sleep 1; echo 1; sleep 9; ls -l) > out 2>err'
+ ]
+ action:[:osStatus | sema signal ].
+
+ Delay waitForSeconds:2.
+ OperatingSystem terminateProcess:pid.
+ Transcript showCR:'terminated'
+ "
+
+ "Modified: / 21.3.1997 / 10:04:35 / dq"
+ "Modified: / 15.7.1997 / 16:03:51 / stefan"
+ "Modified: / 5.6.1998 / 19:03:51 / cg"
+ "Created: / 12.11.1998 / 14:39:20 / cg"
+!
+
+startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream
+ errorTo:anExternalErrStream auxFrom:anAuxiliaryStream
environment:anEvironmentDictionary inDirectory:dir showWindow:ignoredHere
"start executing the OS command as specified by the argument, aCommandString
@@ -3646,109 +3787,10 @@
Use #monitorPid:action: for synchronization and exec status return,
or #killProcess: to stop it."
- |nullStream in out err shellAndArgs rslt auxFd|
-
- aCommandString isNil ifTrue:[^ nil].
-
- (in := anExternalInStream) isNil ifTrue:[
- nullStream := Filename nullDevice readWriteStream.
- in := nullStream.
- ].
- (out := anExternalOutStream) isNil ifTrue:[
- nullStream isNil ifTrue:[nullStream := Filename nullDevice writeStream].
- out := nullStream.
- ].
- (err := anExternalErrStream) isNil ifTrue:[
- err := out
- ].
- anAuxiliaryStream notNil ifTrue:[
- auxFd := anAuxiliaryStream fileDescriptor
- ].
-
- shellAndArgs := self commandAndArgsForOSCommand:aCommandString.
-
- rslt := self
- exec:(shellAndArgs at:1)
- withArguments:(shellAndArgs at:2)
- environment:anEvironmentDictionary
- fileDescriptors:(Array with:in fileDescriptor
- with:out fileDescriptor
- with:err fileDescriptor
- with:auxFd)
- fork:true
- newPgrp:true "/ false
- inDirectory:dir.
-
- nullStream notNil ifTrue:[
- nullStream close.
- ].
-
- ^ rslt
-
- "blocking at current prio (i.e. only higher prio threads execute):
-
- OperatingSystem executeCommand:'ls -l > out'.
- OperatingSystem executeCommand:#('/bin/ls' '-l') outputTo:Transcript.
- "
-
- "non-blocking (lower prio threads continue):
-
- |in out err pid sema|
-
- in := 'out' asFilename readStream.
- out := 'out2' asFilename writeStream.
- err := 'err' asFilename writeStream.
-
- sema := Semaphore new.
- pid := OperatingSystem startProcess:'sleep 10; grep drw' inputFrom:in outputTo:out errorTo:err.
-
- The following will no longer work. monitorPid has disappeared
-
- pid notNil ifTrue:[
- Processor monitorPid:pid action:[:osStatus | sema signal ].
- ].
- in close.
- out close.
- err close.
- sema wait.
- Transcript showCR:'finished'
- "
-
- "
- |pid sema|
-
- sema := Semaphore new.
-
- Processor
- monitor:[
- pid := OperatingSystem startProcess:'(sleep 2; ls -l) > out 2>err'
- ]
- action:[:osStatus | sema signal ].
-
- sema wait.
- Transcript showCR:'finished'
- "
-
- "
- |pid sema|
-
- sema := Semaphore new.
-
- Processor
- monitor:[
- pid := OperatingSystem startProcess:'(sleep 1; echo 1; sleep 9; ls -l) > out 2>err'
- ]
- action:[:osStatus | sema signal ].
-
- Delay waitForSeconds:2.
- OperatingSystem terminateProcess:pid.
- Transcript showCR:'terminated'
- "
-
- "Modified: / 21.3.1997 / 10:04:35 / dq"
- "Modified: / 15.7.1997 / 16:03:51 / stefan"
- "Modified: / 5.6.1998 / 19:03:51 / cg"
- "Created: / 12.11.1998 / 14:39:20 / cg"
+ ^ self
+ startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream
+ errorTo:anExternalErrStream auxFrom:anAuxiliaryStream
+ environment:anEvironmentDictionary inDirectory:dir newPgrp:true showWindow:ignoredHere
! !
!UnixOperatingSystem class methodsFor:'executing OS commands-queries'!
@@ -3829,7 +3871,7 @@
].
"/ command is a single word, not relative and not absolute.
- "/ search along PATH environment variable to see what a shoell would do.
+ "/ search along PATH environment variable to see what a shell would do.
path := self getEnvironment:'PATH'.
path notEmptyOrNil ifTrue:[
(path asCollectionOfSubstringsSeparatedBy:self pathSeparator) do:[:eachPathComponent |
@@ -6106,7 +6148,7 @@
defaultSignal:signalNumber
"revert to the default action on arrival of a (Unix-)signal.
- Dont confuse Unix signals with smalltalk signals.
+ Don't confuse Unix signals with smalltalk signals.
WARNING: for some signals, it is no good idea to revert to default;
for example, the default for SIGINT (i.e. ^C) is to exit; while the
default for SIGQUIT (^ \) is to dump core.
@@ -6118,8 +6160,8 @@
if (__isSmallInteger(signalNumber)) {
#ifdef SIG_DFL
- signal(__intVal(signalNumber), SIG_DFL);
- RETURN (self);
+ signal(__intVal(signalNumber), SIG_DFL);
+ RETURN (self);
#endif
}
%}.
@@ -6175,7 +6217,7 @@
disableSignal:signalNumber
"disable (Unix-) signal processing for signalNumber.
- Dont confuse Unix signals with smalltalk signals.
+ Don't confuse Unix signals with smalltalk signals.
WARNING: for some signals, it is no good idea to disable
them; for example, disabling the SIGINT signal turns off ^C
handling.
@@ -6187,23 +6229,23 @@
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
if (signalNumber.isSmallInteger()) {
- int sigNo = signalNumber.intValue();
-
- if (sigNo != 0) {
- java.lang.System.err.println("ignored disable-signal: "+sigNo);
- }
- return context._RETURN(self);
+ int sigNo = signalNumber.intValue();
+
+ if (sigNo != 0) {
+ java.lang.System.err.println("ignored disable-signal: "+sigNo);
+ }
+ return context._RETURN(self);
}
#else
if (__isSmallInteger(signalNumber)) {
- int sigNo = __intVal(signalNumber);
-
- if (sigNo == 0) {
- RETURN (self);
- }
+ int sigNo = __intVal(signalNumber);
+
+ if (sigNo == 0) {
+ RETURN (self);
+ }
# ifdef SIG_IGN
- signal(sigNo, SIG_IGN);
- RETURN (self);
+ signal(sigNo, SIG_IGN);
+ RETURN (self);
# endif
}
#endif
@@ -9054,7 +9096,7 @@
"return a string giving the type of system we're running on.
This is almost the same as getOSType, but the returned string
is slightly different for some systems (i.e. iris vs. irix).
- Don't depend on this - use getOSType. I dont really see a point
+ Don't depend on this - use getOSType. I don't really see a point
here ...
(except for slight differences between next/mach and other machs)"
@@ -9076,7 +9118,7 @@
%}.
sys isNil ifTrue:[
- ^ self getOSType
+ ^ self getOSType
].
^ sys
@@ -10726,7 +10768,7 @@
}
/*
- * nope - I really dont know who you are.
+ * nope - I really don't know who you are.
*/
if (! name || (name[0] == 0) ) {
name = "you";
@@ -13241,94 +13283,88 @@
type := OperatingSystem socketTypeCodeOf:typeArg.
proto := self protocolCodeOf:protoArg.
serviceNameArg notNil ifTrue:[
- serviceName := serviceNameArg printString. "convert integer port numbers"
+ serviceName := serviceNameArg printString. "convert integer port numbers"
].
hostName isNil ifTrue:[
- encodedHostName := nil.
+ encodedHostName := nil.
] ifFalse:[
- encodedHostName := hostName utf8Encoded.
+ encodedHostName := hostName utf8Encoded.
].
(encodedHostName ~~ hostName and:[OperatingSystem getCodeset ~~ #utf8]) ifTrue:[
- "hostName is not plain ASCII - so this is an IDN domain name. Have to ensure, that the locale is UTF-8.
- Block interrupt to not affect other ST/X processes while the locale is changed."
- |interruptsBlocked oldLocale|
-
- interruptsBlocked := OperatingSystem blockInterrupts.
- oldLocale := OperatingSystem setLocale:#'LC_CTYPE' to:nil.
- OperatingSystem setLocale:#'LC_CTYPE' to:'en_US.UTF-8'.
- result := self primGetAddressInfo:encodedHostName serviceName:serviceName domainCode:domain socketTypeCode:type protocolCode:proto flags:flags.
- OperatingSystem setLocale:#'LC_CTYPE' to:oldLocale.
- interruptsBlocked ifFalse:[
- OperatingSystem unblockInterrupts.
- ].
+ "hostName is not plain ASCII - so this is an IDN domain name. Have to ensure, that the locale is UTF-8.
+ Block interrupt to not affect other ST/X processes while the locale is changed."
+ |interruptsBlocked oldLocale|
+
+ interruptsBlocked := OperatingSystem blockInterrupts.
+ oldLocale := OperatingSystem setLocale:#'LC_CTYPE' to:nil.
+ OperatingSystem setLocale:#'LC_CTYPE' to:'en_US.UTF-8'.
+ result := self primGetAddressInfo:encodedHostName serviceName:serviceName domainCode:domain socketTypeCode:type protocolCode:proto flags:flags.
+ OperatingSystem setLocale:#'LC_CTYPE' to:oldLocale.
+ interruptsBlocked ifFalse:[
+ OperatingSystem unblockInterrupts.
+ ].
] ifFalse:[
- result := self primGetAddressInfo:encodedHostName serviceName:serviceName domainCode:domain socketTypeCode:type protocolCode:proto flags:flags.
+ result := self primGetAddressInfo:encodedHostName serviceName:serviceName domainCode:domain socketTypeCode:type protocolCode:proto flags:flags.
].
result isArray ifFalse:[
- |request|
- request := SocketAddressInfo new
- domain:domainArg;
- type:typeArg;
- protocol:protoArg;
- canonicalName:hostName;
- serviceName:serviceName.
- ^ (HostNameLookupError new
- parameter:result;
- messageText:' - ', (result printString);
- request:request) raiseRequest.
+ |request|
+ request := SocketAddressInfo new
+ domain:domainArg;
+ type:typeArg;
+ protocol:protoArg;
+ canonicalName:hostName;
+ serviceName:serviceName.
+ ^ (HostNameLookupError new
+ parameter:result;
+ messageText:' - ', (result printString);
+ request:request) raiseRequest.
].
1 to:result size do:[:i |
- |entry dom info|
-
- entry := result at:i.
-
- info := SocketAddressInfo new.
- info
- flags:(entry at:1);
- domain:(dom := OperatingSystem domainSymbolOf:(entry at:2));
- type:(OperatingSystem socketTypeSymbolOf:(entry at:3));
- protocol:(self protocolSymbolOf:(entry at:4));
- socketAddress:((SocketAddress newDomain:dom) fromBytes:(entry at:5));
- canonicalName:(entry at:6).
-
- result at:i put:info.
+ |entry dom info|
+
+ entry := result at:i.
+
+ info := SocketAddressInfo new.
+ info
+ flags:(entry at:1);
+ domain:(dom := OperatingSystem domainSymbolOf:(entry at:2));
+ type:(OperatingSystem socketTypeSymbolOf:(entry at:3));
+ protocol:(self protocolSymbolOf:(entry at:4));
+ socketAddress:((SocketAddress newDomain:dom) fromBytes:(entry at:5));
+ canonicalName:(entry at:6).
+
+ result at:i put:info.
].
^ result
"
self getAddressInfo:'localhost' serviceName:nil
- domain:nil type:nil protocol:nil flags:nil
+ domain:nil type:nil protocol:nil flags:nil
self getAddressInfo:'localhost' serviceName:nil
- domain:#inet type:#stream protocol:nil flags:nil
+ domain:#inet type:#stream protocol:nil flags:nil
self getAddressInfo:'localhost' serviceName:nil
- domain:#inet type:#stream protocol:#tcp flags:nil
+ domain:#inet type:#stream protocol:#tcp flags:nil
self getAddressInfo:'blurb.exept.de' serviceName:nil
- domain:#inet type:nil protocol:nil flags:nil
+ domain:#inet type:nil protocol:nil flags:nil
self getAddressInfo:'1.2.3.4' serviceName:'bla'
- domain:#inet type:nil protocol:nil flags:nil
+ domain:#inet type:nil protocol:nil flags:nil
self getAddressInfo:'localhost' serviceName:'echo'
- domain:#inet type:nil protocol:nil flags:nil
+ domain:#inet type:nil protocol:nil flags:nil
self getAddressInfo:nil serviceName:'echo'
- domain:#inet type:nil protocol:nil flags:nil
+ domain:#inet type:nil protocol:nil flags:nil
self getAddressInfo:nil serviceName:nil
- domain:#inet type:nil protocol:nil flags:nil
+ domain:#inet type:nil protocol:nil flags:nil
self getAddressInfo:'www.google.de' serviceName:nil
- domain:nil type:nil protocol:nil flags:nil
- self getAddressInfo:'www.exept.de' serviceName:nil
- domain:nil type:nil protocol:nil flags:nil
+ domain:nil type:nil protocol:nil flags:nil
self getAddressInfo:'www.exept.de' serviceName:nil
- domain:#'AF_INET' type:nil protocol:nil flags:nil
+ domain:nil type:nil protocol:nil flags:nil
self getAddressInfo:'www.exept.de' serviceName:nil
-<<<<<<< UnixOperatingSystem.st
+ domain:#'AF_INET' type:nil protocol:nil flags:nil
+ self getAddressInfo:'www.exept.de' serviceName:nil
domain:#'AF_INET6' type:nil protocol:nil flags:nil
- self getAddressInfo:'www.baden-württemberg.de' serviceName:nil
+ self getAddressInfo:'www.baden-wrttemberg.de' serviceName:nil
domain:#'AF_INET' type:#stream protocol:nil flags:nil
-=======
- domain:#'AF_INET6' type:nil protocol:nil flags:nil
- self getAddressInfo:'www.baden-wrttemberg.de' serviceName:nil
- domain:#'AF_INET' type:#stream protocol:nil flags:nil
->>>>>>> 1.489
"
!