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

« back to all changes in this revision

Viewing changes to lefty/os/unix/io.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
#pragma prototyped
 
2
/* Lefteris Koutsofios - AT&T Bell Laboratories */
 
3
 
 
4
#include "common.h"
 
5
#include "io.h"
 
6
#ifdef FEATURE_CS
 
7
#include "cs2l.h"
 
8
#endif
 
9
#include "mem.h"
 
10
#include <fcntl.h>
 
11
#include <signal.h>
 
12
#include <sys/wait.h>
 
13
#ifndef HAVE_TERMIOS_H
 
14
#include <termio.h>
 
15
#else
 
16
#include <termios.h>
 
17
#endif
 
18
#include <sys/time.h>
 
19
#include <sys/socket.h>
 
20
#include <netinet/in.h>
 
21
#ifdef HAVEVFORK
 
22
#define FORK vfork
 
23
#else
 
24
#define FORK fork
 
25
#endif
 
26
#include <netdb.h>
 
27
 
 
28
io_t *iop;
 
29
int ion;
 
30
 
 
31
static char *shell;
 
32
static char *shbname;
 
33
 
 
34
static FILE *serverconnect (char *);
 
35
static void ptyopen (char *, FILE **, FILE **, int *);
 
36
static int findpty (int *);
 
37
static void pipeopen (char *, FILE **, FILE **, int *);
 
38
static void socketopen (char *, int, FILE **, FILE **, int *);
 
39
 
 
40
static void sigchldhandler (int);
 
41
 
 
42
void IOinit (void) {
 
43
    struct stat statbuf;
 
44
    int ioi;
 
45
 
 
46
    if (!(shell = getenv ("SHELL")))
 
47
        shell = "/bin/sh";
 
48
    if (shell[0] != '/' && shell[0] != '.') {
 
49
        if (!(shell = buildpath (shell, TRUE)))
 
50
            shell = "/bin/sh";
 
51
        else
 
52
            shell = strdup (shell);
 
53
    }
 
54
    shbname = shell + strlen (shell) - 1;
 
55
    while (shbname >= shell && *shbname != '/')
 
56
        shbname--;
 
57
    if (*shbname == '/')
 
58
        shbname++;
 
59
    ion = IOINCR;
 
60
    for (ioi = FD_SETSIZE - 1; ioi >= 0; ioi--) {
 
61
        if (fstat (ioi, &statbuf) == 0) {
 
62
           ion = (ioi / IOINCR + 1) * IOINCR;
 
63
           break;
 
64
        }
 
65
    }
 
66
    iop = Marrayalloc ((long) ion * IOSIZE);
 
67
    for (ioi = 0; ioi < ion; ioi++)
 
68
        iop[ioi].inuse = FALSE;
 
69
    for (ioi = 0; ioi < ion; ioi++) {
 
70
        if (fstat (ioi, &statbuf) == 0) {
 
71
            if ((iop[ioi].ifp = iop[ioi].ofp = fdopen (ioi,
 
72
                    (ioi == 0 ? "r" : "w")))) {
 
73
                iop[ioi].inuse = TRUE;
 
74
                iop[ioi].type = IO_FILE;
 
75
                iop[ioi].ismonitored = FALSE;
 
76
                iop[ioi].pid = -1;
 
77
                iop[ioi].buf = NULL;
 
78
            }
 
79
        }
 
80
    }
 
81
    signal (SIGCHLD, sigchldhandler);
 
82
    signal (SIGPIPE, SIG_IGN);
 
83
}
 
84
 
 
85
void IOterm (void) {
 
86
    int ioi;
 
87
 
 
88
    for (ioi = 3; ioi < ion; ioi++)
 
89
        if (iop[ioi].inuse)
 
90
            IOclose (ioi, NULL);
 
91
    Marrayfree (iop), iop = NULL, ion = 0;
 
92
}
 
