Full Code of beckysag/ftp for AI

master 7fc6696c4b6f cached
11 files
21.9 KB
6.7k tokens
27 symbols
1 requests
Download .txt
Repository: beckysag/ftp
Branch: master
Commit: 7fc6696c4b6f
Files: 11
Total size: 21.9 KB

Directory structure:
gitextract_3_b0db68/

├── README.md
├── client/
│   ├── ftclient.c
│   ├── ftclient.h
│   └── makefile
├── common/
│   ├── common.c
│   └── common.h
└── server/
    ├── .auth
    ├── .auth~
    ├── ftserve.c
    ├── ftserve.h
    └── makefile

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
FTP Client-Server Implementation
===========
Simple implementation of a file transfer program. It includes custom client and server programs that provide functionality to authenticate a user, list remote files, and retrieve remote files.

### Directory layout:
	ftp/
		client/
			ftclient.c
			ftclient.h
			makefile
		common/
			common.c
			common.h
		server/
			ftserve.c
			ftserve.h
			makefile
			.auth

###Usage
To compile and link ftserve:
```
	$ cd server/
	$ make
```

To compile and link ftclient:
```
	$ cd client/
	$ make
```

To run ftserve:
```
	$ server/ftserve PORTNO
```

To run ftclient:
```
	$ client/ftclient HOSTNAME PORTNO

	Commands:
		list
		get <filename>
		quit
```

Available commands:
```
list            - retrieve list of files in the current remote directory
get <filename>  - get the specified file
quit            - end the ftp session
```

Logging In:
```
	Name: anonymous
	Password: [empty]
```


================================================
FILE: client/ftclient.c
================================================
#include "ftclient.h"
	

int sock_control; 


/**
 * Receive a response from server
 * Returns -1 on error, return code on success
 */
int read_reply(){
	int retcode = 0;
	if (recv(sock_control, &retcode, sizeof retcode, 0) < 0) {
		perror("client: error reading message from server\n");
		return -1;
	}	
	return ntohl(retcode);
}



/**
 * Print response message
 */
void print_reply(int rc) 
{
	switch (rc) {
		case 220:
			printf("220 Welcome, server ready.\n");
			break;
		case 221:
			printf("221 Goodbye!\n");
			break;
		case 226:
			printf("226 Closing data connection. Requested file action successful.\n");
			break;
		case 550:
			printf("550 Requested action not taken. File unavailable.\n");
			break;
	}
	
}


/**
 * Parse command in cstruct
 */ 
int ftclient_read_command(char* buf, int size, struct command *cstruct)
{
	memset(cstruct->code, 0, sizeof(cstruct->code));
	memset(cstruct->arg, 0, sizeof(cstruct->arg));
	
	printf("ftclient> ");	// prompt for input		
	fflush(stdout); 	

	// wait for user to enter a command
	read_input(buf, size);
		
	char *arg = NULL;
	arg = strtok (buf," ");
	arg = strtok (NULL, " ");

	if (arg != NULL){
		// store the argument if there is one
		strncpy(cstruct->arg, arg, strlen(arg));
	}

	// buf = command
	if (strcmp(buf, "list") == 0) {
		strcpy(cstruct->code, "LIST");		
	}
	else if (strcmp(buf, "get") == 0) {
		strcpy(cstruct->code, "RETR");		
	}
	else if (strcmp(buf, "quit") == 0) {
		strcpy(cstruct->code, "QUIT");		
	}
	else {//invalid
		return -1;
	}

	// store code in beginning of buffer
	memset(buf, 0, 400);
	strcpy(buf, cstruct->code);

	// if there's an arg, append it to the buffer
	if (arg != NULL) {
		strcat(buf, " ");
		strncat(buf, cstruct->arg, strlen(cstruct->arg));
	}
	
	return 0;
}



/**
 * Do get <filename> command 
 */
