~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to io.c

  • Committer: Arnold D. Robbins
  • Date: 2010-07-16 11:49:57 UTC
  • Revision ID: git-v1:6a2caf2157d87b4b582b2494bdd7d6a688dd0b1f
Tags: gawk-3.1.6
Move to gawk-3.1.6.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 */
4
4
 
5
5
/* 
6
 
 * Copyright (C) 1986, 1988, 1989, 1991-2005 the Free Software Foundation, Inc.
 
6
 * Copyright (C) 1986, 1988, 1989, 1991-2007 the Free Software Foundation, Inc.
7
7
 * 
8
8
 * This file is part of GAWK, the GNU implementation of the
9
9
 * AWK Programming Language.
10
10
 * 
11
11
 * GAWK is free software; you can redistribute it and/or modify
12
12
 * it under the terms of the GNU General Public License as published by
13
 
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * the Free Software Foundation; either version 3 of the License, or
14
14
 * (at your option) any later version.
15
15
 * 
16
16
 * GAWK is distributed in the hope that it will be useful,
45
45
#endif
46
46
 
47
47
#ifdef HAVE_SOCKETS
 
48
 
48
49
#ifdef HAVE_SYS_SOCKET_H
49
50
#include <sys/socket.h>
50
51
#else
51
52
#include <socket.h>
52
53
#endif /* HAVE_SYS_SOCKET_H */
 
54
 
53
55
#ifdef HAVE_NETINET_IN_H
54
56
#include <netinet/in.h>
55
 
#else
 
57
 
 
58
#ifdef HAVE_ARPA_INET_H
 
59
#include <arpa/inet.h>
 
60
#endif
 
61
 
 
62
#else /* ! HAVE_NETINET_IN_H */
56
63
#include <in.h>
57
64
#endif /* HAVE_NETINET_IN_H */
 
65
 
58
66
#ifdef HAVE_NETDB_H
59
67
#include <netdb.h>
60
68
#endif /* HAVE_NETDB_H */
 
69
 
 
70
#ifndef HAVE_GETADDRINFO
 
71
#include "missing_d/getaddrinfo.h"
 
72
#endif
 
73
 
 
74
#ifndef AI_ADDRCONFIG   /* This is a recent symbol, not everyone has it */
 
75
#define AI_ADDRCONFIG 0
 
76
#endif /* AI_ADDRCONFIG */
 
77
 
 
78
#ifndef HAVE_SOCKADDR_STORAGE
 
79
#define sockaddr_storage sockaddr       /* for older systems */
 
80
#endif /* HAVE_SOCKADDR_STORAGE */
 
81
 
61
82
#endif /* HAVE_SOCKETS */
62
83
 
 
84
#ifdef HAVE_LIMITS_H
 
85
#include <limits.h>
 
86
#endif
 
87
 
63
88
#ifdef __EMX__
64
89
#include <process.h>
65
90
#endif
71
96
extern int MRL;
72
97
 
73
98
#ifdef HAVE_SOCKETS
74
 
enum inet_prot { INET_NONE, INET_TCP, INET_UDP, INET_RAW };
75
99
 
76
100
#ifndef SHUT_RD
77
101
#define SHUT_RD         0
103
127
 
104
128
typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type;
105
129
 
 
130
/* For internal files, /dev/pid, etc. */
 
131
#define INTERNAL_HANDLE         (-42)
 
132
 
106
133
/* Several macros make the code a bit clearer:                              */
107
134
/*                                                                          */
108
135
/*                                                                          */
110
137
#define at_eof(iop)     ((iop->flag & IOP_AT_EOF) != 0)
111
138
#define has_no_data(iop)        (iop->dataend == NULL)
112
139
#define no_data_left(iop)       (iop->off >= iop->dataend)
 
140
#define is_internal(iop) ((iop->flag & IOP_IS_INTERNAL) != 0)
113
141
/* The key point to the design is to split out the code that searches through */
114
142
/* a buffer looking for the record and the terminator into separate routines, */
115
143
/* with a higher-level routine doing the reading of data and buffer management. */
158
186
static int wait_any P((int interesting));
159
187
#endif
160
188
static IOBUF *gawk_popen P((const char *cmd, struct redirect *rp));
161
 
static IOBUF *iop_open P((const char *file, const char *how, IOBUF *buf));
 
