Subversion Repositories planix.SVN

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <auth.h>

int verbose;
int trusted;

void
usage(void)
{
        fprint(2, "usage: listen1 [-tv] address cmd args...\n");
        exits("usage");
}

void
becomenone(void)
{
        int fd;

        fd = open("#c/user", OWRITE);
        if(fd < 0 || write(fd, "none", strlen("none")) < 0)
                sysfatal("can't become none: %r");
        close(fd);
        if(newns("none", nil) < 0)
                sysfatal("can't build namespace: %r");
}

char*
remoteaddr(char *dir)
{
        static char buf[128];
        char *p;
        int n, fd;

        snprint(buf, sizeof buf, "%s/remote", dir);
        fd = open(buf, OREAD);
        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)
{
        char data[60], dir[40], ndir[40];
        int ctl, nctl, fd;

        ARGBEGIN{
        default:
                usage();
        case 't':
                trusted = 1;
                break;
        case 'v':
                verbose = 1;
                break;
        }ARGEND

        if(argc < 2)
                usage();

        if(!verbose){
                close(1);
                fd = open("/dev/null", OWRITE);
                if(fd != 1){
                        dup(fd, 1);
                        close(fd);
                }
        }

        if(!trusted)
                becomenone();

        print("listen started\n");
        ctl = announce(argv[0], dir);
        if(ctl < 0)
                sysfatal("announce %s: %r", argv[0]);

        for(;;){
                nctl = listen(dir, ndir);
                if(nctl < 0)
                        sysfatal("listen %s: %r", argv[0]);

                switch(rfork(RFFDG|RFPROC|RFNOWAIT|RFENVG|RFNAMEG|RFNOTEG)){
                case -1:
                        reject(nctl, ndir, "host overloaded");
                        close(nctl);
                        continue;
                case 0:
                        fd = accept(nctl, ndir);
                        if(fd < 0){
                                fprint(2, "accept %s: can't open  %s/data: %r\n",
                                        argv[0], ndir);
                                _exits(0);
                        }
                        print("incoming call for %s from %s in %s\n", argv[0],
                                remoteaddr(ndir), ndir);
                        fprint(nctl, "keepalive");
                        close(ctl);
                        close(nctl);
                        putenv("net", ndir);
                        snprint(data, sizeof data, "%s/data", ndir);
                        bind(data, "/dev/cons", MREPL);
                        dup(fd, 0);
                        dup(fd, 1);
                        dup(fd, 2);
                        close(fd);
                        exec(argv[1], argv+1);
                        if(argv[1][0] != '/')
                                exec(smprint("/bin/%s", argv[1]), argv+1);
                        fprint(2, "%s: exec: %r\n", argv0);
                        exits(nil);
                default:
                        close(nctl);
                        break;
                }
        }
}