9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

io.c (4703B)


      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->qidpath==g->qidpath)
     18 			warn_SS(Wdupfile, &f->name, &g->name);
     19 	}
     20 }
     21 
     22 void
     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->b.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
     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->b, 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
    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->b, 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
    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
    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 		execvp(samterm, argv);
    190 		fprint(2, "can't exec %s: %r\n", samterm);
    191 		_exits("damn");
    192 	}
    193 	if(pipe(ph2t)==-1 || pipe(pt2h)==-1)
    194 		panic("pipe");
    195 	switch(fork()){
    196 	case 0:
    197 		dup(ph2t[0], 0);
    198 		dup(pt2h[1], 1);
    199 		close(ph2t[0]);
    200 		close(ph2t[1]);
    201 		close(pt2h[0]);
    202 		close(pt2h[1]);
    203 		argv[0] = "samterm";
    204 		execvp(samterm, argv);
    205 		fprint(2, "can't exec: ");
    206 		perror(samterm);
    207 		_exits("damn");
    208 	case -1:
    209 		panic("can't fork samterm");
    210 	}
    211 	dup(pt2h[0], 0);
    212 	dup(ph2t[1], 1);
    213 	close(ph2t[0]);
    214 	close(ph2t[1]);
    215 	close(pt2h[0]);
    216 	close(pt2h[1]);
    217 }
    218 
    219 void
    220 connectto(char *machine, char **argv)
    221 {
    222 	int p1[2], p2[2];
    223 	char **av;
    224 	int ac;
    225 
    226 	/* count args */
    227 	for(av = argv; *av; av++)
    228 		;
    229 	av = malloc(sizeof(char*)*((av-argv) + 5));
    230 	if(av == nil){
    231 		dprint("out of memory\n");
    232 		exits("fork/exec");
    233 	}
    234 	ac = 0;
    235 	av[ac++] = RX;
    236 	av[ac++] = machine;
    237 	av[ac++] = rsamname;
    238 	av[ac++] = "-R";
    239 	while(*argv)
    240 		av[ac++] = *argv++;
    241 	av[ac] = 0;
    242 	if(pipe(p1)<0 || pipe(p2)<0){
    243 		dprint("can't pipe\n");
    244 		exits("pipe");
    245 	}
    246 	remotefd0 = p1[0];
    247 	remotefd1 = p2[1];
    248 	switch(fork()){
    249 	case 0:
    250 		dup(p2[0], 0);
    251 		dup(p1[1], 1);
    252 		close(p1[0]);
    253 		close(p1[1]);
    254 		close(p2[0]);
    255 		close(p2[1]);
    256 		execvp(RXPATH, av);
    257 		dprint("can't exec %s\n", RXPATH);
    258 		exits("exec");
    259 
    260 	case -1:
    261 		dprint("can't fork\n");
    262 		exits("fork");
    263 	}
    264 	free(av);
    265 	close(p1[1]);
    266 	close(p2[0]);
    267 }
    268 
    269 void
    270 startup(char *machine, int Rflag, char **argv, char **files)
    271 {
    272 	if(machine)
    273 		connectto(machine, files);
    274 	if(!Rflag)
    275 		bootterm(machine, argv);
    276 	downloaded = 1;
    277 	outTs(Hversion, VERSION);
    278 }