PipeStream.st
author Claus Gittinger <cg@exept.de>
Thu, 23 Nov 1995 02:16:37 +0100
changeset 605 8b17f96bf05a
parent 582 21f08116b28d
child 613 0af19c3594fc
permissions -rw-r--r--
checkin from browser
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
     1
"
5
67342904af11 *** empty log message ***
claus
parents: 3
diff changeset
     2
 COPYRIGHT (c) 1989 by Claus Gittinger
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
     3
	      All Rights Reserved
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
     4
a27a279701f8 Initial revision
claus
parents:
diff changeset
     5
 This software is furnished under a license and may be used
a27a279701f8 Initial revision
claus
parents:
diff changeset
     6
 only in accordance with the terms of that license and with the
a27a279701f8 Initial revision
claus
parents:
diff changeset
     7
 inclusion of the above copyright notice.   This software may not
a27a279701f8 Initial revision
claus
parents:
diff changeset
     8
 be provided or otherwise made available to, or used by, any
a27a279701f8 Initial revision
claus
parents:
diff changeset
     9
 other person.  No title to or ownership of the software is
a27a279701f8 Initial revision
claus
parents:
diff changeset
    10
 hereby transferred.
a27a279701f8 Initial revision
claus
parents:
diff changeset
    11
"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    12
269
93162487a94b *** empty log message ***
claus
parents: 255
diff changeset
    13
NonPositionableExternalStream subclass:#PipeStream
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
    14
       instanceVariableNames:'commandString'
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
    15
       classVariableNames:'BrokenPipeSignal'
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    16
       poolDictionaries:''
a27a279701f8 Initial revision
claus
parents:
diff changeset
    17
       category:'Streams-External'
a27a279701f8 Initial revision
claus
parents:
diff changeset
    18
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    19
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    20
!PipeStream class methodsFor:'documentation'!
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    21
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    22
copyright
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    23
"
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    24
 COPYRIGHT (c) 1989 by Claus Gittinger
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    25
	      All Rights Reserved
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    26
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    27
 This software is furnished under a license and may be used
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    28
 only in accordance with the terms of that license and with the
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    29
 inclusion of the above copyright notice.   This software may not
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    30
 be provided or otherwise made available to, or used by, any
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    31
 other person.  No title to or ownership of the software is
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    32
 hereby transferred.
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    33
"
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    34
!
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    35
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    36
version
582
21f08116b28d BrokenPipeSignal now a child of WriteErrorSignal
Claus Gittinger <cg@exept.de>
parents: 530
diff changeset
    37
    ^ '$Header: /cvs/stx/stx/libbasic/PipeStream.st,v 1.39 1995-11-20 14:51:54 cg Exp $'
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    38
!
2
claus
parents: 1
diff changeset
    39
claus
parents: 1
diff changeset
    40
documentation
claus
parents: 1
diff changeset
    41
"
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    42
    Pipestreams allow reading or writing from/to a unix command.
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    43
    For example, to get a stream reading the output of an 'ls -l'
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    44
    command, a PipeStream can be created with:
2
claus
parents: 1
diff changeset
    45
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    46
	PipeStream readingFrom:'ls -l'
2
claus
parents: 1
diff changeset
    47
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    48
    the characters of the commands output can be read using the
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    49
    standard stream messages as next, nextLine etc.
2
claus
parents: 1
diff changeset
    50
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    51
    If a writing pipeStream is written to, after the command has finished,
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    52
    UNIX will generate an error-signal (SIGPIPE), which will raise the
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    53
    BrokenPipeSignal. 
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    54
    Thus, to handle this condition correctly, the following code is suggested:
2
claus
parents: 1
diff changeset
    55
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    56
	|p|
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    57
	p := PipeStream writingTo:'echo hello'.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    58
	PipeStream brokenPipeSignal handle:[:ex |
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    59
	    'broken pipe' printNewline.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    60
	    p shutDown.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    61
	    ex return
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    62
	] do:[
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    63
	    p nextPutLine:'oops'.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    64
	   'after write' printNewline.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    65
	    p close.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    66
	   'after close' printNewline
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
    67
	]
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
    68
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    69
    Notice, that if the Stream is buffered, the Signal may occur some time after
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    70
    the write - or even at close time; to avoid a recursive signal in the exception
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
    71
    handler, a shutDown is useful there.
2
claus
parents: 1
diff changeset
    72
"
claus
parents: 1
diff changeset
    73
! !
claus
parents: 1
diff changeset
    74
