xref: /plan9/sys/src/cmd/sam/io.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "sam.h"
2 
3 #define	NSYSFILE	3
4 #define	NOFILE		128
5 
6 void
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->qid==g->qid)
18 			warn_SS(Wdupfile, &f->name, &g->name);
19 	}
20 }
21 
22 void
23 writef(File *f)
24 {
25 	Rune c;
26 	Posn n;
27 	char *name;
28 	int i, samename, newfile;
29 	ulong dev, 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->qid!=qid || f->date<mtime)){
40 		f->dev = dev;
41 		f->qid = qid;
42 		f->date = 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_s(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 		state(f, addr.r.p1==0 && addr.r.p2==f->nrunes? Clean : Dirty);
57 	if(newfile)
58 		dprint("(new file) ");
59 	if(addr.r.p2>0 && Fchars(f, &c, addr.r.p2-1, addr.r.p2) && c!='\n')
60 		warn(Wnotnewline);
61 	if(f->name.s[0]==0 || samename){
62 		if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){
63 			f->dev = dev;
64 			f->qid = qid;
65 			f->date = mtime;
66 			checkqid(f);
67 		}
68 	}
69 	closeio(n);
70 }
71 
72 Posn
73 readio(File *f, int *nulls, int setdate)
74 {
75 	int n, b, w;
76 	Rune *r;
77 	Posn nt;
78 	Posn p = addr.r.p2;
79 	ulong dev, qid;
80 	long mtime;
81 	char buf[BLOCKSIZE+1], *s;
82 
83 	*nulls = FALSE;
84 	b = 0;
85 	for(nt = 0; (n = read(io, buf+b, BLOCKSIZE-b))>0; nt+=(r-genbuf)){
86 		n += b;
87 		b = 0;
88 		r = genbuf;
89 		s = buf;
90 		while(n > 0){
91 			if((*r = *(uchar*)s) < Runeself){
92 				if(*r)
93 					r++;
94 				else
95 					*nulls = TRUE;
96 				--n;
97 				s++;
98 				continue;
99 			}
100 			if(fullrune(s, n)){
101 				w = chartorune(r, s);
102 				if(*r)
103 					r++;
104 				else
105 					*nulls = TRUE;
106 				n -= w;
107 				s += w;
108 				continue;
109 			}
110 			b = n;
111 			memmove(buf, s, b);
112 			break;
113 		}
114 		Finsert(f, tmprstr(genbuf, r-genbuf), p);
115 	}
116 	if(b)
117 		*nulls = TRUE;
118 	if(*nulls)
119 		warn(Wnulls);
120 	if(setdate){
121 		if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){
122 			f->dev = dev;
123 			f->qid = qid;
124 			f->date = mtime;
125 			checkqid(f);
126 		}
127 	}
128 	return nt;
129 }
130 
131 Posn
132 writeio(File *f)
133 {
134 	int m, n;
135 	Posn p = addr.r.p1;
136 	char *c;
137 
138 	while(p < addr.r.p2){
139 		if(addr.r.p2-p>BLOCKSIZE)
140 			n = BLOCKSIZE;
141 		else
142 			n = addr.r.p2-p;
143 		if(Fchars(f, genbuf, p, p+n)!=n)
144 			panic("writef read");
145 		c = Strtoc(tmprstr(genbuf, n));
146 		m = strlen(c);
147 		if(Write(io, c, m) != m){
148 			free(c);
149 			if(p > 0)
150 				p += n;
151 			break;
152 		}
153 		free(c);
154 		p += n;
155 	}
156 	return p-addr.r.p1;
157 }
158 void
159 closeio(Posn p)
160 {
161 	close(io);
162 	io = 0;
163 	if(p >= 0)
164 		dprint("#%lud\n", p);
165 }
166 
167 int	remotefd0 = 0;
168 int	remotefd1 = 1;
169 
170 void
171 bootterm(char *machine, char **argv, char **end)
172 {
173 	int ph2t[2], pt2h[2];
174 
175 	if(machine){
176 		dup(remotefd0, 0);
177 		dup(remotefd1, 1);
178 		close(remotefd0);
179 		close(remotefd1);
180 		argv[0] = "samterm";
181 		*end = 0;
182 		exec(samterm, argv);
183 		fprint(2, "can't exec: ");
184 		perror(samterm);
185 		_exits("damn");
186 	}
187 	if(pipe(ph2t)==-1 || pipe(pt2h)==-1)
188 		panic("pipe");
189 	switch(fork()){
190 	case 0:
191 		dup(ph2t[0], 0);
192 		dup(pt2h[1], 1);
193 		close(ph2t[0]);
194 		close(ph2t[1]);
195 		close(pt2h[0]);
196 		close(pt2h[1]);
197 		argv[0] = "samterm";
198 		*end = 0;
199 		exec(samterm, argv);
200 		fprint(2, "can't exec: ");
201 		perror(samterm);
202 		_exits("damn");
203 	case -1:
204 		panic("can't fork samterm");
205 	}
206 	dup(pt2h[0], 0);
207 	dup(ph2t[1], 1);
208 	close(ph2t[0]);
209 	close(ph2t[1]);
210 	close(pt2h[0]);
211 	close(pt2h[1]);
212 }
213 
214 void
215 connectto(char *machine)
216 {
217 	int p1[2], p2[2];
218 
219 	if(pipe(p1)<0 || pipe(p2)<0){
220 		dprint("can't pipe\n");
221 		exits("pipe");
222 	}
223 	remotefd0 = p1[0];
224 	remotefd1 = p2[1];
225 	switch(fork()){
226 	case 0:
227 		dup(p2[0], 0);
228 		dup(p1[1], 1);
229 		close(p1[0]);
230 		close(p1[1]);
231 		close(p2[0]);
232 		close(p2[1]);
233 		execl(RXPATH, RX, machine, rsamname, "-R", (char*)0);
234 		dprint("can't exec %s\n", RXPATH);
235 		exits("exec");
236 
237 	case -1:
238 		dprint("can't fork\n");
239 		exits("fork");
240 	}
241 	close(p1[1]);
242 	close(p2[0]);
243 }
244 
245 void
246 startup(char *machine, int Rflag, char **argv, char **end)
247 {
248 	if(machine)
249 		connectto(machine);
250 	if(!Rflag)
251 		bootterm(machine, argv, end);
252 	downloaded = 1;
253 	outTs(Hversion, VERSION);
254 }
255