From dc0208b08c7df7c0e559b021bdffcebdb2dc221e Mon Sep 17 00:00:00 2001 From: Nate Straz Date: Tue, 13 Sep 2005 19:47:14 +0000 Subject: Merge qarsh revisions 1727:1738 from sistina-test branch djansa-qarsh. --- Makefile | 2 +- qacp.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++----------- qarsh.c | 89 ++++++++++++++-- qarsh_packet.c | 13 +-- qarsh_packet.h | 3 +- qarshd.c | 62 +++++++++-- 6 files changed, 413 insertions(+), 87 deletions(-) diff --git a/Makefile b/Makefile index ca4f0bd..f7cdb0d 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ TARGETS := qarshd qarsh qacp btimed btimec all: $(TARGETS) qarshd: qarshd.c $(COMMON) -lxml2 -qarsh: qarsh.c $(COMMON) -lxml2 +qarsh: qarsh.c $(COMMON) -lxml2 btime.c qacp: qacp.c $(COMMON) -lxml2 btimed: btimed.c btimec: btimec.c btime.c diff --git a/qacp.c b/qacp.c index aa3f22e..90185dd 100644 --- a/qacp.c +++ b/qacp.c @@ -45,29 +45,6 @@ usage() "qacp [user@]host: [[user@]host: ...] "); } -char * -copyargs(char **argv) -{ - int cc; - char **ap, *p; - char *args; - - cc = 0; - for (ap = argv; *ap; ++ap) - cc += strlen(*ap) + 1; - if (cc == 0) return NULL; - args = malloc(cc); - if (!args) { - perror("qacp: malloc failed in copyargs"); - exit(1); - } - for (p = args, ap = argv; *ap; ++ap) { - for (p = strcpy(p, *ap); *p; ++p); - if (ap[1]) - *p++ = ' '; - } - return args; -} void set_remote_user(char *user, char *group) @@ -89,6 +66,38 @@ set_remote_user(char *user, char *group) } } + +struct qp_rstat_pkt * +qacp_rstat(const char *rmtpath, int *rstaterrno) +{ + struct qa_packet *qp; + struct qp_rstat_pkt *rstatp; + + qp = make_qp_rstat(rmtpath, NULL); + send_packet(qacp_fd, qp); + qpfree(qp); + + qp = recv_packet(qacp_fd); + if (qp) { + if (qp->qp_type == QP_RSTAT) { + rstatp = malloc(sizeof *rstatp); + rstatp->qp_path = strdup(qp->qp_rstat.qp_path); + rstatp->qp_st_mode = qp->qp_rstat.qp_st_mode; + rstatp->qp_st_uid = qp->qp_rstat.qp_st_uid; + rstatp->qp_st_gid = qp->qp_rstat.qp_st_gid; + rstatp->qp_st_size = qp->qp_rstat.qp_st_size; + *rstaterrno = 0; + } else if (qp->qp_type == QP_RETURNCODE) { + rstatp = NULL; + *rstaterrno = qp->qp_returncode.qp_errno; + } + + qpfree(qp); + } + + return rstatp; +} + void qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) { @@ -103,9 +112,6 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) off_t offset = 0; struct stat sb; - /* Recall that the packet types are qarshd-centric, so if we want - * to send a file to the host running qarshd we have to tell - * qarshd to recv a file. */ if ((fd = open(srcfile, O_RDONLY)) <0) { fprintf(stderr, "Could not open %s: %s\n", srcfile, strerror(errno)); @@ -122,6 +128,10 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) sd = bind_any(QARSH_MINPORT); port = getsockport(sd); + /* Recall that the packet types are qarshd-centric, so if we want + * to send a file to the host running qarshd we have to tell + * qarshd to recv a file. */ + qp = make_qp_recvfile(destfile, port, sb.st_size, sb.st_mode); qp->qp_seq = 1; send_packet(qacp_fd, qp); @@ -149,65 +159,264 @@ qacp_sendonefile(const char *host, const char *srcfile, const char *destfile) return; } + void qacp_recvonefile(const char *host, const char *srcfile, const char *destfile) { struct qa_packet *qp; + struct sockaddr_in daddr; + socklen_t dlen; + int sd; + int port; + int insd; + int outfd; + char buf[BUFSIZ]; + ssize_t nread; + ssize_t nwrote; + ssize_t nleft; + struct qp_rstat_pkt *rstatp; + int rstaterrno; + + rstatp = qacp_rstat(srcfile, &rstaterrno); + if (!rstatp) { + fprintf(stderr, "%s: %s\n", srcfile, strerror(rstaterrno)); + return; + } + + if ((outfd = open(destfile, O_TRUNC|O_CREAT|O_WRONLY)) <0) { + fprintf(stderr, "Could not open %s: %s\n", destfile, strerror(errno)); + close(qacp_fd); + exit(errno); + } + + fchmod(outfd, rstatp->qp_st_mode); + + sd = bind_any(QARSH_MINPORT); + port = getsockport(sd); /* Recall that the packet types are qarshd-centric, so if we want * to recv a file from the host running qarshd we have to tell * qarshd to send a file. */ - qp = make_qp_sendfile(srcfile, 88, 8888); + qp = make_qp_sendfile(srcfile, port); qp->qp_seq = 1; send_packet(qacp_fd, qp); qpfree(qp); + dlen = sizeof daddr; + insd = accept(sd, (struct sockaddr *) &daddr, &dlen); + + /* Read/write file */ + nleft = rstatp->qp_st_size; + while (nleft > 0) { + nread = read(insd, buf, BUFSIZ); + if (nread < 0) { + fprintf(stderr, "read() error: %s\n", strerror(errno)); + break; + } else if (nread == 0) { /* EOF */ + break; + } + + nwrote = write(outfd, buf, nread); + if (nwrote < 0) { + fprintf(stderr, "write() error: %s\n", strerror(errno)); + break; + } + + nleft -= nread; + } + + if (nleft != 0) { + unlink(destfile); + fprintf(stderr, "Short file transfer of %s, " + "%zd bytes lost, wanted %ld\n", srcfile, nleft, + rstatp->qp_st_size); + } + + close(sd); + close(insd); + close(outfd); + + /* Await our return code from qarshd */ + qp = recv_packet(qacp_fd); + if (qp && qp->qp_type == QP_RETURNCODE + && qp->qp_returncode.qp_rc == -1) { + fprintf(stderr, "Remote side failed, %s\n", + qp->qp_returncode.qp_strerror); + close(qacp_fd); + exit(125); + } + return; } -struct qp_rstat_pkt * -qacp_rstat(const char *rmtpath, int *rstaterrno) +int +recvfiles(char **argv, int argc, int fileidx, short recursive, short quiet) { - struct qa_packet *qp; + char *cp; + char *rhost = NULL; + char *ruser = NULL; + char *rgrp = NULL; + struct passwd *pw; + int file; + char *rmtpath; + char *destpath; + int destisdir; + char *tmpstr; + char *ldnp; /* local path dirname */ + char *rbnp; /* remote path basename */ struct qp_rstat_pkt *rstatp; + struct stat sb; + int rstaterrno; - qp = make_qp_rstat(rmtpath, NULL); - send_packet(qacp_fd, qp); - qpfree(qp); + if (strchr(argv[argc-1], ':') != NULL) { + fprintf(stderr, "%s is not a valid local file string\n", + argv[argc-1]); + return -1; + } - qp = recv_packet(qacp_fd); - if (qp) { - if (qp->qp_type == QP_RSTAT) { - rstatp = malloc(sizeof *rstatp); - rstatp->qp_path = strdup(qp->qp_rstat.qp_path); - rstatp->qp_st_mode = qp->qp_rstat.qp_st_mode; - rstatp->qp_st_uid = qp->qp_rstat.qp_st_uid; - rstatp->qp_st_gid = qp->qp_rstat.qp_st_gid; - rstatp->qp_st_size = qp->qp_rstat.qp_st_size; - *rstaterrno = 0; - } else if (qp->qp_type == QP_RETURNCODE) { - rstatp = NULL; - *rstaterrno = qp->qp_returncode.qp_errno; + destpath = strdup(argv[argc-1]); + + /* Figure out if our destpath is just a dir. + * If so we need to set the flag to tack on the remote + * path basename onto our destpath + */ + + if (stat(destpath, &sb) < 0) { + /* stat couldn't file the file, check if the dirname exists, + * if so we need to reset our destpath to the local dirname + * if that directory exists. + */ + tmpstr = strdup(destpath); + ldnp = strdup(dirname(tmpstr)); + free(tmpstr); + if (stat(ldnp, &sb) < 0) { + fprintf(stderr, "%s: %s\n", ldnp, strerror(errno)); + return -1; } - qpfree(qp); - } + if (S_ISDIR(sb.st_mode)) { + /* No, we don't want to set destisdir, as our dest is really + * a full path, we striped off the filename above to check + * the rest of the path exists. + */ + destisdir = 0; + } else { + fprintf(stderr, "%s not a directory\n", ldnp); + return -1; + } + } else { + if (S_ISDIR(sb.st_mode)) { + destisdir = 1; + } else if (S_ISREG(sb.st_mode)) { + destisdir = 0; + } else { + fprintf(stderr, "%s not a file or directory\n", destpath); + return -1; + } + } + - return rstatp; -} + for (file = fileidx; file < (argc - 1); file++) { + + /* For each file in remote file list (fileidx to argc-2) */ + /* Rstat the file, if it is a dir, error */ + /* Otherwise copy it to local location */ + + if (strchr(argv[file], ':') == NULL) { + fprintf(stderr, "%s is not a valid remote host:file string\n", + argv[file]); + return -1; + } + + rhost = strdup(argv[file]); + cp = strchr(rhost, ':'); + *cp = '\0'; + + /* Grab any user/group info */ + if ((cp = strchr(rhost, '@'))) { + ruser = rhost; + rhost = cp+1; + *cp = '\0'; + } + + if (ruser && (cp = strchr(ruser, '.'))) { + rgrp = cp+1; + *cp = '\0'; + } + + if (!(pw = getpwuid(getuid()))) { + fprintf(stderr, "qacp: unknown user id.\n"); + return -1; + } + + if (ruser == NULL) { + ruser = strdup(pw->pw_name); + } + + qacp_fd = connect_to_host(rhost, QARSHD_CONTROL_PORT); + if (qacp_fd == -1) { + if (errno == 0) { + fprintf(stderr, "Could not connect to %s:%d, %d: %s\n", + rhost, QARSHD_CONTROL_PORT, h_errno, hstrerror(h_errno)); + } else { + fprintf(stderr, "Could not connect to %s:%d, %d: %s\n", + rhost, QARSHD_CONTROL_PORT, errno, strerror(errno)); + } + return -1; + } + + set_remote_user(ruser, rgrp); + + cp = strdup(argv[file]); + cp = strchr(argv[file], ':'); + cp++; + + rmtpath = strdup(cp); + + rstatp = qacp_rstat(rmtpath, &rstaterrno); + if (rstatp) { + if (S_ISREG(rstatp->qp_st_mode)) { + if (destisdir) { + cp = strdup(rmtpath); + rbnp = strdup(basename(cp)); + free(cp); + + cp = malloc(strlen(destpath) + strlen(rbnp) + 2); + strcpy(cp, destpath); + strcat(cp, "/"); + strcat(cp, rbnp); + + qacp_recvonefile(rhost, rmtpath, cp); + free(cp); + free(rbnp); + } else { + if (!quiet) { + printf("%s:%s -> %30.30s\n", + rhost, rmtpath, destpath); + } + qacp_recvonefile(rhost, rmtpath, destpath); + } + } + if (S_ISDIR(rstatp->qp_st_mode)) { + fprintf(stderr, "%s: Not a regular file\n", argv[file]); + return -1; + } + } else { + fprintf(stderr, "%s: %s\n", argv[file], strerror(rstaterrno)); + return -1; + } + + close(qacp_fd); + } -int -recvfiles(char **argv, int argc, short recursive, short quiet) -{ - puts("recvfiles() NA"); return 0; } int -sendfiles(char **argv, int argc, short recursive, short quiet) +sendfiles(char **argv, int argc, int fileidx, short recursive, short quiet) { char *cp; char *rhost = NULL; @@ -276,7 +485,7 @@ sendfiles(char **argv, int argc, short recursive, short quiet) rstatp = qacp_rstat(rmtpath, &rstaterrno); - for (file = optind; file < (argc - 1); file++) { + for (file = fileidx; file < (argc - 1); file++) { tmpstr = strdup(argv[file]); lbnp = strdup(basename(tmpstr)); free(tmpstr); @@ -318,7 +527,7 @@ sendfiles(char **argv, int argc, short recursive, short quiet) } if (!quiet) { - printf("%-40.40s -> %s:%s\n", argv[file], rhost, destpath); + printf("%-30.30s -> %s:%s\n", argv[file], rhost, destpath); } qacp_sendonefile(rhost, argv[file], destpath); @@ -342,6 +551,8 @@ main(int argc, char *argv[]) while ((c = getopt(argc, argv, "+rq")) != -1) { switch (c) { case 'r': + fprintf(stderr, "-r not supported\n"); + exit(2); recursive = 1; break; case 'q': @@ -355,7 +566,7 @@ main(int argc, char *argv[]) } } - if (argv[optind + 1] == NULL) { + if (argv[optind] == NULL) { usage(); exit(2); } @@ -363,11 +574,11 @@ main(int argc, char *argv[]) eflag = 0; /* If last arg has a ':' then we are sending files */ if (strchr(argv[argc-1], ':') != NULL) { - if (sendfiles(argv, argc, recursive, quiet) < 0) { + if (sendfiles(argv, argc, optind, recursive, quiet) < 0) { eflag++; } } else { - if (recvfiles(argv, argc, recursive, quiet) < 0) { + if (recvfiles(argv, argc, optind, recursive, quiet) < 0) { eflag++; } } diff --git a/qarsh.c b/qarsh.c index b0c4aab..5521311 100644 --- a/qarsh.c +++ b/qarsh.c @@ -21,22 +21,34 @@ #include #include - #include "sockutil.h" #include "qarsh_packet.h" +#include "btime.h" #define QARSH_MINPORT 5010 /* Globals */ int qarsh_fd = -1; /* The control connection to qarshd */ +char *qarshd_host; /* hostname of remote host */ +int qarsh_allowed_hbeatmisses = 100; int signal_to_send = 0; int sigs_to_propogate[] = { SIGINT, SIGTERM, SIGHUP, SIGUSR1, SIGUSR2 }; sigset_t pselect_sigmask; void -usage() +usage(const char *pname) { - printf("qarsh: [user[.group]@]hostname cmdline ...\n"); + fprintf(stderr, "%s [options] [user[.group]@]hostname cmdline ...\n" + "-l user Run cmdline using this user name.\n" + "-g group Run cmdline using this group name.\n" + "-p port Use this port to contact qarshd.\n" + "-m misscount Number of missed heartbeats allowed.\n" + " A value of 0 disables heartbeats.\n" + " Default is value is <%d>.\n" + + ,pname, qarsh_allowed_hbeatmisses); + + return; } char * @@ -110,6 +122,29 @@ set_remote_user(char *user, char *group) } } +unsigned int +heartbeat(const char *host) +{ + int retry; + unsigned int hbeat; + + /* User disabled heart beating */ + if (qarsh_allowed_hbeatmisses == 0) { + return 1; + } + + for (retry = 0; retry < qarsh_allowed_hbeatmisses; retry++) { + if ((hbeat = btime(host)) == 0) { + fprintf(stderr, "qarsh: INFO -- missed heartbeat %d\n", retry); + sleep(retry); + } else { + break; + } + } + + return hbeat; +} + int run_remote_cmd(char *cmdline) { @@ -124,6 +159,16 @@ run_remote_cmd(char *cmdline) int nset; struct sockaddr_in caddr; socklen_t clen; + struct timespec timeout; + unsigned int start_hbeat; + unsigned int hbeat; + + /* Use remote node boot time as hearbeat */ + start_hbeat = heartbeat(qarshd_host); + if (!start_hbeat) { + fprintf(stderr, "Can not initialize heartbeat from %s\n", qarshd_host); + return 1; + } l_in = bind_any(QARSH_MINPORT); p_in = getsockport(l_in); @@ -203,11 +248,28 @@ run_remote_cmd(char *cmdline) memset(buf, 0, 1024); for (;;) { + timeout.tv_sec = 5; + timeout.tv_nsec = 0; testfds = readfds; memset(buf, 0, 1024); - nset = pselect(FD_SETSIZE, &testfds, NULL, NULL, NULL, + nset = pselect(FD_SETSIZE, &testfds, NULL, NULL, &timeout, &pselect_sigmask); + + if (nset == 0) { + hbeat = heartbeat(qarshd_host); + if ((!hbeat) || + (abs(hbeat - start_hbeat)) > 5) { + fprintf(stderr, "No heartbeat from %s\n", qarshd_host); + /* Set our return packet as NULL so we exit + * with unknown error. */ + qp = NULL; + break; + } + + continue; + } + if (nset == -1 && errno == EINTR) { /* Only test signals */ if (signal_to_send) { @@ -253,6 +315,10 @@ run_remote_cmd(char *cmdline) } if (nset && FD_ISSET(qarsh_fd, &testfds)) { qp = recv_packet(qarsh_fd); + if (qp == NULL) { + fprintf(stderr, "recv_packet() returned NULL!\n:"); + break; + } /* dump_qp(qp); */ if (qp && qp->qp_type == QP_CMDEXIT) { @@ -294,7 +360,7 @@ main(int argc, char *argv[]) openlog("qarsh", LOG_PID, LOG_DAEMON); - while ((c = getopt(argc, argv, "+p:l:g:")) != -1) { + while ((c = getopt(argc, argv, "+p:l:g:m:")) != -1) { switch (c) { case 'l': remuser = strdup(optarg); @@ -305,17 +371,21 @@ main(int argc, char *argv[]) case 'p': port = atoi(optarg); break; + case 'm': + qarsh_allowed_hbeatmisses = atoi(optarg); + break; case '?': default: printf("Unknown option %c\n", (char)optopt); - usage(); + usage(argv[0]); exit(1); } } if ((host = argv[optind++]) == NULL) { - usage(); + usage(argv[0]); exit(1); } + /* check for user and group in form [user[.group]@]hostname */ { char *sp; @@ -341,9 +411,11 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; if ((args = copyargs(argv)) == NULL) { - usage(); + usage(argv[0]); exit(1); } + + qarshd_host = strdup(host); qarsh_fd = connect_to_host(host, port); if (qarsh_fd == -1) { if (errno == 0) { @@ -361,5 +433,6 @@ main(int argc, char *argv[]) ret = run_remote_cmd(args); close(qarsh_fd); free(args); + free(qarshd_host); return ret; } diff --git a/qarsh_packet.c b/qarsh_packet.c index 76fadf1..151beff 100644 --- a/qarsh_packet.c +++ b/qarsh_packet.c @@ -277,9 +277,6 @@ parse_qp_sendfile(xmlXPathContextPtr ctxt, struct qa_packet *qp) s = get_xpath_string(ctxt, "param[@name='of_port']"); qp->qp_sendfile.qp_of_port = atoi(s); free(s); - s = get_xpath_string(ctxt, "param[@name='count']"); - qp->qp_sendfile.qp_count = atoi(s); - free(s); return 0; } @@ -480,7 +477,7 @@ void string_qp_recvfile(xmlNodePtr node, struct qa_packet *qp) snprintf(tmpstr, 32, "%d", qp->qp_recvfile.qp_if_port); xmlAddChild(node, make_param("if_port", tmpstr)); - snprintf(tmpstr, 32, "%d", qp->qp_recvfile.qp_count); + snprintf(tmpstr, 32, "%zd", qp->qp_recvfile.qp_count); xmlAddChild(node, make_param("count", tmpstr)); snprintf(tmpstr, 32, "%d", qp->qp_recvfile.qp_mode); @@ -494,8 +491,6 @@ void string_qp_sendfile(xmlNodePtr node, struct qa_packet *qp) xmlAddChild(node, make_param("path", qp->qp_sendfile.qp_path)); snprintf(tmpstr, 32, "%d", qp->qp_sendfile.qp_of_port); xmlAddChild(node, make_param("of_port", tmpstr)); - snprintf(tmpstr, 32, "%d", qp->qp_sendfile.qp_count); - xmlAddChild(node, make_param("count", tmpstr)); } void string_qp_rstat(xmlNodePtr node, struct qa_packet *qp) @@ -672,7 +667,7 @@ make_qp_recvfile(const char *path, int if_port, size_t count, mode_t mode) } struct qa_packet * -make_qp_sendfile(const char *path, int of_port, size_t count) +make_qp_sendfile(const char *path, int of_port) { struct qa_packet *qp; qp = malloc(sizeof *qp); @@ -682,7 +677,6 @@ make_qp_sendfile(const char *path, int of_port, size_t count) qp->qp_type = QP_SENDFILE; qp->qp_sendfile.qp_path = strdup(path); qp->qp_sendfile.qp_of_port = of_port; - qp->qp_sendfile.qp_count = count; return qp; } @@ -818,7 +812,7 @@ dump_qp_recvfile(struct qa_packet *qp) { printf("\tpath: %s\n", qp->qp_recvfile.qp_path); printf("\tif_port: %d\n", qp->qp_recvfile.qp_if_port); - printf("\tcount: %d\n", qp->qp_recvfile.qp_count); + printf("\tcount: %zd\n", qp->qp_recvfile.qp_count); printf("\tmode: %o\n", qp->qp_recvfile.qp_mode); } @@ -827,7 +821,6 @@ dump_qp_sendfile(struct qa_packet *qp) { printf("\tpath: %s\n", qp->qp_sendfile.qp_path); printf("\tof_port: %d\n", qp->qp_sendfile.qp_of_port); - printf("\tcount: %d\n", qp->qp_sendfile.qp_count); } void diff --git a/qarsh_packet.h b/qarsh_packet.h index c4316fd..07e90e7 100644 --- a/qarsh_packet.h +++ b/qarsh_packet.h @@ -67,7 +67,6 @@ struct qp_recvfile_pkt { struct qp_sendfile_pkt { char *qp_path; int qp_of_port; - size_t qp_count; }; struct qp_rstat_pkt { @@ -120,7 +119,7 @@ struct qa_packet *make_qp_cmdexit(pid_t pid, int status); struct qa_packet *make_qp_setuser(char *user, char *group); struct qa_packet *make_qp_kill(int sig); struct qa_packet *make_qp_recvfile(const char *path, int if_port, size_t count, mode_t mode); -struct qa_packet *make_qp_sendfile(const char *path, int of_port, size_t count); +struct qa_packet *make_qp_sendfile(const char *path, int of_port); struct qa_packet *make_qp_rstat(const char *path, const struct stat *sb); char *qptostr(struct qa_packet *qp, char **qpstr, int *qpsize); void qpfree(struct qa_packet *qp); diff --git a/qarshd.c b/qarshd.c index ee9e556..4392db8 100644 --- a/qarshd.c +++ b/qarshd.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,7 @@ recvfile(const char *path, int if_port, size_t count, mode_t mode) if (nleft != 0) { unlink(path); syslog(LOG_WARNING, "Short file transfer in recvfile(), " - "%d bytes lost, wanted %d\n", nleft, count); + "%zd bytes lost, wanted %zd\n", nleft, count); } close(sd); @@ -146,6 +147,46 @@ recvfile(const char *path, int if_port, size_t count, mode_t mode) return count - nleft; } +ssize_t +pushfile(const char *path, int of_port) +{ + int outsd; + int infd; + off_t offset = 0; + ssize_t nbytes; + struct stat sb; + + outsd = connect_to_peer(&peername, of_port); + if (outsd == -1) { + syslog(LOG_WARNING, "Connect to of_port (%d) failed: %s\n", + of_port, strerror(errno)); + return -1; + } + + infd = open(path, O_RDONLY); + if (infd == -1) { + syslog(LOG_WARNING, "Could not open %s: %s\n", + path, strerror(errno)); + close(outsd); + return -1; + } + + if (fstat(infd, &sb) < 0) { + syslog(LOG_WARNING, "Could not stat %s: %s\n", + path, strerror(errno)); + close(infd); + close(outsd); + return -1; + } + + nbytes = sendfile(outsd, infd, &offset, sb.st_size); + + close(infd); + close(outsd); + + return nbytes; +} + struct qa_packet * rstat(const char *path) { @@ -186,6 +227,7 @@ handle_packets(int infd) for (;;) { FD_SET(infd, &rfds); timeout.tv_sec = 3; + timeout.tv_nsec = 0; nfd = pselect(infd+1, &rfds, NULL, NULL, &timeout, &orig_sigmask); @@ -238,7 +280,7 @@ handle_packets(int infd) break; case QP_RECVFILE: syslog(LOG_INFO, "Got a QP_RECVFILE with path = %s, " - "ifd = %d, count = %d, mode = %o\n", + "ifd = %d, count = %zd, mode = %o\n", qp->qp_recvfile.qp_path, qp->qp_recvfile.qp_if_port, qp->qp_recvfile.qp_count, @@ -251,7 +293,7 @@ handle_packets(int infd) rp = make_qp_returncode(-1, errno, strerror(errno)); } else if (nbytes < qp->qp_recvfile.qp_count) { char tmpstr[512]; - sprintf(tmpstr, "Excpected %d, wrote %d\n", + sprintf(tmpstr, "Excpected %zd, wrote %zd\n", qp->qp_recvfile.qp_count, nbytes); rp = make_qp_returncode(-1, 0, tmpstr); } else { @@ -262,10 +304,18 @@ handle_packets(int infd) break; case QP_SENDFILE: syslog(LOG_INFO, "Got a QP_SENDFILE with path = %s, " - "ofd = %d, count = %d\n", + "ofd = %d\n", qp->qp_sendfile.qp_path, - qp->qp_sendfile.qp_of_port, - qp->qp_sendfile.qp_count); + qp->qp_sendfile.qp_of_port); + nbytes = pushfile(qp->qp_sendfile.qp_path, + qp->qp_sendfile.qp_of_port); + if (nbytes < 0) { + rp = make_qp_returncode(-1, errno, strerror(errno)); + } else { + rp = make_qp_returncode(0, 0, "Transfer Complete"); + } + send_packet(fileno(stdout), rp); + qpfree(rp); break; case QP_RSTAT: syslog(LOG_INFO, "Got a QP_RSTAT with path = %s\n", -- cgit