Subversion Repositories planix.SVN

Rev

Rev 71 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 71 Rev 72
Line 151... Line 151...
151
int	chatty9p = 0;
151
int	chatty9p = 0;
152
int	network = 1;
152
int	network = 1;
153
int	old9p = -1;
153
int	old9p = -1;
154
int	authed;
154
int	authed;
155
User*	none;
155
User*	none;
-
 
156
int	readonly = 0;
-
 
157
int 	homeroot = 0;
156
 
158
 
157
Auth *authmethods[] = {	/* first is default */
159
Auth *authmethods[] = {	/* first is default */
158
	&authrhosts,
160
	&authrhosts,
159
	&authp9any,
161
	&authp9any,
160
	&authnone,
162
	&authnone,
Line 424... Line 426...
424
 
426
 
425
	if((fid = newfid(rx->fid, &e)) == nil){
427
	if((fid = newfid(rx->fid, &e)) == nil){
426
		seterror(tx, e);
428
		seterror(tx, e);
427
		return;
429
		return;
428
	}
430
	}
429
	fid->path = estrdup("/");
-
 
430
	if(fidstat(fid, &e) < 0){
-
 
431
		seterror(tx, e);
-
 
432
		freefid(fid);
-
 
433
		return;
-
 
434
	}
431
	
435
 
-
 
436
	if(defaultuser)
432
	if(defaultuser)
437
		rx->uname = defaultuser;
433
		rx->uname = defaultuser;
438
 
434
 
439
	if((u = uname2user(rx->uname)) == nil
435
	if((u = uname2user(rx->uname)) == nil
440
	|| (!defaultuser && u->id == 0)){
436
	|| (!defaultuser && u->id == 0)){
441
		/* we don't know anyone named root... */
437
		/* we don't know anyone named root... */
442
		seterror(tx, Eunknownuser);
438
		seterror(tx, Eunknownuser);
443
		freefid(fid);
439
		freefid(fid);
444
		return;
440
		return;
445
	}
441
	}
446
 
442
 
-
 
443
	/* 'chroot' here */	
-
 
444
	if( homeroot ){
-
 
445
		fid->path = estrdup(u->home_dir);
-
 
446
	}		
-
 
447
	else {
-
 
448
		fid->path = estrdup("/");	
-
 
449
	}
-
 
450
	
-
 
451
 
-
 
452
	if(fidstat(fid, &e) < 0){
-
 
453
		seterror(tx, e);
-
 
454
		freefid(fid);
-
 
455
		return;
-
 
456
	}
-
 
457
 
447
 
458
 
448
	fid->u = u;
459
	fid->u = u;
449
	tx->qid = stat2qid(&fid->st);
460
	tx->qid = stat2qid(&fid->st);
450
 
461
 
451
	fprint(2,"Change root for user %s to %s\n",u->name,u->home_dir);
-
 
452
	chroot(u->home_dir);
-
 
453
	return;
462
	return;
454
}
463
}
455
 
464
 
456
void
465
void
457
rwalk(Fcall *rx, Fcall *tx)
466
rwalk(Fcall *rx, Fcall *tx)
458
{
467
{
459
 
468
 
460
	int i;
469
	int i;
461
	char *path, *e;
470
	char *path, *e;
462
	Fid *fid, *nfid;
471
	Fid *fid, *nfid;
463
 
472
 
464
	e = nil;
473
	e = nil;
465
	if((fid = oldfid(rx->fid, &e)) == nil){
474
	if((fid = oldfid(rx->fid, &e)) == nil){
466
		seterror(tx, e);
475
		seterror(tx, e);
467
		return;
476
		return;
468
	}
477
	}
469
 
478
 
470
	if(fid->omode != -1){
479
	if(fid->omode != -1){
471
		seterror(tx, Ebadusefid);
480
		seterror(tx, Ebadusefid);
472
		return;
481
		return;
473
	}
482
	}
474
 
483
 
475
	if(fidstat(fid, &e) < 0){
484
	if(fidstat(fid, &e) < 0){
476
		seterror(tx, e);
485
		seterror(tx, e);
477
		return;
486
		return;
478
	}
487
	}
479
 
488
 
480
	if(!S_ISDIR(fid->st.st_mode) && rx->nwname){
489
	if(!S_ISDIR(fid->st.st_mode) && rx->nwname){
481
		seterror(tx, Enotdir);
490
		seterror(tx, Enotdir);
482
		return;
491
		return;
483
	}
492
	}
484
 
493
 
Line 506... Line 515...
506
	}else{
515
	}else{
507
		if(i > 0)		/* partial walk? */
516
		if(i > 0)		/* partial walk? */
508
			tx->nwqid = i;
517
			tx->nwqid = i;
509
		else
518
		else
510
			seterror(tx, e);
519
			seterror(tx, e);
511
 
520
 
512
		if(nfid)		/* clone implicit new fid */
521
		if(nfid)		/* clone implicit new fid */
513
			freefid(nfid);
522
			freefid(nfid);
514
		free(path);
523
		free(path);
515
	}
524
	}
