Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/sh/io.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1982-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* Input/output file processing
24
*
25
* David Korn
26
* AT&T Labs
27
*
28
*/
29
30
#include "defs.h"
31
#include <fcin.h>
32
#include <ls.h>
33
#include <stdarg.h>
34
#include <regex.h>
35
#include "variables.h"
36
#include "path.h"
37
#include "io.h"
38
#include "jobs.h"
39
#include "shnodes.h"
40
#include "history.h"
41
#include "edit.h"
42
#include "timeout.h"
43
#include "FEATURE/externs"
44
#include "FEATURE/dynamic"
45
#include "FEATURE/poll"
46
47
#ifdef FNDELAY
48
# ifdef EAGAIN
49
# if EAGAIN!=EWOULDBLOCK
50
# undef EAGAIN
51
# define EAGAIN EWOULDBLOCK
52
# endif
53
# else
54
# define EAGAIN EWOULDBLOCK
55
# endif /* EAGAIN */
56
# ifndef O_NONBLOCK
57
# define O_NONBLOCK FNDELAY
58
# endif /* !O_NONBLOCK */
59
#endif /* FNDELAY */
60
61
#ifndef O_SERVICE
62
# define O_SERVICE O_NOCTTY
63
#endif
64
65
#ifndef ERROR_PIPE
66
#ifdef ECONNRESET
67
#define ERROR_PIPE(e) ((e)==EPIPE||(e)==ECONNRESET)
68
#else
69
#define ERROR_PIPE(e) ((e)==EPIPE)
70
#endif
71
#endif
72
73
#define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
74
75
static void *timeout;
76
static int (*fdnotify)(int,int);
77
78
#if defined(_lib_socket) && defined(_sys_socket) && defined(_hdr_netinet_in)
79
# include <sys/socket.h>
80
# include <netdb.h>
81
# include <netinet/in.h>
82
# if !defined(htons) && !_lib_htons
83
# define htons(x) (x)
84
# endif
85
# if !defined(htonl) && !_lib_htonl
86
# define htonl(x) (x)
87
# endif
88
# if _pipe_socketpair && !_stream_peek
89
# ifndef SHUT_RD
90
# define SHUT_RD 0
91
# endif
92
# ifndef SHUT_WR
93
# define SHUT_WR 1
94
# endif
95
# if _socketpair_shutdown_mode
96
# define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||fchmod((v)[1],S_IWUSR)<0||shutdown((v)[0],SHUT_WR)<0||fchmod((v)[0],S_IRUSR)<0)?(-1):0)
97
# else
98
# define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||shutdown((v)[0],SHUT_WR)<0)?(-1):0)
99
# endif
100
# endif
101
102
#if !_lib_getaddrinfo
103
104
#undef EAI_SYSTEM
105
106
#define EAI_SYSTEM 1
107
108
#undef addrinfo
109
#undef getaddrinfo
110
#undef freeaddrinfo
111
112
#define addrinfo local_addrinfo
113
#define getaddrinfo local_getaddrinfo
114
#define freeaddrinfo local_freeaddrinfo
115
116
struct addrinfo
117
{
118
int ai_flags;
119
int ai_family;
120
int ai_socktype;
121
int ai_protocol;
122
socklen_t ai_addrlen;
123
struct sockaddr* ai_addr;
124
struct addrinfo* ai_next;
125
};
126
127
static int
128
getaddrinfo(const char* node, const char* service, const struct addrinfo* hint, struct addrinfo **addr)
129
{
130
unsigned long ip_addr = 0;
131
unsigned short ip_port = 0;
132
struct addrinfo* ap;
133
struct hostent* hp;
134
struct sockaddr_in* ip;
135
char* prot;
136
long n;
137
138
if (!(hp = gethostbyname(node)) || hp->h_addrtype!=AF_INET || hp->h_length>sizeof(struct in_addr))
139
{
140
errno = EADDRNOTAVAIL;
141
return EAI_SYSTEM;
142
}
143
ip_addr = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr;
144
if ((n = strtol(service, &prot, 10)) > 0 && n <= USHRT_MAX && !*prot)
145
ip_port = htons((unsigned short)n);
146
else
147
{
148
struct servent* sp;
149
const char* protocol = 0;
150
151
if (hint)
152
switch (hint->ai_socktype)
153
{
154
case SOCK_STREAM:
155
switch (hint->ai_protocol)
156
{
157
case 0:
158
protocol = "tcp";
159
break;
160
#ifdef IPPROTO_SCTP
161
case IPPROTO_SCTP:
162
protocol = "sctp";
163
break;
164
#endif
165
}
166
break;
167
case SOCK_DGRAM:
168
protocol = "udp";
169
break;
170
}
171
if (!protocol)
172
{
173
errno = EPROTONOSUPPORT;
174
return 1;
175
}
176
if (sp = getservbyname(service, protocol))
177
ip_port = sp->s_port;
178
}
179
if (!ip_port)
180
{
181
errno = EADDRNOTAVAIL;
182
return EAI_SYSTEM;
183
}
184
if (!(ap = newof(0, struct addrinfo, 1, sizeof(struct sockaddr_in))))
185
return EAI_SYSTEM;
186
if (hint)
187
*ap = *hint;
188
ap->ai_family = hp->h_addrtype;
189
ap->ai_addrlen = sizeof(struct sockaddr_in);
190
ap->ai_addr = (struct sockaddr *)(ap+1);
191
ip = (struct sockaddr_in *)ap->ai_addr;
192
ip->sin_family = AF_INET;
193
ip->sin_port = ip_port;
194
ip->sin_addr.s_addr = ip_addr;
195
*addr = ap;
196
return 0;
197
}
198
199
static void
200
freeaddrinfo(struct addrinfo* ap)
201
{
202
if (ap)
203
free(ap);
204
}
205
206
#endif
207
208
/*
209
* return <protocol>/<host>/<service> fd
210
* If called with flags==O_NONBLOCK return 1 if protocol is supported
211
*/
212
213
typedef int (*Inetintr_f)(struct addrinfo*, void*);
214
215
static int
216
inetopen(const char* path, int flags, Inetintr_f onintr, void* handle)
217
{
218
register char* s;
219
register char* t;
220
int fd;
221
int oerrno;
222
struct addrinfo hint;
223
struct addrinfo* addr;
224
struct addrinfo* p;
225
int server = !!(flags&O_SERVICE);
226
227
memset(&hint, 0, sizeof(hint));
228
hint.ai_family = PF_UNSPEC;
229
switch (path[0])
230
{
231
#ifdef IPPROTO_SCTP
232
case 's':
233
if (path[1]!='c' || path[2]!='t' || path[3]!='p' || path[4]!='/')
234
{
235
errno = ENOTDIR;
236
return -1;
237
}
238
hint.ai_socktype = SOCK_STREAM;
239
hint.ai_protocol = IPPROTO_SCTP;
240
path += 5;
241
break;
242
#endif
243
case 't':
244
if (path[1]!='c' || path[2]!='p' || path[3]!='/')
245
{
246
errno = ENOTDIR;
247
return -1;
248
}
249
hint.ai_socktype = SOCK_STREAM;
250
path += 4;
251
break;
252
case 'u':
253
if (path[1]!='d' || path[2]!='p' || path[3]!='/')
254
{
255
errno = ENOTDIR;
256
return -1;
257
}
258
hint.ai_socktype = SOCK_DGRAM;
259
path += 4;
260
break;
261
default:
262
errno = ENOTDIR;
263
return -1;
264
}
265
if(flags==O_NONBLOCK)
266
return 1;
267
if (!(s = strdup(path)))
268
return -1;
269
if (t = strchr(s, '/'))
270
{
271
*t++ = 0;
272
if (streq(s, "local"))
273
s = strdup("localhost");
274
fd = getaddrinfo(s, t, &hint, &addr);
275
}
276
else
277
fd = -1;
278
free(s);
279
if (fd)
280
{
281
if (fd != EAI_SYSTEM)
282
errno = ENOTDIR;
283
return -1;
284
}
285
oerrno = errno;
286
errno = 0;
287
fd = -1;
288
for (p = addr; p; p = p->ai_next)
289
{
290
/*
291
* some api's don't take the hint
292
*/
293
294
if (!p->ai_protocol)
295
p->ai_protocol = hint.ai_protocol;
296
if (!p->ai_socktype)
297
p->ai_socktype = hint.ai_socktype;
298
while ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) >= 0)
299
{
300
if (server && !bind(fd, p->ai_addr, p->ai_addrlen) && !listen(fd, 5) || !server && !connect(fd, p->ai_addr, p->ai_addrlen))
301
goto done;
302
close(fd);
303
fd = -1;
304
if (errno != EINTR || !onintr)
305
break;
306
if ((*onintr)(addr, handle))
307
goto done;
308
}
309
}
310
done:
311
freeaddrinfo(addr);
312
if (fd >= 0)
313
errno = oerrno;
314
return fd;
315
}
316
317
#else
318
319
#undef O_SERVICE
320
#undef SHOPT_COSHELL
321
322
#endif
323
324
struct fdsave
325
{
326
int orig_fd; /* original file descriptor */
327
int save_fd; /* saved file descriptor */
328
int subshell; /* saved for subshell */
329
char *tname; /* name used with >; */
330
};
331
332
struct Iodisc
333
{
334
Sfdisc_t disc;
335
Shell_t *sh;
336
};
337
338
static int subexcept(Sfio_t*, int, void*, Sfdisc_t*);
339
static int eval_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
340
static int slowexcept(Sfio_t*, int, void*, Sfdisc_t*);
341
static int pipeexcept(Sfio_t*, int, void*, Sfdisc_t*);
342
static ssize_t piperead(Sfio_t*, void*, size_t, Sfdisc_t*);
343
static ssize_t slowread(Sfio_t*, void*, size_t, Sfdisc_t*);
344
static ssize_t subread(Sfio_t*, void*, size_t, Sfdisc_t*);
345
static ssize_t tee_write(Sfio_t*,const void*,size_t,Sfdisc_t*);
346
static int io_prompt(Shell_t*,Sfio_t*,int);
347
static int io_heredoc(Shell_t*,register struct ionod*, const char*, int);
348
static void sftrack(Sfio_t*,int,void*);
349
static const Sfdisc_t eval_disc = { NULL, NULL, NULL, eval_exceptf, NULL};
350
static Sfdisc_t tee_disc = {NULL,tee_write,NULL,NULL,NULL};
351
static Sfio_t *subopen(Shell_t *,Sfio_t*, off_t, long);
352
static const Sfdisc_t sub_disc = { subread, 0, 0, subexcept, 0 };
353
354
struct subfile
355
{
356
Sfdisc_t disc;
357
Sfio_t *oldsp;
358
off_t offset;
359
long size;
360
long left;
361
};
362
363
struct Eof
364
{
365
Namfun_t hdr;
366
int fd;
367
};
368
369
static Sfdouble_t nget_cur_eof(register Namval_t* np, Namfun_t *fp)
370
{
371
struct Eof *ep = (struct Eof*)fp;
372
Sfoff_t end, cur =lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
373
if(*np->nvname=='C')
374
return((Sfdouble_t)cur);
375
if(cur<0)
376
return((Sfdouble_t)-1);
377
end =lseek(ep->fd, (Sfoff_t)0, SEEK_END);
378
lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
379
return((Sfdouble_t)end);
380
}
381
382
static const Namdisc_t EOF_disc = { sizeof(struct Eof), 0, 0, nget_cur_eof};
383
384
#define MATCH_BUFF (64*1024)
385
struct Match
386
{
387
Sfoff_t offset;
388
char *base;
389
};
390
391
static int matchf(void *handle, char *ptr, size_t size)
392
{
393
struct Match *mp = (struct Match*)handle;
394
mp->offset += (ptr-mp->base);
395
return(1);
396
}
397
398
399
static struct fdsave *filemap;
400
static short filemapsize;
401
402
#define PSEUDOFD (SHRT_MAX)
403
404
/* ======== input output and file copying ======== */
405
406
int sh_iovalidfd(Shell_t *shp, int fd)
407
{
408
Sfio_t **sftable = shp->sftable;
409
int max,n, **fdptrs = shp->fdptrs;
410
unsigned char *fdstatus = shp->fdstatus;
411
if(fd<0)
412
return(0);
413
if(fd < shp->gd->lim.open_max)
414
return(1);
415
max = strtol(astconf("OPEN_MAX",NiL,NiL),NiL,0);
416
if(fd >= max)
417
{
418
errno = EBADF;
419
return(0);
420
}
421
n = (fd+16)&~0xf;
422
if(n > max)
423
n = max;
424
max = shp->gd->lim.open_max;
425
shp->sftable = (Sfio_t**)calloc((n+1)*(sizeof(int*)+sizeof(Sfio_t*)+1),1);
426
if(max)
427
memcpy(shp->sftable,sftable,max*sizeof(Sfio_t*));
428
shp->fdptrs = (int**)(&shp->sftable[n]);
429
if(max)
430
memcpy(shp->fdptrs,fdptrs,max*sizeof(int*));
431
shp->fdstatus = (unsigned char*)(&shp->fdptrs[n]);
432
if(max)
433
memcpy(shp->fdstatus,fdstatus,max);
434
if(sftable)
435
free((void*)sftable);
436
shp->gd->lim.open_max = n;
437
return(1);
438
}
439
440
int sh_inuse(Shell_t *shp, int fd)
441
{
442
return(fd < shp->gd->lim.open_max && shp->fdptrs[fd]);
443
}
444
445
void sh_ioinit(Shell_t *shp)
446
{
447
filemapsize = 8;
448
filemap = (struct fdsave*)malloc(filemapsize*sizeof(struct fdsave));
449
sh_iovalidfd(shp,16);
450
shp->sftable[0] = sfstdin;
451
shp->sftable[1] = sfstdout;
452
shp->sftable[2] = sfstderr;
453
sfnotify(sftrack);
454
sh_iostream(shp,0);
455
sh_iostream(shp,1);
456
/* all write steams are in the same pool and share outbuff */
457
shp->outpool = sfopen(NIL(Sfio_t*),NIL(char*),"sw"); /* pool identifier */
458
shp->outbuff = (char*)malloc(IOBSIZE+4);
459
shp->errbuff = (char*)malloc(IOBSIZE/4);
460
sfsetbuf(sfstderr,shp->errbuff,IOBSIZE/4);
461
sfsetbuf(sfstdout,shp->outbuff,IOBSIZE);
462
sfpool(sfstdout,shp->outpool,SF_WRITE);
463
sfpool(sfstderr,shp->outpool,SF_WRITE);
464
sfset(sfstdout,SF_LINE,0);
465
sfset(sfstderr,SF_LINE,0);
466
sfset(sfstdin,SF_SHARE|SF_PUBLIC,1);
467
}
468
469
/*
470
* Handle output stream exceptions
471
*/
472
static int outexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
473
{
474
Shell_t *shp = ((struct Iodisc*)handle)->sh;
475
static int active = 0;
476
if(type==SF_DPOP || type==SF_FINAL)
477
free((void*)handle);
478
else if(type==SF_WRITE && (*(ssize_t*)data)<0 && sffileno(iop)!=2)
479
switch (errno)
480
{
481
case EINTR:
482
case EPIPE:
483
#ifdef ECONNRESET
484
case ECONNRESET:
485
#endif
486
#ifdef ESHUTDOWN
487
case ESHUTDOWN:
488
#endif
489
break;
490
default:
491
if(!active)
492
{
493
int mode = ((struct checkpt*)shp->jmplist)->mode;
494
int save = errno;
495
active = 1;
496
((struct checkpt*)shp->jmplist)->mode = 0;
497
sfpurge(iop);
498
sfpool(iop,NIL(Sfio_t*),SF_WRITE);
499
errno = save;
500
errormsg(SH_DICT,ERROR_system(1),e_badwrite,sffileno(iop));
501
active = 0;
502
((struct checkpt*)shp->jmplist)->mode = mode;
503
sh_exit(1);
504
}
505
return(-1);
506
}
507
return(0);
508
}
509
510
/*
511
* create or initialize a stream corresponding to descriptor <fd>
512
* a buffer with room for a sentinal is allocated for a read stream.
513
* A discipline is inserted when read stream is a tty or a pipe
514
* For output streams, the buffer is set to sh.output and put into
515
* the sh.outpool synchronization pool
516
*/
517
Sfio_t *sh_iostream(Shell_t *shp, register int fd)
518
{
519
register Sfio_t *iop;
520
register int status = sh_iocheckfd(shp,fd);
521
register int flags = SF_WRITE;
522
char *bp;
523
struct Iodisc *dp;
524
if(status==IOCLOSE)
525
{
526
switch(fd)
527
{
528
case 0:
529
return(sfstdin);
530
case 1:
531
return(sfstdout);
532
case 2:
533
return(sfstderr);
534
}
535
return(NIL(Sfio_t*));
536
}
537
if(status&IOREAD)
538
{
539
if(!(bp = (char *)malloc(IOBSIZE+1)))
540
return(NIL(Sfio_t*));
541
flags |= SF_READ;
542
if(!(status&IOWRITE))
543
flags &= ~SF_WRITE;
544
}
545
else
546
bp = shp->outbuff;
547
if(status&IODUP)
548
flags |= SF_SHARE|SF_PUBLIC;
549
if((iop = shp->sftable[fd]) && sffileno(iop)>=0)
550
{
551
if(status&IOTTY)
552
sfset(iop,SF_LINE|SF_WCWIDTH,1);
553
sfsetbuf(iop, bp, IOBSIZE);
554
}
555
else if(!(iop=sfnew((fd<=2?iop:0),bp,IOBSIZE,fd,flags)))
556
return(NIL(Sfio_t*));
557
dp = newof(0,struct Iodisc,1,0);
558
dp->sh = shp;
559
if(status&IOREAD)
560
{
561
sfset(iop,SF_MALLOC,1);
562
if(!(status&IOWRITE))
563
sfset(iop,SF_IOCHECK,1);
564
dp->disc.exceptf = slowexcept;
565
if(status&IOTTY)
566
dp->disc.readf = slowread;
567
else if(status&IONOSEEK)
568
{
569
dp->disc.readf = piperead;
570
sfset(iop, SF_IOINTR,1);
571
}
572
else
573
dp->disc.readf = 0;
574
dp->disc.seekf = 0;
575
dp->disc.writef = 0;
576
}
577
else
578
{
579
if((status&(IONOSEEK|IOTTY)) == IONOSEEK)
580
dp->disc.exceptf = pipeexcept;
581
else
582
dp->disc.exceptf = outexcept;
583
sfpool(iop,shp->outpool,SF_WRITE);
584
}
585
sfdisc(iop,&dp->disc);
586
shp->sftable[fd] = iop;
587
return(iop);
588
}
589
590
/*
591
* preserve the file descriptor or stream by moving it
592
*/
593
static void io_preserve(Shell_t* shp, register Sfio_t *sp, register int f2)
594
{
595
register int fd;
596
if(sp)
597
fd = sfsetfd(sp,10);
598
else
599
fd = sh_fcntl(f2,F_DUPFD,10);
600
if(f2==shp->infd)
601
shp->infd = fd;
602
if(fd<0)
603
{
604
shp->toomany = 1;
605
((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
606
errormsg(SH_DICT,ERROR_system(1),e_toomany);
607
}
608
if(f2 >= shp->gd->lim.open_max)
609
sh_iovalidfd(shp,f2);
610
if(shp->fdptrs[fd]=shp->fdptrs[f2])
611
{
612
if(f2==job.fd)
613
job.fd=fd;
614
*shp->fdptrs[fd] = fd;
615
shp->fdptrs[f2] = 0;
616
}
617
shp->sftable[fd] = sp;
618
shp->fdstatus[fd] = shp->fdstatus[f2];
619
if(fcntl(f2,F_GETFD,0)&1)
620
{
621
fcntl(fd,F_SETFD,FD_CLOEXEC);
622
shp->fdstatus[fd] |= IOCLEX;
623
}
624
shp->sftable[f2] = 0;
625
}
626
627
/*
628
* Given a file descriptor <f1>, move it to a file descriptor number <f2>
629
* If <f2> is needed move it, otherwise it is closed first.
630
* The original stream <f1> is closed.
631
* The new file descriptor <f2> is returned;
632
*/
633
int sh_iorenumber(Shell_t *shp, register int f1,register int f2)
634
{
635
register Sfio_t *sp = shp->sftable[f2];
636
if(f1!=f2)
637
{
638
/* see whether file descriptor is in use */
639
if(sh_inuse(shp,f2) || (f2>2 && sp))
640
{
641
if(!(shp->inuse_bits&(1<<f2)))
642
io_preserve(shp,sp,f2);
643
sp = 0;
644
}
645
else if(f2==0)
646
shp->st.ioset = 1;
647
sh_close(f2);
648
if(f2<=2 && sp)
649
{
650
register Sfio_t *spnew = sh_iostream(shp,f1);
651
shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
652
sfsetfd(spnew,f2);
653
sfswap(spnew,sp);
654
sfset(sp,SF_SHARE|SF_PUBLIC,1);
655
}
656
else
657
{
658
shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
659
if((f2 = sh_fcntl(f1,F_DUPFD, f2)) < 0)
660
errormsg(SH_DICT,ERROR_system(1),e_file+4);
661
else if(f2 <= 2)
662
sh_iostream(shp,f2);
663
}
664
if(sp)
665
shp->sftable[f1] = 0;
666
if(shp->fdstatus[f1]!=IOCLOSE)
667
sh_close(f1);
668
}
669
else if(sp)
670
{
671
sfsetfd(sp,f2);
672
if(f2<=2)
673
sfset(sp,SF_SHARE|SF_PUBLIC,1);
674
}
675
if(f2>=shp->gd->lim.open_max)
676
sh_iovalidfd(shp,f2);
677
return(f2);
678
}
679
680
/*
681
* close a file descriptor and update stream table and attributes
682
*/
683
int sh_close(register int fd)
684
{
685
Shell_t *shp = sh_getinterp();
686
register Sfio_t *sp;
687
register int r = 0;
688
if(fd<0)
689
return(-1);
690
if(fd >= shp->gd->lim.open_max)
691
sh_iovalidfd(shp,fd);
692
if(!(sp=shp->sftable[fd]) || sfclose(sp) < 0)
693
{
694
int err=errno;
695
if(fdnotify)
696
(*fdnotify)(fd,SH_FDCLOSE);
697
while((r=close(fd)) < 0 && errno==EINTR)
698
errno = err;
699
}
700
if(fd>2)
701
shp->sftable[fd] = 0;
702
shp->fdstatus[fd] = IOCLOSE;
703
if(shp->fdptrs[fd])
704
*shp->fdptrs[fd] = -1;
705
shp->fdptrs[fd] = 0;
706
if(fd < 10)
707
shp->inuse_bits &= ~(1<<fd);
708
return(r);
709
}
710
711
#ifdef O_SERVICE
712
713
static int
714
onintr(struct addrinfo* addr, void* handle)
715
{
716
Shell_t* sh = (Shell_t*)handle;
717
718
if (sh->trapnote&SH_SIGSET)
719
{
720
freeaddrinfo(addr);
721
sh_exit(SH_EXITSIG);
722
return -1;
723
}
724
if (sh->trapnote)
725
sh_chktrap(sh);
726
return 0;
727
}
728
729
#endif
730
731
/*
732
* Mimic open(2) with checks for pseudo /dev/ files.
733
*/
734
int sh_open(register const char *path, int flags, ...)
735
{
736
Shell_t *shp = sh_getinterp();
737
register int fd = -1;
738
mode_t mode;
739
char *e;
740
va_list ap;
741
va_start(ap, flags);
742
mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
743
va_end(ap);
744
errno = 0;
745
if(path==0)
746
{
747
errno = EFAULT;
748
return(-1);
749
}
750
if(*path==0)
751
{
752
errno = ENOENT;
753
return(-1);
754
}
755
if (path[0]=='/' && path[1]=='d' && path[2]=='e' && path[3]=='v' && path[4]=='/')
756
{
757
switch (path[5])
758
{
759
case 'f':
760
if (path[6]=='d' && path[7]=='/')
761
{
762
if(flags==O_NONBLOCK)
763
return(1);
764
fd = (int)strtol(path+8, &e, 10);
765
if (*e)
766
fd = -1;
767
}
768
break;
769
case 's':
770
if (path[6]=='t' && path[7]=='d')
771
switch (path[8])
772
{
773
case 'e':
774
if (path[9]=='r' && path[10]=='r' && !path[11])
775
fd = 2;
776
break;
777
case 'i':
778
if (path[9]=='n' && !path[10])
779
fd = 0;
780
break;
781
case 'o':
782
if (path[9]=='u' && path[10]=='t' && !path[11])
783
fd = 1;
784
break;
785
}
786
}
787
#ifdef O_SERVICE
788
if (fd < 0)
789
{
790
if ((fd = inetopen(path+5, flags, onintr, shp)) < 0 && errno != ENOTDIR)
791
return -1;
792
if(flags==O_NONBLOCK)
793
return(fd>=0);
794
if (fd >= 0)
795
goto ok;
796
}
797
if(flags==O_NONBLOCK)
798
return(0);
799
#endif
800
}
801
if (fd >= 0)
802
{
803
int nfd= -1;
804
if (flags & O_CREAT)
805
{
806
struct stat st;
807
if (stat(path,&st) >=0)
808
nfd = open(path,flags,st.st_mode);
809
}
810
else
811
nfd = open(path,flags);
812
if(nfd>=0)
813
{
814
fd = nfd;
815
goto ok;
816
}
817
if((mode=sh_iocheckfd(shp,fd))==IOCLOSE)
818
return(-1);
819
flags &= O_ACCMODE;
820
if(!(mode&IOWRITE) && ((flags==O_WRONLY) || (flags==O_RDWR)))
821
return(-1);
822
if(!(mode&IOREAD) && ((flags==O_RDONLY) || (flags==O_RDWR)))
823
return(-1);
824
if((fd=dup(fd))<0)
825
return(-1);
826
}
827
else
828
{
829
#if SHOPT_REGRESS
830
char buf[PATH_MAX];
831
if(strncmp(path,"/etc/",5)==0)
832
{
833
sfsprintf(buf, sizeof(buf), "%s%s", sh_regress_etc(path, __LINE__, __FILE__), path+4);
834
path = buf;
835
}
836
#endif
837
while((fd = open(path, flags, mode)) < 0)
838
if(errno!=EINTR || shp->trapnote)
839
return(-1);
840
}
841
ok:
842
flags &= O_ACCMODE;
843
if(flags==O_WRONLY)
844
mode = IOWRITE;
845
else if(flags==O_RDWR)
846
mode = (IOREAD|IOWRITE);
847
else
848
mode = IOREAD;
849
if(fd >= shp->gd->lim.open_max)
850
sh_iovalidfd(shp,fd);
851
shp->fdstatus[fd] = mode;
852
return(fd);
853
}
854
855
/*
856
* Open a file for reading
857
* On failure, print message.
858
*/
859
int sh_chkopen(register const char *name)
860
{
861
register int fd = sh_open(name,O_RDONLY,0);
862
if(fd < 0)
863
errormsg(SH_DICT,ERROR_system(1),e_open,name);
864
return(fd);
865
}
866
867
/*
868
* move open file descriptor to a number > 2
869
*/
870
int sh_iomovefd(register int fdold)
871
{
872
Shell_t *shp = sh_getinterp();
873
register int fdnew;
874
if(fdold >= shp->gd->lim.open_max)
875
sh_iovalidfd(shp,fdold);
876
if(fdold<0 || fdold>2)
877
return(fdold);
878
fdnew = sh_iomovefd(dup(fdold));
879
shp->fdstatus[fdnew] = (shp->fdstatus[fdold]&~IOCLEX);
880
close(fdold);
881
shp->fdstatus[fdold] = IOCLOSE;
882
return(fdnew);
883
}
884
885
/*
886
* create a pipe and print message on failure
887
*/
888
int sh_pipe(register int pv[])
889
{
890
Shell_t *shp = sh_getinterp();
891
int fd[2];
892
if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
893
errormsg(SH_DICT,ERROR_system(1),e_pipe);
894
pv[0] = sh_iomovefd(pv[0]);
895
pv[1] = sh_iomovefd(pv[1]);
896
shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
897
shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
898
sh_subsavefd(pv[0]);
899
sh_subsavefd(pv[1]);
900
return(0);
901
}
902
903
#ifndef pipe
904
int sh_rpipe(register int pv[])
905
{
906
return sh_pipe(pv);
907
}
908
#else
909
# undef pipe
910
/* create a real pipe when pipe() is socketpair */
911
int sh_rpipe(register int pv[])
912
{
913
Shell_t *shp = sh_getinterp();
914
int fd[2];
915
if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
916
errormsg(SH_DICT,ERROR_system(1),e_pipe);
917
pv[0] = sh_iomovefd(pv[0]);
918
pv[1] = sh_iomovefd(pv[1]);
919
shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
920
shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
921
sh_subsavefd(pv[0]);
922
sh_subsavefd(pv[1]);
923
return(0);
924
}
925
#endif
926
927
#if SHOPT_COSHELL
928
int sh_coaccept(Shell_t *shp,int *pv,int out)
929
{
930
int fd = accept(pv[0],(struct sockaddr*)0,(socklen_t*)0);
931
sh_close(pv[0]);
932
pv[0] = -1;
933
if(fd<0)
934
errormsg(SH_DICT,ERROR_system(1),e_pipe);
935
if((pv[out]=sh_fcntl(fd,F_DUPFD,10)) >=10)
936
sh_close(fd);
937
else
938
pv[out] = sh_iomovefd(fd);
939
if(fcntl(pv[out],F_SETFD,FD_CLOEXEC) >=0)
940
shp->fdstatus[pv[out]] |= IOCLEX;
941
shp->fdstatus[pv[out]] = (out?IOWRITE:IOREAD);
942
shp->fdstatus[pv[out]] |= IONOSEEK;
943
sh_subsavefd(pv[out]);
944
#if defined(SHUT_RD) && defined(SHUT_WR)
945
shutdown(pv[out],out?SHUT_RD:SHUT_WR);
946
#endif
947
return(0);
948
}
949
950
int sh_copipe(Shell_t *shp, int *pv, int out)
951
{
952
int r,port=20000;
953
struct sockaddr_in sin;
954
socklen_t slen;
955
if ((pv[out] = socket (AF_INET, SOCK_STREAM, 0)) < 0)
956
errormsg(SH_DICT,ERROR_system(1),e_pipe);
957
do
958
{
959
sin.sin_family = AF_INET;
960
sin.sin_port = htons(++port);
961
sin.sin_addr.s_addr = INADDR_ANY;
962
slen = sizeof (sin);
963
}
964
while ((r=bind (pv[out], (struct sockaddr *) &sin, slen)) == -1 && errno==EADDRINUSE);
965
if(r<0 || listen(pv[out],5) <0)
966
{
967
close(pv[out]);
968
errormsg(SH_DICT,ERROR_system(1),e_pipe);
969
}
970
fcntl(pv[out],F_SETFD,FD_CLOEXEC);
971
shp->fdstatus[pv[out]] |= IOCLEX;
972
pv[1-out] = -1;
973
pv[2] = port;
974
return(0);
975
}
976
#endif /* SHOPT_COSHELL */
977
978
static int pat_seek(void *handle, const char *str, size_t sz)
979
{
980
char **bp = (char**)handle;
981
*bp = (char*)str;
982
return(-1);
983
}
984
985
static int pat_line(const regex_t* rp, const char *buff, register size_t n)
986
{
987
register const char *cp=buff, *sp;
988
while(n>0)
989
{
990
for(sp=cp; n-->0 && *cp++ != '\n';);
991
if(regnexec(rp,sp,cp-sp, 0, (regmatch_t*)0, 0)==0)
992
return(sp-buff);
993
}
994
return(cp-buff);
995
}
996
997
static int io_patseek(Shell_t *shp, regex_t *rp, Sfio_t* sp, int flags)
998
{
999
char *cp, *match;
1000
int r, fd=sffileno(sp), close_exec = shp->fdstatus[fd]&IOCLEX;
1001
int was_share,s=(PIPE_BUF>SF_BUFSIZE?SF_BUFSIZE:PIPE_BUF);
1002
size_t n,m;
1003
shp->fdstatus[sffileno(sp)] |= IOCLEX;
1004
if(fd==0)
1005
was_share = sfset(sp,SF_SHARE,1);
1006
while((cp=sfreserve(sp, -s, SF_LOCKR)) || (cp=sfreserve(sp,SF_UNBOUND, SF_LOCKR)))
1007
{
1008
m = n = sfvalue(sp);
1009
while(n>0 && cp[n-1]!='\n')
1010
n--;
1011
if(n)
1012
m = n;
1013
r = regrexec(rp,cp,m,0,(regmatch_t*)0, 0, '\n', (void*)&match, pat_seek);
1014
if(r<0)
1015
m = match-cp;
1016
else if(r==2)
1017
{
1018
if((m = pat_line(rp,cp,m)) < n)
1019
r = -1;
1020
}
1021
if(m && (flags&IOCOPY))
1022
sfwrite(sfstdout,cp,m);
1023
sfread(sp,cp,m);
1024
if(r<0)
1025
break;
1026
}
1027
if(!close_exec)
1028
shp->fdstatus[sffileno(sp)] &= ~IOCLEX;
1029
if(fd==0 && !(was_share&SF_SHARE))
1030
sfset(sp, SF_SHARE,0);
1031
return(0);
1032
}
1033
1034
static Sfoff_t file_offset(Shell_t *shp, int fn, char *fname)
1035
{
1036
Sfio_t *sp = shp->sftable[fn];
1037
char *cp;
1038
Sfoff_t off;
1039
struct Eof endf;
1040
Namval_t *mp = nv_open("EOF",shp->var_tree,0);
1041
Namval_t *pp = nv_open("CUR",shp->var_tree,0);
1042
memset(&endf,0,sizeof(struct Eof));
1043
endf.fd = fn;
1044
endf.hdr.disc = &EOF_disc;
1045
endf.hdr.nofree = 1;
1046
if(mp)
1047
nv_stack(mp, &endf.hdr);
1048
if(pp)
1049
nv_stack(pp, &endf.hdr);
1050
if(sp)
1051
sfsync(sp);
1052
off = sh_strnum(fname, &cp, 0);
1053
if(mp)
1054
nv_stack(mp, NiL);
1055
if(pp)
1056
nv_stack(pp, NiL);
1057
return(*cp?(Sfoff_t)-1:off);
1058
}
1059
1060
/*
1061
* close a pipe
1062
*/
1063
void sh_pclose(register int pv[])
1064
{
1065
if(pv[0]>=2)
1066
sh_close(pv[0]);
1067
if(pv[1]>=2)
1068
sh_close(pv[1]);
1069
pv[0] = pv[1] = -1;
1070
}
1071
1072
static char *io_usename(char *name, int *perm, int fno, int mode)
1073
{
1074
struct stat statb;
1075
char *tname, *sp, *ep, path[PATH_MAX+1];
1076
int fd,r;
1077
if(mode==0)
1078
{
1079
if((fd = sh_open(name,O_RDONLY,0)) >= 0)
1080
{
1081
r = fstat(fd,&statb);
1082
close(fd);
1083
if(r)
1084
return(0);
1085
if(!S_ISREG(statb.st_mode))
1086
return(0);
1087
*perm = statb.st_mode&(RW_ALL|(S_IXUSR|S_IXGRP|S_IXOTH));
1088
}
1089
else if(fd < 0 && errno!=ENOENT)
1090
return(0);
1091
}
1092
while((fd=readlink(name, path, PATH_MAX)) >0)
1093
{
1094
name=path;
1095
name[fd] = 0;
1096
}
1097
stakseek(1);
1098
stakputs(name);
1099
stakputc(0);
1100
pathcanon(stakptr(1),PATH_PHYSICAL);
1101
sp = ep = stakptr(1);
1102
if(ep = strrchr(sp,'/'))
1103
{
1104
memmove(stakptr(0),sp,++ep-sp);
1105
stakseek(ep-sp);
1106
}
1107
else
1108
{
1109
ep = sp;
1110
stakseek(0);
1111
}
1112
stakputc('.');
1113
sfprintf(stkstd,"%<#d_%d{;.tmp",getpid(),fno);
1114
tname = stakfreeze(1);
1115
switch(mode)
1116
{
1117
case 1:
1118
rename(tname,name);
1119
break;
1120
default:
1121
unlink(tname);
1122
break;
1123
}
1124
return(tname);
1125
}
1126
1127
/*
1128
* I/O redirection
1129
* flag = 0 if files are to be restored
1130
* flag = 2 if files are to be closed on exec
1131
* flag = 3 when called from $( < ...), just open file and return
1132
* flag = SH_SHOWME for trace only
1133
*/
1134
int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
1135
{
1136
Sfoff_t off;
1137
register char *fname;
1138
register int fd, iof;
1139
const char *message = e_open;
1140
int o_mode; /* mode flag for open */
1141
static char io_op[7]; /* used for -x trace info */
1142
int trunc=0, clexec=0, fn, traceon;
1143
int r, indx = shp->topfd, perm= -1;
1144
char *tname=0, *after="", *trace = shp->st.trap[SH_DEBUGTRAP];
1145
Namval_t *np=0;
1146
int isstring = shp->subshell?(sfset(sfstdout,0,0)&SF_STRING):0;
1147
1148
if(flag==2)
1149
clexec = 1;
1150
if(iop)
1151
traceon = sh_trace(shp,NIL(char**),0);
1152
for(;iop;iop=iop->ionxt)
1153
{
1154
iof=iop->iofile;
1155
fn = (iof&IOUFD);
1156
if(fn==1 && shp->subshell && !shp->subshare && (flag==2 || isstring))
1157
sh_subfork();
1158
if(shp->redir0 && fn==0 && !(iof&IOMOV))
1159
shp->redir0 = 2;
1160
io_op[0] = '0'+(iof&IOUFD);
1161
if(iof&IOPUT)
1162
{
1163
io_op[1] = '>';
1164
o_mode = O_WRONLY|O_CREAT;
1165
}
1166
else
1167
{
1168
io_op[1] = '<';
1169
o_mode = O_RDONLY|O_NONBLOCK;
1170
}
1171
io_op[2] = 0;
1172
io_op[3] = 0;
1173
io_op[4] = 0;
1174
fname = iop->ioname;
1175
if(!(iof&IORAW))
1176
{
1177
if(iof&IOLSEEK)
1178
{
1179
struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
1180
memset(ap, 0, ARGVAL);
1181
ap->argflag = ARG_MAC;
1182
strcpy(ap->argval,iop->ioname);
1183
fname=sh_macpat(shp,ap,(iof&IOARITH)?ARG_ARITH:ARG_EXP);
1184
}
1185
else if(iof&IOPROCSUB)
1186
{
1187
struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
1188
memset(ap, 0, ARGVAL);
1189
if(iof&IOPUT)
1190
ap->argflag = ARG_RAW;
1191
else if(shp->subshell)
1192
sh_subtmpfile(shp);
1193
ap->argchn.ap = (struct argnod*)fname;
1194
ap = sh_argprocsub(shp,ap);
1195
fname = ap->argval;
1196
}
1197
else
1198
fname=sh_mactrim(shp,fname,(!sh_isoption(SH_NOGLOB)&&sh_isoption(SH_INTERACTIVE))?2:0);
1199
}
1200
errno=0;
1201
np = 0;
1202
#if SHOPT_COSHELL
1203
if(shp->inpool)
1204
{
1205
if(!(iof&(IODOC|IOLSEEK|IOMOV)))
1206
sh_coaddfile(shp,fname);
1207
continue;
1208
}
1209
#endif /* SHOPT_COSHELL */
1210
if(iop->iovname)
1211
{
1212
np = nv_open(iop->iovname,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
1213
if(nv_isattr(np,NV_RDONLY))
1214
errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
1215
io_op[0] = '}';
1216
if((iof&IOLSEEK) || ((iof&IOMOV) && *fname=='-'))
1217
fn = nv_getnum(np);
1218
}
1219
if(fn>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fn))
1220
errormsg(SH_DICT,ERROR_system(1),e_file+4);
1221
if(iof&IOLSEEK)
1222
{
1223
io_op[2] = '#';
1224
if(iof&IOARITH)
1225
{
1226
strcpy(&io_op[3]," ((");
1227
after = "))";
1228
}
1229
else if(iof&IOCOPY)
1230
io_op[3] = '#';
1231
goto traceit;
1232
}
1233
if(*fname || (iof&(IODOC|IOSTRG))==(IODOC|IOSTRG))
1234
{
1235
if(iof&IODOC)
1236
{
1237
if(traceon)
1238
sfputr(sfstderr,io_op,'<');
1239
fd = io_heredoc(shp,iop,fname,traceon);
1240
if(traceon && (flag==SH_SHOWME))
1241
sh_close(fd);
1242
fname = 0;
1243
}
1244
else if(iof&IOMOV)
1245
{
1246
int dupfd,toclose= -1;
1247
io_op[2] = '&';
1248
if((fd=fname[0])>='0' && fd<='9')
1249
{
1250
char *number = fname;
1251
dupfd = strtol(fname,&number,10);
1252
if(*number=='-')
1253
{
1254
toclose = dupfd;
1255
number++;
1256
}
1257
if(*number || dupfd > IOUFD)
1258
{
1259
message = e_file;
1260
goto fail;
1261
}
1262
if(shp->subshell && dupfd==1)
1263
{
1264
if(sfset(sfstdout,0,0)&SF_STRING)
1265
sh_subtmpfile(shp);
1266
if(shp->comsub==1)
1267
shp->subdup |= 1<<fn;
1268
dupfd = sffileno(sfstdout);
1269
}
1270
else if(shp->sftable[dupfd])
1271
sfsync(shp->sftable[dupfd]);
1272
if(dupfd!=1 && fn < 10)
1273
shp->subdup &= ~(1<<fn);
1274
}
1275
else if(fd=='-' && fname[1]==0)
1276
{
1277
fd= -1;
1278
goto traceit;
1279
}
1280
else if(fd=='p' && fname[1]==0)
1281
{
1282
if(iof&IOPUT)
1283
dupfd = shp->coutpipe;
1284
else
1285
dupfd = shp->cpipe[0];
1286
if(flag)
1287
toclose = dupfd;
1288
}
1289
else
1290
{
1291
message = e_file;
1292
goto fail;
1293
}
1294
if(flag==SH_SHOWME)
1295
goto traceit;
1296
if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
1297
goto fail;
1298
if(fd>= shp->gd->lim.open_max)
1299
sh_iovalidfd(shp,fd);
1300
sh_iocheckfd(shp,dupfd);
1301
shp->fdstatus[fd] = (shp->fdstatus[dupfd]&~IOCLEX);
1302
if(toclose<0 && shp->fdstatus[fd]&IOREAD)
1303
shp->fdstatus[fd] |= IODUP;
1304
else if(dupfd==shp->cpipe[0])
1305
sh_pclose(shp->cpipe);
1306
else if(toclose>=0)
1307
{
1308
if(flag==0)
1309
sh_iosave(shp,toclose,indx,(char*)0); /* save file descriptor */
1310
sh_close(toclose);
1311
}
1312
}
1313
else if(iof&IORDW)
1314
{
1315
if(sh_isoption(SH_RESTRICTED))
1316
errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1317
io_op[2] = '>';
1318
o_mode = O_RDWR|O_CREAT;
1319
if(iof&IOREWRITE)
1320
trunc = io_op[2] = ';';
1321
goto openit;
1322
}
1323
else if(!(iof&IOPUT))
1324
{
1325
if(flag==SH_SHOWME)
1326
goto traceit;
1327
fd=sh_chkopen(fname);
1328
}
1329
else if(sh_isoption(SH_RESTRICTED))
1330
errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1331
else
1332
{
1333
if(iof&IOAPP)
1334
{
1335
io_op[2] = '>';
1336
o_mode |= O_APPEND;
1337
}
1338
else if((iof&IOREWRITE) && (flag==0 || flag==1 || sh_subsavefd(fn)))
1339
{
1340
io_op[2] = ';';
1341
o_mode |= O_TRUNC;
1342
if(tname = io_usename(fname,&perm,fn,0))
1343
o_mode |= O_EXCL;
1344
}
1345
else
1346
{
1347
o_mode |= O_TRUNC;
1348
if(iof&IOCLOB)
1349
io_op[2] = '|';
1350
else if(sh_isoption(SH_NOCLOBBER))
1351
{
1352
struct stat sb;
1353
if(stat(fname,&sb)>=0)
1354
{
1355
#if SHOPT_FS_3D
1356
if(S_ISREG(sb.st_mode)&&
1357
(!shp->gd->lim.fs3d || iview(&sb)==0))
1358
#else
1359
if(S_ISREG(sb.st_mode))
1360
#endif /* SHOPT_FS_3D */
1361
{
1362
errno = EEXIST;
1363
errormsg(SH_DICT,ERROR_system(1),e_exists,fname);
1364
}
1365
}
1366
else
1367
o_mode |= O_EXCL;
1368
}
1369
}
1370
openit:
1371
if(flag!=SH_SHOWME)
1372
{
1373
if((fd=sh_open(tname?tname:fname,o_mode,RW_ALL)) <0)
1374
errormsg(SH_DICT,ERROR_system(1),((o_mode&O_CREAT)?e_create:e_open),fname);
1375
if(perm>0)
1376
#if _lib_fchmod
1377
fchmod(fd,perm);
1378
#else
1379
chmod(tname,perm);
1380
#endif
1381
}
1382
}
1383
traceit:
1384
if(traceon && fname)
1385
{
1386
if(np)
1387
sfprintf(sfstderr,"{%s",nv_name(np));
1388
sfprintf(sfstderr,"%s %s%s%c",io_op,fname,after,iop->ionxt?' ':'\n');
1389
}
1390
if(flag==SH_SHOWME)
1391
return(indx);
1392
if(trace && fname)
1393
{
1394
char *argv[7], **av=argv;
1395
av[3] = io_op;
1396
av[4] = fname;
1397
av[5] = 0;
1398
av[6] = 0;
1399
if(iof&IOARITH)
1400
av[5] = after;
1401
if(np)
1402
{
1403
av[0] = "{";
1404
av[1] = nv_name(np);
1405
av[2] = "}";
1406
}
1407
else
1408
av +=3;
1409
sh_debug(shp,trace,(char*)0,(char*)0,av,ARG_NOGLOB);
1410
}
1411
if(iof&IOLSEEK)
1412
{
1413
Sfio_t *sp = shp->sftable[fn];
1414
r = shp->fdstatus[fn];
1415
if(!(r&(IOSEEK|IONOSEEK)))
1416
r = sh_iocheckfd(shp,fn);
1417
sfsprintf(io_op,sizeof(io_op),"%d\0",fn);
1418
if(r==IOCLOSE)
1419
{
1420
fname = io_op;
1421
message = e_file;
1422
goto fail;
1423
}
1424
if(iof&IOARITH)
1425
{
1426
if(r&IONOSEEK)
1427
{
1428
fname = io_op;
1429
message = e_notseek;
1430
goto fail;
1431
}
1432
message = e_badseek;
1433
if((off = file_offset(shp,fn,fname))<0)
1434
goto fail;
1435
if(sp)
1436
{
1437
off=sfseek(sp, off, SEEK_SET);
1438
sfsync(sp);
1439
}
1440
else
1441
off=lseek(fn, off, SEEK_SET);
1442
if(off<0)
1443
r = -1;
1444
}
1445
else
1446
{
1447
regex_t *rp;
1448
extern const char e_notimp[];
1449
if(!(r&IOREAD))
1450
{
1451
message = e_noread;
1452
goto fail;
1453
}
1454
if(!(rp = regcache(fname, REG_SHELL|REG_NOSUB|REG_NEWLINE|REG_AUGMENTED|REG_FIRST|REG_LEFT|REG_RIGHT, &r)))
1455
{
1456
message = e_badpattern;
1457
goto fail;
1458
}
1459
if(!sp)
1460
sp = sh_iostream(shp,fn);
1461
r=io_patseek(shp,rp,sp,iof);
1462
if(sp && flag==3)
1463
{
1464
/* close stream but not fn */
1465
sfsetfd(sp,-1);
1466
sfclose(sp);
1467
}
1468
}
1469
if(r<0)
1470
goto fail;
1471
if(flag==3)
1472
return(fn);
1473
continue;
1474
}
1475
if(!np)
1476
{
1477
if(flag==0 || tname || (flag==1 && fn==1 && (shp->fdstatus[fn]&IONOSEEK) && shp->outpipepid && shp->outpipepid==getpid()))
1478
{
1479
if(fd==fn)
1480
{
1481
if((r=sh_fcntl(fd,F_DUPFD,10)) > 0)
1482
{
1483
fd = r;
1484
sh_close(fn);
1485
}
1486
}
1487
sh_iosave(shp,fn,indx,tname?fname:(trunc?Empty:0));
1488
}
1489
else if(sh_subsavefd(fn))
1490
sh_iosave(shp,fn,indx|IOSUBSHELL,tname?fname:0);
1491
}
1492
if(fd<0)
1493
{
1494
if(sh_inuse(shp,fn) || (fn && fn==shp->infd))
1495
{
1496
if(fn>9 || !(shp->inuse_bits&(1<<fn)))
1497
io_preserve(shp,shp->sftable[fn],fn);
1498
}
1499
sh_close(fn);
1500
}
1501
if(flag==3)
1502
return(fd);
1503
if(fd>=0)
1504
{
1505
if(np)
1506
{
1507
int32_t v;
1508
fn = fd;
1509
if(fd<10)
1510
{
1511
if((fn=fcntl(fd,F_DUPFD,10)) < 0)
1512
goto fail;
1513
if(fn>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fn))
1514
goto fail;
1515
if(flag!=2 || shp->subshell)
1516
sh_iosave(shp,fn,indx|0x10000,tname?fname:(trunc?Empty:0));
1517
shp->fdstatus[fn] = shp->fdstatus[fd];
1518
sh_close(fd);
1519
fd = fn;
1520
}
1521
_nv_unset(np,0);
1522
nv_onattr(np,NV_INT32);
1523
v = fn;
1524
nv_putval(np,(char*)&v, NV_INT32);
1525
sh_iocheckfd(shp,fd);
1526
}
1527
else
1528
{
1529
fd = sh_iorenumber(shp,sh_iomovefd(fd),fn);
1530
if(fn>2 && fn<10)
1531
shp->inuse_bits |= (1<<fn);
1532
}
1533
}
1534
if(fd >2 && clexec)
1535
{
1536
fcntl(fd,F_SETFD,FD_CLOEXEC);
1537
shp->fdstatus[fd] |= IOCLEX;
1538
}
1539
}
1540
else
1541
goto fail;
1542
}
1543
return(indx);
1544
fail:
1545
errormsg(SH_DICT,ERROR_system(1),message,fname);
1546
/* NOTREACHED */
1547
return(0);
1548
}
1549
/*
1550
* Create a tmp file for the here-document
1551
*/
1552
static int io_heredoc(Shell_t *shp,register struct ionod *iop, const char *name, int traceon)
1553
{
1554
register Sfio_t *infile = 0, *outfile, *tmp;
1555
register int fd;
1556
Sfoff_t off;
1557
if(!(iop->iofile&IOSTRG) && (!shp->heredocs || iop->iosize==0))
1558
return(sh_open(e_devnull,O_RDONLY));
1559
/* create an unnamed temporary file */
1560
if(!(outfile=sftmp(0)))
1561
errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
1562
if(iop->iofile&IOSTRG)
1563
{
1564
if(traceon)
1565
sfprintf(sfstderr,"< %s\n",name);
1566
sfputr(outfile,name,'\n');
1567
}
1568
else
1569
{
1570
/*
1571
* the locking is only needed in case & blocks process
1572
* here-docs so this can be eliminted in some cases
1573
*/
1574
struct flock lock;
1575
int fno = sffileno(shp->heredocs);
1576
if(fno>=0)
1577
{
1578
memset((void*)&lock,0,sizeof(lock));
1579
lock.l_type = F_WRLCK;
1580
lock.l_whence = SEEK_SET;
1581
fcntl(fno,F_SETLKW,&lock);
1582
lock.l_type = F_UNLCK;
1583
}
1584
off = sftell(shp->heredocs);
1585
infile = subopen(shp,shp->heredocs,iop->iooffset,iop->iosize);
1586
if(traceon)
1587
{
1588
char *cp = sh_fmtq(iop->iodelim);
1589
fd = (*cp=='$' || *cp=='\'')?' ':'\\';
1590
sfprintf(sfstderr," %c%s\n",fd,cp);
1591
sfdisc(outfile,&tee_disc);
1592
}
1593
tmp = outfile;
1594
if(fno>=0 && !(iop->iofile&IOQUOTE))
1595
tmp = sftmp(iop->iosize<IOBSIZE?iop->iosize:0);
1596
if(fno>=0 || (iop->iofile&IOQUOTE))
1597
{
1598
/* This is a quoted here-document, not expansion */
1599
sfmove(infile,tmp,SF_UNBOUND,-1);
1600
sfclose(infile);
1601
if(sffileno(tmp)>0)
1602
{
1603
sfsetbuf(tmp,malloc(IOBSIZE+1),IOBSIZE);
1604
sfset(tmp,SF_MALLOC,1);
1605
}
1606
sfseek(shp->heredocs,off,SEEK_SET);
1607
if(fno>=0)
1608
fcntl(fno,F_SETLK,&lock);
1609
sfseek(tmp,(off_t)0,SEEK_SET);
1610
infile = tmp;
1611
}
1612
if(!(iop->iofile&IOQUOTE))
1613
{
1614
char *lastpath = shp->lastpath;
1615
sh_machere(shp,infile,outfile,iop->ioname);
1616
shp->lastpath = lastpath;
1617
if(infile)
1618
sfclose(infile);
1619
}
1620
}
1621
/* close stream outfile, but save file descriptor */
1622
fd = sffileno(outfile);
1623
sfsetfd(outfile,-1);
1624
sfclose(outfile);
1625
if(traceon && !(iop->iofile&IOSTRG))
1626
sfputr(sfstderr,iop->ioname,'\n');
1627
lseek(fd,(off_t)0,SEEK_SET);
1628
shp->fdstatus[fd] = IOREAD;
1629
return(fd);
1630
}
1631
1632
/*
1633
* This write discipline also writes the output on standard error
1634
* This is used when tracing here-documents
1635
*/
1636
static ssize_t tee_write(Sfio_t *iop,const void *buff,size_t n,Sfdisc_t *unused)
1637
{
1638
NOT_USED(unused);
1639
sfwrite(sfstderr,buff,n);
1640
return(write(sffileno(iop),buff,n));
1641
}
1642
1643
/*
1644
* copy file <origfd> into a save place
1645
* The saved file is set close-on-exec
1646
* if <origfd> < 0, then -origfd is saved, but not duped so that it
1647
* will be closed with sh_iorestore.
1648
*/
1649
void sh_iosave(Shell_t *shp, register int origfd, int oldtop, char *name)
1650
{
1651
register int savefd;
1652
int flag = (oldtop&(IOSUBSHELL|IOPICKFD));
1653
oldtop &= ~(IOSUBSHELL|IOPICKFD);
1654
/* see if already saved, only save once */
1655
for(savefd=shp->topfd; --savefd>=oldtop; )
1656
{
1657
if(filemap[savefd].orig_fd == origfd)
1658
return;
1659
}
1660
/* make sure table is large enough */
1661
if(shp->topfd >= filemapsize)
1662
{
1663
char *cp, *oldptr = (char*)filemap;
1664
char *oldend = (char*)&filemap[filemapsize];
1665
long moved;
1666
filemapsize += 8;
1667
if(!(filemap = (struct fdsave*)realloc(filemap,filemapsize*sizeof(struct fdsave))))
1668
errormsg(SH_DICT,ERROR_exit(4),e_nospace);
1669
if(moved = (char*)filemap - oldptr)
1670
{
1671
for(savefd=shp->gd->lim.open_max; --savefd>=0; )
1672
{
1673
cp = (char*)shp->fdptrs[savefd];
1674
if(cp >= oldptr && cp < oldend)
1675
shp->fdptrs[savefd] = (int*)(cp+moved);
1676
}
1677
}
1678
}
1679
#if SHOPT_DEVFD
1680
if(origfd <0)
1681
{
1682
savefd = origfd;
1683
origfd = -origfd;
1684
}
1685
else
1686
#endif /* SHOPT_DEVFD */
1687
if(flag&IOPICKFD)
1688
savefd = -1;
1689
else
1690
{
1691
if((savefd = sh_fcntl(origfd, F_DUPFD, 10)) < 0 && errno!=EBADF)
1692
{
1693
shp->toomany=1;
1694
((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
1695
errormsg(SH_DICT,ERROR_system(1),e_toomany);
1696
}
1697
}
1698
filemap[shp->topfd].tname = name;
1699
filemap[shp->topfd].subshell = (flag&IOSUBSHELL);
1700
filemap[shp->topfd].orig_fd = origfd;
1701
filemap[shp->topfd++].save_fd = savefd;
1702
if(savefd >=0)
1703
{
1704
register Sfio_t* sp = shp->sftable[origfd];
1705
/* make saved file close-on-exec */
1706
sh_fcntl(savefd,F_SETFD,FD_CLOEXEC);
1707
if(origfd==job.fd)
1708
job.fd = savefd;
1709
shp->fdstatus[savefd] = shp->fdstatus[origfd];
1710
shp->fdptrs[savefd] = &filemap[shp->topfd-1].save_fd;
1711
if(!(shp->sftable[savefd]=sp))
1712
return;
1713
sfsync(sp);
1714
if(origfd <=2)
1715
{
1716
/* copy standard stream to new stream */
1717
sp = sfswap(sp,NIL(Sfio_t*));
1718
shp->sftable[savefd] = sp;
1719
}
1720
else
1721
shp->sftable[origfd] = 0;
1722
}
1723
}
1724
1725
/*
1726
* close all saved file descriptors
1727
*/
1728
void sh_iounsave(Shell_t* shp)
1729
{
1730
register int fd, savefd, newfd;
1731
for(newfd=fd=0; fd < shp->topfd; fd++)
1732
{
1733
if((savefd = filemap[fd].save_fd)< 0)
1734
filemap[newfd++] = filemap[fd];
1735
else
1736
{
1737
shp->sftable[savefd] = 0;
1738
sh_close(savefd);
1739
}
1740
}
1741
shp->topfd = newfd;
1742
}
1743
1744
/*
1745
* restore saved file descriptors from <last> on
1746
*/
1747
void sh_iorestore(Shell_t *shp, int last, int jmpval)
1748
{
1749
register int origfd, savefd, fd;
1750
int flag = (last&IOSUBSHELL);
1751
last &= ~IOSUBSHELL;
1752
for (fd = shp->topfd - 1; fd >= last; fd--)
1753
{
1754
if(!flag && filemap[fd].subshell)
1755
continue;
1756
if(jmpval==SH_JMPSCRIPT)
1757
{
1758
if ((savefd = filemap[fd].save_fd) >= 0)
1759
{
1760
shp->sftable[savefd] = 0;
1761
sh_close(savefd);
1762
}
1763
continue;
1764
}
1765
origfd = filemap[fd].orig_fd;
1766
if(origfd<0)
1767
{
1768
/* this should never happen */
1769
savefd = filemap[fd].save_fd;
1770
shp->sftable[savefd] = 0;
1771
sh_close(savefd);
1772
return;
1773
}
1774
if(filemap[fd].tname == Empty && shp->exitval==0)
1775
ftruncate(origfd,lseek(origfd,0,SEEK_CUR));
1776
else if(filemap[fd].tname)
1777
io_usename(filemap[fd].tname,(int*)0,origfd,shp->exitval?2:1);
1778
sh_close(origfd);
1779
if ((savefd = filemap[fd].save_fd) >= 0)
1780
{
1781
sh_fcntl(savefd, F_DUPFD, origfd);
1782
if(savefd==job.fd)
1783
job.fd=origfd;
1784
shp->fdstatus[origfd] = shp->fdstatus[savefd];
1785
/* turn off close-on-exec if flag if necessary */
1786
if(shp->fdstatus[origfd]&IOCLEX)
1787
fcntl(origfd,F_SETFD,FD_CLOEXEC);
1788
if(origfd<=2)
1789
{
1790
sfswap(shp->sftable[savefd],shp->sftable[origfd]);
1791
if(origfd==0)
1792
shp->st.ioset = 0;
1793
}
1794
else
1795
shp->sftable[origfd] = shp->sftable[savefd];
1796
shp->sftable[savefd] = 0;
1797
sh_close(savefd);
1798
}
1799
else
1800
shp->fdstatus[origfd] = IOCLOSE;
1801
}
1802
if(!flag)
1803
{
1804
/* keep file descriptors for subshell restore */
1805
for (fd = last ; fd < shp->topfd; fd++)
1806
{
1807
if(filemap[fd].subshell)
1808
filemap[last++] = filemap[fd];
1809
}
1810
}
1811
if(last < shp->topfd)
1812
shp->topfd = last;
1813
}
1814
1815
/*
1816
* returns access information on open file <fd>
1817
* returns -1 for failure, 0 for success
1818
* <mode> is the same as for access()
1819
*/
1820
int sh_ioaccess(int fd,register int mode)
1821
{
1822
Shell_t *shp = sh_getinterp();
1823
register int flags;
1824
if(mode==X_OK)
1825
return(-1);
1826
if((flags=sh_iocheckfd(shp,fd))!=IOCLOSE)
1827
{
1828
if(mode==F_OK)
1829
return(0);
1830
if(mode==R_OK && (flags&IOREAD))
1831
return(0);
1832
if(mode==W_OK && (flags&IOWRITE))
1833
return(0);
1834
}
1835
return(-1);
1836
}
1837
1838
/*
1839
* Handle interrupts for slow streams
1840
*/
1841
static int slowexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
1842
{
1843
Shell_t *shp = ((struct Iodisc*)handle)->sh;
1844
register int n,fno;
1845
NOT_USED(handle);
1846
if(type==SF_DPOP || type==SF_FINAL)
1847
free((void*)handle);
1848
if(type==SF_WRITE && ERROR_PIPE(errno))
1849
{
1850
sfpurge(iop);
1851
return(-1);
1852
}
1853
if(type!=SF_READ)
1854
return(0);
1855
if((shp->trapnote&(SH_SIGSET|SH_SIGTRAP)) && errno!=EIO && errno!=ENXIO)
1856
errno = EINTR;
1857
fno = sffileno(iop);
1858
if((n=sfvalue(iop))<=0)
1859
{
1860
#ifndef FNDELAY
1861
# ifdef O_NDELAY
1862
if(errno==0 && (n=fcntl(fno,F_GETFL,0))&O_NDELAY)
1863
{
1864
n &= ~O_NDELAY;
1865
fcntl(fno, F_SETFL, n);
1866
return(1);
1867
}
1868
# endif /* O_NDELAY */
1869
#endif /* !FNDELAY */
1870
#ifdef O_NONBLOCK
1871
if(errno==EAGAIN)
1872
{
1873
n = fcntl(fno,F_GETFL,0);
1874
n &= ~O_NONBLOCK;
1875
fcntl(fno, F_SETFL, n);
1876
return(1);
1877
}
1878
#endif /* O_NONBLOCK */
1879
if(errno!=EINTR)
1880
return(0);
1881
else if(shp->bltinfun && (shp->trapnote&SH_SIGTRAP) && shp->lastsig)
1882
return(-1);
1883
n=1;
1884
sh_onstate(SH_TTYWAIT);
1885
}
1886
else
1887
n = 0;
1888
if(shp->bltinfun && shp->bltindata.sigset)
1889
return(-1);
1890
errno = 0;
1891
if(shp->trapnote&SH_SIGSET)
1892
{
1893
if(isatty(fno))
1894
sfputc(sfstderr,'\n');
1895
sh_exit(SH_EXITSIG);
1896
}
1897
if(shp->trapnote&SH_SIGTRAP)
1898
sh_chktrap(shp);
1899
return(n);
1900
}
1901
1902
/*
1903
* called when slowread times out
1904
*/
1905
static void time_grace(void *handle)
1906
{
1907
Shell_t *shp = (Shell_t*)handle;
1908
timeout = 0;
1909
if(sh_isstate(SH_GRACE))
1910
{
1911
sh_offstate(SH_GRACE);
1912
if(!sh_isstate(SH_INTERACTIVE))
1913
return;
1914
((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
1915
errormsg(SH_DICT,2,e_timeout);
1916
shp->trapnote |= SH_SIGSET;
1917
return;
1918
}
1919
errormsg(SH_DICT,0,e_timewarn);
1920
sh_onstate(SH_GRACE);
1921
sigrelease(SIGALRM);
1922
shp->trapnote |= SH_SIGTRAP;
1923
}
1924
1925
static ssize_t piperead(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1926
{
1927
Shell_t *shp = ((struct Iodisc*)handle)->sh;
1928
int fd = sffileno(iop);
1929
if(job.waitsafe && job.savesig)
1930
{
1931
job_lock();
1932
job_unlock();
1933
}
1934
if(shp->trapnote)
1935
{
1936
errno = EINTR;
1937
return(-1);
1938
}
1939
if(sh_isstate(SH_INTERACTIVE) && sffileno(iop)==0 && io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
1940
return(0);
1941
sh_onstate(SH_TTYWAIT);
1942
if(!(shp->fdstatus[fd]&IOCLEX) && (sfset(iop,0,0)&SF_SHARE))
1943
size = ed_read(shgd->ed_context, fd, (char*)buff, size,0);
1944
else
1945
size = sfrd(iop,buff,size,handle);
1946
sh_offstate(SH_TTYWAIT);
1947
return(size);
1948
}
1949
/*
1950
* This is the read discipline that is applied to slow devices
1951
* This routine takes care of prompting for input
1952
*/
1953
static ssize_t slowread(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1954
{
1955
Shell_t *shp = ((struct Iodisc*)handle)->sh;
1956
int (*readf)(void*, int, char*, int, int);
1957
int reedit=0, rsize;
1958
#if SHOPT_HISTEXPAND
1959
char *xp=0;
1960
#endif
1961
# if SHOPT_ESH
1962
if(sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS))
1963
readf = ed_emacsread;
1964
else
1965
# endif /* SHOPT_ESH */
1966
# if SHOPT_VSH
1967
# if SHOPT_RAWONLY
1968
if(sh_isoption(SH_VI) || ((SHOPT_RAWONLY-0) && mbwide()))
1969
# else
1970
if(sh_isoption(SH_VI))
1971
# endif
1972
readf = ed_viread;
1973
else
1974
# endif /* SHOPT_VSH */
1975
readf = ed_read;
1976
if(shp->trapnote)
1977
{
1978
errno = EINTR;
1979
return(-1);
1980
}
1981
while(1)
1982
{
1983
if(io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
1984
return(0);
1985
if(shp->timeout)
1986
timeout = (void*)sh_timeradd(sh_isstate(SH_GRACE)?1000L*TGRACE:1000L*shp->timeout,0,time_grace,shp);
1987
rsize = (*readf)(shgd->ed_context, sffileno(iop), (char*)buff, size, reedit);
1988
if(timeout)
1989
timerdel(timeout);
1990
timeout=0;
1991
#if SHOPT_HISTEXPAND
1992
if(rsize && *(char*)buff != '\n' && shp->nextprompt==1 && sh_isoption(SH_HISTEXPAND))
1993
{
1994
int r;
1995
((char*)buff)[rsize] = '\0';
1996
if(xp)
1997
{
1998
free(xp);
1999
xp = 0;
2000
}
2001
r = hist_expand(buff, &xp);
2002
if((r & (HIST_EVENT|HIST_PRINT)) && !(r & HIST_ERROR) && xp)
2003
{
2004
strlcpy(buff, xp, size);
2005
rsize = strlen(buff);
2006
if(!sh_isoption(SH_HISTVERIFY) || readf==ed_read)
2007
{
2008
sfputr(sfstderr, xp, -1);
2009
break;
2010
}
2011
reedit = rsize - 1;
2012
continue;
2013
}
2014
if((r & HIST_ERROR) && sh_isoption(SH_HISTREEDIT))
2015
{
2016
reedit = rsize - 1;
2017
continue;
2018
}
2019
if(r & (HIST_ERROR|HIST_PRINT))
2020
{
2021
*(char*)buff = '\n';
2022
rsize = 1;
2023
}
2024
}
2025
#endif
2026
break;
2027
}
2028
return(rsize);
2029
}
2030
2031
/*
2032
* check and return the attributes for a file descriptor
2033
*/
2034
2035
int sh_iocheckfd(Shell_t *shp, register int fd)
2036
{
2037
register int flags, n;
2038
if((n=shp->fdstatus[fd])&IOCLOSE)
2039
return(n);
2040
if(!(n&(IOREAD|IOWRITE)))
2041
{
2042
#ifdef F_GETFL
2043
if((flags=fcntl(fd,F_GETFL,0)) < 0)
2044
return(shp->fdstatus[fd]=IOCLOSE);
2045
if((flags&O_ACCMODE)!=O_WRONLY)
2046
n |= IOREAD;
2047
if((flags&O_ACCMODE)!=O_RDONLY)
2048
n |= IOWRITE;
2049
#else
2050
struct stat statb;
2051
if((flags = fstat(fd,&statb))< 0)
2052
return(shp->fdstatus[fd]=IOCLOSE);
2053
n |= (IOREAD|IOWRITE);
2054
if(read(fd,"",0) < 0)
2055
n &= ~IOREAD;
2056
#endif /* F_GETFL */
2057
}
2058
if(!(n&(IOSEEK|IONOSEEK)))
2059
{
2060
struct stat statb;
2061
/* /dev/null check is a workaround for select bug */
2062
static ino_t null_ino;
2063
static dev_t null_dev;
2064
if(null_ino==0 && stat(e_devnull,&statb) >=0)
2065
{
2066
null_ino = statb.st_ino;
2067
null_dev = statb.st_dev;
2068
}
2069
if(tty_check(fd))
2070
n |= IOTTY;
2071
if(lseek(fd,NIL(off_t),SEEK_CUR)<0)
2072
{
2073
n |= IONOSEEK;
2074
#ifdef S_ISSOCK
2075
if((fstat(fd,&statb)>=0) && S_ISSOCK(statb.st_mode))
2076
{
2077
n |= IOREAD|IOWRITE;
2078
# if _socketpair_shutdown_mode
2079
if(!(statb.st_mode&S_IRUSR))
2080
n &= ~IOREAD;
2081
else if(!(statb.st_mode&S_IWUSR))
2082
n &= ~IOWRITE;
2083
# endif
2084
}
2085
#endif /* S_ISSOCK */
2086
}
2087
else if((fstat(fd,&statb)>=0) && (
2088
S_ISFIFO(statb.st_mode) ||
2089
#ifdef S_ISSOCK
2090
S_ISSOCK(statb.st_mode) ||
2091
#endif /* S_ISSOCK */
2092
/* The following is for sockets on the sgi */
2093
(statb.st_ino==0 && (statb.st_mode & ~(S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH|S_IXUSR|S_IXGRP|S_IXOTH|S_ISUID|S_ISGID))==0) ||
2094
(S_ISCHR(statb.st_mode) && (statb.st_ino!=null_ino || statb.st_dev!=null_dev))
2095
))
2096
n |= IONOSEEK;
2097
else
2098
n |= IOSEEK;
2099
}
2100
if(fd==0)
2101
n &= ~IOWRITE;
2102
else if(fd==1)
2103
n &= ~IOREAD;
2104
shp->fdstatus[fd] = n;
2105
return(n);
2106
}
2107
2108
/*
2109
* Display prompt PS<flag> on standard error
2110
*/
2111
2112
static int io_prompt(Shell_t *shp,Sfio_t *iop,register int flag)
2113
{
2114
register char *cp;
2115
char buff[1];
2116
char *endprompt;
2117
static short cmdno;
2118
int sfflags;
2119
if(flag<3 && !sh_isstate(SH_INTERACTIVE))
2120
flag = 0;
2121
if(flag==2 && sfpkrd(sffileno(iop),buff,1,'\n',0,1) >= 0)
2122
flag = 0;
2123
if(flag==0)
2124
return(sfsync(sfstderr));
2125
sfflags = sfset(sfstderr,SF_SHARE|SF_PUBLIC|SF_READ,0);
2126
if(!(shp->prompt=(char*)sfreserve(sfstderr,0,0)))
2127
shp->prompt = "";
2128
switch(flag)
2129
{
2130
case 1:
2131
{
2132
register int c;
2133
#if defined(TIOCLBIC) && defined(LFLUSHO)
2134
if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
2135
{
2136
/*
2137
* re-enable output in case the user has
2138
* disabled it. Not needed with edit mode
2139
*/
2140
int mode = LFLUSHO;
2141
ioctl(sffileno(sfstderr),TIOCLBIC,&mode);
2142
}
2143
#endif /* TIOCLBIC */
2144
cp = sh_mactry(shp,nv_getval(sh_scoped(shp,PS1NOD)));
2145
for(;c= *cp;cp++)
2146
{
2147
if(c==HIST_CHAR)
2148
{
2149
/* look at next character */
2150
c = *++cp;
2151
/* print out line number if not !! */
2152
if(c!= HIST_CHAR)
2153
{
2154
sfprintf(sfstderr,"%d", shp->gd->hist_ptr?(int)shp->gd->hist_ptr->histind:++cmdno);
2155
}
2156
if(c==0)
2157
goto done;
2158
}
2159
sfputc(sfstderr,c);
2160
}
2161
goto done;
2162
}
2163
case 2:
2164
cp = nv_getval(sh_scoped(shp,PS2NOD));
2165
break;
2166
case 3:
2167
cp = nv_getval(sh_scoped(shp,PS3NOD));
2168
break;
2169
default:
2170
goto done;
2171
}
2172
if(cp)
2173
sfputr(sfstderr,cp,-1);
2174
done:
2175
if(*shp->prompt && (endprompt=(char*)sfreserve(sfstderr,0,0)))
2176
*endprompt = 0;
2177
sfset(sfstderr,sfflags&SF_READ|SF_SHARE|SF_PUBLIC,1);
2178
return(sfsync(sfstderr));
2179
}
2180
2181
/*
2182
* This discipline is inserted on write pipes to prevent SIGPIPE
2183
* from causing an infinite loop
2184
*/
2185
static int pipeexcept(Sfio_t* iop, int mode, void *data, Sfdisc_t* handle)
2186
{
2187
if(mode==SF_DPOP || mode==SF_FINAL)
2188
free((void*)handle);
2189
else if(mode==SF_WRITE && ERROR_PIPE(errno))
2190
{
2191
sfpurge(iop);
2192
return(-1);
2193
}
2194
return(0);
2195
}
2196
2197
/*
2198
* keep track of each stream that is opened and closed
2199
*/
2200
static void sftrack(Sfio_t* sp, int flag, void* data)
2201
{
2202
Shell_t *shp = sh_getinterp();
2203
register int fd = sffileno(sp);
2204
register struct checkpt *pp;
2205
register int mode;
2206
int newfd = integralof(data);
2207
if(flag==SF_SETFD || flag==SF_CLOSING)
2208
{
2209
if(newfd<0)
2210
flag = SF_CLOSING;
2211
if(fdnotify)
2212
(*fdnotify)(sffileno(sp),flag==SF_CLOSING?-1:newfd);
2213
}
2214
#ifdef DEBUG
2215
if(flag==SF_READ || flag==SF_WRITE)
2216
{
2217
char *z = fmtbase((long)getpid(),0,0);
2218
write(ERRIO,z,strlen(z));
2219
write(ERRIO,": ",2);
2220
write(ERRIO,"attempt to ",11);
2221
if(flag==SF_READ)
2222
write(ERRIO,"read from",9);
2223
else
2224
write(ERRIO,"write to",8);
2225
write(ERRIO," locked stream\n",15);
2226
return;
2227
}
2228
#endif
2229
if(fd<0 || fd==PSEUDOFD || (fd>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fd)))
2230
return;
2231
if(sh_isstate(SH_NOTRACK))
2232
return;
2233
mode = sfset(sp,0,0);
2234
if(sp==shp->heredocs && fd < 10 && flag==SF_SETFD)
2235
{
2236
fd = sfsetfd(sp,10);
2237
fcntl(fd,F_SETFD,FD_CLOEXEC);
2238
}
2239
if(fd < 3)
2240
return;
2241
if(flag==SF_NEW)
2242
{
2243
if(!shp->sftable[fd] && shp->fdstatus[fd]==IOCLOSE)
2244
{
2245
shp->sftable[fd] = sp;
2246
flag = (mode&SF_WRITE)?IOWRITE:0;
2247
if(mode&SF_READ)
2248
flag |= IOREAD;
2249
shp->fdstatus[fd] = flag;
2250
sh_iostream(shp,fd);
2251
}
2252
if((pp=(struct checkpt*)shp->jmplist) && pp->mode==SH_JMPCMD)
2253
{
2254
struct openlist *item;
2255
/*
2256
* record open file descriptors so they can
2257
* be closed in case a longjmp prevents
2258
* built-ins from cleanup
2259
*/
2260
item = new_of(struct openlist, 0);
2261
item->strm = sp;
2262
item->next = pp->olist;
2263
pp->olist = item;
2264
}
2265
if(fdnotify)
2266
(*fdnotify)(-1,sffileno(sp));
2267
}
2268
else if(flag==SF_CLOSING || (flag==SF_SETFD && newfd<=2))
2269
{
2270
shp->sftable[fd] = 0;
2271
shp->fdstatus[fd]=IOCLOSE;
2272
if(pp=(struct checkpt*)shp->jmplist)
2273
{
2274
struct openlist *item;
2275
for(item=pp->olist; item; item=item->next)
2276
{
2277
if(item->strm == sp)
2278
{
2279
item->strm = 0;
2280
break;
2281
}
2282
}
2283
}
2284
}
2285
}
2286
2287
struct eval
2288
{
2289
Sfdisc_t disc;
2290
char **argv;
2291
short slen;
2292
char addspace;
2293
};
2294
2295
/*
2296
* Create a stream consisting of a space separated argv[] list
2297
*/
2298
2299
Sfio_t *sh_sfeval(register char *argv[])
2300
{
2301
register Sfio_t *iop;
2302
register char *cp;
2303
if(argv[1])
2304
cp = "";
2305
else
2306
cp = argv[0];
2307
iop = sfopen(NIL(Sfio_t*),(char*)cp,"s");
2308
if(argv[1])
2309
{
2310
register struct eval *ep;
2311
if(!(ep = new_of(struct eval,0)))
2312
return(NIL(Sfio_t*));
2313
ep->disc = eval_disc;
2314
ep->argv = argv;
2315
ep->slen = -1;
2316
ep->addspace = 0;
2317
sfdisc(iop,&ep->disc);
2318
}
2319
return(iop);
2320
}
2321
2322
/*
2323
* This code gets called whenever an end of string is found with eval
2324
*/
2325
2326
static int eval_exceptf(Sfio_t *iop,int type, void *data, Sfdisc_t *handle)
2327
{
2328
register struct eval *ep = (struct eval*)handle;
2329
register char *cp;
2330
register int len;
2331
2332
/* no more to do */
2333
if(type!=SF_READ || !(cp = ep->argv[0]))
2334
{
2335
if(type==SF_CLOSING)
2336
sfdisc(iop,SF_POPDISC);
2337
else if(ep && (type==SF_DPOP || type==SF_FINAL))
2338
free((void*)ep);
2339
return(0);
2340
}
2341
2342
if(!ep->addspace)
2343
{
2344
/* get the length of this string */
2345
ep->slen = len = strlen(cp);
2346
/* move to next string */
2347
ep->argv++;
2348
}
2349
else /* insert space between arguments */
2350
{
2351
len = 1;
2352
cp = " ";
2353
}
2354
/* insert the new string */
2355
sfsetbuf(iop,cp,len);
2356
ep->addspace = !ep->addspace;
2357
return(1);
2358
}
2359
2360
/*
2361
* This routine returns a stream pointer to a segment of length <size> from
2362
* the stream <sp> starting at offset <offset>
2363
* The stream can be read with the normal stream operations
2364
*/
2365
2366
static Sfio_t *subopen(Shell_t *shp,Sfio_t* sp, off_t offset, long size)
2367
{
2368
register struct subfile *disp;
2369
if(sfseek(sp,offset,SEEK_SET) <0)
2370
return(NIL(Sfio_t*));
2371
if(!(disp = (struct subfile*)malloc(sizeof(struct subfile)+IOBSIZE+1)))
2372
return(NIL(Sfio_t*));
2373
disp->disc = sub_disc;
2374
disp->oldsp = sp;
2375
disp->offset = offset;
2376
disp->size = disp->left = size;
2377
sp = sfnew(NIL(Sfio_t*),(char*)(disp+1),IOBSIZE,PSEUDOFD,SF_READ);
2378
sfdisc(sp,&disp->disc);
2379
return(sp);
2380
}
2381
2382
/*
2383
* read function for subfile discipline
2384
*/
2385
static ssize_t subread(Sfio_t* sp,void* buff,register size_t size,Sfdisc_t* handle)
2386
{
2387
register struct subfile *disp = (struct subfile*)handle;
2388
ssize_t n;
2389
NOT_USED(sp);
2390
sfseek(disp->oldsp,disp->offset,SEEK_SET);
2391
if(disp->left == 0)
2392
return(0);
2393
if(size > disp->left)
2394
size = disp->left;
2395
disp->left -= size;
2396
n = sfread(disp->oldsp,buff,size);
2397
if(size>0)
2398
disp->offset += size;
2399
return(n);
2400
}
2401
2402
/*
2403
* exception handler for subfile discipline
2404
*/
2405
static int subexcept(Sfio_t* sp,register int mode, void *data, Sfdisc_t* handle)
2406
{
2407
register struct subfile *disp = (struct subfile*)handle;
2408
if(mode==SF_CLOSING)
2409
{
2410
sfdisc(sp,SF_POPDISC);
2411
sfsetfd(sp,-1);
2412
return(0);
2413
}
2414
else if(disp && (mode==SF_DPOP || mode==SF_FINAL))
2415
{
2416
free((void*)disp);
2417
return(0);
2418
}
2419
#ifdef SF_ATEXIT
2420
else if (mode==SF_ATEXIT)
2421
{
2422
sfdisc(sp, SF_POPDISC);
2423
return(0);
2424
}
2425
#endif
2426
else if(mode==SF_READ)
2427
return(0);
2428
return(-1);
2429
}
2430
2431
#define NROW 15 /* number of rows before going to multi-columns */
2432
#define LBLSIZ 3 /* size of label field and interfield spacing */
2433
/*
2434
* print a list of arguments in columns
2435
*/
2436
void sh_menu(Sfio_t *outfile,int argn,char *argv[])
2437
{
2438
Shell_t *shp = sh_getinterp();
2439
register int i,j;
2440
register char **arg;
2441
int nrow, ncol=1, ndigits=1;
2442
int fldsize, wsize = ed_window();
2443
char *cp = nv_getval(sh_scoped(shp,LINES));
2444
nrow = (cp?1+2*((int)strtol(cp, (char**)0, 10)/3):NROW);
2445
for(i=argn;i >= 10;i /= 10)
2446
ndigits++;
2447
if(argn < nrow)
2448
{
2449
nrow = argn;
2450
goto skip;
2451
}
2452
i = 0;
2453
for(arg=argv; *arg;arg++)
2454
{
2455
if((j=strlen(*arg)) > i)
2456
i = j;
2457
}
2458
i += (ndigits+LBLSIZ);
2459
if(i < wsize)
2460
ncol = wsize/i;
2461
if(argn > nrow*ncol)
2462
{
2463
nrow = 1 + (argn-1)/ncol;
2464
}
2465
else
2466
{
2467
ncol = 1 + (argn-1)/nrow;
2468
nrow = 1 + (argn-1)/ncol;
2469
}
2470
skip:
2471
fldsize = (wsize/ncol)-(ndigits+LBLSIZ);
2472
for(i=0;i<nrow;i++)
2473
{
2474
if(shp->trapnote&SH_SIGSET)
2475
return;
2476
j = i;
2477
while(1)
2478
{
2479
arg = argv+j;
2480
sfprintf(outfile,"%*d) %s",ndigits,j+1,*arg);
2481
j += nrow;
2482
if(j >= argn)
2483
break;
2484
sfnputc(outfile,' ',fldsize-strlen(*arg));
2485
}
2486
sfputc(outfile,'\n');
2487
}
2488
}
2489
2490
#undef read
2491
/*
2492
* shell version of read() for user added builtins
2493
*/
2494
ssize_t sh_read(register int fd, void* buff, size_t n)
2495
{
2496
Shell_t *shp = sh_getinterp();
2497
register Sfio_t *sp;
2498
if(sp=shp->sftable[fd])
2499
return(sfread(sp,buff,n));
2500
else
2501
return(read(fd,buff,n));
2502
}
2503
2504
#undef write
2505
/*
2506
* shell version of write() for user added builtins
2507
*/
2508
ssize_t sh_write(register int fd, const void* buff, size_t n)
2509
{
2510
Shell_t *shp = sh_getinterp();
2511
register Sfio_t *sp;
2512
if(sp=shp->sftable[fd])
2513
return(sfwrite(sp,buff,n));
2514
else
2515
return(write(fd,buff,n));
2516
}
2517
2518
#undef lseek
2519
/*
2520
* shell version of lseek() for user added builtins
2521
*/
2522
off_t sh_seek(register int fd, off_t offset, int whence)
2523
{
2524
Shell_t *shp = sh_getinterp();
2525
register Sfio_t *sp;
2526
if((sp=shp->sftable[fd]) && (sfset(sp,0,0)&(SF_READ|SF_WRITE)))
2527
return(sfseek(sp,offset,whence));
2528
else
2529
return(lseek(fd,offset,whence));
2530
}
2531
2532
#undef dup
2533
int sh_dup(register int old)
2534
{
2535
Shell_t *shp = sh_getinterp();
2536
register int fd = dup(old);
2537
if(fd>=0)
2538
{
2539
if(shp->fdstatus[old] == IOCLOSE)
2540
shp->fdstatus[old] = 0;
2541
shp->fdstatus[fd] = (shp->fdstatus[old]&~IOCLEX);
2542
if(fdnotify)
2543
(*fdnotify)(old,fd);
2544
}
2545
return(fd);
2546
}
2547
2548
#undef fcntl
2549
int sh_fcntl(register int fd, int op, ...)
2550
{
2551
Shell_t *shp = sh_getinterp();
2552
int newfd, arg;
2553
va_list ap;
2554
va_start(ap, op);
2555
arg = va_arg(ap, int) ;
2556
va_end(ap);
2557
newfd = fcntl(fd,op,arg);
2558
if(newfd>=0) switch(op)
2559
{
2560
case F_DUPFD:
2561
if(shp->fdstatus[fd] == IOCLOSE)
2562
shp->fdstatus[fd] = 0;
2563
if(newfd>=shp->gd->lim.open_max)
2564
sh_iovalidfd(shp,newfd);
2565
shp->fdstatus[newfd] = (shp->fdstatus[fd]&~IOCLEX);
2566
if(fdnotify)
2567
(*fdnotify)(fd,newfd);
2568
break;
2569
case F_SETFD:
2570
if(shp->fdstatus[fd] == IOCLOSE)
2571
shp->fdstatus[fd] = 0;
2572
if(arg&FD_CLOEXEC)
2573
shp->fdstatus[fd] |= IOCLEX;
2574
else
2575
shp->fdstatus[fd] &= ~IOCLEX;
2576
}
2577
return(newfd);
2578
}
2579
2580
#undef umask
2581
mode_t sh_umask(mode_t m)
2582
{
2583
Shell_t *shp = sh_getinterp();
2584
shp->mask = m;
2585
return(umask(m));
2586
}
2587
2588
/*
2589
* give file descriptor <fd> and <mode>, return an iostream pointer
2590
* <mode> must be SF_READ or SF_WRITE
2591
* <fd> must be a non-negative number ofr SH_IOCOPROCESS or SH_IOHISTFILE.
2592
* returns NULL on failure and may set errno.
2593
*/
2594
2595
Sfio_t *sh_iogetiop(int fd, int mode)
2596
{
2597
Shell_t *shp = sh_getinterp();
2598
int n;
2599
Sfio_t *iop=0;
2600
if(mode!=SF_READ && mode!=SF_WRITE)
2601
{
2602
errno = EINVAL;
2603
return(iop);
2604
}
2605
switch(fd)
2606
{
2607
case SH_IOHISTFILE:
2608
if(!sh_histinit((void*)shp))
2609
return(iop);
2610
fd = sffileno(shp->gd->hist_ptr->histfp);
2611
break;
2612
case SH_IOCOPROCESS:
2613
if(mode==SF_WRITE)
2614
fd = shp->coutpipe;
2615
else
2616
fd = shp->cpipe[0];
2617
break;
2618
default:
2619
if(fd<0 || !sh_iovalidfd(shp,fd))
2620
fd = -1;
2621
}
2622
if(fd<0)
2623
{
2624
errno = EBADF;
2625
return(iop);
2626
}
2627
if(!(n=shp->fdstatus[fd]))
2628
n = sh_iocheckfd(shp,fd);
2629
if(mode==SF_WRITE && !(n&IOWRITE))
2630
return(iop);
2631
if(mode==SF_READ && !(n&IOREAD))
2632
return(iop);
2633
if(!(iop = shp->sftable[fd]))
2634
iop=sh_iostream(shp,fd);
2635
return(iop);
2636
}
2637
2638
typedef int (*Notify_f)(int,int);
2639
2640
Notify_f sh_fdnotify(Notify_f notify)
2641
{
2642
Notify_f old;
2643
old = fdnotify;
2644
fdnotify = notify;
2645
return(old);
2646
}
2647
2648
Sfio_t *sh_fd2sfio(int fd)
2649
{
2650
Shell_t *shp = sh_getinterp();
2651
register int status;
2652
Sfio_t *sp = shp->sftable[fd];
2653
if(!sp && (status = sh_iocheckfd(shp,fd))!=IOCLOSE)
2654
{
2655
register int flags=0;
2656
if(status&IOREAD)
2657
flags |= SF_READ;
2658
if(status&IOWRITE)
2659
flags |= SF_WRITE;
2660
sp = sfnew(NULL, NULL, -1, fd,flags);
2661
shp->sftable[fd] = sp;
2662
}
2663
return(sp);
2664
}
2665
2666
Sfio_t *sh_pathopen(const char *cp)
2667
{
2668
Shell_t *shp = sh_getinterp();
2669
int n;
2670
#ifdef PATH_BFPATH
2671
if((n=path_open(shp,cp,path_get(shp,cp))) < 0)
2672
n = path_open(shp,cp,(Pathcomp_t*)0);
2673
#else
2674
if((n=path_open(shp,cp,path_get(cp))) < 0)
2675
n = path_open(shp,cp,"");
2676
#endif
2677
if(n < 0)
2678
errormsg(SH_DICT,ERROR_system(1),e_open,cp);
2679
return(sh_iostream(shp,n));
2680
}
2681
2682
int sh_isdevfd(register const char *fd)
2683
{
2684
if(!fd || memcmp(fd,"/dev/fd/",8) || fd[8]==0)
2685
return(0);
2686
for ( fd=&fd[8] ; *fd != '\0' ; fd++ )
2687
{
2688
if (*fd < '0' || *fd > '9')
2689
return(0);
2690
}
2691
return(1);
2692
}
2693
2694
#undef fchdir
2695
int sh_fchdir(int fd)
2696
{
2697
int r,err=errno;
2698
while((r=fchdir(fd))<0 && errno==EINTR)
2699
errno = err;
2700
return(r);
2701
}
2702
2703
#undef chdir
2704
int sh_chdir(const char* dir)
2705
{
2706
int r,err=errno;
2707
while((r=chdir(dir))<0 && errno==EINTR)
2708
errno = err;
2709
return(r);
2710
}
2711
2712
2713