int ftclient_get(int data_sock, int sock_control, char* arg)
{
    char data[MAXSIZE];
    int size;
    FILE* fd = fopen(arg, "w");
    
    while ((size = recv(data_sock, data, MAXSIZE, 0)) > 0) {
        fwrite(data, 1, size, fd);
    }

    if (size < 0) {
        perror("error\n");
    }

    fclose(fd);
    return 0;
}


/**
 * Open data connection
 */
int ftclient_open_conn(int sock_con)
{
	int sock_listen = socket_create(CLIENT_PORT_ID);

	// send an ACK on control conn
	int ack = 1;
	if ((send(sock_con, (char*) &ack, sizeof(ack), 0)) < 0) {
		printf("client: ack write error :%d\n", errno);
		exit(1);
	}		

	int sock_conn = socket_accept(sock_listen);
	close(sock_listen);
	return sock_conn;
}




/** 
 * Do list commmand
 */
int ftclient_list(int sock_data, int sock_con)
{
	size_t num_recvd;			// number of bytes received with recv()
	char buf[MAXSIZE];			// hold a filename received from server
	int tmp = 0;

	// Wait for server starting message
	if (recv(sock_con, &tmp, sizeof tmp, 0) < 0) {
		perror("client: error reading message from server\n");
		return -1;
	}
	
	memset(buf, 0, sizeof(buf));
	while ((num_recvd = recv(sock_data, buf, MAXSIZE, 0)) > 0) {
        	printf("%s", buf);
		memset(buf, 0, sizeof(buf));
	}
	
	if (num_recvd < 0) {
	        perror("error");
	}

	// Wait for server done message
	if (recv(sock_con, &tmp, sizeof tmp, 0) < 0) {
		perror("client: error reading message from server\n");
		return -1;
	}
	return 0;
}



/**
 * Input: cmd struct with an a code and an arg
 * Concats code + arg into a string and sends to server
 */
int ftclient_send_cmd(struct command *cmd)
{
	char buffer[MAXSIZE];
	int rc;

	sprintf(buffer, "%s %s", cmd->code, cmd->arg);
	
	// Send command string to server
	rc = send(sock_control, buffer, (int)strlen(buffer), 0);	
	if (rc < 0) {
		perror("Error sending command to server");
		return -1;
	}
	
	return 0;
}



/**
 * Get login details from user and
 * send to server for authentication
 */
void ftclient_login()
{
	struct command cmd;
	char user[256];
	memset(user, 0, 256);

	// Get username from user
	printf("Name: ");	
	fflush(stdout); 		
	read_input(user, 256);

	// Send USER command to server
	strcpy(cmd.code, "USER");
	strcpy(cmd.arg, user);
	ftclient_send_cmd(&cmd);
	
	// Wait for go-ahead to send password
	int wait;
	recv(sock_control, &wait, sizeof wait, 0);

	// Get password from user
	fflush(stdout);	
	char *pass = getpass("Password: ");	

	// Send PASS command to server
	strcpy(cmd.code, "PASS");
	strcpy(cmd.arg, pass);
	ftclient_send_cmd(&cmd);
	
	// wait for response
	int retcode = read_reply();
	switch (retcode) {
		case 430:
			printf("Invalid username/password.\n");
			exit(0);
		case 230:
			printf("Successful login.\n");
			break;
		default:
			perror("error reading message from server");
			exit(1);		
			break;
	}
}