93
 
 
94
int IOopen (char *kind, char *name, char *mode, char *fmt) {
 
95
    io_t *p;
 
96
    iotype_t type;
 
97
    char *path, *command;
 
98
    char hname[200];
 
99
    int sfd, slen;
 
100
    int i;
 
101
    struct sockaddr_in sname;
 
102
 
 
103
    if (Strcmp (kind, "file") == 0)
 
104
        type = IO_FILE;
 
105
    else if (Strcmp (kind, "pty") == 0)
 
106
        type = IO_PTY;
 
107
    else if (Strcmp (kind, "pipe") == 0)
 
108
        type = IO_PIPE;
 
109
    else if (Strcmp (kind, "socket") == 0)
 
110
        type = IO_SOCKET;
 
111
#ifdef FEATURE_CS
 
112
    else if (Strcmp (kind, "cs") == 0)
 
113
        type = IO_CS;
 
114
#endif
 
115
    else
 
116
        return -1;
 
117
    for (i = 0; i < ion; i++)
 
118
        if (!iop[i].inuse)
 
119
            break;
 
120
    if (i == ion) {
 
121
        iop = Marraygrow (iop, (long) (ion + IOINCR) * IOSIZE);
 
122
        for (i = ion + IOINCR - 1; i >= ion; i--)
 
123
            iop[i].inuse = FALSE;
 
124
        i++, ion += IOINCR;
 
125
    }
 
126
    p = &iop[i];
 
127
    p->type = type;
 
128
    p->pid = -1;
 
129
    switch (type) {
 
130
    case IO_FILE:
 
131
        if (!(p->ifp = p->ofp = fopen (name, mode))) {
 
132
            if (strncmp (name, "/dev/tcp/", 9) == 0) {
 
133
                if (!(p->ifp = p->ofp = serverconnect (name)))
 
134
                    return -1;
 
135
                break;
 
136
            }
 
137
            path = buildpath (name, FALSE);
 
138
            if (!path || !(p->ifp = p->ofp = fopen (path, mode)))
 
139
                return -1;
 
140
        }
 
141
        break;
 
142
    case IO_PTY:
 
143
        if (!fmt)
 
144
            fmt = "%e";
 
145
        if (!(path = buildpath (name, TRUE)) ||
 
146
                !(command = buildcommand (path, NULL, -1, -1, fmt)))
 
147
            return -1;
 
148
        ptyopen (command, &p->ifp, &p->ofp, &p->pid);
 
149
        if (!p->ifp || !p->ofp)
 
150
            return -1;
 
151
        break;
 
152
    case IO_PIPE:
 
153
        if (!fmt)
 
154
            fmt = "%e";
 
155
        if (!(path = buildpath (name, TRUE)) ||
 
156
                !(command = buildcommand (path, NULL, -1, -1, fmt)))
 
157
            return -1;
 
158
        pipeopen (command, &p->ifp, &p->ofp, &p->pid);
 
159
        if (!p->ifp || !p->ofp)
 
160
            return -1;
 
161
        break;
 
162
    case IO_SOCKET:
 
163
        if (!fmt)
 
164
            fmt = "%e";
 
165
        if ((sfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
 
166
            return -1;
 
167
        sname.sin_family = AF_INET;
 
168
        sname.sin_port = 0;
 
169
        sname.sin_addr.s_addr = htonl (INADDR_ANY);
 
170
        slen = sizeof (sname);
 
171
        if (bind (sfd, (struct sockaddr *) &sname, slen) < 0 ||
 
172
                getsockname (sfd, (struct sockaddr *) &sname, &slen) < 0)
 
173
            return -1;
 
174
        if (listen (sfd, 5) < 0)
 
175
            return -1;
 
176
        gethostname (hname, sizeof (hname));
 
177
        if (!(path = buildpath (name, TRUE)) ||
 
178
                !(command = buildcommand (path, hname,
 
179
                (int) ntohs (sname.sin_port),
 
180
                (int) ntohs (sname.sin_port), fmt)))
 
181
            return -1;
 
182
        socketopen (command, sfd, &p->ifp, &p->ofp, &p->pid);
 
183
        if (!p->ifp || !p->ofp)
 
184
            return -1;
 
185
        close (sfd);
 
186
        break;
 
187
#ifdef FEATURE_CS
 
188
    case IO_CS:
 
189
        if (C2Lopen (name, mode, &p->ifp, &p->ofp) == -1)
 
190
            return -1;
 
191
        break;
 
192
#endif
 
193
    }
 
194
    p->inuse = TRUE;
 
195
    FD_CLR (fileno (p->ifp), &inputfds);
 
196
    FD_CLR (fileno (p->ofp), &inputfds);
 
197
    return i;
 
198
}
 
199
 
 
200
int IOclose (int ioi, char *action) {
 
201
    io_t *p;
 
202
 
 
203
    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)
 
204
        return -1;
 
205
    p = &iop[ioi];
 
206
    FD_CLR (fileno (p->ifp), &inputfds);
 
207
    FD_CLR (fileno (p->ofp), &inputfds);
 
208
    if (p->ifp != p->ofp)
 
209
        fclose (p->ifp);
 
210
    fclose (p->ofp);
 
211
    p->inuse = FALSE;
 
212
    if (action && Strcmp (action, "kill") == 0 && p->pid != -1)
 
213
        kill (p->pid, 15);
 
214
    return 0;
 
215
}
 
216
 
 
217
int IOreadline (int ioi, char *bufp, int bufn) {
 
218
    io_t *p;
 
219
    int l;
 
220
 
 
221
    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)
 
222
        return -1;
 
223
    p = &iop[ioi];
 
224
    fseek (p->ofp, 0L, 1);
 
225
    if (fgets (bufp, bufn, p->ifp) == NULL)
 
226
        return -1;
 
227
    l = strlen (bufp) - 1;
 
228
    while (bufp[l] == '\n' || bufp[l] == '\r')
 
229
        bufp[l--] = '\000';
 
230
    return l + 1;
 
231
}
 
