diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/rx.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/rx.c')
-rwxr-xr-x | sys/src/cmd/rx.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/sys/src/cmd/rx.c b/sys/src/cmd/rx.c new file mode 100755 index 000000000..0bf9dd5b8 --- /dev/null +++ b/sys/src/cmd/rx.c @@ -0,0 +1,257 @@ +#include <u.h> +#include <libc.h> +#include <auth.h> + +int eof; /* send an eof if true */ +int crtonl; /* convert all received \r to \n */ +int returns; /* strip \r on reception */ +char *note = "die: yankee dog"; +char *ruser; /* for BSD authentication */ +char *key; + +void rex(int, char*, char*); +void tcpexec(int, char*, char*); +int call(char *, char*, char*, char**); +char *buildargs(char*[]); +int send(int); +void error(char*, char*); +void sshexec(char*, char*); + +void +usage(void) +{ + fprint(2, "usage: %s [-e] [-T] [-r] [-k keypattern] [-l user] net!host command...\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + char *host, *addr, *args; + int fd; + + key = ""; + eof = 1; + crtonl = 0; + returns = 1; + ARGBEGIN{ + case 'T': + crtonl = 1; + break; + case 'r': + returns = 0; + break; + case 'e': + eof = 0; + break; + case 'k': + key = EARGF(usage()); + break; + case 'l': + ruser = EARGF(usage()); + break; + default: + usage(); + }ARGEND + + if(argc < 2) + usage(); + host = argv[0]; + args = buildargs(&argv[1]); + + /* try rexexec p9any then dial again with p9sk2 */ + fd = call(0, host, "rexexec", &addr); + if(fd >= 0) + rex(fd, args, "p9any"); + close(fd); + fd = call(0, host, "rexexec", &addr); + if(fd >= 0) + rex(fd, args, "p9sk2"); + close(fd); + + /* if there's an ssh port, try that */ + fd = call("tcp", host, "ssh", &addr); + if(fd >= 0){ + close(fd); + sshexec(host, args); + /* falls through if no ssh */ + } + + /* specific attempts */ + fd = call("tcp", host, "shell", &addr); + if(fd >= 0) + tcpexec(fd, addr, args); + + error("can't dial", host); + exits(0); +} + +int +call(char *net, char *host, char *service, char **na) +{ + *na = netmkaddr(host, net, service); + return dial(*na, 0, 0, 0); +} + +void +rex(int fd, char *cmd, char *proto) +{ + char buf[4096]; + int kid, n; + AuthInfo *ai; + + ai = auth_proxy(fd, auth_getkey, "proto=%s role=client %s", proto, key); + if(ai == nil){ + if(strcmp(proto, "p9any") == 0) + return; + error("auth_proxy", nil); + } + write(fd, cmd, strlen(cmd)+1); + + kid = send(fd); + while((n=read(fd, buf, sizeof buf))>0) + if(write(1, buf, n)!=n) + error("write error", 0); + sleep(250); + postnote(PNPROC, kid, note);/**/ + exits(0); +} + +void +tcpexec(int fd, char *addr, char *cmd) +{ + char *cp, *ep, *u, *ru, buf[4096]; + int kid, n; + + /* + * do the ucb authentication and send command + */ + u = getuser(); + ru = ruser; + if(ru == nil) + ru = u; + if(write(fd, "", 1)<0 || write(fd, u, strlen(u)+1)<0 + || write(fd, ru, strlen(ru)+1)<0 || write(fd, cmd, strlen(cmd)+1)<0){ + close(fd); + error("can't authenticate to", addr); + } + + /* + * get authentication reply + */ + if(read(fd, buf, 1) != 1){ + close(fd); + error("can't authenticate to", addr); + } + if(buf[0] != 0){ + while(read(fd, buf, 1) == 1){ + write(2, buf, 1); + if(buf[0] == '\n') + break; + } + close(fd); + error("rejected by", addr); + } + + kid = send(fd); + while((n=read(fd, buf, sizeof buf))>0){ + if(crtonl) { + /* convert cr's to nl's */ + for (cp = buf; cp < buf + n; cp++) + if (*cp == '\r') + *cp = '\n'; + } + else if(!returns){ + /* convert cr's to null's */ + cp = buf; + ep = buf + n; + while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){ + memmove(cp, cp+1, ep-cp-1); + ep--; + n--; + } + } + if(write(1, buf, n)!=n) + error("write error", 0); + } + sleep(250); + postnote(PNPROC, kid, note);/**/ + exits(0); +} + +void +sshexec(char *host, char *cmd) +{ + char *argv[10]; + int n; + + n = 0; + argv[n++] = "ssh"; + argv[n++] = "-iCm"; + if(!returns) + argv[n++] = "-r"; + if(ruser){ + argv[n++] = "-l"; + argv[n++] = ruser; + } + argv[n++] = host; + argv[n++] = cmd; + argv[n] = 0; + exec("/bin/ssh", argv); +} + +int +send(int fd) +{ + char buf[4096]; + int n; + int kid; + switch(kid = fork()){ + case -1: + error("fork error", 0); + case 0: + break; + default: + return kid; + } + while((n=read(0, buf, sizeof buf))>0) + if(write(fd, buf, n)!=n) + exits("write error"); + if(eof) + write(fd, buf, 0); + + exits(0); + return 0; /* to keep compiler happy */ +} + +void +error(char *s, char *z) +{ + if(z == 0) + fprint(2, "%s: %s: %r\n", argv0, s); + else + fprint(2, "%s: %s %s: %r\n", argv0, s, z); + exits(s); +} + +char * +buildargs(char *argv[]) +{ + char *args; + int m, n; + + args = malloc(1); + args[0] = '\0'; + n = 0; + while(*argv){ + m = strlen(*argv) + 1; + args = realloc(args, n+m +1); + if(args == 0) + error("malloc fail", 0); + args[n] = ' '; /* smashes old null */ + strcpy(args+n+1, *argv); + n += m; + argv++; + } + return args; +} |