PipeStr.st
changeset 159 514c749165c3
parent 99 afba01fbe15c
child 180 c488255bd0be
equal deleted inserted replaced
158:be947d4e7fb2 159:514c749165c3
     1 "
     1 "
     2  COPYRIGHT (c) 1989 by Claus Gittinger
     2  COPYRIGHT (c) 1989 by Claus Gittinger
     3               All Rights Reserved
     3 	      All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 NonPositionableExternalStream subclass:#PipeStream
    13 UnboundedExternalStream subclass:#PipeStream
    14        instanceVariableNames:'commandString'
    14        instanceVariableNames:'commandString'
    15        classVariableNames:'BrokenPipeSignal'
    15        classVariableNames:'BrokenPipeSignal'
    16        poolDictionaries:''
    16        poolDictionaries:''
    17        category:'Streams-External'
    17        category:'Streams-External'
    18 !
    18 !
    19 
    19 
    20 PipeStream comment:'
    20 PipeStream comment:'
    21 COPYRIGHT (c) 1989 by Claus Gittinger
    21 COPYRIGHT (c) 1989 by Claus Gittinger
    22               All Rights Reserved
    22 	      All Rights Reserved
    23 
    23 
    24 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.13 1994-08-06 10:32:00 claus Exp $
    24 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.14 1994-10-10 00:27:18 claus Exp $
    25 '!
    25 '!
    26 
    26 
    27 !PipeStream class methodsFor:'documentation'!
    27 !PipeStream class methodsFor:'documentation'!
    28 
    28 
    29 copyright
    29 copyright
    30 "
    30 "
    31  COPYRIGHT (c) 1989 by Claus Gittinger
    31  COPYRIGHT (c) 1989 by Claus Gittinger
    32               All Rights Reserved
    32 	      All Rights Reserved
    33 
    33 
    34  This software is furnished under a license and may be used
    34  This software is furnished under a license and may be used
    35  only in accordance with the terms of that license and with the
    35  only in accordance with the terms of that license and with the
    36  inclusion of the above copyright notice.   This software may not
    36  inclusion of the above copyright notice.   This software may not
    37  be provided or otherwise made available to, or used by, any
    37  be provided or otherwise made available to, or used by, any
    40 "
    40 "
    41 !
    41 !
    42 
    42 
    43 version
    43 version
    44 "
    44 "
    45 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.13 1994-08-06 10:32:00 claus Exp $
    45 $Header: /cvs/stx/stx/libbasic/Attic/PipeStr.st,v 1.14 1994-10-10 00:27:18 claus Exp $
    46 "
    46 "
    47 !
    47 !
    48 
    48 
    49 documentation
    49 documentation
    50 "
    50 "
    51 Pipestreams allow reading or writing from/to a unix command.
    51 Pipestreams allow reading or writing from/to a unix command.
    52 For example, to get a stream reading the output of an 'ls -l'
    52 For example, to get a stream reading the output of an 'ls -l'
    53 command, a PipeStream can be created with:
    53 command, a PipeStream can be created with:
    54 
    54 
    55         PipeStream readingFrom:'ls -l'
    55 	PipeStream readingFrom:'ls -l'
    56 
    56 
    57 the characters of the commands output can be read using the
    57 the characters of the commands output can be read using the
    58 standard stream messages as next, nextLine etc.
    58 standard stream messages as next, nextLine etc.
    59 
    59 
    60 If a writing pipeStream is written to, after the command has finished,
    60 If a writing pipeStream is written to, after the command has finished,
    61 UNIX will generate an error-signal (SIGPIPE), which will raise the
    61 UNIX will generate an error-signal (SIGPIPE), which will raise the
    62 BrokenPipeSignal. 
    62 BrokenPipeSignal. 
    63 Thus, to handle this condition correctly, the following code is suggested:
    63 Thus, to handle this condition correctly, the following code is suggested:
    64 
    64 
    65         |p|
    65 	|p|
    66         p := PipeStream writingTo:'echo hello'.
    66 	p := PipeStream writingTo:'echo hello'.
    67         PipeStream brokenPipeSignal handle:[:ex |
    67 	PipeStream brokenPipeSignal handle:[:ex |
    68             'broken pipe' printNewline.
    68 	    'broken pipe' printNewline.
    69             p shutDown.
    69 	    p shutDown.
    70             ex return
    70 	    ex return
    71         ] do:[
    71 	] do:[
    72             p nextPutLine:'oops'.
    72 	    p nextPutLine:'oops'.
    73            'after write' printNewline.
    73 	   'after write' printNewline.
    74             p close.
    74 	    p close.
    75            'after close' printNewline
    75 	   'after close' printNewline
    76         ]
    76 	]
    77 
    77 
    78 Notice, that if the Stream is buffered, the Signal may occur some time after
    78 Notice, that if the Stream is buffered, the Signal may occur some time after
    79 the write - or even at close time; to avoid a recursive signal in the exception
    79 the write - or even at close time; to avoid a recursive signal in the exception
    80 handler, a shutDown is useful there.
    80 handler, a shutDown is useful there.
    81 "
    81 "
    94 
    94 
    95 initialize
    95 initialize
    96     "setup the signal"
    96     "setup the signal"
    97 
    97 
    98     BrokenPipeSignal isNil ifTrue:[
    98     BrokenPipeSignal isNil ifTrue:[
    99         BrokenPipeSignal := (Signal new) mayProceed:true.
    99 	Object initialize.
   100         BrokenPipeSignal notifierString:'write on a pipe with no one to read'.
   100 
       
   101 	BrokenPipeSignal := Object errorSignal newSignalMayProceed:true.
       
   102 	BrokenPipeSignal nameClass:self message:#brokenPipeSignal.
       
   103 	BrokenPipeSignal notifierString:'write on a pipe with no one to read'.
   101     ]
   104     ]
   102 ! !
   105 ! !
   103 
   106 
   104 !PipeStream class methodsFor:'signal access'!
   107 !PipeStream class methodsFor:'signal access'!
   105 
   108 
   151 %{  /* UNLIMITEDSTACK */
   154 %{  /* UNLIMITEDSTACK */
   152 #ifndef transputer
   155 #ifndef transputer
   153     extern int _immediateInterrupt;
   156     extern int _immediateInterrupt;
   154 
   157 
   155     if (_INST(filePointer) != nil) {
   158     if (_INST(filePointer) != nil) {
   156         /*
   159 	/*
   157          * allow interrupt even when blocking here ...
   160 	 * allow interrupt even when blocking here ...
   158          */
   161 	 */
   159         _immediateInterrupt = 1;
   162 	_immediateInterrupt = 1;
   160         pclose(MKFD(_INST(filePointer)));
   163 	pclose(MKFD(_INST(filePointer)));
   161         _immediateInterrupt = 0;
   164 	_immediateInterrupt = 0;
   162     }
   165     }
   163 #endif
   166 #endif
   164 %}
   167 %}
   165 ! !
   168 ! !
   166 
   169 
   167 !PipeStream methodsFor:'private'!
   170 !PipeStream methodsFor:'private'!
   168 
   171 
   169 atEnd
   172 XXatEnd
   170     "return true, if position is at end"
   173     "return true, if position is at end"
   171 
   174 
   172 %{  /* NOCONTEXT */
   175 %{  /* NOCONTEXT */
   173 #ifdef IRIX5
   176 #ifdef IRIX5
   174     FILE *f;
   177     FILE *f;
   175     OBJ t;
   178     OBJ t;
   176     OBJ _true = true;
   179     OBJ _true = true;
   177     int c;
   180     int c;
   178 
   181 
   179     if (_INST(hitEOF) == _true) {
   182     if (_INST(hitEOF) == _true) {
   180         RETURN (_true);
   183 	RETURN (_true);
   181     }
   184     }
   182     if ((t = _INST(filePointer)) != nil) {
   185     if ((t = _INST(filePointer)) != nil) {
   183         f = MKFD(t);
   186 	f = MKFD(t);
   184         if (feof(f)) {
   187 	if (feof(f)) {
   185             _INST(hitEOF) = true;
   188 	    _INST(hitEOF) = true;
   186             RETURN (true);
   189 	    RETURN (true);
   187         }
   190 	}
   188         RETURN ( false );
   191 	RETURN ( false );
   189     }
   192     }
   190 #endif
   193 #endif
   191 %}
   194 %}
   192 .
   195 .
   193     ^ super atEnd
   196     ^ super atEnd
   201     |retVal|
   204     |retVal|
   202 
   205 
   203 %{  /* STACK: 32000 */
   206 %{  /* STACK: 32000 */
   204 #ifndef transputer
   207 #ifndef transputer
   205     {
   208     {
   206         FILE *f;
   209 	FILE *f;
   207         extern errno;
   210 	extern errno;
   208         extern int _immediateInterrupt;
   211 	extern int _immediateInterrupt;
   209 
   212 
   210         if (__isString(aCommandString) && __isString(mode)) {
   213 	if (__isString(aCommandString) && __isString(mode)) {
   211             _immediateInterrupt = 1;
   214 	    _immediateInterrupt = 1;
   212             do {
   215 	    do {
   213 #ifdef LINUX
   216 #ifdef LINUX
   214                 /* LINUX returns a non-NULL f even when interrupted */
   217 		/* LINUX returns a non-NULL f even when interrupted */
   215                 errno = 0;
   218 		errno = 0;
   216                 f = (FILE *)popen((char *) _stringVal(aCommandString),
   219 		f = (FILE *)popen((char *) _stringVal(aCommandString),
   217                                   (char *) _stringVal(mode));
   220 				  (char *) _stringVal(mode));
   218                 if (errno == EINTR)
   221 		if (errno == EINTR)
   219                     f = NULL;
   222 		    f = NULL;
   220 #else
   223 #else
   221                 f = (FILE *)popen((char *) _stringVal(aCommandString),
   224 		f = (FILE *)popen((char *) _stringVal(aCommandString),
   222                                   (char *) _stringVal(mode));
   225 				  (char *) _stringVal(mode));
   223 #endif
   226 #endif
   224             } while ((f == NULL) && (errno == EINTR));
   227 	    } while ((f == NULL) && (errno == EINTR));
   225             _immediateInterrupt = 0;
   228 	    _immediateInterrupt = 0;
   226             if (f == NULL) {
   229 	    if (f == NULL) {
   227                 ExternalStream_LastErrorNumber = _MKSMALLINT(errno);
   230 		_INST(lastErrorNumber) = _MKSMALLINT(errno);
   228             } else {
   231 	    } else {
   229                 _INST(filePointer) = MKOBJ(f);
   232 		_INST(filePointer) = MKOBJ(f);
   230                 retVal = self;
   233 		retVal = self;
   231             }
   234 	    }
   232         }
   235 	}
   233     }
   236     }
   234 #endif
   237 #endif
   235 %}
   238 %}
   236 .
   239 .
   237     retVal notNil ifTrue:[
   240     retVal notNil ifTrue:[
   238         commandString := aCommandString.
   241 	commandString := aCommandString.
   239         buffered := true.
   242 	buffered := true.
   240         hitEOF := false.
   243 	hitEOF := false.
   241         Lobby register:self
   244 	Lobby register:self
   242     ].
   245     ].
   243     ^ retVal
   246     ^ retVal
   244 !
   247 !
   245 
   248 
   246 readingFrom:command
   249 readingFrom:command