tBasic client/server returning timestamp - synk - synchronize files between hosts
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit d19f7b2d444e65f4d780ac3132968e432110ede9
 (DIR) parent bc0015b7394a71bac114b9f8f836d27f6b3de890
 (HTM) Author: Willy <willyatmailoodotorg>
       Date:   Fri, 12 Aug 2016 02:22:39 +0200
       
       Basic client/server returning timestamp
       
       Server reads file path on client's socket, and return the UNIX timestamp
       of the last modification time for this file to the client.
       
       Diffstat:
         A LICENSE                             |      13 +++++++++++++
         A arg.h                               |      65 +++++++++++++++++++++++++++++++
         A config.mk                           |      12 ++++++++++++
         A mkfile                              |      20 ++++++++++++++++++++
         A synk.c                              |      71 +++++++++++++++++++++++++++++++
         A synkd.c                             |     124 +++++++++++++++++++++++++++++++
       
       6 files changed, 305 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/LICENSE b/LICENSE
       t@@ -0,0 +1,13 @@
       +Copyright (c) 2016 z3bra <willyatmailoodotorg>
       +
       +Permission to use, copy, modify, and distribute this software for any
       +purpose with or without fee is hereby granted, provided that the above
       +copyright notice and this permission notice appear in all copies.
       +
       +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
       +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
       +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
       +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
       +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
       +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
       +PERFORMANCE OF THIS SOFTWARE.
 (DIR) diff --git a/arg.h b/arg.h
       t@@ -0,0 +1,65 @@
       +/*
       + * Copy me if you can.
       + * by 20h
       + */
       +
       +#ifndef ARG_H__
       +#define ARG_H__
       +
       +extern char *argv0;
       +
       +/* use main(int argc, char *argv[]) */
       +#define ARGBEGIN        for (argv0 = *argv, argv++, argc--;\
       +                                        argv[0] && argv[0][1]\
       +                                        && argv[0][0] == '-';\
       +                                        argc--, argv++) {\
       +                                char argc_;\
       +                                char **argv_;\
       +                                int brk_;\
       +                                if (argv[0][1] == '-' && argv[0][2] == '\0') {\
       +                                        argv++;\
       +                                        argc--;\
       +                                        break;\
       +                                }\
       +                                for (brk_ = 0, argv[0]++, argv_ = argv;\
       +                                                argv[0][0] && !brk_;\
       +                                                argv[0]++) {\
       +                                        if (argv_ != argv)\
       +                                                break;\
       +                                        argc_ = argv[0][0];\
       +                                        switch (argc_)
       +
       +/* Handles obsolete -NUM syntax */
       +#define ARGNUM                                case '0':\
       +                                        case '1':\
       +                                        case '2':\
       +                                        case '3':\
       +                                        case '4':\
       +                                        case '5':\
       +                                        case '6':\
       +                                        case '7':\
       +                                        case '8':\
       +                                        case '9'
       +
       +#define ARGEND                        }\
       +                        }
       +
       +#define ARGC()                argc_
       +
       +#define ARGNUMF()        (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
       +
       +#define EARGF(x)        ((argv[0][1] == '\0' && argv[1] == NULL)?\
       +                                ((x), abort(), (char *)0) :\
       +                                (brk_ = 1, (argv[0][1] != '\0')?\
       +                                        (&argv[0][1]) :\
       +                                        (argc--, argv++, argv[0])))
       +
       +#define ARGF()                ((argv[0][1] == '\0' && argv[1] == NULL)?\
       +                                (char *)0 :\
       +                                (brk_ = 1, (argv[0][1] != '\0')?\
       +                                        (&argv[0][1]) :\
       +                                        (argc--, argv++, argv[0])))
       +
       +#define LNGARG()        &argv[0][0]
       +
       +#endif
 (DIR) diff --git a/config.mk b/config.mk
       t@@ -0,0 +1,12 @@
       +VERSION = 0.0
       +
       +CC = cc
       +LD = ${CC}
       +
       +PREFIX = /usr/local
       +MANDIR = ${PREFIX}/man
       +
       +CPPFLAGS = -DVERSION=\"${VERSION}\"
       +CFLAGS = ${CPPFLAGS} -Wall -Wextra -pedantic -g
       +LDFLAGS =
       +LIBS = -lpthread
 (DIR) diff --git a/mkfile b/mkfile
       t@@ -0,0 +1,20 @@
       +<config.mk
       +
       +all:V: synk synkd
       +
       +%: %.o
       +        $LD -o $target $prereq $LDFLAGS $LIBS
       +
       +%.o: %.c
       +        $CC $CFLAGS -c $stem.c -o $stem.o
       +
       +clean:V:
       +        rm -f *.o synk synkd
       +
       +install:V: all
       +        mkdir -p ${DESTDIR}${PREFIX}/bin
       +        cp synk ${DESTDIR}${PREFIX}/bin/synk
       +        chmod 755 ${DESTDIR}${PREFIX}/bin/synk
       +
       +uninstall:V:
       +        rm ${DESTDIR}${PREFIX}/bin/synk
 (DIR) diff --git a/synk.c b/synk.c
       t@@ -0,0 +1,71 @@
       +#include <limits.h>
       +#include <pthread.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <unistd.h>
       +#include <arpa/inet.h>
       +#include <sys/socket.h>
       +#include <sys/stat.h>
       +#include <sys/types.h>
       +
       +#include "arg.h"
       +
       +#define SERVER_HOST "127.0.0.1"
       +#define SERVER_PORT 9723
       +
       +void
       +usage(char *name)
       +{
       +        fprintf(stderr, "usage: %s [-h HOST] [-p PORT] FILE\n", name),
       +        exit(1);
       +}
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        int cfd;
       +        char *argv0;
       +        size_t len = 0;
       +        uint16_t port = SERVER_PORT;
       +        uint32_t host = INADDR_LOOPBACK;
       +        struct sockaddr_in clt;
       +        char path[PATH_MAX] = "", ts[32] = "";
       +
       +        ARGBEGIN{
       +        case 'h': host = atol(EARGF(usage(argv0))); break;
       +        case 'p': port = atoi(EARGF(usage(argv0))); break;
       +        }ARGEND;
       +
       +        if (argc < 2)
       +                return 1;
       +        
       +        if ((cfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
       +                perror("socket");
       +                return 1;
       +        }
       +
       +        memset(&clt, 0, sizeof(clt));
       +        clt.sin_family        = AF_INET;
       +        clt.sin_addr.s_addr   = htonl(host);
       +        clt.sin_port          = htons(port);
       +
       +        if (connect(cfd, (struct sockaddr *)&clt, sizeof(clt)) < 0) {
       +                perror("connect");
       +                return 1;
       +        }
       +
       +        snprintf(path, PATH_MAX, "%s", argv[1]);
       +        len = strnlen(path, PATH_MAX);
       +        if (send(cfd, path, len, 0) < 0) {
       +                perror("send");
       +                return -1;
       +        }
       +
       +        send(cfd, "\n", 1, 0);
       +
       +        recv(cfd, ts, 32, 0);
       +        printf("%s: %s\n", path, ts);
       +
       +        return 0;
       +}
 (DIR) diff --git a/synkd.c b/synkd.c
       t@@ -0,0 +1,124 @@
       +#include <limits.h>
       +#include <pthread.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <unistd.h>
       +#include <arpa/inet.h>
       +#include <sys/socket.h>
       +#include <sys/stat.h>
       +#include <sys/types.h>
       +
       +#include "arg.h"
       +
       +#define LISTEN_PORT 9723
       +#define MAXCONN 10
       +
       +struct client_t {
       +        int fd;
       +        struct in_addr in;        
       +};
       +
       +void
       +usage(char *name) {
       +        fprintf(stderr, "usage: %s [-h HOST] [-p PORT]\n", name);
       +        exit(1);
       +}
       +
       +void *
       +handle_client(void *arg)
       +{
       +        int i = 0;
       +        char buf, path[PATH_MAX] = "", ts[32] = "";
       +        size_t len = 0;
       +        struct stat sb;
       +        struct client_t *c = *(struct client_t **)arg;
       +
       +        printf("%s: connected\n", inet_ntoa(c->in));
       +        while ((len = recv(c->fd, &buf, 1, 0)) > 0) {
       +                if (i > PATH_MAX) {
       +                        printf("%s: filename too long (>%d)\n", inet_ntoa(c->in), PATH_MAX);
       +                        break;
       +                }
       +
       +                if (buf == '\n' || buf == '\0') {
       +                        printf("%s: %s\n", inet_ntoa(c->in), path);
       +                        stat(path, &sb);
       +                        snprintf(ts, 32, "%lu", sb.st_mtim.tv_sec);
       +                        len = strnlen(ts, 32);
       +                        send(c->fd, ts, len, 0);
       +                        memset(path, 0, PATH_MAX);
       +                        i = 0;
       +                } else {
       +                        path[i++] = buf;
       +                }
       +        }
       +
       +        close(c->fd);
       +        len = 0;
       +        printf("%s: disconnected\n", inet_ntoa(c->in));
       +        free(c);
       +        pthread_exit((int *)&len);
       +}
       +
       +int
       +loop(int sfd)
       +{
       +        int cfd;
       +        socklen_t len;
       +        struct sockaddr_in clt;
       +        struct client_t *c = NULL;
       +        pthread_t th;
       +
       +        for (;;) {
       +                len = sizeof(clt);
       +                if ((cfd = accept(sfd, (struct sockaddr *)&clt, &len)) < 0) {
       +                        perror("accept");
       +                        return 1;
       +                }
       +
       +                c = malloc(sizeof(struct client_t));
       +                c->fd = cfd;
       +                c->in = clt.sin_addr;
       +
       +                pthread_create(&th, NULL, handle_client, &c);
       +        }
       +}
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        int sfd;
       +        char *argv0;
       +        uint16_t port = LISTEN_PORT;
       +        uint32_t host = INADDR_LOOPBACK;
       +        struct sockaddr_in srv;
       +
       +        ARGBEGIN{
       +        case 'p':
       +                port = atoi(EARGF(usage(argv0)));
       +                break;
       +        }ARGEND;
       +        
       +        if ((sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
       +                perror("socket");
       +                return 1;
       +        }
       +
       +        memset(&srv, 0, sizeof(srv));
       +        srv.sin_family        = AF_INET;
       +        srv.sin_addr.s_addr   = htonl(host);
       +        srv.sin_port          = htons(port);
       +
       +        if (bind(sfd, (struct sockaddr *)&srv, sizeof(srv)) < 0) {
       +                perror("bind");
       +                return 1;
       +        }
       +
       +        if (listen(sfd, MAXCONN) < 0) {
       +                perror("listen");
       +                return 1;
       +        }
       +
       +        return loop(sfd);
       +}