diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/Makefile | 5 | ||||
-rw-r--r-- | client/nft.c | 415 |
2 files changed, 420 insertions, 0 deletions
diff --git a/client/Makefile b/client/Makefile new file mode 100644 index 0000000..9869b14 --- /dev/null +++ b/client/Makefile @@ -0,0 +1,5 @@ +nft: nft.c + $(CC) -o nft nft.c + +clean: + rm -f nft core nft.exe diff --git a/client/nft.c b/client/nft.c new file mode 100644 index 0000000..9d03295 --- /dev/null +++ b/client/nft.c @@ -0,0 +1,415 @@ +/* Next File Transfer Client + Copyright (C) 2020 Ian Cowburn + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <netdb.h> + +static const char *name; + + +static void *Malloc(size_t len) +{ + void *p; + + p = malloc(len); + + if (!p) + { + perror(name); + exit(EXIT_FAILURE); + } + + return p; +} + + +static char *GetLine(char *buff, size_t len) +{ + size_t l; + + if (feof(stdin)) + { + return NULL; + } + + printf("NFT> "); + + if (!fgets(buff, len, stdin)) + { + return NULL; + } + + l = strlen(buff); + + if (l > 0 && buff[l-1]=='\n') + { + buff[l-1]=0; + } + + if (l) + { + return buff; + } + else + { + return GetLine(buff, len); + } +} + + +static int Connect(const char *n, int p) +{ + struct hostent *remote; + struct sockaddr_in addr; + int sock; + + if (!(remote = gethostbyname(n))) + { + fprintf(stderr,"%s: unknown host %s\n",name,n); + exit(EXIT_FAILURE); + } + + memcpy(&addr.sin_addr, remote->h_addr, remote->h_length); + + if ((sock = socket(AF_INET, SOCK_STREAM, 0))==-1) + { + perror(name); + exit(EXIT_FAILURE); + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(p); + + if (connect(sock,(void*)&addr,sizeof(addr)) == -1) + { + perror(name); + exit(EXIT_FAILURE); + } + + return sock; +} + + +static int Read(int sock, char *buff, size_t len) +{ + while(len > 0) + { + size_t rd; + + rd = read(sock, buff, len); + + if (rd == -1) + { + perror(name); + return 0; + } + else if (rd == 0) + { + return 0; + } + else + { + len -= rd; + buff += rd; + } + } + + return 1; +} + + +static int Write(int sock, const char *buff, size_t len) +{ + while(len > 0) + { + size_t wr; + + wr = write(sock, buff, len); + + if (wr == -1) + { + perror(name); + return 0; + } + else if (wr == 0) + { + return 0; + } + else + { + len -= wr; + buff += wr; + } + } + + return 1; +} + + +static int WriteBlock(int sock, const char *block, size_t len) +{ + char buff[32]; + + if (len > 99999) + { + fprintf(stderr, "%s: length of block %zu too large\n", name, len); + return 0; + } + + snprintf(buff, sizeof buff, "%.5zu", len); + + if (!Write(sock, buff, 5)) + { + return 0; + } + + if (!Write(sock, block, len)) + { + return 0; + } + + return 1; +} + + +static size_t ReadSize(int sock) +{ + char buff[32]; + + if (!Read(sock, buff, 5)) + { + return 0; + } + + return atoi(buff); +} + + +static size_t FileSize(const char *path) +{ + struct stat st; + + if (stat(path, &st) == 0) + { + return st.st_size; + } + else + { + return 0; + } +} + + +static int Put(int sock, const char *path) +{ + int quit = 0; + char status[3] = {0}; + size_t len; + int fd; + + if ((len = FileSize(path)) == 0) + { + perror(path); + } + else + { + char *buff; + int fd; + + buff = Malloc(len); + + fd = open(path, O_RDONLY); + read(fd, buff, len); + close(fd); + + if (!Write(sock, "PF", 2)) + { + quit = 1; + } + + if (!quit && !WriteBlock(sock, path, strlen(path))) + { + quit = 1; + } + + if (!quit && !WriteBlock(sock, buff, len)) + { + quit = 1; + } + + if (!quit && Read(sock, status, 2)) + { + if (strcmp(status, "!E") == 0) + { + printf("Command failed\n"); + } + } + else + { + quit = 1; + } + + } + + return quit; +} + + +static int Get(int sock, const char *path) +{ + int quit = 0; + char status[3] = {0}; + int fd; + + if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC)) == -1) + { + perror(path); + return 0; + } + + if (!Write(sock, "GF", 2)) + { + quit = 1; + } + + if (!quit && !WriteBlock(sock, path, strlen(path))) + { + quit = 1; + } + + if (!quit && Read(sock, status, 2)) + { + if (strcmp(status, "!E") == 0) + { + printf("Command failed\n"); + } + else + { + size_t len; + + if ((len = ReadSize(sock)) > 0) + { + char buff[100000]; + + if (Read(sock, buff, len)) + { + write(fd, buff, len); + } + else + { + quit = 1; + } + } + } + } + else + { + quit = 1; + } + + close(fd); + + return quit; +} + + +static int Cd(int sock, const char *path) +{ + int quit = 0; + + return quit; +} + + +static int Mkdir(int sock, const char *path) +{ + int quit = 0; + + return quit; +} + + +int main(int argc, char *argv[]) +{ + char buff[1024]; + int sock; + int quit = 0; + + if ((name = strrchr(argv[0], '/'))) + { + name++; + } + else + { + name = argv[0]; + } + + if (argc<3) + { + fprintf(stderr,"%s: usage %s host port\n",name,name); + exit(EXIT_FAILURE); + } + + sock = Connect(argv[1],atoi(argv[2])); + + while(!quit && GetLine(buff, sizeof buff)) + { + char *tok; + + tok = strtok(buff, " \t"); + + if (strcmp(tok, "exit") == 0) + { + break; + } + else if (strcmp(tok, "put") == 0) + { + quit = Put(sock, strtok(NULL, " \t")); + } + else if (strcmp(tok, "get") == 0) + { + quit = Get(sock, strtok(NULL, " \t")); + } + else if (strcmp(tok, "cd") == 0) + { + quit = Cd(sock, strtok(NULL, " \t")); + } + else if (strcmp(tok, "mkdir") == 0) + { + quit = Mkdir(sock, strtok(NULL, " \t")); + } + else + { + printf("Unrecognised command '%s'\n", tok); + } + } + + close(sock); + + return EXIT_SUCCESS; +} |