~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to tools/sfio/sfpopen.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include        "sfhdr.h"
 
2
 
 
3
/*      Create a coprocess.
 
4
**      Written by Kiem-Phong Vo.
 
5
*/
 
6
 
 
7
#if _PACKAGE_ast
 
8
#include        <proc.h>
 
9
#else
 
10
 
 
11
#define EXIT_NOTFOUND   127
 
12
 
 
13
#define READ            0
 
14
#define WRITE           1
 
15
 
 
16
#ifndef CHAR_BIT
 
17
#define CHAR_BIT        8
 
18
#endif
 
19
static char     Meta[1<<CHAR_BIT], **Path;
 
20
 
 
21
/* execute command directly if possible; else use the shell */
 
22
#if __STD_C
 
23
static void execute(const char* argcmd)
 
24
#else
 
25
static void execute(argcmd)
 
26
char*   argcmd;
 
27
#endif
 
28
{
 
29
        reg char        *s, *cmd, **argv, **p, *interp;
 
30
        reg int         n;
 
31
 
 
32
        /* define interpreter */
 
33
        if(!(interp = getenv("SHELL")) || !interp[0])
 
34
                interp = "/bin/sh";
 
35
 
 
36
        if(strcmp(interp,"/bin/sh") != 0 && strcmp(interp,"/bin/ksh") != 0 )
 
37
        {       if(access(interp,X_OK) == 0)
 
38
                        goto do_interp;
 
39
                else    interp = "/bin/sh";
 
40
        }
 
41
 
 
42
        /* if there is a meta character, let the shell do it */
 
43
        for(s = (char*)argcmd; *s; ++s)
 
44
                if(Meta[(uchar)s[0]])
 
45
                        goto do_interp;
 
46
 
 
47
        /* try to construct argv */
 
48
        if(!(cmd = (char*)malloc(strlen(argcmd)+1)) )
 
49
                goto do_interp;
 
50
        strcpy(cmd,argcmd);
 
51
        if(!(argv = (char**)malloc(16*sizeof(char*))) )
 
52
                goto do_interp;
 
53
        for(n = 0, s = cmd;; )
 
54
        {       while(isspace(s[0]))
 
55
                        s += 1;
 
56
                if(s[0] == 0)
 
57
                        break;
 
58
 
 
59
                /* new argument */
 
60
                argv[n++] = s;
 
61
                if((n%16) == 0 && !(argv = (char**)realloc(argv,(n+16)*sizeof(char*))) )
 
62
                        goto do_interp;
 
63
 
 
64
                /* make this into a C string */
 
65
                while(s[0] && !isspace(s[0]))
 
66
                        s += 1;
 
67
                if(!s[0])
 
68
                        *s++ = 0;
 
69
        }
 
70
        if(n == 0)
 
71
                goto do_interp;
 
72
        argv[n] = NIL(char*);
 
73
 
 
74
        /* get the command name */
 
75
        cmd = argv[0];
 
76
        for(s = cmd+strlen(cmd)-1; s >= cmd; --s)
 
77
                if(*s == '/')
 
78
                        break;
 
79
        argv[0] = s+1;
 
80
 
 
81
        /* Non-standard pathnames as in nDFS should be handled by the shell */
 
82
        for(s = cmd+strlen(cmd)-1; s >= cmd+2; --s)
 
83
                if(s[0] == '.' && s[-1] == '.' && s[-2] == '.')
 
84
                        goto do_interp;
 
85
 
 
86
        if(cmd[0] == '/' ||
 
87
           (cmd[0] == '.' && cmd[1] == '/') ||
 
88
           (cmd[0] == '.' && cmd[1] == '.' && cmd[2] == '/') )
 
89
        {       if(access(cmd,X_OK) != 0)
 
90
                        goto do_interp;
 
91
                else    execv(cmd,argv);
 
92
        }
 
93
        else
 
94
        {       for(p = Path; *p; ++p)
 
95
                {       s = sfprints("%s/%s", *p, cmd);
 
96
                        if(access(s,X_OK) == 0)
 
97
                                execv(s,argv);
 
98
                }
 
99
        }
 
100
 
 
101
        /* if get here, let the interpreter do it */
 
102
do_interp: 
 
103
        for(s = interp+strlen(interp)-1; s >= interp; --s)
 
104
                if(*s == '/')
 
105
                        break;
 
106
        execl(interp, s+1, "-c", argcmd, NIL(char*));
 
107
        _exit(EXIT_NOTFOUND);
 
108
}
 
109
 
 
110
#endif /*_PACKAGE_ast*/
 
111
 
 
112
#if __STD_C
 
113
Sfio_t* sfpopen(Sfio_t* f, const char* command, const char* mode)
 
114
#else
 
115
Sfio_t* sfpopen(f,command,mode)
 
116
Sfio_t* f;
 
117
char*   command;        /* command to execute */
 
118
char*   mode;           /* mode of the stream */
 
119
#endif
 