int main(int argc, char* argv[]) 
{		
	int data_sock, retcode, s;
	char buffer[MAXSIZE];
	struct command cmd;	
	struct addrinfo hints, *res, *rp;

	if (argc != 3) {
		printf("usage: ./ftclient hostname port\n");
		exit(0);
	}

	char *host = argv[1];
	char *port = argv[2];

	// Get matching addresses
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	
	s = getaddrinfo(host, port, &hints, &res);
	if (s != 0) {
		printf("getaddrinfo() error %s", gai_strerror(s));
		exit(1);
	}
	
	// Find an address to connect to & connect
	for (rp = res; rp != NULL; rp = rp->ai_next) {
		sock_control = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

		if (sock_control < 0)
			continue;

		if(connect(sock_control, res->ai_addr, res->ai_addrlen)==0) {
			break;
		} else {
			perror("connecting stream socket");
			exit(1);
		}
		close(sock_control);
	}
	freeaddrinfo(rp);


	// Get connection, welcome messages
	printf("Connected to %s.\n", host);
	print_reply(read_reply()); 
	

	/* Get name and password and send to server */
	ftclient_login();

	while (1) { // loop until user types quit

		// Get a command from user
		if ( ftclient_read_command(buffer, sizeof buffer, &cmd) < 0) {
			printf("Invalid command\n");
			continue;	// loop back for another command
		}

		// Send command to server
		if (send(sock_control, buffer, (int)strlen(buffer), 0) < 0 ) {
			close(sock_control);
			exit(1);
		}

		retcode = read_reply();		
		if (retcode == 221) {
			/* If command was quit, just exit */
			print_reply(221);		
			break;
		}
		
		if (retcode == 502) {
			// If invalid command, show error message
			printf("%d Invalid command.\n", retcode);
		} else {			
			// Command is valid (RC = 200), process command
		
			// open data connection
			if ((data_sock = ftclient_open_conn(sock_control)) < 0) {
				perror("Error opening socket for data connection");
				exit(1);
			}			
			
			// execute command
			if (strcmp(cmd.code, "LIST") == 0) {
				ftclient_list(data_sock, sock_control);
			} 
			else if (strcmp(cmd.code, "RETR") == 0) {
				// wait for reply (is file valid)
				if (read_reply() == 550) {
					print_reply(550);		
					close(data_sock);
					continue; 
				}
				ftclient_get(data_sock, sock_control, cmd.arg);
				print_reply(read_reply()); 
			}
			close(data_sock);
		}

	} // loop back to get more user input

	// Close the socket (control connection)
	close(sock_control);
    return 0;  
}


================================================
FILE: client/ftclient.h
================================================
/* ftclient.h
 *
 * Rebecca Sagalyn
 * 11/15/13
 *
 * Client side of TCP file transfer implementation, runs with custom server, 
 * ftserve.c. Receives commands from input, and retreives list of files in current 
 * and files. 
   * 
 * Valid commands: 
 *    get <filename>
 *    list
 *    quit
 *    
 * Usage: 
 *    ./ftclient SERVER_HOSTNAME PORT#
 */

#ifndef FTCLIENT_H
#define FTCLIENT_H

#include "../common/common.h"


/**
 * Receive a response from server
 * Returns -1 on error, return code on success
 */
int read_reply();


/**
 * Print response message
 */
void print_reply(int rc);


/**
 * Parse command in cstruct
 */ 
int ftclient_read_command(char* buf, int size, struct command *cstruct);


/**
 * Do get <filename> command 
 */
int ftclient_get(int data_sock, int sock_control, char* arg);


/**
 * Open data connection
 */
int ftclient_open_conn(int sock_con);


/** 
 * Do list commmand
 */
int ftclient_list(int sock_data, int sock_con);


/**
 * Input: cmd struct with an a code and an arg
 * Concats code + arg into a string and sends to server
 */
int ftclient_send_cmd(struct command *cmd);


/**
 * Get login details from user and
 * send to server for authentication
 */
void ftclient_login();


#endif


================================================
FILE: client/makefile
================================================
CC := gcc
CFLAGS := -Wall -g -Os

SHDIR := ../common

OBJS = ftclient.o $(SHDIR)/common.o

all: ftclient

ftclient: $(OBJS)
	@$(CC) -o ftclient $(CFLAGS) $(OBJS)

$(OBJS) : %.o: %.c 
	@$(CC) -c $(CFLAGS) $< -o $@

.PHONY:
clean:
	@rm -f *.o ftclient
	@rm -f ../common/*.o
	@echo Done cleaning


================================================
FILE: common/common.c
================================================
#include "common.h"


/**
 * Create listening socket on remote host
 * Returns -1 on error, socket fd on success
 */
