void tolocal(int argc, char **argv) { int i, len; char *bp, *host, *src, *suser; arglist alist; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; for (i = 0; i < argc - 1; i++) { if (!(src = colon(argv[i]))) { /* Local to local. */ freeargs(&alist); addargs(&alist, "%s", _PATH_CP); if (iamrecursive) addargs(&alist, "-r"); if (pflag) addargs(&alist, "-p"); addargs(&alist, "%s", argv[i]); addargs(&alist, "%s", argv[argc-1]); if (do_local_cmd(&alist)) ++errs; continue; } *src++ = 0; if (*src == 0) src = "."; if ((host = strrchr(argv[i], '@')) == NULL) { host = argv[i]; suser = NULL; } else { *host++ = 0; suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; } host = cleanhostname(host); len = strlen(src) + CMDNEEDS + 20; bp = xmalloc(len); (void) snprintf(bp, len, "%s -f %s", cmd, src); if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) { (void) xfree(bp); ++errs; continue; } xfree(bp); sink(1, argv + argc - 1); (void) close(remin); remin = remout = -1; } }
void exec_ipsecctl(int action, char *rules) { int s; int p[2]; char *ipsecctl_program = _PATH_IPSECCTL; arglist args; memset(&args, '\0', sizeof(args)); args.list = NULL; addargs(&args, ipsecctl_program); switch(action) { case IPSECCTL_ADD: break; case IPSECCTL_TEST: addargs(&args, "-n"); break; case IPSECCTL_DELETE: addargs(&args, "-d"); break; } addargs(&args, "-f-"); if (pipe(p) == -1) fatal("could not create pipe"); if ((ipsecpid = fork()) == -1) fatal("fork: %s", strerror(errno)); else if (ipsecpid == 0) { if (dup2(p[1], STDIN_FILENO) == -1) { error("dup2: %s\n", strerror(errno)); _exit(1); } close(p[0]); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_DFL); execvp(ipsecctl_program, args.list); error("exec: %s: %s\n", *args.list, strerror(errno)); _exit(1); } close(p[1]); if (atomicio(vwrite, p[0], rules, strlen(rules)) != strlen(rules)) fatal("writing rules to ipsecctl stdin failed"); close(p[0]); waitpid(ipsecpid, &s, 0); if (s != 0) fatal("exec: ipsecctl exited abnormally"); }
static void display(const char *s) { arglist args; char *cmd; if (env->sc_queue_flags & QUEUE_COMPRESS) cmd = PATH_GZCAT; else cmd = PATH_CAT; bzero(&args, sizeof(args)); addargs(&args, "%s", cmd); addargs(&args, "%s", s); execvp(cmd, args.list); errx(1, "execvp"); }
/* * This functions executes a command simlar to do_cmd(), but expects the * input and output descriptors to be setup by a previous call to do_cmd(). * This way the input and output of two commands can be connected. */ int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout) { pid_t pid; int status; if (verbose_mode) fprintf(stderr, "Executing: 2nd program %s host %s, user %s, command %s\n", ssh_program, host, remuser ? remuser : "******", cmd); /* Fork a child to execute the command on the remote host using ssh. */ pid = fork(); if (pid == 0) { dup2(fdin, 0); dup2(fdout, 1); replacearg(&args, 0, "%s", ssh_program); if (remuser != NULL) { addargs(&args, "-l"); addargs(&args, "%s", remuser); } addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", cmd); execvp(ssh_program, args.list); perror(ssh_program); exit(1); } else if (pid == -1) { fatal("fork: %s", strerror(errno)); } while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("do_cmd2: waitpid: %s", strerror(errno)); return 0; }
static void tolocal(int argc, char **argv) { char *bp, *host = NULL, *suser = NULL; const char *src = NULL; arglist alist; int i, r, sport = -1; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; for (i = 0; i < argc - 1; i++) { free(suser); free(host); free(__UNCONST(src)); r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[i]); ++errs; continue; } if (r != 0) parse_user_host_path(argv[i], &suser, &host, &src); if (suser != NULL && !okname(suser)) { ++errs; continue; } if (!host) { /* Local to local. */ freeargs(&alist); addargs(&alist, "%s", _PATH_CP); if (iamrecursive) addargs(&alist, "-r"); if (pflag) addargs(&alist, "-p"); addargs(&alist, "--"); addargs(&alist, "%s", argv[i]); addargs(&alist, "%s", argv[argc-1]); if (do_local_cmd(&alist)) ++errs; continue; } /* Remote to local. */ xasprintf(&bp, "%s -f %s%s", cmd, *src == '-' ? "-- " : "", src); if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) { free(bp); ++errs; continue; } free(bp); sink(1, argv + argc - 1); (void) close(remin); remin = remout = -1; } free(suser); free(host); free(__UNCONST(src)); }
void toremote(char *targ, int argc, char **argv) { char *bp, *host, *src, *suser, *thost, *tuser, *arg; arglist alist; int i; u_int j; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; *targ++ = 0; if (*targ == 0) targ = "."; arg = xstrdup(argv[argc - 1]); if ((thost = strrchr(arg, '@'))) { /* user@host */ *thost++ = 0; tuser = arg; if (*tuser == '\0') tuser = NULL; } else { thost = arg; tuser = NULL; } if (tuser != NULL && !okname(tuser)) { free(arg); return; } for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src && throughlocal) { /* extended remote to remote */ *src++ = 0; if (*src == 0) src = "."; host = strrchr(argv[i], '@'); if (host) { *host++ = 0; host = cleanhostname(host); suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser)) continue; } else { host = cleanhostname(argv[i]); suser = NULL; } xasprintf(&bp, "%s -f %s%s", cmd, *src == '-' ? "-- " : "", src); if (do_cmd(host, suser, bp, &remin, &remout) < 0) exit(1); free(bp); host = cleanhostname(thost); xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd2(host, tuser, bp, remin, remout) < 0) exit(1); free(bp); (void) close(remin); (void) close(remout); remin = remout = -1; } else if (src) { /* standard remote to remote */ freeargs(&alist); addargs(&alist, "%s", ssh_program); addargs(&alist, "-x"); addargs(&alist, "-oClearAllForwardings=yes"); addargs(&alist, "-n"); for (j = 0; j < remote_remote_args.num; j++) { addargs(&alist, "%s", remote_remote_args.list[j]); } *src++ = 0; if (*src == 0) src = "."; host = strrchr(argv[i], '@'); if (host) { *host++ = 0; host = cleanhostname(host); suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser)) continue; addargs(&alist, "-l"); addargs(&alist, "%s", suser); } else { host = cleanhostname(argv[i]); } addargs(&alist, "--"); addargs(&alist, "%s", host); addargs(&alist, "%s", cmd); addargs(&alist, "%s", src); addargs(&alist, "%s%s%s:%s", tuser ? tuser : "", tuser ? "@" : "", thost, targ); if (do_local_cmd(&alist) != 0) errs = 1; } else { /* local to remote */ if (remin == -1) { xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); host = cleanhostname(thost); if (do_cmd(host, tuser, bp, &remin, &remout) < 0) exit(1); if (response() < 0) exit(1); free(bp); } source(1, argv + i); } } free(arg); }
int main(int argc, char **argv) { int ch, fflag, tflag, status, n; char *targ, **newargv; const char *errstr; extern char *optarg; extern int optind; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* Copy argv, because we modify it */ newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv)); for (n = 0; n < argc; n++) newargv[n] = xstrdup(argv[n]); argv = newargv; __progname = ssh_get_progname(argv[0]); memset(&args, '\0', sizeof(args)); memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); args.list = remote_remote_args.list = NULL; addargs(&args, "%s", ssh_program); addargs(&args, "-x"); addargs(&args, "-oForwardAgent=no"); addargs(&args, "-oPermitLocalCommand=no"); addargs(&args, "-oClearAllForwardings=yes"); fflag = tflag = 0; while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) switch (ch) { /* User-visible flags. */ case '1': case '2': case '4': case '6': case 'C': addargs(&args, "-%c", ch); addargs(&remote_remote_args, "-%c", ch); break; case '3': throughlocal = 1; break; case 'o': case 'c': case 'i': case 'F': addargs(&remote_remote_args, "-%c", ch); addargs(&remote_remote_args, "%s", optarg); addargs(&args, "-%c", ch); addargs(&args, "%s", optarg); break; case 'P': addargs(&remote_remote_args, "-p"); addargs(&remote_remote_args, "%s", optarg); addargs(&args, "-p"); addargs(&args, "%s", optarg); break; case 'B': addargs(&remote_remote_args, "-oBatchmode=yes"); addargs(&args, "-oBatchmode=yes"); break; case 'l': limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, &errstr); if (errstr != NULL) usage(); limit_kbps *= 1024; /* kbps */ bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); break; case 'p': pflag = 1; break; case 'r': iamrecursive = 1; break; case 'S': ssh_program = xstrdup(optarg); break; case 'v': addargs(&args, "-v"); addargs(&remote_remote_args, "-v"); verbose_mode = 1; break; case 'q': addargs(&args, "-q"); addargs(&remote_remote_args, "-q"); showprogress = 0; break; /* Server options. */ case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ iamremote = 1; fflag = 1; break; case 't': /* "to" */ iamremote = 1; tflag = 1; #ifdef HAVE_CYGWIN setmode(0, O_BINARY); #endif break; default: usage(); } argc -= optind; argv += optind; if ((pwd = getpwuid(userid = getuid())) == NULL) fatal("unknown user %u", (u_int) userid); if (!isatty(STDOUT_FILENO)) showprogress = 0; remin = STDIN_FILENO; remout = STDOUT_FILENO; if (fflag) { /* Follow "protocol", send data. */ (void) response(); source(argc, argv); exit(errs != 0); } if (tflag) { /* Receive data. */ sink(argc, argv); exit(errs != 0); } if (argc < 2) usage(); if (argc > 2) targetshouldbedirectory = 1; remin = remout = -1; do_cmd_pid = -1; /* Command to be executed on remote system using "ssh". */ (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); (void) signal(SIGPIPE, lostconn); if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ toremote(targ, argc, argv); else { if (targetshouldbedirectory) verifydir(argv[argc - 1]); tolocal(argc, argv); /* Dest is local host. */ } /* * Finally check the exit status of the ssh process, if one was forked * and no error has occurred yet */ if (do_cmd_pid != -1 && errs == 0) { if (remin != -1) (void) close(remin); if (remout != -1) (void) close(remout); if (waitpid(do_cmd_pid, &status, 0) == -1) errs = 1; else { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errs = 1; } } exit(errs != 0); }
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) { int pin[2], pout[2], reserved[2]; if (verbose_mode) fprintf(stderr, "Executing: program %s host %s, user %s, command %s\n", ssh_program, host, remuser ? remuser : "******", cmd); /* * Reserve two descriptors so that the real pipes won't get * descriptors 0 and 1 because that will screw up dup2 below. */ if (pipe(reserved) < 0) fatal("pipe: %s", strerror(errno)); /* Create a socket pair for communicating with ssh. */ if (pipe(pin) < 0) fatal("pipe: %s", strerror(errno)); if (pipe(pout) < 0) fatal("pipe: %s", strerror(errno)); /* Free the reserved descriptors. */ close(reserved[0]); close(reserved[1]); signal(SIGTSTP, suspchild); signal(SIGTTIN, suspchild); signal(SIGTTOU, suspchild); /* Fork a child to execute the command on the remote host using ssh. */ do_cmd_pid = fork(); if (do_cmd_pid == 0) { /* Child. */ close(pin[1]); close(pout[0]); dup2(pin[0], 0); dup2(pout[1], 1); close(pin[0]); close(pout[1]); replacearg(&args, 0, "%s", ssh_program); if (remuser != NULL) { addargs(&args, "-l"); addargs(&args, "%s", remuser); } addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", cmd); execvp(ssh_program, args.list); perror(ssh_program); exit(1); } else if (do_cmd_pid == -1) { fatal("fork: %s", strerror(errno)); } /* Parent. Close the other side, and return the local side. */ close(pin[0]); *fdout = pin[1]; close(pout[1]); *fdin = pout[0]; signal(SIGTERM, killchild); signal(SIGINT, killchild); signal(SIGHUP, killchild); return 0; }
process shell ( did32 dev /* ID of tty device from which */ ) /* to accept commands */ { char buf[SHELL_BUFLEN]; /* Input line (large enough for */ /* one line from a tty device */ int32 len; /* Length of line read */ char tokbuf[SHELL_BUFLEN + /* Buffer to hold a set of */ SHELL_MAXTOK]; /* Contiguous null-terminated */ /* Strings of tokens */ int32 tlen; /* Current length of all data */ /* in array tokbuf */ int32 tok[SHELL_MAXTOK]; /* Index of each token in */ /* array tokbuf */ int32 toktyp[SHELL_MAXTOK]; /* Type of each token in tokbuf */ int32 ntok; /* Number of tokens on line */ pid32 child; /* Process ID of spawned child */ bool8 backgnd; /* Run command in background? */ char *outname, *inname; /* Pointers to strings for file */ /* names that follow > and < */ did32 stdinput, stdoutput; /* Descriptors for redirected */ /* input and output */ int32 i; /* Index into array of tokens */ int32 j; /* Index into array of commands */ int32 msg; /* Message from receive() for */ /* child termination */ int32 tmparg; /* Address of this var is used */ /* when first creating child */ /* process, but is replaced */ char *src, *cmp; /* Pointers used during name */ /* comparison */ bool8 diff; /* Was difference found during */ /* comparison */ char *args[SHELL_MAXTOK]; /* Argument vector passed to */ /* builtin commands */ /* Print shell banner and startup message */ fprintf(dev, "\n\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", SHELL_BAN0,SHELL_BAN1,SHELL_BAN2,SHELL_BAN3,SHELL_BAN4, SHELL_BAN5,SHELL_BAN6,SHELL_BAN7,SHELL_BAN8,SHELL_BAN9); fprintf(dev, "%s\n\n", SHELL_STRTMSG); /* Continually prompt the user, read input, and execute command */ while (TRUE) { /* Display prompt */ fprintf(dev, SHELL_PROMPT); /* Read a command */ len = read(dev, buf, sizeof(buf)); /* Exit gracefully on end-of-file */ if (len == EOF) { break; } /* If line contains only NEWLINE, go to next line */ if (len <= 1) { continue; } buf[len] = SH_NEWLINE; /* terminate line */ /* Parse input line and divide into tokens */ ntok = lexan(buf, len, tokbuf, &tlen, tok, toktyp); /* Handle parsing error */ if (ntok == SYSERR) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } /* If line is empty, go to next input line */ if (ntok == 0) { fprintf(dev, "\n"); continue; } /* If last token is '&', set background */ if (toktyp[ntok-1] == SH_TOK_AMPER) { ntok-- ; tlen-= 2; backgnd = TRUE; } else { backgnd = FALSE; } /* Check for input/output redirection (default is none) */ outname = inname = NULL; if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS) ||(toktyp[ntok-2] == SH_TOK_GREATER))){ if (toktyp[ntok-1] != SH_TOK_OTHER) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } if (toktyp[ntok-2] == SH_TOK_LESS) { inname = &tokbuf[tok[ntok-1]]; } else { outname = &tokbuf[tok[ntok-1]]; } ntok -= 2; tlen = tok[ntok]; } if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS) ||(toktyp[ntok-2] == SH_TOK_GREATER))){ if (toktyp[ntok-1] != SH_TOK_OTHER) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } if (toktyp[ntok-2] == SH_TOK_LESS) { if (inname != NULL) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } inname = &tokbuf[tok[ntok-1]]; } else { if (outname != NULL) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } outname = &tokbuf[tok[ntok-1]]; } ntok -= 2; tlen = tok[ntok]; } /* Verify remaining tokens are type "other" */ for (i=0; i<ntok; i++) { if (toktyp[i] != SH_TOK_OTHER) { break; } } if ((ntok == 0) || (i < ntok)) { fprintf(dev, SHELL_SYNERRMSG); continue; } stdinput = stdoutput = dev; /* Lookup first token in the command table */ for (j = 0; j < ncmd; j++) { src = cmdtab[j].cname; cmp = tokbuf; diff = FALSE; while (*src != NULLCH) { if (*cmp != *src) { diff = TRUE; break; } src++; cmp++; } if (diff || (*cmp != NULLCH)) { continue; } else { break; } } /* Handle command not found */ if (j >= ncmd) { fprintf(dev, "command %s not found\n", tokbuf); continue; } /* Handle built-in command */ if (cmdtab[j].cbuiltin) { /* No background or redirect. */ if (inname != NULL || outname != NULL || backgnd){ fprintf(dev, SHELL_BGERRMSG); continue; } else { /* Set up arg vector for call */ for (i=0; i<ntok; i++) { args[i] = &tokbuf[tok[i]]; } /* Call builtin shell function */ if ((*cmdtab[j].cfunc)(ntok, args) == SHELL_EXIT) { break; } } continue; } /* Open files and redirect I/O if specified */ if (inname != NULL) { stdinput = open(NAMESPACE,inname,"ro"); if (stdinput == SYSERR) { fprintf(dev, SHELL_INERRMSG, inname); continue; } } if (outname != NULL) { stdoutput = open(NAMESPACE,outname,"w"); if (stdoutput == SYSERR) { fprintf(dev, SHELL_OUTERRMSG, outname); continue; } else { control(stdoutput, F_CTL_TRUNC, 0, 0); } } /* Spawn child thread for non-built-in commands */ child = create(cmdtab[j].cfunc, SHELL_CMDSTK, SHELL_CMDPRIO, cmdtab[j].cname, 2, ntok, &tmparg); /* If creation or argument copy fails, report error */ if ((child == SYSERR) || (addargs(child, ntok, tok, tlen, tokbuf, &tmparg) == SYSERR) ) { fprintf(dev, SHELL_CREATMSG); continue; } /* Set stdinput and stdoutput in child to redirect I/O */ proctab[child].prdesc[0] = stdinput; proctab[child].prdesc[1] = stdoutput; msg = recvclr(); resume(child); if (! backgnd) { msg = receive(); while (msg != child) { msg = receive(); } } } /* Terminate the shell process by returning from the top level */ fprintf(dev,SHELL_EXITMSG); return OK; }
void toremote(char *targ, int argc, char **argv) { int i, len; char *bp, *host, *src, *suser, *thost, *tuser, *arg; arglist alist; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; *targ++ = 0; if (*targ == 0) targ = "."; arg = xstrdup(argv[argc - 1]); if ((thost = strrchr(arg, '@'))) { /* user@host */ *thost++ = 0; tuser = arg; if (*tuser == '\0') tuser = NULL; } else { thost = arg; tuser = NULL; } if (tuser != NULL && !okname(tuser)) { xfree(arg); return; } for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src) { /* remote to remote */ freeargs(&alist); addargs(&alist, "%s", ssh_program); if (verbose_mode) addargs(&alist, "-v"); #if 0 // Disabled since dbclient won't understand them // and scp works fine without them. addargs(&alist, "-x"); addargs(&alist, "-oClearAllForwardings yes"); addargs(&alist, "-n"); #endif *src++ = 0; if (*src == 0) src = "."; host = strrchr(argv[i], '@'); if (host) { *host++ = 0; host = cleanhostname(host); suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser)) continue; addargs(&alist, "-l"); addargs(&alist, "%s", suser); } else { host = cleanhostname(argv[i]); } addargs(&alist, "%s", host); addargs(&alist, "%s", cmd); addargs(&alist, "%s", src); addargs(&alist, "%s%s%s:%s", tuser ? tuser : "", tuser ? "@" : "", thost, targ); if (do_local_cmd(&alist) != 0) errs = 1; } else { /* local to remote */ if (remin == -1) { len = strlen(targ) + CMDNEEDS + 20; bp = xmalloc(len); (void) snprintf(bp, len, "%s -t %s", cmd, targ); host = cleanhostname(thost); if (do_cmd(host, tuser, bp, &remin, &remout, argc) < 0) exit(1); if (response() < 0) exit(1); (void) xfree(bp); } source(1, argv + i); } } }
int main(int argc, char **argv) #endif { int ch, fflag, tflag, status; double speed; char *targ, *endp; extern char *optarg; extern int optind; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); memset(&args, '\0', sizeof(args)); args.list = NULL; addargs(&args, "%s", ssh_program); fflag = tflag = 0; while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1) switch (ch) { /* User-visible flags. */ case '1': case '2': case '4': case '6': case 'C': addargs(&args, "-%c", ch); break; case 'o': case 'c': case 'i': case 'F': addargs(&args, "-%c%s", ch, optarg); break; case 'P': addargs(&args, "-p%s", optarg); break; case 'B': fprintf(stderr, "Note: -B option is disabled in this version of scp"); break; case 'l': speed = strtod(optarg, &endp); if (speed <= 0 || *endp != '\0') usage(); limit_rate = speed * 1024; break; case 'p': pflag = 1; break; case 'r': iamrecursive = 1; break; case 'S': ssh_program = xstrdup(optarg); break; case 'v': addargs(&args, "-v"); verbose_mode = 1; break; #ifdef PROGRESS_METER case 'q': addargs(&args, "-q"); showprogress = 0; break; #endif /* Server options. */ case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ iamremote = 1; fflag = 1; break; case 't': /* "to" */ iamremote = 1; tflag = 1; #ifdef HAVE_CYGWIN setmode(0, O_BINARY); #endif break; default: usage(); } argc -= optind; argv += optind; if ((pwd = getpwuid(userid = getuid())) == NULL) fatal("unknown user %u", (u_int) userid); if (!isatty(STDERR_FILENO)) showprogress = 0; remin = STDIN_FILENO; remout = STDOUT_FILENO; if (fflag) { /* Follow "protocol", send data. */ (void) response(); source(argc, argv); exit(errs != 0); } if (tflag) { /* Receive data. */ sink(argc, argv); exit(errs != 0); } if (argc < 2) usage(); if (argc > 2) targetshouldbedirectory = 1; remin = remout = -1; do_cmd_pid = -1; /* Command to be executed on remote system using "ssh". */ (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); (void) signal(SIGPIPE, lostconn); if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ toremote(targ, argc, argv); else { if (targetshouldbedirectory) verifydir(argv[argc - 1]); tolocal(argc, argv); /* Dest is local host. */ } /* * Finally check the exit status of the ssh process, if one was forked * and no error has occured yet */ if (do_cmd_pid != -1 && errs == 0) { if (remin != -1) (void) close(remin); if (remout != -1) (void) close(remout); if (waitpid(do_cmd_pid, &status, 0) == -1) errs = 1; else { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errs = 1; } } exit(errs != 0); }
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) { int pin[2], pout[2], reserved[2]; if (verbose_mode) fprintf(stderr, "Executing: program %s host %s, user %s, command %s\n", ssh_program, host, remuser ? remuser : "******", cmd); /* * Reserve two descriptors so that the real pipes won't get * descriptors 0 and 1 because that will screw up dup2 below. */ pipe(reserved); /* Create a socket pair for communicating with ssh. */ if (pipe(pin) < 0) fatal("pipe: %s", strerror(errno)); if (pipe(pout) < 0) fatal("pipe: %s", strerror(errno)); /* Free the reserved descriptors. */ close(reserved[0]); close(reserved[1]); /* uClinux needs to build the args here before vforking, otherwise we do it later on. */ #ifdef __uClinux__ replacearg(&args, 0, "%s", ssh_program); if (remuser != NULL) addargs(&args, "-l%s", remuser); addargs(&args, "%s", host); addargs(&args, "%s", cmd); #endif /* __uClinux__ */ /* Fork a child to execute the command on the remote host using ssh. */ #ifdef __uClinux__ do_cmd_pid = vfork(); #else do_cmd_pid = fork(); #endif /* __uClinux__ */ if (do_cmd_pid == 0) { /* Child. */ close(pin[1]); close(pout[0]); dup2(pin[0], 0); dup2(pout[1], 1); close(pin[0]); close(pout[1]); #ifndef __uClinux__ replacearg(&args, 0, "%s", ssh_program); if (remuser != NULL) addargs(&args, "-l%s", remuser); addargs(&args, "%s", host); addargs(&args, "%s", cmd); #endif /* __uClinux__ */ execvp(ssh_program, args.list); perror(ssh_program); #ifndef __uClinux__ exit(1); #else _exit(1); #endif /* __uClinux__ */ } else if (do_cmd_pid == -1) { fatal("fork: %s", strerror(errno)); } #ifdef __uClinux__ /* clean up command */ /* pop cmd */ xfree(args.list[args.num-1]); args.list[args.num-1]=NULL; args.num--; /* pop host */ xfree(args.list[args.num-1]); args.list[args.num-1]=NULL; args.num--; /* pop user */ if (remuser != NULL) { xfree(args.list[args.num-1]); args.list[args.num-1]=NULL; args.num--; } #endif /* __uClinux__ */ /* Parent. Close the other side, and return the local side. */ close(pin[0]); *fdout = pin[1]; close(pout[1]); *fdin = pout[0]; signal(SIGTERM, killchild); signal(SIGINT, killchild); signal(SIGHUP, killchild); return 0; }
int main(int argc, char **argv) { int in, out, ch; pid_t sshpid; char *host, *userhost, *cp, *file2; int debug_level = 0, sshver = 2; char *file1 = NULL, *sftp_server = NULL; char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; LogLevel ll = SYSLOG_LEVEL_INFO; arglist args; extern int optind; extern char *optarg; __progname = get_progname(argv[0]); args.list = NULL; addargs(&args, "ssh"); /* overwritten with ssh_program */ addargs(&args, "-oFallBackToRsh no"); addargs(&args, "-oForwardX11 no"); addargs(&args, "-oForwardAgent no"); addargs(&args, "-oClearAllForwardings yes"); ll = SYSLOG_LEVEL_INFO; infile = stdin; /* Read from STDIN unless changed by -b */ while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { switch (ch) { case 'C': addargs(&args, "-C"); break; case 'v': if (debug_level < 3) { addargs(&args, "-v"); ll = SYSLOG_LEVEL_DEBUG1 + debug_level; } debug_level++; break; case 'F': case 'o': addargs(&args, "-%c%s", ch, optarg); break; case '1': sshver = 1; if (sftp_server == NULL) sftp_server = _PATH_SFTP_SERVER; break; case 's': sftp_server = optarg; break; case 'S': ssh_program = optarg; break; case 'b': if (infile == stdin) { infile = fopen(optarg, "r"); if (infile == NULL) fatal("%s (%s).", strerror(errno), optarg); } else fatal("Filename already specified."); break; case 'P': sftp_direct = optarg; break; case 'B': copy_buffer_len = strtol(optarg, &cp, 10); if (copy_buffer_len == 0 || *cp != '\0') fatal("Invalid buffer size \"%s\"", optarg); break; case 'R': num_requests = strtol(optarg, &cp, 10); if (num_requests == 0 || *cp != '\0') fatal("Invalid number of requests \"%s\"", optarg); break; case 'h': default: usage(); } } log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); if (sftp_direct == NULL) { if (optind == argc || argc > (optind + 2)) usage(); userhost = xstrdup(argv[optind]); file2 = argv[optind+1]; if ((cp = colon(userhost)) != NULL) { *cp++ = '\0'; file1 = cp; } if ((host = strchr(userhost, '@')) == NULL) host = userhost; else { *host++ = '\0'; if (!userhost[0]) { fprintf(stderr, "Missing username\n"); usage(); } addargs(&args, "-l%s",userhost); } host = cleanhostname(host); if (!*host) { fprintf(stderr, "Missing hostname\n"); usage(); } addargs(&args, "-oProtocol %d", sshver); /* no subsystem if the server-spec contains a '/' */ if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) addargs(&args, "-s"); addargs(&args, "%s", host); addargs(&args, "%s", (sftp_server != NULL ? sftp_server : "sftp")); args.list[0] = ssh_program; fprintf(stderr, "Connecting to %s...\n", host); connect_to_server(ssh_program, args.list, &in, &out, &sshpid); } else { args.list = NULL; addargs(&args, "sftp-server"); fprintf(stderr, "Attaching to %s...\n", sftp_direct); connect_to_server(sftp_direct, args.list, &in, &out, &sshpid); } interactive_loop(in, out, file1, file2); #if !defined(USE_PIPES) shutdown(in, SHUT_RDWR); shutdown(out, SHUT_RDWR); #endif close(in); close(out); if (infile != stdin) fclose(infile); while (waitpid(sshpid, NULL, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for ssh process: %s", strerror(errno)); exit(0); }
void toremote(int argc, char **argv) { char *suser = NULL, *host = NULL; const char *src = NULL; char *bp, *tuser, *thost; const char *targ; int sport = -1, tport = -1; arglist alist; int i, r; u_int j; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; /* Parse target */ r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]); ++errs; goto out; } if (r != 0) { if (parse_user_host_path(argv[argc - 1], &tuser, &thost, &targ) == -1) { fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]); ++errs; goto out; } } if (tuser != NULL && !okname(tuser)) { ++errs; goto out; } /* Parse source files */ for (i = 0; i < argc - 1; i++) { free(suser); free(host); free(__UNCONST(src)); r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[i]); ++errs; continue; } if (r != 0) { parse_user_host_path(argv[i], &suser, &host, &src); } if (suser != NULL && !okname(suser)) { ++errs; continue; } if (host && throughlocal) { /* extended remote to remote */ xasprintf(&bp, "%s -f %s%s", cmd, *src == '-' ? "-- " : "", src); if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) exit(1); free(bp); xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0) exit(1); free(bp); (void) close(remin); (void) close(remout); remin = remout = -1; } else if (host) { /* standard remote to remote */ if (tport != -1 && tport != SSH_DEFAULT_PORT) { /* This would require the remote support URIs */ fatal("target port not supported with two " "remote hosts without the -3 option"); } freeargs(&alist); addargs(&alist, "%s", ssh_program); addargs(&alist, "-x"); addargs(&alist, "-oClearAllForwardings=yes"); addargs(&alist, "-n"); for (j = 0; j < remote_remote_args.num; j++) { addargs(&alist, "%s", remote_remote_args.list[j]); } if (sport != -1) { addargs(&alist, "-p"); addargs(&alist, "%d", sport); } if (suser) { addargs(&alist, "-l"); addargs(&alist, "%s", suser); } addargs(&alist, "--"); addargs(&alist, "%s", host); addargs(&alist, "%s", cmd); addargs(&alist, "%s", src); addargs(&alist, "%s%s%s:%s", tuser ? tuser : "", tuser ? "@" : "", thost, targ); if (do_local_cmd(&alist) != 0) errs = 1; } else { /* local to remote */ if (remin == -1) { xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd(thost, tuser, tport, bp, &remin, &remout) < 0) exit(1); if (response() < 0) exit(1); free(bp); } source(1, argv + i); } } out: free(tuser); free(thost); free(__UNCONST(targ)); free(suser); free(host); free(__UNCONST(src)); }
int main(int argc, char **argv) { int in, out, ch, err; char *host, *userhost, *cp, *file2 = NULL; int debug_level = 0, sshver = 2; char *file1 = NULL, *sftp_server = NULL; char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; LogLevel ll = SYSLOG_LEVEL_INFO; arglist args; extern int optind; extern char *optarg; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); __progname = ssh_get_progname(argv[0]); memset(&args, '\0', sizeof(args)); args.list = NULL; addargs(&args, ssh_program); addargs(&args, "-oForwardX11 no"); addargs(&args, "-oForwardAgent no"); addargs(&args, "-oPermitLocalCommand no"); addargs(&args, "-oClearAllForwardings yes"); ll = SYSLOG_LEVEL_INFO; infile = stdin; while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { switch (ch) { case 'C': addargs(&args, "-C"); break; case 'v': if (debug_level < 3) { addargs(&args, "-v"); ll = SYSLOG_LEVEL_DEBUG1 + debug_level; } debug_level++; break; case 'F': case 'o': addargs(&args, "-%c%s", ch, optarg); break; case '1': sshver = 1; if (sftp_server == NULL) sftp_server = _PATH_SFTP_SERVER; break; case 's': sftp_server = optarg; break; case 'S': ssh_program = optarg; replacearg(&args, 0, "%s", ssh_program); break; case 'b': if (batchmode) fatal("Batch file already specified."); /* Allow "-" as stdin */ if (strcmp(optarg, "-") != 0 && (infile = fopen(optarg, "r")) == NULL) fatal("%s (%s).", strerror(errno), optarg); showprogress = 0; batchmode = 1; addargs(&args, "-obatchmode yes"); break; case 'P': sftp_direct = optarg; break; case 'B': copy_buffer_len = strtol(optarg, &cp, 10); if (copy_buffer_len == 0 || *cp != '\0') fatal("Invalid buffer size \"%s\"", optarg); break; case 'R': num_requests = strtol(optarg, &cp, 10); if (num_requests == 0 || *cp != '\0') fatal("Invalid number of requests \"%s\"", optarg); break; case 'h': default: usage(); } } if (!isatty(STDERR_FILENO)) showprogress = 0; log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); if (sftp_direct == NULL) { if (optind == argc || argc > (optind + 2)) usage(); userhost = xstrdup(argv[optind]); file2 = argv[optind+1]; if ((host = strrchr(userhost, '@')) == NULL) host = userhost; else { *host++ = '\0'; if (!userhost[0]) { fprintf(stderr, "Missing username\n"); usage(); } addargs(&args, "-l%s",userhost); } if ((cp = colon(host)) != NULL) { *cp++ = '\0'; file1 = cp; } host = cleanhostname(host); if (!*host) { fprintf(stderr, "Missing hostname\n"); usage(); } addargs(&args, "-oProtocol %d", sshver); /* no subsystem if the server-spec contains a '/' */ if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) addargs(&args, "-s"); addargs(&args, "%s", host); addargs(&args, "%s", (sftp_server != NULL ? sftp_server : "sftp")); if (!batchmode) fprintf(stderr, "Connecting to %s...\n", host); connect_to_server(ssh_program, args.list, &in, &out); } else { args.list = NULL; addargs(&args, "sftp-server"); if (!batchmode) fprintf(stderr, "Attaching to %s...\n", sftp_direct); connect_to_server(sftp_direct, args.list, &in, &out); } freeargs(&args); err = interactive_loop(in, out, file1, file2); #if !defined(USE_PIPES) shutdown(in, SHUT_RDWR); shutdown(out, SHUT_RDWR); #endif close(in); close(out); if (batchmode) fclose(infile); while (waitpid(sshpid, NULL, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for ssh process: %s", strerror(errno)); exit(err == 0 ? 0 : 1); }