first stable version - fiche - A pastebin adjusted for gopher use | |
git clone git://vernunftzentrum.de/fiche.git | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit 829c8e16d81ac4f88f192e103b50ea874850696a | |
parent bcbc2791960567465518a1914c19604da186f077 | |
Author: solusipse <[email protected]> | |
Date: Fri, 6 Sep 2013 04:01:55 +0200 | |
first stable version | |
Diffstat: | |
Makefile | 15 +++++++++++++++ | |
README.md | 80 +++++++++++++++++++++++++++++++ | |
fiche.c | 239 +++++++++++++++++++++++++++++++ | |
fiche.h | 47 +++++++++++++++++++++++++++++++ | |
4 files changed, 381 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -0,0 +1,15 @@ | |
+# ----------------------------------- | |
+# Fiche MAKEFILE | |
+# https://github.com/solusipse/fiche | |
+# solusipse.net | |
+# ----------------------------------- | |
+ | |
+CC=gcc | |
+CFLAGS=-pthread -O2 | |
+prefix=/usr/local | |
+ | |
+all: fiche.c | |
+ $(CC) -o fiche $(CFLAGS) fiche.c | |
+ | |
+install: fiche | |
+ install -m 0755 fiche $(prefix)/bin | |
diff --git a/README.md b/README.md | |
@@ -2,3 +2,83 @@ fiche | |
===== | |
Command line pastebin for sharing terminal output. | |
+ | |
+## Installation ## | |
+ | |
+1. Clone into repository: | |
+ | |
+ ``` | |
+ https://github.com/solusipse/fiche.git | |
+ ``` | |
+ | |
+2. Build program: | |
+ | |
+ ``` | |
+ make | |
+ ``` | |
+ | |
+3. Install: | |
+ | |
+ ``` | |
+ sudo make install | |
+ ``` | |
+ | |
+## Client-side usage ## | |
+ | |
+Self explanatory live examples: | |
+ | |
+``` | |
+ls -la | nc localhost 9999 | |
+``` | |
+ | |
+``` | |
+cat file.txt | nc someserverrunningfiche.net 1234 | |
+``` | |
+ | |
+``` | |
+echo just testing! | nc code.solusipse.net 9999 | |
+``` | |
+ | |
+If you already haven't set up your server on localhost, try third line! My ser… | |
+pastebin server powered by fiche - ```code.solusipse.net``` on port ```9999```. | |
+ | |
+- To upload text you need to have netcat installed (to check if netcat is inst… | |
+ | |
+## Server-side usage ## | |
+ | |
+``` | |
+usage: fiche [-bdpqs]. | |
+ [-d host_domain.com] [-p port] [-s slug_size] | |
+ [-o output_directory] [-b buffer_size] [-q queue_size] | |
+``` | |
+ | |
+These are command line arguments. You don't have to provide any, but doing tha… | |
+will use these default settings: | |
+ | |
+```C | |
+domain = "http://localhost/"; | |
+basedir= "~/code/"; | |
+port = 9999; | |
+slug_size = 4; | |
+buffer_size = 8192; | |
+queue_size = 100; | |
+``` | |
+ | |
+### Basic arguments ### | |
+ | |
+Most important is providing **basedir** and **domain**. | |
+ | |
+Basedir should be **absolute** path to directory where you would like to store… | |
+ | |
+Domain should be provided in such format ```domain.com```. | |
+ | |
+Slug size: ```yourserver.com/SLUG_OF_CHOSEN_LENGTH/```. | |
+ | |
+### Parameters for advanced users ### | |
+ | |
+- Buffer size | |
+- Queue size | |
+ | |
+### License ### | |
+ | |
+Fiche is MIT licensed. | |
diff --git a/fiche.c b/fiche.c | |
@@ -0,0 +1,238 @@ | |
+/* | |
+Fiche - terminal pastebin | |
+Still in development, not usable! | |
+*/ | |
+ | |
+#include "fiche.h" | |
+ | |
+int main(int argc, char **argv) | |
+{ | |
+ srand((unsigned int) time(0)); | |
+ | |
+ set_basedir(); | |
+ parse_parameters(argc, argv); | |
+ startup_message(); | |
+ | |
+ int listen_socket, address_lenght, optval = 1; | |
+ struct sockaddr_in server_address; | |
+ | |
+ listen_socket = create_socket(); | |
+ setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval … | |
+ | |
+ server_address = set_address(server_address); | |
+ bind_to_port(listen_socket, server_address); | |
+ | |
+ while (1) perform_connection(listen_socket); | |
+} | |
+ | |
+void *thread_connection(void *args) | |
+{ | |
+ char buffer[BUFSIZE]; | |
+ int n, client = *(int *)args; | |
+ bzero(buffer, BUFSIZE); | |
+ | |
+ int status = recv(client, buffer, BUFSIZE, 0); | |
+ | |
+ if (status != -1) | |
+ { | |
+ char slug[SLUG_SIZE]; | |
+ generate_url(buffer, slug); | |
+ | |
+ char response[strlen(slug) + strlen(DOMAIN) + 2]; | |
+ strcpy(response, DOMAIN); | |
+ strcat(response, slug); | |
+ strcat(response, "/\n"); | |
+ write(client, response, strlen(response)); | |
+ } | |
+ else | |
+ { | |
+ printf("Invalid connection.\n"); | |
+ write(client, "Use netcat.\n", 13); | |
+ } | |
+ | |
+ close(client); | |
+ pthread_exit(NULL); | |
+ return NULL; | |
+} | |
+ | |
+void perform_connection(int listen_socket) | |
+{ | |
+ void *status = 0; | |
+ pthread_t thread_id; | |
+ struct sockaddr_in client_address; | |
+ | |
+ int address_lenght = sizeof(client_address); | |
+ int connection_socket = accept(listen_socket, (struct sockaddr *) &client_… | |
+ | |
+ struct timeval timeout; | |
+ timeout.tv_sec = 10; | |
+ timeout.tv_usec = 0; | |
+ | |
+ if (setsockopt (connection_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeo… | |
+ error(); | |
+ if (setsockopt (connection_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeo… | |
+ error(); | |
+ | |
+ get_client_address(client_address); | |
+ | |
+ if (pthread_create(&thread_id, NULL, &thread_connection, &connection_socke… | |
+ error(); | |
+ else | |
+ pthread_detach(thread_id); | |
+ | |
+} | |
+ | |
+void display_date() | |
+{ | |
+ time_t rawtime; | |
+ struct tm *timeinfo; | |
+ | |
+ time(&rawtime); | |
+ timeinfo = localtime(&rawtime); | |
+ printf("%s", asctime(timeinfo)); | |
+} | |
+ | |
+void get_client_address(struct sockaddr_in client_address) | |
+{ | |
+ display_line(); | |
+ | |
+ struct hostent *hostp; | |
+ char *hostaddrp; | |
+ | |
+ hostp = gethostbyaddr((const char *)&client_address.sin_addr.s_addr, sizeo… | |
+ if (hostp == NULL) error(); | |
+ | |
+ hostaddrp = inet_ntoa(client_address.sin_addr); | |
+ if (hostaddrp == NULL) error(); | |
+ | |
+ display_date(); | |
+ printf("Client: %s (%s)\n", hostaddrp, hostp->h_name); | |
+} | |
+ | |
+int create_socket() | |
+{ | |
+ int lsocket = socket(AF_INET, SOCK_STREAM, 0); | |
+ if (lsocket < 0) | |
+ error(); | |
+ else return lsocket; | |
+} | |
+ | |
+struct sockaddr_in set_address(struct sockaddr_in server_address) | |
+{ | |
+ bzero((char *) &server_address, sizeof(server_address)); | |
+ server_address.sin_family = AF_INET; | |
+ server_address.sin_addr.s_addr = htonl(INADDR_ANY); | |
+ server_address.sin_port = htons((unsigned short)PORT); | |
+ return server_address; | |
+} | |
+ | |
+void bind_to_port(int listen_socket, struct sockaddr_in server_address) | |
+{ | |
+ if (bind(listen_socket, (struct sockaddr *) &server_address, sizeof(server… | |
+ error(); | |
+ if (listen(listen_socket, QUEUE_SIZE) < 0) | |
+ error(); | |
+} | |
+ | |
+void generate_url(char *buffer, char *slug) | |
+{ | |
+ int i; | |
+ int time_seed = time(0); | |
+ memset(slug, '\0', sizeof(slug)); | |
+ | |
+ for (i = 0; i <= SLUG_SIZE - 1; i++) | |
+ { | |
+ int symbol_id = rand_r(&time_seed) % strlen(symbols); | |
+ slug[i] = symbols[symbol_id]; | |
+ } | |
+ | |
+ while (create_directory(slug) == -1) | |
+ { | |
+ int symbol_id = rand() % strlen(symbols); | |
+ slug[strlen(slug)] = symbols[symbol_id]; | |
+ } | |
+ | |
+ save_to_file(slug, buffer); | |
+} | |
+ | |
+int create_directory(char *slug) | |
+{ | |
+ char *directory = malloc(100); | |
+ | |
+ strcpy(directory, BASEDIR); | |
+ strcat(directory, slug); | |
+ | |
+ mkdir(BASEDIR, S_IRWXU | S_IRGRP | S_IROTH); | |
+ int result = mkdir(directory, S_IRWXU | S_IRGRP | S_IROTH); | |
+ | |
+ free(directory); | |
+ | |
+ return result; | |
+} | |
+ | |
+void save_to_file(char *slug, char *buffer) | |
+{ | |
+ char *directory = malloc(strlen(BASEDIR) + strlen(slug) + strlen("/index.h… | |
+ strcpy(directory, BASEDIR); | |
+ strcat(directory, slug); | |
+ strcat(directory, "/index.html"); | |
+ | |
+ FILE *fp; | |
+ fp = fopen(directory, "w"); | |
+ fprintf(fp, "%s", buffer); | |
+ fclose(fp); | |
+ | |
+ printf("Saved to: %s\n", directory); | |
+ free(directory); | |
+} | |
+ | |
+void set_basedir() | |
+{ | |
+ BASEDIR = getenv("HOME"); | |
+ strcat(BASEDIR, "/code/"); | |
+} | |
+ | |
+void startup_message() | |
+{ | |
+ printf("Fiche started listening on port %d.\n", PORT); | |
+ printf("Domain name: %s\n", DOMAIN); | |
+ printf("Saving files to: %s\n", BASEDIR); | |
+} | |
+ | |
+void parse_parameters(int argc, char **argv) | |
+{ | |
+ int c; | |
+ | |
+ while ((c = getopt (argc, argv, "p:b:q:s:d:o:")) != -1) | |
+ switch (c) | |
+ { | |
+ case 'd': | |
+ snprintf(DOMAIN, sizeof DOMAIN, "%s%s%s", "http://", optarg, "… | |
+ break; | |
+ case 'p': | |
+ PORT = atoi(optarg); | |
+ break; | |
+ case 'b': | |
+ BUFSIZE = atoi(optarg); | |
+ printf("Buffer size set to: %d.\n", BUFSIZE); | |
+ break; | |
+ case 'q': | |
+ QUEUE_SIZE = atoi(optarg); | |
+ printf("Queue size set to: %d.\n", QUEUE_SIZE); | |
+ break; | |
+ case 's': | |
+ SLUG_SIZE = atoi(optarg); | |
+ printf("Slug size set to: %d.\n", SLUG_SIZE); | |
+ break; | |
+ case 'o': | |
+ BASEDIR = optarg; | |
+ if((BASEDIR[strlen(BASEDIR) - 1]) != '/') | |
+ strcat(BASEDIR, "/"); | |
+ break; | |
+ default: | |
+ printf("usage: fiche [-bdpqs].\n"); | |
+ printf(" [-d host_domain.com] [-p port] [-s slug_s… | |
+ printf(" [-o output_directory] [-b buffer_size] [-… | |
+ exit(1); | |
+ } | |
+} | |
+\ No newline at end of file | |
diff --git a/fiche.h b/fiche.h | |
@@ -0,0 +1,46 @@ | |
+/* | |
+Fiche - terminal pastebin | |
+*/ | |
+ | |
+#ifndef FICHE_H | |
+#define FICHE_H | |
+ | |
+#include <stdio.h> | |
+#include <unistd.h> | |
+#include <stdlib.h> | |
+#include <string.h> | |
+#include <netdb.h> | |
+#include <sys/types.h> | |
+#include <sys/socket.h> | |
+#include <netinet/in.h> | |
+#include <arpa/inet.h> | |
+#include <pthread.h> | |
+#include <time.h> | |
+#include <sys/stat.h> | |
+ | |
+int BUFSIZE = 8192; | |
+int QUEUE_SIZE = 100; | |
+int PORT = 9999; | |
+int SLUG_SIZE = 4; | |
+char *BASEDIR; | |
+char DOMAIN[128] = "http://localhost/"; | |
+const char *symbols = "abcdefghijklmnopqrstuvwxyz0123456789"; | |
+ | |
+int create_socket(); | |
+int create_directory(char *slug); | |
+ | |
+void bind_to_port(int listen_socket, struct sockaddr_in serveraddr); | |
+void display_line(){printf("====================================\n");} | |
+void error(){perror("ERROR"); exit(1);} | |
+void display_date(); | |
+void get_client_address(struct sockaddr_in client_address); | |
+void perform_connection(int listen_socket); | |
+void generate_url(char *buffer, char *slug); | |
+void save_to_file(char *buffer, char *slug); | |
+void startup_message(); | |
+void set_basedir(); | |
+void parse_parameters(int argc, char **argv); | |
+ | |
+struct sockaddr_in set_address(struct sockaddr_in serveraddr); | |
+ | |
+#endif | |
+\ No newline at end of file |