int socket_create(int port)
{
	int sockfd;
	int yes = 1;
	struct sockaddr_in sock_addr;

	// create new socket
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("socket() error"); 
		return -1; 
	}

	// set local address info
	sock_addr.sin_family = AF_INET;
	sock_addr.sin_port = htons(port);
	sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);		

	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
		close(sockfd);
		perror("setsockopt() error");
		return -1; 
	}

	// bind
	if (bind(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0) {
		close(sockfd);
		perror("bind() error"); 
		return -1; 
	}
   
	// begin listening for incoming TCP requests
	if (listen(sockfd, 5) < 0) {
		close(sockfd);
		perror("listen() error");
		return -1;
	}              
	return sockfd;
}





/**
 * Create new socket for incoming client connection request
 * Returns -1 on error, or fd of newly created socket
 */
int socket_accept(int sock_listen)
{
	int sockfd;
	struct sockaddr_in client_addr;
	socklen_t len = sizeof(client_addr);

	// Wait for incoming request, store client info in client_addr
	sockfd = accept(sock_listen, (struct sockaddr *) &client_addr, &len);
	
	if (sockfd < 0) {
		perror("accept() error"); 
		return -1; 
	}
	return sockfd;
}




/**
 * Connect to remote host at given port
 * Returns:	socket fd on success, -1 on error
 */
int socket_connect(int port, char*host)
{
	int sockfd;  					
	struct sockaddr_in dest_addr;

	// create socket
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
        	perror("error creating socket");
        	return -1;
    }

	// create server address
	memset(&dest_addr, 0, sizeof(dest_addr));
	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(port);
	dest_addr.sin_addr.s_addr = inet_addr(host);

	// Connect on socket
	if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0 ) {
        	perror("error connecting to server");
		return -1;
    	}    
	return sockfd;
}



/**
 * Receive data on sockfd
 * Returns -1 on error, number of bytes received 
 * on success
 */
int recv_data(int sockfd, char* buf, int bufsize){
	size_t num_bytes;
	memset(buf, 0, bufsize);
	num_bytes = recv(sockfd, buf, bufsize, 0);
	if (num_bytes < 0) {
		return -1;
	}
	return num_bytes;
}




/**
 * Trim whiteshpace and line ending
 * characters from a string
 */
void trimstr(char *str, int n)
{
	int i;
	for (i = 0; i < n; i++) {
		if (isspace(str[i])) str[i] = 0;
		if (str[i] == '\n') str[i] = 0;
	}
}


/**
 * Send resposne code on sockfd
 * Returns -1 on error, 0 on success
 */
int send_response(int sockfd, int rc)
{
	int conv = htonl(rc);
	if (send(sockfd, &conv, sizeof conv, 0) < 0 ) {
		perror("error sending...\n");
		return -1;
	}
	return 0;
}




/** 
 * Read input from command line
 */
void read_input(char* buffer, int size)
{
	char *nl = NULL;
	memset(buffer, 0, size);

	if ( fgets(buffer, size, stdin) != NULL ) {
		nl = strchr(buffer, '\n');
		if (nl) *nl = '\0'; // truncate, ovewriting newline
	}
}




================================================
FILE: common/common.h
================================================
#ifndef COMMON_H
#define COMMON_H

#include <arpa/inet.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>		// getaddrinfo()
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>



/* constants */
#define DEBUG				1
#define MAXSIZE 			512 	// max buffer size
#define CLIENT_PORT_ID		30020


/* Holds command code and argument */
struct command {
	char arg[255];
	char code[5];
};




/**
 * Create listening socket on remote host
 * Returns -1 on error, socket fd on success
 */
int socket_create(int port);


/**
 * Create new socket for incoming client connection request
 * Returns -1 on error, or fd of newly created socket
 */
int socket_accept(int sock_listen);


/**
 * Connect to remote host at given port
 * Returns socket fd on success, -1 on error
 */
int socket_connect(int port, char *host);



/**
 * Receive data on sockfd
 * Returns -1 on error, number of bytes received 
 * on success
 */
