mirror of
https://github.com/eddyem/snippets_library.git
synced 2025-12-06 02:35:20 +03:00
version 0.2.1
This commit is contained in:
parent
511a83e506
commit
e77fddc3b8
@ -2,3 +2,5 @@ cmake defines:
|
||||
-DDEBUG=1 - debug mode
|
||||
-DNOGETTEXT=1 - don't run xgettext
|
||||
-DEXAMPLES=1 - to compile examples
|
||||
-DSL_USE_OLD_TTY - use old termios instead of termios2 (you should use this flag always if library works so)
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
set(PROJ usefull_macros)
|
||||
set(MINOR_VERSION "1")
|
||||
set(MID_VERSION "1")
|
||||
set(MID_VERSION "2")
|
||||
set(MAJOR_VERSION "0")
|
||||
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||
|
||||
@ -51,6 +51,16 @@ message("Build type: ${CMAKE_BUILD_TYPE}")
|
||||
# here is one of two variants: all .c in directory or .c files in list
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
|
||||
|
||||
get_filename_component(term_c ${CMAKE_CURRENT_SOURCE_DIR}/term.c ABSOLUTE)
|
||||
if(DEFINED USE_OLD_TTY OR DEFINED SL_USE_OLD_TTY)
|
||||
get_filename_component(term_c ${CMAKE_CURRENT_SOURCE_DIR}/term2.c ABSOLUTE)
|
||||
add_definitions(-DSL_USE_OLD_TTY)
|
||||
endif()
|
||||
|
||||
message("remove ${term_c}")
|
||||
list(REMOVE_ITEM SOURCES ${term_c})
|
||||
|
||||
|
||||
# directory should contain dir locale/ru for gettext translations
|
||||
set(LCPATH ${CMAKE_SOURCE_DIR}/locale/ru)
|
||||
if(NOT DEFINED LOCALEDIR)
|
||||
@ -136,7 +146,7 @@ if(NOT DEFINED NOGETTEXT)
|
||||
add_custom_command(
|
||||
OUTPUT ${PO_FILE}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=utf-8 ${SOURCES} -c -k_ -kN_ -o ${PO_FILE}
|
||||
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=koi8-r ${SOURCES} -c -k_ -kN_ -o ${PO_FILE}
|
||||
COMMAND sed -i 's/charset=.*\\\\n/charset=koi8-r\\\\n/' ${PO_FILE}
|
||||
COMMAND enconv ${PO_FILE}
|
||||
DEPENDS ${SOURCES}
|
||||
|
||||
49
Changelog
49
Changelog
@ -5,3 +5,52 @@ add tty_timeout()
|
||||
fix read_tty() for disconnect
|
||||
add logging
|
||||
add sl_libversion()
|
||||
|
||||
VERSION 0.2.1:
|
||||
RENAME:
|
||||
initial_setup -> sl_init
|
||||
dtime -> sl_dtime
|
||||
my_alloc -> sl_alloc
|
||||
mmapbuf -> sl_mmapuf_t
|
||||
My_mmap -> sl_mmap
|
||||
My_munmap -> sl_munmap
|
||||
restore_console -> sl_restore_con
|
||||
setup_con -> sl_setup_con
|
||||
read_console -> sl_read_con
|
||||
mygetchar -> sl_getchar
|
||||
throw_random_seed -> sl_random_seed
|
||||
get_available_mem -> sl_mem_avail
|
||||
TTY_descr -> sl_tty_t
|
||||
close_tty -> sl_tty_close
|
||||
new_tty -> sl_tty_new
|
||||
tty_open -> sl_tty_open
|
||||
read_tty -> sl_tty_read
|
||||
tty_timeout -> sl_tty_tmout
|
||||
write_tty -> sl_tty_write
|
||||
conv_spd -> sl_tty_convspd
|
||||
str2double -> sl_str2d
|
||||
globlog -> sl_globlog
|
||||
sl_loglevel -> sl_loglevel_e
|
||||
sl_log -> sl_log_t
|
||||
argfn -> sl_argfn_t
|
||||
argtype -> sl_argtype_e
|
||||
hasarg -> sl_hasarg_e
|
||||
myoption -> sl_option_t
|
||||
mysuboption -> sl_suboption_t
|
||||
showhelp -> sl_showhelp
|
||||
parseargs -> sl_parseargs
|
||||
change_helpstring -> sl_helpstring
|
||||
get_suboption -> sl_get_suboption
|
||||
iffound_default -> sl_iffound_deflt
|
||||
check4running -> sl_check4running
|
||||
readPSname -> sl_getPSname
|
||||
struct buff_node -> struct sl_buff_node
|
||||
List -> sl_list_t
|
||||
list_push_tail -> sl_list_push_tail
|
||||
list_push -> sl_list_push
|
||||
list_pop -> sl_list_pop
|
||||
Remove deprecated code (openlogfile, putlog)
|
||||
Remove "bool" type (change to int)
|
||||
FIXED bug with several only long options with same shortopt mark (like 0)
|
||||
Add simple config files, so you can move some of your parameters settings to it
|
||||
|
||||
|
||||
1
TODO
1
TODO
@ -1,2 +1 @@
|
||||
BUG in commandline options: '?' don't work!
|
||||
Add prefixes sl_ to every function for solving further problems
|
||||
|
||||
300
config.c
Normal file
300
config.c
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* 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 <ctype.h>
|
||||
#include <float.h> // FLT_max/min
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "usefull_macros.h"
|
||||
|
||||
/**
|
||||
* @brief sl_get_keyval - get key name and its value from string pair
|
||||
* @param pair - empty string, `key = value` or just `key`
|
||||
* @param key - substring with `key`
|
||||
* @param value - its value or empty line
|
||||
* @return 0 if no key found (or line is a comment with '#' first); 1 if only key found and 2 if found both key and value
|
||||
* this function removes all leading and trailing spaces in `key` and `value`;
|
||||
* also if `key` have several words only first saved, `value` can be long string with or without quotations
|
||||
*/
|
||||
int sl_get_keyval(const char *pair, char key[SL_KEY_LEN], char value[SL_VAL_LEN]){
|
||||
DBG("got pair: '%s'", pair);
|
||||
if(!pair || !*pair) return 0; // empty line
|
||||
char *kstart = sl_omitspaces(pair);
|
||||
if(!*kstart || *kstart == SL_COMMENT_CHAR) return 0; // only spaces
|
||||
int ret = 1;
|
||||
char *eq = strchr(kstart, '='), *kend = kstart + 1;
|
||||
if(eq == kstart) return 0; // only = (and maybe val)
|
||||
char *cmnt = strchr(kstart, SL_COMMENT_CHAR);
|
||||
if(eq && cmnt && cmnt < eq) eq = NULL; // comment starting before equal sign
|
||||
if(eq){ do{
|
||||
DBG("got equal symbol: '%s'", eq);
|
||||
char *vstart = sl_omitspaces(eq + 1);
|
||||
if(!*vstart) break; // empty line or only spaces after `=`
|
||||
char *vend = sl_omitspacesr(vstart);
|
||||
size_t l = SL_VAL_LEN - 1; // truncate value to given length
|
||||
if(l > (size_t)(vend - vstart)) l = vend - vstart;
|
||||
DBG("l=%zd", l);
|
||||
strncpy(value, vstart, l);
|
||||
value[l] = 0;
|
||||
cmnt = strchr(value, SL_COMMENT_CHAR);
|
||||
if(cmnt){ // remove trailing spaces before comment
|
||||
*cmnt = 0;
|
||||
*sl_omitspacesr(value) = 0;
|
||||
}
|
||||
if(!*value) break;
|
||||
DBG("Got value: '%s'", value);
|
||||
ret = 2;
|
||||
}while(0);
|
||||
}else eq = kstart + strlen(kstart) - 1;
|
||||
for(; kend < eq && !isspace(*kend); ++kend);
|
||||
size_t l = SL_KEY_LEN - 1;
|
||||
if(l > (size_t)(kend - kstart)) l = kend - kstart;
|
||||
strncpy(key, kstart, l);
|
||||
key[l] = 0;
|
||||
cmnt = strchr(key, SL_COMMENT_CHAR);
|
||||
if(cmnt) *cmnt = 0;
|
||||
DBG("Got key: '%s'", key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Read key/value from file; return -1 when file is over
|
||||
static int read_key(FILE *file, char key[SL_KEY_LEN], char value[SL_VAL_LEN]){
|
||||
char *line = NULL;
|
||||
size_t n = 0;
|
||||
ssize_t got = getline(&line, &n, file);
|
||||
if(!line) return 0;
|
||||
if(got < 0){ // EOF
|
||||
free(line);
|
||||
return -1;
|
||||
}
|
||||
int r = sl_get_keyval(line, key, value);
|
||||
free(line);
|
||||
return r;
|
||||
}
|
||||
|
||||
// search `opt` record for given `key`
|
||||
static sl_option_t *opt_search(const char *key, sl_option_t *options){
|
||||
while(options->name){
|
||||
if(0 == strcmp(key, options->name)) return options;
|
||||
++options;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_print_opts - fills string buffer with information from opt
|
||||
* @param opt - options buffer
|
||||
* @param showall - TRUE to show even uninitialized options with NO_ARGS
|
||||
* @return allocated string (should be free'd)
|
||||
*/
|
||||
char *sl_print_opts(sl_option_t *opt, int showall){
|
||||
char *buf = MALLOC(char, BUFSIZ);
|
||||
size_t L = BUFSIZ, l = 0;
|
||||
for(; opt->name; ++opt){
|
||||
DBG("check %s", opt->name);
|
||||
if(!showall && opt->has_arg == NO_ARGS) continue; // show NO_ARGS only when `showall==TRUE`
|
||||
if(!showall && opt->type == arg_string && !opt->argptr) continue; // empty string
|
||||
if((ssize_t)L - l < SL_KEY_LEN + SL_VAL_LEN + 5){
|
||||
L += BUFSIZ;
|
||||
buf = realloc(buf, L);
|
||||
if(!buf) ERR("realloc()");
|
||||
}
|
||||
l += sprintf(buf + l, "%s=", opt->name);
|
||||
if(opt->flag){
|
||||
DBG("got flag '%d'", *opt->flag);
|
||||
l += sprintf(buf + l, "%d\n", *opt->flag);
|
||||
continue;
|
||||
}
|
||||
if(!opt->argptr){ // ERR!
|
||||
l += sprintf(buf + l, "\"(no argptr)\"\n");
|
||||
WARNX("Parameter \"%s\" have no argptr!", opt->name);
|
||||
continue;
|
||||
}
|
||||
int z = 0;
|
||||
DBG("type: %d", opt->type);
|
||||
switch(opt->type){
|
||||
case arg_none:
|
||||
case arg_int:
|
||||
DBG("int %d", *(int*) opt->argptr);
|
||||
l += sprintf(buf + l, "%d", *(int*) opt->argptr);
|
||||
break;
|
||||
case arg_longlong:
|
||||
DBG("long long %lld", *(long long*) opt->argptr);
|
||||
l += sprintf(buf + l, "%lld", *(long long*) opt->argptr);
|
||||
break;
|
||||
case arg_float:
|
||||
DBG("float %g", *(float*) opt->argptr);
|
||||
l += sprintf(buf + l, "%g", *(float*) opt->argptr);
|
||||
break;
|
||||
case arg_double:
|
||||
DBG("double %g", *(double*) opt->argptr);
|
||||
l += sprintf(buf + l, "%g", *(double*) opt->argptr);
|
||||
break;
|
||||
case arg_string:
|
||||
if(!opt->argptr || !(*(char*)opt->argptr)){
|
||||
l += sprintf(buf + l, "(null)");
|
||||
break;
|
||||
}else if(!(**(char**)opt->argptr)){
|
||||
l += sprintf(buf + l, "(empty)");
|
||||
break;
|
||||
}
|
||||
DBG("string %s", *(char**) opt->argptr);
|
||||
z = strlen(*(char**) opt->argptr);
|
||||
while(l + z > L + 3){
|
||||
L += BUFSIZ;
|
||||
buf = realloc(buf, L);
|
||||
}
|
||||
l += sprintf(buf + l, "%s", *(char**) opt->argptr);
|
||||
break;
|
||||
default:
|
||||
DBG("function");
|
||||
l += sprintf(buf + l, "\"(unsupported)\"");
|
||||
break;
|
||||
}
|
||||
l += sprintf(buf + l, "\n");
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_set_optval - convert `val` to `oval` parameter according to argument type
|
||||
* @param oval (o) - value in int/long long/double/float
|
||||
* @param opt (i) - record with options
|
||||
* @param val (i) - new value
|
||||
* @return FALSE if failed (or wrong data range)
|
||||
*/
|
||||
int sl_set_optval(sl_optval *oval, sl_option_t *opt, const char *val){
|
||||
if(!oval || !opt || !val) return FALSE;
|
||||
long long ll;
|
||||
double d;
|
||||
switch(opt->type){
|
||||
case arg_none:
|
||||
case arg_int:
|
||||
case arg_longlong:
|
||||
do{
|
||||
if(!sl_str2ll(&ll, val)){
|
||||
break;
|
||||
}
|
||||
if(opt->type != arg_longlong){
|
||||
if(ll > INT_MAX || ll < INT_MIN){
|
||||
break;
|
||||
}
|
||||
oval->ival = (int)ll;
|
||||
}else oval->llval = ll;
|
||||
return TRUE;
|
||||
}while(0);
|
||||
break;
|
||||
case arg_double:
|
||||
case arg_float:
|
||||
do{
|
||||
if(!sl_str2d(&d, val)){
|
||||
break;
|
||||
}
|
||||
if(opt->type == arg_double){
|
||||
oval->dval = d;
|
||||
}else{
|
||||
if(d > FLT_MAX || d < FLT_MIN){
|
||||
break;
|
||||
}
|
||||
oval->fval = (float)d;
|
||||
}
|
||||
return TRUE;
|
||||
}while(0);
|
||||
break;
|
||||
case arg_string:
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
WARNX(_("Unsupported option type"));
|
||||
return FALSE;
|
||||
}
|
||||
WARNX(_("Wrong number format '%s'"), val);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// increment opt->argptr or set it to val
|
||||
static void setoa(sl_option_t *opt, const char *val){
|
||||
if(!opt || !opt->argptr || opt->type == arg_function) return;
|
||||
sl_optval O;
|
||||
if(!sl_set_optval(&O, opt, val)) return;
|
||||
switch(opt->type){
|
||||
case arg_none: // increment integer
|
||||
*(int*) opt->argptr += O.ival;
|
||||
break;
|
||||
case arg_int:
|
||||
*(int*) opt->argptr = O.ival;
|
||||
break;
|
||||
case arg_longlong:
|
||||
*(long long*) opt->argptr = O.llval;
|
||||
break;
|
||||
case arg_double:
|
||||
*(double*) opt->argptr = O.dval;
|
||||
break;
|
||||
case arg_float:
|
||||
*(float*) opt->argptr = O.fval;
|
||||
break;
|
||||
case arg_string:
|
||||
*(char**)opt->argptr = strdup(val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_conf_readopts - simplest configuration:
|
||||
* read file with lines "par" or "par = val" and set variables like they are options
|
||||
* @param filename - configuration file name
|
||||
* @param options - array with options (could be the same like for sl_parseargs)
|
||||
* @return amount of data read
|
||||
*/
|
||||
int sl_conf_readopts(const char *filename, sl_option_t *options){
|
||||
if(!filename || !options) return 0;
|
||||
FILE *f = fopen(filename, "r");
|
||||
if(!f){
|
||||
WARN(_("Can't open %s"), filename);
|
||||
return 0;
|
||||
}
|
||||
int N = 0;
|
||||
char key[SL_KEY_LEN], val[SL_VAL_LEN];
|
||||
do{
|
||||
int r = read_key(f, key, val);
|
||||
if(r < 0) break;
|
||||
if(r == 0) continue;
|
||||
sl_option_t *opt = opt_search(key, options);
|
||||
if(!opt){
|
||||
WARNX(_("Wrong key: '%s'"), key);
|
||||
continue;
|
||||
}
|
||||
if(opt->flag) *opt->flag = opt->val;
|
||||
if(r == 1){ // only key
|
||||
if(opt->has_arg != NO_ARGS && opt->has_arg != OPT_ARG){
|
||||
WARNX(_("Key '%s' need value"), opt->name);
|
||||
continue;
|
||||
}
|
||||
if(opt->argptr) setoa(opt, "1");
|
||||
}else{ // key + value
|
||||
if(opt->argptr) setoa(opt, val);
|
||||
else WARNX(_("Key '%s' have no argptr!"), opt->name);
|
||||
}
|
||||
++N;
|
||||
}while(1);
|
||||
return N;
|
||||
}
|
||||
22
daemon.c
22
daemon.c
@ -31,13 +31,13 @@
|
||||
#include "usefull_macros.h"
|
||||
|
||||
/**
|
||||
* @brief readPSname - read process name from /proc/PID/cmdline
|
||||
* @brief sl_getPSname - read process name from /proc/PID/cmdline
|
||||
* @param pid - PID of interesting process
|
||||
* @return filename or NULL if not found
|
||||
* don't use this function twice for different names without copying
|
||||
* its returning by strdup, because `name` contains in static array
|
||||
*/
|
||||
char *readPSname(pid_t pid){
|
||||
char *sl_getPSname(pid_t pid){
|
||||
static char name[PATH_MAX];
|
||||
char *pp = name, byte, path[PATH_MAX];
|
||||
FILE *file;
|
||||
@ -61,11 +61,11 @@ char *readPSname(pid_t pid){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief iffound_default - default action when running process found
|
||||
* @brief sl_iffound_deflt - default action when running process found
|
||||
* @param pid - another process' pid
|
||||
* Redefine this function for user action
|
||||
*/
|
||||
void WEAK iffound_default(pid_t pid){
|
||||
void WEAK sl_iffound_deflt(pid_t pid){
|
||||
/// \nïÂÎÁÒÕÖÅÎ ÏÄÎÏÉÍÅÎÎÙÊ ÐÒÏÃÅÓÓ (pid=%d), ×ÙÈÏÄ.\n
|
||||
fprintf(stderr, _("\nFound running process (pid=%d), exit.\n"), pid);
|
||||
exit(-1);
|
||||
@ -81,7 +81,7 @@ void WEAK iffound_default(pid_t pid){
|
||||
* @param selfname - argv[0] or NULL for non-locking
|
||||
* @param pidfilename - name of pidfile or NULL if none
|
||||
*/
|
||||
void check4running(char *selfname, char *pidfilename){
|
||||
void sl_check4running(char *selfname, char *pidfilename){
|
||||
DIR *dir;
|
||||
FILE *pidfile, *fself;
|
||||
struct dirent *de;
|
||||
@ -102,7 +102,7 @@ void check4running(char *selfname, char *pidfilename){
|
||||
goto selfpid;
|
||||
}
|
||||
if(fl.l_type != F_UNLCK){ // file is locking - exit
|
||||
iffound_default(fl.l_pid);
|
||||
sl_iffound_deflt(fl.l_pid);
|
||||
}
|
||||
fl.l_type = F_RDLCK;
|
||||
if(fcntl(fileno(fself), F_SETLKW, &fl) == -1){
|
||||
@ -114,7 +114,7 @@ void check4running(char *selfname, char *pidfilename){
|
||||
if(!(dir = opendir(PROC_BASE))){ // open /proc directory
|
||||
ERR(PROC_BASE);
|
||||
}
|
||||
if(!(name = readPSname(self))){ // error reading self name
|
||||
if(!(name = sl_getPSname(self))){ // error reading self name
|
||||
ERR(_("Can't read self name"));
|
||||
}
|
||||
myname = strdup(name);
|
||||
@ -122,8 +122,8 @@ void check4running(char *selfname, char *pidfilename){
|
||||
pidfile = fopen(pidfilename, "r");
|
||||
if(pidfile){
|
||||
if(fscanf(pidfile, "%d", &pid) > 0){ // read PID of (possibly) running process
|
||||
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0)
|
||||
iffound_default(pid);
|
||||
if((name = sl_getPSname(pid)) && strncmp(name, myname, 255) == 0)
|
||||
sl_iffound_deflt(pid);
|
||||
}
|
||||
fclose(pidfile);
|
||||
}
|
||||
@ -132,8 +132,8 @@ void check4running(char *selfname, char *pidfilename){
|
||||
while((de = readdir(dir))){ // scan /proc
|
||||
if(!(pid = (pid_t)atoi(de->d_name)) || pid == self) // pass non-PID files and self
|
||||
continue;
|
||||
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0)
|
||||
iffound_default(pid);
|
||||
if((name = sl_getPSname(pid)) && strncmp(name, myname, 255) == 0)
|
||||
sl_iffound_deflt(pid);
|
||||
}
|
||||
closedir(dir);
|
||||
free(myname);
|
||||
|
||||
@ -9,3 +9,4 @@ link_libraries(usefull_macros)
|
||||
add_executable(helloworld helloworld.c)
|
||||
add_executable(options options.c cmdlnopts.c)
|
||||
add_executable(fifo fifo.c)
|
||||
add_executable(conffile conffile.c)
|
||||
|
||||
@ -38,6 +38,9 @@ static glob_pars G;
|
||||
// DEFAULTS
|
||||
// default global parameters
|
||||
static glob_pars const Gdefault = {
|
||||
.lo0 = INT_MIN,
|
||||
.lo1 = INT_MIN,
|
||||
.lo2 = INT_MIN,
|
||||
.device = NULL,
|
||||
.pidfile = DEFAULT_PIDFILE,
|
||||
.speed = 9600,
|
||||
@ -48,15 +51,21 @@ static glob_pars const Gdefault = {
|
||||
* Define command line options by filling structure:
|
||||
* name has_arg flag val type argptr help
|
||||
*/
|
||||
static myoption cmdlnopts[] = {
|
||||
// common options
|
||||
static sl_option_t cmdlnopts[] = {
|
||||
{"lo0", NEED_ARG, NULL, 0, arg_int, APTR(&G.lo0), _("only long arg 0")},
|
||||
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
|
||||
// {"dup", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
|
||||
{"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), _("serial device name")},
|
||||
{"lo2", NEED_ARG, NULL, 0, arg_int, APTR(&G.lo2), _("only long arg 2")},
|
||||
{"speed", NEED_ARG, NULL, 's', arg_int, APTR(&G.speed), _("serial device speed (default: 9600)")},
|
||||
{"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("file to save logs")},
|
||||
{"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfile), _("pidfile (default: " DEFAULT_PIDFILE ")")},
|
||||
{"exclusive",NO_ARGS, NULL, 'e', arg_int, APTR(&G.exclusive), _("open serial device exclusively")},
|
||||
// example of multiple options
|
||||
{"Int", MULT_PAR, NULL, 'I', arg_int, APTR(&G.intarr), _("integer multiplying parameter")},
|
||||
{"Dbl", MULT_PAR, NULL, 'D', arg_double, APTR(&G.dblarr), _("double multiplying parameter")},
|
||||
{"Str", MULT_PAR, NULL, 'S', arg_string, APTR(&G.strarr), _("string multiplying parameter")},
|
||||
{"lo1", NEED_ARG, NULL, 0, arg_int, APTR(&G.lo1), _("only long arg 1")},
|
||||
end_option
|
||||
};
|
||||
|
||||
@ -75,10 +84,10 @@ glob_pars *parse_args(int argc, char **argv){
|
||||
char helpstring[1024], *hptr = helpstring;
|
||||
snprintf(hptr, hlen, "Usage: %%s [args]\n\n\tWhere args are:\n");
|
||||
// format of help: "Usage: progname [args]\n"
|
||||
change_helpstring(helpstring);
|
||||
sl_helpstring(helpstring);
|
||||
// parse arguments
|
||||
parseargs(&argc, &argv, cmdlnopts);
|
||||
if(help) showhelp(-1, cmdlnopts);
|
||||
sl_parseargs(&argc, &argv, cmdlnopts);
|
||||
if(help) sl_showhelp(-1, cmdlnopts);
|
||||
if(argc > 0){
|
||||
G.rest_pars_num = argc;
|
||||
G.rest_pars = MALLOC(char *, argc);
|
||||
|
||||
@ -31,8 +31,14 @@ typedef struct{
|
||||
char *pidfile; // name of PID file
|
||||
char *logfile; // logging to this file
|
||||
int speed; // connection speed
|
||||
int rest_pars_num; // number of rest parameters
|
||||
int exclusive; // exclusive open port
|
||||
int **intarr; // integer multopt
|
||||
double **dblarr; // double -//-
|
||||
char **strarr; // char -//-
|
||||
int lo0; // only long options
|
||||
int lo1;
|
||||
int lo2;
|
||||
int rest_pars_num; // number of rest parameters
|
||||
char** rest_pars; // the rest parameters: array of char*
|
||||
} glob_pars;
|
||||
|
||||
|
||||
101
examples/conffile.c
Normal file
101
examples/conffile.c
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 <math.h> // NaN
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "usefull_macros.h"
|
||||
|
||||
typedef struct{
|
||||
char *sp1;
|
||||
char *sp2;
|
||||
int ip1;
|
||||
int ip2;
|
||||
double dp1;
|
||||
double dp2;
|
||||
float fp1;
|
||||
float fp2;
|
||||
int help;
|
||||
int verbose;
|
||||
char *confname;
|
||||
} parameters;
|
||||
|
||||
static parameters G = {
|
||||
.ip1 = INT_MIN,
|
||||
.ip2 = INT_MIN,
|
||||
.dp1 = NAN,
|
||||
.dp2 = NAN,
|
||||
.fp1 = NAN,
|
||||
.fp2 = NAN
|
||||
};
|
||||
|
||||
static sl_option_t cmdlnopts[] = {
|
||||
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&G.help), "show this help"},
|
||||
{"string1", NEED_ARG, NULL, 's', arg_string, APTR(&G.sp1), "string one"},
|
||||
{"string2", NEED_ARG, NULL, 'c', arg_string, APTR(&G.sp2), "string two"},
|
||||
{"int1", NEED_ARG, NULL, 'i', arg_int, APTR(&G.ip1), "integer one"},
|
||||
{"int2", NEED_ARG, NULL, 'u', arg_int, APTR(&G.ip2), "integer two"},
|
||||
{"double1", NEED_ARG, NULL, 'd', arg_double, APTR(&G.dp1), "double one"},
|
||||
{"double2", NEED_ARG, NULL, 'o', arg_double, APTR(&G.dp2), "double two"},
|
||||
{"float1", NEED_ARG, NULL, 'f', arg_float, APTR(&G.fp1), "float one"},
|
||||
{"float2", NEED_ARG, NULL, 'l', arg_float, APTR(&G.fp2), "float two"},
|
||||
{"config", NEED_ARG, NULL, 'C', arg_string, APTR(&G.confname),"name of configuration file"},
|
||||
{"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&G.verbose),"verbose level (each -v adds 1)"},
|
||||
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;
|
||||
printf("verbose level: %d\n", lvl);
|
||||
if(G.sp1){
|
||||
printf("Parsing of string1: ");
|
||||
char key[SL_KEY_LEN], val[SL_VAL_LEN];
|
||||
int k = sl_get_keyval(G.sp1, key, val);
|
||||
switch(k){
|
||||
case 0:
|
||||
red("key not found\n");
|
||||
break;
|
||||
case 1:
|
||||
green("got key='%s'\n", key);
|
||||
break;
|
||||
default:
|
||||
green("got key='%s', value='%s'\n", key, val);
|
||||
}
|
||||
}
|
||||
green("Starting parameters values:\n");
|
||||
char *buf = sl_print_opts(cmdlnopts, TRUE);
|
||||
printf("%s\n", buf);
|
||||
FREE(buf);
|
||||
if(G.confname){
|
||||
int o = sl_conf_readopts(G.confname, cmdlnopts);
|
||||
if(o > 0){
|
||||
printf("got %d options in '%s'\n", o, G.confname);
|
||||
green("And after reading of conffile:\n");
|
||||
buf = sl_print_opts(cmdlnopts, TRUE);
|
||||
printf("%s\n", buf);
|
||||
FREE(buf);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -23,8 +23,8 @@
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[argc]) {
|
||||
List *f = NULL;
|
||||
printf("Available memory: %luMB\n", get_available_mem()/1024/1024);
|
||||
sl_list_t *f = NULL;
|
||||
printf("Available memory: %luMB\n", sl_mem_avail()/1024/1024);
|
||||
//initial_setup(); - there's no need for this function if you don't use locale & don't want to have
|
||||
// specific output in non-tty
|
||||
if(argc == 1){
|
||||
@ -33,26 +33,26 @@ int main(int argc, char *argv[argc]) {
|
||||
}
|
||||
red("\n\nLIFO example\n");
|
||||
for(int i = 1; i < argc; ++i){
|
||||
if(!list_push(&f, argv[i])) ERR("Allocation error!");
|
||||
if(!sl_list_push(&f, argv[i])) ERR("Allocation error!");
|
||||
green("push to list ");
|
||||
printf("%s\n", argv[i]);
|
||||
}
|
||||
char *d;
|
||||
printf("\n");
|
||||
while(f){
|
||||
d = list_pop(&f);
|
||||
d = sl_list_pop(&f);
|
||||
green("pull: ");
|
||||
printf("%s\n", d);
|
||||
}
|
||||
red("\n\nFIFO example\n");
|
||||
for(int i = 1; i < argc; ++i){
|
||||
if(!list_push_tail(&f, argv[i])) ERR("Allocation error!");
|
||||
if(!sl_list_push_tail(&f, argv[i])) ERR("Allocation error!");
|
||||
green("push to list ");
|
||||
printf("%s\n", argv[i]);
|
||||
}
|
||||
printf("\n");
|
||||
while(f){
|
||||
d = list_pop(&f);
|
||||
d = sl_list_pop(&f);
|
||||
green("pull: ");
|
||||
printf("%s\n", d);
|
||||
// after last usage we should FREE data, but here it is parameter of main()
|
||||
|
||||
@ -23,13 +23,13 @@
|
||||
*/
|
||||
|
||||
int main(){
|
||||
initial_setup();
|
||||
sl_init();
|
||||
// setup non-echo non-canonical mode
|
||||
setup_con();
|
||||
sl_setup_con();
|
||||
green("Press any key...\n");
|
||||
char k = mygetchar();
|
||||
char k = sl_getchar();
|
||||
red("You press %c\n", k);
|
||||
// don't forget to restore @exit!
|
||||
restore_console();
|
||||
sl_restore_con();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -24,20 +24,6 @@
|
||||
#include <unistd.h> // sleep
|
||||
#include <usefull_macros.h>
|
||||
|
||||
|
||||
#include <termios.h> // tcsetattr
|
||||
#include <unistd.h> // tcsetattr, close, read, write
|
||||
#include <sys/ioctl.h> // ioctl
|
||||
#include <stdio.h> // printf, getchar, fopen, perror
|
||||
#include <stdlib.h> // exit
|
||||
#include <sys/stat.h> // read
|
||||
#include <fcntl.h> // read
|
||||
#include <signal.h> // signal
|
||||
#include <time.h> // time
|
||||
#include <string.h> // memcpy
|
||||
#include <stdint.h> // int types
|
||||
#include <sys/time.h> // gettimeofday
|
||||
|
||||
/**
|
||||
* This is an example of usage:
|
||||
* - command line arguments,
|
||||
@ -48,7 +34,7 @@
|
||||
* The `cmdlnopts.[hc]` are intrinsic files of this demo.
|
||||
*/
|
||||
|
||||
static TTY_descr *dev = NULL; // shoul be global to restore if die
|
||||
static sl_tty_t *dev = NULL; // shoul be global to restore if die
|
||||
static glob_pars *GP = NULL; // for GP->pidfile need in `signals`
|
||||
|
||||
/**
|
||||
@ -62,28 +48,26 @@ void signals(int sig){
|
||||
LOGERR("Exit with status %d", sig);
|
||||
if(GP && GP->pidfile) // remove unnesessary PID file
|
||||
unlink(GP->pidfile);
|
||||
restore_console();
|
||||
if(dev) close_tty(&dev);
|
||||
sl_restore_con();
|
||||
if(dev) sl_tty_close(&dev);
|
||||
exit(sig);
|
||||
}
|
||||
|
||||
void iffound_default(pid_t pid){
|
||||
void sl_iffound_deflt(pid_t pid){
|
||||
ERRX("Another copy of this process found, pid=%d. Exit.", pid);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
initial_setup();
|
||||
char *self = strdup(argv[0]);
|
||||
sl_init();
|
||||
GP = parse_args(argc, argv);
|
||||
if(GP->rest_pars_num){
|
||||
printf("%d extra options:\n", GP->rest_pars_num);
|
||||
for(int i = 0; i < GP->rest_pars_num; ++i)
|
||||
printf("%s\n", GP->rest_pars[i]);
|
||||
}
|
||||
check4running(self, GP->pidfile);
|
||||
red("%s started, snippets library version is %s\n", self, sl_libversion());
|
||||
free(self);
|
||||
setup_con();
|
||||
sl_check4running((char*)__progname, GP->pidfile);
|
||||
red("%s started, snippets library version is %s\n", __progname, sl_libversion());
|
||||
sl_setup_con();
|
||||
signal(SIGTERM, signals); // kill (-15) - quit
|
||||
signal(SIGHUP, SIG_IGN); // hup - ignore
|
||||
signal(SIGINT, signals); // ctrl+C - quit
|
||||
@ -95,10 +79,25 @@ int main(int argc, char *argv[]){
|
||||
for(int i = 0; i < GP->rest_pars_num; ++i)
|
||||
printf("Extra argument: %s\n", GP->rest_pars[i]);
|
||||
}
|
||||
if(GP->intarr){
|
||||
int **p = GP->intarr;
|
||||
for(int i = 0; *p; ++i) printf("Integer[%d]: %d\n", i, **p++);
|
||||
}
|
||||
if(GP->dblarr){
|
||||
double **p = GP->dblarr;
|
||||
for(int i = 0; *p; ++i) printf("Double[%d]: %g\n", i, **p++);
|
||||
}
|
||||
if(GP->strarr){
|
||||
char **p = GP->strarr;
|
||||
for(int i = 0; *p; ++i) printf("String[%d]: \"%s\"\n", i, *p++);
|
||||
}
|
||||
if(GP->lo0 != INT_MIN) printf("You set lo0 to %d\n", GP->lo0);
|
||||
if(GP->lo1 != INT_MIN) printf("You set lo1 to %d\n", GP->lo1);
|
||||
if(GP->lo2 != INT_MIN) printf("You set lo2 to %d\n", GP->lo2);
|
||||
if(GP->device){
|
||||
LOGDBG("Try to open serial %s", GP->device);
|
||||
dev = new_tty(GP->device, GP->speed, 4096);
|
||||
if(dev) dev = tty_open(dev, GP->exclusive);
|
||||
dev = sl_tty_new(GP->device, GP->speed, 4096);
|
||||
if(dev) dev = sl_tty_open(dev, GP->exclusive);
|
||||
if(!dev){
|
||||
LOGERR("Can't open %s with speed %d. Exit.", GP->device, GP->speed);
|
||||
signals(0);
|
||||
@ -106,26 +105,26 @@ int main(int argc, char *argv[]){
|
||||
}
|
||||
|
||||
// main stuff goes here
|
||||
long seed = throw_random_seed();
|
||||
long seed = sl_random_seed();
|
||||
green("Now I will sleep for 10 seconds after your last input.\n Do whatever you want. Random seed: %ld\n", seed);
|
||||
LOGWARN("warning message example");
|
||||
LOGWARNADD("with next string without timestamp");
|
||||
double t0 = dtime();
|
||||
double t0 = sl_dtime();
|
||||
char b[2] = {0};
|
||||
while(dtime() - t0 < 10.){ // read data from port and print in into terminal
|
||||
while(sl_dtime() - t0 < 10.){ // read data from port and print in into terminal
|
||||
if(dev){
|
||||
if(read_tty(dev)){
|
||||
if(sl_tty_read(dev)){
|
||||
printf("Got %zd bytes from port: %s\n", dev->buflen, dev->buf);
|
||||
LOGMSG("Got from serial: %s", dev->buf);
|
||||
t0 = dtime();
|
||||
t0 = sl_dtime();
|
||||
}
|
||||
int r = read_console();
|
||||
int r = sl_read_con();
|
||||
if(r < 1) continue;
|
||||
t0 = dtime();
|
||||
t0 = sl_dtime();
|
||||
b[0] = (char) r;
|
||||
printf("send to tty: %d (%c)\n", r, b[0]);
|
||||
LOGMSG("send to tty: %d (%c)\n", r, b[0]);
|
||||
write_tty(dev->comfd, b, 1);
|
||||
sl_tty_write(dev->comfd, b, 1);
|
||||
}
|
||||
}
|
||||
// clean everything
|
||||
|
||||
22
fifo_lifo.c
22
fifo_lifo.c
@ -22,15 +22,15 @@
|
||||
#include "usefull_macros.h"
|
||||
|
||||
/**
|
||||
* @brief list_push_tail - push data into the tail of a stack (like FIFO)
|
||||
* @brief sl_list_push_tail - push data into the tail of a stack (like FIFO)
|
||||
* @param lst (io) - list
|
||||
* @param v (i) - data to push
|
||||
* @return pointer to just pused node or NULL in case of error
|
||||
*/
|
||||
List *list_push_tail(List **lst, void *v){
|
||||
List *node;
|
||||
sl_list_t *sl_list_push_tail(sl_list_t **lst, void *v){
|
||||
sl_list_t *node;
|
||||
if(!lst) return NULL;
|
||||
if((node = MALLOC(List, 1)) == NULL)
|
||||
if((node = MALLOC(sl_list_t, 1)) == NULL)
|
||||
return NULL; // allocation error
|
||||
node->data = v; // insert data
|
||||
if(!*lst){
|
||||
@ -43,15 +43,15 @@ List *list_push_tail(List **lst, void *v){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief list_push - push data into the head of a stack (like LIFO)
|
||||
* @brief sl_list_push - push data into the head of a stack (like LIFO)
|
||||
* @param lst (io) - list
|
||||
* @param v (i) - data to push
|
||||
* @return pointer to just pused node
|
||||
*/
|
||||
List *list_push(List **lst, void *v){
|
||||
List *node;
|
||||
sl_list_t *sl_list_push(sl_list_t **lst, void *v){
|
||||
sl_list_t *node;
|
||||
if(!lst) return NULL;
|
||||
if((node = MALLOC(List, 1)) == NULL)
|
||||
if((node = MALLOC(sl_list_t, 1)) == NULL)
|
||||
return NULL; // allocation error
|
||||
node->data = v; // insert data
|
||||
if(!*lst){
|
||||
@ -66,13 +66,13 @@ List *list_push(List **lst, void *v){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief list_pop - get data from head of list. Don't forget to FREE list data after `pop`
|
||||
* @brief sl_list_pop - get data from head of list. Don't forget to FREE list data after `pop`
|
||||
* @param lst (io) - list
|
||||
* @return data from lst head
|
||||
*/
|
||||
void *list_pop(List **lst){
|
||||
void *sl_list_pop(sl_list_t **lst){
|
||||
void *ret;
|
||||
List *node = *lst;
|
||||
sl_list_t *node = *lst;
|
||||
if(!lst || !*lst) return NULL;
|
||||
ret = (*lst)->data;
|
||||
*lst = (*lst)->next;
|
||||
|
||||
Binary file not shown.
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-24 12:22+0300\n"
|
||||
"POT-Creation-Date: 2024-11-15 11:38+0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -17,8 +17,36 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=koi8-r\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#. / \nОбнаружен одноименный процесс (pid=%d), выход.\n
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:70
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:225
|
||||
msgid "Unsupported option type"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:228
|
||||
#, c-format
|
||||
msgid "Wrong number format '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:272
|
||||
#, c-format
|
||||
msgid "Can't open %s"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:283
|
||||
#, c-format
|
||||
msgid "Wrong key: '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:289
|
||||
#, c-format
|
||||
msgid "Key '%s' need value"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:295
|
||||
#, c-format
|
||||
msgid "Key '%s' have no argptr!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:69
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\n"
|
||||
@ -26,154 +54,137 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#. error reading self name
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:118
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:117
|
||||
msgid "Can't read self name"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу открыть PID файл
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:143
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:141
|
||||
msgid "Can't open PID file"
|
||||
msgstr ""
|
||||
|
||||
#. amount of pcount and/or scount wrong
|
||||
#. / Неправильный формат строки помощи
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:54
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:53
|
||||
msgid "Wrong helpstring!"
|
||||
msgstr ""
|
||||
|
||||
#. / Целое вне допустимого диапазона
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:84
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:82
|
||||
msgid "Integer out of range"
|
||||
msgstr ""
|
||||
|
||||
#. / "Не могу использовать несколько параметров без аргументов!"
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:151
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:166
|
||||
msgid "Can't use multiple args with arg_none!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:252
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:267
|
||||
#, c-format
|
||||
msgid "double long arguments: --%s"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:258
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:273
|
||||
#, c-format
|
||||
msgid "double short arguments: -%c"
|
||||
msgstr ""
|
||||
|
||||
#. / Неправильный параметр: %s
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:470
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:332
|
||||
#, c-format
|
||||
msgid "Need argument with %s type\n"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:486
|
||||
#, c-format
|
||||
msgid "Wrong parameter: %s"
|
||||
msgstr ""
|
||||
|
||||
#. / %s: необходим аргумент!
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:475
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:490
|
||||
#, c-format
|
||||
msgid "%s: need argument!"
|
||||
msgstr ""
|
||||
|
||||
#. / Неправильный аргумент \"%s\" параметра \"%s\"
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:480
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:494
|
||||
#, c-format
|
||||
msgid "Wrong argument \"%s\" of parameter \"%s\""
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:92
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:87
|
||||
#, c-format
|
||||
msgid "Wrong speed value: %d!"
|
||||
msgid "Wrong USART format \"%s\"; use NPS, where N: 5..8; P: N/E/O/1/0, S: 1/2"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу использовать порт %s
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:105
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:102
|
||||
#, c-format
|
||||
msgid "Can't use port %s"
|
||||
msgstr ""
|
||||
|
||||
#. Get settings
|
||||
#. / Не могу получить действующие настройки порта
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:110
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:106
|
||||
msgid "Can't get old TTY settings"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу сменить настройки порта
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:121
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:119
|
||||
msgid "Can't apply new TTY settings"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу сделать порт эксклюзивным
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:128
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:124
|
||||
#, c-format
|
||||
msgid "Can't set speed %d, got ispeed=%d, ospeed=%d"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:130
|
||||
msgid "Can't do exclusive open"
|
||||
msgstr ""
|
||||
|
||||
#. / Отсутствует имя порта
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:164
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:162
|
||||
msgid "Port name is missing"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:170
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:168
|
||||
msgid "Need non-zero buffer for TTY device"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу открыть /dev/random
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:185
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:194
|
||||
msgid "Can't open /dev/random"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу прочесть /dev/random
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:190
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:198
|
||||
msgid "Can't read /dev/random"
|
||||
msgstr ""
|
||||
|
||||
#. / Не задано имя файла!
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:241
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:248
|
||||
msgid "No filename given!"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу открыть %s для чтения
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:246
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:252
|
||||
#, c-format
|
||||
msgid "Can't open %s for reading"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу выполнить stat %s
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:251
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:256
|
||||
#, c-format
|
||||
msgid "Can't stat %s"
|
||||
msgstr ""
|
||||
|
||||
#. / Ошибка mmap
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:258
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:262
|
||||
msgid "Mmap error for input"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу закрыть mmap'нутый файл
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:263
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:266
|
||||
msgid "Can't close mmap'ed file"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу munmap
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:277
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:279
|
||||
msgid "Can't munmap"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу настроить консоль
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:308
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:347
|
||||
msgid "Can't setup console"
|
||||
msgstr ""
|
||||
|
||||
#. / Не задано имя логфайла
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:383
|
||||
msgid "Need filename for log file"
|
||||
msgstr ""
|
||||
|
||||
#. / Пробую открыть логфайл %s в режиме дополнения\n
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:387
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:403
|
||||
#, c-format
|
||||
msgid "Try to open log file %s in append mode\n"
|
||||
msgid "Wrong double number format '%s'"
|
||||
msgstr ""
|
||||
|
||||
#. / Не могу открыть логфайл
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:391
|
||||
msgid "Can't open log file"
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:416
|
||||
#, c-format
|
||||
msgid "Wrong integer number format '%s'"
|
||||
msgstr ""
|
||||
|
||||
155
locale/ru/ru.po
155
locale/ru/ru.po
@ -7,7 +7,7 @@
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-24 12:22+0300\n"
|
||||
"POT-Creation-Date: 2024-11-15 11:38+0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -16,164 +16,177 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Content-Type: text/plain; charset=koi8-r\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#. / \nОбнаружен одноименный процесс (pid=%d), выход.\n
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:70
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:69
|
||||
#, c-format
|
||||
msgid "\n"
|
||||
"Found running process (pid=%d), exit.\n"
|
||||
msgstr "\n"
|
||||
"ïÂÎÁÒÕÖÅÎ ÏÄÎÏÉÍÅÎÎÙÊ ÐÒÏÃÅÓÓ (pid=%d), ×ÙÈÏÄ.\n"
|
||||
|
||||
#. / %s: необходим аргумент!
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:475
|
||||
#, fuzzy, c-format
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:490
|
||||
#, c-format
|
||||
msgid "%s: need argument!"
|
||||
msgstr "%s: ÎÅÏÂÈÏÄÉÍ ÁÒÇÕÍÅÎÔ!"
|
||||
|
||||
#. / Не могу сменить настройки порта
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:121
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:119
|
||||
msgid "Can't apply new TTY settings"
|
||||
msgstr "îÅ ÍÏÇÕ ÓÍÅÎÉÔØ ÎÁÓÔÒÏÊËÉ ÐÏÒÔÁ"
|
||||
|
||||
#. / Не могу закрыть mmap'нутый файл
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:263
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:266
|
||||
msgid "Can't close mmap'ed file"
|
||||
msgstr "îÅ ÍÏÇÕ ÚÁËÒÙÔØ mmap'ÎÕÔÙÊ ÆÁÊÌ"
|
||||
|
||||
#. / Не могу сделать порт эксклюзивным
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:128
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:130
|
||||
msgid "Can't do exclusive open"
|
||||
msgstr "îÅ ÍÏÇÕ ÐÅÒÅ×ÅÓÔÉ ÐÏÒÔ × ÜËÓËÌÀÚÉ×ÎÙÊ ÒÅÖÉÍ"
|
||||
|
||||
#. Get settings
|
||||
#. / Не могу получить действующие настройки порта
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:110
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:106
|
||||
msgid "Can't get old TTY settings"
|
||||
msgstr "îÅ ÍÏÇÕ ÐÏÌÕÞÉÔØ ÄÅÊÓÔ×ÕÀÝÉÅ ÎÁÓÔÒÏÊËÉ ÐÏÒÔÁ"
|
||||
|
||||
#. / Не могу munmap
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:277
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:279
|
||||
msgid "Can't munmap"
|
||||
msgstr "îÅ ÍÏÇÕ munmap"
|
||||
|
||||
#. / Не могу открыть %s для чтения
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:246
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:272
|
||||
#, c-format
|
||||
msgid "Can't open %s"
|
||||
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:252
|
||||
#, c-format
|
||||
msgid "Can't open %s for reading"
|
||||
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
|
||||
|
||||
#. / Не могу открыть /dev/random
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:185
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:194
|
||||
msgid "Can't open /dev/random"
|
||||
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ /dev/random"
|
||||
|
||||
#. / Не могу открыть PID файл
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:143
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:141
|
||||
msgid "Can't open PID file"
|
||||
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ PID ÆÁÊÌ"
|
||||
|
||||
#. / Не могу открыть логфайл
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:391
|
||||
msgid "Can't open log file"
|
||||
msgstr "Не могу открыть логфайл"
|
||||
|
||||
#. / Не могу прочесть /dev/random
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:190
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:198
|
||||
msgid "Can't read /dev/random"
|
||||
msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ /dev/random"
|
||||
|
||||
#. error reading self name
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:118
|
||||
#, fuzzy
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:117
|
||||
msgid "Can't read self name"
|
||||
msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ ÉÍÑ ÐÒÏÃÅÓÓÁ"
|
||||
|
||||
#. / Не могу настроить консоль
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:308
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:124
|
||||
#, c-format
|
||||
msgid "Can't set speed %d, got ispeed=%d, ospeed=%d"
|
||||
msgstr "îÅ ÍÏÇÕ ÓÍÅÎÉÔØ ÓËÏÒÏÓÔØ ÎÁ %d; ispeed=%d, ospeed=%d"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:347
|
||||
msgid "Can't setup console"
|
||||
msgstr "îÅ ÍÏÇÕ ÎÁÓÔÒÏÉÔØ ËÏÎÓÏÌØ"
|
||||
|
||||
#. / Не могу выполнить stat %s
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:251
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:256
|
||||
#, c-format
|
||||
msgid "Can't stat %s"
|
||||
msgstr "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ stat %s"
|
||||
|
||||
#. / "Не могу использовать несколько параметров без аргументов!"
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:151
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:166
|
||||
msgid "Can't use multiple args with arg_none!"
|
||||
msgstr "íÁÓÓÉ× ÐÁÒÁÍÅÔÒÏ× ÎÅ ÍÏÖÅÔ ÉÍÅÔØ ÔÉÐ arg_none!"
|
||||
|
||||
#. / Не могу использовать порт %s
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:105
|
||||
#, fuzzy, c-format
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:102
|
||||
#, c-format
|
||||
msgid "Can't use port %s"
|
||||
msgstr "îÅ ÍÏÇÕ ÉÓÐÏÌØÚÏ×ÁÔØ ÐÏÒÔ %s"
|
||||
|
||||
#. / Целое вне допустимого диапазона
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:84
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:82
|
||||
msgid "Integer out of range"
|
||||
msgstr "ãÅÌÏÅ ×ÎÅ ÄÏÐÕÓÔÉÍÏÇÏ ÄÉÁÐÁÚÏÎÁ"
|
||||
|
||||
#. / Ошибка mmap
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:258
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:295
|
||||
#, c-format
|
||||
msgid "Key '%s' have no argptr!"
|
||||
msgstr "õ ËÌÀÞÁ '%s' ÎÅÔ ÕËÁÚÁÔÅÌÑ ÎÁ ÐÅÒÅÍÅÎÎÕÀ!"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:289
|
||||
#, c-format
|
||||
msgid "Key '%s' need value"
|
||||
msgstr "ëÌÀÞ '%s' ÔÒÅÂÕÅÔ ÚÎÁÞÅÎÉÑ"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:262
|
||||
msgid "Mmap error for input"
|
||||
msgstr "ïÛÉÂËÁ mmap"
|
||||
|
||||
#. / Не задано имя логфайла
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:383
|
||||
msgid "Need filename for log file"
|
||||
msgstr "Не задано имя логфайла"
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:332
|
||||
#, c-format
|
||||
msgid "Need argument with %s type\n"
|
||||
msgstr "îÅÏÂÈÏÄÉÍ ÁÒÇÕÍÅÎÔ Ó ÔÉÐÏÍ %s\n"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:170
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:168
|
||||
msgid "Need non-zero buffer for TTY device"
|
||||
msgstr "äÌÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÇÏ ÕÓÔÒÏÊÓÔ×Á ÔÒÅÂÕÅÔÓÑ ÂÕÆÅÒ ÎÅÎÕÌÅ×ÏÇÏ ÒÁÚÍÅÒÁ"
|
||||
|
||||
#. / Не задано имя файла!
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:241
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:248
|
||||
msgid "No filename given!"
|
||||
msgstr "îÅ ÚÁÄÁÎÏ ÉÍÑ ÆÁÊÌÁ!"
|
||||
|
||||
#. / Отсутствует имя порта
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:164
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:162
|
||||
msgid "Port name is missing"
|
||||
msgstr "ïÔÓÕÔÓÔ×ÕÅÔ ÉÍÑ ÐÏÒÔÁ"
|
||||
|
||||
#. / Пробую открыть логфайл %s в режиме дополнения\n
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:387
|
||||
#, c-format
|
||||
msgid "Try to open log file %s in append mode\n"
|
||||
msgstr "Пробую открыть логфайл %s в режиме дополнения\n"
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:225
|
||||
msgid "Unsupported option type"
|
||||
msgstr "îÅÐÏÄÄÅÒÖÉ×ÁÅÍÙÊ ÔÉÐ ÏÐÃÉÉ"
|
||||
|
||||
#. / Неправильный аргумент \"%s\" параметра \"%s\"
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:480
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term2.c:87
|
||||
#, c-format
|
||||
msgid "Wrong USART format \"%s\"; use NPS, where N: 5..8; P: N/E/O/1/0, S: "
|
||||
"1/2"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ USART \"%s\"; ÎÕÖÅÎ NPS, ÇÄÅ N: 5..8; P: N/E/"
|
||||
"O/1/0, S: 1/2"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:494
|
||||
#, c-format
|
||||
msgid "Wrong argument \"%s\" of parameter \"%s\""
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÁÒÇÕÍÅÎÔ \"%s\" ÐÁÒÁÍÅÔÒÁ \"%s\""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:403
|
||||
#, c-format
|
||||
msgid "Wrong double number format '%s'"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ double: %s"
|
||||
|
||||
#. amount of pcount and/or scount wrong
|
||||
#. / Неправильный формат строки помощи
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:54
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:53
|
||||
msgid "Wrong helpstring!"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÓÔÒÏËÉ ÐÏÍÏÝÉ"
|
||||
|
||||
#. / Неправильный параметр: %s
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:470
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:416
|
||||
#, c-format
|
||||
msgid "Wrong integer number format '%s'"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÃÅÌÏÇÏ: %s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:283
|
||||
#, c-format
|
||||
msgid "Wrong key: '%s'"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ËÌÀÞ: %s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:228
|
||||
#, c-format
|
||||
msgid "Wrong number format '%s'"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÞÉÓÌÁ: %s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:486
|
||||
#, c-format
|
||||
msgid "Wrong parameter: %s"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÐÁÒÁÍÅÔÒ: %s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:92
|
||||
#, c-format
|
||||
msgid "Wrong speed value: %d!"
|
||||
msgstr "Неправильное значение скорости: %d!"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:252
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:267
|
||||
#, c-format
|
||||
msgid "double long arguments: --%s"
|
||||
msgstr "ÄÕÂÌÉÒÕÀÝÉÊÓÑ ÄÌÉÎÎÙÊ ÐÁÒÁÍÅÔÒ: --%s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:258
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:273
|
||||
#, c-format
|
||||
msgid "double short arguments: -%c"
|
||||
msgstr "ÄÕÂÌÉÒÕÀÝÉÊÓÑ ËÏÒÏÔËÉÊ ÐÁÒÁÍÅÔÒ: -%c"
|
||||
|
||||
|
||||
124
parseargs.c
124
parseargs.c
@ -33,10 +33,10 @@
|
||||
char *helpstring = "%s\n";
|
||||
|
||||
/**
|
||||
* @brief change_helpstring - change standard help header
|
||||
* @brief sl_helpstring - change standard help header
|
||||
* @param str (i) - new format (MAY consist ONE "%s" for progname)
|
||||
*/
|
||||
void change_helpstring(char *s){
|
||||
void sl_helpstring(char *s){
|
||||
int pcount = 0, scount = 0;
|
||||
char *str = s;
|
||||
// check `helpstring` and set it to default in case of error
|
||||
@ -63,7 +63,7 @@ void change_helpstring(char *s){
|
||||
* @param t (i) - T_INT for integer or T_LLONG for long long (if argtype would be wided, may add more)
|
||||
* @return TRUE if conversion done without errors, FALSE otherwise
|
||||
*/
|
||||
static bool myatoll(void *num, char *str, argtype t){
|
||||
static int myatoll(void *num, char *str, sl_argtype_e t){
|
||||
long long tmp, *llptr;
|
||||
int *iptr;
|
||||
char *endptr;
|
||||
@ -92,7 +92,7 @@ static bool myatoll(void *num, char *str, argtype t){
|
||||
|
||||
// the same as myatoll but for double
|
||||
// There's no NAN & INF checking here (what if they would be needed?)
|
||||
static bool myatod(void *num, const char *str, argtype t){
|
||||
static int myatod(void *num, const char *str, sl_argtype_e t){
|
||||
double tmp, *dptr;
|
||||
float *fptr;
|
||||
char *endptr;
|
||||
@ -114,21 +114,39 @@ static bool myatod(void *num, const char *str, argtype t){
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief get_optind - get index of current option in array options
|
||||
* @param opt (i) - returning val of getopt_long
|
||||
* @param options (i) - array of options
|
||||
* @return index in array
|
||||
*/
|
||||
static int get_optind(int opt, myoption *options){
|
||||
static int get_optind(int opt, sl_option_t *options){
|
||||
int oind;
|
||||
myoption *opts = options;
|
||||
sl_option_t *opts = options;
|
||||
assert(opts);
|
||||
for(oind = 0; opts->name && opts->val != opt; oind++, opts++);
|
||||
for(oind = 0; opts->name && opts->val != opt; oind++, opts++){
|
||||
DBG("cmp %c and %c", opt, opts->val);
|
||||
}
|
||||
if(!opts->name || opts->val != opt) // no such parameter
|
||||
showhelp(-1, options);
|
||||
sl_showhelp(-1, options);
|
||||
return oind;
|
||||
}
|
||||
#if 0
|
||||
static int get_optindl(struct option *opt, sl_option_t *options){
|
||||
int oind;
|
||||
sl_option_t *opts = options;
|
||||
assert(opts);
|
||||
for(oind = 0; opts->name; ){
|
||||
DBG("cmp '%s' and '%s'", opt->name, opts->name);
|
||||
if(0 == strcmp(opt->name, opts->name)) break;
|
||||
oind++, opts++;
|
||||
}
|
||||
if(!opts->name || strcmp(opt->name, opts->name)) // no such parameter
|
||||
sl_showhelp(-1, options);
|
||||
return oind;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief get_aptr - reallocate new value in array of multiple repeating arguments
|
||||
@ -136,7 +154,7 @@ static int get_optind(int opt, myoption *options){
|
||||
* @arg type - its type (for realloc)
|
||||
* @return pointer to new (next) value
|
||||
*/
|
||||
void *get_aptr(void *paptr, argtype type){
|
||||
void *get_aptr(void *paptr, sl_argtype_e type){
|
||||
int i = 1;
|
||||
void **aptr = *((void***)paptr);
|
||||
if(aptr){ // there's something in array
|
||||
@ -181,7 +199,7 @@ void *get_aptr(void *paptr, argtype type){
|
||||
|
||||
|
||||
/**
|
||||
* @brief parseargs - parse command line arguments
|
||||
* @brief sl_parseargs - parse command line arguments
|
||||
* ! If arg is string, then value will be strdup'ed!
|
||||
*
|
||||
* @param argc (io) - address of argc of main(), return value of argc stay after `getopt`
|
||||
@ -192,11 +210,11 @@ void *get_aptr(void *paptr, argtype type){
|
||||
*
|
||||
* @exit: in case of error this function show help & make `exit(-1)`
|
||||
*/
|
||||
void parseargs(int *argc, char ***argv, myoption *options){
|
||||
void sl_parseargs(int *argc, char ***argv, sl_option_t *options){
|
||||
char *short_options, *soptr;
|
||||
struct option *long_options, *loptr;
|
||||
size_t optsize, i;
|
||||
myoption *opts = options;
|
||||
sl_option_t *opts = options;
|
||||
// check whether there is at least one options
|
||||
assert(opts);
|
||||
assert(opts[0].name);
|
||||
@ -263,31 +281,45 @@ void parseargs(int *argc, char ***argv, myoption *options){
|
||||
// now we have both long_options & short_options and can parse `getopt_long`
|
||||
while(1){
|
||||
int opt;
|
||||
int oindex = 0, optind = 0; // oindex - number of option in argv, optind - number in options[]
|
||||
if((opt = getopt_long(*argc, *argv, short_options, long_options, &oindex)) == -1) break;
|
||||
if(opt == '?'){
|
||||
opt = optopt;
|
||||
optind = get_optind(opt, options);
|
||||
int /*oindex = -1,*/ optind = -1; // oindex - number of option in long_options, optind - number in options[]
|
||||
if((opt = getopt_long(*argc, *argv, short_options, long_options, &optind)) == -1) break;
|
||||
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)
|
||||
showhelp(optind, options); // need argument
|
||||
}
|
||||
else{
|
||||
if(opt == 0 || oindex > 0) optind = oindex;
|
||||
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];
|
||||
// if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag
|
||||
DBG("Got option %s", opts->name);
|
||||
|
||||
// now check option
|
||||
if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR)
|
||||
if(!optarg) showhelp(optind, options); // need argument
|
||||
if(!optarg) sl_showhelp(optind, options); // need argument
|
||||
void *aptr;
|
||||
if(opts->has_arg == MULT_PAR){
|
||||
aptr = get_aptr(opts->argptr, opts->type);
|
||||
}else
|
||||
aptr = opts->argptr;
|
||||
bool result = TRUE;
|
||||
int result = TRUE;
|
||||
// even if there is no argument, but argptr != NULL, think that optarg = "1"
|
||||
if(!optarg) optarg = "1";
|
||||
const char *type = NULL;
|
||||
switch(opts->type){
|
||||
default:
|
||||
case arg_none:
|
||||
@ -295,25 +327,31 @@ void parseargs(int *argc, char ***argv, myoption *options){
|
||||
break;
|
||||
case arg_int:
|
||||
result = myatoll(aptr, optarg, arg_int);
|
||||
type = _("integer");
|
||||
break;
|
||||
case arg_longlong:
|
||||
result = myatoll(aptr, optarg, arg_longlong);
|
||||
type = _("long long");
|
||||
break;
|
||||
case arg_double:
|
||||
result = myatod(aptr, optarg, arg_double);
|
||||
type = _("double");
|
||||
break;
|
||||
case arg_float:
|
||||
result = myatod(aptr, optarg, arg_float);
|
||||
type = _("float");
|
||||
break;
|
||||
case arg_string:
|
||||
result = (*((void**)aptr) = (void*)strdup(optarg));
|
||||
result = (*((void**)aptr) = (void*)strdup(optarg)) != NULL;
|
||||
type = _("string");
|
||||
break;
|
||||
case arg_function:
|
||||
result = ((argfn)aptr)(optarg);
|
||||
result = ((sl_argfn_t)aptr)(optarg);
|
||||
break;
|
||||
}
|
||||
if(!result){
|
||||
showhelp(optind, options);
|
||||
if(type) fprintf(stderr, _("Need argument with %s type\n"), type);
|
||||
sl_showhelp(optind, options);
|
||||
}
|
||||
}
|
||||
*argc -= optind;
|
||||
@ -325,7 +363,7 @@ void parseargs(int *argc, char ***argv, myoption *options){
|
||||
* first - sort by short options; second - sort arguments without sort opts (by long options)
|
||||
*/
|
||||
static int argsort(const void *a1, const void *a2){
|
||||
const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2;
|
||||
const sl_option_t *o1 = (sl_option_t*)a1, *o2 = (sl_option_t*)a2;
|
||||
const char *l1 = o1->name, *l2 = o2->name;
|
||||
int s1 = o1->val, s2 = o2->val;
|
||||
int *f1 = o1->flag, *f2 = o2->flag;
|
||||
@ -341,17 +379,17 @@ static int argsort(const void *a1, const void *a2){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief showhelp - show help information based on myoption->help values
|
||||
* @param oindex (i) - if non-negative, show only help by myoption[oindex].help
|
||||
* @param options (i) - array of `myoption`
|
||||
* @brief sl_showhelp - show help information based on sl_option_t->help values
|
||||
* @param oindex (i) - if non-negative, show only help by sl_option_t[oindex].help
|
||||
* @param options (i) - array of `sl_option_t`
|
||||
*
|
||||
* @exit: run `exit(-1)` !!!
|
||||
*/
|
||||
void showhelp(int oindex, myoption *options){
|
||||
void sl_showhelp(int oindex, sl_option_t *options){
|
||||
int max_opt_len = 0; // max len of options substring - for right indentation
|
||||
const int bufsz = 255;
|
||||
char buf[bufsz+1];
|
||||
myoption *opts = options;
|
||||
sl_option_t *opts = options;
|
||||
assert(opts);
|
||||
assert(opts[0].name); // check whether there is at least one options
|
||||
if(oindex > -1){ // print only one message
|
||||
@ -383,7 +421,7 @@ void showhelp(int oindex, myoption *options){
|
||||
if(N == 0) exit(-2);
|
||||
// Now print all help (sorted)
|
||||
opts = options;
|
||||
qsort(opts, N, sizeof(myoption), argsort);
|
||||
qsort(opts, N, sizeof(sl_option_t), argsort);
|
||||
do{
|
||||
int p = sprintf(buf, " "); // a little indent
|
||||
if(!opts->flag && opts->val) // .val is short argument
|
||||
@ -402,13 +440,13 @@ void showhelp(int oindex, myoption *options){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get_suboption - get suboptions from parameter string
|
||||
* @brief sl_get_suboption - get suboptions from parameter string
|
||||
* @param str - parameter string
|
||||
* @param opt - pointer to suboptions structure
|
||||
* @return TRUE if all OK
|
||||
*/
|
||||
bool get_suboption(char *str, mysuboption *opt){
|
||||
int findsubopt(char *par, mysuboption *so){
|
||||
int sl_get_suboption(char *str, sl_suboption_t *opt){
|
||||
int findsubopt(char *par, sl_suboption_t *so){
|
||||
int idx = 0;
|
||||
if(!par) return -1;
|
||||
while(so[idx].name){
|
||||
@ -417,9 +455,9 @@ bool get_suboption(char *str, mysuboption *opt){
|
||||
}
|
||||
return -1; // badarg
|
||||
}
|
||||
bool opt_setarg(mysuboption *so, int idx, char *val){
|
||||
mysuboption *soptr = &so[idx];
|
||||
bool result = FALSE;
|
||||
int opt_setarg(sl_suboption_t *so, int idx, char *val){
|
||||
sl_suboption_t *soptr = &so[idx];
|
||||
int result = FALSE;
|
||||
void *aptr = soptr->argptr;
|
||||
switch(soptr->type){
|
||||
default:
|
||||
@ -440,16 +478,16 @@ bool get_suboption(char *str, mysuboption *opt){
|
||||
result = myatod(aptr, val, arg_float);
|
||||
break;
|
||||
case arg_string:
|
||||
result = (*((void**)aptr) = (void*)strdup(val));
|
||||
result = (*((void**)aptr) = (void*)strdup(val)) != NULL;
|
||||
break;
|
||||
case arg_function:
|
||||
result = ((argfn)aptr)(val);
|
||||
result = ((sl_argfn_t)aptr)(val);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
char *tok;
|
||||
bool ret = FALSE;
|
||||
int ret = FALSE;
|
||||
char *tmpbuf;
|
||||
tok = strtok_r(str, ":,", &tmpbuf);
|
||||
do{
|
||||
|
||||
50
term.c
50
term.c
@ -1,11 +1,10 @@
|
||||
/*
|
||||
* client.c - simple terminal client
|
||||
* This file is part of the Snippets project.
|
||||
* Copyright 2013 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* 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 2 of the License, or
|
||||
* 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,
|
||||
@ -14,10 +13,9 @@
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <unistd.h> // tcsetattr, close, read, write
|
||||
#include <sys/ioctl.h> // ioctl
|
||||
#include <stdio.h> // printf, getchar, fopen, perror
|
||||
@ -39,7 +37,7 @@ typedef struct {
|
||||
tcflag_t bspeed; // baudrate from termios.h
|
||||
} spdtbl;
|
||||
|
||||
static int tty_init(TTY_descr *descr);
|
||||
static int tty_init(sl_tty_t *descr);
|
||||
|
||||
static spdtbl speeds[] = {
|
||||
{50, B50},
|
||||
@ -76,11 +74,11 @@ static spdtbl speeds[] = {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief conv_spd - test if `speed` is in .speed of `speeds` array
|
||||
* @brief sl_tty_convspd - test if `speed` is in .speed of `speeds` array
|
||||
* @param speed - integer speed (bps)
|
||||
* @return 0 if error, Bxxx if all OK
|
||||
*/
|
||||
tcflag_t conv_spd(int speed){
|
||||
tcflag_t sl_tty_convspd(int speed){
|
||||
spdtbl *spd = speeds;
|
||||
int curspeed = 0;
|
||||
do{
|
||||
@ -98,7 +96,7 @@ tcflag_t conv_spd(int speed){
|
||||
* @param descr (io) - port descriptor
|
||||
* @return 0 if all OK or error code
|
||||
*/
|
||||
static int tty_init(TTY_descr *descr){
|
||||
static int tty_init(sl_tty_t *descr){
|
||||
// |O_NONBLOCK ?
|
||||
if ((descr->comfd = open(descr->portname, O_RDWR|O_NOCTTY)) < 0){
|
||||
/// 钆 拖钦 捎邢特谙琢载 邢以 %s
|
||||
@ -134,9 +132,9 @@ static int tty_init(TTY_descr *descr){
|
||||
/**
|
||||
* @brief restore_tty - restore opened TTY to previous state and close it
|
||||
*/
|
||||
void close_tty(TTY_descr **descr){
|
||||
void sl_tty_close(sl_tty_t **descr){
|
||||
if(descr == NULL || *descr == NULL) return;
|
||||
TTY_descr *d = *descr;
|
||||
sl_tty_t *d = *descr;
|
||||
if(d->comfd){
|
||||
ioctl(d->comfd, TCSANOW, &d->oldtty); // return TTY to previous state
|
||||
close(d->comfd);
|
||||
@ -147,16 +145,16 @@ void close_tty(TTY_descr **descr){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief new_tty - create new TTY structure with partially filled fields
|
||||
* @brief sl_tty_new - create new TTY structure with partially filled fields
|
||||
* @param comdev - TTY device filename
|
||||
* @param speed - speed (number)
|
||||
* @param bufsz - size of buffer for input data (or 0 if opened only to write)
|
||||
* @return pointer to TTY structure if all OK
|
||||
*/
|
||||
TTY_descr *new_tty(char *comdev, int speed, size_t bufsz){
|
||||
tcflag_t spd = conv_spd(speed);
|
||||
sl_tty_t *sl_tty_new(char *comdev, int speed, size_t bufsz){
|
||||
tcflag_t spd = sl_tty_convspd(speed);
|
||||
if(!spd) return NULL;
|
||||
TTY_descr *descr = MALLOC(TTY_descr, 1);
|
||||
sl_tty_t *descr = MALLOC(sl_tty_t, 1);
|
||||
descr->portname = strdup(comdev);
|
||||
descr->baudrate = spd;
|
||||
descr->speed = speed;
|
||||
@ -176,12 +174,12 @@ TTY_descr *new_tty(char *comdev, int speed, size_t bufsz){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief tty_open - init & open tty device
|
||||
* @brief sl_tty_open - init & open tty device
|
||||
* @param d - already filled structure (with new_tty or by hands)
|
||||
* @param exclusive - == 1 to make exclusive open
|
||||
* @return pointer to TTY structure if all OK
|
||||
*/
|
||||
TTY_descr *tty_open(TTY_descr *d, int exclusive){
|
||||
sl_tty_t *sl_tty_open(sl_tty_t *d, int exclusive){
|
||||
if(!d || !d->portname || !d->baudrate) return NULL;
|
||||
if(exclusive) d->exclusive = TRUE;
|
||||
else d->exclusive = FALSE;
|
||||
@ -191,11 +189,11 @@ TTY_descr *tty_open(TTY_descr *d, int exclusive){
|
||||
|
||||
static struct timeval tvdefault = {.tv_sec = 0, .tv_usec = 5000};
|
||||
/**
|
||||
* @brief tty_timeout - set timeout for select() on reading
|
||||
* @brief sl_tty_tmout - set timeout for select() on reading
|
||||
* @param usec - microseconds of timeout
|
||||
* @return -1 if usec < 0, 0 if all OK
|
||||
*/
|
||||
int tty_timeout(double usec){
|
||||
int sl_tty_tmout(double usec){
|
||||
if(usec < 0.) return -1;
|
||||
tvdefault.tv_sec = 0;
|
||||
if(usec > 999999){
|
||||
@ -207,12 +205,12 @@ int tty_timeout(double usec){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief read_tty - read data from TTY with 10ms timeout
|
||||
* @brief sl_tty_read - read data from TTY with 10ms timeout
|
||||
* @param buff (o) - buffer for data read
|
||||
* @param length - buffer len
|
||||
* @return amount of bytes read or -1 if disconnected
|
||||
*/
|
||||
int read_tty(TTY_descr *d){
|
||||
int sl_tty_read(sl_tty_t *d){
|
||||
if(!d || d->comfd < 0) return 0;
|
||||
size_t L = 0;
|
||||
ssize_t l;
|
||||
@ -246,12 +244,12 @@ int read_tty(TTY_descr *d){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write_tty - write data to serial port
|
||||
* @brief sl_tty_write - write data to serial port
|
||||
* @param buff (i) - data to write
|
||||
* @param length - its length
|
||||
* @return 0 if all OK
|
||||
*/
|
||||
int write_tty(int comfd, const char *buff, size_t length){
|
||||
int sl_tty_write(int comfd, const char *buff, size_t length){
|
||||
ssize_t L = write(comfd, buff, length);
|
||||
if((size_t)L != length){
|
||||
/// "镗陕肆 诹猩由!"
|
||||
|
||||
264
term2.c
Normal file
264
term2.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 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 <unistd.h> // tcsetattr, close, read, write
|
||||
#include <fcntl.h> // read
|
||||
#include <stdio.h> // printf, getchar, fopen, perror
|
||||
#include <stdlib.h> // exit, realloc
|
||||
#include <string.h> // memcpy
|
||||
#include <sys/ioctl.h> // ioctl
|
||||
#include <sys/stat.h> // read
|
||||
#include <sys/time.h> // gettimeofday
|
||||
#include <time.h> // time
|
||||
#include <unistd.h> // usleep, tcsetattr, close, read, write
|
||||
#include "usefull_macros.h"
|
||||
|
||||
#define LOGBUFSZ (1024)
|
||||
|
||||
// return FALSE if failed
|
||||
static int parse_format(const char *iformat, tcflag_t *flags){
|
||||
tcflag_t f = 0;
|
||||
if(!iformat){ // default
|
||||
if(flags) *flags = CS8;
|
||||
return TRUE;
|
||||
}
|
||||
if(strlen(iformat) != 3) goto someerr;
|
||||
switch(iformat[0]){
|
||||
case '5':
|
||||
f |= CS5;
|
||||
break;
|
||||
case '6':
|
||||
f |= CS6;
|
||||
break;
|
||||
case '7':
|
||||
f |= CS7;
|
||||
break;
|
||||
case '8':
|
||||
f |= CS8;
|
||||
break;
|
||||
default:
|
||||
goto someerr;
|
||||
}
|
||||
switch(iformat[1]){
|
||||
case '0': // always 0
|
||||
f |= PARENB | CMSPAR;
|
||||
break;
|
||||
case '1': // always 1
|
||||
f |= PARENB | CMSPAR | PARODD;
|
||||
break;
|
||||
case 'E': // even
|
||||
f |= PARENB;
|
||||
break;
|
||||
case 'N': // none
|
||||
break;
|
||||
case 'O': // odd
|
||||
f |= PARENB | PARODD;
|
||||
break;
|
||||
default:
|
||||
goto someerr;
|
||||
}
|
||||
switch(iformat[2]){
|
||||
case '1':
|
||||
break;
|
||||
case '2':
|
||||
f |= CSTOPB;
|
||||
break;
|
||||
default:
|
||||
goto someerr;
|
||||
}
|
||||
if(flags) *flags = f;
|
||||
return TRUE;
|
||||
someerr:
|
||||
WARNX(_("Wrong USART format \"%s\"; use NPS, where N: 5..8; P: N/E/O/1/0, S: 1/2"), iformat);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief tty_init - open & setup terminal
|
||||
* @param descr (io) - port descriptor
|
||||
* !!! default settings are "8N1".
|
||||
* !!! If you want other, set it like `descr->format = "7O2"` between `sl_tty_new` and `sl_tty_open`
|
||||
* @return 0 if all OK, last error code or 1
|
||||
*/
|
||||
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;
|
||||
}
|
||||
descr->tty = descr->oldtty;
|
||||
descr->tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG)
|
||||
descr->tty.c_iflag = 0; // don't do any changes in input stream
|
||||
descr->tty.c_oflag = 0; // don't do any changes in output stream
|
||||
descr->tty.c_cflag = BOTHER | flags | CREAD | CLOCAL; // other speed, user format, RW, ignore line ctrl
|
||||
descr->tty.c_ispeed = descr->speed;
|
||||
descr->tty.c_ospeed = descr->speed;
|
||||
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;
|
||||
}
|
||||
ioctl(descr->comfd, TCGETS2, &descr->tty);
|
||||
if(descr->tty.c_ispeed != (speed_t)descr->speed || descr->tty.c_ospeed != (speed_t)descr->speed){
|
||||
WARN(_("Can't set speed %d, got ispeed=%d, ospeed=%d"), descr->speed, descr->tty.c_ispeed, descr->tty.c_ospeed);
|
||||
descr->speed = descr->tty.c_ispeed;
|
||||
}
|
||||
// make exclusive open
|
||||
if(descr->exclusive){
|
||||
if(ioctl(descr->comfd, TIOCEXCL)){
|
||||
/// îÅ ÍÏÇÕ ÓÄÅÌÁÔØ ÐÏÒÔ ÜËÓËÌÀÚÉ×ÎÙÍ
|
||||
WARN(_("Can't do exclusive open"));
|
||||
}}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief restore_tty - restore opened TTY to previous state and close it
|
||||
*/
|
||||
void sl_tty_close(sl_tty_t **descr){
|
||||
if(descr == NULL || *descr == NULL) return;
|
||||
sl_tty_t *d = *descr;
|
||||
if(d->comfd){
|
||||
ioctl(d->comfd, TCSETS2, &d->oldtty); // return TTY to previous state
|
||||
close(d->comfd);
|
||||
}
|
||||
FREE(d->portname);
|
||||
FREE(d->buf);
|
||||
FREE(*descr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_tty_new - create new TTY structure with partially filled fields
|
||||
* @param comdev - TTY device filename
|
||||
* @param speed - speed (number)
|
||||
* @param bufsz - size of buffer for input data (or 0 if opened only to write)
|
||||
* @return pointer to TTY structure if all OK
|
||||
*/
|
||||
sl_tty_t *sl_tty_new(char *comdev, int speed, size_t bufsz){
|
||||
sl_tty_t *descr = MALLOC(sl_tty_t, 1);
|
||||
descr->portname = strdup(comdev);
|
||||
descr->speed = speed;
|
||||
if(!descr->portname){
|
||||
/// ïÔÓÕÔÓÔ×ÕÅÔ ÉÍÑ ÐÏÒÔÁ
|
||||
WARNX(_("Port name is missing"));
|
||||
}else{
|
||||
if(bufsz){
|
||||
descr->buf = MALLOC(char, bufsz+1);
|
||||
descr->bufsz = bufsz;
|
||||
return descr;
|
||||
}else WARNX(_("Need non-zero buffer for TTY device"));
|
||||
}
|
||||
FREE(descr->portname);
|
||||
FREE(descr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_tty_open - init & open tty device
|
||||
* @param d - already filled structure (with new_tty or by hands)
|
||||
* @param exclusive - == 1 to make exclusive open
|
||||
* @return pointer to TTY structure if all OK
|
||||
*/
|
||||
sl_tty_t *sl_tty_open(sl_tty_t *d, int exclusive){
|
||||
if(!d || !d->portname) return NULL;
|
||||
if(exclusive) d->exclusive = TRUE;
|
||||
else d->exclusive = FALSE;
|
||||
if(tty_init(d)) return NULL;
|
||||
return d;
|
||||
}
|
||||
|
||||
static struct timeval tvdefault = {.tv_sec = 0, .tv_usec = 5000};
|
||||
/**
|
||||
* @brief sl_tty_tmout - set timeout for select() on reading
|
||||
* @param usec - microseconds of timeout
|
||||
* @return -1 if usec < 0, 0 if all OK
|
||||
*/
|
||||
int sl_tty_tmout(double usec){
|
||||
if(usec < 0.) return -1;
|
||||
tvdefault.tv_sec = 0;
|
||||
if(usec > 999999){
|
||||
tvdefault.tv_sec = (__time_t)(usec / 1e6);
|
||||
usec -= tvdefault.tv_sec * 1e6;
|
||||
}
|
||||
tvdefault.tv_usec = (__suseconds_t) usec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_tty_read - read data from TTY with 10ms timeout
|
||||
* @param buff (o) - buffer for data read
|
||||
* @param length - buffer len
|
||||
* @return amount of bytes read or -1 if disconnected
|
||||
*/
|
||||
int sl_tty_read(sl_tty_t *d){
|
||||
if(!d || d->comfd < 0) return 0;
|
||||
size_t L = 0;
|
||||
ssize_t l;
|
||||
size_t length = d->bufsz;
|
||||
char *ptr = d->buf;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int retval;
|
||||
do{
|
||||
l = 0;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(d->comfd, &rfds);
|
||||
//memcpy(&tv, &tvdefault, sizeof(struct timeval));
|
||||
tv = tvdefault;
|
||||
retval = select(d->comfd + 1, &rfds, NULL, NULL, &tv);
|
||||
if(!retval) break;
|
||||
if(retval < 0){
|
||||
if(errno == EINTR) continue;
|
||||
return -1;
|
||||
}
|
||||
if(FD_ISSET(d->comfd, &rfds)){
|
||||
l = read(d->comfd, ptr, length);
|
||||
if(l < 1) return -1; // disconnected
|
||||
ptr += l; L += l;
|
||||
length -= l;
|
||||
}
|
||||
}while(l && length);
|
||||
d->buflen = L;
|
||||
d->buf[L] = 0;
|
||||
return (size_t)L;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_tty_write - write data to serial port
|
||||
* @param buff (i) - data to write
|
||||
* @param length - its length
|
||||
* @return 0 if all OK
|
||||
*/
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
224
usefull_macros.c
224
usefull_macros.c
@ -18,23 +18,25 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <ctype.h> // isspace
|
||||
#include <err.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/file.h> // flock
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h> // PATH_MAX
|
||||
#include <locale.h>
|
||||
#include <math.h> // floor
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/file.h> // flock
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "usefull_macros.h"
|
||||
|
||||
@ -56,10 +58,10 @@ const char *sl_libversion(){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief dtime - function for different purposes that need to know time intervals
|
||||
* @brief sl_dtime - function for different purposes that need to know time intervals
|
||||
* @return double value: UNIX time in seconds
|
||||
*/
|
||||
double dtime(){
|
||||
double sl_dtime(){
|
||||
double t;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
@ -77,7 +79,7 @@ int globErr = 0; // errno for WARN/ERR
|
||||
* @param fmt ... - printf-like format
|
||||
* @return number of printed symbols
|
||||
*/
|
||||
int r_pr_(const char *fmt, ...){
|
||||
static int r_pr_(const char *fmt, ...){
|
||||
va_list ar; int i;
|
||||
printf(COLOR_RED);
|
||||
va_start(ar, fmt);
|
||||
@ -86,7 +88,7 @@ int r_pr_(const char *fmt, ...){
|
||||
printf(COLOR_OLD);
|
||||
return i;
|
||||
}
|
||||
int g_pr_(const char *fmt, ...){
|
||||
static int g_pr_(const char *fmt, ...){
|
||||
va_list ar; int i;
|
||||
printf(COLOR_GREEN);
|
||||
va_start(ar, fmt);
|
||||
@ -101,7 +103,7 @@ int g_pr_(const char *fmt, ...){
|
||||
* @param fmt ... - printf-like format
|
||||
* @return number of printed symbols
|
||||
*/
|
||||
int r_WARN(const char *fmt, ...){
|
||||
static int r_WARN(const char *fmt, ...){
|
||||
va_list ar; int i = 1;
|
||||
fprintf(stderr, COLOR_RED);
|
||||
va_start(ar, fmt);
|
||||
@ -128,7 +130,7 @@ static const char stars[] = "****************************************";
|
||||
* @param fmt ... - printf-like format
|
||||
* @return number of printed symbols
|
||||
*/
|
||||
int s_WARN(const char *fmt, ...){
|
||||
static int s_WARN(const char *fmt, ...){
|
||||
va_list ar; int i;
|
||||
i = fprintf(stderr, "\n%s\n", stars);
|
||||
va_start(ar, fmt);
|
||||
@ -143,7 +145,7 @@ int s_WARN(const char *fmt, ...){
|
||||
i += fprintf(stderr, "\n");
|
||||
return i;
|
||||
}
|
||||
int r_pr_notty(const char *fmt, ...){
|
||||
static int r_pr_notty(const char *fmt, ...){
|
||||
va_list ar; int i;
|
||||
i = printf("\n%s\n", stars);
|
||||
va_start(ar, fmt);
|
||||
@ -154,10 +156,10 @@ int r_pr_notty(const char *fmt, ...){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initial_setup - setup locale & console
|
||||
* @brief sl_init - setup locale & console
|
||||
* Run this function in the beginning of main() to setup locale & coloured output
|
||||
*/
|
||||
void initial_setup(){
|
||||
void sl_init(){
|
||||
// setup coloured output
|
||||
if(isatty(STDOUT_FILENO)){ // make color output in tty
|
||||
red = r_pr_; green = g_pr_;
|
||||
@ -180,10 +182,10 @@ void initial_setup(){
|
||||
\******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief throw_random_seed - Generate a quasy-random number to initialize PRNG
|
||||
* @brief sl_random_seed - Generate a quasy-random number to initialize PRNG
|
||||
* @return value for srand48
|
||||
*/
|
||||
long throw_random_seed(){
|
||||
long sl_random_seed(){
|
||||
long r_ini;
|
||||
int fail = 0;
|
||||
int fd = open("/dev/random", O_RDONLY);
|
||||
@ -201,7 +203,7 @@ long throw_random_seed(){
|
||||
close(fd);
|
||||
}while(0);
|
||||
if(fail){
|
||||
double tt = dtime() * 1e6;
|
||||
double tt = sl_dtime() * 1e6;
|
||||
double mx = (double)LONG_MAX;
|
||||
r_ini = (long)(tt - mx * floor(tt/mx));
|
||||
}
|
||||
@ -209,10 +211,10 @@ long throw_random_seed(){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get_available_mem
|
||||
* @brief sl_mem_avail
|
||||
* @return system available physical memory
|
||||
*/
|
||||
uint64_t get_available_mem(){
|
||||
uint64_t sl_mem_avail(){
|
||||
return sysconf(_SC_AVPHYS_PAGES) * (uint64_t) sysconf(_SC_PAGE_SIZE);
|
||||
}
|
||||
|
||||
@ -222,12 +224,12 @@ uint64_t get_available_mem(){
|
||||
* Memory
|
||||
\******************************************************************************/
|
||||
/**
|
||||
* @brief my_alloc - safe memory allocation for macro ALLOC
|
||||
* @brief sl_alloc - safe memory allocation for macro ALLOC
|
||||
* @param N - number of elements to allocate
|
||||
* @param S - size of single element (typically sizeof)
|
||||
* @return pointer to allocated memory area
|
||||
*/
|
||||
void *my_alloc(size_t N, size_t S){
|
||||
void *sl_alloc(size_t N, size_t S){
|
||||
void *p = calloc(N, S);
|
||||
if(!p) ERR("malloc");
|
||||
//assert(p);
|
||||
@ -235,11 +237,11 @@ void *my_alloc(size_t N, size_t S){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief My_mmap - mmap file to a memory area
|
||||
* @brief sl_mmap - mmap file to a memory area
|
||||
* @param filename (i) - name of file to mmap
|
||||
* @return stuct with mmap'ed file or die
|
||||
*/
|
||||
mmapbuf *My_mmap(char *filename){
|
||||
sl_mmapbuf_t *sl_mmap(char *filename){
|
||||
int fd;
|
||||
char *ptr;
|
||||
size_t Mlen;
|
||||
@ -269,17 +271,17 @@ mmapbuf *My_mmap(char *filename){
|
||||
}
|
||||
/// îÅ ÍÏÇÕ ÚÁËÒÙÔØ mmap'ÎÕÔÙÊ ÆÁÊÌ
|
||||
if(close(fd)) WARN(_("Can't close mmap'ed file"));
|
||||
mmapbuf *ret = MALLOC(mmapbuf, 1);
|
||||
sl_mmapbuf_t *ret = MALLOC(sl_mmapbuf_t, 1);
|
||||
ret->data = ptr;
|
||||
ret->len = Mlen;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief My_munmap - unmap memory file
|
||||
* @brief sl_munmap - unmap memory file
|
||||
* @param b (i) - mmap'ed buffer
|
||||
*/
|
||||
void My_munmap(mmapbuf *b){
|
||||
void sl_munmap(sl_mmapbuf_t *b){
|
||||
if(munmap(b->data, b->len)){
|
||||
/// îÅ ÍÏÇÕ munmap
|
||||
ERR(_("Can't munmap"));
|
||||
@ -287,44 +289,86 @@ void My_munmap(mmapbuf *b){
|
||||
FREE(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_omitspaces - omit leading spaces
|
||||
* @param v - source string
|
||||
* @return pointer to first non-blank character (could be '\0' if end of string reached)
|
||||
*/
|
||||
char *sl_omitspaces(const char *v){
|
||||
if(!v) return NULL;
|
||||
char *p = (char*)v;
|
||||
while(*p && isspace(*p)) ++p;
|
||||
return p;
|
||||
}
|
||||
|
||||
// the same as sl_omitspaces, but return (last non-space char + 1) in string or its first char
|
||||
char *sl_omitspacesr(const char *v){
|
||||
if(!v) return NULL;
|
||||
char *eol = (char*)v + strlen(v) - 1;
|
||||
while(eol > v && isspace(*eol)) --eol;
|
||||
if(eol == v && isspace(*eol)) return eol;
|
||||
return eol + 1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
* Terminal in no-echo mode
|
||||
* BE CAREFULL! These functions aren't thread-safe!
|
||||
\******************************************************************************/
|
||||
static struct termios oldt, newt; // console flags
|
||||
// console flags
|
||||
#ifndef SL_USE_OLD_TTY
|
||||
static struct termios2 oldt, newt;
|
||||
#else
|
||||
static struct termios oldt, newt;
|
||||
#endif
|
||||
static int console_changed = 0;
|
||||
/**
|
||||
* @brief restore_console - restore console to default mode
|
||||
* @brief sl_restore_con - restore console to default mode
|
||||
*/
|
||||
void restore_console(){
|
||||
void sl_restore_con(){
|
||||
if(console_changed)
|
||||
#ifndef SL_USE_OLD_TTY
|
||||
ioctl(STDIN_FILENO, TCSETS2, &oldt);
|
||||
#else
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state
|
||||
#endif
|
||||
console_changed = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setup_con - setup console to non-canonical noecho mode
|
||||
* @brief sl_setup_con - setup console to non-canonical noecho mode
|
||||
*/
|
||||
void setup_con(){
|
||||
void sl_setup_con(){
|
||||
if(console_changed) return;
|
||||
#ifndef SL_USE_OLD_TTY
|
||||
ioctl(STDIN_FILENO, TCGETS2, &oldt);
|
||||
#else
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
#endif
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ICANON | ECHO);
|
||||
#ifndef SL_USE_OLD_TTY
|
||||
if(ioctl(STDIN_FILENO, TCSETS2, &newt)){
|
||||
#else
|
||||
if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){
|
||||
#endif
|
||||
/// îÅ ÍÏÇÕ ÎÁÓÔÒÏÉÔØ ËÏÎÓÏÌØ
|
||||
WARN(_("Can't setup console"));
|
||||
#ifndef SL_USE_OLD_TTY
|
||||
ioctl(STDIN_FILENO, TCSETS2, &oldt);
|
||||
#else
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
#endif
|
||||
signals(1); //quit?
|
||||
}
|
||||
console_changed = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief read_console - read character from console without echo
|
||||
* @brief sl_read_con - read character from console without echo
|
||||
* @return char read or zero
|
||||
*/
|
||||
int read_console(){
|
||||
int sl_read_con(){
|
||||
int rb;
|
||||
struct timeval tv;
|
||||
int retval;
|
||||
@ -346,102 +390,58 @@ int read_console(){
|
||||
* wait until at least one character pressed
|
||||
* @return character read
|
||||
*/
|
||||
int mygetchar(){
|
||||
int sl_getchar(){
|
||||
int ret;
|
||||
do ret = read_console();
|
||||
do ret = sl_read_con();
|
||||
while(ret == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief str2double - safely convert data from string to double
|
||||
* @brief sl_str2d - safely convert data from string to double
|
||||
* @param num (o) - double number read from string
|
||||
* @param str (i) - input string
|
||||
* @return 1 if success, 0 if fails
|
||||
*/
|
||||
int str2double(double *num, const char *str){
|
||||
int sl_str2d(double *num, const char *str){
|
||||
double res;
|
||||
char *endptr;
|
||||
if(!str) return 0;
|
||||
if(!str) return FALSE;
|
||||
res = strtod(str, &endptr);
|
||||
if(endptr == str || *str == '\0' || *endptr != '\0'){
|
||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÞÉÓÌÁ double!"
|
||||
WARNX("Wrong double number format!");
|
||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÞÉÓÌÁ double '%s'"
|
||||
WARNX(_("Wrong double number format '%s'"), str);
|
||||
return FALSE;
|
||||
}
|
||||
if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
* Logging to file
|
||||
* DEPRECATED!!! DEPRECATED!!! DEPRECATED!!! DEPRECATED!!! DEPRECATED!!! DEPRECATED!!!
|
||||
\******************************************************************************/
|
||||
FILE *Flog = NULL; // log file descriptor
|
||||
char *logname = NULL;
|
||||
time_t log_open_time = 0;
|
||||
/**
|
||||
* @brief openlogfile - try to open log file
|
||||
* @param name (i) - log file name
|
||||
* if failed show warning message
|
||||
*/
|
||||
void openlogfile(char *name){
|
||||
if(!name){
|
||||
/// îÅ ÚÁÄÁÎÏ ÉÍÑ ÌÏÇÆÁÊÌÁ
|
||||
WARNX(_("Need filename for log file"));
|
||||
return;
|
||||
// and so on
|
||||
int sl_str2ll(long long *num, const char *str){
|
||||
long long res;
|
||||
char *endptr;
|
||||
if(!str) return FALSE;
|
||||
res = strtoll(str, &endptr, 0);
|
||||
if(endptr == str || *str == '\0' || *endptr != '\0'){
|
||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÞÉÓÌÁ double!"
|
||||
WARNX(_("Wrong number format!"));
|
||||
return FALSE;
|
||||
}
|
||||
/// ðÒÏÂÕÀ ÏÔËÒÙÔØ ÌÏÇÆÁÊÌ %s × ÒÅÖÉÍÅ ÄÏÐÏÌÎÅÎÉÑ\n
|
||||
green(_("Try to open log file %s in append mode\n"), name);
|
||||
fflush(stdout);
|
||||
if(!(Flog = fopen(name, "a"))){
|
||||
/// îÅ ÍÏÇÕ ÏÔËÒÙÔØ ÌÏÇÆÁÊÌ
|
||||
WARN(_("Can't open log file"));
|
||||
return;
|
||||
}
|
||||
log_open_time = time(NULL);
|
||||
logname = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save message to log file, rotate logs every 24 hours
|
||||
*/
|
||||
int putlog(const char *fmt, ...){
|
||||
if(!Flog) return 0;
|
||||
time_t t_now = time(NULL);
|
||||
if(t_now - log_open_time > 86400){ // rotate log
|
||||
fprintf(Flog, "\n\t\t%sRotate log\n", ctime(&t_now));
|
||||
fclose(Flog);
|
||||
char newname[PATH_MAX];
|
||||
snprintf(newname, PATH_MAX, "%s.old", logname);
|
||||
if(rename(logname, newname)) WARN("rename()");
|
||||
openlogfile(logname);
|
||||
if(!Flog) return 0;
|
||||
}
|
||||
//int i = fprintf(Flog, "%s\t\t", ctime(&t_now));
|
||||
char buf[256];
|
||||
strftime(buf, 255, "%Y/%m/%d %H:%M:%S", localtime(&t_now));
|
||||
int i = fprintf(Flog, "%s\t\t", buf);
|
||||
va_list ar;
|
||||
va_start(ar, fmt);
|
||||
i = vfprintf(Flog, fmt, ar);
|
||||
va_end(ar);
|
||||
fprintf(Flog, "\n");
|
||||
fflush(Flog);
|
||||
return i;
|
||||
if(num) *num = res;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************\
|
||||
* Logging to file
|
||||
\******************************************************************************/
|
||||
sl_log *globlog = NULL; // "global" log file (the first opened logfile)
|
||||
sl_log_t *sl_globlog = NULL; // "global" log file (the first opened logfile)
|
||||
/**
|
||||
* @brief sl_createlog - create log file, test file open ability
|
||||
* @param logpath - path to log file
|
||||
* @param level - lowest message level (e.g. LOGLEVEL_ERR won't allow to write warn/msg/dbg)
|
||||
* @return allocated structure (should be free'd later by Cl_deletelog) or NULL
|
||||
*/
|
||||
sl_log *sl_createlog(const char *logpath, sl_loglevel level, int prefix){
|
||||
sl_log_t *sl_createlog(const char *logpath, sl_loglevel_e level, int prefix){
|
||||
if(level < LOGLEVEL_NONE || level > LOGLEVEL_ANY) return NULL;
|
||||
if(!logpath) return NULL;
|
||||
FILE *logfd = fopen(logpath, "a");
|
||||
@ -450,7 +450,7 @@ sl_log *sl_createlog(const char *logpath, sl_loglevel level, int prefix){
|
||||
return NULL;
|
||||
}
|
||||
fclose(logfd);
|
||||
sl_log *log = MALLOC(sl_log, 1);
|
||||
sl_log_t *log = MALLOC(sl_log_t, 1);
|
||||
log->logpath = strdup(logpath);
|
||||
if(!log->logpath){
|
||||
WARN("strdup()");
|
||||
@ -462,7 +462,7 @@ sl_log *sl_createlog(const char *logpath, sl_loglevel level, int prefix){
|
||||
return log;
|
||||
}
|
||||
|
||||
void sl_deletelog(sl_log **log){
|
||||
void sl_deletelog(sl_log_t **log){
|
||||
if(!log || !*log) return;
|
||||
FREE((*log)->logpath);
|
||||
FREE(*log);
|
||||
@ -476,7 +476,7 @@ void sl_deletelog(sl_log **log){
|
||||
* @param fmt - format and the rest part of message
|
||||
* @return amount of symbols saved in file
|
||||
*/
|
||||
int sl_putlogt(int timest, sl_log *log, sl_loglevel lvl, const char *fmt, ...){
|
||||
int sl_putlogt(int timest, sl_log_t *log, sl_loglevel_e lvl, const char *fmt, ...){
|
||||
if(!log || !log->logpath) return 0;
|
||||
if(lvl > log->loglevel) return 0;
|
||||
int i = 0;
|
||||
@ -484,9 +484,9 @@ int sl_putlogt(int timest, sl_log *log, sl_loglevel lvl, const char *fmt, ...){
|
||||
if(!logfd) return 0;
|
||||
int lfd = fileno(logfd);
|
||||
// try to lock file
|
||||
double t0 = dtime();
|
||||
double t0 = sl_dtime();
|
||||
int locked = 0;
|
||||
while(dtime() - t0 < 0.1){ // timeout for 0.1s
|
||||
while(sl_dtime() - t0 < 0.1){ // timeout for 0.1s
|
||||
if(-1 == flock(lfd, LOCK_EX | LOCK_NB)) continue;
|
||||
locked = 1;
|
||||
break;
|
||||
|
||||
198
usefull_macros.h
198
usefull_macros.h
@ -20,14 +20,17 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __USEFULL_MACROS_H__
|
||||
#define __USEFULL_MACROS_H__
|
||||
|
||||
#include <stdbool.h> // bool
|
||||
#include <unistd.h> // pid_t
|
||||
#include <errno.h> // errno
|
||||
#ifdef SL_USE_OLD_TTY
|
||||
#include <termios.h> // termios
|
||||
#else
|
||||
#include <asm-generic/termbits.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h> // errno
|
||||
#include <stdlib.h> // alloc, free
|
||||
#include <sys/types.h> // pid_t
|
||||
#include <unistd.h> // pid_t
|
||||
// just for different purposes
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
@ -103,8 +106,8 @@ void WEAK signals(int sig);
|
||||
/*
|
||||
* Memory allocation
|
||||
*/
|
||||
#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
|
||||
#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type)))
|
||||
#define ALLOC(type, var, size) type * var = ((type *)sl_alloc(size, sizeof(type)))
|
||||
#define MALLOC(type, size) ((type *)sl_alloc(size, sizeof(type)))
|
||||
#define FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0)
|
||||
|
||||
#ifndef DBL_EPSILON
|
||||
@ -115,38 +118,48 @@ void WEAK signals(int sig);
|
||||
const char *sl_libversion();
|
||||
|
||||
// double value of UNIX time
|
||||
double dtime();
|
||||
double sl_dtime();
|
||||
|
||||
// functions for color output in tty & no-color in pipes
|
||||
extern int (*red)(const char *fmt, ...);
|
||||
extern int (*_WARN)(const char *fmt, ...);
|
||||
extern int (*green)(const char *fmt, ...);
|
||||
// safe allocation
|
||||
void * my_alloc(size_t N, size_t S);
|
||||
void *sl_alloc(size_t N, size_t S);
|
||||
// setup locales & other
|
||||
void initial_setup();
|
||||
void sl_init();
|
||||
|
||||
// mmap file
|
||||
typedef struct{
|
||||
char *data;
|
||||
size_t len;
|
||||
} mmapbuf;
|
||||
mmapbuf *My_mmap(char *filename);
|
||||
void My_munmap(mmapbuf *b);
|
||||
} sl_mmapbuf_t;
|
||||
sl_mmapbuf_t *sl_mmap(char *filename);
|
||||
void sl_munmap(sl_mmapbuf_t *b);
|
||||
|
||||
// console in non-echo mode
|
||||
void restore_console();
|
||||
void setup_con();
|
||||
int read_console();
|
||||
int mygetchar();
|
||||
void sl_restore_con();
|
||||
void sl_setup_con();
|
||||
int sl_read_con();
|
||||
int sl_getchar();
|
||||
|
||||
long throw_random_seed();
|
||||
long sl_random_seed();
|
||||
|
||||
uint64_t get_available_mem();
|
||||
uint64_t sl_mem_avail();
|
||||
|
||||
// omit leading spaces
|
||||
char *sl_omitspaces(const char *str);
|
||||
// omit trailing spaces
|
||||
char *sl_omitspacesr(const char *v);
|
||||
|
||||
// convert string to double with checking
|
||||
int sl_str2d(double *num, const char *str);
|
||||
int sl_str2ll(long long *num, const char *str);
|
||||
|
||||
/******************************************************************************\
|
||||
The original term.h
|
||||
\******************************************************************************/
|
||||
#ifdef SL_USE_OLD_TTY
|
||||
typedef struct {
|
||||
char *portname; // device filename (should be freed before structure freeing)
|
||||
int speed; // baudrate in human-readable format
|
||||
@ -157,23 +170,31 @@ typedef struct {
|
||||
char *buf; // buffer for data read
|
||||
size_t bufsz; // size of buf
|
||||
size_t buflen; // length of data read into buf
|
||||
bool exclusive; // should device be exclusive opened
|
||||
} TTY_descr;
|
||||
int exclusive; // should device be exclusive opened
|
||||
} sl_tty_t;
|
||||
|
||||
void close_tty(TTY_descr **descr);
|
||||
TTY_descr *new_tty(char *comdev, int speed, size_t bufsz);
|
||||
TTY_descr *tty_open(TTY_descr *d, int exclusive);
|
||||
int read_tty(TTY_descr *descr);
|
||||
int tty_timeout(double usec);
|
||||
int write_tty(int comfd, const char *buff, size_t length);
|
||||
tcflag_t conv_spd(int speed);
|
||||
tcflag_t sl_tty_convspd(int speed);
|
||||
#else
|
||||
typedef struct {
|
||||
char *portname; // device filename (should be freed before structure freeing)
|
||||
int speed; // baudrate in human-readable format
|
||||
char *format; // format like 8N1
|
||||
struct termios2 oldtty; // TTY flags for previous port settings
|
||||
struct termios2 tty; // TTY flags for current settings
|
||||
int comfd; // TTY file descriptor
|
||||
char *buf; // buffer for data read
|
||||
size_t bufsz; // size of buf
|
||||
size_t buflen; // length of data read into buf
|
||||
int exclusive; // should device be exclusive opened
|
||||
} sl_tty_t;
|
||||
#endif
|
||||
|
||||
// convert string to double with checking
|
||||
int str2double(double *num, const char *str);
|
||||
|
||||
// logging (deprecated)
|
||||
void __attribute__ ((deprecated)) openlogfile(char *name);
|
||||
int __attribute__ ((deprecated)) putlog(const char *fmt, ...);
|
||||
void sl_tty_close(sl_tty_t **descr);
|
||||
sl_tty_t *sl_tty_new(char *comdev, int speed, size_t bufsz);
|
||||
sl_tty_t *sl_tty_open(sl_tty_t *d, int exclusive);
|
||||
int sl_tty_read(sl_tty_t *descr);
|
||||
int sl_tty_tmout(double usec);
|
||||
int sl_tty_write(int comfd, const char *buff, size_t length);
|
||||
|
||||
/******************************************************************************\
|
||||
Logging
|
||||
@ -184,31 +205,32 @@ typedef enum{
|
||||
LOGLEVEL_WARN, // only warnings and errors
|
||||
LOGLEVEL_MSG, // all without debug
|
||||
LOGLEVEL_DBG, // all messages
|
||||
LOGLEVEL_ANY // all shit
|
||||
} sl_loglevel;
|
||||
LOGLEVEL_ANY, // all shit
|
||||
LOGLEVEL_AMOUNT // total amount
|
||||
} sl_loglevel_e;
|
||||
|
||||
typedef struct{
|
||||
char *logpath; // full path to logfile
|
||||
sl_loglevel loglevel; // loglevel
|
||||
sl_loglevel_e loglevel; // loglevel
|
||||
int addprefix; // if !=0 add record type to each line(e.g. [ERR])
|
||||
} sl_log;
|
||||
} sl_log_t;
|
||||
|
||||
extern sl_log *globlog; // "global" log file
|
||||
extern sl_log_t *sl_globlog; // "global" log file
|
||||
|
||||
sl_log *sl_createlog(const char *logpath, sl_loglevel level, int prefix);
|
||||
void sl_deletelog(sl_log **log);
|
||||
int sl_putlogt(int timest, sl_log *log, sl_loglevel lvl, const char *fmt, ...);
|
||||
sl_log_t *sl_createlog(const char *logpath, sl_loglevel_e level, int prefix);
|
||||
void sl_deletelog(sl_log_t **log);
|
||||
int sl_putlogt(int timest, sl_log_t *log, sl_loglevel_e lvl, const char *fmt, ...);
|
||||
// open "global" log
|
||||
#define OPENLOG(nm, lvl, prefix) (globlog = sl_createlog(nm, lvl, prefix))
|
||||
#define OPENLOG(nm, lvl, prefix) (sl_globlog = sl_createlog(nm, lvl, prefix))
|
||||
// shortcuts for different log levels; ..ADD - add message without timestamp
|
||||
#define LOGERR(...) do{sl_putlogt(1, globlog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
|
||||
#define LOGERRADD(...) do{sl_putlogt(0, globlog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
|
||||
#define LOGWARN(...) do{sl_putlogt(1, globlog, LOGLEVEL_WARN, __VA_ARGS__);}while(0)
|
||||
#define LOGWARNADD(...) do{sl_putlogt(0, globlog, LOGLEVEL_WARN, __VA_ARGS__);}while(0)
|
||||
#define LOGMSG(...) do{sl_putlogt(1, globlog, LOGLEVEL_MSG, __VA_ARGS__);}while(0)
|
||||
#define LOGMSGADD(...) do{sl_putlogt(0, globlog, LOGLEVEL_MSG, __VA_ARGS__);}while(0)
|
||||
#define LOGDBG(...) do{sl_putlogt(1, globlog, LOGLEVEL_DBG, __VA_ARGS__);}while(0)
|
||||
#define LOGDBGADD(...) do{sl_putlogt(0, globlog, LOGLEVEL_DBG, __VA_ARGS__);}while(0)
|
||||
#define LOGERR(...) do{sl_putlogt(1, sl_globlog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
|
||||
#define LOGERRADD(...) do{sl_putlogt(0, sl_globlog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
|
||||
#define LOGWARN(...) do{sl_putlogt(1, sl_globlog, LOGLEVEL_WARN, __VA_ARGS__);}while(0)
|
||||
#define LOGWARNADD(...) do{sl_putlogt(0, sl_globlog, LOGLEVEL_WARN, __VA_ARGS__);}while(0)
|
||||
#define LOGMSG(...) do{sl_putlogt(1, sl_globlog, LOGLEVEL_MSG, __VA_ARGS__);}while(0)
|
||||
#define LOGMSGADD(...) do{sl_putlogt(0, sl_globlog, LOGLEVEL_MSG, __VA_ARGS__);}while(0)
|
||||
#define LOGDBG(...) do{sl_putlogt(1, sl_globlog, LOGLEVEL_DBG, __VA_ARGS__);}while(0)
|
||||
#define LOGDBGADD(...) do{sl_putlogt(0, sl_globlog, LOGLEVEL_DBG, __VA_ARGS__);}while(0)
|
||||
|
||||
/******************************************************************************\
|
||||
The original parseargs.h
|
||||
@ -217,7 +239,7 @@ int sl_putlogt(int timest, sl_log *log, sl_loglevel lvl, const char *fmt, ...);
|
||||
#define APTR(x) ((void*)x)
|
||||
|
||||
// if argptr is a function:
|
||||
typedef bool(*argfn)(void *arg);
|
||||
typedef int(*sl_argfn_t)(void *arg);
|
||||
|
||||
/**
|
||||
* type of getopt's argument
|
||||
@ -238,8 +260,8 @@ typedef enum {
|
||||
arg_double, // double
|
||||
arg_float, // float
|
||||
arg_string, // char *
|
||||
arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)`
|
||||
} argtype;
|
||||
arg_function // parse_args will run function `int (*fn)(char *optarg, int N)`
|
||||
} sl_argtype_e;
|
||||
|
||||
/**
|
||||
* Structure for getopt_long & help
|
||||
@ -265,30 +287,30 @@ typedef enum{
|
||||
NEED_ARG = 1,
|
||||
OPT_ARG = 2,
|
||||
MULT_PAR
|
||||
} hasarg;
|
||||
} sl_hasarg_e;
|
||||
|
||||
typedef struct{
|
||||
// these are from struct option:
|
||||
const char *name; // long option's name
|
||||
hasarg has_arg; // 0 - no args, 1 - nesessary arg, 2 - optionally arg, 4 - need arg & key can repeat (args are stored in null-terminated array)
|
||||
sl_hasarg_e has_arg; // 0 - no args, 1 - nesessary arg, 2 - optionally arg, 3 - need arg & key can repeat (args are stored in null-terminated array)
|
||||
int *flag; // NULL to return val, pointer to int - to set its value of val (function returns 0)
|
||||
int val; // short opt name (if flag == NULL) or flag's value
|
||||
// and these are mine:
|
||||
argtype type; // type of argument
|
||||
void *argptr; // pointer to variable to assign optarg value or function `bool (*fn)(char *optarg, int N)`
|
||||
sl_argtype_e type; // type of argument
|
||||
void *argptr; // pointer to variable to assign optarg value or function `int (*fn)(char *optarg, int N)`
|
||||
const char *help; // help string which would be shown in function `showhelp` or NULL
|
||||
} myoption;
|
||||
} sl_option_t;
|
||||
|
||||
/*
|
||||
* Suboptions structure, almost the same like myoption
|
||||
* Suboptions structure, almost the same like sl_option_t
|
||||
* used in parse_subopts()
|
||||
*/
|
||||
typedef struct{
|
||||
const char *name;
|
||||
hasarg has_arg;
|
||||
argtype type;
|
||||
sl_hasarg_e has_arg;
|
||||
sl_argtype_e type;
|
||||
void *argptr;
|
||||
} mysuboption;
|
||||
} sl_suboption_t;
|
||||
|
||||
// last string of array (all zeros)
|
||||
#define end_option {0,0,0,0,0,0,0}
|
||||
@ -296,14 +318,14 @@ typedef struct{
|
||||
|
||||
extern const char *__progname;
|
||||
|
||||
void showhelp(int oindex, myoption *options);
|
||||
void parseargs(int *argc, char ***argv, myoption *options);
|
||||
void sl_showhelp(int oindex, sl_option_t *options);
|
||||
void sl_parseargs(int *argc, char ***argv, sl_option_t *options);
|
||||
/**
|
||||
* @brief change_helpstring - change standard help header
|
||||
* @brief sl_helpstring - change standard help header
|
||||
* @param str (i) - new format (MAY consist ONE "%s" for progname)
|
||||
*/
|
||||
void change_helpstring(char *s);
|
||||
bool get_suboption(char *str, mysuboption *opt);
|
||||
void sl_helpstring(char *s);
|
||||
int sl_get_suboption(char *str, sl_suboption_t *opt);
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
@ -314,24 +336,44 @@ bool get_suboption(char *str, mysuboption *opt);
|
||||
#endif
|
||||
|
||||
// default function to run if another process found
|
||||
void WEAK iffound_default(pid_t pid);
|
||||
void WEAK sl_iffound_deflt(pid_t pid);
|
||||
// check that our process is exclusive
|
||||
void check4running(char *selfname, char *pidfilename);
|
||||
void sl_check4running(char *selfname, char *pidfilename);
|
||||
// read name of process by its PID
|
||||
char *readPSname(pid_t pid);
|
||||
char *sl_getPSname(pid_t pid);
|
||||
|
||||
/******************************************************************************\
|
||||
The original fifo_lifo.h
|
||||
\******************************************************************************/
|
||||
typedef struct buff_node{
|
||||
typedef struct sl_buff_node{
|
||||
void *data;
|
||||
struct buff_node *next, *last;
|
||||
} List;
|
||||
struct sl_buff_node *next, *last;
|
||||
} sl_list_t;
|
||||
|
||||
List *list_push_tail(List **lst, void *v);
|
||||
List *list_push(List **lst, void *v);
|
||||
void *list_pop(List **lst);
|
||||
sl_list_t *sl_list_push_tail(sl_list_t **lst, void *v);
|
||||
sl_list_t *sl_list_push(sl_list_t **lst, void *v);
|
||||
void *sl_list_pop(sl_list_t **lst);
|
||||
|
||||
/******************************************************************************\
|
||||
The original config.h
|
||||
\******************************************************************************/
|
||||
|
||||
// max length of key (including '\0')
|
||||
#define SL_KEY_LEN (32)
|
||||
// max length of value (including '\0')
|
||||
#define SL_VAL_LEN (128)
|
||||
|
||||
#endif // __USEFULL_MACROS_H__
|
||||
// starting symbol of any comment
|
||||
#define SL_COMMENT_CHAR '#'
|
||||
|
||||
// option or simple configuration value (don't work for functions)
|
||||
typedef struct{
|
||||
union{
|
||||
int ival; long long llval; double dval; float fval;
|
||||
};
|
||||
sl_argtype_e type;
|
||||
} sl_optval;
|
||||
|
||||
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user