CFLAGS += -I../ucx -I..
SRC = main.c
+SRC += srvctrl.c
OBJ = $(SRC:%.c=$(BUILD_ROOT)/build/mizucp/%.$(OBJ_EXT))
#include "main.h"
+#include "srvctrl.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucx/utils.h>
-#define OPTSTR "hlpsuv"
-#define TIMEOUT_IDLE -1
-#define TIMEOUT_CLIENT 1000
-#define CLIENT_UPDATE_INTERVALL 1
-static char *cfgdir;
-static char *socket_path;
+#define OPTSTR "hlpsuv"
+
-static int srvctrl;
-static int eventp[2];
+static char *cfgdir;
+static char *copydir;
int main(int argc, char** argv) {
int ret = 1;
// copy
settings.from = argv[optind];
settings.to = argv[optind+1];
- ret = uwcp_copy(&settings);
+ ret = mzcp_copy(&settings);
} else {
// print usage
return ret;
}
-static int check_configdir(void) {
- char *home = getenv(UWCP_ENV_HOME);
-
- cfgdir = util_concat_path(home, UWCP_CFG_DIR);
-
+static int check_dir(const char *path) {
struct stat s;
- if(stat(cfgdir, &s)) {
+ if(stat(path, &s)) {
if(errno == ENOENT) {
- if(mkdir(cfgdir, S_IRWXU)) {
- fprintf(stderr, "Cannot create %s: %s", cfgdir, strerror(errno));
+ if(mkdir(path, S_IRWXU)) {
+ fprintf(stderr, "Cannot create %s: %s", path, strerror(errno));
return 1;
}
} else {
- fprintf(stderr, "Cannot access %s: %s", cfgdir, strerror(errno));
+ fprintf(stderr, "Cannot access %s: %s", path, strerror(errno));
return 1;
}
}
-
return 0;
}
-static int create_control_socket(void) {
- char *copydir = util_concat_path(cfgdir, UWCP_COPY_DIR);
-
- struct stat s;
- if(stat(copydir, &s)) {
- if(errno == ENOENT) {
- if(mkdir(copydir, S_IRWXU)) {
- fprintf(stderr, "Cannot create %s: %s", copydir, strerror(errno));
- return 1;
- }
- } else {
- fprintf(stderr, "Cannot access %s: %s", copydir, strerror(errno));
- return 1;
- }
- }
-
- // create unix domain socket
- char *random_str = util_random_str();
- sstr_t socketp = ucx_sprintf("%s/%.*s", copydir, 8, random_str);
- free(random_str);
- socket_path = socketp.ptr;
-
- struct sockaddr_un addr;
- if(socketp.length > sizeof(addr.sun_path)-1) {
- fprintf(stderr,
- "path '%s' too long for unix domain socket",
- socketp.ptr);
- return 1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- memcpy(addr.sun_path, socketp.ptr, socketp.length);
+static int check_configdir(void) {
+ char *home = getenv(MZCP_ENV_HOME);
- srvctrl = socket(AF_UNIX, SOCK_STREAM, 0);
- if(srvctrl == -1) {
- fprintf(stderr,
- "Cannot create server control socket: %s",
- strerror(errno));
- return 1;
- }
- if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) {
- fprintf(stderr,
- "srvctrl socket bind failed: %s",
- strerror(errno));
- return 1;
- }
+ char *base = util_concat_path(home, MZCP_CFG_BASE);
+ if(check_dir(base)) return 1;
+ free(base);
+
+ cfgdir = util_concat_path(home, MZCP_CFG_DIR);
+ if(check_dir(cfgdir)) return 1;
- listen(srvctrl, 4);
+ copydir = util_concat_path(mzcp_get_cfgdir(), MZCP_COPY_DIR);
+ if(check_dir(copydir)) return 1;
return 0;
}
-int uwcp_copy(CPSettings *settings) {
+const char* mzcp_get_cfgdir(void) {
+ return cfgdir;
+}
+
+const char* mzcp_get_copydir(void) {
+ return copydir;
+}
+
+int mzcp_copy(CPSettings *settings) {
int ret = 0;
if(check_configdir()) {
}
if(settings->printsocket) {
- printf("%s\n", socket_path);
+ printf("%s\n", mzcp_get_socketpath());
} else {
printf("copy %s to %s\n", settings->from, settings->to);
if(settings->pause) {
//close(1);
//close(2);
- ret = uwcp_srvctrl(settings);
+ ret = mzcp_srvctrl(settings);
}
return ret;
}
-
-int uwcp_srvctrl(CPSettings *settings) {
- if(pipe(eventp)) {
- perror("Cannot create event pipe");
- return 1;
- }
-
- size_t allocfds = 8;
- size_t numfds = 1;
-
- struct pollfd *fds = calloc(allocfds, sizeof(struct pollfd));
- CtrlClient **clients = calloc(allocfds, sizeof(void*));
-
- int timeout = TIMEOUT_IDLE;
-
- fds[0].fd = srvctrl;
- fds[0].events = POLLIN;
-
- int abort = 0;
-
- time_t tbegin = time(NULL);
-
- while(poll(fds, numfds, 1000) >= 0) {
- time_t tend = time(NULL);
- time_t diff = tend - tbegin;
- tbegin = tend;
-
- if((fds[0].revents & POLLIN) == POLLIN) {
- printf("accept\n");
- int fd = accept(srvctrl, NULL, 0);
- if(fd < 0) {
- break;
- }
-
- //int flags = fcntl(fd, F_GETFL, 0);
- //flags = flags & ~O_NONBLOCK;
- //fcntl(fd, F_SETFL, flags);
-
- CtrlClient *client = malloc(sizeof(CtrlClient));
- memset(client, 0, sizeof(CtrlClient));
- client->fd = fd;
-
- printf("add client: %d\n", client->fd);
-
- fds[numfds].fd = client->fd;
- fds[numfds].events = POLLIN;
- fds[numfds].revents = 0;
- clients[numfds] = client;
- numfds++;
- }
-
- // check clients
- int remove = 0;
- for(int i=1;i<numfds;i++) {
- if((fds[i].revents & POLLIN) == POLLIN) {
- CtrlClient *client = clients[i];
- ssize_t r = read(fds[i].fd, client->buf + client->pos, CLIENT_MSG_BUFSIZE - client->pos);
- if(r <= 0) {
- printf("remove client: %d\n", fds[i].fd);
- fds[i].events = 0;
- remove = 1;
- } else {
- client->pos += r;
-
- int msgret = handle_messages(client);
- if(msgret == 1) {
- fds[i].events = 0;
- remove = 1;
- } else if(msgret == -1) {
- abort = 1;
- }
- }
- }
- }
-
- if(remove) {
- int j = 1;
- for(int i=1;i<numfds;i++) {
- if(fds[i].events != 0) {
- fds[j] = fds[i];
- clients[j] = clients[j];
- j++;
- } else {
- client_free(clients[i]);
- close(fds[i].fd);
- }
- }
- numfds = j;
- }
-
- if(diff >= CLIENT_UPDATE_INTERVALL) {
- for(int i=1;i<numfds;i++) {
- client_send_status(clients[i]);
- }
- }
-
- if(abort) break;
-
- timeout = numfds > 1 ? TIMEOUT_CLIENT : TIMEOUT_IDLE;
- }
-
- unlink(socket_path);
-
- return 0;
-}
-
-
-void client_free(CtrlClient *client) {
- free(client);
-}
-
-int handle_messages(CtrlClient *client) {
- if(client->pos == CLIENT_MSG_BUFSIZE) {
- return 1;
- }
-
- int msgstart = 0;
- for(int i=0;i<client->pos;i++) {
- if(client->buf[i] == '\n') {
- sstr_t msg;
- msg.ptr = &client->buf[msgstart];
- msg.length = i - msgstart;
- msgstart = i+1;
-
- int msgret = handle_client_msg(client, msg);
- if(msgret) return msgret;
- }
- }
-
- if(msgstart < client->pos) {
- // incomplete message
- memmove(client->buf, client->buf + msgstart, client->pos - msgstart);
- client->pos -= msgstart;
- } else {
- client->pos = 0;
- }
-
- return 0;
-}
-
-int handle_client_msg(CtrlClient *client, sstr_t msg) {
- printf("msg: %.*s\n", (int)msg.length, msg.ptr);
-
- if(!sstrcmp(msg, S("abort"))) {
- return -1;
- }
-
- return 0;
-}
-
-void client_send_status(CtrlClient *client) {
- char *msg = "s 0\n";
- write(client->fd, msg, strlen(msg));
-}
extern "C" {
#endif
-#define UWCP_ENV_HOME "HOME"
-#define UWCP_CFG_DIR ".uwfile"
-#define UWCP_COPY_DIR "copy"
+#define MZCP_ENV_HOME "HOME"
+#define MZCP_CFG_BASE ".config"
+#define MZCP_CFG_DIR ".config/mizunara"
+#define MZCP_COPY_DIR "copy"
#define CLIENT_MSG_BUFSIZE 512
CPBool printsocket;
} CPSettings;
-typedef struct {
- int fd;
- char buf[CLIENT_MSG_BUFSIZE];
- size_t pos;
-} CtrlClient;
-
-int uwcp_copy(CPSettings *settings);
-
-int uwcp_srvctrl(CPSettings *settings);
+const char* mzcp_get_cfgdir(void);
+const char* mzcp_get_copydir(void);
-void client_free(CtrlClient *client);
+int mzcp_copy(CPSettings *settings);
-int handle_messages(CtrlClient *client);
-int handle_client_msg(CtrlClient *client, sstr_t msg);
-void client_send_status(CtrlClient *client);
#ifdef __cplusplus
}
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2021 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "srvctrl.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/fcntl.h>
+#include <pthread.h>
+#include <poll.h>
+
+#include <ucx/utils.h>
+#include <libidav/utils.h>
+
+#define TIMEOUT_IDLE -1
+#define TIMEOUT_CLIENT 1000
+#define CLIENT_UPDATE_INTERVALL 1
+
+static char *socket_path;
+
+static int srvctrl;
+
+
+int create_control_socket(void) {
+ const char *copydir = mzcp_get_copydir();
+
+ // create unix domain socket
+ char *random_str = util_random_str();
+ sstr_t socketp = ucx_sprintf("%s/%.*s", copydir, 8, random_str);
+ free(random_str);
+ socket_path = socketp.ptr;
+
+ struct sockaddr_un addr;
+ if(socketp.length > sizeof(addr.sun_path)-1) {
+ fprintf(stderr,
+ "path '%s' too long for unix domain socket",
+ socketp.ptr);
+ return 1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, socketp.ptr, socketp.length);
+
+ srvctrl = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(srvctrl == -1) {
+ fprintf(stderr,
+ "Cannot create server control socket: %s",
+ strerror(errno));
+ return 1;
+ }
+ if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) {
+ fprintf(stderr,
+ "srvctrl socket bind failed: %s",
+ strerror(errno));
+ return 1;
+ }
+
+ listen(srvctrl, 4);
+
+ return 0;
+}
+
+const char* mzcp_get_socketpath(void) {
+ return socket_path;
+}
+
+int mzcp_srvctrl(CPSettings *settings) {
+
+ size_t allocfds = 8;
+ size_t numfds = 1;
+
+ struct pollfd *fds = calloc(allocfds, sizeof(struct pollfd));
+ CtrlClient **clients = calloc(allocfds, sizeof(void*));
+
+ int timeout = TIMEOUT_IDLE;
+
+ fds[0].fd = srvctrl;
+ fds[0].events = POLLIN;
+
+ int abort = 0;
+
+ time_t tbegin = time(NULL);
+
+ while(poll(fds, numfds, 1000) >= 0) {
+ time_t tend = time(NULL);
+ time_t diff = tend - tbegin;
+ tbegin = tend;
+
+ if((fds[0].revents & POLLIN) == POLLIN) {
+ printf("accept\n");
+ int fd = accept(srvctrl, NULL, 0);
+ if(fd < 0) {
+ break;
+ }
+
+ //int flags = fcntl(fd, F_GETFL, 0);
+ //flags = flags & ~O_NONBLOCK;
+ //fcntl(fd, F_SETFL, flags);
+
+ CtrlClient *client = malloc(sizeof(CtrlClient));
+ memset(client, 0, sizeof(CtrlClient));
+ client->fd = fd;
+
+ printf("add client: %d\n", client->fd);
+
+ fds[numfds].fd = client->fd;
+ fds[numfds].events = POLLIN;
+ fds[numfds].revents = 0;
+ clients[numfds] = client;
+ numfds++;
+ }
+
+ // check clients
+ int remove = 0;
+ for(int i=1;i<numfds;i++) {
+ if((fds[i].revents & POLLIN) == POLLIN) {
+ CtrlClient *client = clients[i];
+ ssize_t r = read(fds[i].fd, client->buf + client->pos, CLIENT_MSG_BUFSIZE - client->pos);
+ if(r <= 0) {
+ printf("remove client: %d\n", fds[i].fd);
+ fds[i].events = 0;
+ remove = 1;
+ } else {
+ client->pos += r;
+
+ int msgret = handle_messages(client);
+ if(msgret == 1) {
+ fds[i].events = 0;
+ remove = 1;
+ } else if(msgret == -1) {
+ abort = 1;
+ }
+ }
+ }
+ }
+
+ if(remove) {
+ int j = 1;
+ for(int i=1;i<numfds;i++) {
+ if(fds[i].events != 0) {
+ fds[j] = fds[i];
+ clients[j] = clients[j];
+ j++;
+ } else {
+ client_free(clients[i]);
+ close(fds[i].fd);
+ }
+ }
+ numfds = j;
+ }
+
+ if(diff >= CLIENT_UPDATE_INTERVALL) {
+ for(int i=1;i<numfds;i++) {
+ client_send_status(clients[i]);
+ }
+ }
+
+ if(abort) break;
+
+ timeout = numfds > 1 ? TIMEOUT_CLIENT : TIMEOUT_IDLE;
+ }
+
+ unlink(socket_path);
+
+ return 0;
+}
+
+
+void client_free(CtrlClient *client) {
+ free(client);
+}
+
+int handle_messages(CtrlClient *client) {
+ if(client->pos == CLIENT_MSG_BUFSIZE) {
+ return 1;
+ }
+
+ int msgstart = 0;
+ for(int i=0;i<client->pos;i++) {
+ if(client->buf[i] == '\n') {
+ sstr_t msg;
+ msg.ptr = &client->buf[msgstart];
+ msg.length = i - msgstart;
+ msgstart = i+1;
+
+ int msgret = handle_client_msg(client, msg);
+ if(msgret) return msgret;
+ }
+ }
+
+ if(msgstart < client->pos) {
+ // incomplete message
+ memmove(client->buf, client->buf + msgstart, client->pos - msgstart);
+ client->pos -= msgstart;
+ } else {
+ client->pos = 0;
+ }
+
+ return 0;
+}
+
+int handle_client_msg(CtrlClient *client, sstr_t msg) {
+ printf("msg: %.*s\n", (int)msg.length, msg.ptr);
+
+ if(!sstrcmp(msg, S("abort"))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void client_send_status(CtrlClient *client) {
+ char *msg = "s 0\n";
+ write(client->fd, msg, strlen(msg));
+}
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2021 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRVTRL_H
+#define SRVTRL_H
+
+#include "main.h"
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ int fd;
+ char buf[CLIENT_MSG_BUFSIZE];
+ size_t pos;
+} CtrlClient;
+
+int create_control_socket(void);
+
+const char* mzcp_get_socketpath(void);
+
+int mzcp_srvctrl(CPSettings *settings);
+
+void client_free(CtrlClient *client);
+
+int handle_messages(CtrlClient *client);
+int handle_client_msg(CtrlClient *client, sstr_t msg);
+
+void client_send_status(CtrlClient *client);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SRVTRL_H */
+