home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-17 | 60.7 KB | 2,602 lines |
- /* FTP client (interactive user) code */
- #define LINELEN 128 /* Length of command buffer */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <stdarg.h>
- #include <ctype.h>
- #include "alarm.h"
- #include "global.h"
- #include "mbuf.h"
- #include "domain.h"
- #include "netuser.h"
- #include "icmp.h"
- #include "timer.h"
- #include "tcp.h"
- #include "ftp.h"
- #include "session.h"
- #include "cmdparse.h"
- #include "misc.h"
- #include "Terminal.h"
- #include "vterm.h"
- #include "bbc.h"
- #include "files.h"
- #include "pathent.h"
- #include "var.h"
-
- #include "os.h"
- #include "swis.h"
-
- extern os_error *create_path(char *path, int size, int type);
- static int create_fetchedfile(struct ftp *ftp, char *localname, char *remotename, char *givenname);
- static int create_localfile(struct ftp *ftp, char *localname, int filetype);
- extern char *fttoa(int t);
-
- extern struct session *current;
- struct session *current_ftp;
- extern char nospace[];
- extern char badhost[];
- static char notsess[] = "Not an FTP session!\r\n";
- static char cantwrite[] = "Can't write %s\r\n";
- static char cantread[] = "Can't read %s\r\n";
- static char nomemforop[] = "Insufficient memory for this operation\r\n";
-
- static int dotrace(int, char **);
- static int doprompt(int, char **);
- static int dosite(int, char **);
- static int donothing(int, char **);
- static int doftpquit(int, char **);
- static int dowinclose(int, char **);
- static int dowinopen(int, char **);
- static int doftpcd(int, char **);
- static int domkdir(int, char **);
- static int dormdir(int, char **);
- static int dodelete(int, char **);
- static int doascii(int, char **);
- static int dobinary(int, char **);
- static int dotype(int, char **);
- static int doget(int, char **);
- static int doreget(int, char **);
- static int domget(int, char **);
- static int dobatch(int, char **);
- static int dopath(int, char **);
- static int doquote(int, char **);
- static int doview(int, char **);
- static int dohash(int, char **);
- static int dolist(int, char **);
- static int dols(int, char **);
- static int doput(int, char **);
- static int dopwd(int, char **);
- static int doftpcdup(int, char **);
- static int dospool(int, char **);
-
- static void doreply(struct ftp *);
- static void ftpsetup(struct ftp *, void (*)(), void (*)(), void (*)());
- static void ftpccs(struct tcb *, char, char);
- static void ftpcds(struct tcb *, char, char);
- static int sndftpmsg(struct ftp *, char *, ...);
- static void prompt(struct ftp *ftp);
- static int batch_ftp(struct ftp *ftp);
- static int batch_open(struct ftp *ftp, char *batch);
- static int mprocess(struct ftp *ftp);
-
- static int doopttype(int, char **);
- static int doopthash(int, char **);
- static int dooptpath(int, char **);
- static int dooptwinsz(int, char **);
- static int doopttrace(int, char **);
- static int dooptprompt(int, char **);
-
- void ftp_mpcleanup(struct ftp *ftp);
-
- struct cmds ftpabort[] = {
- "", donothing, 0, NULLCHAR, NULLCHAR,
- "abort", doabort, 0, NULLCHAR, NULLCHAR,
- "hash", dohash, 2, "hash lumpsize", NULLCHAR,
- "prompt", doprompt, 0, NULLCHAR, NULLCHAR,
- "spool", dospool, 0, "spool [open [<file>]] | [pause] | [continue] | [pause]", NULLCHAR,
- "trace", dotrace, 0, NULLCHAR, NULLCHAR,
- "winclose", dowinclose, 0, "winclose", NULLCHAR,
- "winopen", dowinopen, 0, "winopen", NULLCHAR,
- NULLCHAR, NULLFP, 0, "Only valid command is \"abort\"", NULLCHAR,
- };
-
- struct cmds ftpcmds[] = {
- "", donothing, 0, NULLCHAR, NULLCHAR,
- "ascii", doascii, 0, NULLCHAR, NULLCHAR,
- "abort", doabort, 0, NULLCHAR, NULLCHAR,
- "binary", dobinary, 0, NULLCHAR, NULLCHAR,
- "cd", doftpcd, 2, "cd <directory>", NULLCHAR,
- "cdup", doftpcdup, 0, NULLCHAR, NULLCHAR,
- "delete", dodelete, 0, NULLCHAR, NULLCHAR,
- "dir", dolist, 0, NULLCHAR, NULLCHAR,
- "list", dolist, 0, NULLCHAR, NULLCHAR,
- "get", doget, 2, "get remotefile <localfile>", NULLCHAR,
- "hash", dohash, 2, "hash lumpsize", NULLCHAR,
- "image", dobinary, 0, NULLCHAR, NULLCHAR,
- "ls", dols, 0, NULLCHAR, NULLCHAR,
- "mget", domget, 0, "mget <filelist>", NULLCHAR,
- "mkdir", domkdir, 2, "mkdir <directory>", NULLCHAR,
- "nlst", dols, 0, NULLCHAR, NULLCHAR,
- "path", dopath, 0, "path [<path process options>|off|default]", NULLCHAR,
- "prompt", doprompt, 0, NULLCHAR, NULLCHAR,
- "put", doput, 2, "put localfile <remotefile>", NULLCHAR,
- "pwd", dopwd, 0, NULLCHAR, NULLCHAR,
- "quote", doquote, 0, "quote <command>", NULLCHAR,
- "reget", doreget, 2, "reget remotefile <localfile>", NULLCHAR,
- "rmdir", dormdir, 2, "rmdir <directory>", NULLCHAR,
- "site", dosite, 0, "site <command>", NULLCHAR,
- "source", dobatch, 0, "source <ftp command file>", NULLCHAR,
- "spool", dospool, 0, "spool [open [<file>]] | [pause] | [continue] | [pause]", NULLCHAR,
- "trace", dotrace, 0, NULLCHAR, NULLCHAR,
- "type", dotype, 0, NULLCHAR, NULLCHAR,
- "view", doview, 1, "view remotefile", NULLCHAR,
- "winclose", dowinclose, 0, "winclose", NULLCHAR,
- "winopen", dowinopen, 0, "winopen", NULLCHAR,
- "quit", doftpquit, 0, "quit", NULLCHAR,
- "bye", doftpquit, 0, "bye", NULLCHAR,
- NULLCHAR, NULLFP, 0, NULLCHAR, NULLCHAR,
- };
-
- struct cmds ftpopts[] = {
- "type", doopttype, 0, NULLCHAR, NULLCHAR,
- "hash", doopthash, 0, NULLCHAR, NULLCHAR,
- "path", dooptpath, 0, NULLCHAR, NULLCHAR,
- "prompt", dooptprompt, 0, NULLCHAR, NULLCHAR,
- "trace", doopttrace, 0, NULLCHAR, NULLCHAR,
- "winsize", dooptwinsz, 0, NULLCHAR, NULLCHAR,
- NULLCHAR, NULLFP, 0, "Only valid command is \"abort\"", NULLCHAR,
- };
-
- #define PROMPT_NODIR 0
- #define PROMPT_SHORTDIR 1
- #define PROMPT_LONGDIR 2
-
- extern varlist global_vars;
-
- /*
- * Default options set by ftpopt commands
- */
- static pathent_str *default_pathopts = PATH_OFF;
- static int default_win_xv = 80;
- static int default_win_yv = 24;
- static int default_win_xe = 80;
- static int default_win_ye = 24;
- static int default_trace = 0;
- static int default_prompt = 0;
- static int default_hash = 0;
- static int default_type = ASCII_TYPE;
-
- /*
- * Auto login FTP
- */
- int doaftp(int argc, char **argv)
- {
- extern char ftphostfile[];
-
- FILE *fp;
- int n, line;
- char *p;
- char ln[256];
- char buf[256];
- long pos, defpos = -1L;
- struct ftp *ftp;
-
- char missing[] = "Missing %s in FTPHosts file at line %d\r\n";
-
- char *hostname = NULL; /* Host name from command or Accounts file */
- char *username = NULL; /* username from accounts file */
- char *password = NULL; /* password from accounts file */
- char *source = NULL; /* Source file from accounts file */
- char *menu = NULL; /* Menu from accounts file */
- char *directory = NULL; /* Default directory */
-
- if (fp = fopen(ftphostfile, "r"), fp==NULL)
- {
- cwprintf(NULL, "FTP hosts file \"%s\" not found.\r\n", ftphostfile);
- return 1;
- }
- /*
- bbc_vdu(4);
- bbc_vdu(26);
- bbc_vdu(30);
- */
- line = 0;
- pos = 0L;
- n = strlen(argv[1]);
-
- /*
- printf("searching for %s\n", argv[1]);
- */
- while (fgets(ln, 256, fp)!=NULL)
- {
- ++line;
- /*
- * Skip parameters or command for other entries...
- */
- /*
- printf("Checking %s", buf);
- */
-
- if (*ln=='#' || *ln==' ' || *ln=='\t' || *ln=='\n')
- continue;
-
- var_translate(global_vars, ln, 0, buf, 256);
-
- if (!strncmp(buf, argv[1], n) && buf[n]==':')
- {
- p = buf+n+1;
- goto found;
- }
- else if (!strncmp(buf, "default", 7) && buf[7]==':')
- defpos = pos;
- pos = ftell(fp);
- }
-
- /*
- printf("Checking for default\n");
- */
- /*
- * Not found, use default entry for login etc
- */
- if (defpos<0)
- {
- /*
- * No default - print error and return
- */
- cwprintf(NULL, "No entry found for %s, and no default either\r\n", argv[1]);
- fclose(fp);
- return 1;
- }
- else
- {
- /*
- * Position at default entry and refill the buffer
- * and assume that the given parameter was the hostname.
- */
- fseek(fp, defpos, SEEK_SET);
- fgets(ln, 256, fp);
- var_translate(global_vars, ln, 0, buf, 256);
- hostname = strdup(argv[1]);
- n = 7; /* length of "default" */
- }
-
-
- found:
- p = strtok(buf+n+1, " \t\n");
-
- for (;;)
- {
- if (p==NULL)
- {
- /*
- printf("Get another line...\n");
- */
- while (p = fgets(ln, 256, fp), p!=NULL && (*ln=='#' || *ln=='\n'))
- {
- /*
- printf("Read %s",buf);
- */
- ++line;
- }
- /*
- * If end of file, or start of next entry
- */
- if (p==NULL || (*ln!=' ' && *ln!='\t'))
- break;
-
- var_translate(global_vars, ln, 0, buf, 256);
-
- if (p = strtok(buf, " \t\n"), p==NULL)
- break;
- }
-
- /*
- printf("p = %s\n", (p)?p:"<null>");
- */
-
- if (!strcmp(p, "host"))
- {
- if (p = strtok(NULL, " \t\n"), p==NULL)
- {
- cwprintf(NULL, missing, "host name", line);
- goto error;
- }
- else
- hostname = strdup(p);
- }
- else if (!strcmp(p, "login"))
- {
- if (p = strtok(NULL, " \t\n"), p==NULL)
- {
- cwprintf(NULL, missing, "login name", line);
- goto error;
- }
- else
- username = strdup(p);
- }
- else if (!strcmp(p, "password"))
- {
- if (p = strtok(NULL, " \t\n"), p==NULL)
- {
- cwprintf(NULL, missing, "password", line);
- goto error;
- }
- else
- password = strdup(p);
- }
- else if (!strcmp(p, "source"))
- {
- if (p = strtok(NULL, " \t\n"), p==NULL)
- {
- cwprintf(NULL, missing, "command file name", line);
- goto error;
- }
- else
- source = strdup(p);
- }
- else if (!strcmp(p, "directory"))
- {
- if (p = strtok(NULL, " \t\n"), p==NULL)
- {
- cwprintf(NULL, missing, "directory name", line);
- goto error;
- }
- else
- directory = strdup(p);
- }
- else if (!strcmp(p, "menu"))
- {
- if (p = strtok(NULL, " \t\n"), p==NULL)
- {
- cwprintf(NULL, missing, "menu file name", line);
- goto error;
- }
- else
- menu = strdup(p);
- }
- p = strtok(NULL, " \t\n");
- }
-
- fclose(fp);
- fp = NULL;
-
- /*
- printf("hostname = %s\n", (hostname)?hostname:"<null>");
- printf("login = %s\n", (username)?username:"<null>");
- printf("password = %s\n", (password)?password:"<null>");
- printf("menu = %s\n", (menu)?menu:"<null>");
- printf("source = %s\n", (source)?source:"<null>");
- */
- /*
- * Substitute new hostname into original command
- */
- if (argv[1] = hostname, hostname==NULL)
- {
- cwprintf(NULL, "No hostname specified\r\n");
- goto error;
- }
-
- if (doftp(2, argv)==0)
- {
- free(hostname);
- ftp = current_ftp->cb.ftp;
- ftp->username = username;
- ftp->password = password;
- ftp->cd = directory;
-
- if (menu!=NULL)
- {
- vterm_attach_macros(ftp->window->vt, menu);
- free(menu);
- }
-
- if (argc>2 && *argv[2]!='>')
- {
- if (source)
- ftp->nextsource = strdup(argv[2]);
- else
- source = strdup(argv[2]);
- }
-
- if (source)
- {
- if (!batch_open(ftp, source) && ftp->nextsource!=NULL)
- {
- batch_open(ftp, ftp->nextsource);
- free(ftp->nextsource);
- ftp->nextsource = NULL;
- }
- free(source);
- }
-
- if (argc>2 && *argv[argc-1]=='>')
- {
- char *s[3];
- s[0] = "spool";
- s[1] = "open";
- s[2] = argv[argc-1]+1;
- dospool(3, s);
- }
-
- return 0;
- }
-
- error:
- if (fp!=NULL)
- fclose(fp);
- if (hostname)
- free(hostname);
- if (username)
- free(username);
- if (password)
- free(password);
- if (menu)
- free(menu);
- if (source)
- free(source);
- if (directory)
- free(directory);
-
- return 1;
- }
-
- /* Handle top-level FTP command */
- int doftp(int argc, char **argv)
- {
- int used_args;
- struct session *s;
- struct ftp *ftp;
- struct tcb *tcb;
- struct socket lsocket,fsocket;
-
- lsocket.address = ip_addr;
- lsocket.port = lport++;
-
- if ((fsocket.address = resolve(argv[1])) == 0)
- {
- cwprintf(NULL, badhost,argv[1]);
- return 1;
- }
-
- if (argc<3)
- {
- fsocket.port = FTP_PORT;
- used_args = 2;
- }
- else
- {
- if (*argv[2]!='\\')
- {
- fsocket.port = atoi(argv[2]);
- used_args = 3;
- }
- else
- {
- fsocket.port = FTP_PORT;
- used_args = 2;
- }
- }
- /* Allocate a session control block */
- if ((s = newsession()) == NULLSESSION)
- {
- cwprintf(NULL, "Too many sessions\r\n");
- return 1;
- }
- if ((s->name = malloc((unsigned)strlen(argv[1])+1)) != NULLCHAR)
- strcpy(s->name,argv[1]);
- s->type = FTP;
- s->parse = (void(*)())ftpparse;
-
- /* Allocate an FTP control block */
- if ((ftp = ftp_create(LINELEN)) == NULLFTP)
- {
- s->type = FREE;
- cwprintf(NULL, nospace);
- return 1;
- }
-
- ftp->window = Window_Open(s, "FTP", term_SIXTEEN | term_CARET);
-
- /* ftpopt winsize */
- vterm_resize(ftp->window->vt, default_win_xe, default_win_ye);
- vterm_visible(ftp->window->vt, default_win_xv, default_win_yv);
-
- vterm_parse(ftp->window->vt, argc-used_args, &argv[used_args]);
-
- current = s;
- current_ftp = s;
- ftp->state = STARTUP_STATE;
- s->cb.ftp = ftp; /* Downward link */
- ftp->session = s; /* Upward link */
- s->window = ftp->window;
- ftp->session->echo = TRUE;
- ftp->trace = default_trace; /* ftpopt trace */
- ftp->prompt = default_prompt; /* ftpopt prompt */
- ftp->hash = default_hash; /* ftpopt hash */
- ftp->pathopts = duppathent(default_pathopts); /* ftpopt path */
- ftp->flags = 0;
-
- /* Now open the control connection */
- tcb = open_tcp(&lsocket, &fsocket, TCP_ACTIVE, 0, (void(*)())ftpccr, NULLVFP, (void(*)())ftpccs, 0,( char *)ftp);
- ftp->control = tcb;
- go(s);
- return 0;
- }
-
- /* Parse user FTP commands */
- void ftpparse(struct session *active, char *line, int16 len)
- {
- struct mbuf *bp;
- extern struct cmds cmds[];
- if (active == NULL)
- active = current;
- current_ftp = active;
-
- /* direct '*' prefixed commands to main command window */
- if (*line=='*')
- {
- cmdparse(cmds, line+1, NULL);
- prompt(active->cb.ftp);
- return;
- }
-
- switch(active->cb.ftp->state)
- {
- case RECEIVING_STATE1:
- case SENDING_FILE_STATE1:
- case RECEIVING_STATE2:
- case SENDING_FILE_STATE2:
- /* The only command allowed in data transfer state is ABORT */
- if (cmdparse(ftpabort, line, active->window) == -1)
- {
- cwprintf(active->window, "Transfer in progress; only ABORT is acceptable\r\n");
- }
- break;
- case COMMAND_STATE:
- /* Save it now because cmdparse modifies the original */
- bp = qdata(line,len);
- if (cmdparse(ftpcmds, line, active->window) == -1)
- {
- /* Send it direct */
- if (bp != NULLBUF)
- {
- send_tcp(active->cb.ftp->control,bp);
- active->cb.ftp->replycount++;
- }
- else
- cwprintf(active->window, nospace);
- }
- else
- {
- free_p(bp);
- }
- break;
- case STARTUP_STATE: /* Startup up autologin */
- cwprintf(active->window, "Not connected yet, ignoring %s\r\n",line);
- break;
- case USER_STATE: /* Got the user name */
- line[len] = '\0';
- sndftpmsg(active->cb.ftp,"USER %s",line);
- break;
- case PASS_STATE: /* Got the password */
- cooked();
- active->raw = FALSE;
- vterm_setflags(active->window->vt,
- /* Clear */ VTSW_CHAT|VTSW_LINE|VTSW_NEWLINE|VTSW_WRAP|VTSW_ECHO,
- /* Set */ VTSW_LINE|VTSW_NEWLINE|VTSW_WRAP|VTSW_ECHO );
- line[len] = '\0';
- sndftpmsg(active->cb.ftp,"PASS %s",line);
- break;
- }
- }
-
- /* Handle null line to avoid trapping on first command in table */
- static int donothing(int argc, char **argv)
- {
- argc = argc;
- argv = argv;
- return 0;
- }
-
- /* Spool control */
- static int dospool(int argc, char **argv)
- {
- int a = 0;
- struct ftp *ftp;
-
- char filename[256];
-
- ftp = current_ftp->cb.ftp;
-
- if (argc<2)
- {
- switch(vterm_spool(ftp->window->vt, NULL, 0))
- {
- case 0:
- cwprintf(ftp->window, "Closed\r\n");
- break;
- case 1:
- cwprintf(ftp->window, "Open\r\n");
- break;
- case 2:
- cwprintf(ftp->window, "Paused\r\n");
- break;
- }
- }
- else
- {
- if (!strncmp(argv[1], "open", strlen(argv[1])))
- {
- if (argc<3)
- a = vterm_spool(ftp->window->vt, "*", 1);
- else
- {
- strcpy(filename, argv[2]);
- if (create_localfile(ftp, filename, -1))
- a = vterm_spool(ftp->window->vt, argv[2], 1);
- else
- a = 0;
- }
- }
- else if (!strncmp(argv[1], "pause", strlen(argv[1])))
- a = vterm_spool(ftp->window->vt, NULL, 2);
- else if (!strncmp(argv[1], "continue", strlen(argv[1])))
- a = vterm_spool(ftp->window->vt, NULL, 3);
- else if (!strncmp(argv[1], "close", strlen(argv[1])))
- a = vterm_spool(ftp->window->vt, NULL, 1);
- else
- {
- /* Unknown command - complain and return */
- cwprintf(ftp->window, "Spool commands are open|close|pause|continue\r\n");
- return 1;
- }
- /* process spool command answer */
- switch (a)
- {
- case 1:
- cwprintf(ftp->window, "Spooling to %s\r\n", (argc<3 || *argv[2]=='*')?"temp file":filename);
- break;
- case 0:
- cwprintf(ftp->window, "Can't open file %s\r\n", (argc<3 || *argv[2]=='*')?"temp file":filename);
- break;
- case -1:
- cwprintf(ftp->window, "Spool allready open\r\n");
- break;
- case -2:
- cwprintf(ftp->window, "Spool allready paused\r\n");
- break;
- case -3:
- cwprintf(ftp->window, "Spool not paused\r\n");
- break;
- case -4:
- cwprintf(ftp->window, "Not spooling\r\n");
- break;
- }
- }
- prompt(ftp);
- return 0;
- }
-
- /*
- * Set default trace level
- */
- static int dotrace(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
-
- if (argc<2)
- cwprintf(ftp->window, "FTP trace level is %d\r\n", ftp->trace);
- else
- ftp->trace = atoi(argv[1]);
-
- prompt(ftp);
- return 0;
- }
-
- /*
- * Set default prompt type
- */
- static int doprompt(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
-
- if (argc<2)
- {
- char *type;
- switch (ftp->prompt)
- {
- case PROMPT_SHORTDIR:
- type = "Short directory";
- break;
- case PROMPT_LONGDIR:
- type = "Full directory";
- break;
- default:
- type = "No directory";
- }
- cwprintf(ftp->window, "FTP prompt type: %s\r\n", type);
- }
- else
- {
- if (!strncmp(argv[1], "nodir", strlen(argv[1])))
- ftp->prompt = PROMPT_NODIR;
- else if (!strncmp(argv[1], "short", strlen(argv[1])))
- ftp->prompt = PROMPT_SHORTDIR;
- else if (!strncmp(argv[1], "long", strlen(argv[1])))
- ftp->prompt = PROMPT_LONGDIR;
- else if (*argv[1]=='=')
- cwprintf(ftp->window, "Reply counter: %d\r\n", ftp->replycount);
- else if (*argv[1]=='+')
- cwprintf(ftp->window, "Reply counter: %d\r\n", ftp->replycount++);
- else if (*argv[1]=='-')
- cwprintf(ftp->window, "Reply counter: %d\r\n", ftp->replycount--);
- else
- cwprintf(ftp->window, "Unknown prompt type. Valid prompts are: nodir short long\r\n");
- }
- prompt(ftp);
- return 0;
- }
-
- static int dowinclose(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current_ftp->cb.ftp;
- vterm_close(current_ftp->window->vt);
- current_ftp->window->Flags.flags.closing = 1;
- prompt(ftp);
-
- return 0;
- }
-
- static int dowinopen(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current_ftp->cb.ftp;
- vterm_open(current_ftp->window->vt);
- current_ftp->window->Flags.flags.closing = 0;
- prompt(ftp);
-
- return 0;
- }
-
- static int doftpquit(int argc, char **argv)
- {
- int a;
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current_ftp->cb.ftp;
- a = sndftpmsg(ftp,"QUIT\r\n");
- prompt(ftp);
-
- return a;
- }
-
-
- /* Translate 'cd' to 'cwd' for convenience */
- static int doftpcd(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current_ftp->cb.ftp;
- ftp->flags |= (FTP_TRAP_257|FTP_SUPP_257);
- sndftpmsg(ftp,"CWD %s\r\n",argv[1]);
- return sndftpmsg(ftp,"PWD\r\n");
- }
-
- /* Translate 'cd' to 'cwd' for convenience */
- static int doftpcdup(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current_ftp->cb.ftp;
- sndftpmsg(ftp,"CDUP\r\n");
- ftp->flags |= (FTP_TRAP_257|FTP_SUPP_257);
- return sndftpmsg(ftp,"PWD\r\n");
- }
-
- /* Translate 'cd' to 'cwd' for convenience */
- static int dopwd(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current_ftp->cb.ftp;
- ftp->flags |= FTP_TRAP_257;
- return sndftpmsg(ftp,"PWD\r\n");
- }
-
- /* Translate 'mkdir' to 'xmkd' for convenience */
- static int domkdir(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current_ftp->cb.ftp;
- return sndftpmsg(ftp,"XMKD %s\r\n",argv[1]);
- }
-
- static int dohash(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current_ftp->cb.ftp;
- ftp->hash = atoi(argv[1]);
- ftp->last = 0;
-
- prompt(ftp);
- return(0);
- }
-
- /* Translate 'rmdir' to 'xrmd' for convenience */
- static int dormdir(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current_ftp->cb.ftp;
- return sndftpmsg(ftp,"XRMD %s\r\n",argv[1]);
- }
-
- static int dodelete(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current_ftp->cb.ftp;
- return sndftpmsg(ftp,"DELE %s\r\n",argv[1]);
- }
-
- static int dobinary(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current_ftp->cb.ftp;
- ftp->type = IMAGE_TYPE;
- sndftpmsg(ftp,"TYPE I\r\n");
- return(0);
- }
-
- static int doascii(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current_ftp->cb.ftp;
- ftp->type = ASCII_TYPE;
- sndftpmsg(ftp,"TYPE A\r\n");
-
- return(0);
- }
-
- /* Handle "type" command from user */
- static int dotype(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
- if (argc < 2)
- {
- switch(ftp->type)
- {
- case IMAGE_TYPE:
- cwprintf(ftp->window, "Image\r\n");
- break;
- case ASCII_TYPE:
- cwprintf(ftp->window, "Ascii\r\n");
- break;
- }
- return 0;
- }
- switch(*argv[1])
- {
- case 'i':
- case 'b':
- ftp->type = IMAGE_TYPE;
- sndftpmsg(ftp,"TYPE I\r\n");
- break;
- case 'a':
- ftp->type = ASCII_TYPE;
- sndftpmsg(ftp,"TYPE A\r\n");
- break;
- case 'l':
- ftp->type = IMAGE_TYPE;
- sndftpmsg(ftp,"TYPE L %s\r\n",argv[2]);
- break;
- default:
- cwprintf(ftp->window, "Invalid type %s\r\n",argv[1]);
- return 1;
- }
- return 0;
- }
-
- /* Verbatim command to server */
- static int doquote(int argc, char **argv)
- {
- char localname[256];
- register struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
- if (ftp == NULLFTP)
- {
- cwprintf(ftp->window, notsess);
- return 1;
- }
-
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->restart = 0;
-
- ftp->fp = NULLFILE;
-
- if (argc < 3)
- {
- ftp->fp = stdout;
- }
- else
- {
- strcpy(localname, argv[2]);
- if (!create_localfile(ftp, localname, 0xfff))
- return 1;
-
- /* Set variable to name of most recent file */
- var_create_string(global_vars, "ftp_list", 0, localname);
-
- if ((ftp->fp = fopen(localname, "w")), ftp->fp == NULLFILE)
- {
- cwprintf(ftp->window, cantwrite, localname);
- return 1;
- }
- }
-
- ftp->state = RECEIVING_STATE1;
- ftp->expected_size = 0;
- ftp->start_time = alarm_timenow () ;
- if ( ftp->type == IMAGE_TYPE )
- {
- ftp->type = IMAGE_PENDING ;
- sndftpmsg(ftp,"TYPE A\r\n");
- }
- ftpsetup(ftp,(void(*)())ftpdr,NULLVFP,(void(*)())ftpcds);
- /* Generate the command to start the transfer */
- return sndftpmsg(ftp,"%s\r\n",argv[1]);
- }
-
- static int dosite(int argc, char **argv)
- {
- int i;
- char buf[512];
- char *p = buf;
- struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
-
- for (i=1; i<argc; i++)
- p += sprintf(p, "%s%s",(p==buf)?"":" ", argv[i]);
-
- return sndftpmsg(ftp,"%s\r\n",buf);
- }
-
-
- /* Set current path processing options */
- static int dopath(int argc, char **argv)
- {
- int i, n;
- struct ftp *ftp;
- char opts[256];
- char *p;
- pathent_str *pe;
-
- ftp = current_ftp->cb.ftp;
-
- if (ftp == NULLFTP)
- {
- cwprintf(NULL, notsess);
- return 1;
- }
-
- if (argc>1)
- {
- if ((argc==2) && !strncmp(argv[1], "off", strlen(argv[1])))
- {
- delpathent(ftp->pathopts);
- ftp->pathopts = PATH_OFF;
- }
- else if ((argc==2) && !strncmp(argv[1], "auto", strlen(argv[1])))
- {
- delpathent(ftp->pathopts);
- ftp->pathopts = PATH_DEF;
- }
- else if ((argc==2) && !strncmp(argv[1], "type", strlen(argv[1])))
- {
- delpathent(ftp->pathopts);
- ftp->pathopts = PATH_TYPE;
- }
- else if ((argc>=2) && !strncmp(argv[1], "test", strlen(argv[1])))
- {
- int filetype;
- char filename[256];
-
- if (pathmap(argv[2], filename, &filetype, ftp->pathopts))
- cwprintf(ftp->window, "%s (%s)\r\n", filename, fttoa(filetype));
- else
- cwprintf(ftp->window, "No convertion applicable\r\n");
- }
- else
- {
- /* Reconstrunct original path command */
- *opts = '$';
- p = opts+1;
- for (i=1; i<argc; i++)
- {
- n = sprintf(p, " %s", argv[i]);
- p += n;
- }
- if (pe = getpathent(opts), pe!=NULL)
- {
- delpathent(ftp->pathopts);
- ftp->pathopts = pe;
- }
- else
- {
- cwprintf(ftp->window, "Parse error in path options.\r\n");
- prompt(ftp);
- return 1;
- }
- }
- }
- else
- {
- if (ftp->pathopts == PATH_OFF)
- cwprintf(ftp->window, "Path processing off\r\n");
- else if (ftp->pathopts == PATH_DEF)
- cwprintf(ftp->window, "Auto path processing by extension\r\n");
- else
- {
- cwprintf(ftp->window, "Preset path processing:\r\n");
- cwprintf(ftp->window, " Path : %s\r\n", (ftp->pathopts->path)?ftp->pathopts->path:"<none>");
- cwprintf(ftp->window, " Exts :");
- for (n=0; n<ftp->pathopts->numexts; n++)
- cwprintf(ftp->window, " %s", ftp->pathopts->exts[n]);
- cwprintf(ftp->window, "\r\n");
- cwprintf(ftp->window, " On : %s\r\n", pe_optflagstostr(ftp->pathopts->setopts, opts) );
- cwprintf(ftp->window, " Off : %s\r\n", pe_optflagstostr(ftp->pathopts->clropts | (1<<31), opts) );
- cwprintf(ftp->window, " Type : %s\r\n", fttoa(ftp->pathopts->filetype));
- cwprintf(ftp->window, "\r\n");
- }
- }
-
- prompt(ftp);
- return 0;
- }
-
-
- /*
- * Start processing a batch file.
- */
- static int dobatch(int argc, char **argv)
- {
- int a;
- struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
-
- if (ftp == NULLFTP)
- {
- cwprintf(NULL, notsess);
- return 1;
- }
-
- if (ftp->batch!=NULL)
- {
- cwprintf(ftp->window, "Batch allready in progress.\r\n");
- return 1;
- }
-
- if (argc<2)
- {
- cwprintf(ftp->window, "No batch in progress.\r\n");
- return 0;
- }
-
- if (a = batch_open(ftp, argv[1]), a==0)
- cwprintf(ftp->window, "Cant find batch file \"%s\".\r\n", argv[1]);
-
- prompt(ftp);
- return a;
- }
-
- static int batch_open(struct ftp *ftp, char *batch)
- {
- extern char scripts[];
- char file[256];
-
- if (strpbrk(batch, "@&%$:<>"))
- sprintf(file, "%s", batch);
- else
- sprintf(file, "%s.%s", scripts, batch);
- if (ftp->batch = fopen(file, "r"), ftp->batch!=NULL)
- return 1;
-
- sprintf(file, "%s%s", RESROOT, batch);
- if (ftp->batch = fopen(file, "r"), ftp->batch!=NULL)
- return 1;
-
- sprintf(file, "%s^.%s", RESROOT, batch);
- if (ftp->batch = fopen(file, "r"), ftp->batch!=NULL)
- return 1;
-
- sprintf(file, "@.%s", batch);
- if (ftp->batch = fopen(file, "r"), ftp->batch!=NULL)
- return 1;
-
- sprintf(file, "$.%s", batch);
- if (ftp->batch = fopen(file, "r"), ftp->batch!=NULL)
- return 1;
-
- cwprintf(ftp->window, "Cant find batch file \"%s\".\r\n", batch);
- return 0;
- }
-
-
- /* Start receive transfer. Syntax: get <remote name> [<local name>] */
- static int doget(int argc, char **argv)
- {
- char *remotename, localname[256];
- register struct ftp *ftp;
- char *mode;
-
- ftp = current_ftp->cb.ftp;
- if (ftp == NULLFTP)
- {
- cwprintf(NULL, notsess);
- return 1;
- }
- remotename = argv[1];
-
- if (!create_fetchedfile(ftp, localname, remotename, (argc<3)?NULL:argv[2]))
- return 1;
-
- /* Set variable to name of most recent file */
- var_create_string(global_vars, "ftp_data", 0, localname);
-
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->restart = 0;
-
- ftp->fp = NULLFILE;
-
- if (ftp->type == IMAGE_PENDING)
- {
- ftp->type = IMAGE_TYPE ;
- sndftpmsg(ftp,"TYPE I\r\n");
- }
-
- if (ftp->type == IMAGE_TYPE)
- mode = binmode[WRITE_BINARY];
- else
- mode = "w";
-
- if ((ftp->fp = fopen(localname,mode)) == NULLFILE)
- {
- cwprintf(ftp->window, cantwrite, localname);
- return 1;
- }
- if (ftp->type == IMAGE_TYPE)
- setvbuf(ftp->fp, NULL, _IOFBF, 16384);
-
- ftp->last = 0;
- ftp->state = RECEIVING_STATE1;
- ftp->expected_size = 0;
- ftp->start_time = alarm_timenow () ;
- ftpsetup(ftp,(void(*)())ftpdr, NULLVFP, (void(*)())ftpcds);
-
- /* Generate the command to start the transfer */
- return sndftpmsg(ftp,"RETR %s\r\n",remotename);
- }
-
- static int doreget(int argc, char **argv)
- {
- char *remotename, localname[256];
- register struct ftp *ftp;
- char *mode;
-
- ftp = current_ftp->cb.ftp;
- if (ftp == NULLFTP)
- {
- cwprintf(NULL, notsess);
- return 1;
- }
- remotename = argv[1];
-
- if (!create_fetchedfile(ftp, localname, remotename, (argc<3)?NULL:argv[2]))
- return 1;
-
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
-
- ftp->fp = NULLFILE;
-
- if (ftp->type == IMAGE_PENDING)
- {
- ftp->type = IMAGE_TYPE ;
- sndftpmsg(ftp,"TYPE I\r\n");
- }
-
- if (ftp->type == IMAGE_TYPE)
- mode = "ab";
- else
- mode = "a";
-
- if ((ftp->fp = fopen(localname,mode)) == NULLFILE)
- {
- cwprintf(ftp->window, cantwrite, localname);
- return 1;
- }
- if (ftp->type == IMAGE_TYPE)
- setvbuf(ftp->fp, NULL, _IOFBF, 16384);
-
- ftp->restart = ftell(ftp->fp);
-
- ftp->last = 0;
- ftp->state = RECEIVING_STATE1;
- ftp->expected_size = 0;
- ftp->start_time = alarm_timenow () ;
- ftpsetup(ftp,(void(*)())ftpdr, NULLVFP, (void(*)())ftpcds);
-
- /* Generate the commands to start the transfer */
- sndftpmsg(ftp,"REST %ld\r\n",ftp->restart);
- return sndftpmsg(ftp,"RETR %s\r\n",remotename);
- }
-
- /* Start receive transfer. Syntax: view <remote name> */
- static int doview(int argc, char **argv)
- {
- char *remotename;
- register struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
- if (ftp == NULLFTP)
- {
- cwprintf(ftp->window, notsess);
- return 1;
- }
- remotename = argv[1];
-
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
- ftp->restart = 0;
-
- if (ftp->type == IMAGE_PENDING)
- {
- ftp->type = IMAGE_TYPE ;
- sndftpmsg(ftp,"TYPE I\r\n");
- }
-
- ftp->fp = stdout ;
- ftp->last = 0;
- ftp->state = RECEIVING_STATE1;
- ftp->expected_size = 0;
- ftp->start_time = alarm_timenow () ;
- ftpsetup(ftp,(void(*)())ftpdr, NULLVFP, (void(*)())ftpcds);
- /* Generate the command to start the transfer */
- return sndftpmsg(ftp,"RETR %s\r\n",remotename);
- }
-
- /* List remote directory. Syntax: dir <remote directory/file> [<local name>] */
- static int dolist(int argc, char **argv)
- {
- char localname[256];
- register struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
- if (ftp == NULLFTP)
- {
- cwprintf(ftp->window, notsess);
- return 1;
- }
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
- ftp->restart = 0;
-
- if (argc < 3)
- {
- ftp->fp = stdout;
- }
- else
- {
- strcpy(localname, argv[2]);
- if (!create_localfile(ftp, localname, 0xfff))
- return 1;
-
- /* Set variable to name of most recent file */
- var_create_string(global_vars, "ftp_list", 0, localname);
-
- if ((ftp->fp = fopen(localname, "w")), ftp->fp == NULLFILE)
- {
- cwprintf(ftp->window, cantwrite, localname);
- return 1;
- }
- }
- ftp->state = RECEIVING_STATE1;
- ftp->expected_size = 0;
- ftp->start_time = alarm_timenow () ;
- ftpsetup(ftp,(void(*)())ftpdr,NULLVFP,(void(*)())ftpcds);
- /* Generate the command to start the transfer
- It's done this way to avoid confusing the 4.2 FTP server
- if there's no argument */
- if (argc > 1)
- {
- if ( ftp->type == IMAGE_TYPE )
- {
- ftp->type = IMAGE_PENDING ;
- sndftpmsg(ftp,"TYPE A\r\n");
- }
- return sndftpmsg(ftp,"LIST %s\r\n",argv[1]);
- }
- else
- {
- if ( ftp->type == IMAGE_TYPE )
- {
- ftp->type = IMAGE_PENDING ;
- sndftpmsg(ftp,"TYPE A\r\n");
- }
- return sndftpmsg(ftp,"LIST\r\n","");
- }
- }
- /* Abbreviated (name only) list of remote directory.
- * Syntax: ls <remote directory/file> [<local name>]
- */
- static int dols(int argc, char **argv)
- {
- char localname[256];
- register struct ftp *ftp;
-
- ftp = current_ftp->cb.ftp;
- if (ftp == NULLFTP)
- {
- cwprintf(ftp->window, notsess);
- return 1;
- }
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
- ftp->restart = 0;
-
- if (argc < 3)
- {
- ftp->fp = stdout;
- }
- else
- {
- strcpy(localname, argv[2]);
- if (!create_localfile(ftp, localname, 0xfff))
- return 1;
-
- /* Set variable to name of most recent file */
- var_create_string(global_vars, "ftp_list", 0, localname);
-
- if ((ftp->fp = fopen(localname, "w")), ftp->fp == NULLFILE)
- {
- cwprintf(ftp->window, cantwrite,argv[2]);
- return 1;
- }
- }
- ftp->state = RECEIVING_STATE1;
- ftp->expected_size = 0;
- ftp->start_time = alarm_timenow () ;
-
- if ( ftp->type == IMAGE_TYPE )
- {
- ftp->type = IMAGE_PENDING ;
- sndftpmsg(ftp,"TYPE A\r\n");
- }
-
- ftpsetup(ftp,(void(*)())ftpdr,NULLVFP,(void(*)())ftpcds);
- /* Generate the command to start the transfer */
- if (argc > 1)
- {
- return sndftpmsg(ftp,"NLST %s\r\n",argv[1]);
- }
- else
- {
- return sndftpmsg(ftp,"NLST\r\n","");
- }
- }
- /* Start transmit. Syntax: put <local name> [<remote name>] */
- static int doput(int argc, char **argv)
- {
- char *remotename,*localname;
- char *mode;
- struct ftp *ftp;
-
- if ((ftp = current_ftp->cb.ftp) == NULLFTP)
- {
- cwprintf(ftp->window, notsess);
- return 1;
- }
- localname = argv[1];
- if (argc < 3)
- remotename = localname;
- else
- remotename = argv[2];
-
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->restart = 0;
-
- if (ftp->type == IMAGE_PENDING)
- {
- ftp->type = IMAGE_TYPE ;
- sndftpmsg(ftp,"TYPE I\r\n");
- }
-
- if (ftp->type == IMAGE_TYPE)
- mode = binmode[READ_BINARY];
- else
- mode = "r";
-
- if ((ftp->fp = fopen(localname,mode)) == NULLFILE)
- {
- cwprintf(ftp->window, cantread, localname);
- return 1;
- }
- fseek(ftp->fp,0,SEEK_END);
- ftp->expected_size = ftell(ftp->fp);
- fseek(ftp->fp,0,SEEK_SET);
- ftp->last = 0;
- ftp->state = SENDING_FILE_STATE1;
- ftp->start_time = alarm_timenow () ;
- ftpsetup(ftp, NULLVFP, (void(*)())ftpdt, (void(*)())ftpcds);
-
- /* Generate the command to start the transfer */
- return sndftpmsg(ftp,"STOR %s\r\n",remotename);
- }
- /* Abort a GET or PUT operation in progress. Note: this will leave
- * the partial file on the local or remote system
- */
- int doabort(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current_ftp->cb.ftp;
-
- /* Close the local file */
- if (ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
-
- ftp->restart = 0;
- ftp->replycount = 0;
-
- ftp_mpcleanup(ftp);
-
- if (ftp->batch)
- {
- cwprintf(ftp->window, "Batch file closed\r\n");
- fclose(ftp->batch);
- ftp->batch = NULL;
- }
-
- switch(ftp->state)
- {
- case SENDING_FILE_STATE1:
- case SENDING_FILE_STATE2:
- /* Send a premature EOF.
- Unfortunately we can't just reset the connection
- since the remote side might end up waiting forever
- for us to send something. */
- close_tcp(ftp->data);
- cwprintf(ftp->window, "Put aborted\r\n");
- break;
- case RECEIVING_STATE1:
- case RECEIVING_STATE2:
- /* Just exterminate the data channel TCB; this will
- * generate a RST on the next data packet which will
- * abort the sender
- */
- del_tcp(ftp->data);
- ftp->data = NULLTCB;
- cwprintf(ftp->window, "Get aborted\r\n");
- break;
- }
-
- ftp->state = COMMAND_STATE;
- prompt(ftp);
- return 0;
- }
- /* create data port, and send PORT message */
- static void ftpsetup(struct ftp *ftp, void (*recv)(),
- void (*send)(), void (*state)())
- {
- struct socket lsocket;
- struct mbuf *bp;
-
- lsocket.address = ip_addr;
- lsocket.port = lport++;
-
- /* Compose and send PORT a,a,a,a,p,p message */
-
- if ((bp = alloc_mbuf(35)) == NULLBUF)
- { /* 5 more than worst case */
- cwprintf(ftp->window, nospace);
- return;
- }
- /* I know, this looks gross, but it works! */
- sprintf(bp->data,"PORT %u,%u,%u,%u,%u,%u\r\n",
- hibyte(hiword(lsocket.address)),
- lobyte(hiword(lsocket.address)),
- hibyte(loword(lsocket.address)),
- lobyte(loword(lsocket.address)),
- hibyte(lsocket.port),
- lobyte(lsocket.port) );
- bp->cnt = strlen(bp->data);
- send_tcp(ftp->control,bp);
- ftp->replycount++;
-
- /* Post a listen on the data connection */
- ftp->data = open_tcp(&lsocket,NULLSOCK,TCP_PASSIVE,0,
- recv,send,state,0,(char *)ftp);
- }
-
- /* FTP Client Control channel Receiver upcall routine */
- void ftpccr(register struct tcb *tcb, int16 cnt)
- {
- extern int ttyflow;
- struct mbuf *bp;
- struct ftp *ftp;
- char c;
-
- if ((ftp = (struct ftp *)tcb->user) == NULLFTP)
- {
- /* Unknown connection; kill it */
- close_tcp(tcb);
- return;
- }
- /* Hold output if we're not the current session */
- if (ftp->window == NULL && (mode != CONV_MODE || current == NULLSESSION
- || ttyflow == 0 || current->cb.ftp != ftp))
- return;
-
- if (recv_tcp(tcb,&bp,cnt) > 0)
- {
- while(pullone(&bp,&c) == 1)
- {
- switch(c)
- {
- case '\n': /* Complete line; process it */
-
- ftp->buf[ftp->cnt] = '\0';
- doreply(ftp);
- ftp->cnt = 0;
- break;
- default:
- if (ftp->cnt != LINELEN-1)
- ftp->buf[ftp->cnt++] = c;
- break;
- }
- }
- }
- }
-
- int extract_line_number (char *l)
- {
- int i=0, c;
-
- for (c=0; c<3; c++)
- {
- if (isdigit(l[c]))
- i = i*10 + (l[c]-'0');
- else
- break;
- }
- return (i);
- }
-
- /* Process replies from the server */
- static void doreply(register struct ftp *ftp)
- {
- int code, more;
-
- if (ftp->cnt<3)
- return;
-
- if (ftp->trace>9)
- cwprintf(ftp->window, "Cur State: %d\r\n", ftp->state);
-
- code = extract_line_number(ftp->buf);
- more = (ftp->buf[3]=='-');
-
- if (ftp->state == CONTINUATION_STATE)
- {
- if (ftp->continue_val == code)
- ftp->state = ftp->last_state;
- else
- return;
- }
-
- if (more)
- {
- cwprintf(ftp->window, "%s\r\n", (ftp->trace)?ftp->buf:ftp->buf+4);
- ftp->last_state = ftp->state;
- ftp->state = CONTINUATION_STATE;
- ftp->continue_val = code;
- return;
- }
-
- switch(ftp->state)
- {
- case SENDING_FILE_STATE1:
- case SENDING_FILE_STATE2:
- case RECEIVING_STATE1:
- case RECEIVING_STATE2:
- --ftp->replycount;
- if (ftp->buf[0] == '4' || ftp->buf[0] == '5')
- {
- char *s[1];
- doabort(0, s);
- }
- else if (code == 150)
- {
- /* Opening message - see if we can find a file size... */
- char *s = strchr(ftp->buf , '(');
- if (sscanf(s, "(%lu bytes)", &ftp->expected_size) < 1)
- ftp->expected_size = 0;
- }
- else if (code==226)
- {
- if (ftp->state == SENDING_FILE_STATE1)
- ftp->state = SENDING_FILE_STATE2;
- else if (ftp->state == SENDING_FILE_STATE2)
- ftp->state = COMMAND_STATE;
- else if (ftp->state == RECEIVING_STATE1)
- ftp->state = RECEIVING_STATE2;
- else if (ftp->state == RECEIVING_STATE2)
- ftp->state = COMMAND_STATE;
- }
- if (ftp->trace || ftp->buf[0] == '4' || ftp->buf[0] == '5')
- cwprintf(ftp->window, "%s\r\n", (ftp->trace)?ftp->buf:ftp->buf+4);
- break;
- case STARTUP_STATE:
- cwprintf(ftp->window, "%s\r\n", (ftp->trace)?ftp->buf:ftp->buf+4);
- if (code==220)
- {
- ftp->state = USER_STATE;
- if (ftp->trace || !ftp->username)
- cwprintf(ftp->window, "Enter user name: ");
- if (ftp->username)
- {
- cwprintf(ftp->window, "Username Entered\r\n");
- sndftpmsg(ftp,"USER %s\r\n",ftp->username);
- }
- }
- else
- {
- ftp->state = COMMAND_STATE;
- ftp->replycount = 0;
- }
- break;
- case USER_STATE:
- --ftp->replycount;
- cwprintf(ftp->window, "%s\r\n", (ftp->trace)?ftp->buf:ftp->buf+4);
- if (code==331)
- {
- ftp->state = PASS_STATE;
- noecho();
- ftp->session->echo = FALSE;
- if (ftp->trace || !ftp->password)
- cwprintf(ftp->window, "Password: ");
- vterm_setflags(ftp->window->vt,VTSW_ECHO,0);
- if (ftp->password)
- {
- cwprintf(ftp->window, "Password Entered\r\n");
- sndftpmsg(ftp,"PASS %s\r\n",ftp->password);
- }
- }
- else
- {
- ftp->state = COMMAND_STATE;
- ftp->replycount = 0;
- }
- break;
- case PASS_STATE:
- --ftp->replycount;
- cwprintf(ftp->window, "%s\r\n", (ftp->trace)?ftp->buf:ftp->buf+4);
- echo();
- ftp->session->echo = TRUE;
- ftp->state = COMMAND_STATE;
- ftp->replycount = 0;
- vterm_setflags(ftp->window->vt,VTSW_ECHO,VTSW_ECHO);
- /*
- * Set default transfer type at server
- */
- ftp->type = (default_type==IMAGE_TYPE)?IMAGE_TYPE:ASCII_TYPE;
- sndftpmsg(ftp,"TYPE %c\r\n",(default_type==IMAGE_TYPE)?'I':'A');
- /*
- * Set the default directory if given and
- * do a pwd to get the name of the dir you end up in
- */
- ftp->flags |= FTP_TRAP_257;
- if (ftp->cd!=NULL)
- sndftpmsg(ftp, "CWD %s\r\n", ftp->cd);
- sndftpmsg(ftp,"PWD\r\n");
- break;
- case COMMAND_STATE:
- switch (code)
- {
- case 257:
- /*
- * Capture current directory
- */
- if (ftp->flags & FTP_TRAP_257)
- {
- char *p, *q;
-
- if (ftp->cd!=NULL)
- free(ftp->cd);
-
- if (p = strchr(ftp->buf+4, '\"'), p!=NULL)
- {
- if (q = strchr(p+1, '\"'), q!=NULL)
- ftp->cd = strndup(p+1, q-(p+1));
- }
- ftp->flags &= ~FTP_TRAP_257;
- }
-
- if (ftp->flags & FTP_SUPP_257 && !ftp->trace)
- {
- ftp->flags &= ~FTP_SUPP_257;
- break;
- }
-
- default:
- cwprintf(ftp->window, "%s\r\n", (ftp->trace)?ftp->buf:ftp->buf+4);
- }
- --ftp->replycount;
- break;
- }
- if (ftp->trace>9)
- cwprintf(ftp->window, "State now: %d\r\n", ftp->state);
- if (ftp->trace>9)
- cwprintf(ftp->window, "Reply counter: %d\r\n", ftp->replycount);
-
- if (ftp->replycount<=0 && ftp->state==COMMAND_STATE)
- {
- ftp->replycount = 0;
- prompt(ftp);
- }
- }
-
- /* FTP Client Control channel State change upcall routine */
- static void ftpccs(register struct tcb *tcb, char old, char new)
- {
- extern int ttyflow;
- struct ftp *ftp;
- char notify = 0;
- extern char *tcpstates[];
- extern char *reasons[];
- extern char *unreach[];
- extern char *exceed[];
-
- old = old;
-
- /* Can't add a check for unknown connection here, it would loop
- * on a close upcall! We're just careful later on.
- */
- ftp = (struct ftp *)tcb->user;
-
- if (ftp->window || (ttyflow && current != NULLSESSION && current->cb.ftp == ftp))
- notify = 1;
-
- switch(new)
- {
- case CLOSE_WAIT:
- if (notify)
- cwprintf(ftp->window, "%s\r\n",tcpstates[new]);
- close_tcp(tcb);
- break;
- case CLOSED: /* heh heh */
- if (notify)
- {
- cwprintf(ftp->window, "%s (%s",tcpstates[new],reasons[tcb->reason]);
- if (tcb->reason == NETWORK)
- {
- switch(tcb->type)
- {
- case DEST_UNREACH:
- cwprintf(ftp->window, ": %s unreachable",unreach[tcb->code]);
- break;
- case TIME_EXCEED:
- cwprintf(ftp->window, ": %s time exceeded",exceed[tcb->code]);
- break;
- }
- }
- cwprintf(ftp->window, ")\r\n");
- cmdmode();
- }
- del_tcp(tcb);
- if (ftp != NULLFTP)
- {
- if (ftp->window)
- {
- ftp->window->Attr = ATTR_REVERSE;
- ftp->window->Flags.flags.dont_destroy = FALSE;
- ftp->window->Session = NULL;
- Window_CloseDown(ftp->window);
- }
- ftp_delete(ftp);
- }
- break;
- default:
- if (notify)
- cwprintf(ftp->window, "%s\r\n",tcpstates[new]);
- break;
- }
- }
- /* FTP Client Data channel State change upcall handler */
- static void ftpcds(struct tcb *tcb, char old, char new)
- {
- extern int ttyflow;
- struct ftp *ftp;
-
- old = old;
-
- if ((ftp = (struct ftp *)tcb->user) == NULLFTP)
- {
- /* Unknown connection, kill it */
- close_tcp(tcb);
- return;
- }
- switch(new)
- {
- /* case FINWAIT2: */
- case TIME_WAIT:
- if (ftp->state == SENDING_FILE_STATE1 || ftp->state == SENDING_FILE_STATE2)
- {
- /* We've received an ack of our FIN, so
- * return to command mode
- */
- if (ftp->state == SENDING_FILE_STATE1)
- ftp->state = SENDING_FILE_STATE2;
- else
- ftp->state = COMMAND_STATE;
- ftp->replycount = 0;
- if (ftp->window != NULL || (ttyflow && current != NULLSESSION && current->cb.ftp == ftp))
- {
- int a = alarm_timedifference(ftp->start_time, alarm_timenow()) / 100;
- long b = tcb->snd.una - tcb->iss - 2;
-
- if (ftp->hash > 0)
- cwputchar(ftp->window, '\n');
- if (a == 0)
- a++;
- cwprintf(ftp->window, "Put complete, %lu bytes sent (%lu cps)\r\n", b, b/a);
- if (ftp->state == COMMAND_STATE)
- prompt(ftp);
- }
- }
- break;
- case CLOSE_WAIT:
- close_tcp(tcb);
- if (ftp->state == RECEIVING_STATE1 || ftp->state == RECEIVING_STATE2)
- {
- /* End of file received on incoming file */
- int to_screen = (ftp->fp==stdout);
-
- if (ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
- if (ftp->state == RECEIVING_STATE1)
- ftp->state = RECEIVING_STATE2;
- else
- ftp->state = COMMAND_STATE;
- ftp->replycount = 0;
- if (ftp->window != NULL || (ttyflow && current != NULLSESSION && current->cb.ftp == ftp))
- {
- int a;
- long b;
- if (!to_screen || ftp->trace)
- {
- a = alarm_timedifference(ftp->start_time, alarm_timenow()) / 100;
- b = tcb->rcv.nxt - tcb->irs - 2;
-
- if ( ftp->hash > 0 )
- cwputchar(ftp->window, '\n');
- if (a == 0)
- a++;
- if (ftp->restart)
- {
- cwprintf(ftp->window, "Get complete, remaining %lu of %lu bytes received (%lu cps)\r\n",
- b, b+ftp->restart, b/a);
- ftp->restart = 0;
- }
- else
- cwprintf(ftp->window, "Get complete, %lu bytes received (%lu cps)\r\n", b, b/a);
- }
- if (ftp->state == COMMAND_STATE)
- prompt(ftp);
- }
- }
- break;
- case CLOSED:
- ftp->data = NULLTCB;
- del_tcp(tcb);
- break;
- }
- }
-
- /* Send a message on the control channel */
- static int sndftpmsg(struct ftp *ftp, char *fmt, ...)
- {
- va_list argptr;
- struct mbuf *bp;
- int16 len;
-
- len = strlen(fmt)+256;
-
- if ((bp = alloc_mbuf(len)) == NULLBUF)
- {
- cwprintf(ftp->window, nospace);
- return 1;
- }
-
- va_start(argptr,fmt);
- vsprintf(bp->data,fmt,argptr);
- va_end(argptr);
- bp->cnt = strlen(bp->data);
- send_tcp(ftp->control,bp);
-
- ftp->replycount++;
-
- return 0;
- }
-
-
- static void prompt(struct ftp *ftp)
- {
- /*
- * A conditional newline - only doe a newline if cursor not at start of line
- */
- vterm_newline(ftp->window->vt);
-
- if (ftp->state==RECEIVING_STATE1 || ftp->state==SENDING_FILE_STATE1 &&
- ftp->state==RECEIVING_STATE2 || ftp->state==SENDING_FILE_STATE2)
- cwprintf(ftp->window, "%s- ",(ftp->batch)?"batch":(ftp->mpstate==FTPM_IDLE)?"ftp":"mget");
- else if (!mprocess(ftp) && !batch_ftp(ftp))
-
- /*
- * Contructs a suitable prompt that wont take up too much screen
- * Likely this will need alot more fiddling before everyone is happy...
- */
- {
- int mode;
-
- mode = ftp->prompt;
- if (ftp->cd==NULL && (mode==PROMPT_SHORTDIR || mode==PROMPT_LONGDIR))
- mode = PROMPT_NODIR;
-
- if (mode==PROMPT_SHORTDIR)
- {
- char *s;
- int n = strlen(ftp->cd);
-
-
- /*
- * Try to determine what kind of file system we are
- * dealing with and so work out how/where to split
- * the leaf directory off - look for unix '/', dos '\'
- * then checks to see if there is both '[' and the last
- * char is ']', and so is talking to VMS, so use .'., but strip
- * trailing ']', failing that, it may even be RISC OS local
- * server, else it just prints last 16 characters...
- */
- if (s = strrchr(ftp->cd, '/'), s!=NULL)
- cwprintf(ftp->window, "%s> ", (s[1])?s+1:s);
- else if (s = strrchr(ftp->cd, '\\'), s!=NULL)
- cwprintf(ftp->window, "%s> ", (s[1])?s+1:s);
- else if (s = strchr(ftp->cd, '['), s!=NULL && ftp->cd[n-1]==']')
- {
- /*
- * UGH - horrible VMS!
- */
- char *q;
- char buf[20];
-
- if (q = strrchr(s, '.'), q!=NULL)
- s = q+1;
-
- memset(buf, '\0', 20);
- if (s>(ftp->cd+(n-16)))
- {
- s = ftp->cd+(n-16);
- strcpy(buf+3, s);
- buf[0] = '.'; buf[1] = '.'; buf[2] = '.';
- }
- else
- strcpy(buf, s);
- buf[strlen(buf)-1] = '\0';
- cwprintf(ftp->window, "%s> ", buf);
- }
- else if (s = strrchr(ftp->cd, '.'), s!=NULL)
- cwprintf(ftp->window, "%s> ", (s[1])?s+1:s);
- }
- else if (mode==PROMPT_LONGDIR)
- {
- if (strlen(ftp->cd)>20)
- {
- cwprintf(ftp->window, "%s\r\n", ftp->cd);
- cwprintf(ftp->window, "> ");
- }
- else
- cwprintf(ftp->window, "%s> ", ftp->cd);
- }
- else
- cwprintf(ftp->window, "ftp> ");
- }
- }
-
- static int batch_ftp(struct ftp *ftp)
- {
- char *p;
- char buf[256];
-
- if (!ftp->batch)
- return 0;
-
- cwprintf(ftp->window, "batch> ");
-
- do
- {
- p = fgets(buf, 256, ftp->batch);
- rip(buf);
- }
- while (p!=NULL && (*buf=='\0' || *buf=='#'));
-
- if (p!=NULL)
- {
- vterm_printf(ftp->window->vt, ATTRIB_BOLD, "%s\r\n", buf);
- ftpparse(ftp->session, buf, strlen(buf));
- }
- else
- {
- vterm_printf(ftp->window->vt, ATTRIB_BOLD, "Batch completed.\r\n");
- fclose(ftp->batch);
- ftp->batch = NULL;
- if (ftp->nextsource!=NULL)
- {
- if (!batch_open(ftp, ftp->nextsource))
- cwprintf(ftp->window, "Cant find batch file \"%s\".\r\n", ftp->nextsource);
- free(ftp->nextsource);
- ftp->nextsource = NULL;
- prompt(ftp);
- return 1;
- }
- }
- return 0;
- }
-
- void ftp_mpcleanup(struct ftp *ftp)
- {
- int i;
-
- ftp->margp = 0;
-
- if (ftp->margv!=NULL)
- {
- for (i=0; ftp->margv[i]!=NULL; i++)
- free(ftp->margv[i]);
- free(ftp->margv);
- ftp->margv = NULL;
- }
-
- if (ftp->mfp!=NULL)
- {
- fclose(ftp->mfp);
- ftp->mfp = NULL;
- }
-
- if (ftp->mtemp!=NULL)
- {
- remove(ftp->mtemp);
- free(ftp->mtemp);
- ftp->mtemp = NULL;
- }
-
- ftp->mpstate = FTPM_IDLE;
- }
-
-
- static int domget(int argc, char **argv)
- {
- int i;
- struct ftp *ftp;
-
- if ((ftp = current_ftp->cb.ftp) == NULLFTP)
- {
- cwprintf(ftp->window, notsess);
- return 1;
- }
-
- ftp_mpcleanup(ftp);
-
- /* must have at least one file */
- if (argc<2)
- {
- cwprintf(ftp->window, "No files requested.\r\n");
- return 1;
- }
-
- /* alloc for temp name and file list */
- if ((ftp->mtemp = strdup(tmpnam(NULL)), ftp->mtemp==NULL) ||
- (ftp->margv = (char **)malloc(argc*sizeof(char *)), ftp->margv==NULL))
- {
- ftp_mpcleanup(ftp);
- cwprintf(ftp->window, nomemforop);
- return 1;
- }
-
- for (i=0; i<argc; i++)
- ftp->margv[i] = NULL;
-
- ftp->margp = 0;
-
- /* Copy file list */
- for (i=1; i<argc; i++)
- {
- if (ftp->margv[i-1] = strdup(argv[i]), ftp->margv[i-1]==NULL)
- {
- ftp_mpcleanup(ftp);
- cwprintf(ftp->window, nomemforop);
- return 1;
- }
- }
-
- /* Initial open of temp list file */
- if (ftp->fp = fopen(ftp->mtemp, "w"), ftp->fp==NULL)
- {
- ftp_mpcleanup(ftp);
- cwprintf(ftp->window, "Oops - temp file wont open\r\n");
- return 1;
- }
-
- /* start the ball rolling... */
- ftp->mpstate = FTPM_LISTING;
- mprocess(ftp);
- return 0;
- }
-
- static int mprocess(struct ftp *ftp)
- {
- char buf[256];
-
- if (ftp->mpstate==FTPM_IDLE)
- return 0;
-
- cwprintf(ftp->window, "mget> ");
-
- if (ftp->mpstate==FTPM_LISTING)
- {
- if (ftp->margv[ftp->margp]!=NULL)
- {
- if (ftp->fp==NULL)
- ftp->fp = fopen(ftp->mtemp, "a");
-
- if (ftp->fp==NULL)
- {
- ftp_mpcleanup(ftp);
- cwprintf(ftp->window, "Temp file wont open - mget aborted\r\n");
- return 0;
- }
-
- ftp->state = RECEIVING_STATE1;
- ftp->expected_size = 0;
- ftp->start_time = alarm_timenow () ;
- if ( ftp->type == IMAGE_TYPE )
- {
- ftp->type = IMAGE_PENDING ;
- sndftpmsg(ftp,"TYPE A\r\n");
- }
- ftpsetup(ftp,(void(*)())ftpdr,NULLVFP,(void(*)())ftpcds);
- /*
- * Generate the command to start the transfer
- * also send "NLST" on its own rather than "NLST " when the arg is empty
- */
- sndftpmsg(ftp,"NLST%s%s\r\n",(*ftp->margv[ftp->margp])?" ":"", ftp->margv[ftp->margp]);
- ++ftp->margp;
- return 1;
- }
- else
- {
- ftp->mpstate = FTPM_GETFILES;
- if (ftp->mfp = fopen(ftp->mtemp, "r"), ftp->mtemp==NULL)
- {
- ftp_mpcleanup(ftp);
- cwprintf(ftp->window, "Temp file wont open - mget aborted\r\n");
- return 0;
- }
- }
- }
-
- if (ftp->mpstate == FTPM_GETFILES)
- {
- strcpy(buf, "get ");
-
- if (fgets(buf+4, 256, ftp->mfp)!=NULL)
- {
- rip(buf);
- cwprintf(ftp->window, "%s\r\n", buf);
- ftpparse(ftp->session, buf, strlen(buf));
- }
- else
- {
- ftp_mpcleanup(ftp);
- cwprintf(ftp->window, "MGet completed.\r\n");
- }
- return 0;
- }
-
- return 0;
- }
-
-
- /*
- * Options presetting commands
- */
- /*
- * Set default path processing options
- * with which each FTP is initialised
- */
- static int dooptpath(int argc, char **argv)
- {
- int i, n;
- char opts[256];
- char *p;
- pathent_str *pe;
-
- if (argc>1)
- {
- if ((argc==2) && !strncmp(argv[1], "off", strlen(argv[1])))
- {
- delpathent(default_pathopts);
- default_pathopts = PATH_OFF;
- }
- else if ((argc==2) && !strncmp(argv[1], "auto", strlen(argv[1])))
- {
- delpathent(default_pathopts);
- default_pathopts = PATH_DEF;
- }
- else if ((argc==2) && !strncmp(argv[1], "type", strlen(argv[1])))
- {
- delpathent(default_pathopts);
- default_pathopts = PATH_TYPE;
- }
- else
- {
- /* Reconstrunct original path command */
- *opts = '$';
- p = opts+1;
- for (i=1; i<argc; i++)
- {
- n = sprintf(p, " %s", argv[i]);
- p += n;
- }
- if (pe = getpathent(opts), pe!=NULL)
- {
- delpathent(default_pathopts);
- default_pathopts = pe;
- }
- else
- {
- cwprintf(NULL, "Parse error in path options.\r\n");
- return 1;
- }
- }
- }
- else
- {
- if (default_pathopts == PATH_OFF)
- cwprintf(NULL, "Path processing off\r\n");
- else if (default_pathopts == PATH_DEF)
- cwprintf(NULL, "Auto path processing by extension\r\n");
- else
- cwprintf(NULL, "Preset path processing\r\n");
- /* show_pathent(ftp->pathopts); */
- }
-
- return 0;
- }
-
- static int dooptwinsz(int argc, char **argv)
- {
- if (argc<2)
- {
- cwprintf(NULL, "FTP window %d x %d, (visible %d x %d)\r\n",
- default_win_xv, default_win_yv, default_win_xe, default_win_ye);
- return 0;
- }
-
- if (argc==2)
- {
- /*
- * Changing YE only
- */
- default_win_ye = atoi(argv[1]);
- }
- else if (argc>2)
- {
- default_win_xe = atoi(argv[1]);
- default_win_ye = atoi(argv[2]);
- if (argc==4)
- {
- default_win_yv = atoi(argv[3]);
- }
- else if (argc>4)
- {
- default_win_xv = atoi(argv[3]);
- default_win_yv = atoi(argv[4]);
- }
- }
-
- if (default_win_xe < 80)
- default_win_xe = 80;
-
- if (default_win_xv < 16)
- default_win_xv = 16;
-
- if (default_win_xv > default_win_xe)
- default_win_xv = default_win_xe;
-
- if (default_win_ye < 24)
- default_win_ye = 24;
-
- if (default_win_yv < 8)
- default_win_yv = 8;
-
- if (default_win_yv > default_win_ye)
- default_win_yv = default_win_ye;
-
- return 0;
- }
-
- /*
- * Set default trace level
- */
- static int doopttrace(int argc, char **argv)
- {
- if (argc<2)
- cwprintf(NULL, "FTP trace level is %d\r\n", default_trace);
- else
- default_trace = atoi(argv[1]);
-
- return 0;
- }
-
- /*
- * Set default lump size
- */
- static int doopthash(int argc, char **argv)
- {
- if (argc<2)
- cwprintf(NULL, "FTP lump size is %d\r\n", default_hash);
- else
- default_hash = atoi(argv[1]);
-
- return 0;
- }
-
- /*
- * Set default transfer type
- */
- static int doopttype(int argc, char **argv)
- {
- if (argc<2)
- {
- char *p;
- switch (default_type)
- {
- case IMAGE_TYPE:
- p = "Image";
- break;
- case ASCII_TYPE:
- p = "Ascii";
- break;
- default:
- p = "Ascii";
- default_type = ASCII_TYPE;
- break;
- }
- cwprintf(NULL, "FTP transfer type is %s\r\n", p);
- }
- else
- {
- switch (*argv[1])
- {
- case 'i':
- case 'b':
- default_type = IMAGE_TYPE;
- break;
- case 'a':
- default_type = ASCII_TYPE;
- break;
- default:
- cwprintf(NULL, "Invalid type %s\r\n",argv[1]);
- return 1;
- }
- }
- return 0;
- }
-
- /*
- * Set default prompt type
- */
- static int dooptprompt(int argc, char **argv)
- {
- if (argc<2)
- {
- char *type;
- switch (default_prompt)
- {
- case PROMPT_SHORTDIR:
- type = "Short directory";
- break;
- case PROMPT_LONGDIR:
- type = "Full directory";
- break;
- default:
- type = "No directory";
- }
- cwprintf(NULL, "FTP prompt type: %s\r\n", type);
- }
- else
- {
- if (!strncmp(argv[1], "nodir", strlen(argv[1])))
- default_prompt = PROMPT_NODIR;
- else if (!strncmp(argv[1], "short", strlen(argv[1])))
- default_prompt = PROMPT_SHORTDIR;
- else if (!strncmp(argv[1], "long", strlen(argv[1])))
- default_prompt = PROMPT_LONGDIR;
- else
- cwprintf(NULL, "Unknown prompt type. Valid prompts are: nodir short long\r\n");
- }
-
- return 0;
- }
-
- int doftpopt(int argc, char **argv)
- {
- return subcmd(ftpopts,argc,argv);
- }
-
- /*
- * Calls the pathname processor according to user options
- * and retains the old path name handling...
- */
- static int create_fetchedfile(struct ftp *ftp, char *localname, char *remotename, char *givenname)
- {
- int filetype = -1;
-
- if (givenname==NULL)
- {
- /*
- * Local name not specified
- */
- if (ftp->pathopts==PATH_OFF ||
- !pathmap(remotename, localname, &filetype, ftp->pathopts) ||
- ftp->pathopts==PATH_TYPE )
- {
- char *cp, *temp;
- temp = strdup(remotename);
- cp = temp;
- while (cp = strpbrk(cp, "\"[]|<>+=;,./\\"), cp != NULL)
- {
- if (*cp=='/' || *cp=='\\')
- *cp++ = '.';
- else if (*cp=='.')
- *cp++ = '/';
- else
- *cp++ = '_';
- }
- sprintf(localname, "<FTP$dir>.%s", (*temp=='.')?temp+1:temp);
- free(temp);
- }
- }
- else
- {
- /*
- * Local name specified
- */
- strcpy(localname, givenname);
-
- if (ftp->pathopts!=PATH_OFF)
- pathmap(remotename, localname, &filetype, PATH_TYPE);
- }
-
- if (filetype<0)
- filetype = (ftp->type == IMAGE_TYPE)?0xffd:0xfff;
-
- if (create_localfile(ftp, localname, filetype))
- {
- ftp->filetype = filetype;
- return 1;
- }
-
- return 0;
- }
-
- /*
- * Takes a filename, expands it into a canonicalised name
- * then recursively creates directories and finally the
- * file with the specifued filetype
- */
- static int create_localfile(struct ftp *ftp, char *localname, int filetype)
- {
- os_regset r;
- os_error *e;
-
- char tempname[256];
-
- if (strpbrk(localname, "@$&%<>:"))
- strcpy(tempname, localname);
- else
- sprintf(tempname, "<ftp$dir>.%s", (*localname=='.')?localname+1:localname);
-
- r.r[0] = 37;
- r.r[1] = (int)tempname;
- r.r[2] = (int)localname;
- r.r[3] = (int)NULL;
- r.r[4] = (int)NULL;
- r.r[5] = 256;
-
- if (e = os_swix(OS_FSControl, &r), e==NULL)
- e = create_path(localname, 0, (filetype<0)?0xfff:filetype);
-
- if (filetype>=0)
- {
- if (e!=NULL)
- {
- cwprintf(ftp->window,"Cant create local file - %s\n", e->errmess);
- return 0;
- }
- else
- cwprintf(ftp->window,"Opening %s (%s)\r\n", localname, fttoa(filetype));
- }
- return 1;
- }
-