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
gitextract_3_b0db68/
├── README.md
├── client/
│ ├── ftclient.c
│ ├── ftclient.h
│ └── makefile
├── common/
│ ├── common.c
│ └── common.h
└── server/
├── .auth
├── .auth~
├── ftserve.c
├── ftserve.h
└── makefile
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.