/* * This function executes a command similar 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, int port, char *cmd, int fdin, int fdout) { pid_t pid; int status; if (verbose_mode) fmprintf(stderr, "Executing: 2nd program %s host %s, user %s, command %s\n", ssh_program, host, remuser ? remuser : "******", cmd); if (port == -1) port = sshport; /* 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 (port != -1) { addargs(&args, "-p"); addargs(&args, "%d", port); } 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; }
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; }
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, 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); }