int recv_data(int sockfd, char* buf, int bufsize);


/**
 * Send resposne code on sockfd
 * Returns -1 on error, 0 on success
 */
int send_response(int sockfd, int rc);



//------------------- UTILITY FUNCTIONS-------------------//

/**
 * Trim whiteshpace and line ending
 * characters from a string
 */
void trimstr(char *str, int n);



/** 
 * Read input from command line
 */
void read_input(char* buffer, int size);


#endif









================================================
FILE: server/.auth
================================================
user pass
test testpass
anonymous 


================================================
FILE: server/.auth~
================================================
user pass
test testpass


================================================
FILE: server/ftserve.c
================================================
#include "ftserve.h"


int main(int argc, char *argv[])
{	
	int sock_listen, sock_control, port, pid;

	if (argc != 2) {
		printf("usage: ./ftserve port\n");
		exit(0);
	}

	port = atoi(argv[1]);

	// create socket
	if ((sock_listen = socket_create(port)) < 0 ) {
		perror("Error creating socket");
		exit(1);
	}		
	
	while(1) {	// wait for client request

		// create new socket for control connection
		if ((sock_control = socket_accept(sock_listen))	< 0 )
			break;			
		
		// create child process to do actual file transfer
		if ((pid = fork()) < 0) { 
			perror("Error forking child process");
		} else if (pid == 0) { 
			close(sock_listen);
			ftserve_process(sock_control);		
			close(sock_control);
			exit(0);
		}
			
		close(sock_control);
	}

	close(sock_listen);	

	return 0;
}



/**
 * Send file specified in filename over data connection, sending
 * control message over control connection
 * Handles case of null or invalid filename
 */
void ftserve_retr(int sock_control, int sock_data, char* filename)
{	
	FILE* fd = NULL;
	char data[MAXSIZE];
	size_t num_read;							
		
	fd = fopen(filename, "r");
	
	if (!fd) {	
		// send error code (550 Requested action not taken)
		send_response(sock_control, 550);
		
	} else {	
		// send okay (150 File status okay)
		send_response(sock_control, 150);
	
		do {
			num_read = fread(data, 1, MAXSIZE, fd);

			if (num_read < 0) {
				printf("error in fread()\n");
			}

			// send block
			if (send(sock_data, data, num_read, 0) < 0)
				perror("error sending file\n");

		} while (num_read > 0);													
			
		// send message: 226: closing conn, file transfer successful
		send_response(sock_control, 226);

		fclose(fd);
	}
}





/**
 * Send list of files in current directory
 * over data connection
 * Return -1 on error, 0 on success
 */
int ftserve_list(int sock_data, int sock_control)
{
	char data[MAXSIZE];
	size_t num_read;									
	FILE* fd;

	int rs = system("ls -l | tail -n+2 > tmp.txt");
	if ( rs < 0) {
		exit(1);
	}
	
	fd = fopen("tmp.txt", "r");	
	if (!fd) {
		exit(1);
	}

	/* Seek to the beginning of the file */
	fseek(fd, SEEK_SET, 0);

	send_response(sock_control, 1); //starting

	memset(data, 0, MAXSIZE);
	while ((num_read = fread(data, 1, MAXSIZE, fd)) > 0) {
		if (send(sock_data, data, num_read, 0) < 0) {
			perror("err");
		}
		memset(data, 0, MAXSIZE);
	}

	fclose(fd);

	send_response(sock_control, 226);	// send 226

	return 0;	
}






/**
 * Open data connection to client 
 * Returns: socket for data connection
 * or -1 on error
 */
int ftserve_start_data_conn(int sock_control)
{
	char buf[1024];	
	int wait, sock_data;

	// Wait for go-ahead on control conn
	if (recv(sock_control, &wait, sizeof wait, 0) < 0 ) {
		perror("Error while waiting");
		return -1;
	}

	// Get client address
	struct sockaddr_in client_addr;
	socklen_t len = sizeof client_addr;
	getpeername(sock_control, (struct sockaddr*)&client_addr, &len);
	inet_ntop(AF_INET, &client_addr.sin_addr, buf, sizeof(buf));

	// Initiate data connection with client
	if ((sock_data = socket_connect(CLIENT_PORT_ID, buf)) < 0)
		return -1;

	return sock_data;		
}