516
	return;
525
	return;
517
}
526
}
518
 
527
 
519
void
528
void
520
ropen(Fcall *rx, Fcall *tx)
529
ropen(Fcall *rx, Fcall *tx)
521
{
530
{
522
	char *e;
531
	char *e;
523
	Fid *fid;
532
	Fid *fid;
524
 
533
 
525
	if((fid = oldfid(rx->fid, &e)) == nil){
534
	if((fid = oldfid(rx->fid, &e)) == nil){
526
		seterror(tx, e);
535
		seterror(tx, e);
527
		return;
536
		return;
528
	}
537
	}
529
 
538
 
530
	if(fid->omode != -1){
539
	if(fid->omode != -1){
531
		seterror(tx, Ebadusefid);
540
		seterror(tx, Ebadusefid);
532
		return;
541
		return;
533
	}
542
	}
534
 
543
 
535
	if(fidstat(fid, &e) < 0){
544
	if(fidstat(fid, &e) < 0){
536
		seterror(tx, e);
545
		seterror(tx, e);
537
		return;
546
		return;
538
	}
547
	}
539
 
548
 
540
	if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){
549
	if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){
541
		seterror(tx, Especial);
550
		seterror(tx, Especial);
542
		return;
551
		return;
543
	}
552
	}
544
 
553
 
545
	if(useropen(fid, rx->mode, &e) < 0){
554
	if(useropen(fid, rx->mode, &e) < 0){
546
		seterror(tx, e);
555
		seterror(tx, e);
547
		return;
556
		return;
548
	}
557
	}
549
 
558
 
550
	tx->iounit = 0;
559
	tx->iounit = 0;
551
	tx->qid = stat2qid(&fid->st);
560
	tx->qid = stat2qid(&fid->st);
552
}
561
}
553
 
562
 
554
void
563
void
555
rcreate(Fcall *rx, Fcall *tx)
564
rcreate(Fcall *rx, Fcall *tx)
556
{
565
{
557
	char *e;
566
	char *e;
558
	Fid *fid;
567
	Fid *fid;
-
 
568
 
-
 
569
	if(readonly){
-
 
570
		seterror(tx, Eperm);
-
 
571
		return;
-
 
572
	}
559
 
573
 
560
	if((fid = oldfid(rx->fid, &e)) == nil){
574
	if((fid = oldfid(rx->fid, &e)) == nil){
561
		fprint(2,"oldfid error\n");
-
 
562
		seterror(tx, e);
575
		seterror(tx, e);
563
		return;
576
		return;
564
	}
577
	}
565
 
578
 
566
	if(fid->omode != -1){
579
	if(fid->omode != -1){
567
		fprint(2,"oldmode error\n");
-
 
568
		seterror(tx, Ebadusefid);
580
		seterror(tx, Ebadusefid);
569
		return;
581
		return;
570
	}
582
	}
571
 
583
 
572
	if(fidstat(fid, &e) < 0){
584
	if(fidstat(fid, &e) < 0){
573
		fprint(2,"fidstat error\n");
-
 
574
		seterror(tx, e);
585
		seterror(tx, e);
575
		return;
586
		return;
576
	}
587
	}
577
 
588
 
578
	if(!S_ISDIR(fid->st.st_mode)){
589
	if(!S_ISDIR(fid->st.st_mode)){
579
		fprint(2,"isdir error\n");
-
 
580
		seterror(tx, Enotdir);
590
		seterror(tx, Enotdir);
581
		return;
591
		return;
582
	}
592
	}
583
 
593
 
584
	if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){
594
	if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){
585
		fprint(2,"usercreate error\n");
-
 
586
		seterror(tx, e);
595
		seterror(tx, e);
587
		return;
596
		return;
588
	}
597
	}
