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);
+}