plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

9p.c (9683B)


      1 #include <u.h>
      2 #include <signal.h>
      3 #include <libc.h>
      4 #include <bio.h>
      5 #include <fcall.h>
      6 #include <9pclient.h>
      7 #include <auth.h>
      8 #include <thread.h>
      9 
     10 char *addr;
     11 
     12 void
     13 usage(void)
     14 {
     15 	fprint(2, "usage: 9p [-n] [-a address] [-A aname] cmd args...\n");
     16 	fprint(2, "possible cmds:\n");
     17 	fprint(2, "	read name\n");
     18 	fprint(2, "	readfd name\n");
     19 	fprint(2, "	write [-l] name\n");
     20 	fprint(2, "	writefd name\n");
     21 	fprint(2, "	stat name\n");
     22 	fprint(2, "	rdwr name\n");
     23 	fprint(2, "	ls [-ldn] name\n");
     24 	fprint(2, "without -a, name elem/path means /path on server unix!$ns/elem\n");
     25 	threadexitsall("usage");
     26 }
     27 
     28 CFsys *(*nsmnt)(char*, char*) = nsamount;
     29 CFsys *(*fsmnt)(int, char*) = fsamount;
     30 
     31 char *aname;
     32 void xread(int, char**);
     33 void xwrite(int, char**);
     34 void xreadfd(int, char**);
     35 void xwritefd(int, char**);
     36 void xstat(int, char**);
     37 void xls(int, char**);
     38 void xrdwr(int, char**);
     39 void xrm(int, char**);
     40 void xcreate(int, char**);
     41 void xcon(int, char**);
     42 
     43 struct {
     44 	char *s;
     45 	void (*f)(int, char**);
     46 } cmds[] = {
     47 	"con", xcon,
     48 	"read", xread,
     49 	"write", xwrite,
     50 	"readfd", xreadfd,
     51 	"writefd", xwritefd,
     52 	"stat", xstat,
     53 	"rdwr", xrdwr,
     54 	"ls", xls,
     55 	"rm", xrm,
     56 	"create", xcreate,
     57 };
     58 
     59 void
     60 threadmain(int argc, char **argv)
     61 {
     62 	char *cmd;
     63 	int i;
     64 
     65 	ARGBEGIN{
     66 	case 'A':
     67 		aname = EARGF(usage());
     68 		break;
     69 	case 'a':
     70 		addr = EARGF(usage());
     71 		if(strchr(addr, '!') == nil)
     72 			addr = netmkaddr(addr, "tcp", "9fs");
     73 		break;
     74 	case 'n':
     75 		nsmnt = nsmount;
     76 		fsmnt = fsmount;
     77 		break;
     78 	case 'D':
     79 		chatty9pclient = 1;
     80 		break;
     81 	default:
     82 		usage();
     83 	}ARGEND
     84 
     85 	signal(SIGINT, SIG_DFL);
     86 
     87 	if(argc < 1)
     88 		usage();
     89 
     90 	cmd = argv[0];
     91 	for(i=0; i<nelem(cmds); i++){
     92 		if(strcmp(cmds[i].s, cmd) == 0){
     93 			cmds[i].f(argc, argv);
     94 			threadexitsall(0);
     95 		}
     96 	}
     97 	usage();
     98 }
     99 
    100 CFsys*
    101 xparse(char *name, char **path)
    102 {
    103 	int fd;
    104 	char *p;
    105 	CFsys *fs;
    106 
    107 	if(addr == nil){
    108 		p = strchr(name, '/');
    109 		if(p == nil)
    110 			p = name+strlen(name);
    111 		else
    112 			*p++ = 0;
    113 		*path = p;
    114 		fs = nsmnt(name, aname);
    115 		if(fs == nil)
    116 			sysfatal("mount: %r");
    117 	}else{
    118 		*path = name;
    119 		if((fd = dial(addr, nil, nil, nil)) < 0)
    120 			sysfatal("dial: %r");
    121 		if((fs = fsmnt(fd, aname)) == nil)
    122 			sysfatal("mount: %r");
    123 	}
    124 	return fs;
    125 }
    126 
    127 CFid*
    128 xopen(char *name, int mode)
    129 {
    130 	CFid *fid;
    131 	CFsys *fs;
    132 
    133 	fs = xparse(name, &name);
    134 	fid = fsopen(fs, name, mode);
    135 	if(fid == nil)
    136 		sysfatal("fsopen %s: %r", name);
    137 	return fid;
    138 }
    139 
    140 int
    141 xopenfd(char *name, int mode)
    142 {
    143 	CFsys *fs;
    144 
    145 	fs = xparse(name, &name);
    146 	return fsopenfd(fs, name, mode);
    147 }
    148 
    149 void
    150 xread(int argc, char **argv)
    151 {
    152 	char buf[4096];
    153 	int n;
    154 	CFid *fid;
    155 
    156 	ARGBEGIN{
    157 	default:
    158 		usage();
    159 	}ARGEND
    160 
    161 	if(argc != 1)
    162 		usage();
    163 
    164 	fid = xopen(argv[0], OREAD);
    165 	while((n = fsread(fid, buf, sizeof buf)) > 0)
    166 		if(write(1, buf, n) < 0)
    167 			sysfatal("write error: %r");
    168 	fsclose(fid);
    169 	if(n < 0)
    170 		sysfatal("read error: %r");
    171 	threadexitsall(0);
    172 }
    173 
    174 void
    175 xreadfd(int argc, char **argv)
    176 {
    177 	char buf[4096];
    178 	int n;
    179 	int fd;
    180 
    181 	ARGBEGIN{
    182 	default:
    183 		usage();
    184 	}ARGEND
    185 
    186 	if(argc != 1)
    187 		usage();
    188 
    189 	fd = xopenfd(argv[0], OREAD);
    190 	while((n = read(fd, buf, sizeof buf)) > 0)
    191 		if(write(1, buf, n) < 0)
    192 			sysfatal("write error: %r");
    193 	if(n < 0)
    194 		sysfatal("read error: %r");
    195 	threadexitsall(0);
    196 }
    197 
    198 void
    199 xwrite(int argc, char **argv)
    200 {
    201 	char buf[4096];
    202 	int n, did;
    203 	CFid *fid;
    204 	Biobuf *b;
    205 	char *p;
    206 	int byline;
    207 
    208 	byline = 0;
    209 	ARGBEGIN{
    210 	case 'l':
    211 		byline = 1;
    212 		break;
    213 	default:
    214 		usage();
    215 	}ARGEND
    216 
    217 	if(argc != 1)
    218 		usage();
    219 
    220 	did = 0;
    221 	fid = xopen(argv[0], OWRITE|OTRUNC);
    222 	if(byline){
    223 		n = 0;
    224 		b = malloc(sizeof *b);
    225 		if(b == nil)
    226 			sysfatal("out of memory");
    227 		Binit(b, 0, OREAD);
    228 		while((p = Brdstr(b, '\n', 0)) != nil){
    229 			n = strlen(p);
    230 			did = 1;
    231 			if(fswrite(fid, p, n) != n)
    232 				fprint(2, "write: %r\n");
    233 		}
    234 		free(b);
    235 	}else{
    236 		while((n = read(0, buf, sizeof buf)) > 0){
    237 			did = 1;
    238 			if(fswrite(fid, buf, n) != n)
    239 				sysfatal("write error: %r");
    240 		}
    241 	}
    242 	if(n == 0 && !did){
    243 		if(fswrite(fid, buf, 0) != 0)
    244 			sysfatal("write error: %r");
    245 	}
    246 	if(n < 0)
    247 		sysfatal("read error: %r");
    248 	fsclose(fid);
    249 	threadexitsall(0);
    250 }
    251 
    252 void
    253 xwritefd(int argc, char **argv)
    254 {
    255 	char buf[4096];
    256 	int n;
    257 	int fd;
    258 
    259 	ARGBEGIN{
    260 	default:
    261 		usage();
    262 	}ARGEND
    263 
    264 	if(argc != 1)
    265 		usage();
    266 
    267 	fd = xopenfd(argv[0], OWRITE|OTRUNC);
    268 	while((n = read(0, buf, sizeof buf)) > 0)
    269 		if(write(fd, buf, n) != n)
    270 			sysfatal("write error: %r");
    271 	if(n < 0)
    272 		sysfatal("read error: %r");
    273 	threadexitsall(0);
    274 }
    275 
    276 void
    277 xstat(int argc, char **argv)
    278 {
    279 	Dir *d;
    280 	CFsys *fs;
    281 	char *name;
    282 
    283 	ARGBEGIN{
    284 	default:
    285 		usage();
    286 	}ARGEND
    287 
    288 	if(argc != 1)
    289 		usage();
    290 
    291 	name = argv[0];
    292 	fs = xparse(name, &name);
    293 	if((d = fsdirstat(fs, name)) == 0)
    294 		sysfatal("dirstat: %r");
    295 	fmtinstall('D', dirfmt);
    296 	fmtinstall('M', dirmodefmt);
    297 	print("%D\n", d);
    298 	threadexitsall(0);
    299 }
    300 
    301 void
    302 xrdwr(int argc, char **argv)
    303 {
    304 	char buf[4096];
    305 	char *p;
    306 	int n;
    307 	CFid *fid;
    308 	Biobuf *b;
    309 
    310 	ARGBEGIN{
    311 	default:
    312 		usage();
    313 	}ARGEND
    314 
    315 	if(argc != 1)
    316 		usage();
    317 
    318 	if((b = Bfdopen(0, OREAD)) == nil)
    319 		sysfatal("out of memory");
    320 	fid = xopen(argv[0], ORDWR);
    321 	for(;;){
    322 		fsseek(fid, 0, 0);
    323 		if((n = fsread(fid, buf, sizeof buf)) < 0)
    324 			fprint(2, "read: %r\n");
    325 		else{
    326 			if(write(1, buf, n) < 0 || write(1, "\n", 1) < 0)
    327 				sysfatal("write error: %r");
    328 		}
    329 		if((p = Brdstr(b, '\n', 1)) == nil)
    330 			break;
    331 		n = strlen(p);
    332 		if(fswrite(fid, p, n) != n)
    333 			fprint(2, "write: %r\n");
    334 		free(p);
    335 	}
    336 	fsclose(fid);
    337 	Bterm(b);
    338 	threadexitsall(0);
    339 }
    340 
    341 void
    342 xcreate(int argc, char **argv)
    343 {
    344 	int i;
    345 	CFsys *fs;
    346 	CFid *fid;
    347 	char *p;
    348 
    349 	ARGBEGIN{
    350 	default:
    351 		usage();
    352 	}ARGEND
    353 
    354 	if(argc == 0)
    355 		usage();
    356 
    357 	for(i=0; i<argc; i++){
    358 		fs = xparse(argv[i], &p);
    359 		if((fid=fscreate(fs, p, OREAD, 0666)) == nil)
    360 			fprint(2, "create %s: %r\n", argv[i]);
    361 		else
    362 			fsclose(fid);
    363 		fsunmount(fs);
    364 	}
    365 }
    366 
    367 void
    368 xrm(int argc, char **argv)
    369 {
    370 	int i;
    371 	CFsys *fs;
    372 	char *p;
    373 
    374 	ARGBEGIN{
    375 	default:
    376 		usage();
    377 	}ARGEND
    378 
    379 	if(argc == 0)
    380 		usage();
    381 
    382 	for(i=0; i<argc; i++){
    383 		fs = xparse(argv[i], &p);
    384 		if(fsremove(fs, p) < 0)
    385 			fprint(2, "remove %s: %r\n", argv[i]);
    386 		fsunmount(fs);
    387 	}
    388 }
    389 
    390 void
    391 rdcon(void *v)
    392 {
    393 	int n;
    394 	char buf[4096];
    395 	CFid *fid;
    396 
    397 	fid = v;
    398 	for(;;){
    399 		n = read(0, buf, sizeof buf);
    400 		if(n <= 0)
    401 			threadexitsall(0);
    402 		if(buf[0] == 'R'-'A'+1)
    403 			threadexitsall(0);
    404 		if(fswrite(fid, buf, n) != n)
    405 			fprint(2, "write: %r\n");
    406 	}
    407 }
    408 
    409 void
    410 xcon(int argc, char **argv)
    411 {
    412 	char buf[4096], *r, *w, *e;
    413 	int n, nocr;
    414 	CFid *fid;
    415 
    416 	nocr = 1;
    417 
    418 	ARGBEGIN{
    419 	case 'r':
    420 		nocr = 0;
    421 		break;
    422 	default:
    423 		usage();
    424 	}ARGEND
    425 
    426 	if(argc != 1)
    427 		usage();
    428 
    429 	fid = xopen(argv[0], ORDWR);
    430 	proccreate(rdcon, fid, 32768);
    431 	for(;;){
    432 		n = fsread(fid, buf, sizeof buf);
    433 		if(n <= 0)
    434 			threadexitsall(0);
    435 		if(nocr){
    436 			for(r=w=buf, e=buf+n; r<e; r++)
    437 				if(*r != '\r')
    438 					*w++ = *r;
    439 			n = w-buf;
    440 		}
    441 		if(write(1, buf, n) != n)
    442 			threadexitsall(0);
    443 	}
    444 	fsclose(fid);
    445 	threadexitsall(0);
    446 }
    447 
    448 static char *mon[] =
    449 {
    450 	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
    451 	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    452 };
    453 
    454 
    455 int
    456 timefmt(Fmt *fmt)
    457 {
    458 	ulong u;
    459 	static ulong time0;
    460 	Tm *tm;
    461 
    462 	if(time0 == 0)
    463 		time0 = time(0);
    464 	u = va_arg(fmt->args, ulong);
    465 	tm = localtime(u);
    466 	if((long)(time0-u) < 6*30*86400)
    467 		return fmtprint(fmt, "%s %2d %02d:%02d",
    468 			mon[tm->mon], tm->mday, tm->hour, tm->min);
    469 	return fmtprint(fmt, "%s %2d %5d",
    470 		mon[tm->mon], tm->mday, tm->year+1900);
    471 }
    472 
    473 static int
    474 dircmp(const void *va, const void *vb)
    475 {
    476 	Dir *a, *b;
    477 
    478 	a = (Dir*)va;
    479 	b = (Dir*)vb;
    480 	return strcmp(a->name, b->name);
    481 }
    482 
    483 static int
    484 timecmp(const void *va, const void *vb)
    485 {
    486 	Dir *a, *b;
    487 
    488 	a = (Dir*)va;
    489 	b = (Dir*)vb;
    490 	if(a->mtime < b->mtime)
    491 		return -1;
    492 	else if(a->mtime > b->mtime)
    493 		return 1;
    494 	else
    495 		return 0;
    496 }
    497 
    498 char *dot[] = { "." };
    499 
    500 void
    501 xls(int argc, char **argv)
    502 {
    503 	char *err, *name, *xname, *f[4], buf[4096];
    504 	int i, j, l, sort;
    505 	int lflag, dflag, tflag, n, len[4];
    506 	Dir *d;
    507 	CFid *fid;
    508 	CFsys *fs;
    509 
    510 	err = nil;
    511 	sort = 1;
    512 	lflag = dflag = tflag = 0;
    513 	ARGBEGIN{
    514 	case 'n':
    515 		sort = 0;
    516 		break;
    517 	case 'l':
    518 		lflag = 1;
    519 		break;
    520 	case 'd':
    521 		dflag = 1;
    522 		break;
    523 	case 't':
    524 		tflag = 1;
    525 		break;
    526 	}ARGEND
    527 
    528 	fmtinstall('D', dirfmt);
    529 	fmtinstall('M', dirmodefmt);
    530 	quotefmtinstall();
    531 	fmtinstall('T', timefmt);
    532 
    533 	if(argc == 0){
    534 		argv = dot;
    535 		argc = 1;
    536 	}
    537 	for(i=0; i<argc; i++){
    538 		name = argv[i];
    539 		fs = xparse(name, &xname);
    540 		if((d = fsdirstat(fs, xname)) == nil){
    541 			fprint(2, "dirstat %s: %r\n", name);
    542 			fsunmount(fs);
    543 			err = "errors";
    544 			continue;
    545 		}
    546 		if((d->mode&DMDIR) && !dflag){
    547 			if((fid = fsopen(fs, xname, OREAD)) == nil){
    548 				fprint(2, "open %s: %r\n", name);
    549 				fsunmount(fs);
    550 				free(d);
    551 				err = "errors";
    552 				continue;
    553 			}
    554 			free(d);
    555 			n = fsdirreadall(fid, &d);
    556 			fsclose(fid);
    557 			if(n < 0){
    558 				fprint(2, "dirreadall %s: %r\n", name);
    559 				fsunmount(fs);
    560 				err = "errors";
    561 				continue;
    562 			}
    563 			if(sort){
    564 				if(tflag)
    565 					qsort(d, n, sizeof d[0], timecmp);
    566 				else
    567 					qsort(d, n, sizeof d[0], dircmp);
    568 			}
    569 			for(j=0; j<4; j++)
    570 				len[j] = 0;
    571 			for(i=0; i<n; i++){
    572 				d[i].type = 'M';
    573 				d[i].dev = 0;
    574 				snprint(buf, sizeof buf, "%d %s %s %lld",
    575 					d[i].dev, d[i].uid, d[i].gid, d[i].length);
    576 				getfields(buf, f, 4, 0, " ");
    577 				for(j=0; j<4; j++){
    578 					l = strlen(f[j]);
    579 					if(l > len[j])
    580 						len[j] = l;
    581 				}
    582 			}
    583 			for(i=0; i<n; i++){
    584 				if(!lflag){
    585 					print("%q\n", d[i].name);
    586 					continue;
    587 				}
    588 				print("%M %C %*d %*s %*s %*lld %T %q\n",
    589 					d[i].mode, d[i].type, len[0], d[i].dev,
    590 					-len[1], d[i].uid, -len[2], d[i].gid,
    591 					len[3], d[i].length, d[i].mtime, d[i].name);
    592 			}
    593 		}else{
    594 			d->type = 'M';
    595 			d->dev = 0;
    596 			if(lflag)
    597 				print("%M %C %d %s %s %lld %T %q\n",
    598 					d->mode, d->type, d->dev,
    599 					d->uid, d->gid, d->length, d->mtime, d->name);
    600 			else
    601 				print("%q\n", d->name);
    602 		}
    603 		free(d);
    604 	}
    605 	threadexitsall(err);
    606 }