589
 
598
 
590
	if(fidstat(fid, &e) < 0){
599
	if(fidstat(fid, &e) < 0){
591
		fprint(2,"fidstat again error\n");
-
 
592
		seterror(tx, e);
600
		seterror(tx, e);
593
		return;
601
		return;
594
	}
602
	}
595
 
603
 
596
	tx->iounit = 0;
604
	tx->iounit = 0;
Line 816... Line 824...
816
rwrite(Fcall *rx, Fcall *tx)
824
rwrite(Fcall *rx, Fcall *tx)
817
{
825
{
818
	char *e;
826
	char *e;
819
	Fid *fid;
827
	Fid *fid;
820
	int n;
828
	int n;
-
 
829
 
-
 
830
	if(readonly){
-
 
831
		seterror(tx, Eperm);
-
 
832
		return;
-
 
833
	}
821
 
834
 
822
	if(rx->count > msize-IOHDRSZ){
835
	if(rx->count > msize-IOHDRSZ){
823
		seterror(tx, Etoolarge);
836
		seterror(tx, Etoolarge);
824
		return;
837
		return;
825
	}
838
	}
Line 842... Line 855...
842
		return;
855
		return;
843
	}
856
	}
844
 
857
 
845
	if((n = pwrite(fid->fd, rx->data, rx->count, rx->offset)) < 0){
858
	if((n = pwrite(fid->fd, rx->data, rx->count, rx->offset)) < 0){
846
		seterror(tx, strerror(errno));
859
		seterror(tx, strerror(errno));
847
		return;
860
		return;
848
	}
861
	}
849
	tx->count = n;
862
	tx->count = n;
850
}
863
}
851
 
864
 
852
void
865
void
853
rclunk(Fcall *rx, Fcall *tx)
866
rclunk(Fcall *rx, Fcall *tx)
854
{
867
{
855
	char *e;
868
	char *e;
856
	Fid *fid;
869
	Fid *fid;
857
 
870
 
858
	if((fid = oldfidex(rx->fid, -1, &e)) == nil){
871
	if((fid = oldfidex(rx->fid, -1, &e)) == nil){
859
		seterror(tx, e);
872
		seterror(tx, e);
860
		return;
873
		return;
861
	}
874
	}
862
	if (fid->auth) {
875
	if (fid->auth) {
863
		if (auth->clunk) {
876
		if (auth->clunk) {
864
			e = (*auth->clunk)(rx, tx);
877
			e = (*auth->clunk)(rx, tx);
865
			if (e) {
878
			if (e) {
Line 868... Line 881...
868
			}
881
			}
869
		}
882
		}
870
	}
883
	}
871
	else if(fid->omode != -1 && fid->omode&ORCLOSE)
884
	else if(fid->omode != -1 && fid->omode&ORCLOSE)
872
		remove(fid->path);
885
		remove(fid->path);
873
	freefid(fid);
886
	freefid(fid);
874
}
887
}
875
 
888
 
876
void
889
void
877
rremove(Fcall *rx, Fcall *tx)
890
rremove(Fcall *rx, Fcall *tx)
878
{
891
{
879
	char *e;
892
	char *e;
880
	Fid *fid;
893
	Fid *fid;
881
 
894
 
882
	if((fid = oldfid(rx->fid, &e)) == nil){
895
	if((fid = oldfid(rx->fid, &e)) == nil){
883
		seterror(tx, e);
896
		seterror(tx, e);
884
		return;
897
		return;
885
	}
898
	}
886
	if(userremove(fid, &e) < 0)
899
	if(userremove(fid, &e) < 0)
887
		seterror(tx, e);
900
		seterror(tx, e);
888
	freefid(fid);
901
	freefid(fid);
889
}
902
}
890
 
903
 