232
 
 
233
int IOread (int ioi, char *bufp, int bufn) {
 
234
    io_t *p;
 
235
    int l;
 
236
 
 
237
    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)
 
238
        return -1;
 
239
    p = &iop[ioi];
 
240
    if ((l = read (fileno (p->ifp), bufp, bufn - 1)) == -1)
 
241
        return -1;
 
242
    else if (l == 0)
 
243
        return 0;
 
244
    bufp[l] = '\000';
 
245
    return l;
 
246
}
 
247
 
 
248
int IOwriteline (int ioi, char *bufp) {
 
249
    io_t *p;
 
250
 
 
251
    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)
 
252
        return -1;
 
253
    p = &iop[ioi];
 
254
    fseek (p->ofp, 0L, 1);
 
255
    if (fputs (bufp, p->ofp) == EOF || fputs ("\n", p->ofp) == EOF)
 
256
        return -1;
 
257
    fflush (p->ofp);
 
258
    fseek (p->ofp, 0L, 1);
 
259
    return 0;
 
260
}
 
261
 
 
262
static FILE *serverconnect (char *name) {
 
263
    char *host, *portp, buf[1024];
 
264
    int port;
 
265
    struct hostent *hp;
 
266
    struct sockaddr_in sin;
 
267
    int cfd;
 
268
 
 
269
    strcpy (buf, name);
 
270
    host = buf + 9;
 
271
    portp = strchr (host, '/');
 
272
    if (*host == 0 || !portp)
 
273
        return NULL;
 
274
    *portp++ = 0, port = atoi (portp);
 
275
    if (!(hp = gethostbyname (host)))
 
276
        return NULL;
 
277
    memset ((char *) &sin, 1, sizeof (sin));
 
278
    memcpy ((char *) &sin.sin_addr, hp->h_addr, hp->h_length);
 
279
    sin.sin_family = hp->h_addrtype;
 
280
    sin.sin_port = htons (port);
 
281
    if ((cfd = socket (hp->h_addrtype, SOCK_STREAM, 0)) < 0)
 
282
        return NULL;
 
283
    if (connect (cfd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
 
284
        return NULL;
 
285
    return fdopen (cfd, "w+");
 
286
}
 
287
 
 
288
static void ptyopen (char *cmd, FILE **ifp, FILE **ofp, int *pidp) {
 
289
    int fd[2];
 
290
 
 
291
    if (findpty (fd) == -1) {
 
292
        *ifp = NULL;
 
293
        return;
 
294
    }
 
295
    switch ((*pidp = FORK ())) {
 
296
    case -1:
 
297
        panic2 (POS, "ptyopen", "cannot fork");
 
298
    case 0:
 
299
        close (fd[0]), close (0), dup (fd[1]);
 
300
        close (1), dup (fd[1]), close (fd[1]);
 
301
        execl (shell, shbname, "-c", cmd, 0);
 
302
        panic2 (POS, "ptyopen", "child cannot exec: %s\n", cmd);
 
303
    default:
 
304
        close (fd[1]);
 
305
    }
 
306
    fcntl (fd[0], F_SETFD, FD_CLOEXEC);
 
307
    *ifp = fdopen (fd[0], "r"), *ofp = fdopen (fd[0], "a+");
 
308
    return;
 
309
}
 
310
 
 
311
static int findpty (int *fd) {
 
312
    char *majorp, *minorp;
 
313
    char pty[32], tty[32];
 
314
#ifndef HAVE_TERMIOS_H
 
315
    struct termio tio;
 
316
#else
 
317
    struct termios tio;
 
318
#endif
 
319
    static char ptymajor[] = "pqrs";
 
320
    static char ptyminor[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 
321
 
 
322
    for (majorp = ptymajor; *majorp; majorp++) {
 
323
        for (minorp = ptyminor; *minorp; minorp++) {
 
324
            sprintf (pty, "/dev/pty%c%c", *majorp, *minorp);
 
325
            if ((fd[0] = open (pty, O_RDWR)) >= 0) {
 
326
                sprintf (tty, "/dev/tty%c%c", *majorp, *minorp);
 
327
                if ((fd[1] = open (tty, O_RDWR)) >= 0) {
 
328
#ifndef HAVE_TERMIOS_H
 
329
                    ioctl (fd[1], TCGETA, &tio);
 
330
                    tio.c_lflag &= ~ECHO;
 
331
                    ioctl (fd[1], TCSETA, &tio);
 
332
#else
 
333
                    tcgetattr(fd[1], &tio);
 
334
                    tio.c_lflag &= ~ECHO;
 
335
                    tcsetattr(fd[1], TCSANOW, &tio);
 
336
#endif
 
337
                    return 0;
 
338
                }
 
339
                close (fd[0]);
 
340
            }
 
341
        }
 
342
    }
 
343
    return -1;
 
344
}
 
345
 
 
346
static void pipeopen (char *cmd, FILE **ifp, FILE **ofp, int *pidp) {
 
347
    int p1[2], p2[2];
 
348
    char cmd2[1024];
 
349
    char *s;
 
350
 
 
351
    if (pipe (p1) == -1 || pipe (p2) == -1) {
 
352
        *ifp = NULL;
 
353
        return;
 
354
    }
 
355
    switch ((*pidp = FORK ())) {
 
356
    case -1:
 
357
        panic2 (POS, "pipeopen", "cannot fork");
 
358
    case 0:
 
359
        close (p1[0]), close (p2[1]);
 
360
        for (s = cmd; *s; s++)
 
361
            if (*s == '%' && *(s + 1) && *(s + 1) == 'd') {
 
362
                sprintf (cmd2, cmd, p2[0], p1[1]);
 
363
                execl (shell, shbname, "-c", cmd2, 0);
 
364
                panic2 (POS, "pipeopen", "child cannot exec: %s\n", cmd2);
 
365
            }
 
366
        close (1), dup (p1[1]), close (p1[1]);
 
367
        close (0), dup (p2[0]), close (p2[0]);
 
368
        execl (shell, shbname, "-c", cmd, 0);
 
369
        panic2 (POS, "pipeopen", "child cannot exec: %s\n", cmd);
 
370
    default:
 
371
        close (p1[1]), close (p2[0]);
 
372
    }
 
373
    fcntl (p1[0], F_SETFD, FD_CLOEXEC);
 
374
    fcntl (p2[1], F_SETFD, FD_CLOEXEC);
 
375
    *ifp = fdopen (p1[0], "r"), *ofp = fdopen (p2[1], "a");
 
376
    return;
 
377
}
 
378
 
 
379
static void socketopen (char *cmd, int sfd, FILE **ifp, FILE **ofp, int *pidp) {
 
380
    int fd;
 
381
 
 
382
    switch ((*pidp = FORK ())) {
 
383
    case -1:
 
384
        panic2 (POS, "socketopen", "cannot fork");
 
385
    case 0:
 
386
        execl (shell, shbname, "-c", cmd, 0);
 
387
        panic2 (POS, "socketopen", "child cannot exec: %s\n", cmd);
 
388
    default:
 
389
        if ((fd = accept (sfd, NULL, NULL)) < 0) {
 
390
            *ifp = NULL;
 
391
            return;
 
392
        }
 
393
    }
 
394
    fcntl (fd, F_SETFD, FD_CLOEXEC);
 
395
    *ifp = fdopen (fd, "r"), *ofp = fdopen (fd, "a+");
 
396
    return;
 
397
}
 
398
 
 
399
static void sigchldhandler (int data) {
 
400
    while (waitpid (-1, NULL, WNOHANG) > 0)
 
401
        ;
 
402
    signal (SIGCHLD, sigchldhandler);
 
403
}