217
a0400fdbc933 *** empty log message ***
claus
parents: 180
diff changeset
    75
!PipeStream primitiveDefinitions!
180
c488255bd0be *** empty log message ***
claus
parents: 159
diff changeset
    76
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    77
%{
437
claus
parents: 410
diff changeset
    78
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    79
#include <stdio.h>
437
claus
parents: 410
diff changeset
    80
#define _STDIO_H_INCLUDED_
claus
parents: 410
diff changeset
    81
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    82
#include <errno.h>
437
claus
parents: 410
diff changeset
    83
#define _ERRNO_H_INCLUDED_
claus
parents: 410
diff changeset
    84
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    85
#ifndef transputer
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    86
# include <sys/types.h>
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    87
# include <sys/stat.h>
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    88
#endif
230
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    89
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    90
/*
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    91
 * on some systems errno is a macro ... check for it here
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    92
 */
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    93
#ifndef errno
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    94
 extern errno;
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    95
#endif
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
    96
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    97
%}
180
c488255bd0be *** empty log message ***
claus
parents: 159
diff changeset
    98
! !
88
81dacba7a63a *** empty log message ***
claus
parents: 85
diff changeset
    99
325
claus
parents: 308
diff changeset
   100
!PipeStream primitiveFunctions!
claus
parents: 308
diff changeset
   101
claus
parents: 308
diff changeset
   102
%{
claus
parents: 308
diff changeset
   103
claus
parents: 308
diff changeset
   104
/*
claus
parents: 308
diff changeset
   105
 * some systems (i.e. ultrix) use fork;
claus
parents: 308
diff changeset
   106
 * were better off with a popen based on vfork ...
claus
parents: 308
diff changeset
   107
 */
claus
parents: 308
diff changeset
   108
#ifdef NEED_POPEN_WITH_VFORK
claus
parents: 308
diff changeset
   109
claus
parents: 308
diff changeset
   110
static int popen_pid = 0;
claus
parents: 308
diff changeset
   111
claus
parents: 308
diff changeset
   112
FILE *
claus
parents: 308
diff changeset
   113
popen(command, type)
claus
parents: 308
diff changeset
   114
/* const */ char *command;
claus
parents: 308
diff changeset
   115
/* const */ char *type;
claus
parents: 308
diff changeset
   116
{
claus
parents: 308
diff changeset
   117
    int pipes[2];
claus
parents: 308
diff changeset
   118
    int itype = (strcmp(type, "w") == 0 ? 1 : 0);
claus
parents: 308
diff changeset
   119
claus
parents: 308
diff changeset
   120
    if (pipe(pipes) == -1)
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   121
	return NULL;
325
claus
parents: 308
diff changeset
   122
claus
parents: 308
diff changeset
   123
    switch (popen_pid = vfork()) {
claus
parents: 308
diff changeset
   124
    case -1:
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   125
	(void)close(pipes[0]);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   126
	(void)close(pipes[1]);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   127
	return NULL;
325
claus
parents: 308
diff changeset
   128
claus
parents: 308
diff changeset
   129
    case 0:
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   130
	if (itype) {
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   131
	    dup2(pipes[0], fileno(stdin));
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   132
	    close(pipes[1]);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   133
	} else {
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   134
	    dup2(pipes[1], fileno(stdout));
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   135
	    close(pipes[0]);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   136
	}
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   137
	execl("/bin/sh", "/bin/sh", "-c", command, 0);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   138
	fprintf(stderr, "XRN Error: failed the execlp\n");
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   139
	_exit(-1);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   140
	/* NOTREACHED */
325
claus
parents: 308
diff changeset
   141
claus
parents: 308
diff changeset
   142
    default:
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   143
	    if (itype) {
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   144
		close(pipes[0]);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   145
		return fdopen(pipes[1], "w");
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   146
	    } else {
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   147
		close(pipes[1]);
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   148
		return fdopen(pipes[0], "r");
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   149
	    }
325
claus
parents: 308
diff changeset
   150
    }
claus
parents: 308
diff changeset
   151
}
claus
parents: 308
diff changeset
   152
claus
parents: 308
diff changeset
   153
int
claus
parents: 308
diff changeset
   154
pclose(str)
claus
parents: 308
diff changeset
   155
FILE *str;
claus
parents: 308
diff changeset
   156
{
claus
parents: 308
diff changeset
   157
    int pd = 0;
claus
parents: 308
diff changeset
   158
    int status;
claus
parents: 308
diff changeset
   159
    int err;
claus
parents: 308
diff changeset
   160
claus
parents: 308
diff changeset
   161
    err = fclose(str);
claus
parents: 308
diff changeset
   162
claus
parents: 308
diff changeset
   163
    do {
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   164
	if ((pd = wait(&status)) == -1)
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   165
	{
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   166
		err = EOF;
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   167
		break;
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   168
	}
325
claus
parents: 308
diff changeset
   169
    } while (pd !=  popen_pid);
claus
parents: 308
diff changeset
   170
claus
parents: 308
diff changeset
   171
    if (err == EOF)
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   172
	return  -1;
325
claus
parents: 308
diff changeset
   173
claus
parents: 308
diff changeset
   174
    if (status)
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   175
	status >>= 8;   /* exit status in high byte */
325
claus
parents: 308
diff changeset
   176
claus
parents: 308
diff changeset
   177
    return status;
claus
parents: 308
diff changeset
   178
}
claus
parents: 308
diff changeset
   179
claus
parents: 308
diff changeset
   180
#endif
claus
parents: 308
diff changeset
   181
claus
parents: 308
diff changeset
   182
%}
claus
parents: 308
diff changeset
   183
