xref: /plan9/sys/src/cmd/sam/io.c (revision e7d295677b9ada08eb7a196a06047fdf5d8dfea2)
1 #include "sam.h"
2 
3 #define	NSYSFILE	3
4 #define	NOFILE		128
5 
6 void
checkqid(File * f)7 checkqid(File *f)
8 {
9 	int i, w;
10 	File *g;
11 
12 	w = whichmenu(f);
13 	for(i=1; i<file.nused; i++){
14 		g = file.filepptr[i];
15 		if(w == i)
16 			continue;
17 		if(f->dev==g->dev && f->qidpath==g->qidpath)
18 			warn_SS(Wdupfile, &f->name, &g->name);
19 	}
20 }
21 
22 void
writef(File * f)23 writef(File *f)
24 {
25 	Posn n;
26 	char *name;
27 	int i, samename, newfile;
28 	ulong dev;
29 	uvlong qid;
30 	long mtime, appendonly, length;
31 
32 	newfile = 0;
33 	samename = Strcmp(&genstr, &f->name) == 0;
34 	name = Strtoc(&f->name);
35 	i = statfile(name, &dev, &qid, &mtime, 0, 0);
36 	if(i == -1)
37 		newfile++;
38 	else if(samename &&
39 	        (f->dev!=dev || f->qidpath!=qid || f->mtime<mtime)){
40 		f->dev = dev;
41 		f->qidpath = qid;
42 		f->mtime = mtime;
43 		warn_S(Wdate, &genstr);
44 		return;
45 	}
46 	if(genc)
47 		free(genc);
48 	genc = Strtoc(&genstr);
49 	if((io=create(genc, 1, 0666L)) < 0)
50 		error_r(Ecreate, genc);
51 	dprint("%s: ", genc);
52 	if(statfd(io, 0, 0, 0, &length, &appendonly) > 0 && appendonly && length>0)
53 		error(Eappend);
54 	n = writeio(f);
55 	if(f->name.s[0]==0 || samename){
56 		if(addr.r.p1==0 && addr.r.p2==f->nc)
57 			f->cleanseq = f->seq;
58 		state(f, f->cleanseq==f->seq? Clean : Dirty);
59 	}
60 	if(newfile)
61 		dprint("(new file) ");
62 	if(addr.r.p2>0 && filereadc(f, addr.r.p2-1)!='\n')
63 		warn(Wnotnewline);
64 	closeio(n);
65 	if(f->name.s[0]==0 || samename){
66 		if(statfile(name, &dev, &qid, &mtime, 0, 0) > 0){
67 			f->dev = dev;
68 			f->qidpath = qid;
69 			f->mtime = mtime;
70 			checkqid(f);
71 		}
72 	}
73 }
74 
75 Posn
readio(File * f,int * nulls,int setdate,int toterm)76 readio(File *f, int *nulls, int setdate, int toterm)
77 {
78 	int n, b, w;
79 	Rune *r;
80 	Posn nt;
81 	Posn p = addr.r.p2;
82 	ulong dev;
83 	uvlong qid;
84 	long mtime;
85 	char buf[BLOCKSIZE+1], *s;
86 
87 	*nulls = FALSE;
88 	b = 0;
89 	if(f->unread){
90 		nt = bufload(f, 0, io, nulls);
91 		if(toterm)
92 			raspload(f);
93 	}else
94 		for(nt = 0; (n = read(io, buf+b, BLOCKSIZE-b))>0; nt+=(r-genbuf)){
95 			n += b;
96 			b = 0;
97 			r = genbuf;
98 			s = buf;
99 			while(n > 0){
100 				if((*r = *(uchar*)s) < Runeself){
101 					if(*r)
102 						r++;
103 					else
104 						*nulls = TRUE;
105 					--n;
106 					s++;
107 					continue;
108 				}
109 				if(fullrune(s, n)){
110 					w = chartorune(r, s);
111 					if(*r)
112 						r++;
113 					else
114 						*nulls = TRUE;
115 					n -= w;
116 					s += w;
117 					continue;
118 				}
119 				b = n;
120 				memmove(buf, s, b);
121 				break;
122 			}
123 			loginsert(f, p, genbuf, r-genbuf);
124 		}
125 	if(b)
126 		*nulls = TRUE;
127 	if(*nulls)
128 		warn(Wnulls);
129 	if(setdate){
130 		if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){
131 			f->dev = dev;
132 			f->qidpath = qid;
133 			f->mtime = mtime;
134 			checkqid(f);
135 		}
136 	}
137 	return nt;
138 }
139 
140 Posn
writeio(File * f)141 writeio(File *f)
142 {
143 	int m, n;
144 	Posn p = addr.r.p1;
145 	char *c;
146 
147 	while(p < addr.r.p2){
148 		if(addr.r.p2-p>BLOCKSIZE)
149 			n = BLOCKSIZE;
150 		else
151 			n = addr.r.p2-p;
152 		bufread(f, p, genbuf, n);
153 		c = Strtoc(tmprstr(genbuf, n));
154 		m = strlen(c);
155 		if(Write(io, c, m) != m){
156 			free(c);
157 			if(p > 0)
158 				p += n;
159 			break;
160 		}
161 		free(c);
162 		p += n;
163 	}
164 	return p-addr.r.p1;
165 }
166 void
closeio(Posn p)167 closeio(Posn p)
168 {
169 	close(io);
170 	io = 0;
171 	if(p >= 0)
172 		dprint("#%lud\n", p);
173 }
174 
175 int	remotefd0 = 0;
176 int	remotefd1 = 1;
177 
178 void
bootterm(char * machine,char ** argv)179 bootterm(char *machine, char **argv)
180 {
181 	int ph2t[2], pt2h[2];
182 
183 	if(machine){
184 		dup(remotefd0, 0);
185 		dup(remotefd1, 1);
186 		close(remotefd0);
187 		close(remotefd1);
188 		argv[0] = "samterm";
189 		exec(samterm, argv);
190 		fprint(2, "can't exec: ");
191 		perror(samterm);
192 		_exits("damn");
193 	}
194 	if(pipe(ph2t)==-1 || pipe(pt2h)==-1)
195 		panic("pipe");
196 	switch(fork()){
197 	case 0:
198 		dup(ph2t[0], 0);
199 		dup(pt2h[1], 1);
200 		close(ph2t[0]);
201 		close(ph2t[1]);
202 		close(pt2h[0]);
203 		close(pt2h[1]);
204 		argv[0] = "samterm";
205 		exec(samterm, argv);
206 		fprint(2, "can't exec: ");
207 		perror(samterm);
208 		_exits("damn");
209 	case -1:
210 		panic("can't fork samterm");
211 	}
212 	dup(pt2h[0], 0);
213 	dup(ph2t[1], 1);
214 	close(ph2t[0]);
215 	close(ph2t[1]);
216 	close(pt2h[0]);
217 	close(pt2h[1]);
218 }
219 
220 void
connectto(char * machine,char ** argv)221 connectto(char *machine, char **argv)
222 {
223 	int p1[2], p2[2];
224 	char **av;
225 	int ac;
226 
227 	// count args
228 	for(av = argv; *av; av++)
229 		;
230 	av = malloc(sizeof(char*)*((av-argv) + 5));
231 	if(av == nil){
232 		dprint("out of memory\n");
233 		exits("fork/exec");
234 	}
235 	ac = 0;
236 	av[ac++] = RX;
237 	av[ac++] = machine;
238 	av[ac++] = rsamname;
239 	av[ac++] = "-R";
240 	while(*argv)
241 		av[ac++] = *argv++;
242 	av[ac] = 0;
243 	if(pipe(p1)<0 || pipe(p2)<0){
244 		dprint("can't pipe\n");
245 		exits("pipe");
246 	}
247 	remotefd0 = p1[0];
248 	remotefd1 = p2[1];
249 	switch(fork()){
250 	case 0:
251 		dup(p2[0], 0);
252 		dup(p1[1], 1);
253 		close(p1[0]);
254 		close(p1[1]);
255 		close(p2[0]);
256 		close(p2[1]);
257 		exec(RXPATH, av);
258 		dprint("can't exec %s\n", RXPATH);
259 		exits("exec");
260 
261 	case -1:
262 		dprint("can't fork\n");
263 		exits("fork");
264 	}
265 	free(av);
266 	close(p1[1]);
267 	close(p2[0]);
268 }
269 
270 void
startup(char * machine,int Rflag,char ** argv,char ** files)271 startup(char *machine, int Rflag, char **argv, char **files)
272 {
273 	if(machine)
274 		connectto(machine, files);
275 	if(!Rflag)
276 		bootterm(machine, argv);
277 	downloaded = 1;
278 	outTs(Hversion, VERSION);
279 }
280