| /*  | 
 |  * 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 <iplib/iplib.h> | 
 | #include <iplib/icmp.h> | 
 | #include <ctype.h> | 
 | #include <pthread.h> | 
 | #include <parlib/spinlock.h> | 
 | #include <parlib/timing.h> | 
 | #include <parlib/tsc-compat.h> | 
 | #include <parlib/printf-ext.h> | 
 | #include <parlib/alarm.h> | 
 | #include <ndblib/ndb.h> | 
 | #include <fcntl.h> | 
 |  | 
 | #include <sys/types.h> | 
 | #include <sys/wait.h> | 
 |  | 
 | int verbose; | 
 |  | 
 | void | 
 | usage(void) | 
 | { | 
 | 	fprintf(stderr, "usage: listen1 [-tv] address cmd args...\n"); | 
 | 	fprintf(stderr, "usage"); | 
 | 	exit(1); | 
 | } | 
 |  | 
 | char* | 
 | remoteaddr(char *dir) | 
 | { | 
 | 	static char buf[128]; | 
 | 	char *p; | 
 | 	int n, fd; | 
 |  | 
 | 	snprintf(buf, sizeof buf, "%s/remote", dir); | 
 | 	fd = open(buf, O_RDONLY); | 
 | 	if(fd < 0) | 
 | 		return ""; | 
 | 	n = read(fd, buf, sizeof(buf)); | 
 | 	close(fd); | 
 | 	if(n > 0){ | 
 | 		buf[n] = 0; | 
 | 		p = strchr(buf, '!'); | 
 | 		if(p) | 
 | 			*p = 0; | 
 | 		return buf; | 
 | 	} | 
 | 	return ""; | 
 | } | 
 |  | 
 | void | 
 | main(int argc, char **argv) | 
 | { | 
 | 	static char data[1024], dir[1024], ndir[1024]; | 
 | 	int ctl, nctl, fd; | 
 |  | 
 | 	verbose = 1; | 
 |  | 
 | 	if(!verbose){ | 
 | 		close(1); | 
 | 		fd = open("/dev/null", O_WRONLY); | 
 | 		if(fd != 1){ | 
 | 			dup2(fd, 1); | 
 | 			close(fd); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	argc--, argv++; | 
 | 	printf("listen started\n"); | 
 | 	ctl = announce9(argv[0], dir, 0); | 
 | 	if(ctl < 0){ | 
 | 		fprintf(stderr, "announce %s: %r", argv[0]); | 
 | 		exit(1); | 
 | 	} | 
 |  | 
 | 	for(;;){ | 
 | 		nctl = listen9(dir, ndir, 0); | 
 | 		if(nctl < 0){ | 
 | 			fprintf(stderr, "listen %s: %r", argv[0]); | 
 | 			exit(1); | 
 | 		} | 
 |  | 
 | 		//switch(rfork(RFFDG|RFPROC|RFNOWAIT|RFENVG|RFNAMEG|RFNOTEG)){ | 
 | 		switch(fork()){ | 
 | 		case -1: | 
 | 			reject9(nctl, ndir, "host overloaded"); | 
 | 			close(nctl); | 
 | 			continue; | 
 | 		case 0: | 
 | 			fd = accept9(nctl, ndir); | 
 | 			if(fd < 0){ | 
 | 				fprintf(stderr, | 
 | 					"accept %s: can't open  %s/data: %r\n", | 
 | 					argv[0], ndir); | 
 | 				exit(1); | 
 | 			} | 
 | 			printf("incoming call for %s from %s in %s\n", argv[0], | 
 | 				remoteaddr(ndir), ndir); | 
 | 			//fprintf(nctl, "keepalive"); | 
 | 			close(ctl); | 
 | 			close(nctl); | 
 | 			//putenv("net", ndir); | 
 | 			/* this is for children that open /dev/cons. Too bad.  | 
 | 			snprintf(data, sizeof data, "%s/data", ndir); | 
 | 			bind(data, "/dev/cons", MREPL); | 
 | 			*/ | 
 | 			dup2(fd, 0); | 
 | 			dup2(fd, 1); | 
 | 			dup2(fd, 2); | 
 | 			close(fd); | 
 | 			execv(argv[1], argv+1); | 
 | //			if(argv[1][0] != '/') | 
 | //				exec(smprintf("%s", argv[1]), argv+1); | 
 | 			fprintf(stderr, "exec: %r\n"); | 
 | 			exit(1); | 
 | 		default: | 
 | 			/* reap any available children */ | 
 | 			while (waitpid(-1, 0, WNOHANG) > 0) | 
 | 				; | 
 | 			close(nctl); | 
 | 			break; | 
 | 		} | 
 | 	} | 
 | } |