! !
claus
parents: 308
diff changeset
   184
2
claus
parents: 1
diff changeset
   185
!PipeStream class methodsFor:'initialization'!
claus
parents: 1
diff changeset
   186
claus
parents: 1
diff changeset
   187
initialize
claus
parents: 1
diff changeset
   188
    "setup the signal"
claus
parents: 1
diff changeset
   189
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   190
    BrokenPipeSignal isNil ifTrue:[
582
21f08116b28d BrokenPipeSignal now a child of WriteErrorSignal
Claus Gittinger <cg@exept.de>
parents: 530
diff changeset
   191
	BrokenPipeSignal := WriteErrorSignal newSignalMayProceed:true.
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   192
	BrokenPipeSignal nameClass:self message:#brokenPipeSignal.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   193
	BrokenPipeSignal notifierString:'write on a pipe with no one to read'.
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   194
    ]
2
claus
parents: 1
diff changeset
   195
! !
claus
parents: 1
diff changeset
   196
345
claus
parents: 326
diff changeset
   197
!PipeStream class methodsFor:'Signal constants'!
2
claus
parents: 1
diff changeset
   198
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   199
brokenPipeSignal
2
claus
parents: 1
diff changeset
   200
    "return the signal used to handle SIGPIPE unix-signals"
claus
parents: 1
diff changeset
   201
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   202
    ^ BrokenPipeSignal
2
claus
parents: 1
diff changeset
   203
! !
claus
parents: 1
diff changeset
   204
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   205
!PipeStream class methodsFor:'instance creation'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   206
2
claus
parents: 1
diff changeset
   207
writingTo:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   208
    "create and return a new pipeStream which can write to the unix command
a27a279701f8 Initial revision
claus
parents:
diff changeset
   209
     given by command."
a27a279701f8 Initial revision
claus
parents:
diff changeset
   210
2
claus
parents: 1
diff changeset
   211
    ^ (self basicNew) writingTo:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   212
a27a279701f8 Initial revision
claus
parents:
diff changeset
   213
    "PipeStream writingTo:'sort'"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   214
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   215
2
claus
parents: 1
diff changeset
   216
readingFrom:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   217
    "create and return a new pipeStream which can read from the unix command
a27a279701f8 Initial revision
claus
parents:
diff changeset
   218
     given by command."
a27a279701f8 Initial revision
claus
parents:
diff changeset
   219
2
claus
parents: 1
diff changeset
   220
    ^ (self basicNew) readingFrom:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   221
2
claus
parents: 1
diff changeset
   222
    "PipeStream readingFrom:'ls -l'"
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   223
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   224
99
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   225
!PipeStream methodsFor:'accessing'!
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   226
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   227
commandString
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   228
    "return the command string"
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   229
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   230
    ^ commandString
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   231
! !
afba01fbe15c added access method for commandString
claus
parents: 93
diff changeset
   232
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   233
!PipeStream methodsFor:'instance release'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   234
230
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   235
disposed
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   236
    "redefined to avoid blocking in close."
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   237
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   238
    self shutDown
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   239
!
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   240
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   241
shutDown
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   242
    "close the Stream, ignoring any broken-pipe errors"
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   243
369
claus
parents: 362
diff changeset
   244
    BrokenPipeSignal catch:[
claus
parents: 362
diff changeset
   245
	Lobby unregister:self.
claus
parents: 362
diff changeset
   246
	self closeFileDescriptor
claus
parents: 362
diff changeset
   247
    ]
