diff options
Diffstat (limited to 'utils.c')
-rw-r--r-- | utils.c | 141 |
1 files changed, 141 insertions, 0 deletions
@@ -0,0 +1,141 @@ +/* + * rhdropbox + * + * Copyright (C) 2009 Christian Pointner <equinox@helsinki.at> + * + * This file is part of rhdropbox. + * + * rhdropbox 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 + * any later version. + * + * rhdropbox 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 rhdropbox. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "datatypes.h" + +#include <sys/un.h> +#include <termios.h> +#include <unistd.h> +#include <errno.h> + +#include "log.h" + +#include "utils.h" + +int init_command_socket(const char* path) +{ + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(fd < 0) { + log_printf(ERROR, "unable to open socket: %s", strerror(errno)); + return -1; + } + + struct sockaddr_un local; + local.sun_family = AF_UNIX; + if(sizeof(local.sun_path) <= strlen(path)) { + log_printf(ERROR, "socket path is to long (max %d)", sizeof(local.sun_path)-1); + return -1; + } + strcpy(local.sun_path, path); + unlink(local.sun_path); + int len = SUN_LEN(&local); + int ret = bind(fd, (struct sockaddr*)&local, len); + if(ret) { + log_printf(ERROR, "unable to bind to '%s': %s", local.sun_path, strerror(errno)); + return -1; + } + + ret = listen(fd, 4); + if(ret) { + log_printf(ERROR, "unable to listen on command socket: %s", local.sun_path, strerror(errno)); + return -1; + } + + log_printf(INFO, "now listening on %s for incoming commands", path); + + return fd; +} + +int connect_command_socket(const char* path) +{ + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(fd < 0) { + log_printf(ERROR, "unable to open socket: %s", strerror(errno)); + return -1; + } + + struct sockaddr_un remote; + remote.sun_family = AF_UNIX; + if(sizeof(remote.sun_path) <= strlen(path)) { + log_printf(ERROR, "socket path is to long (max %d)", sizeof(remote.sun_path)-1); + return -1; + } + strcpy(remote.sun_path, path); + int len = SUN_LEN(&remote); + int ret = connect(fd, (struct sockaddr*)&remote, len); + if(ret) { + log_printf(ERROR, "unable to connect to '%s': %s", remote.sun_path, strerror(errno)); + return -1; + } + + return fd; +} + +int send_string(int fd, const char* string) +{ + int len = strlen(string); + int offset = 0; + int ret; + for(;;) { + ret = write(fd, &string[offset], len - offset); + if(ret < 0) { + if(errno != EINTR) + return ret; + + ret = 0; + } + + offset += ret; + if(offset+1 >= len) + break; + } + return ret; +} + +int nonblock_recvline(read_buffer_t* buffer, int fd, cmd_t** cmd_q, client_t* client_lst, options_t* opt) +{ + int ret = 0; + for(;;) { + ret = recv(fd, &buffer->buf[buffer->offset], 1, 0); + if(!ret) + return 2; + if(ret == -1 && errno == EAGAIN) + return 0; + else if(ret < 0) + break; + + if(buffer->buf[buffer->offset] == '\n') { + buffer->buf[buffer->offset] = 0; + ret = process_cmd(buffer->buf, fd, cmd_q, client_lst, opt); + buffer->offset = 0; + break; + } + + buffer->offset++; + if(buffer->offset >= sizeof(buffer->buf)) { + log_printf(DEBUG, "string too long (fd=%d)", fd); + buffer->offset = 0; + return 0; + } + } + + return ret; +} |