/**
 * Authenticate a user's credentials
 * Return 1 if authenticated, 0 if not
 */
int ftserve_check_user(char*user, char*pass)
{
	char username[MAXSIZE];
	char password[MAXSIZE];
	char *pch;
	char buf[MAXSIZE];
	char *line = NULL;
	size_t num_read;									
	size_t len = 0;
	FILE* fd;
	int auth = 0;
	
	fd = fopen(".auth", "r");
	if (fd == NULL) {
		perror("file not found");
		exit(1);
	}	

	while ((num_read = getline(&line, &len, fd)) != -1) {
		memset(buf, 0, MAXSIZE);
		strcpy(buf, line);
		
		pch = strtok (buf," ");
		strcpy(username, pch);

		if (pch != NULL) {
			pch = strtok (NULL, " ");
			strcpy(password, pch);
		}

		// remove end of line and whitespace
		trimstr(password, (int)strlen(password));

		if ((strcmp(user,username)==0) && (strcmp(pass,password)==0)) {
			auth = 1;
			break;
		}		
	}
	free(line);	
	fclose(fd);	
	return auth;
}





/** 
 * Log in connected client
 */
int ftserve_login(int sock_control)
{	
	char buf[MAXSIZE];
	char user[MAXSIZE];
	char pass[MAXSIZE];	
	memset(user, 0, MAXSIZE);
	memset(pass, 0, MAXSIZE);
	memset(buf, 0, MAXSIZE);
	
	// Wait to recieve username
	if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1) {
		perror("recv error\n"); 
		exit(1);
	}	

	int i = 5;
	int n = 0;
	while (buf[i] != 0)
		user[n++] = buf[i++];
	
	// tell client we're ready for password
	send_response(sock_control, 331);					
	
	// Wait to recieve password
	memset(buf, 0, MAXSIZE);
	if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1) {
		perror("recv error\n"); 
		exit(1);
	}
	
	i = 5;
	n = 0;
	while (buf[i] != 0) {
		pass[n++] = buf[i++];
	}
	
	return (ftserve_check_user(user, pass));
}





/**
 * Wait for command from client and
 * send response
 * Returns response code
 */
int ftserve_recv_cmd(int sock_control, char*cmd, char*arg)
{	
	int rc = 200;
	char buffer[MAXSIZE];
	
	memset(buffer, 0, MAXSIZE);
	memset(cmd, 0, 5);
	memset(arg, 0, MAXSIZE);
		
	// Wait to recieve command
	if ((recv_data(sock_control, buffer, sizeof(buffer)) ) == -1) {
		perror("recv error\n"); 
		return -1;
	}
	
	strncpy(cmd, buffer, 4);
	char *tmp = buffer + 5;
	strcpy(arg, tmp);
	
	if (strcmp(cmd, "QUIT")==0) {
		rc = 221;
	} else if((strcmp(cmd, "USER")==0) || (strcmp(cmd, "PASS")==0) ||
			(strcmp(cmd, "LIST")==0) || (strcmp(cmd, "RETR")==0)) {
		rc = 200;
	} else { //invalid command
		rc = 502;
	}

	send_response(sock_control, rc);	
	return rc;
}






/** 
 * Child process handles connection to client
 */