57
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   248
!
db9677479d35 *** empty log message ***
claus
parents: 49
diff changeset
   249
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   250
closeFile
230
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   251
    "low level close - redefined since we close a pipe here.
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   252
     This waits for the command to finish. 
0300c6797890 interrupt & blocking close
claus
parents: 217
diff changeset
   253
     Use shutDown for a fast (nonBlocking) close."
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   254
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   255
%{  /* UNLIMITEDSTACK */
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   256
#ifndef transputer
360
claus
parents: 345
diff changeset
   257
    OBJ fp;
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   258
360
claus
parents: 345
diff changeset
   259
    if ((fp = _INST(filePointer)) != nil) {
claus
parents: 345
diff changeset
   260
	_INST(filePointer) = nil;
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   261
	/*
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   262
	 * allow interrupt even when blocking here ...
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   263
	 */
362
claus
parents: 360
diff changeset
   264
	__BEGIN_INTERRUPTABLE__
475
b57530aa1b0a use new FILE* wrapper macros (based on externalAddress)
Claus Gittinger <cg@exept.de>
parents: 437
diff changeset
   265
	pclose(__FILEVal(fp));
362
claus
parents: 360
diff changeset
   266
	__END_INTERRUPTABLE__
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   267
    }
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   268
#endif
a27a279701f8 Initial revision
claus
parents:
diff changeset
   269
%}
369
claus
parents: 362
diff changeset
   270
!
claus
parents: 362
diff changeset
   271
claus
parents: 362
diff changeset
   272
closeFileDescriptor
claus
parents: 362
diff changeset
   273
    "alternative very low level close 
claus
parents: 362
diff changeset
   274
     This closes the underlying OS-fileDescriptor 
claus
parents: 362
diff changeset
   275
     - and will NOT write any buffered data to the stream.
claus
parents: 362
diff changeset
   276
     You have been warned."
claus
parents: 362
diff changeset
   277
claus
parents: 362
diff changeset
   278
%{  /* NOCONTEXT */
claus
parents: 362
diff changeset
   279
claus
parents: 362
diff changeset
   280
    OBJ fp;
claus
parents: 362
diff changeset
   281
    FILE *f;
claus
parents: 362
diff changeset
   282
claus
parents: 362
diff changeset
   283
    if ((fp = _INST(filePointer)) != nil) {
claus
parents: 362
diff changeset
   284
	_INST(filePointer) = nil;
claus
parents: 362
diff changeset
   285
	__BEGIN_INTERRUPTABLE__
475
b57530aa1b0a use new FILE* wrapper macros (based on externalAddress)
Claus Gittinger <cg@exept.de>
parents: 437
diff changeset
   286
	f = __FILEVal(fp);
369
claus
parents: 362
diff changeset
   287
	close(fileno(f));
claus
parents: 362
diff changeset
   288
	__END_INTERRUPTABLE__
claus
parents: 362
diff changeset
   289
    }
claus
parents: 362
diff changeset
   290
%}
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   291
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   292
a27a279701f8 Initial revision
claus
parents:
diff changeset
   293
!PipeStream methodsFor:'private'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   294
379
5b5a130ccd09 revision added
claus
parents: 369
diff changeset
   295
