123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- /*
- * 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 <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");
- }
- static int
- catch(void *v, char *s)
- {
- return strstr(s, "alarm") != nil;
- }
- 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]);
- atnotify(catch, 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, oalarm;
- AuthInfo *ai;
- oalarm = alarm(2 * 60 * 1000); /* don't hang forever */
- ai = auth_proxy(fd, auth_getkey, "proto=%s role=client %s", proto, key);
- alarm(oalarm);
- 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;
- }
|