/* Stuff common to both the FTP server and client */ #include #include "machdep.h" #include "mbuf.h" #include "netuser.h" #include "timer.h" #include "tcp.h" #include "ftp.h" #include "session.h" #ifdef AMIGA #define UNIX 1 /* UNIX semantics work for Amiga in this module */ #endif /* FTP data channel receive upcall handler */ void r_ftpd(tcb,cnt) struct tcb *tcb; int16 cnt; { register struct ftp *ftp; struct mbuf *bp; #ifdef UNIX char c; #endif ftp = (struct ftp *)tcb->user; if(ftp->state != RECEIVING_STATE){ close_tcp(tcb); return; } /* This will likely also generate an ACK with window rotation */ recv_tcp(tcb,&bp,cnt); #ifdef UNIX while(pullup(&bp,&c,1) == 1){ if(ftp->type == IMAGE_TYPE || c != '\r') putc(c,ftp->fp); } #else while(bp != NULLBUF){ if(bp->cnt != 0) fwrite(bp->data,1,(unsigned)bp->cnt,ftp->fp); bp = free_mbuf(bp); } #endif } /* FTP data channel transmit upcall handler */ void t_ftpd(tcb,cnt) struct tcb *tcb; int16 cnt; { struct ftp *ftp; struct mbuf *bp; char *cp; int c; #ifndef CPM #ifndef AMIGA char *cdsave,*pwd(); #endif #endif ftp = (struct ftp *)tcb->user; if(ftp->state != SENDING_STATE){ close_tcp(tcb); return; } if((bp = alloc_mbuf(cnt)) == NULLBUF){ /* Hard to know what to do here */ return; } cp = bp->data; while(cnt > 1 && (c = getc(ftp->fp)) != EOF){ #ifdef CPM if(ftp->type == ASCII_TYPE && c == CTLZ) break; /* CTLZ is CP/M's text EOF marker */ #endif #ifdef UNIX if(ftp->type == ASCII_TYPE && c == '\n'){ *cp++ = '\r'; bp->cnt++; cnt--; } #endif *cp++ = c; bp->cnt++; cnt--; } if(bp->cnt != 0) send_tcp(tcb,bp); else free_p(bp); if(cnt > 1){ /* EOF seen */ #ifndef CPM #ifndef AMIGA cdsave = pwd(); /* Save current directory */ chdir(ftp->cd); /* Switch to user's directory*/ #endif #endif fclose(ftp->fp); #ifndef CPM #ifndef AMIGA chdir(cdsave); /* And back */ free(cdsave); #endif #endif ftp->fp = NULLFILE; close_tcp(tcb); } } /* Allocate an FTP control block */ struct ftp * ftp_create(bufsize) unsigned bufsize; { void ftp_delete(); char *calloc(),*malloc(); register struct ftp *ftp; if((ftp = (struct ftp *)calloc(1,sizeof (struct ftp))) == NULLFTP) return NULLFTP; if(bufsize != 0 && (ftp->buf = malloc(bufsize)) == NULLCHAR){ ftp_delete(ftp); return NULLFTP; } ftp->state = COMMAND_STATE; ftp->type = ASCII_TYPE; /* Default transfer type */ return ftp; } /* Free resources, delete control block */ void ftp_delete(ftp) register struct ftp *ftp; { if(ftp->fp != NULLFILE) fclose(ftp->fp); if(ftp->data != NULLTCB) del_tcp(ftp->data); if(ftp->username != NULLCHAR) free(ftp->username); if(ftp->buf != NULLCHAR) free(ftp->buf); #ifndef AMIGA if(ftp->cd != NULLCHAR) free(ftp->cd); #endif if(ftp->session != NULLSESSION) ftp->session->type = FREE; free((char *)ftp); } #ifndef AMIGA /* Call getcwd(), but stick a backslash on the front (!) */ #define CWDLEN 256 /* max path len */ char * pwd() { char *buf,*malloc(),*getcwd(); if((buf = malloc(CWDLEN+1)) == NULLCHAR) return NULLCHAR; buf[0] = '\\'; if(getcwd(buf+1,CWDLEN) == NULLCHAR){ free(buf); return NULLCHAR; } return buf; } #endif