891
void
904
void
892
rstat(Fcall *rx, Fcall *tx)
905
rstat(Fcall *rx, Fcall *tx)
893
{
906
{
894
	char *e;
907
	char *e;
895
	Fid *fid;
908
	Fid *fid;
896
	Dir d;
909
	Dir d;
897
 
910
 
898
	if((fid = oldfid(rx->fid, &e)) == nil){
911
	if((fid = oldfid(rx->fid, &e)) == nil){
899
		seterror(tx, e);
912
		seterror(tx, e);
900
		return;
913
		return;
901
	}
914
	}
902
 
915
 
903
	if(fidstat(fid, &e) < 0){
916
	if(fidstat(fid, &e) < 0){
904
		seterror(tx, e);
917
		seterror(tx, e);
905
		return;
918
		return;
906
	}
919
	}
907
 
920
 
908
	stat2dir(fid->path, &fid->st, &d);
921
	stat2dir(fid->path, &fid->st, &d);
909
	if((tx->nstat=(old9p ? convD2Mold : convD2M)(&d, tx->stat, msize)) <= BIT16SZ)
922
	if((tx->nstat=(old9p ? convD2Mold : convD2M)(&d, tx->stat, msize)) <= BIT16SZ)
910
		seterror(tx, "convD2M fails");
923
		seterror(tx, "convD2M fails");
911
}
924
}
912
 
925
 
913
void
926
void
914
rwstat(Fcall *rx, Fcall *tx)
927
rwstat(Fcall *rx, Fcall *tx)
915
{
928
{
916
	char *e;
929
	char *e;
917
	char *p, *old, *new, *dir;
930
	char *p, *old, *new, *dir;
918
	gid_t gid;
931
	gid_t gid;
919
	Dir d;
932
	Dir d;
920
	Fid *fid;
933
	Fid *fid;
921
 
934
 
922
	if((fid = oldfid(rx->fid, &e)) == nil){
935
	if((fid = oldfid(rx->fid, &e)) == nil){
923
		seterror(tx, e);
936
		seterror(tx, e);
924
		return;
937
		return;
925
	}
938
	}
-
 
939
 
926
 
940
 
927
	/*
941
	/*
928
	 * wstat is supposed to be atomic.
942
	 * wstat is supposed to be atomic.
929
	 * we check all the things we can before trying anything.
943
	 * we check all the things we can before trying anything.
930
	 * still, if we are told to truncate a file and rename it and only
944
	 * still, if we are told to truncate a file and rename it and only
Line 968... Line 982...
968
 
982
 
969
	if((u32int)d.mode != (u32int)~0 && (((d.mode&DMDIR)!=0) ^ (S_ISDIR(fid->st.st_mode)!=0))){
983
	if((u32int)d.mode != (u32int)~0 && (((d.mode&DMDIR)!=0) ^ (S_ISDIR(fid->st.st_mode)!=0))){
970
		seterror(tx, Edirchange);
984
		seterror(tx, Edirchange);
971
		return;
985
		return;
972
	}
986
	}
-
 
987
 
973
 
988
 
974
	if(strcmp(fid->path, "/") == 0){
989
	if(strcmp(fid->path, "/") == 0){
975
		seterror(tx, "no wstat of root");
990
		seterror(tx, "no wstat of root");
976
		return;
991
		return;
977
	}
992
	}
Line 984... Line 999...
984
	 * (see above comment about atomicity).
999
	 * (see above comment about atomicity).
985
	 */
1000
	 */
986
	if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){
1001
	if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){
987
		if(chatty9p)
1002
		if(chatty9p)
988
			fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d));
1003
			fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d));
989
		seterror(tx, strerror(errno));
1004
		seterror(tx, strerror(errno));
990
		return;
1005
		return;
991
	}
1006
	}
992
 
1007
 
993
	if((u32int)d.mtime != (u32int)~0){
1008
	if((u32int)d.mtime != (u32int)~0){
994
		struct utimbuf t;
1009
		struct utimbuf t;
995
 
1010
 
996
		t.actime = 0;
1011
		t.actime = 0;
997
		t.modtime = d.mtime;
1012
		t.modtime = d.mtime;
998
		if(utime(fid->path, &t) < 0){
1013
		if(utime(fid->path, &t) < 0){
999
			if(chatty9p)
1014
			if(chatty9p)
1000
				fprint(2, "utime(%s) failed\n", fid->path);
1015
				fprint(2, "utime(%s) failed\n", fid->path);
Line 1003... Line 1018...
1003
		}
1018
		}
1004
	}
1019
	}
