Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "sam.h"
2
#include "parse.h"
3
 
4
extern	jmp_buf	mainloop;
5
 
6
char	errfile[64];
7
String	plan9cmd;	/* null terminated */
8
Buffer	plan9buf;
9
void	checkerrs(void);
10
 
11
int
12
plan9(File *f, int type, String *s, int nest)
13
{
14
	long l;
15
	int m;
16
	int pid, fd;
17
	int retcode;
18
	char *retmsg;
19
	int pipe1[2], pipe2[2];
20
 
21
	if(s->s[0]==0 && plan9cmd.s[0]==0)
22
		error(Enocmd);
23
	else if(s->s[0])
24
		Strduplstr(&plan9cmd, s);
25
	if(downloaded){
26
		samerr(errfile);
27
		remove(errfile);
28
	}
29
	if(type!='!' && pipe(pipe1)==-1)
30
		error(Epipe);
31
	if(type=='|')
32
		snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1);
33
	if((pid=fork()) == 0){
34
		if(downloaded){	/* also put nasty fd's into errfile */
35
			fd = create(errfile, 1, 0666L);
36
			if(fd < 0)
37
				fd = create("/dev/null", 1, 0666L);
38
			dup(fd, 2);
39
			close(fd);
40
			/* 2 now points at err file */
41
			if(type == '>')
42
				dup(2, 1);
43
			else if(type=='!'){
44
				dup(2, 1);
45
				fd = open("/dev/null", 0);
46
				dup(fd, 0);
47
				close(fd);
48
			}
49
		}
50
		if(type != '!') {
51
			if(type=='<' || type=='|')
52
				dup(pipe1[1], 1);
53
			else if(type == '>')
54
				dup(pipe1[0], 0);
55
			close(pipe1[0]);
56
			close(pipe1[1]);
57
		}
58
		if(type == '|'){
59
			if(pipe(pipe2) == -1)
60
				exits("pipe");
61
			if((pid = fork())==0){
62
				/*
63
				 * It's ok if we get SIGPIPE here
64
				 */
65
				close(pipe2[0]);
66
				io = pipe2[1];
67
				if(retcode=!setjmp(mainloop)){	/* assignment = */
68
					char *c;
69
					for(l = 0; l<plan9buf.nc; l+=m){
70
						m = plan9buf.nc-l;
71
						if(m>BLOCKSIZE-1)
72
							m = BLOCKSIZE-1;
73
						bufread(&plan9buf, l, genbuf, m);
74
						genbuf[m] = 0;
75
						c = Strtoc(tmprstr(genbuf, m+1));
76
						Write(pipe2[1], c, strlen(c));
77
						free(c);
78
					}
79
				}
80
				exits(retcode? "error" : 0);
81
			}
82
			if(pid==-1){
83
				fprint(2, "Can't fork?!\n");
84
				exits("fork");
85
			}
86
			dup(pipe2[0], 0);
87
			close(pipe2[0]);
88
			close(pipe2[1]);
89
		}
90
		if(type=='<'){
91
			close(0);	/* so it won't read from terminal */
92
			open("/dev/null", 0);
93
		}
94
		execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), nil);
95
		exits("exec");
96
	}
97
	if(pid == -1)
98
		error(Efork);
99
	if(type=='<' || type=='|'){
100
		int nulls;
101
		if(downloaded && addr.r.p1 != addr.r.p2)
102
			outTl(Hsnarflen, addr.r.p2-addr.r.p1);
103
		snarf(f, addr.r.p1, addr.r.p2, &snarfbuf, 0);
104
		logdelete(f, addr.r.p1, addr.r.p2);
105
		close(pipe1[1]);
106
		io = pipe1[0];
107
		f->tdot.p1 = -1;
108
		f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0, FALSE);
109
		f->ndot.r.p1 = addr.r.p2;
110
		closeio((Posn)-1);
111
	}else if(type=='>'){
112
		close(pipe1[0]);
113
		io = pipe1[1];
114
		bpipeok = 1;
115
		writeio(f);
116
		bpipeok = 0;
117
		closeio((Posn)-1);
118
	}
119
	retmsg = waitfor(pid);
120
	if(type=='|' || type=='<')
121
		if(retmsg[0]!=0)
122
			warn_s(Wbadstatus, retmsg);
123
	if(downloaded)
124
		checkerrs();
125
	if(!nest)
126
		dprint("!\n");
127
	return retmsg[0] ? -1 : 0;
128
}
129
 
130
void
131
checkerrs(void)
132
{
133
	char buf[256];
134
	int f, n, nl;
135
	char *p;
136
	long l;
137
 
138
	if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){
139
		if((f=open((char *)errfile, 0)) != -1){
140
			if((n=read(f, buf, sizeof buf-1)) > 0){
141
				for(nl=0,p=buf; nl<3 && p<&buf[n]; p++)
142
					if(*p=='\n')
143
						nl++;
144
				*p = 0;
145
				dprint("%s", buf);
146
				if(p-buf < l-1)
147
					dprint("(sam: more in %s)\n", errfile);
148
			}
149
			close(f);
150
		}
151
	}else
152
		remove((char *)errfile);
153
}