| /* |
| * 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; |
| } |
| } |
| } |