/** The /who command: retrieves information from users. */ DLLFUNC int m_who(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aChannel *target_channel; char *mask = parv[1]; char star[] = "*"; int i = 0; who_flags = 0; memset(&wfl, 0, sizeof(wfl)); if (parc > 1) { i = parse_who_options(sptr, parc - 1, parv + 1); if (i < 0) { sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask); return 0; } } if (parc-i < 2 || strcmp(parv[1 + i], "0") == 0) mask = star; else mask = parv[1 + i]; if (!i && parc > 2 && *parv[2] == 'o') who_flags |= WF_OPERONLY; collapse(mask); if (*mask == '\0') { /* no mask given */ sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], "*"); return 0; } if ((target_channel = find_channel(mask, NULL)) != NULL) { do_channel_who(sptr, target_channel, mask); sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask); return 0; } if (wfl.channel && wfl.want_channel == WHO_WANT && (target_channel = find_channel(wfl.channel, NULL)) != NULL) { do_channel_who(sptr, target_channel, mask); sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask); return 0; } else { do_other_who(sptr, mask); sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask); return 0; } return 0; }
/* * login to remote system with given user name and password. */ void clogin(char *cuser, char *cpassword) { free(user); user = strdup(cuser); if (strcmp(user, "anonymous") != 0 && strcmp(user, "ftp") != 0) fatal("User must be 'anonymous' or 'ftp'"); sendrequest("USER", user); switch(getreply(&ctlin, msg, sizeof(msg), 1)){ case Success: return; case Incomplete: break; case TempFail: case PermFail: fatal("login failed"); } if (cpassword == 0) fatal("password needed"); sendrequest("PASS", cpassword); if(getreply(&ctlin, msg, sizeof(msg), 1) != Success) fatal("password failed"); if(strstr(msg, "Sess#")) defos = MVS; return; }
static char * doauth(char *methods) { char *buf, *err; UserPasswd *p; int n; DS ds; dial_string_parse(ddomain, &ds); if(user != nil) p = auth_getuserpasswd(nil, "proto=pass service=smtp server=%q user=%q", ds.host, user); else p = auth_getuserpasswd(nil, "proto=pass service=smtp server=%q", ds.host); if (p == nil) return Giveup; err = Retry; if (strstr(methods, "LOGIN")){ dBprint("AUTH LOGIN\r\n"); if (getreply() != 3) goto out; dBprint("%.*[\r\n", strlen(p->user), p->user); if (getreply() != 3) goto out; dBprint("%.*[\r\n", strlen(p->passwd), p->passwd); if (getreply() != 2) goto out; err = nil; } else if (strstr(methods, "PLAIN")){ n = strlen(p->user) + strlen(p->passwd) + 2; buf = malloc(n+1); if (buf == nil) { free(buf); goto out; /* Out of memory */ } snprint(buf, n, "%c%s%c%s", 0, p->user, 0, p->passwd); dBprint("AUTH PLAIN %.*[\r\n", n, buf); memset(buf, 0, n); free(buf); if (getreply() != 2) goto out; err = nil; } else err = "No supported AUTH method"; out: memset(p->user, 0, strlen(p->user)); memset(p->passwd, 0, strlen(p->passwd)); free(p); return err; }
/* * login to remote system */ void rlogin(char *rsys, char *keyspec) { char *line; char pass[128]; UserPasswd *up; up = nil; for(;;){ if(up == nil && os != Plan9) up = auth_getuserpasswd(auth_getkey, "proto=pass server=%s service=ftp %s", rsys, keyspec); if(up != nil){ sendrequest("USER", up->user); } else { print("User[default = %s]: ", user); line = Brdline(&stdin, '\n'); if(line == 0) exits(0); line[Blinelen(&stdin)-1] = 0; if(*line){ free(user); user = strdup(line); } sendrequest("USER", user); } switch(getreply(&ctlin, msg, sizeof(msg), 1)){ case Success: goto out; case Incomplete: break; case TempFail: case PermFail: continue; } if(up != nil){ sendrequest("PASS", up->passwd); } else { if(getpassword(pass, pass+sizeof(pass)) < 0) exits(0); sendrequest("PASS", pass); } if(getreply(&ctlin, msg, sizeof(msg), 1) == Success){ if(strstr(msg, "Sess#")) defos = MVS; break; } } out: if(up != nil){ memset(up, 0, sizeof(*up)); free(up); } }
/* * connect to remote server, default network is "tcp/ip" */ void hello(char *dest) { char *p; char dir[Maxpath]; TLSconn conn; Binit(&stdin, 0, OREAD); /* init for later use */ ctlfd = dial(netmkaddr(dest, "tcp", "ftp"), 0, dir, 0); if(ctlfd < 0){ fprint(2, "can't dial %s: %r\n", dest); exits("dialing"); } Binit(&ctlin, ctlfd, OREAD); /* remember network for the data connections */ p = strrchr(dir+1, '/'); if(p == 0) fatal("wrong dial(2) linked with ftp"); *p = 0; safecpy(net, dir, sizeof(net)); /* wait for hello from other side */ if(getreply(&ctlin, msg, sizeof(msg), 1) != Success) fatal("bad hello"); if(strstr(msg, "Plan 9")) os = Plan9; if(usetls){ sendrequest("AUTH", "TLS"); if(getreply(&ctlin, msg, sizeof(msg), 1) != Success) fatal("bad auth tls"); ctlfd = tlsClient(ctlfd, &conn); if(ctlfd < 0) fatal("starting tls: %r"); free(conn.cert); Binit(&ctlin, ctlfd, OREAD); sendrequest("PBSZ", "0"); if(getreply(&ctlin, msg, sizeof(msg), 1) != Success) fatal("bad pbsz 0"); sendrequest("PROT", "P"); if(getreply(&ctlin, msg, sizeof(msg), 1) != Success) fatal("bad prot p"); } }
static void send_who_reply(aClient *sptr, aClient *acptr, char *channel, char *status, char *xstat) { char *stat; char *host; int flat = (FLAT_MAP && !IsAnOper(sptr)) ? 1 : 0; stat = malloc(strlen(status) + strlen(xstat) + 1); sprintf(stat, "%s%s", status, xstat); if (IsAnOper(sptr)) { if (who_flags & WF_REALHOST) host = acptr->user->realhost; else if (who_flags & WF_IP) host = (acptr->user->ip_str ? acptr->user->ip_str : acptr->user->realhost); else host = GetHost(acptr); } else host = GetHost(acptr); if (IsULine(acptr) && !IsOper(sptr) && HIDE_ULINES) sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name, channel, /* channel name */ acptr->user->username, /* user name */ host, /* hostname */ "hidden", /* let's hide the server from normal users if the server is a uline and HIDE_ULINES is on */ acptr->name, /* nick */ stat, /* status */ 0, /* hops (hidden) */ acptr->info /* realname */ ); else sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name, channel, /* channel name */ acptr->user->username, /* user name */ host, /* hostname */ acptr->user->server, /* server name */ acptr->name, /* nick */ stat, /* status */ flat ? 0 : acptr->hopcount, /* hops */ acptr->info /* realname */ ); free(stat); }
/* * tell remote that we're exiting and then do it */ void quit(void) { sendrequest("QUIT", nil); getreply(&ctlin, msg, sizeof(msg), 0); exits(0); }
/* * report a recipient to remote */ char * rcptto(char *to) { String *s; s = unescapespecial(bangtoat(to)); if(toline == 0) toline = s_new(); else s_append(toline, ", "); s_append(toline, s_to_c(s)); if(strchr(s_to_c(s), '@')) dBprint("RCPT TO:<%s>\r\n", s_to_c(s)); else { s_append(toline, "@"); s_append(toline, ddomain); dBprint("RCPT TO:<%s@%s>\r\n", s_to_c(s), ddomain); } alarm(10*alarmscale); switch(getreply()){ case 2: break; case 5: return Giveup; default: return Retry; } return 0; }
void Connection::site(int argc, char *argv[]) { PROC(("site","%d [%s,%s,%s]",argc,(argc>=1)?argv[0]:"nil",(argc>=2)?argv[1]:"nil",(argc>=3)?argv[2]:"nil")); int i; char buf[BUFSIZ]; if(argc < 2) { code = -1; return; } strcpy(buf, Opt.cmdSite); strcat(buf, " "); strcat(buf, argv[1]); for(i = 2; i < argc; i++) { strcat(buf, " "); strcat(buf, argv[i]); } if(command(buf) == RPL_PRELIM) while(getreply(0) == RPL_PRELIM); }
static int _ftp( struct ftp_info *info, unsigned long flags, const char *cmd ) { struct opusftp_globals *ogp = info->fi_og; int len; // Valid? if (!info || !cmd) return 600; // Socket used by non-owner task? if (info->fi_task != FindTask(0)) return 600; // Log outgoing commands if debugging is turned on // NOOPs are never logged, passwords are hidden if (!info->fi_doing_noop && ogp->og_oc.oc_log_debug) logprintf("--> %s\n", strnicmp(cmd,"PASS ",5) ? cmd : "PASS ....." ); len = strlen(cmd); send( info->fi_cs, (char *)cmd, len, 0 ); // Don't get reply if this is an asynchronous command, simply return 0 if (flags & FTPFLAG_ASYNCH) return 0; // Can TIMEOUT return getreply( info ); }
/* * used for keep alives */ void nop(void) { if(lastsend - time(0) < 15) return; sendrequest("PWD", nil); getreply(&ctlin, msg, sizeof(msg), 0); }
static void image(void) { sendrequest("TYPE I", nil); switch(getreply(&ctlin, msg, sizeof(msg), 0)){ case Success: break; default: fatal("can't set type to image/binary"); } }
static void ascii(void) { sendrequest("TYPE A", nil); switch(getreply(&ctlin, msg, sizeof(msg), 0)){ case Success: break; default: fatal("can't set type to ascii"); } }
/* * create a remote directory */ int createdir(Node *node) { if(changedir(node->parent) < 0) return -1; sendrequest("MKD", node->d->name); if(getreply(&ctlin, msg, sizeof(msg), 0) != Success) return -1; return 0; }
/* * remove a remote directory */ int removedir(Node *node) { if(changedir(node->parent) < 0) return -1; sendrequest("RMD", s_to_c(node->remname)); if(getreply(&ctlin, msg, sizeof(msg), 0) != Success) return -1; return 0; }
/* * we're leaving */ void quit(char *rv) { /* 60 minutes to quit */ quitting = 1; quitrv = rv; alarm(60*alarmscale); dBprint("QUIT\r\n"); getreply(); Bterm(&bout); Bterm(&bfile); }
/* * exchange names with remote host, attempt to * enable encryption and optionally authenticate. * not fatal if we can't. */ static char * dotls(char *me) { char *err; dBprint("STARTTLS\r\n"); if (getreply() != 2) return Giveup; err = wraptls(); if (err != nil) return err; return(hello(me, 1)); }
/* * Announce on a local port and tell its address to the the remote side */ static int port(void) { char buf[256]; int n, fd; char *ptr; uchar ipaddr[IPaddrlen]; int port; /* get a channel to listen on, let kernel pick the port number */ sprint(buf, "%s!*!0", net); listenfd = announce(buf, netdir); if(listenfd < 0) return seterr("can't announce"); /* get the local address and port number */ sprint(buf, "%s/local", netdir); fd = open(buf, OREAD); if(fd < 0) return seterr("opening %s: %r", buf); n = read(fd, buf, sizeof(buf)-1); close(fd); if(n <= 0) return seterr("opening %s/local: %r", netdir); buf[n] = 0; ptr = strchr(buf, ' '); if(ptr) *ptr = 0; ptr = strchr(buf, '!')+1; port = atoi(ptr); memset(ipaddr, 0, IPaddrlen); if (*net){ strcpy(buf, net); ptr = strchr(buf +1, '/'); if (ptr) *ptr = 0; myipaddr(ipaddr, buf); } /* tell remote side */ sprint(buf, "PORT %d,%d,%d,%d,%d,%d", ipaddr[IPv4off+0], ipaddr[IPv4off+1], ipaddr[IPv4off+2], ipaddr[IPv4off+3], port>>8, port&0xff); sendrequest(buf, nil); if(getreply(&ctlin, msg, sizeof(msg), 0) != Success) return seterr(msg); return 0; }
/* * read a remote file */ int readfile1(Node *node) { Biobuf *bp; char buf[4*1024]; long off; int n; int tries; if(changedir(node->parent) < 0) return -1; for(tries = 0; tries < 4; tries++){ switch(data(OREAD, &bp, "RETR", s_to_c(node->remname))){ case Extra: break; case TempFail: continue; default: return seterr(nosuchfile); } off = 0; while((n = read(Bfildes(bp), buf, sizeof buf)) > 0){ if(filewrite(node, buf, off, n) != n){ off = -1; break; } off += n; } if(off < 0) return -1; /* make sure a file gets created even for a zero length file */ if(off == 0) filewrite(node, buf, 0, 0); close(Bfildes(bp)); switch(getreply(&ctlin, msg, sizeof(msg), 0)){ case Success: return off; case TempFail: continue; default: return seterr(nosuchfile); } } return seterr(nosuchfile); }
/* * have server call back for a data connection */ static int active(int mode, Biobuf **bpp, char *cmda, char *cmdb) { int cfd, dfd, rv; char newdir[Maxpath]; char datafile[Maxpath + 6]; TLSconn conn; if(port() < 0) return TempFail; sendrequest(cmda, cmdb); rv = getreply(&ctlin, msg, sizeof(msg), 0); if(rv != Extra){ close(listenfd); return rv; } /* wait for a new call */ cfd = listen(netdir, newdir); if(cfd < 0) fatal("waiting for data connection"); close(listenfd); /* open it's data connection and close the control connection */ sprint(datafile, "%s/data", newdir); dfd = open(datafile, ORDWR); close(cfd); if(dfd < 0) fatal("opening data connection"); if(usetls){ memset(&conn, 0, sizeof(conn)); dfd = tlsClient(dfd, &conn); if(dfd < 0) fatal("starting tls: %r"); free(conn.cert); } Binit(&dbuf, dfd, mode); *bpp = &dbuf; return Extra; }
/* * exchange names with remote host, attempt to * enable encryption and optionally authenticate. * not fatal if we can't. */ static char * dotls(char *me) { TLSconn *c; char *err; int fd; c = mallocz(sizeof(*c), 1); /* Note: not freed on success */ if (c == nil) return Giveup; dBprint("STARTTLS\r\n"); if (getreply() != 2) return Giveup; fd = tlsClient(Bfildes(&bout), c); if (fd < 0) { syslog(0, "smtp", "tlsClient to %q: %r", ddomain); return Giveup; } err = ckthumbs(c); if (err && !okunksecure) { free(c); close(fd); return err; /* how to recover? TLS is started */ } Bterm(&bin); Bterm(&bout); /* * set up bin & bout to use the TLS fd, i/o upon which generates * i/o on the original, underlying fd. */ Binit(&bin, fd, OREAD); fd = dup(fd, -1); Binit(&bout, fd, OWRITE); syslog(0, "smtp", "started TLS to %q", ddomain); return(hello(me, 1)); }
/*VARARGS1*/ int command(const char *fmt, ...) { va_list ap; int r; void (*oldintr)(int); abrtflag = 0; if (debug) { printf("---> "); va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); printf("\n"); (void) fflush(stdout); } if (cout == 0) { perror ("No control connection for command"); code = -1; return (0); } oldintr = signal(SIGINT,cmdabort); { char buffer[1024]; va_start(ap, fmt); vsprintf(buffer, fmt, ap); va_end(ap); //DLJ: to work through firewalls - send the command as a single message strcat(buffer,"\r\n"); fprintfSocket(cout, buffer); } //DLJ: the following two lines are replaced by the strcat above - seems to // make it work through firewalls. // fprintfSocket(cout, "\r\n"); // (void) fflush(cout); cpend = 1; r = getreply(!strcmp(fmt, "QUIT")); if (abrtflag && oldintr != SIG_IGN) (*oldintr)(SIGINT); // (void) signal(SIGINT, oldintr); return(r); }
/* * report sender to remote */ char * mailfrom(char *from) { if(!returnable(from)) dBprint("MAIL FROM:<>\r\n"); else if(strchr(from, '@')) dBprint("MAIL FROM:<%s>\r\n", from); else dBprint("MAIL FROM:<%s@%s>\r\n", from, hostdomain); switch(getreply()){ case 2: break; case 5: return Giveup; default: return Retry; } return 0; }
int command(const char *fmt, ...) { va_list ap; int r; void (*oldintr)(int); abrtflag = 0; if (debug) { printf("---> "); va_start(ap, fmt); if (strncmp("PASS ", fmt, 5) == 0) printf("PASS XXXX"); else vfprintf(stdout, fmt, ap); va_end(ap); printf("\n"); (void) fflush(stdout); } if (cout == NULL) { perror ("No control connection for command"); code = -1; return (0); } oldintr = signal(SIGINT, cmdabort); va_start(ap, fmt); vfprintf(cout, fmt, ap); va_end(ap); fprintf(cout, "\r\n"); (void) fflush(cout); cpend = 1; r = getreply(!strcmp(fmt, "QUIT")); if (abrtflag && oldintr != SIG_IGN) (*oldintr)(SIGINT); (void) signal(SIGINT, oldintr); return(r); }
/* * write back a file */ int createfile1(Node *node) { Biobuf *bp; char buf[4*1024]; long off; int n; if(changedir(node->parent) < 0) return -1; if(data(OWRITE, &bp, "STOR", s_to_c(node->remname)) != Extra) return -1; for(off = 0; ; off += n){ n = fileread(node, buf, off, sizeof(buf)); if(n <= 0) break; write(Bfildes(bp), buf, n); } close(Bfildes(bp)); if(getreply(&ctlin, msg, sizeof(msg), 0) != Success) return -1; return off; }
/* * send the damn thing */ char * data(String *from, Biobuf *b) { char *buf, *cp; int i, n, nbytes, bufsize, eof, r; String *fromline; char errmsg[Errlen]; char id[40]; /* * input the header. */ buf = malloc(1); if(buf == 0){ s_append(s_restart(reply), "out of memory"); return Retry; } n = 0; eof = 0; for(;;){ cp = Brdline(b, '\n'); if(cp == nil){ eof = 1; break; } nbytes = Blinelen(b); buf = realloc(buf, n+nbytes+1); if(buf == 0){ s_append(s_restart(reply), "out of memory"); return Retry; } strncpy(buf+n, cp, nbytes); n += nbytes; if(nbytes == 1) /* end of header */ break; } buf[n] = 0; bufsize = n; /* * parse the header, turn all addresses into @ format */ yyinit(buf, n); yyparse(); /* * print message observing '.' escapes and using \r\n for \n */ alarm(20*alarmscale); if(!filter){ dBprint("DATA\r\n"); switch(getreply()){ case 3: break; case 5: free(buf); return Giveup; default: free(buf); return Retry; } } /* * send header. add a message-id, a sender, and a date if there * isn't one */ nbytes = 0; fromline = convertheader(from); uneaten = buf; srand(truerand()); if(messageid == 0){ for(i=0; i<16; i++){ r = rand()&0xFF; id[2*i] = hex[r&0xF]; id[2*i+1] = hex[(r>>4)&0xF]; } id[2*i] = '\0'; nbytes += Bprint(&bout, "Message-ID: <%s@%s>\r\n", id, hostdomain); if(debug) Bprint(&berr, "Message-ID: <%s@%s>\r\n", id, hostdomain); } if(originator==0){ nbytes += Bprint(&bout, "From: %s\r\n", s_to_c(fromline)); if(debug) Bprint(&berr, "From: %s\r\n", s_to_c(fromline)); } s_free(fromline); if(destination == 0 && toline) if(*s_to_c(toline) == '@'){ /* route addr */ nbytes += Bprint(&bout, "To: <%s>\r\n", s_to_c(toline)); if(debug) Bprint(&berr, "To: <%s>\r\n", s_to_c(toline)); } else { nbytes += Bprint(&bout, "To: %s\r\n", s_to_c(toline)); if(debug) Bprint(&berr, "To: %s\r\n", s_to_c(toline)); } if(date==0 && udate) nbytes += printdate(udate); if (usys) uneaten = usys->end + 1; nbytes += printheader(); if (*uneaten != '\n') putcrnl("\n", 1); /* * send body */ putcrnl(uneaten, buf+n - uneaten); nbytes += buf+n - uneaten; if(eof == 0){ for(;;){ n = Bread(b, buf, bufsize); if(n < 0){ rerrstr(errmsg, sizeof(errmsg)); s_append(s_restart(reply), errmsg); free(buf); return Retry; } if(n == 0) break; alarm(10*alarmscale); putcrnl(buf, n); nbytes += n; } } free(buf); if(!filter){ if(last != '\n') dBprint("\r\n.\r\n"); else dBprint(".\r\n"); alarm(10*alarmscale); switch(getreply()){ case 2: break; case 5: return Giveup; default: return Retry; } syslog(0, "smtp", "%s sent %d bytes to %s", s_to_c(from), nbytes, s_to_c(toline));/**/ } return 0; }
char * hello(char *me, int encrypted) { int ehlo; String *r; char *ret, *s, *t; if (!encrypted) { if(trysecure > 1){ if((ret = wraptls()) != nil) return ret; encrypted = 1; } /* * Verizon fails to print the smtp greeting banner when it * answers a call. Send a no-op in the hope of making it * talk. */ if (autistic) { dBprint("NOOP\r\n"); getreply(); /* consume the smtp greeting */ /* next reply will be response to noop */ } switch(getreply()){ case 2: break; case 5: return Giveup; default: return Retry; } } ehlo = 1; Again: if(ehlo) dBprint("EHLO %s\r\n", me); else dBprint("HELO %s\r\n", me); switch (getreply()) { case 2: break; case 5: if(ehlo){ ehlo = 0; goto Again; } return Giveup; default: return Retry; } r = s_clone(reply); if(r == nil) return Retry; /* Out of memory or couldn't get string */ /* Invariant: every line has a newline, a result of getcrlf() */ for(s = s_to_c(r); (t = strchr(s, '\n')) != nil; s = t + 1){ *t = '\0'; for (t = s; *t != '\0'; t++) *t = toupper(*t); if(!encrypted && trysecure && (strcmp(s, "250-STARTTLS") == 0 || strcmp(s, "250 STARTTLS") == 0)){ s_free(r); return dotls(me); } if(tryauth && (encrypted || insecure) && (strncmp(s, "250 AUTH", strlen("250 AUTH")) == 0 || strncmp(s, "250-AUTH", strlen("250 AUTH")) == 0)){ ret = doauth(s + strlen("250 AUTH ")); s_free(r); return ret; } } s_free(r); return 0; }
void recvrequest(const char *cmd, char *volatile local, char *remote, const char *lmode, int printnames) { FILE *volatile fout, *volatile din = 0; int (*volatile closefunc)(FILE *); void (*volatile oldintp)(int); void (*volatile oldintr)(int); volatile int is_retr, tcrflag, bare_lfs = 0; static unsigned bufsize; static char *buf; volatile long bytes = 0, hashbytes = HASHBYTES; register int c, d; struct timeval start, stop; struct stat st; #if 0 printf("%s(%d): recvrequest(cmd=%s,local=%s,remote=%s)\n", __FILE__, __LINE__, cmd, local, remote); #endif is_retr = strcmp(cmd, "RETR") == 0; if (is_retr && ftpverbose && printnames) { if (local && *local != '-') printf("local: %s ", local); if (remote) printf("remote: %s\n", remote); } #if 0 if (proxy && is_retr) { proxtrans(cmd, local, remote); return; } #endif closefunc = NULL; oldintr = NULL; oldintp = NULL; tcrflag = !crflag && is_retr; if (sigsetjmp(recvabort, 1)) { while (cpend) { (void) getreply(0); } if (data >= 0) { (void) close(data); data = -1; } if (oldintr) (void) signal(SIGINT, oldintr); code = -1; return; } oldintr = signal(SIGINT, abortrecv); #if 0 if (strcmp(local, "-") && *local != '|') { if (access(local, W_OK) < 0) { char *dir = rindex(local, '/'); if (errno != ENOENT && errno != EACCES) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); (void) signal(SIGINT, oldintr); code = -1; return; } if (dir != NULL) *dir = 0; d = access(dir ? local : ".", W_OK); if (dir != NULL) *dir = '/'; if (d < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); (void) signal(SIGINT, oldintr); code = -1; return; } if (!runique && errno == EACCES && chmod(local, 0600) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); /* * Believe it or not, this was actually * repeated in the original source. */ (void) signal(SIGINT, oldintr); /*(void) signal(SIGINT, oldintr);*/ code = -1; return; } if (runique && errno == EACCES && (local = gunique(local)) == NULL) { (void) signal(SIGINT, oldintr); code = -1; return; } } else if (runique && (local = gunique(local)) == NULL) { (void) signal(SIGINT, oldintr); code = -1; return; } } #endif if (!is_retr) { if (curtype != TYPE_A) changetype(TYPE_A, 0); } else if (curtype != type) { changetype(type, 0); } if (initconn()) { (void) signal(SIGINT, oldintr); code = -1; return; } if (sigsetjmp(recvabort, 1)) goto abort; if (is_retr && restart_point && command("REST %ld", (long) restart_point) != CONTINUE) return; if (remote) { if (command("%s %s", cmd, remote) != PRELIM) { (void) signal(SIGINT, oldintr); return; } } else { if (command("%s", cmd) != PRELIM) { (void) signal(SIGINT, oldintr); return; } } din = dataconn("r"); if (din == NULL) goto abort; if (strcmp(local, "-") == 0) fout = stdout; else if (*local == '|') { oldintp = signal(SIGPIPE, SIG_IGN); fout = popen(local + 1, "w"); if (fout == NULL) { perror(local+1); goto abort; } closefunc = pclose; } else { extern int local_fclose(); fout = local_fopen(local, lmode); if (fout == NULL) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); goto abort; } closefunc = local_fclose; } if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) st.st_blksize = BUFSIZ; if (st.st_blksize > bufsize) { if (buf) (void) free(buf); buf = malloc((unsigned)st.st_blksize); if (buf == NULL) { perror("malloc"); bufsize = 0; goto abort; } bufsize = st.st_blksize; } (void) gettimeofday(&start, (struct timezone *)0); switch (curtype) { case TYPE_I: case TYPE_L: if (restart_point && lseek(fileno(fout), (long) restart_point, L_SET) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); if (closefunc != NULL) (*closefunc)(fout); return; } errno = d = 0; while ((c = read(fileno(din), buf, bufsize)) > 0) { if ((d = local_write(fileno(fout), buf, c)) != c) break; bytes += c; if (hash && is_retr) { while (bytes >= hashbytes) { (void) putchar('#'); hashbytes += HASHBYTES; } (void) fflush(stdout); } if (tick && (bytes >= hashbytes) && is_retr) { (void) printf("\rBytes transferred: %ld", bytes); (void) fflush(stdout); while (bytes >= hashbytes) hashbytes += TICKBYTES; } } if (hash && bytes > 0) { if (bytes < HASHBYTES) (void) putchar('#'); (void) putchar('\n'); (void) fflush(stdout); } if (tick && is_retr) { (void) printf("\rBytes transferred: %ld\n", bytes); (void) fflush(stdout); } if (c < 0) { if (errno != EPIPE) perror("netin"); bytes = -1; } if (d < c) { if (d < 0) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); else fprintf(stderr, "%s: short write\n", local); } break; case TYPE_A: #if 0 /* ascii mode not supported for netflash */ if (restart_point) { register int i, n, ch; if (fseek(fout, 0L, L_SET) < 0) goto done; n = restart_point; for (i = 0; i++ < n;) { if ((ch = getc(fout)) == EOF) goto done; if (ch == '\n') i++; } if (fseek(fout, 0L, L_INCR) < 0) { done: fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); if (closefunc != NULL) (*closefunc)(fout); return; } } while ((c = getc(din)) != EOF) { if (c == '\n') bare_lfs++; while (c == '\r') { while (hash && (bytes >= hashbytes) && is_retr) { (void) putchar('#'); (void) fflush(stdout); hashbytes += HASHBYTES; } if (tick && (bytes >= hashbytes) && is_retr) { printf("\rBytes transferred: %ld", bytes); fflush(stdout); while (bytes >= hashbytes) hashbytes += TICKBYTES; } bytes++; if ((c = getc(din)) != '\n' || tcrflag) { if (ferror(fout)) goto break2; (void) putc('\r', fout); if (c == '\0') { bytes++; goto contin2; } if (c == EOF) goto contin2; } } (void) putc(c, fout); bytes++; contin2: ; } break2: if (hash && is_retr) { if (bytes < hashbytes) (void) putchar('#'); (void) putchar('\n'); (void) fflush(stdout); } if (tick && is_retr) { (void) printf("\rBytes transferred: %ld\n", bytes); (void) fflush(stdout); } if (bare_lfs) { printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); printf("File may not have transferred correctly.\n"); } if (ferror(din)) { if (errno != EPIPE) perror("netin"); bytes = -1; } if (ferror(fout)) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); #else printf("Netflash does not support ASCII downloads!\n"); bytes = -1; #endif 0 /* ascii mode not supported for netflash */ break; } if (closefunc != NULL) (*closefunc)(fout); (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); (void) gettimeofday(&stop, (struct timezone *)0); (void) fclose(din); /* closes data as well, so discard it */ data = -1; (void) getreply(0); if (bytes > 0 && is_retr) ptransfer("received", bytes, &start, &stop); return; abort: /* abort using RFC959 recommended IP,SYNC sequence */ (void) gettimeofday(&stop, (struct timezone *)0); if (oldintp) (void) signal(SIGPIPE, oldintp); (void) signal(SIGINT, SIG_IGN); if (!cpend) { code = -1; (void) signal(SIGINT, oldintr); return; } abort_remote(din); code = -1; if (closefunc != NULL && fout != NULL) (*closefunc)(fout); if (din) { (void) fclose(din); } if (data >= 0) { /* if it just got closed with din, again won't hurt */ (void) close(data); data = -1; } if (bytes > 0) ptransfer("received", bytes, &start, &stop); (void) signal(SIGINT, oldintr); }
void sendrequest(const char *cmd, char *local, char *remote, int printnames) { struct stat st; struct timeval start, stop; register int c, d; FILE *volatile fin, *volatile dout = 0; int (*volatile closefunc)(FILE *); void (*volatile oldintr)(int); void (*volatile oldintp)(int); volatile long bytes = 0, hashbytes = HASHBYTES; char buf[BUFSIZ], *bufp; const char *volatile lmode; #if 1 printf("%s(%d): sendrequest(cmd=%s,local=%s,remote=%s)\n", __FILE__, __LINE__, cmd, local, remote); #endif if (ftpverbose && printnames) { if (local && *local != '-') printf("local: %s ", local); if (remote) printf("remote: %s\n", remote); } #if 0 if (proxy) { proxtrans(cmd, local, remote); return; } #endif if (curtype != type) changetype(type, 0); closefunc = NULL; oldintr = NULL; oldintp = NULL; lmode = "w"; if (sigsetjmp(sendabort, 1)) { while (cpend) { (void) getreply(0); } if (data >= 0) { (void) close(data); data = -1; } if (oldintr) (void) signal(SIGINT,oldintr); if (oldintp) (void) signal(SIGPIPE,oldintp); code = -1; return; } oldintr = signal(SIGINT, abortsend); if (strcmp(local, "-") == 0) fin = stdin; else if (*local == '|') { oldintp = signal(SIGPIPE,SIG_IGN); fin = popen(local + 1, "r"); if (fin == NULL) { perror(local + 1); (void) signal(SIGINT, oldintr); (void) signal(SIGPIPE, oldintp); code = -1; return; } closefunc = pclose; } else { fin = fopen(local, "r"); if (fin == NULL) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); (void) signal(SIGINT, oldintr); code = -1; return; } closefunc = fclose; if (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG) { fprintf(stdout, "%s: not a plain file.\n", local); (void) signal(SIGINT, oldintr); fclose(fin); code = -1; return; } } if (initconn()) { (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); code = -1; if (closefunc != NULL) (*closefunc)(fin); return; } if (sigsetjmp(sendabort, 1)) goto abort; if (restart_point && (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { if (fseek(fin, (long) restart_point, 0) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); restart_point = 0; if (closefunc != NULL) (*closefunc)(fin); return; } if (command("REST %ld", (long) restart_point) != CONTINUE) { restart_point = 0; if (closefunc != NULL) (*closefunc)(fin); return; } restart_point = 0; lmode = "r+w"; } if (remote) { if (command("%s %s", cmd, remote) != PRELIM) { (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); if (closefunc != NULL) (*closefunc)(fin); return; } } else if (command("%s", cmd) != PRELIM) { (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); if (closefunc != NULL) (*closefunc)(fin); return; } dout = dataconn(lmode); if (dout == NULL) goto abort; (void) gettimeofday(&start, (struct timezone *)0); oldintp = signal(SIGPIPE, SIG_IGN); switch (curtype) { case TYPE_I: case TYPE_L: errno = d = 0; while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { bytes += c; for (bufp = buf; c > 0; c -= d, bufp += d) if ((d = local_write(fileno(dout), bufp, c)) <= 0) break; if (hash) { while (bytes >= hashbytes) { (void) putchar('#'); hashbytes += HASHBYTES; } (void) fflush(stdout); } if (tick && (bytes >= hashbytes)) { printf("\rBytes transferred: %ld", bytes); (void) fflush(stdout); while (bytes >= hashbytes) hashbytes += TICKBYTES; } } if (hash && (bytes > 0)) { if (bytes < HASHBYTES) (void) putchar('#'); (void) putchar('\n'); (void) fflush(stdout); } if (tick) { (void) printf("\rBytes transferred: %ld\n", bytes); (void) fflush(stdout); } if (c < 0) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); if (d < 0) { if (errno != EPIPE) perror("netout"); bytes = -1; } break; case TYPE_A: while ((c = getc(fin)) != EOF) { if (c == '\n') { while (hash && (bytes >= hashbytes)) { (void) putchar('#'); (void) fflush(stdout); hashbytes += HASHBYTES; } if (tick && (bytes >= hashbytes)) { (void) printf("\rBytes transferred: %ld", bytes); (void) fflush(stdout); while (bytes >= hashbytes) hashbytes += TICKBYTES; } if (ferror(dout)) break; (void) putc('\r', dout); bytes++; } (void) putc(c, dout); bytes++; /* if (c == '\r') { */ /* (void) putc('\0', dout); (* this violates rfc */ /* bytes++; */ /* } */ } if (hash) { if (bytes < hashbytes) (void) putchar('#'); (void) putchar('\n'); (void) fflush(stdout); } if (tick) { (void) printf("\rBytes transferred: %ld\n", bytes); (void) fflush(stdout); } if (ferror(fin)) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); if (ferror(dout)) { if (errno != EPIPE) perror("netout"); bytes = -1; } break; } (void) gettimeofday(&stop, (struct timezone *)0); if (closefunc != NULL) (*closefunc)(fin); (void) fclose(dout); /* closes data as well, so discard it */ data = -1; (void) getreply(0); (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); if (bytes > 0) ptransfer("sent", bytes, &start, &stop); return; abort: (void) gettimeofday(&stop, (struct timezone *)0); (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); if (!cpend) { code = -1; return; } if (dout) { (void) fclose(dout); } if (data >= 0) { /* if it just got closed with dout, again won't hurt */ (void) close(data); data = -1; } (void) getreply(0); code = -1; if (closefunc != NULL && fin != NULL) (*closefunc)(fin); if (bytes > 0) ptransfer("sent", bytes, &start, &stop); }
char * hookup(char *host, int port) { register struct hostent *hp = 0; int s, tos; socklen_t len; static char hostnamebuf[256]; memset(&hisctladdr, 0, sizeof(hisctladdr)); if (inet_aton(host, &hisctladdr.sin_addr)) { hisctladdr.sin_family = AF_INET; strncpy(hostnamebuf, host, sizeof(hostnamebuf)); hostnamebuf[sizeof(hostnamebuf)-1]=0; } else { hp = gethostbyname(host); if (hp == NULL) { fprintf(stderr, "ftp: %s: ", host); #ifndef EMBED herror((char *)NULL); #endif code = -1; return((char *) 0); } hisctladdr.sin_family = hp->h_addrtype; if (hp->h_length > (int)sizeof(hisctladdr.sin_addr)) { hp->h_length = sizeof(hisctladdr.sin_addr); } memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length); (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); hostnamebuf[sizeof(hostnamebuf)-1] = 0; } hostname = hostnamebuf; s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); if (s < 0) { perror("ftp: socket"); code = -1; return (0); } hisctladdr.sin_port = port; while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { if (hp && hp->h_addr_list[1]) { int oerrno = errno; fprintf(stderr, "ftp: connect to address %s: ", inet_ntoa(hisctladdr.sin_addr)); errno = oerrno; perror((char *) 0); hp->h_addr_list++; memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length); fprintf(stdout, "Trying %s...\n", inet_ntoa(hisctladdr.sin_addr)); (void) close(s); s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); if (s < 0) { perror("ftp: socket"); code = -1; return (0); } continue; } perror("ftp: connect"); code = -1; goto bad; } len = sizeof (myctladdr); if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { perror("ftp: getsockname"); code = -1; goto bad; } #ifdef IP_TOS tos = IPTOS_LOWDELAY; if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) perror("ftp: setsockopt TOS (ignored)"); #endif cin = fdopen(s, "r"); cout = fdopen(s, "w"); if (cin == NULL || cout == NULL) { fprintf(stderr, "ftp: fdopen failed.\n"); if (cin) (void) fclose(cin); if (cout) (void) fclose(cout); code = -1; goto bad; } if (ftpverbose) printf("Connected to %s.\n", hostname); if (getreply(0) > 2) { /* read startup message from server */ if (cin) (void) fclose(cin); if (cout) (void) fclose(cout); code = -1; goto bad; } #ifdef SO_OOBINLINE { int on = 1; if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0 && debug) { perror("ftp: setsockopt"); } } #endif /* SO_OOBINLINE */ return (hostname); bad: (void) close(s); return ((char *)0); }