void ftserve_process(int sock_control)
{
	int sock_data;
	char cmd[5];
	char arg[MAXSIZE];

	// Send welcome message
	send_response(sock_control, 220);

	// Authenticate user
	if (ftserve_login(sock_control) == 1) {
		send_response(sock_control, 230);
	} else {
		send_response(sock_control, 430);	
		exit(0);
	}	
	
	while (1) {
		// Wait for command
		int rc = ftserve_recv_cmd(sock_control, cmd, arg);
		
		if ((rc < 0) || (rc == 221)) {
			break;
		}
		
		if (rc == 200 ) {
			// Open data connection with client
			if ((sock_data = ftserve_start_data_conn(sock_control)) < 0) {
				close(sock_control);
				exit(1); 
			}

			// Execute command
			if (strcmp(cmd, "LIST")==0) { // Do list
				ftserve_list(sock_data, sock_control);
			} else if (strcmp(cmd, "RETR")==0) { // Do get <filename>
				ftserve_retr(sock_control, sock_data, arg);
			}
		
			// Close data connection
			close(sock_data);
		} 
	}
}




================================================
FILE: server/ftserve.h
================================================
/* ftserve.h
 *
 * Rebecca Sagalyn
 * CS372, Program 1
 * 11/15/13
 *
 * Server side of TCP file transfer implementation, runs with custom client, 
 * ftclient.c. Sends list of files in current directory and files to ftclient. 
 * Requires user login.
 * 
 * Usage: 
 *    ./ftserve PORT#
 */

#ifndef FTSERVE_H
#define FTSERVE_H

#include "../common/common.h"


/**
 * Send file specified in filename over data connection, sending
 * control message over control connection
 * Handles case of null or invalid filename
 */
void ftserve_retr(int sock_control, int sock_data, char* filename);



/**
 * Send list of files in current directory
 * over data connection
 * Return -1 on error, 0 on success
 */
int ftserve_list(int sock_data, int sock_control);




/**
 * Open data connection to client 
 * Returns: socket for data connection
 * or -1 on error
 */
int ftserve_start_data_conn(int sock_control);



/**
 * Authenticate a user's credentials
 * Return 1 if authenticated, 0 if not
 */
int ftserve_check_user(char*user, char*pass);



/** 
 * Log in connected client
 */
int ftserve_login(int sock_control);


/**
 * Wait for command from client and send response
 * Returns response code
 */
int ftserve_recv_cmd(int sock_control, char*cmd, char*arg);



/** 
 * Child process handles connection to client
 */
void ftserve_process(int sock_control);


#endif


================================================
FILE: server/makefile
================================================
CC := gcc
CFLAGS := -Wall -g -Os

SHDIR := ../common

OBJS = ftserve.o $(SHDIR)/common.o

all: ftserve

ftserve: $(OBJS)
	@$(CC) -o ftserve $(CFLAGS) $(OBJS)

$(OBJS) : %.o: %.c 
	@$(CC) -c $(CFLAGS) $< -o $@