atEnd
93
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   296
    "return true, if position is at end"
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   297
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   298
%{  /* NOCONTEXT */
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   299
    FILE *f;
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   300
    OBJ t;
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   301
    OBJ _true = true;
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   302
    int c;
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   303
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   304
    if (_INST(hitEOF) == _true) {
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   305
	RETURN (_true);
93
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   306
    }
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   307
    if ((t = _INST(filePointer)) != nil) {
475
b57530aa1b0a use new FILE* wrapper macros (based on externalAddress)
Claus Gittinger <cg@exept.de>
parents: 437
diff changeset
   308
	f = __FILEVal(t);
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   309
	if (feof(f)) {
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   310
	    _INST(hitEOF) = true;
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   311
	    RETURN (true);
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   312
	}
401
claus
parents: 384
diff changeset
   313
	clearerr(f);
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   314
	RETURN ( false );
93
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   315
    }
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   316
%}
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   317
.
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   318
    ^ super atEnd
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   319
! !
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   320
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   321
!PipeStream methodsFor:'private'!
e31220cb391f *** empty log message ***
claus
parents: 88
diff changeset
   322
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   323
openPipeFor:aCommandString withMode:mode
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   324
    "open a pipe to the unix command in aCcommandString; 
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   325
     mode may be 'r' or 'w'"
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   326
a27a279701f8 Initial revision
claus
parents:
diff changeset
   327
    |retVal|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   328
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   329
    filePointer notNil ifTrue:[
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   330
	"the pipe was already open ...
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   331
	 this should (can) not happen."
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   332
	^ self errorOpen
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   333
    ].
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   334
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   335
%{  /* STACK: 32000 */
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   336
#ifndef transputer
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   337
    FILE *f;
477
8710aba7876b oops - making id's real objects requires a store macro
Claus Gittinger <cg@exept.de>
parents: 475
diff changeset
   338
    OBJ fp;
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   339
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   340
    _INST(lastErrorNumber) = nil;
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   341
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   342
    if (__isString(aCommandString) && __isString(mode)) {
362
claus
parents: 360
diff changeset
   343
	__BEGIN_INTERRUPTABLE__
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   344
	do {
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   345
#ifdef LINUX
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   346
	    /* LINUX returns a non-NULL f even when interrupted */
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   347
	    errno = 0;
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   348
	    f = (FILE *)popen((char *) _stringVal(aCommandString),
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   349
			      (char *) _stringVal(mode));
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   350
	    if (errno == EINTR)
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   351
		f = NULL;
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   352
#else
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   353
	    f = (FILE *)popen((char *) _stringVal(aCommandString),
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   354
			      (char *) _stringVal(mode));
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   355
#endif
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   356
	} while ((f == NULL) && (errno == EINTR));
362
claus
parents: 360
diff changeset
   357
	__END_INTERRUPTABLE__
claus
parents: 360
diff changeset
   358
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   359
	if (f == NULL) {
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   360
	    _INST(lastErrorNumber) = _MKSMALLINT(errno);
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   361
	} else {
401
claus
parents: 384
diff changeset
   362
	    clearerr(f);
478
8b34ec2ef801 *** empty log message ***
Claus Gittinger <cg@exept.de>
parents: 477
diff changeset
   363
	    _INST(filePointer) = fp = __MKOBJ(f); __STORE(self, fp);
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   364
	    retVal = self;
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   365
	}
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   366
    }
a27a279701f8 Initial revision
claus
parents:
diff changeset
   367
#endif
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   368
%}.
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   369
    retVal notNil ifTrue:[
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   370
	commandString := aCommandString.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   371
	buffered := true.
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   372
	hitEOF := false.
406
claus
parents: 401
diff changeset
   373
	binary := false.
159
514c749165c3 *** empty log message ***
claus
parents: 99
diff changeset
   374
	Lobby register:self
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   375
    ].
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   376
    lastErrorNumber notNil ifTrue:[
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   377
	"
308
f04744ef7b5d *** empty log message ***
claus
parents: 302
diff changeset
   378
	 the pipe open failed for some reason ...
f04744ef7b5d *** empty log message ***
claus
parents: 302
diff changeset
   379
	 ... this may be either due to an invalid command string,
f04744ef7b5d *** empty log message ***
claus
parents: 302
diff changeset
   380
	 or due to the system running out of memory (when forking
f04744ef7b5d *** empty log message ***
claus
parents: 302
diff changeset
   381
	 the unix process)
255
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   382
	"
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   383
	^ self openError
2b2c5c0facab *** empty log message ***
claus
parents: 230
diff changeset
   384
    ].
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   385
    ^ retVal
a27a279701f8 Initial revision
claus
parents:
diff changeset
   386
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   387
a27a279701f8 Initial revision
claus
parents:
diff changeset
   388
readingFrom:command
a27a279701f8 Initial revision
claus
parents:
diff changeset
   389
    "setup the receiver to read from command"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   390
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   391
    mode := #readonly. didWrite := false.
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   392
    ^ self openPipeFor:command withMode:'r'
a27a279701f8 Initial revision
claus
parents:
diff changeset
   393
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   394
a27a279701f8 Initial revision
claus
parents:
diff changeset
   395
writingTo:command
a27a279701f8 Initial revision
claus
parents:
diff changeset
   396
    "setup the receiver to write to command"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   397
326
d2902942491d *** empty log message ***
claus
parents: 325
diff changeset
   398
    mode := #writeonly. didWrite := true.
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   399
    ^ self openPipeFor:command withMode:'w'
a27a279701f8 Initial revision
claus
parents:
diff changeset
   400
! !