1005
 
1020
 
1006
	if(gid != (gid_t)-1 && gid != fid->st.st_gid){
1021
	if(gid != (gid_t)-1 && gid != fid->st.st_gid){
1007
		if(chown(fid->path, (uid_t)-1, gid) < 0){
1022
		if(chown(fid->path, (uid_t)-1, gid) < 0){
1008
			if(chatty9p)
1023
			if(chatty9p)
1009
				fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid);
1024
				fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid);
1010
			seterror(tx, strerror(errno));
1025
			seterror(tx, strerror(errno));
1011
			return;
1026
			return;
1012
		}
1027
		}
1013
	}
1028
	}
Line 1037... Line 1052...
1037
 
1052
 
1038
	if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){
1053
	if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){
1039
		fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length);
1054
		fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length);
1040
		seterror(tx, strerror(errno));
1055
		seterror(tx, strerror(errno));
1041
		return;
1056
		return;
1042
	}
1057
	}
1043
}
1058
}
1044
 
1059
 
1045
/*
1060
/*
1046
 * we keep a table by numeric id.  by name lookups happen infrequently
1061
 * we keep a table by numeric id.  by name lookups happen infrequently
1047
 * while by-number lookups happen once for every directory entry read
1062
 * while by-number lookups happen once for every directory entry read
1048
 * and every stat request.
1063
 * and every stat request.
Line 1058... Line 1073...
1058
	u = emalloc(sizeof(*u));
1073
	u = emalloc(sizeof(*u));
1059
	u->id = p->pw_uid;
1074
	u->id = p->pw_uid;
1060
	u->name = estrdup(p->pw_name);
1075
	u->name = estrdup(p->pw_name);
1061
	u->next = utab[p->pw_uid%nelem(utab)];
1076
	u->next = utab[p->pw_uid%nelem(utab)];
1062
	u->defaultgid = p->pw_gid;
1077
	u->defaultgid = p->pw_gid;
-
 
1078
 
1063
	if (p->pw_dir != nil ){
1079
	if (p->pw_dir != nil ){
1064
		int n;
1080
		int n;
1065
		strncpy(u->home_dir,p->pw_dir,PATH_MAX);
1081
		strncpy(u->home_dir,p->pw_dir,PATH_MAX);
1066
		u->home_dir[PATH_MAX-1]=0;
1082
		u->home_dir[PATH_MAX-1]=0;
1067
	}
1083
	}
Line 1109... Line 1125...
1109
	u->id = g->gr_gid;
1125
	u->id = g->gr_gid;
1110
	u->name = estrdup(g->gr_name);
1126
	u->name = estrdup(g->gr_name);
1111
	u->next = gtab[g->gr_gid%nelem(gtab)];
1127
	u->next = gtab[g->gr_gid%nelem(gtab)];
1112
	gtab[g->gr_gid%nelem(gtab)] = u;
1128
	gtab[g->gr_gid%nelem(gtab)] = u;
1113
	return u;
1129
	return u;
1114
}
1130
}
1115
 
1131
 
1116
User*
1132
User*
1117
uname2user(char *name)
1133
uname2user(char *name)
1118
{
1134
{
1119
	int i;
1135
	int i;
1120
	User *u;
1136
	User *u;
1121
	struct passwd *p;
1137
	struct passwd *p;
Line 1604... Line 1620...
1604
usercreate(Fid *fid, char *elem, int omode, long perm, char **ep)
1620
usercreate(Fid *fid, char *elem, int omode, long perm, char **ep)
1605
{
1621
{
1606
	int o, m;
1622
	int o, m;
1607
	char *opath, *npath;
1623
	char *opath, *npath;
1608
	struct stat st, parent;
1624
	struct stat st, parent;
1609
	fprint(2,"Called user create\n");
-
 
1610
 
1625
 
1611
	if(stat(fid->path, &parent) < 0){
1626
	if(stat(fid->path, &parent) < 0){
1612
		*ep = strerror(errno);
1627
		*ep = strerror(errno);
1613
		return -1;
1628
		return -1;
1614
	}
1629
	}
Line 1712... Line 1727...
1712
}
1727
}
1713
 
1728
 
1714
void
1729
void
1715
usage(void)
1730
usage(void)
1716
{
1731
{
1717
	fprint(2, "usage: u9fs [-Dnz] [-a authmethod] [-m msize] [-u user] [root]\n");
1732
	fprint(2, "usage: u9fs [-Dnhrz] [-a authmethod] [-m msize] [-u user] [root]\n");
1718
	exit(1);
1733
	exit(1);
1719
}
1734
}
1720
 
1735
 
1721
int
1736
int
1722
main(int argc, char **argv)
1737
main(int argc, char **argv)
Line 1754... Line 1769...
1754
		network = 0;
1769
		network = 0;
1755
		break;
1770
		break;
1756
	case 'u':
1771
	case 'u':
1757
		defaultuser = EARGF(usage());
1772
		defaultuser = EARGF(usage());
1758
		break;
1773
		break;
-
 
1774
	case 'r':
-
 
1775
		readonly = 1;
-
 
1776
		break;
-
 
1777
	case 'h':
-
 
1778
		homeroot = 1;
-
 
1779
		break;		
-
 
1780
 
1759
	case 'z':
1781
	case 'z':
1760
		logflag |= O_TRUNC;
1782
		logflag |= O_TRUNC;
1761
	}ARGEND
1783
	}ARGEND
1762
 
1784
 
1763
	if(argc > 1)
1785
	if(argc > 1)
Line 1768... Line 1790...
1768
		sysfatal("cannot open log '%s'", logfile);
1790
		sysfatal("cannot open log '%s'", logfile);
1769
 
1791
 
1770
	if(dup2(fd, 2) < 0)
1792
	if(dup2(fd, 2) < 0)
1771
		sysfatal("cannot dup fd onto stderr");
1793
		sysfatal("cannot dup fd onto stderr");
1772
	fprint(2, "u9fs\nkill %d\n", (int)getpid());
1794
	fprint(2, "u9fs\nkill %d\n", (int)getpid());
1773
 
1795
 
1774
	fmtinstall('F', fcallconv);
1796
	fmtinstall('F', fcallconv);
1775
	fmtinstall('D', dirconv);
1797
	fmtinstall('D', dirconv);
1776
	fmtinstall('M', dirmodeconv);
1798
	fmtinstall('M', dirmodeconv);
1777
 
1799
 
1778
	rxbuf = emalloc(msize);
1800
	rxbuf = emalloc(msize);
1779
	txbuf = emalloc(msize);
1801
	txbuf = emalloc(msize);
1780
	databuf = emalloc(msize);
1802
	databuf = emalloc(msize);
1781
 
1803
 
1782
	if(auth->init)
1804
	if(auth->init)
1783
		auth->init();
1805
		auth->init();
1784
 
1806
 
1785
	if(network)
1807
	if(network)
1786
		getremotehostname(remotehostname, sizeof remotehostname);
1808
		getremotehostname(remotehostname, sizeof remotehostname);
1787
 
1809
 
1788
	if(gethostname(hostname, sizeof hostname) < 0)
1810
	if(gethostname(hostname, sizeof hostname) < 0)
1789
		strcpy(hostname, "gnot");
1811
		strcpy(hostname, "gnot");
1790
 
1812
 
1791
	umask(0);
1813
	umask(0);
1792
 
1814
 
1793
	if(argc == 1)
1815
	if(argc == 1)
1794
		if(chroot(argv[0]) < 0)
1816
		if(chroot(argv[0]) < 0)
1795
			sysfatal("chroot '%s' failed", argv[0]);
1817
			sysfatal("chroot '%s' failed", argv[0]);
1796
 
1818
	
1797
	none = uname2user("none");
1819
	none = uname2user("none");
1798
	if(none == nil)
1820
	if(none == nil)
1799
		none = uname2user("nobody");
1821
		none = uname2user("nobody");
1800
 
1822
 
1801
	serve(0, 1);
1823
	serve(0, 1);