# define NOT_SWITCH 'X' # define DIR_SWITCH 'l' # define GET_SWITCH 'g' # define PUT_SWITCH 'p' # define REP_SWITCH 'r' # define DEL_SWITCH 'd' # include # include # include # include # include # include const int BUFSIZE = 256; const int BLOCKSIZE = 128; int readLine(char buf[], const int BUFSIZE, FILE *recv); int sftpLogin(FILE *send, FILE *receive); char checkArg(char arg[], FILE *send, FILE *receive); void eraseFile(FILE *send, FILE *receive, char filename[]); void getTextFile(FILE *receive, FILE *writeFile); int main (int argc, char *argv[]) { register struct hostent *hp = 0; struct sockaddr_in remoteaddr; struct servent *sp; FILE *send, *receive; int sock, port, status; char buffer[BUFSIZE]; int bs = '\r'; FILE *readFile, *writeFile; hp = gethostbyname (argv[1]); /* WHAT IF GETHOSTBYNAME FAILS? */ if(hp == NULL) { printf("Could not locate %s, quitting...",argv[1]); exit(1); } /* Extract the remote address and put it into the structure for socket */ remoteaddr.sin_family = hp->h_addrtype; bcopy (hp->h_addr_list[0], (caddr_t) &remoteaddr.sin_addr, hp->h_length); sock = socket (remoteaddr.sin_family, SOCK_STREAM, 0); if (sock < 0) { printf("Socket not created. Exiting...\n"); exit (1); } sp = getservbyname ("comp347","tcp"); if (sp == 0) { printf("Could not find sftp service in /etc/services...\n"); exit (1); } else { port = sp->s_port; } remoteaddr.sin_port = port; if (comp347_connect (sock, &remoteaddr, sizeof (remoteaddr)) < 0) { printf("Connect failed...\n"); exit (1); } receive = fdopen (sock,"rb"); send = fdopen (sock,"wb"); //LOGIN HERE status = sftpLogin(send,receive); if(status != 0) { printf("Server error: %d ...quitting.\n", status); exit(1); } int i; for(i = 2; i < argc ; i++) { char currentC = '\r'; switch(checkArg(argv[i],send,receive)) { case NOT_SWITCH: break; case DIR_SWITCH: printf("DIR\r\n"); fprintf(send,"DIR\r\n"); fflush(send); status = readLine(buffer,BUFSIZE,receive); currentC = '\r'; if(status == 0) { /*while(currentC != '\0') { currentC = fgetc(receive); fputc(currentC,stdout); }*/ getTextFile(receive,stdout); } break; case GET_SWITCH: printf("FETCH %s\r\n",argv[i+1]); fprintf(send,"FETCH %s\r\n",argv[i+1]); fflush(send); status = readLine(buffer,BUFSIZE,receive); if(status == 0) { currentC = '\r'; writeFile = fopen(argv[i+1],"w"); if(writeFile != NULL) { if(argv[i][2] == 'b' || argv[i][1] == 'b') { bs = '\r'; while(bs != '\0') { bs = fgetc(receive); fread(buffer,bs,1,receive); fwrite(buffer,bs,1,writeFile); } fflush(writeFile); } else { /*while(currentC != '\0') { currentC = fgetc(receive); fputc(currentC,writeFile); }*/ getTextFile(receive,writeFile); } fclose(writeFile); } else { printf("Could not open %s for writing. Quitting!\n",argv[i+1]); } } break; case REP_SWITCH: eraseFile(send,receive,argv[i+1]); status = readLine(buffer,BUFSIZE,receive); case PUT_SWITCH: readFile = fopen(argv[i+1],"r"); if(readFile == NULL) { printf("File %s not exist...\n",argv[i+1]); exit(1); } else { printf("STORE %s\r\n",argv[i+1]); fprintf(send,"STORE %s\r\n",argv[i+1]); fflush(send); status = readLine(buffer,BUFSIZE,receive); if(status == 0) { long readSize; size_t readResult; fseek(readFile,0,SEEK_END); readSize = ftell(readFile); rewind(readFile); if(argv[i][2] == 'b' || argv[i][1] == 'b') { bs = BLOCKSIZE; char readBuffer[bs]; fseek(readFile,0,SEEK_END); readSize = ftell(readFile); rewind(readFile); while(readSize != 0) { if(readSize < BLOCKSIZE) bs = readSize; fread(readBuffer,bs,1,readFile); fputc(bs,send); fflush(send); fwrite(readBuffer,bs,1,send); readSize -= bs; } fputc('\0',send); free(readBuffer); } else { char *readBuffer; readBuffer = (char*) malloc (sizeof(char)*readSize); fread(readBuffer,1,readSize,readFile); char currentC = '\r'; int currentI; int i; for(i = 0; i < readSize; i++) { currentI = (unsigned int) readBuffer[i]; if( (currentI > 31 && currentI < 127) || (currentI > 8 && currentI < 14 && currentI != 12)) { fprintf(send,"%c",readBuffer[i]); } } fputc('\0',send); } fflush(send); fclose(readFile); status = readLine(buffer,BUFSIZE,receive); } } break; case DEL_SWITCH: eraseFile(send,receive,argv[i+1]); status = readLine(buffer,BUFSIZE,receive); break; } } // QUIT // printf("QUIT\r\n"); fprintf(send,"QUIT\r\n"); fflush(send); status = readLine(buffer,BUFSIZE,receive); return 0; } int readLine(char buf[], const int BUFSIZE, FILE *receive) { bzero(buf,BUFSIZE); fgets(buf,BUFSIZE-1,receive); printf("%s",buf); int status; char statmsg[20]; sscanf(buf,"%s %d",statmsg,&status); return status; } int sftpLogin(FILE *send, FILE *receive) { const int SLEEPTIME = 3; const int BUSYERR = 500; char buffer[BUFSIZE]; char loginname[BUFSIZE]; int status = '\0'; bzero(buffer,BUFSIZE); bzero(loginname,BUFSIZE); status = readLine(buffer,BUFSIZE,receive); if(status == 0) { getlogin_r(loginname,sizeof(loginname)); printf("USER %s\r\n",loginname); fprintf(send,"USER %s\r\n",loginname); fflush(send); status = readLine(buffer,BUFSIZE,receive); while(status == BUSYERR) { printf("Server busy, reconnecting in %d seconds...\n",SLEEPTIME); sleep(SLEEPTIME); printf("USER %s\r\n",loginname); fprintf(send,"USER %s\r\n",loginname); fflush(send); status = readLine(buffer,BUFSIZE,receive); } } free(buffer); free(loginname); return status; } void eraseFile(FILE *send, FILE *receive, char filename[]) { printf("ERASE %s\r\n",filename); fprintf(send,"ERASE %s\r\n",filename); fflush(send); } char checkArg(char arg[], FILE *send, FILE *receive) { char switchcode; if(arg[0] == '-') { char buffer[BUFSIZE]; int status ='\0'; if(arg[1] == 'b' || arg[2] == 'b') { printf("MODE BINARY\r\n"); fprintf(send,"MODE BINARY\r\n"); fflush(send); status = readLine(buffer,BUFSIZE,receive); if(arg[1] == 'b') switchcode = arg[2]; else switchcode = arg[1]; } else { printf("MODE TEXT\r\n"); fprintf(send,"MODE TEXT\r\n"); fflush(send); status = readLine(buffer,BUFSIZE,receive); switchcode = arg[1]; } free(buffer); } else switchcode = NOT_SWITCH; return switchcode; } void getTextFile(FILE *receive, FILE *writeFile) { int currentC = '\r'; while(currentC != '\0') { currentC = fgetc(receive); fputc(currentC,writeFile); } }