PipeStream.st
author claus
Sat, 05 Feb 1994 13:23:03 +0100
changeset 49 f1c2d75f2eb6
parent 32 ee1a621c696c
child 57 db9677479d35
permissions -rw-r--r--
*** empty log message ***
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
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
     3
              All Rights Reserved
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
a27a279701f8 Initial revision
claus
parents:
diff changeset
    13
NonPositionableExternalStream subclass:#PipeStream
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
    14
       instanceVariableNames:'commandString'
2
claus
parents: 1
diff changeset
    15
       classVariableNames:'PipeSignal'
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
a27a279701f8 Initial revision
claus
parents:
diff changeset
    20
PipeStream comment:'
a27a279701f8 Initial revision
claus
parents:
diff changeset
    21
5
67342904af11 *** empty log message ***
claus
parents: 3
diff changeset
    22
COPYRIGHT (c) 1989 by Claus Gittinger
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    23
              All Rights Reserved
a27a279701f8 Initial revision
claus
parents:
diff changeset
    24
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
    25
$Header: /cvs/stx/stx/libbasic/PipeStream.st,v 1.8 1994-02-05 12:22:43 claus Exp $
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    26
'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    27
a27a279701f8 Initial revision
claus
parents:
diff changeset
    28
%{
a27a279701f8 Initial revision
claus
parents:
diff changeset
    29
#include <stdio.h>
10
claus
parents: 5
diff changeset
    30
#include <errno.h>
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    31
#ifndef transputer
a27a279701f8 Initial revision
claus
parents:
diff changeset
    32
# include <sys/types.h>
a27a279701f8 Initial revision
claus
parents:
diff changeset
    33
# include <sys/stat.h>
a27a279701f8 Initial revision
claus
parents:
diff changeset
    34
#endif
a27a279701f8 Initial revision
claus
parents:
diff changeset
    35
%}
a27a279701f8 Initial revision
claus
parents:
diff changeset
    36
2
claus
parents: 1
diff changeset
    37
!PipeStream class methodsFor:'documentation'!
claus
parents: 1
diff changeset
    38
claus
parents: 1
diff changeset
    39
documentation
claus
parents: 1
diff changeset
    40
"
claus
parents: 1
diff changeset
    41
Pipestreams allow reading or writing from/to a unix command.
claus
parents: 1
diff changeset
    42
For example, to get a stream reading the output of an 'ls -l'
claus
parents: 1
diff changeset
    43
command, a PipeStream can be created with:
claus
parents: 1
diff changeset
    44
claus
parents: 1
diff changeset
    45
        PipeStream readingFrom:'ls -l'
claus
parents: 1
diff changeset
    46
claus
parents: 1
diff changeset
    47
the characters of the commands output can be read using the
claus
parents: 1
diff changeset
    48
standard stream messages as next, nextLine etc.
claus
parents: 1
diff changeset
    49
claus
parents: 1
diff changeset
    50
If a writing pipeStream is written to, after the command has finished,
claus
parents: 1
diff changeset
    51
UNIX will generate an error-signal (SIGPIPE), which will raise a
claus
parents: 1
diff changeset
    52
PipeSignal. Thus, to handle this condition correctly, the following
claus
parents: 1
diff changeset
    53
code is suggested:
claus
parents: 1
diff changeset
    54
claus
parents: 1
diff changeset
    55
        p := PipeStream writingTo:' ... '.
claus
parents: 1
diff changeset
    56
        PipeString pipeSignal handle:[:ex |
claus
parents: 1
diff changeset
    57
            ....
claus
parents: 1
diff changeset
    58
            any cleanup action
claus
parents: 1
diff changeset
    59
        ] do:[
claus
parents: 1
diff changeset
    60
            p nextPutLine:' ... '
claus
parents: 1
diff changeset
    61
        ]
claus
parents: 1
diff changeset
    62
"
claus
parents: 1
diff changeset
    63
! !
claus
parents: 1
diff changeset
    64
claus
parents: 1
diff changeset
    65
!PipeStream class methodsFor:'initialization'!
claus
parents: 1
diff changeset
    66
