From 54e88cfd92ebf9fabaa44bd62c73514e2c7892ef Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Fri, 15 Nov 2024 15:29:03 +0300 Subject: [PATCH] Add ringbuffer to start adding sockets --- daemon.c | 2 - examples/CMakeLists.txt | 2 + examples/__template.c | 46 ++++++++ examples/clientserver.c | 46 ++++++++ examples/ringbuffer.c | 80 +++++++++++++ parseargs.c | 34 +----- ringbuffer.c | 256 ++++++++++++++++++++++++++++++++++++++++ socket.c | 20 ++++ term.c | 6 - term2.c | 6 - usefull_macros.c | 13 +- usefull_macros.h | 62 ++++++++++ 12 files changed, 518 insertions(+), 55 deletions(-) create mode 100644 examples/__template.c create mode 100644 examples/clientserver.c create mode 100644 examples/ringbuffer.c create mode 100644 ringbuffer.c create mode 100644 socket.c diff --git a/daemon.c b/daemon.c index ba54db4..8abc317 100644 --- a/daemon.c +++ b/daemon.c @@ -66,7 +66,6 @@ char *sl_getPSname(pid_t pid){ * Redefine this function for user action */ void WEAK sl_iffound_deflt(pid_t pid){ - /// \nОбнаружен одноименный процесс (pid=%d), выход.\n fprintf(stderr, _("\nFound running process (pid=%d), exit.\n"), pid); exit(-1); } @@ -139,7 +138,6 @@ void sl_check4running(char *selfname, char *pidfilename){ free(myname); if(pidfilename){ pidfile = fopen(pidfilename, "w"); - /// Не могу открыть PID файл if(!pidfile) ERR(_("Can't open PID file")); fprintf(pidfile, "%d\n", self); // write self PID to pidfile fclose(pidfile); diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 274a513..9a2daef 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -10,3 +10,5 @@ add_executable(helloworld helloworld.c) add_executable(options options.c cmdlnopts.c) add_executable(fifo fifo.c) add_executable(conffile conffile.c) +add_executable(clientserver clientserver.c) +add_executable(ringbuffer ringbuffer.c) diff --git a/examples/__template.c b/examples/__template.c new file mode 100644 index 0000000..cfc1941 --- /dev/null +++ b/examples/__template.c @@ -0,0 +1,46 @@ +/* + * This file is part of the Snippets project. + * Copyright 2024 Edward V. Emelianov . + * + * This program 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 + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#include + +typedef struct{ + int help; + int verbose; + char *logfile; +} parameters; + +static parameters G = {0}; + +static sl_option_t cmdlnopts[] = { + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&G.help), "show this help"}, + {"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&G.verbose), "verbose level (each -v adds 1)"}, + {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), "log file name"}, + end_option +}; + +int main(int argc, char **argv){ + sl_init(); + sl_parseargs(&argc, &argv, cmdlnopts); + if(G.help) sl_showhelp(-1, cmdlnopts); + sl_loglevel_e lvl = G.verbose + LOGLEVEL_ERR; + if(lvl >= LOGLEVEL_AMOUNT) lvl = LOGLEVEL_AMOUNT - 1; + if(G.logfile) OPENLOG(G.logfile, lvl, 1); + LOGMSG("hello"); + LOGERRADD("additional to err"); + return 0; +} diff --git a/examples/clientserver.c b/examples/clientserver.c new file mode 100644 index 0000000..cfc1941 --- /dev/null +++ b/examples/clientserver.c @@ -0,0 +1,46 @@ +/* + * This file is part of the Snippets project. + * Copyright 2024 Edward V. Emelianov . + * + * This program 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 + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#include + +typedef struct{ + int help; + int verbose; + char *logfile; +} parameters; + +static parameters G = {0}; + +static sl_option_t cmdlnopts[] = { + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&G.help), "show this help"}, + {"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&G.verbose), "verbose level (each -v adds 1)"}, + {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), "log file name"}, + end_option +}; + +int main(int argc, char **argv){ + sl_init(); + sl_parseargs(&argc, &argv, cmdlnopts); + if(G.help) sl_showhelp(-1, cmdlnopts); + sl_loglevel_e lvl = G.verbose + LOGLEVEL_ERR; + if(lvl >= LOGLEVEL_AMOUNT) lvl = LOGLEVEL_AMOUNT - 1; + if(G.logfile) OPENLOG(G.logfile, lvl, 1); + LOGMSG("hello"); + LOGERRADD("additional to err"); + return 0; +} diff --git a/examples/ringbuffer.c b/examples/ringbuffer.c new file mode 100644 index 0000000..d7c8900 --- /dev/null +++ b/examples/ringbuffer.c @@ -0,0 +1,80 @@ +/* + * This file is part of the Snippets project. + * Copyright 2024 Edward V. Emelianov . + * + * This program 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 + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#include +#include +#include + +#define BUFS 128 + +typedef struct{ + int help; + int verbose; + int size; +} parameters; + +static parameters G = { + .size = 1024, +}; + +static sl_option_t cmdlnopts[] = { + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&G.help), "show this help"}, + {"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&G.verbose), "verbose level (each -v adds 1)"}, + {"bufsize", NEED_ARG, NULL, 's', arg_longlong,APTR(&G.size), "size of ring buffer"}, + end_option +}; + +int main(int argc, char **argv){ + sl_init(); + sl_parseargs(&argc, &argv, cmdlnopts); + if(G.help) sl_showhelp(-1, cmdlnopts); + sl_ringbuffer *b = sl_RB_new(G.size); + if(!b) return 1; + printf("Created ring buffer of %d bytes\n", G.size); + printf("Enter lines of text to fill it or type (get) to get one line from buffer\n"); + ssize_t got = -1; + char buf[BUFS]; + for(int nline = 1; ; ++nline){ + printf("%4d > ", nline); + char *ln = NULL; size_t ls = 0; + got = getline(&ln, &ls, stdin); + if(got < 1){ FREE(ln); break; } + if(0 == strcmp(ln, "get\n")){ + if(sl_RB_readline(b, buf, BUFS)){ + printf("line: %s\n", buf); + nline -= 2; + }else --nline; + continue; + } + if(!sl_RB_writestr(b, ln)){ + WARNX("Buffer overfull"); + break; + } + } + printf("\n This is all rest buffer data:\n"); + for(int nline = 1; ; ++nline){ + int r = sl_RB_readline(b, buf, BUFS); + if(r < 1){ + if(r == -1) WARNX("Next string it too long"); + break; + } + printf("line %d: %s\n", nline, buf); + } + sl_RB_delete(&b); + return 0; +} diff --git a/parseargs.c b/parseargs.c index 6fad51e..263e8e8 100644 --- a/parseargs.c +++ b/parseargs.c @@ -50,7 +50,6 @@ void sl_helpstring(char *s){ if(str[1] == 's') scount++; // increment "%s" counter }; if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong - /// Неправильный формат строки помощи ERRX(_("Wrong helpstring!")); } helpstring = s; @@ -80,7 +79,6 @@ static int myatoll(void *num, char *str, sl_argtype_e t){ case arg_int: default: if(tmp < INT_MIN || tmp > INT_MAX){ - /// Целое вне допустимого диапазона WARNX(_("Integer out of range")); return FALSE; } @@ -165,7 +163,6 @@ void *get_aptr(void *paptr, sl_argtype_e type){ switch(type){ default: case arg_none: - /// "Не могу использовать несколько параметров без аргументов!" ERRX(_("Can't use multiple args with arg_none!")); break; case arg_int: @@ -286,24 +283,6 @@ void sl_parseargs(int *argc, char ***argv, sl_option_t *options){ DBG("%c(%d) = getopt_long(argc, argv, %s, long_options, &%d); optopt=%c(%d), errno=%d", opt, opt, short_options, optind, optopt, optopt, errno); if(optind < 0 ) optind = get_optind(opt, options); // find short option -> need to know index of long // be careful with "-?" flag: all wrong or ambiguous flags will be interpreted as this! - /* - if(opt == '?'){ // real '?', wrong option or no argument when need - opt = optopt; // original short opt or 0 for wrong or long - if(opt == 0){ // '?' or wrong long - // there's no way to understand difference between real '-?' and unknown long flag - DBG("'?' or unknown parameter"); - sl_showhelp(-1, options); - }else optind = get_optind(opt, options); - DBG("optind = %d", optind); - if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR) - sl_showhelp(optind, options); // need argument - }else{ - // we should call functions get_optind / get_optindl for options where there's no long analog - if(opt < ' ') optind = get_optindl(&long_options[oindex], options); - else optind = get_optind(opt, options); - } - if(optind < 0) sl_showhelp(-1, options); // wrong argument - */ DBG("index=%d", optind); opts = &options[optind]; DBG("Got option %s", opts->name); @@ -327,23 +306,23 @@ void sl_parseargs(int *argc, char ***argv, sl_option_t *options){ break; case arg_int: result = myatoll(aptr, optarg, arg_int); - type = _("integer"); + type = "integer"; break; case arg_longlong: result = myatoll(aptr, optarg, arg_longlong); - type = _("long long"); + type = "long long"; break; case arg_double: result = myatod(aptr, optarg, arg_double); - type = _("double"); + type = "double"; break; case arg_float: result = myatod(aptr, optarg, arg_float); - type = _("float"); + type = "float"; break; case arg_string: result = (*((void**)aptr) = (void*)strdup(optarg)) != NULL; - type = _("string"); + type = "string"; break; case arg_function: result = ((sl_argfn_t)aptr)(optarg); @@ -504,17 +483,14 @@ int sl_get_suboption(char *str, sl_suboption_t *opt){ } int idx = findsubopt(tok, opt); if(idx < 0){ - /// Неправильный параметр: %s WARNX(_("Wrong parameter: %s"), tok); goto returning; } if(noarg && opt[idx].has_arg == NEED_ARG){ - /// %s: необходим аргумент! WARNX(_("%s: need argument!"), tok); goto returning; } if(!opt_setarg(opt, idx, val)){ - /// Неправильный аргумент \"%s\" параметра \"%s\" WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); goto returning; } diff --git a/ringbuffer.c b/ringbuffer.c new file mode 100644 index 0000000..e3ad12d --- /dev/null +++ b/ringbuffer.c @@ -0,0 +1,256 @@ +/* + * This file is part of the Snippets project. + * Copyright 2024 Edward V. Emelianov . + * + * This program 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 + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#include +#include +#include "usefull_macros.h" + +/** + * @brief sl_RB_new - create ringbuffer with `size` bytes + * @param size - RB size + * @return RB + */ +sl_ringbuffer *sl_RB_new(size_t size){ + sl_ringbuffer *b = MALLOC(sl_ringbuffer, 1); + b->data = MALLOC(uint8_t, size); + pthread_mutex_init(&b->busy, NULL); + b->head = b->tail = 0; + b->length = size; + return b; +} + +/** + * @brief sl_RB_delete - free ringbuffer + * @param b - buffer to free + */ +void sl_RB_delete(sl_ringbuffer **b){ + if(!b || !*b) return; + sl_ringbuffer *bptr = *b; + pthread_mutex_lock(&bptr->busy); + FREE(bptr->data); + *b = 0; + pthread_mutex_unlock(&bptr->busy); + FREE(bptr); +} + +/** + * @brief datalen - amount of bytes in buffer + * @param b - buffer + * @return N + */ +static size_t datalen(sl_ringbuffer *b){ + if(b->tail >= b->head) return (b->tail - b->head); + else return (b->length - b->head + b->tail); +} + +// datalen but with blocking of RB +size_t sl_RB_datalen(sl_ringbuffer *b){ + pthread_mutex_lock(&b->busy); + size_t l = datalen(b); + pthread_mutex_unlock(&b->busy); + return l; +} + +/** + * @brief hasbyte - check if RB have given byte + * @param b - rb + * @param byte - what to find + * @return index of byte or -1 if not found or no data + */ +static ssize_t hasbyte(sl_ringbuffer *b, uint8_t byte){ + if(b->head == b->tail) return -1; // no data in buffer + size_t startidx = b->head; + if(b->head > b->tail){ + for(size_t found = b->head; found < b->length; ++found) + if(b->data[found] == byte) return found; + startidx = 0; + } + for(size_t found = startidx; found < b->tail; ++found) + if(b->data[found] == byte) return found; + return -1; +} + +// hasbyte with block +ssize_t sl_RB_hasbyte(sl_ringbuffer *b, uint8_t byte){ + pthread_mutex_lock(&b->busy); + size_t idx = hasbyte(b, byte); + pthread_mutex_unlock(&b->busy); + return idx; +} +// increment head or tail +inline void incr(sl_ringbuffer *b, volatile size_t *what, size_t n){ + *what += n; + if(*what >= b->length) *what -= b->length; +} + +static size_t rbread(sl_ringbuffer *b, uint8_t *s, size_t len){ + size_t l = datalen(b); + if(!l) return 0; + if(l > len) l = len; + size_t _1st = b->length - b->head; + if(_1st > l) _1st = l; + if(_1st > len) _1st = len; + memcpy(s, b->data + b->head, _1st); + if(_1st < len && l > _1st){ + memcpy(s+_1st, b->data, l - _1st); + incr(b, &b->head, l); + return l; + } + incr(b, &b->head, _1st); + return _1st; +} + +/** + * @brief sl_RB_read - read data from rb + * @param b - rb + * @param s - buffer for data + * @param len - length of `s` + * @return amount of bytes read + */ +size_t sl_RB_read(sl_ringbuffer *b, uint8_t *s, size_t len){ + pthread_mutex_lock(&b->busy); + size_t got = rbread(b, s, len); + pthread_mutex_unlock(&b->busy); + return got; +} + +/** + * @brief sl_RB_readto - read until meet byte `byte` + * @param b - rb + * @param byte - byte to find + * @param s - receiver + * @param len - length of `s` + * @return amount of bytes read or -1 if `s` have insufficient size + */ +ssize_t sl_RB_readto(sl_ringbuffer *b, uint8_t byte, uint8_t *s, size_t len){ + ssize_t got = 0; + pthread_mutex_lock(&b->busy); + ssize_t idx = hasbyte(b, byte); + if(idx < 0) goto ret; + size_t partlen = idx + 1 - b->head; + // now calculate length of new data portion + if((size_t)idx < b->head) partlen += b->length; + if(partlen > len) got = -1; + else got = rbread(b, s, partlen); +ret: + pthread_mutex_unlock(&b->busy); + return got; +} + +/** + * @brief sl_RB_readline - read string of text ends with '\n' + * @param b - rb + * @param s - string buffer + * @param len - length of `s` + * @return amount of characters read or -1 if buffer too small + * !!! this function changes '\n' to 0 in `s`; `len` should include trailing '\0' too + */ +ssize_t sl_RB_readline(sl_ringbuffer *b, char *s, size_t len){ + ssize_t got = 0; + pthread_mutex_lock(&b->busy); + ssize_t idx = hasbyte(b, '\n'); + if(idx < 0) goto ret; + size_t partlen = idx + 1 - b->head; + // now calculate length of new data portion + if((size_t)idx < b->head) partlen += b->length; + if(partlen > len) got = -1; + else{ + got = rbread(b, (uint8_t*)s, partlen); + s[partlen - 1] = 0; // substitute '\n' with trailing zero + } +ret: + pthread_mutex_unlock(&b->busy); + return got; +} + +/** + * @brief sl_RB_putbyte - put one byte into rb + * @param b - rb + * @param byte - data byte + * @return FALSE if there's no place for `byte` in `b` + */ +int sl_RB_putbyte(sl_ringbuffer *b, uint8_t byte){ + int rtn = FALSE; + pthread_mutex_lock(&b->busy); + size_t s = datalen(b); + if(b->length == s + 1) goto ret; + b->data[b->tail] = byte; + incr(b, &b->tail, 1); + rtn = TRUE; +ret: + pthread_mutex_unlock(&b->busy); + return rtn; +} + +/** + * @brief sl_RB_write - write data to buffer + * @param b - buffer + * @param str - data + * @param len - data length + * @return amount of bytes wrote (can be less than `len`) + */ +size_t sl_RB_write(sl_ringbuffer *b, const uint8_t *str, size_t len){ + pthread_mutex_lock(&b->busy); + size_t r = b->length - 1 - datalen(b); // rest length + if(len > r) len = r; + if(!len){ r = 0; goto ret; } + size_t _1st = b->length - b->tail; + if(_1st > len) _1st = len; + memcpy(b->data + b->tail, str, _1st); + if(_1st < len){ // add another piece from start + memcpy(b->data, str+_1st, len-_1st); + } + incr(b, &b->tail, len); +ret: + pthread_mutex_unlock(&b->busy); + return r; +} + +/** + * @brief sl_RB_clearbuf - reset buffer + * @param b - rb + */ +void sl_RB_clearbuf(sl_ringbuffer *b){ + pthread_mutex_lock(&b->busy); + b->head = 0; + b->tail = 0; + pthread_mutex_unlock(&b->busy); +} + +/** + * @brief sl_RB_writestr - write FULL string `s` to buffer (without trailing zero!) + * @param b - rb + * @param s - string + * @return amount of bytes written (strlen of s) or 0 + */ +size_t sl_RB_writestr(sl_ringbuffer *b, char *s){ + size_t len = strlen(s); + pthread_mutex_lock(&b->busy); + size_t r = b->length - 1 - datalen(b); // rest length + if(len > r){ len = 0; goto ret; } // insufficient space - don't even try to write a part + size_t _1st = b->length - b->tail; + if(_1st > len) _1st = len; + memcpy(b->data + b->tail, s, _1st); + if(_1st < len){ // add another piece from start + memcpy(b->data, s+_1st, len-_1st); + } + incr(b, &b->tail, len); +ret: + pthread_mutex_unlock(&b->busy); + return len; +} diff --git a/socket.c b/socket.c new file mode 100644 index 0000000..97b6fab --- /dev/null +++ b/socket.c @@ -0,0 +1,20 @@ +/* + * This file is part of the Snippets project. + * Copyright 2024 Edward V. Emelianov . + * + * This program 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 + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#include "usefull_macros.h" + diff --git a/term.c b/term.c index 20c55b7..b81d2f9 100644 --- a/term.c +++ b/term.c @@ -99,12 +99,10 @@ tcflag_t sl_tty_convspd(int speed){ static int tty_init(sl_tty_t *descr){ // |O_NONBLOCK ? if ((descr->comfd = open(descr->portname, O_RDWR|O_NOCTTY)) < 0){ - /// Не могу использовать порт %s WARN(_("Can't use port %s"), descr->portname); return globErr ? globErr : 1; } if(tcgetattr(descr->comfd, &descr->oldtty) < 0){ // Get settings - /// Не могу получить действующие настройки порта WARN(_("Can't get old TTY settings")); return globErr ? globErr : 1; } @@ -116,14 +114,12 @@ static int tty_init(sl_tty_t *descr){ descr->tty.c_cc[VMIN] = 0; // non-canonical mode descr->tty.c_cc[VTIME] = 5; if(tcsetattr(descr->comfd, TCSANOW, &descr->tty) < 0){ - /// Не могу сменить настройки порта WARN(_("Can't apply new TTY settings")); return globErr ? globErr : 1; } // make exclusive open if(descr->exclusive){ if(ioctl(descr->comfd, TIOCEXCL)){ - /// Не могу сделать порт эксклюзивным WARN(_("Can't do exclusive open")); }} return 0; @@ -159,7 +155,6 @@ sl_tty_t *sl_tty_new(char *comdev, int speed, size_t bufsz){ descr->baudrate = spd; descr->speed = speed; if(!descr->portname){ - /// Отсутствует имя порта WARNX(_("Port name is missing")); }else{ if(bufsz){ @@ -252,7 +247,6 @@ int sl_tty_read(sl_tty_t *d){ int sl_tty_write(int comfd, const char *buff, size_t length){ ssize_t L = write(comfd, buff, length); if((size_t)L != length){ - /// "Ошибка записи!" WARN("Write error"); return 1; } diff --git a/term2.c b/term2.c index 5a6ee7f..0c17720 100644 --- a/term2.c +++ b/term2.c @@ -99,12 +99,10 @@ static int tty_init(sl_tty_t *descr){ tcflag_t flags; if(!parse_format(descr->format, &flags)) return 1; if((descr->comfd = open(descr->portname, O_RDWR|O_NOCTTY)) < 0){ - /// Не могу использовать порт %s WARN(_("Can't use port %s"), descr->portname); return globErr ? globErr : 1; } if(ioctl(descr->comfd, TCGETS2, &descr->oldtty)){ // Get settings - /// Не могу получить действующие настройки порта WARN(_("Can't get old TTY settings")); return globErr ? globErr : 1; } @@ -118,7 +116,6 @@ static int tty_init(sl_tty_t *descr){ descr->tty.c_cc[VMIN] = 0; // non-canonical mode descr->tty.c_cc[VTIME] = 5; if(ioctl(descr->comfd, TCSETS2, &descr->tty)){ - /// Не могу сменить настройки порта WARN(_("Can't apply new TTY settings")); return globErr ? globErr : 1; } @@ -130,7 +127,6 @@ static int tty_init(sl_tty_t *descr){ // make exclusive open if(descr->exclusive){ if(ioctl(descr->comfd, TIOCEXCL)){ - /// Не могу сделать порт эксклюзивным WARN(_("Can't do exclusive open")); }} return 0; @@ -163,7 +159,6 @@ sl_tty_t *sl_tty_new(char *comdev, int speed, size_t bufsz){ descr->portname = strdup(comdev); descr->speed = speed; if(!descr->portname){ - /// Отсутствует имя порта WARNX(_("Port name is missing")); }else{ if(bufsz){ @@ -256,7 +251,6 @@ int sl_tty_read(sl_tty_t *d){ int sl_tty_write(int comfd, const char *buff, size_t length){ ssize_t L = write(comfd, buff, length); if((size_t)L != length){ - /// "Ошибка записи!" WARN("Write error"); return 1; } diff --git a/usefull_macros.c b/usefull_macros.c index 3f8b9f1..59691c4 100644 --- a/usefull_macros.c +++ b/usefull_macros.c @@ -191,12 +191,10 @@ long sl_random_seed(){ int fd = open("/dev/random", O_RDONLY); do{ if(-1 == fd){ - /// Не могу открыть /dev/random WARN(_("Can't open /dev/random")); fail = 1; break; } if(sizeof(long) != read(fd, &r_ini, sizeof(long))){ - /// Не могу прочесть /dev/random WARN(_("Can't read /dev/random")); fail = 1; } @@ -247,29 +245,24 @@ sl_mmapbuf_t *sl_mmap(char *filename){ size_t Mlen; struct stat statbuf; if(!filename){ - /// Не задано имя файла! WARNX(_("No filename given!")); return NULL; } if((fd = open(filename, O_RDONLY)) < 0){ - /// Не могу открыть %s для чтения WARN(_("Can't open %s for reading"), filename); return NULL; } if(fstat (fd, &statbuf) < 0){ - /// Не могу выполнить stat %s WARN(_("Can't stat %s"), filename); close(fd); return NULL; } Mlen = statbuf.st_size; if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){ - /// Ошибка mmap WARN(_("Mmap error for input")); close(fd); return NULL; } - /// Не могу закрыть mmap'нутый файл if(close(fd)) WARN(_("Can't close mmap'ed file")); sl_mmapbuf_t *ret = MALLOC(sl_mmapbuf_t, 1); ret->data = ptr; @@ -283,7 +276,6 @@ sl_mmapbuf_t *sl_mmap(char *filename){ */ void sl_munmap(sl_mmapbuf_t *b){ if(munmap(b->data, b->len)){ - /// Не могу munmap ERR(_("Can't munmap")); } FREE(b); @@ -352,7 +344,6 @@ void sl_setup_con(){ #else if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ #endif - /// Не могу настроить консоль WARN(_("Can't setup console")); #ifndef SL_USE_OLD_TTY ioctl(STDIN_FILENO, TCSETS2, &oldt); @@ -409,7 +400,6 @@ int sl_str2d(double *num, const char *str){ if(!str) return FALSE; res = strtod(str, &endptr); if(endptr == str || *str == '\0' || *endptr != '\0'){ - /// "Неправильный формат числа double '%s'" WARNX(_("Wrong double number format '%s'"), str); return FALSE; } @@ -423,8 +413,7 @@ int sl_str2ll(long long *num, const char *str){ if(!str) return FALSE; res = strtoll(str, &endptr, 0); if(endptr == str || *str == '\0' || *endptr != '\0'){ - /// "Неправильный формат числа double!" - WARNX(_("Wrong number format!")); + WARNX(_("Wrong integer number format '%s'")); return FALSE; } if(num) *num = res; diff --git a/usefull_macros.h b/usefull_macros.h index 1194d9d..f92ddf9 100644 --- a/usefull_macros.h +++ b/usefull_macros.h @@ -377,3 +377,65 @@ typedef struct{ int sl_get_keyval(const char *pair, char key[SL_KEY_LEN], char value[SL_VAL_LEN]); char *sl_print_opts(sl_option_t *opt, int showall); int sl_conf_readopts(const char *filename, sl_option_t *options); + +/******************************************************************************\ + The original ringbuffer.h +\******************************************************************************/ + +// ring buffer for string or binary data +typedef struct{ + uint8_t *data; // data buffer + size_t length; // its length + size_t head; // head index + size_t tail; // tail index + pthread_mutex_t busy; // mutex of buffer activity +} sl_ringbuffer; + +sl_ringbuffer *sl_RB_new(size_t size); +void sl_RB_delete(sl_ringbuffer **b); +size_t sl_RB_read(sl_ringbuffer *b, uint8_t *s, size_t len); +ssize_t sl_RB_readto(sl_ringbuffer *b, uint8_t byte, uint8_t *s, size_t len); +ssize_t sl_RB_hasbyte(sl_ringbuffer *b, uint8_t byte); +int sl_RB_putbyte(sl_ringbuffer *b, uint8_t byte); +size_t sl_RB_write(sl_ringbuffer *b, const uint8_t *str, size_t len); +size_t sl_RB_datalen(sl_ringbuffer *b); +void sl_RB_clearbuf(sl_ringbuffer *b); +ssize_t sl_RB_readline(sl_ringbuffer *b, char *s, size_t len); +size_t sl_RB_writestr(sl_ringbuffer *b, char *s); + +/******************************************************************************\ + The original socket.h +\******************************************************************************/ + +// handler result: what to send to client + +typedef enum{ + RESULT_OK, // all OK + RESULT_FAIL, // failed running command + RESULT_BADVAL, // bad value + RESULT_BADKEY, // bad (non-existant) key + RESULT_SILENCE, // send nothing to client (in case of handlers which sends data by themself) + RESULT_NUM // total amount of enum fields +} sl_hresult; + +typedef sl_hresult (*sl_msghandler)(int fd, const char *key, const char *val); + +typedef struct{ + sl_msghandler handler; + const char *key; + const char *help; +} sl_handleritem; + +typedef enum{ + SOCKT_UNIX, // UNIX socket + SOCKT_NETLOCAL, // INET socket but only for localhost + SOCKT_NET // true INET socket +} sl_socktype; + +const char *sl_hresult2str(sl_hresult r); +int sl_start_socket(int isserver, int isnet, const char *path); +void sl_sendbinmessage(int fd, const uint8_t *msg, int l); +void sl_sendstrmessage(int fd, const char *msg); + + +