Add ringbuffer to start adding sockets

This commit is contained in:
Edward Emelianov 2024-11-15 15:29:03 +03:00
parent e77fddc3b8
commit 54e88cfd92
12 changed files with 518 additions and 55 deletions

View File

@ -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);

View File

@ -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)

46
examples/__template.c Normal file
View File

@ -0,0 +1,46 @@
/*
* This file is part of the Snippets project.
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <usefull_macros.h>
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;
}

46
examples/clientserver.c Normal file
View File

@ -0,0 +1,46 @@
/*
* This file is part of the Snippets project.
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <usefull_macros.h>
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;
}

80
examples/ringbuffer.c Normal file
View File

@ -0,0 +1,80 @@
/*
* This file is part of the Snippets project.
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <usefull_macros.h>
#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;
}

View File

@ -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;
}

256
ringbuffer.c Normal file
View File

@ -0,0 +1,256 @@
/*
* This file is part of the Snippets project.
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include <string.h>
#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;
}

20
socket.c Normal file
View File

@ -0,0 +1,20 @@
/*
* This file is part of the Snippets project.
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "usefull_macros.h"

6
term.c
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);