120
{
 
121
#if _PACKAGE_ast
 
122
        reg Proc_t*     proc;
 
123
        reg int         sflags;
 
124
        reg long        flags;
 
125
        reg int         bits;
 
126
        char*           av[4];
 
127
 
 
128
        if (!command || !command[0] || !(sflags = _sftype(mode, NiL, NiL)))
 
129
                return 0;
 
130
 
 
131
        if(f == (Sfio_t*)(-1))
 
132
        {       /* stdio compatibility mode */
 
133
                f = NIL(Sfio_t*);
 
134
                bits = SF_STDIO;
 
135
        }
 
136
        else    bits = 0;
 
137
 
 
138
        flags = 0;
 
139
        if (sflags & SF_READ)
 
140
                flags |= PROC_READ;
 
141
        if (sflags & SF_WRITE)
 
142
                flags |= PROC_WRITE;
 
143
        av[0] = "sh";
 
144
        av[1] = "-c";
 
145
        av[2] = (char*)command;
 
146
        av[3] = 0;
 
147
        if (!(proc = procopen(0, av, 0, 0, flags)))
 
148
                return 0;
 
149
        if (!(f = sfnew(f, NIL(Void_t*), (size_t)SF_UNBOUND,
 
150
                        (sflags&SF_READ) ? proc->rfd : proc->wfd, sflags)) ||
 
151
            ((f->bits |= bits),
 
152
             _sfpopen(f, (sflags&SF_READ) ? proc->wfd : -1, proc->pid)) < 0)
 
153
        {
 
154
                if (f) sfclose(f);
 
155
                procclose(proc);
 
156
                return 0;
 
157
        }
 
158
        procfree(proc);
 
159
        return f;
 
160
#else
 
161
        reg int         pid, fd, pkeep, ckeep, sflags;
 
162
        int             stdio, parent[2], child[2];
 
163
        Sfio_t          sf;
 
164
 
 
165
        /* set shell meta characters */
 
166
        if(Meta[0] == 0)
 
167
        {       reg char*       s;
 
168
                Meta[0] = 1;
 
169
                for(s = "!@#$%&*(){}[]:;<>~`'|\"\\"; *s; ++s)
 
170
                        Meta[(uchar)s[0]] = 1;
 
171
        }
 
172
        if(!Path)
 
173
                Path = _sfgetpath("PATH");
 
174
 
 
175
        /* sanity check */
 
176
        if(!command || !command[0] || !(sflags = _sftype(mode,NIL(int*),NIL(int*))))
 
177
                return NIL(Sfio_t*);
 
178
 
 
179
        /* make pipes */
 
180
        parent[0] = parent[1] = child[0] = child[1] = -1;
 
181
        if(pipe(parent) < 0)
 
182
                goto error;
 
183
        if((sflags&SF_RDWR) == SF_RDWR && pipe(child) < 0)
 
184
                goto error;
 
185
 
 
186
        switch((pid = fork()) )
 
187
        {
 
188
        default :       /* in parent process */
 
189
                if(sflags&SF_READ)
 
190
                        { pkeep = READ; ckeep = WRITE; }
 
191
                else    { pkeep = WRITE; ckeep = READ; }
 
192
 
 
193
                if(f == (Sfio_t*)(-1))
 
194
                {       /* stdio compatibility mode */
 
195
                        f = NIL(Sfio_t*);
 
196
                        stdio = 1;
 
197
                }
 
198
                else    stdio = 0;
 
199
 
 
200
                /* make the streams */
 
201
                if(!(f = sfnew(f,NIL(Void_t*),(size_t)SF_UNBOUND,parent[pkeep],sflags)))
 
202
                        goto error;
 
203
                CLOSE(parent[!pkeep]);
 
204
                SETCLOEXEC(parent[pkeep]);
 
205
 
 
206
                if((sflags&SF_RDWR) == SF_RDWR)
 
207
                {       CLOSE(child[!ckeep]);
 
208
                        SETCLOEXEC(child[ckeep]);
 
209
                }
 
210
 
 
211
                /* save process info */
 
212
                fd = (sflags&SF_RDWR) == SF_RDWR ? child[ckeep] : -1;
 
213
                if(_sfpopen(f,fd,pid,stdio) < 0)
 
214
                {       (void)sfclose(f);
 
215
                        goto error;
 
216
                }
 
217
 
 
218
                return f;
 
219
 
 
220
        case 0 :        /* in child process */
 
221
                /* determine what to keep */
 
222
                if(sflags&SF_READ)
 
223
                        { pkeep = WRITE; ckeep = READ; }
 
224
                else    { pkeep = READ; ckeep = WRITE; }
 
225
 
 
226
                /* zap fd that we don't need */
 
227
                CLOSE(parent[!pkeep]);
 
228
                if((sflags&SF_RDWR) == SF_RDWR)
 
229
                        CLOSE(child[!ckeep]);
 
230
 
 
231
                /* use sfsetfd to make these descriptors the std-ones */
 
232
                SFCLEAR(&sf,NIL(Vtmutex_t*));
 
233
 
 
234
                /* must be careful so not to close something useful */
 
235
                if((sflags&SF_RDWR) == SF_RDWR && pkeep == child[ckeep])
 
236
                        if((child[ckeep] = dup(pkeep)) < 0)
 
237
                                _exit(EXIT_NOTFOUND);
 
238
 
 
239
                if(parent[pkeep] != pkeep)
 
240
                {       sf.file = parent[pkeep];
 
241
                        CLOSE(pkeep);
 
242
                        if(sfsetfd(&sf,pkeep) != pkeep)
 
243
                                _exit(EXIT_NOTFOUND);
 
244
                }
 
245
 
 
246
                if((sflags&SF_RDWR) == SF_RDWR && child[ckeep] != ckeep)
 
247
                {       sf.file = child[ckeep];
 
248
                        CLOSE(ckeep);
 
249
                        if(sfsetfd(&sf,ckeep) != ckeep)
 
250
                                _exit(EXIT_NOTFOUND);
 
251
                }
 
252
 
 
253
                execute(command);
 
254
                return NIL(Sfio_t*);
 
255
 
 
256
        case -1 :       /* error */
 
257
        error:
 
258
                if(parent[0] >= 0)
 
259
                        { CLOSE(parent[0]); CLOSE(parent[1]); }
 
260
                if(child[0] >= 0)
 
261
                        { CLOSE(child[0]); CLOSE(child[1]); }
 
262
                return NIL(Sfio_t*);
 
263
        }
 
264
#endif /*_PACKAGE_ast*/
 
265
}