| /*  | 
 |  * This file is part of the UCB release of Plan 9. It is subject to the license | 
 |  * terms in the LICENSE file found in the top-level directory of this | 
 |  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No | 
 |  * part of the UCB release of Plan 9, including this file, may be copied, | 
 |  * modified, propagated, or distributed except according to the terms contained | 
 |  * in the LICENSE file. | 
 |  */ | 
 | #include <stdlib.h> | 
 |  | 
 | #include <stdio.h> | 
 | #include <parlib/parlib.h> | 
 | #include <unistd.h> | 
 | #include <signal.h> | 
 | #include <fcntl.h> | 
 | #include <iplib/iplib.h> | 
 | #include <ndblib/ndb.h> | 
 |  | 
 | /* | 
 |  *  search for a tuple that has the given 'attr=val' and also 'rattr=x'. | 
 |  *  copy 'x' into 'buf' and return the whole tuple. | 
 |  * | 
 |  *  return 0 if not found. | 
 |  */ | 
 | char* | 
 | csgetvalue(char *netroot, char *attr, char *val, char *rattr, | 
 | 	   struct ndbtuple **pp) | 
 | { | 
 | 	struct ndbtuple *t, *first, *last; | 
 | 	int n, linefound; | 
 | 	char line[1024]; | 
 | 	int fd; | 
 | 	int oops = 0; | 
 | 	char *rv; | 
 |  | 
 | 	if(pp) | 
 | 		*pp = NULL; | 
 | 	rv = NULL; | 
 |  | 
 | 	if(netroot) | 
 | 		snprintf(line, sizeof(line), "%s/cs", netroot); | 
 | 	else | 
 | 		strcpy(line, "/net/cs"); | 
 | 	fd = open(line, O_RDWR); | 
 | 	if(fd < 0) | 
 | 		return 0; | 
 | 	lseek(fd, 0, 0); | 
 | 	snprintf(line, sizeof(line), "!%s=%s %s=*", attr, val, rattr); | 
 | 	if(write(fd, line, strlen(line)) < 0){ | 
 | 		close(fd); | 
 | 		return 0; | 
 | 	} | 
 | 	lseek(fd, 0, 0); | 
 |  | 
 | 	first = last = 0; | 
 | 	linefound = 0; | 
 | 	for(;;){ | 
 | 		n = read(fd, line, sizeof(line)-2); | 
 | 		if(n <= 0) | 
 | 			break; | 
 | 		line[n] = '\n'; | 
 | 		line[n+1] = 0; | 
 |  | 
 | 		t = _ndbparseline(line); | 
 | 		if(t == 0) | 
 | 			continue; | 
 | 		if(first) | 
 | 			last->entry = t; | 
 | 		else | 
 | 			first = t; | 
 | 		last = t; | 
 |  | 
 | 		while(last->entry) | 
 | 			last = last->entry; | 
 |  | 
 | 		for(; t; t = t->entry){ | 
 | 			if(linefound == 0){ | 
 | 				if(strcmp(rattr, t->attr) == 0){ | 
 | 					linefound = 1; | 
 | 					rv = strdup(t->val); | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	close(fd); | 
 |  | 
 | 	if(oops){ | 
 | 		werrstr("buffer too short"); | 
 | 		ndbfree(first); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | 	if(pp){ | 
 | 		*pp = first; | 
 | 	} else | 
 | 		ndbfree(first); | 
 |  | 
 | 	return rv; | 
 | } | 
 |  | 
 | struct ndbtuple* | 
 | csgetval(char *netroot, char *attr, char *val, char *rattr, char *buf) | 
 | { | 
 | 	struct ndbtuple *t; | 
 | 	char *p; | 
 |  | 
 | 	p = csgetvalue(netroot, attr, val, rattr, &t); | 
 | 	if(p == NULL){ | 
 | 		if(buf != NULL) | 
 | 			*buf = 0; | 
 | 	} else { | 
 | 		if(buf != NULL){ | 
 | 			strncpy(buf, p, Ndbvlen-1); | 
 | 			buf[Ndbvlen-1] = 0; | 
 | 		} | 
 | 		free(p); | 
 | 	} | 
 | 	ndbsetmalloctag(t, getcallerpc(&netroot)); | 
 | 	return t; | 
 | } |