|
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! |