claus
parents: 1
diff changeset
    67
initialize
claus
parents: 1
diff changeset
    68
    "setup the signal"
claus
parents: 1
diff changeset
    69
claus
parents: 1
diff changeset
    70
    PipeSignal := (Signal new) mayProceed:true.
claus
parents: 1
diff changeset
    71
    PipeSignal notifierString:'write on a pipe with no one to read'.
claus
parents: 1
diff changeset
    72
! !
claus
parents: 1
diff changeset
    73
claus
parents: 1
diff changeset
    74
!PipeStream class methodsFor:'signal access'!
claus
parents: 1
diff changeset
    75
claus
parents: 1
diff changeset
    76
pipeSignal
claus
parents: 1
diff changeset
    77
    "return the signal used to handle SIGPIPE unix-signals"
claus
parents: 1
diff changeset
    78
claus
parents: 1
diff changeset
    79
    ^ PipeSignal
claus
parents: 1
diff changeset
    80
! !
claus
parents: 1
diff changeset
    81
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    82
!PipeStream class methodsFor:'instance creation'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    83
2
claus
parents: 1
diff changeset
    84
writingTo:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    85
    "create and return a new pipeStream which can write to the unix command
a27a279701f8 Initial revision
claus
parents:
diff changeset
    86
     given by command."
a27a279701f8 Initial revision
claus
parents:
diff changeset
    87
2
claus
parents: 1
diff changeset
    88
    ^ (self basicNew) writingTo:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    89
a27a279701f8 Initial revision
claus
parents:
diff changeset
    90
    "PipeStream writingTo:'sort'"
a27a279701f8 Initial revision
claus
parents:
diff changeset
    91
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
    92
2
claus
parents: 1
diff changeset
    93
readingFrom:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    94
    "create and return a new pipeStream which can read from the unix command
a27a279701f8 Initial revision
claus
parents:
diff changeset
    95
     given by command."
a27a279701f8 Initial revision
claus
parents:
diff changeset
    96
2
claus
parents: 1
diff changeset
    97
    ^ (self basicNew) readingFrom:commandString
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
    98
2
claus
parents: 1
diff changeset
    99
    "PipeStream readingFrom:'ls -l'"
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   100
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   101
a27a279701f8 Initial revision
claus
parents:
diff changeset
   102
!PipeStream methodsFor:'instance release'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   103
a27a279701f8 Initial revision
claus
parents:
diff changeset
   104
closeFile
a27a279701f8 Initial revision
claus
parents:
diff changeset
   105
    "low level close - redefined since we close a pipe here"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   106
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   107
%{  /* UNLIMITEDSTACK */
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   108
#ifndef transputer
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   109
    extern int _immediateInterrupt;
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   110
    int savInt;
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   111
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   112
    if (_INST(filePointer) != nil) {
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   113
        savInt = _immediateInterrupt;
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   114
        _immediateInterrupt = 1;
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   115
        pclose(MKFD(_INST(filePointer)));
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   116
        _immediateInterrupt = savInt;
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   117
    }
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   118
#endif
a27a279701f8 Initial revision
claus
parents:
diff changeset
   119
%}
a27a279701f8 Initial revision
claus
parents:
diff changeset
   120
! !
a27a279701f8 Initial revision
claus
parents:
diff changeset
   121
a27a279701f8 Initial revision
claus
parents:
diff changeset
   122
!PipeStream methodsFor:'private'!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   123
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   124
openPipeFor:aCommandString withMode:mode
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   125
    "open a pipe to the unix command in aCcommandString; mode may be 'r' or 'w'"
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   126
a27a279701f8 Initial revision
claus
parents:
diff changeset
   127
    |retVal|
