Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <fcntl.h>
- #include <arpa/inet.h>
- #include <signal.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <netdb.h>
- #include <ifaddrs.h>
- #include <ctype.h>
- #include <libgen.h>
- #define MAX_COMMAND_SIZE 4 //макимальный размер команды
- #define USER "USER %s\r\n" //имя пользователя
- #define PASS "PASS %s\r\n" //пароль
- #define PWD "PWD\r\n"
- #define RETR "RETR %s\r\n" //RETR — Скачать файл. Перед RETR должна быть команда PASV или PORT.
- #define LIST "LIST %s\r\n" // LIST Возвращает список файлов директории.
- #define STOR "STOR %s\r\n" // Закачать файл. Перед STOR должна быть команда PASV или PORT.
- static char buf[1024];
- static int bytes_read;
- static char my_ip[23];
- typedef void (*sighandler)(int);
- typedef struct {
- int sock;
- struct addrinfo *info;
- } conn_t;
- typedef void (*command_t) (conn_t *);
- conn_t* toListen = NULL, *toRecive = NULL;
- void to_default(conn_t *connection)
- {
- if (connection) {
- connection->sock = -1;
- connection->info = NULL;
- }
- }
- int is_one_answer(const char *buf, int len)
- {
- int i = 0;
- while(i < len && !(buf[i - 1] == '\r' && buf[i] == '\n')) ++i;
- if (i + 2 == len) return 0;
- if (i + 1 == len) return 0;
- return i + 1;
- }
- void close_handler(int c) { //экстренное завершение соединения из-за возникшей ошибки
- if (toListen && toListen->sock >= 0)
- close(toListen->sock);
- printf("Interupting programm. Closing connection.\n");
- exit(c);
- }
- conn_t *new_conn(const char *port, const char *ipAdress)
- {
- conn_t *conn = (conn_t *) malloc(sizeof(conn_t));
- to_default(conn);
- int status;
- struct addrinfo hints;
- memset(&hints, 0, sizeof hints);
- hints.ai_family = AF_INET; //AF_UNSPEC; hints.ai_socktype = SOCK_STREAM;
- if (ipAdress == NULL) hints.ai_flags = AI_PASSIVE;
- printf("connection port:%s\n", port);
- status = getaddrinfo(ipAdress, port, &hints, &(conn->info));
- conn->sock = socket(conn->info->ai_family, conn->info->ai_socktype,
- conn->info->ai_protocol); // установка сокета
- if (conn->sock < 0) {
- perror("socket");
- close_handler(1);
- }
- return conn;
- }
- int get_list(conn_t *connection) {
- char buf[1024];
- int bytes_read;
- while (1) {
- bytes_read = recv(connection->sock, buf, 1024, 0);
- if (bytes_read <= 0) {
- break;
- }
- write(1, buf, bytes_read);
- }
- close(connection->sock);
- freeaddrinfo(connection->info);
- free(connection);
- return 0;
- }
- int get_file(conn_t *connection, char *fileName) {
- int fileNameDescriptor = open(fileName, O_WRONLY | O_TRUNC | O_CREAT, 0664);
- printf("%s\n", fileName);
- char buf_here[1024];
- int bytes_read_here = 0;
- while ((bytes_read_here = recv(connection->sock, buf_here, 1000, 0)) > 0) {
- write(fileNameDescriptor,
- buf_here, bytes_read_here);
- }
- close(fileNameDescriptor);
- close(connection->sock);
- freeaddrinfo(connection->info);
- free(connection);
- return 0;
- }
- int get_command() {
- static char command[MAX_COMMAND_SIZE];
- int commandNum = -1;
- printf("ftp> ");
- scanf("%s", command);
- if (strcmp(command, "open") == 0) {
- commandNum = 1;
- }
- if (strcmp(command, "get") == 0) {
- commandNum = 2;
- }
- if (strcmp(command, "put") == 0) {
- commandNum = 3;
- }
- if (strcmp(command, "pwd") == 0) {
- commandNum = 4;
- }
- if (strcmp(command, "help") == 0) {
- commandNum = 5;
- }
- if (strcmp(command, "ls") == 0) {
- commandNum = 6;
- }
- if (strcmp(command, "quit") == 0) {
- commandNum = 0;
- }
- return commandNum;
- }
- int length(const char *str) {
- int count = 0;
- while (str[count++] != '\n');
- return count;
- }
- void get_ans(char *buf, int *bytes_read, int sock, int fileDescriptor) {
- *bytes_read = (int)recv(sock, buf, 1024, 0);
- buf[(*bytes_read)++] = '\n';
- if (fileDescriptor > -1)
- write(fileDescriptor, buf, *bytes_read);
- }
- void help(conn_t* c) {
- printf("open - open connection\n");
- printf("pwd\n");
- printf("get - get file\n");
- printf("put - put file\n");
- printf("quit\n");
- printf("help - help\n");
- printf("ls - list directory\n");
- }
- void open_(conn_t *toSend) { // открытие соединения
- static char ip_addr[15];
- do {
- scanf("%s", ip_addr);
- } while (strlen(ip_addr) == 0);
- *toSend = *(new_conn("21", ip_addr));
- if (connect(toSend->sock, toSend->info->ai_addr, toSend->info->ai_addrlen) < 0) {
- perror("connect");
- close_handler(2);
- }
- get_ans(buf, &bytes_read, toSend->sock, 1);
- if (strncmp(buf, "220", 3) != 0)
- to_default(toSend);
- else {
- printf("Write your login: ");
- char *username = (char *) malloc(sizeof(char) * 256);
- scanf("%s", username);
- char *user = (char *) malloc(sizeof(char) * (4 + 1 + strlen(username) + 2));
- sprintf(user, USER, username);
- free(username);
- send(toSend->sock, user, length(user) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- free(user);
- if (strncmp(buf, "331", 3) != 0)
- to_default(toSend);
- else {
- printf("Write your password: ");
- char *password = (char *) malloc(sizeof(char) * 256);
- scanf("%s", password);
- char *pass = (char *) malloc(sizeof(char) * (4 + 1 + strlen(password) + 2));
- sprintf(pass, PASS, password);
- free(password);
- send(toSend->sock, pass, length(pass) * sizeof(char), 0);
- free(pass);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- if (strncmp(buf, "230", 3) != 0) to_default(toSend);
- }
- }
- }
- void ls(conn_t *toSend) {//функция,которая выдает файлы из текущей директории
- int i = 0;
- int flag = 0;
- int tempNumber = 0;
- int mas[6] = {0, 0, 0, 0, 0, 0};
- int j = 0;
- char *ipAdress_toRecive = (char *) malloc(sizeof(char) * 15);
- char *port_toRecive = (char *) malloc
- (sizeof(char) * 5);
- if (toSend == NULL || toSend->info == NULL) return;
- char *dir = (char *) malloc(sizeof(char) * 15);
- scanf("%s", dir);
- char *list = (char *) malloc(sizeof(char) * (4 + 2));
- sprintf(list, LIST, dir);
- char type[] = "TYPE I\r\n";
- send(toSend->sock, type, length(type) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- if (strncmp(buf, "200", 3) == 0) {
- char pasv[] = "PASV\r\n";
- send(toSend->sock, pasv, length(pasv) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- if (strncmp(buf, "227", 3) == 0) {
- for (; i < length(buf); ++i) {
- if (buf[i] == '(') flag = 1;
- if (isdigit(buf[i]) && flag == 1)
- tempNumber = tempNumber * 10 + buf[i] - '0';
- if (buf[i] == ',' || buf[i] == ')') {
- mas[j++] = tempNumber;
- tempNumber = 0;
- }
- }
- sprintf(ipAdress_toRecive, "%d.%d.%d.%d", mas[0], mas[1], mas[2], mas[3]);
- sprintf(port_toRecive, "%d", mas[4] * 256 + mas[5]);
- toRecive = new_conn(port_toRecive, ipAdress_toRecive);
- if (connect(toRecive->sock, toRecive->info->ai_addr,
- toRecive->info->ai_addrlen) < 0) {
- perror("connect");
- close_handler(2);
- }
- send(toSend->sock, list, length(list) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- int wasSend = 0;
- if (strncmp(buf, "150", 3) == 0) {
- get_list(toRecive);
- if ((wasSend = is_one_answer(buf, bytes_read / (sizeof(char)))) == 0) {
- get_ans(buf + wasSend, &bytes_read, toSend->sock, 1);
- }
- }
- }
- }
- free(port_toRecive);
- free(ipAdress_toRecive);
- free(list);
- free(dir);
- }
- void get(conn_t *toSend) {//получение файла с сервера
- int i = 0;
- int flag = 0;
- int tempNumber = 0;
- int mas[6] = {0, 0, 0, 0, 0, 0};
- int j = 0;
- char *ipAdress_toRecive = (char *) malloc(sizeof(char) * 15);
- char *port_toRecive = (char *) malloc(sizeof(char) * 5);
- if (toSend == NULL || toSend->info == NULL) return;
- char *fileName = (char *) malloc(sizeof(char) * 256);
- char *nameFile = (char *) malloc(sizeof(char) * 256);
- scanf("%s", fileName);
- char *retr = (char *) malloc(sizeof(char) * (4 + 1 + strlen(fileName) + 2));
- sprintf(retr, RETR, fileName);
- char type[] = "TYPE I\r\n"; //тип файла
- send(toSend->sock, type, length(type) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- if (strncmp(buf, "200", 3) == 0) {
- char pasv[] = "PASV\r\n";
- send(toSend->sock, pasv, length(pasv) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- i = 0;
- if (strncmp(buf, "227", 3) == 0) {
- while(buf[i] != '(' && i < bytes_read) i++;
- }
- tempNumber = 0;
- while (i < bytes_read) {
- if (isdigit(buf[i]))
- tempNumber = tempNumber * 10 + buf[i] - '0';
- if (buf[i] == ',' || buf[i] == ')') {
- mas[j++] = tempNumber;
- tempNumber = 0;
- }
- i++;
- }
- }
- sprintf(ipAdress_toRecive, "%d.%d.%d.%d", mas[0], mas[1], mas[2], mas[3]);
- sprintf(port_toRecive, "%d", mas[4] * 256 + mas[5]);
- toRecive = new_conn(port_toRecive, ipAdress_toRecive);
- if (connect(toRecive->sock, toRecive->info->ai_addr, toRecive->info->ai_addrlen) < 0) {
- perror("connect");
- close_handler(2);
- }
- send(toSend->sock, retr, length(retr) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- int wasSend = 0;
- if (strncmp(buf, "150", 3) == 0) {
- sprintf(nameFile, "%s", basename(fileName));
- get_file(toRecive, nameFile);
- if ((wasSend = is_one_answer(buf, bytes_read / (sizeof(char)))) == 0) {
- get_ans(buf + wasSend, &bytes_read, toSend->sock, 1);
- }
- }
- free(port_toRecive);
- free(ipAdress_toRecive);
- free(fileName);
- free(nameFile);
- free(retr);
- }
- void put(conn_t *toSend) {//функция передачи файла на сервер
- int i = 0;
- int flag = 0;
- int tempNumber = 0;
- int mas[6] = {0, 0, 0, 0, 0, 0};
- int j = 0;
- char *ipAdress_toRecive = (char *) malloc(sizeof(char) * 15);
- char *port_toRecive = (char *) malloc
- (sizeof(char) * 5);
- if (toSend == NULL || toSend->info == NULL) return;
- char *fileName = (char *) malloc(sizeof(char) * 256);
- char *nameFile = (char *) malloc(sizeof(char) * 256);
- scanf("%s", fileName);
- char *stor = (char *) malloc(sizeof(char) * (4 + 1 + strlen(fileName) + 2));
- sprintf(stor, STOR, fileName);
- char type[] = "TYPE I\r\n";//тип файла
- send(toSend->sock, type, length(type) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- if (strncmp(buf, "200", 3) == 0) {
- char pasv[] = "PASV\r\n";
- send(toSend->sock, pasv, length(pasv) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- if (strncmp(buf, "227", 3) == 0) {
- for (; i < length(buf); ++i) {
- if (buf[i] == '(') flag = 1;
- if (isdigit(buf[i]) && flag == 1)
- tempNumber = tempNumber * 10 + buf[i] - '0';
- if (buf[i] == ',' || buf[i] == ')') {
- mas[j++] = tempNumber;
- tempNumber = 0;
- }
- }
- sprintf(ipAdress_toRecive, "%d.%d.%d.%d", mas[0], mas[1], mas[2], mas[3]);
- sprintf(port_toRecive, "%d", mas[4] * 256 + mas[5]);
- toRecive = new_conn(port_toRecive, ipAdress_toRecive);
- if (connect(toRecive->sock, toRecive->info->ai_addr, toRecive->info->ai_addrlen) < 0) {
- perror("connect");
- close_handler(2);
- }
- send(toSend->sock, stor, length(stor) * sizeof(char), 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- int wasSend = 0;
- if (strncmp(buf, "150", 3) == 0) {
- if ((wasSend = is_one_answer(buf, bytes_read / (sizeof(char)))) == 0) {
- get_ans(buf + wasSend,
- &bytes_read, toSend->sock, 1);
- }
- }
- }
- }
- free(port_toRecive);
- free(ipAdress_toRecive);
- free(fileName);
- free(nameFile);
- free(stor);
- }
- void pwd(conn_t *toSend) {//возвращает текущую директорию
- if (!toSend || !toSend->info)
- return;
- static char pwd[6];
- snprintf(pwd, 6, PWD);
- send(toSend->sock, pwd, 5, 0);
- get_ans(buf, &bytes_read, toSend->sock, 1);
- }
- void quit(conn_t *toSend) {
- printf("Bye-bye\n");
- close(toSend->sock);
- freeaddrinfo(toSend->info);
- }
- void main_loop() {
- conn_t toSend;
- command_t masOfCommands[] = {quit, open_, get, put, pwd, help, ls};
- int commandNum;
- do {
- commandNum = get_command();
- if (commandNum > -1)
- masOfCommands[commandNum](&toSend);
- } while (commandNum != 0);
- }
- void set_ip(char *ip) {
- struct ifaddrs *ifaddr, *ifa;
- int family, s;
- char host[NI_MAXHOST];
- if (getifaddrs(&ifaddr) == -1) {
- perror("getifaddrs");
- exit(EXIT_FAILURE);
- }
- for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
- family = ifa->ifa_addr->sa_family;
- if (family == AF_INET) {
- s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0,
- NI_NUMERICHOST);
- if (s != 0) {
- close_handler(-4);
- printf("getnameinfo() failed: %s\n", gai_strerror(s));
- }
- if (strcmp(ifa->ifa_name, "lo") != 0) {
- sprintf(ip, "%s", host);
- return;
- }
- }
- }
- }
- int main(int argc, char *argv[]) {
- set_ip(my_ip);
- signal(SIGINT, (sighandler) close_handler);
- main_loop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement