plan9port

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

9srv.c (4076B)


      1 #include "stdinc.h"
      2 
      3 #include "9.h"
      4 
      5 typedef struct Srv Srv;
      6 struct Srv {
      7 	int	fd;
      8 	int	srvfd;
      9 	char*	service;
     10 	char*	mntpnt;
     11 
     12 	Srv*	next;
     13 	Srv*	prev;
     14 };
     15 
     16 static struct {
     17 	RWLock	lock;
     18 
     19 	Srv*	head;
     20 	Srv*	tail;
     21 } sbox;
     22 
     23 #ifndef PLAN9PORT
     24 static int
     25 srvFd(char* name, int mode, int fd, char** mntpnt)
     26 {
     27 	int n, srvfd;
     28 	char *p, buf[10];
     29 
     30 	/*
     31 	 * Drop a file descriptor with given name and mode into /srv.
     32 	 * Create with ORCLOSE and don't close srvfd so it will be removed
     33 	 * automatically on process exit.
     34 	 */
     35 	p = smprint("/srv/%s", name);
     36 	if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){
     37 		vtfree(p);
     38 		p = smprint("#s/%s", name);
     39 		if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){
     40 			werrstr("create %s: %r", p);
     41 			vtfree(p);
     42 			return -1;
     43 		}
     44 	}
     45 
     46 	n = snprint(buf, sizeof(buf), "%d", fd);
     47 	if(write(srvfd, buf, n) < 0){
     48 		close(srvfd);
     49 		werrstr("write %s: %r", p);
     50 		vtfree(p);
     51 		return -1;
     52 	}
     53 
     54 	*mntpnt = p;
     55 
     56 	return srvfd;
     57 }
     58 #endif
     59 
     60 static void
     61 srvFree(Srv* srv)
     62 {
     63 	if(srv->prev != nil)
     64 		srv->prev->next = srv->next;
     65 	else
     66 		sbox.head = srv->next;
     67 	if(srv->next != nil)
     68 		srv->next->prev = srv->prev;
     69 	else
     70 		sbox.tail = srv->prev;
     71 
     72 	if(srv->srvfd != -1)
     73 		close(srv->srvfd);
     74 	vtfree(srv->service);
     75 	vtfree(srv->mntpnt);
     76 	vtfree(srv);
     77 }
     78 
     79 static Srv*
     80 srvAlloc(char* service, int mode, int fd)
     81 {
     82 	Dir *dir;
     83 	Srv *srv;
     84 	int srvfd;
     85 	char *mntpnt;
     86 
     87 	wlock(&sbox.lock);
     88 	for(srv = sbox.head; srv != nil; srv = srv->next){
     89 		if(strcmp(srv->service, service) != 0)
     90 			continue;
     91 		/*
     92 		 * If the service exists, but is stale,
     93 		 * free it up and let the name be reused.
     94 		 */
     95 		if((dir = dirfstat(srv->srvfd)) != nil){
     96 			free(dir);
     97 			werrstr("srv: already serving '%s'", service);
     98 			wunlock(&sbox.lock);
     99 			return nil;
    100 		}
    101 		srvFree(srv);
    102 		break;
    103 	}
    104 
    105 #ifdef PLAN9PORT
    106 	mntpnt = nil;
    107 	if((srvfd = post9pservice(fd, service, mntpnt)) < 0){
    108 #else
    109 	if((srvfd = srvFd(service, mode, fd, &mntpnt)) < 0){
    110 #endif
    111 		wunlock(&sbox.lock);
    112 		return nil;
    113 	}
    114 	close(fd);
    115 
    116 	srv = vtmallocz(sizeof(Srv));
    117 	srv->srvfd = srvfd;
    118 	srv->service = vtstrdup(service);
    119 	srv->mntpnt = mntpnt;
    120 
    121 	if(sbox.tail != nil){
    122 		srv->prev = sbox.tail;
    123 		sbox.tail->next = srv;
    124 	}
    125 	else{
    126 		sbox.head = srv;
    127 		srv->prev = nil;
    128 	}
    129 	sbox.tail = srv;
    130 	wunlock(&sbox.lock);
    131 
    132 	return srv;
    133 }
    134 
    135 static int
    136 cmdSrv(int argc, char* argv[])
    137 {
    138 	Con *con;
    139 	Srv *srv;
    140 	char *usage = "usage: srv [-APWdp] [service]";
    141 	int conflags, dflag, fd[2], mode, pflag, r;
    142 
    143 	dflag = 0;
    144 	pflag = 0;
    145 	conflags = 0;
    146 	mode = 0666;
    147 
    148 	ARGBEGIN{
    149 	default:
    150 		return cliError(usage);
    151 	case 'A':
    152 		conflags |= ConNoAuthCheck;
    153 		break;
    154 	case 'I':
    155 		conflags |= ConIPCheck;
    156 		break;
    157 	case 'N':
    158 		conflags |= ConNoneAllow;
    159 		break;
    160 	case 'P':
    161 		conflags |= ConNoPermCheck;
    162 		mode = 0600;
    163 		break;
    164 	case 'W':
    165 		conflags |= ConWstatAllow;
    166 		mode = 0600;
    167 		break;
    168 	case 'd':
    169 		dflag = 1;
    170 		break;
    171 	case 'p':
    172 		pflag = 1;
    173 		mode = 0600;
    174 		break;
    175 	}ARGEND
    176 
    177 	if(pflag && (conflags&ConNoPermCheck)){
    178 		werrstr("srv: cannot use -P with -p");
    179 		return 0;
    180 	}
    181 
    182 	switch(argc){
    183 	default:
    184 		return cliError(usage);
    185 	case 0:
    186 		rlock(&sbox.lock);
    187 		for(srv = sbox.head; srv != nil; srv = srv->next)
    188 			consPrint("\t%s\t%d\n", srv->service, srv->srvfd);
    189 		runlock(&sbox.lock);
    190 
    191 		return 1;
    192 	case 1:
    193 		if(!dflag)
    194 			break;
    195 
    196 		wlock(&sbox.lock);
    197 		for(srv = sbox.head; srv != nil; srv = srv->next){
    198 			if(strcmp(srv->service, argv[0]) != 0)
    199 				continue;
    200 			srvFree(srv);
    201 			break;
    202 		}
    203 		wunlock(&sbox.lock);
    204 
    205 		if(srv == nil){
    206 			werrstr("srv: '%s' not found", argv[0]);
    207 			return 0;
    208 		}
    209 
    210 		return 1;
    211 	}
    212 
    213 #ifdef PLAN9PORT	/* fossilcons unsupported */
    214 	if(pflag)
    215 		return 1;
    216 #endif
    217 
    218 	if(pipe(fd) < 0){
    219 		werrstr("srv pipe: %r");
    220 		return 0;
    221 	}
    222 	if((srv = srvAlloc(argv[0], mode, fd[0])) == nil){
    223 		close(fd[0]); close(fd[1]);
    224 		return 0;
    225 	}
    226 
    227 	if(pflag)
    228 		r = consOpen(fd[1], srv->srvfd, -1);
    229 	else{
    230 		con = conAlloc(fd[1], srv->mntpnt, conflags);
    231 		if(con == nil)
    232 			r = 0;
    233 		else
    234 			r = 1;
    235 	}
    236 	if(r == 0){
    237 		close(fd[1]);
    238 		wlock(&sbox.lock);
    239 		srvFree(srv);
    240 		wunlock(&sbox.lock);
    241 	}
    242 
    243 	return r;
    244 }
    245 
    246 int
    247 srvInit(void)
    248 {
    249 	cliAddCmd("srv", cmdSrv);
    250 
    251 	return 1;
    252 }