a27a279701f8 Initial revision
claus
parents:
diff changeset
   128
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   129
%{  /* STACK: 32000 */
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   130
#ifndef transputer
a27a279701f8 Initial revision
claus
parents:
diff changeset
   131
    {
a27a279701f8 Initial revision
claus
parents:
diff changeset
   132
        FILE *f;
a27a279701f8 Initial revision
claus
parents:
diff changeset
   133
        extern OBJ ErrorNumber;
a27a279701f8 Initial revision
claus
parents:
diff changeset
   134
        extern errno;
2
claus
parents: 1
diff changeset
   135
        extern int _immediateInterrupt;
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   136
        int savInt;
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   137
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   138
        if (_isString(aCommandString) && _isString(mode)) {
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   139
            savInt = _immediateInterrupt;
2
claus
parents: 1
diff changeset
   140
            _immediateInterrupt = 1;
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   141
            do {
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   142
#ifdef LINUX
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   143
                /* LINUX returns a non-NULL f even when interrupted */
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   144
                errno = 0;
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   145
                f = (FILE *)popen((char *) _stringVal(aCommandString),
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   146
                                  (char *) _stringVal(mode));
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   147
                if (errno == EINTR)
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   148
                    f = NULL;
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   149
#else
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   150
                f = (FILE *)popen((char *) _stringVal(aCommandString),
10
claus
parents: 5
diff changeset
   151
                                  (char *) _stringVal(mode));
13
62303f84ff5f *** empty log message ***
claus
parents: 10
diff changeset
   152
#endif
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   153
            } while ((f == NULL) && (errno == EINTR));
10
claus
parents: 5
diff changeset
   154
            _immediateInterrupt = savInt;
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   155
            if (f == NULL) {
a27a279701f8 Initial revision
claus
parents:
diff changeset
   156
                ErrorNumber = _MKSMALLINT(errno);
a27a279701f8 Initial revision
claus
parents:
diff changeset
   157
            } else {
a27a279701f8 Initial revision
claus
parents:
diff changeset
   158
                _INST(filePointer) = MKOBJ(f);
a27a279701f8 Initial revision
claus
parents:
diff changeset
   159
                retVal = self;
a27a279701f8 Initial revision
claus
parents:
diff changeset
   160
            }
a27a279701f8 Initial revision
claus
parents:
diff changeset
   161
        }
a27a279701f8 Initial revision
claus
parents:
diff changeset
   162
    }
a27a279701f8 Initial revision
claus
parents:
diff changeset
   163
#endif
a27a279701f8 Initial revision
claus
parents:
diff changeset
   164
%}
a27a279701f8 Initial revision
claus
parents:
diff changeset
   165
.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   166
    retVal notNil ifTrue:[
49
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   167
        commandString := aCommandString.
f1c2d75f2eb6 *** empty log message ***
claus
parents: 32
diff changeset
   168
        buffered := true.
32
ee1a621c696c *** empty log message ***
claus
parents: 13
diff changeset
   169
        Lobby register:self
1
a27a279701f8 Initial revision
claus
parents:
diff changeset
   170
    ].
a27a279701f8 Initial revision
claus
parents:
diff changeset
   171
    ^ retVal
a27a279701f8 Initial revision
claus
parents:
diff changeset
   172
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   173
a27a279701f8 Initial revision
claus
parents:
diff changeset
   174
readingFrom:command
a27a279701f8 Initial revision
claus
parents:
diff changeset
   175
    "setup the receiver to read from command"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   176
a27a279701f8 Initial revision
claus
parents:
diff changeset
   177
    self readonly.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   178
    ^ self openPipeFor:command withMode:'r'
a27a279701f8 Initial revision
claus
parents:
diff changeset
   179
!
a27a279701f8 Initial revision
claus
parents:
diff changeset
   180
a27a279701f8 Initial revision
claus
parents:
diff changeset
   181
writingTo:command
a27a279701f8 Initial revision
claus
parents:
diff changeset
   182
    "setup the receiver to write to command"
a27a279701f8 Initial revision
claus
parents:
diff changeset
   183
a27a279701f8 Initial revision
claus
parents:
diff changeset
   184
    self writeonly.
a27a279701f8 Initial revision
claus
parents:
diff changeset
   185
    ^ self openPipeFor:command withMode:'w'
a27a279701f8 Initial revision
claus
parents:
diff changeset
   186
! !