189
static IOBUF *iop_open P((const char *file, const char *how, IOBUF *buf, int *isdir));
162
190
static IOBUF *iop_alloc P((int fd, const char *name, IOBUF *buf));
163
191
static int gawk_pclose P((struct redirect *rp));
164
192
static int do_pathopen P((const char *file));
165
193
static int str2mode P((const char *mode));
166
 
static void spec_setup P((IOBUF *iop, int len, int allocate));
167
 
static int specfdopen P((IOBUF *iop, const char *name, const char *mode));
168
 
static int pidopen P((IOBUF *iop, const char *name, const char *mode));
169
 
static int useropen P((IOBUF *iop, const char *name, const char *mode));
 
194
static void spec_setup P((IOBUF *iop, int len));
 
195
static IOBUF *specfdopen P((IOBUF *iop, const char *name, const char *mode));
 
196
static IOBUF *pidopen P((IOBUF *iop, const char *name, const char *mode));
 
197
static IOBUF *useropen P((IOBUF *iop, const char *name, const char *mode));
170
198
static int two_way_open P((const char *str, struct redirect *rp));
171
199
static int pty_vs_pipe P((const char *command));
172
200
 
275
303
                        ARGIND_node->var_value = make_number((AWKNUM) i);
276
304
                }
277
305
                if (! arg_assign(arg->stptr, FALSE)) {
 
306
                        int isdir = FALSE;
 
307
 
278
308
                        files = TRUE;
279
309
                        fname = arg->stptr;
280
 
                        curfile = iop_open(fname, binmode("r"), &mybuf);
281
 
                        if (curfile == NULL)
 
310
                        curfile = iop_open(fname, binmode("r"), &mybuf, & isdir);
 
311
                        if (curfile == NULL) {
 
312
#if NO_DIRECTORY_FATAL
 
313
                                if (isdir)
 
314
                                        continue;
 
315
#else
 
316
                                if (isdir && do_traditional)
 
317
                                        continue;
 
318
#endif
282
319
                                goto give_up;
 
320
                        }
283
321
                        curfile->flag |= IOP_NOFREE_OBJ;
284
322
                        /* This is a kludge.  */
285
323
                        unref(FILENAME_node->var_value);
296
334
                unref(FILENAME_node->var_value);
297
335
                FILENAME_node->var_value = make_string("-", 1);
298
336
                fname = "-";
299
 
                curfile = iop_open(fname, binmode("r"), &mybuf);
 
337
                curfile = iop_open(fname, binmode("r"), &mybuf, NULL);
300
338
                if (curfile == NULL)
301
339
                        goto give_up;
302
340
                curfile->flag |= IOP_NOFREE_OBJ;
503
541
        const char *mode;
504
542
        int fd;
505
543
        const char *what = NULL;
 
544
        int isdir = FALSE;
506
545
 
507
546
        switch (tree->type) {
508
547
        case Node_redirect_append:
654
693
                        break;
655
694
                case Node_redirect_input:
656
695
                        direction = "from";
657
 
                        rp->iop = iop_open(str, binmode("r"), NULL);
 
696
                        rp->iop = iop_open(str, binmode("r"), NULL, & isdir);
 
697
                        if (isdir)
 
698
                                fatal(_("file `%s' is a directory"), str);
658
699
                        break;
659
700
                case Node_redirect_twoway:
660
701
                        direction = "to/from";
1129
1170
}
1130
1171
 
1131
1172
#ifdef HAVE_SOCKETS
 
1173
 
1132
1174
/* socketopen --- open a socket and set it into connected state */
1133
1175
 
1134
1176
static int
1135
 
socketopen(enum inet_prot type, int localport, int remoteport, const char *remotehostname)
 
1177
socketopen(int type, const char *localpname, const char *remotepname,
 
1178
        const char *remotehostname)
1136
1179
{
1137
 
        struct hostent *hp = gethostbyname(remotehostname);
1138
 
        struct sockaddr_in local_addr, remote_addr;
1139
 
        int socket_fd;
1140
 
        int any_remote_host = strcmp(remotehostname, "0");
1141
 
 
1142
 
        socket_fd = INVALID_HANDLE;
1143
 
        switch (type) {
1144
 
        case INET_TCP:  
1145
 
                if (localport != 0 || remoteport != 0) {
1146
 
                        int on = 1;
1147
 
#ifdef SO_LINGER
1148
 
                        struct linger linger;
1149
 
 
1150
 
                        memset(& linger, '\0', sizeof(linger));
1151
 
#endif
1152
 
                        socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
1153
 
                        setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR,
1154
 
                                (char *) & on, sizeof(on));
1155
 
#ifdef SO_LINGER
1156
 
                        linger.l_onoff = 1;
1157
 
                        linger.l_linger = 30;    /* linger for 30/100 second */
1158
 
                        setsockopt(socket_fd, SOL_SOCKET, SO_LINGER,
1159
 
                                (char *) & linger, sizeof(linger));
1160
 
#endif
 
1180
        struct addrinfo *lres, *lres0;
 
1181
        struct addrinfo lhints;
 
1182
        struct addrinfo *rres, *rres0;
 
1183
        struct addrinfo rhints;
 
1184
 
 
1185
        int lerror;
 
1186
        int rerror;
 
1187
 
 
1188
        int socket_fd = INVALID_HANDLE;
 
1189
        int any_remote_host = (strcmp(remotehostname, "0") == 0);
 
1190
 
 
1191
        memset (&lhints, '\0', sizeof (lhints));
 
1192
        lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
 
1193
        lhints.ai_socktype = type;
 
1194
 
 
1195
        lerror = getaddrinfo (NULL, localpname, &lhints, &lres);
 
1196
        if (lerror) {
 
1197
                if (strcmp(localpname, "0") != 0)
 
1198
                        fatal(_("local port %s invalid in `/inet'"), localpname);
 
1199
                lres0 = NULL;
 
1200
                lres = &lhints;
 
1201
        } else
 
1202
                lres0 = lres;
 
1203
 
 
1204
        while (lres != NULL) {
 
1205
                memset (&rhints, '\0', sizeof (rhints));
 
1206
                rhints.ai_flags = lhints.ai_flags;
 
1207
                rhints.ai_socktype = lhints.ai_socktype;
 
1208
                rhints.ai_family = lhints.ai_family;
 
1209
                rhints.ai_protocol = lhints.ai_protocol;
 
1210
 
 
1211
                rerror = getaddrinfo (remotehostname, remotepname, &rhints, &rres);
 
1212
                if (rerror) {
 
1213
                        if (lres0 != NULL)
 
1214
                                freeaddrinfo(lres0);
 
1215
                        fatal(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname);
1161
1216
                }
1162
 
                break;
1163
 
        case INET_UDP:  
1164
 
                if (localport != 0 || remoteport != 0)
1165
 
                        socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
1166
 
                break;
1167
 
        case INET_RAW:  
1168
 
#ifdef SOCK_RAW
1169
 
                if (localport == 0 && remoteport == 0)
1170
 
                        socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 
1171
 
#endif
1172
 
                break;
1173
 
        case INET_NONE:
1174
 
                /* fall through */
1175
 
        default:
1176
 
                cant_happen();
1177
 
                break;
1178
 
        }
1179
 
 
1180
 
        if (socket_fd < 0 || socket_fd == INVALID_HANDLE
1181
 
            || (hp == NULL && any_remote_host != 0))
1182
 
                return INVALID_HANDLE;
1183
 
 
1184
 
        local_addr.sin_family = remote_addr.sin_family = AF_INET;
1185
 
        local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1186
 
        remote_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1187
 
        local_addr.sin_port  = htons(localport);
1188
 
        remote_addr.sin_port = htons(remoteport);
1189
 
        if (bind(socket_fd, (struct sockaddr *) &local_addr, sizeof(local_addr)) == 0) {
1190
 
                if (any_remote_host != 0) { /* not ANY => create a client */
1191
 
                        if (type == INET_TCP || type == INET_UDP) {
1192
 
                                memcpy(&remote_addr.sin_addr, hp->h_addr,
1193
 
                                        sizeof(remote_addr.sin_addr));
1194
 
                                if (connect(socket_fd,
1195
 
                                                (struct sockaddr *) &remote_addr,
1196
 
                                                sizeof(remote_addr)) != 0) {
1197
 
                                        close(socket_fd);
1198
 
                                        if (localport == 0)
1199
 
                                                socket_fd = INVALID_HANDLE;
1200
 
                                        else
1201
 
                                                socket_fd = socketopen(type, localport, 0, "0");
 
1217
                rres0 = rres;
 
1218
                socket_fd = INVALID_HANDLE;
 
1219
                while (rres != NULL) {
 
1220
                        socket_fd = socket (rres->ai_family,
 
1221
                                rres->ai_socktype, rres->ai_protocol);
 
1222
                        if (socket_fd < 0 || socket_fd == INVALID_HANDLE)
 
1223
                                goto nextrres;
 
1224
 
 
1225
                        if (type == SOCK_STREAM) {
 
1226
                                int on = 1;
 
1227
#ifdef SO_LINGER
 
1228
                                struct linger linger;
 
1229
                                memset(& linger, '\0', sizeof(linger));
 
1230
#endif
 
1231
                                setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR,
 
1232
                                        (char *) & on, sizeof(on));
 
1233
#ifdef SO_LINGER
 
1234
                                linger.l_onoff = 1;
 
1235
                                linger.l_linger = 30;    /* linger for 30/100 second */
 
1236
                                setsockopt(socket_fd, SOL_SOCKET, SO_LINGER,
 
1237
                                        (char *) & linger, sizeof(linger));
 
1238
#endif
 
1239
                        }
 
1240
                        if (bind(socket_fd, lres->ai_addr, lres->ai_addrlen) != 0)
 
1241
                                goto nextrres;
 
1242
 
 
1243
                        if (! any_remote_host) { /* not ANY => create a client */
 
1244
                                if (type != SOCK_RAW) {
 
1245
                                        if (connect(socket_fd, rres->ai_addr,
 
1246
                                                rres->ai_addrlen) == 0)
 
1247
                                                break;
 
1248
                                } else {
 
1249
                                        /* /inet/raw client not ready yet */ 
 
1250
                                        fatal(_("/inet/raw client not ready yet, sorry"));
 
1251
                                        if (geteuid() != 0)
 
1252
                                                /* FIXME: is this second fatal ever reached? */
 
1253
                                                fatal(_("only root may use `/inet/raw'."));
1202
1254
                                }
1203
 
                        } else {
1204
 
                                /* /inet/raw client not ready yet */ 
1205
 
                                fatal(_("/inet/raw client not ready yet, sorry"));
1206
 
                                if (geteuid() != 0)
1207
 
                                        fatal(_("only root may use `/inet/raw'."));
1208
 
                        }
1209
 
                } else { /* remote host is ANY => create a server */
1210
 
                        if (type == INET_TCP) {
1211
 
                                int clientsocket_fd = INVALID_HANDLE;
1212
 
                                socklen_t namelen = sizeof(remote_addr);
1213
 
 
1214
 
                                if (listen(socket_fd, 1) >= 0
1215
 
                                    && (clientsocket_fd = accept(socket_fd,
 
1255
                        } else { /* remote host is ANY => create a server */
 
1256
                                if (type == SOCK_STREAM) {
 
1257
                                        int clientsocket_fd = INVALID_HANDLE;
 
1258
 
 
1259
                                        struct sockaddr_storage remote_addr;
 
1260
                                        socklen_t namelen = sizeof (remote_addr);
 
1261
 
 
1262
                                        if (listen(socket_fd, 1) >= 0
 
1263
                                            && (clientsocket_fd = accept(socket_fd,
1216
1264
                                                (struct sockaddr *) &remote_addr,
1217
1265
                                                &namelen)) >= 0) {
1218
 
                                        close(socket_fd);
1219
 
                                        socket_fd = clientsocket_fd;
1220
 
                                } else {
1221
 
                                        close(socket_fd);
1222
 
                                        socket_fd = INVALID_HANDLE;
1223
 
                                }
1224
 
                        } else if (type == INET_UDP) {
 
1266
                                                close(socket_fd);
 
1267
                                                socket_fd = clientsocket_fd;
 
1268
                                                break;
 
1269
                                        }
 
1270
                                } else if (type == SOCK_DGRAM) {
1225
1271
#ifdef MSG_PEEK
1226
 
                                char buf[10];
1227
 
                                socklen_t readle;
 
1272
                                        char buf[10];
 
1273
                                        struct sockaddr_storage remote_addr;
 
1274
                                        socklen_t readle;
1228
1275
 
1229
 
                                if (recvfrom(socket_fd, buf, 1, MSG_PEEK,
1230
 
                                        (struct sockaddr *) & remote_addr,
1231
 
                                        & readle) < 1
1232
 
                                                || readle != sizeof(remote_addr)
1233
 
                                    || connect(socket_fd,
1234
 
                                        (struct sockaddr *)& remote_addr,
1235
 
                                                readle) != 0) {
1236
 
                                        close(socket_fd);
1237
 
                                        socket_fd = INVALID_HANDLE;
 
1276
                                        if (recvfrom(socket_fd, buf, 1, MSG_PEEK,
 
1277
                                                (struct sockaddr *) & remote_addr,
 
1278
                                                        & readle) >= 0
 
1279
                                                        && readle
 
1280
                                                        && connect(socket_fd,
 
1281
                                                (struct sockaddr *)& remote_addr,
 
1282
                                                                readle) == 0)
 
1283
                                                        break;
 
1284
#endif
 
1285
                                } else {
 
1286
                                        /* /inet/raw server not ready yet */ 
 
1287
                                        fatal(_("/inet/raw server not ready yet, sorry"));
 
1288
                                        if (geteuid() != 0)
 
1289
                                                fatal(_("only root may use `/inet/raw'."));
1238
1290
                                }
1239
 
#endif
1240
 
                        } else {
1241
 
                                /* /inet/raw server not ready yet */ 
1242
 
                                fatal(_("/inet/raw server not ready yet, sorry"));
1243
 
                                if (geteuid() != 0)
1244
 
                                        fatal(_("only root may use `/inet/raw'."));
1245
1291
                        }
 
1292
 
 
1293
nextrres:
 
1294
                        if (socket_fd != INVALID_HANDLE)
 
1295
                                close(socket_fd);
 
1296
                        socket_fd = INVALID_HANDLE;
 
1297
                        rres = rres->ai_next;
1246
1298
                }
1247
 
        } else {
1248
 
                close(socket_fd);
1249
 
                socket_fd = INVALID_HANDLE;
 
1299
                freeaddrinfo(rres0);
 
1300
                if (socket_fd != INVALID_HANDLE)
 
1301
                        break;
 
1302
                lres = lres->ai_next;
1250
1303
        }
 
1304
        if (lres0)
 
1305
                freeaddrinfo(lres0);
1251
1306
 
1252
1307
        return socket_fd;
1253
1308
}
1312
1367
        } else if (STREQN(name, "/inet/", 6)) {
1313
1368
#ifdef HAVE_SOCKETS
1314
1369
                /* /inet/protocol/localport/hostname/remoteport */
1315
 
                enum inet_prot protocol = INET_NONE;
1316
 
                int localport, remoteport;
 
1370
                int protocol;
1317
1371
                char *hostname;
1318
1372
                char *hostnameslastcharp;
1319
1373
                char *localpname;
1320
 
                char proto[4];
1321
 
                struct servent *service;
 
1374
                char *localpnamelastcharp;
1322
1375
 
1323
1376
                cp = (char *) name + 6;
1324
1377
                /* which protocol? */
1325
1378
                if (STREQN(cp, "tcp/", 4))
1326
 
                        protocol = INET_TCP;
 
1379
                        protocol = SOCK_STREAM;
1327
1380
                else if (STREQN(cp, "udp/", 4))
1328
 
                        protocol = INET_UDP;
 
1381
                        protocol = SOCK_DGRAM;
1329
1382
                else if (STREQN(cp, "raw/", 4))
1330
 
                        protocol = INET_RAW;
 
1383
                        protocol = SOCK_RAW;
1331
1384
                else
1332
1385
                        fatal(_("no (known) protocol supplied in special filename `%s'"),
1333
1386
                                name);
1334
1387
 
1335
 
                proto[0] = cp[0];
1336
 
                proto[1] = cp[1];   
1337
 
                proto[2] = cp[2];   
1338
 
                proto[3] =  '\0';
1339
1388
                cp += 4;
1340
1389
 
1341
1390
                /* which localport? */
1353
1402
                 * By using atoi() the use of decimal numbers is enforced.
1354
1403
                 */
1355
1404
                *cp = '\0';
1356
 
 
1357
 
                localport = atoi(localpname);
1358
 
                if (strcmp(localpname, "0") != 0
1359
 
                    && (localport <= 0 || localport > 65535)) {
1360
 
                        service = getservbyname(localpname, proto);
1361
 
                        if (service == NULL)
1362
 
                                fatal(_("local port invalid in `%s'"), name);
1363
 
                        else
1364
 
                                localport = ntohs(service->s_port);
1365
 
                }
1366
 
                *cp = '/';
 
1405
                localpnamelastcharp = cp;
1367
1406
 
1368
1407
                /* which hostname? */
1369
1408
                cp++;
1370
1409
                hostname = cp;
1371
1410
                while (*cp != '/' && *cp != '\0')
1372
1411
                        cp++; 
1373
 
                if (*cp != '/' || cp == hostname)
 
1412
                if (*cp != '/' || cp == hostname) {
 
1413
                        *localpnamelastcharp = '/';
1374
1414
                        fatal(_("must supply a remote hostname to `/inet'"));
 
1415
                }
1375
1416
                *cp = '\0';
1376
1417
                hostnameslastcharp = cp;
1377
1418
 
1385
1426
                 * Here too, require a port, let them explicitly put 0 if
1386
1427
                 * they don't care.
1387
1428
                 */
1388
 
                if (*cp == '\0')
 
1429
                if (*cp == '\0') {
 
1430
                        *localpnamelastcharp = '/';
 
1431
                        *hostnameslastcharp = '/';
1389
1432
                        fatal(_("must supply a remote port to `/inet'"));
1390
 
                remoteport = atoi(cp);
1391
 
                if (strcmp(cp, "0") != 0
1392
 
                    && (remoteport <= 0 || remoteport > 65535)) {
1393
 
                        service = getservbyname(cp, proto);
1394
 
                        if (service == NULL)
1395
 
                                 fatal(_("remote port invalid in `%s'"), name);
1396
 
                        else
1397
 
                                remoteport = ntohs(service->s_port);
1398
1433
                }
1399
1434
 
1400
 
                /* Open Sesame! */
1401
 
                openfd = socketopen(protocol, localport, remoteport, hostname);
 
1435
                openfd = socketopen(protocol, localpname, cp, hostname);
 
1436
                *localpnamelastcharp = '/';
1402
1437
                *hostnameslastcharp = '/';
1403
 
 
1404
1438
#else /* ! HAVE_SOCKETS */
1405
1439
                fatal(_("TCP/IP communications are not supported"));
1406
1440
#endif /* HAVE_SOCKETS */
1422
1456
/* spec_setup --- setup an IOBUF for a special internal file */
1423
1457
 
1424
1458
static void
1425
 
spec_setup(IOBUF *iop, int len, int allocate)
 
1459
spec_setup(IOBUF *iop, int len)
1426
1460
{
1427
1461
        char *cp;
1428
1462
 
1429
 
        if (allocate) {
1430
 
                emalloc(cp, char *, len+2, "spec_setup");
1431
 
                iop->buf = cp;
1432
 
        } else {
1433
 
                len = strlen(iop->buf);
1434
 
                iop->buf[len++] = '\n'; /* get_a_record clobbered it */
1435
 
                iop->buf[len] = '\0';   /* just in case */
1436
 
        }
 
1463
        emalloc(cp, char *, len+2, "spec_setup");
 
1464
        iop->buf = cp;
1437
1465
        iop->off = iop->buf;
1438
1466
        iop->count = 0;
1439
1467
        iop->size = len;
1440
1468
        iop->end = iop->buf + len;
1441
1469
        iop->dataend = iop->end;
1442
1470
        iop->fd = -1;
1443
 
        iop->flag = IOP_IS_INTERNAL | IOP_AT_START;
 
1471
        iop->flag = IOP_IS_INTERNAL | IOP_AT_START | IOP_NO_FREE;
1444
1472
}
1445
1473
 
1446
1474
/* specfdopen --- open an fd special file */
1447
1475
 
1448
 
static int
 
1476
static IOBUF *
1449
1477
specfdopen(IOBUF *iop, const char *name, const char *mode)
1450
1478
{
1451
1479
        int fd;
1453
1481
 
1454
1482
        fd = devopen(name, mode);
1455
1483
        if (fd == INVALID_HANDLE)
1456
 
                return INVALID_HANDLE;
1457
 
        tp = iop_alloc(fd, name, NULL);
 
1484
                return NULL;
 
1485
        tp = iop_alloc(fd, name, iop);
1458
1486
        if (tp == NULL) {
1459
1487
                /* don't leak fd's */
1460
1488
                close(fd);
1461
 
                return INVALID_HANDLE;
 
1489
                return NULL;
1462
1490
        }
1463
 
        *iop = *tp;
1464
 
        iop->flag |= IOP_NO_FREE;
1465
 
        free(tp);
1466
 
        return 0;
 
1491
        return tp;
1467
1492
}
1468
1493
 
1469
1494
#ifdef GETPGRP_VOID
1474
1499
 
1475
1500
/* pidopen --- "open" /dev/pid, /dev/ppid, and /dev/pgrpid */
1476
1501
 
1477
 
static int
 
1502
static IOBUF *
1478
1503
pidopen(IOBUF *iop, const char *name, const char *mode ATTRIBUTE_UNUSED)
1479
1504
{
1480
1505
        char tbuf[BUFSIZ];
1483
1508
 
1484
1509
        warning(_("use `PROCINFO[\"%s\"]' instead of `%s'"), cp, name);
1485
1510
 
 
1511
        if (iop == NULL) {
 
1512
                iop = iop_alloc(INTERNAL_HANDLE, name, iop);
 
1513
                if (iop == NULL)
 
1514
                        return NULL;
 
1515
        }
 
1516
 
1486
1517
        if (name[6] == 'g')
1487
1518
                sprintf(tbuf, "%d\n", (int) getpgrp(getpgrp_arg()));
1488
1519
        else if (name[6] == 'i')
1490
1521
        else
1491
1522
                sprintf(tbuf, "%d\n", (int) getppid());
1492
1523
        i = strlen(tbuf);
1493
 
        spec_setup(iop, i, TRUE);
 
1524
        spec_setup(iop, i);
1494
1525
        strcpy(iop->buf, tbuf);
1495
 
        return 0;
 
1526
        return iop;
1496
1527
}
1497
1528
 
1498
1529
/* useropen --- "open" /dev/user */
1507
1538
 * supplementary group set.
1508
1539
 */
1509
1540
 
1510
 
static int
 
1541
static IOBUF *
1511
1542
useropen(IOBUF *iop, const char *name ATTRIBUTE_UNUSED, const char *mode ATTRIBUTE_UNUSED)
1512
1543
{
1513
1544
        char tbuf[BUFSIZ], *cp;
1515
1546
 
1516
1547
        warning(_("use `PROCINFO[...]' instead of `/dev/user'"));
1517
1548
 
 
1549
        if (iop == NULL) {
 
1550
                iop = iop_alloc(INTERNAL_HANDLE, name, iop);
 
1551
                if (iop == NULL)
 
1552
                        return NULL;
 
1553
        }
 
1554
 
1518
1555
        sprintf(tbuf, "%d %d %d %d", (int) getuid(), (int) geteuid(), (int) getgid(), (int) getegid());
1519
1556
 
1520
1557
        cp = tbuf + strlen(tbuf);
1529
1566
        *cp++ = '\0';
1530
1567
 
1531
1568
        i = strlen(tbuf);
1532
 
        spec_setup(iop, i, TRUE);
 
1569
        spec_setup(iop, i);
1533
1570
        strcpy(iop->buf, tbuf);
1534
 
        return 0;
 
1571
        return iop;
1535
1572
}
1536
1573
 
1537
1574
/* iop_open --- handle special and regular files for input */
1538
1575
 
1539
1576
static IOBUF *
1540
 
iop_open(const char *name, const char *mode, IOBUF *iop)
 
1577
iop_open(const char *name, const char *mode, IOBUF *iop, int *isdir)
1541
1578
{
1542
1579
        int openfd = INVALID_HANDLE;
1543
1580
        int flag = 0;
1544
1581
        static struct internal {
1545
1582
                const char *name;
1546
1583
                int compare;
1547
 
                int (*fp) P((IOBUF *, const char *, const char *));
1548
 
                IOBUF iob;
 
1584
                IOBUF *(*fp) P((IOBUF *, const char *, const char *));
1549
1585
        } table[] = {
1550
1586
                { "/dev/fd/",           8,      specfdopen },
1551
1587
                { "/dev/stdin",         10,     specfdopen },
1570
1606
 
1571
1607
                for (i = 0; i < devcount; i++) {
1572
1608
                        if (STREQN(name, table[i].name, table[i].compare)) {
1573
 
                                iop = & table[i].iob;
1574
 
 
1575
 
                                if (iop->buf != NULL) {
1576
 
                                        spec_setup(iop, 0, FALSE);
1577
 
                                        return iop;
1578
 
                                } else if ((*table[i].fp)(iop, name, mode) == 0)
 
1609
                                if ((iop = (*table[i].fp)(iop, name, mode)) != NULL)
1579
1610
                                        return iop;
1580
1611
                                else {
1581
1612
                                        warning(_("could not open `%s', mode `%s'"),
1591
1622
        if (openfd == INVALID_HANDLE)
1592
1623
                openfd = open(name, flag, 0666);
1593
1624
        if (openfd != INVALID_HANDLE) {
1594
 
                if (os_isdir(openfd))
1595
 
                        fatal(_("file `%s' is a directory"), name);
 
1625
                if (os_isdir(openfd)) {
 
1626
                        if (isdir)
 
1627
                                *isdir = TRUE;
 
1628
                        (void) close(openfd);   /* don't leak fds */
 
1629
                        return NULL;
 
1630
                }
1596
1631
        }
1597
1632
        /*
1598
1633
         * At this point, fd could still be INVALID_HANDLE.
2480
2515
{
2481
2516
        struct stat sbuf;
2482
2517
        struct open_hook *oh;
 
2518
        int iop_malloced = FALSE;
2483
2519
 
2484
 
        if (iop == NULL)
 
2520
        if (iop == NULL) {
2485
2521
                emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
 
2522
                iop_malloced = TRUE;
 
2523
        }
2486
2524
        memset(iop, '\0', sizeof(IOBUF));
2487
2525
        iop->flag = 0;
2488
2526
        iop->fd = fd;
2494
2532
                        break;
2495
2533
        }
2496
2534
 
 
2535
        if (iop->fd == INTERNAL_HANDLE)
 
2536
                return iop;
 
2537
 
2497
2538
        if (iop->fd == INVALID_HANDLE) {
2498
 
                free(iop);
 
2539
                if (iop_malloced)
 
2540
                        free(iop);
2499
2541
                return NULL;
2500
2542
        }
2501
2543
        if (isatty(iop->fd))
2503
2545
        iop->readsize = iop->size = optimal_bufsize(iop->fd, & sbuf);
2504
2546
        iop->sbuf = sbuf;
2505
2547
        if (do_lint && S_ISREG(sbuf.st_mode) && sbuf.st_size == 0)
2506
 
                        lintwarn(_("data file `%s' is empty"), name);
 
2548
                lintwarn(_("data file `%s' is empty"), name);
2507
2549
        errno = 0;
2508
2550
        iop->count = iop->scanoff = 0;
2509
2551
        emalloc(iop->buf, char *, iop->size += 2, "iop_alloc");
2886
2928
/* <getarecord>=                                                            */
2887
2929
/* get_a_record --- read a record from IOP into out, return length of EOF, set RT */
2888
2930
 
2889
 
int
 
2931
static int
2890
2932
get_a_record(char **out,        /* pointer to pointer to data */
2891
2933
        IOBUF *iop,             /* input IOP */
2892
2934
        int *errcode)           /* pointer to error variable */
2906
2948
 
2907
2949
        /* <fill initial buffer>=                                                   */
2908
2950
        if (has_no_data(iop) || no_data_left(iop)) {
 
2951
                if (is_internal(iop)) {
 
2952
                        iop->flag |= IOP_AT_EOF;
 
2953
                        return EOF;
 
2954
                }
2909
2955
                iop->count = read(iop->fd, iop->buf, iop->readsize);
2910
2956
                if (iop->count == 0) {
2911
2957
                        iop->flag |= IOP_AT_EOF;
2974
3020
                        while (amt_to_read + iop->readsize < room_left)
2975
3021
                                amt_to_read += iop->readsize;
2976
3022
 
 
3023
#ifdef SSIZE_MAX
 
3024
                        /*
 
3025
                         * POSIX limits read to SSIZE_MAX. There are (bizarre)
 
3026
                         * systems where this amount is small.
 
3027
                         */
 
3028
                        amt_to_read = min(amt_to_read, SSIZE_MAX);
 
3029
#endif
 
3030
 
2977
3031
                        iop->count = read(iop->fd, iop->dataend, amt_to_read);
2978
3032
                        if (iop->count == -1) {
2979
3033
                                if (! do_traditional && errcode != NULL) {
3097
3151
                RS_is_null = TRUE;
3098
3152
                matchrec = rsnullscan;
3099
3153
        } else if (RS->stlen > 1) {
3100
 
                static int warned = FALSE;
 
3154
                static short warned = FALSE;
3101
3155
 
3102
3156
                RS_re_yes_case = make_regexp(RS->stptr, RS->stlen, FALSE, TRUE);
3103
3157
                RS_re_no_case = make_regexp(RS->stptr, RS->stlen, TRUE, TRUE);