.PHONY:
clean:
	@rm -f *.o ftserve
	@rm -f ../common/*.o
	@echo Done cleaning
Download .txt
gitextract_3_b0db68/

├── README.md
├── client/
│   ├── ftclient.c
│   ├── ftclient.h
│   └── makefile
├── common/
│   ├── common.c
│   └── common.h
└── server/
    ├── .auth
    ├── .auth~
    ├── ftserve.c
    ├── ftserve.h
    └── makefile
Download .txt
SYMBOL INDEX (27 symbols across 5 files)

FILE: client/ftclient.c
  function read_reply (line 11) | int read_reply(){
  function print_reply (line 25) | void print_reply(int rc)
  function ftclient_read_command (line 48) | int ftclient_read_command(char* buf, int size, struct command *cstruct)
  function ftclient_get (line 100) | int ftclient_get(int data_sock, int sock_control, char* arg)
  function ftclient_open_conn (line 122) | int ftclient_open_conn(int sock_con)
  function ftclient_list (line 144) | int ftclient_list(int sock_data, int sock_con)
  function ftclient_send_cmd (line 180) | int ftclient_send_cmd(struct command *cmd)
  function ftclient_login (line 203) | void ftclient_login()
  function main (line 252) | int main(int argc, char* argv[])

FILE: client/ftclient.h
  type command (line 41) | struct command
  type command (line 66) | struct command

FILE: common/common.c
  function socket_create (line 8) | int socket_create(int port)
  function socket_accept (line 55) | int socket_accept(int sock_listen)
  function socket_connect (line 78) | int socket_connect(int port, char*host)
  function recv_data (line 110) | int recv_data(int sockfd, char* buf, int bufsize){
  function trimstr (line 127) | void trimstr(char *str, int n)
  function send_response (line 141) | int send_response(int sockfd, int rc)
  function read_input (line 157) | void read_input(char* buffer, int size)

FILE: common/common.h
  type command (line 28) | struct command {

FILE: server/ftserve.c
  function main (line 4) | int main(int argc, char *argv[])
  function ftserve_retr (line 52) | void ftserve_retr(int sock_control, int sock_data, char* filename)
  function ftserve_list (line 97) | int ftserve_list(int sock_data, int sock_control)
  function ftserve_start_data_conn (line 143) | int ftserve_start_data_conn(int sock_control)
  function ftserve_check_user (line 175) | int ftserve_check_user(char*user, char*pass)
  function ftserve_login (line 225) | int ftserve_login(int sock_control)
  function ftserve_recv_cmd (line 273) | int ftserve_recv_cmd(int sock_control, char*cmd, char*arg)
  function ftserve_process (line 313) | void ftserve_process(int sock_control)
Condensed preview — 11 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (25K chars).
[
  {
    "path": "README.md",
    "chars": 930,
    "preview": "FTP Client-Server Implementation\n===========\nSimple implementation of a file transfer program. It includes custom client"
  },
  {
    "path": "client/ftclient.c",
    "chars": 7122,
    "preview": "#include \"ftclient.h\"\n\t\n\nint sock_control; \n\n\n/**\n * Receive a response from server\n * Returns -1 on error, return code "
  },
  {
    "path": "client/ftclient.h",
    "chars": 1235,
    "preview": "/* ftclient.h\n *\n * Rebecca Sagalyn\n * 11/15/13\n *\n * Client side of TCP file transfer implementation, runs with custom "
  },
  {
    "path": "client/makefile",
    "chars": 293,
    "preview": "CC := gcc\nCFLAGS := -Wall -g -Os\n\nSHDIR := ../common\n\nOBJS = ftclient.o $(SHDIR)/common.o\n\nall: ftclient\n\nftclient: $(OB"
  },
  {
    "path": "common/common.c",
    "chars": 3154,
    "preview": "#include \"common.h\"\n\n\n/**\n * Create listening socket on remote host\n * Returns -1 on error, socket fd on success\n */\nint"
  },
  {
    "path": "common/common.h",
    "chars": 1511,
    "preview": "#ifndef COMMON_H\n#define COMMON_H\n\n#include <arpa/inet.h>\n#include <ctype.h>\n#include <dirent.h>\n#include <errno.h>\n#inc"
  },
  {
    "path": "server/.auth",
    "chars": 35,
    "preview": "user pass\ntest testpass\nanonymous \n"
  },
  {
    "path": "server/.auth~",
    "chars": 24,
    "preview": "user pass\ntest testpass\n"
  },
  {
    "path": "server/ftserve.c",
    "chars": 6504,
    "preview": "#include \"ftserve.h\"\n\n\nint main(int argc, char *argv[])\n{\t\n\tint sock_listen, sock_control, port, pid;\n\n\tif (argc != 2) {"
  },
  {
    "path": "server/ftserve.h",
    "chars": 1368,
    "preview": "/* ftserve.h\n *\n * Rebecca Sagalyn\n * CS372, Program 1\n * 11/15/13\n *\n * Server side of TCP file transfer implementation"
  },
  {
    "path": "server/makefile",
    "chars": 288,
    "preview": "CC := gcc\nCFLAGS := -Wall -g -Os\n\nSHDIR := ../common\n\nOBJS = ftserve.o $(SHDIR)/common.o\n\nall: ftserve\n\nftserve: $(OBJS)"
  }
]

About this extraction

This page contains the full source code of the beckysag/ftp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 11 files (21.9 KB), approximately 6.7k tokens, and a symbol index with 27 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!