diff --git a/.gitignore b/.gitignore index e83a4ee..0be9ac5 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ # Shared objects *.so *.so.* + +# qt-creator +Snippets.* diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bac400..f5f859e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 3.9) set(PROJ usefull_macros) set(MINOR_VERSION "1") -set(MID_VERSION "0") +set(MID_VERSION "1") set(MAJOR_VERSION "0") -set(PROJ_VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}") +set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}") -project(${PROJ} VERSION ${PROJ_VERSION} LANGUAGES C) +project(${PROJ} VERSION ${VERSION} LANGUAGES C) # default flags set(CMAKE_C_FLAGS "${CFLAGS} -O2") @@ -95,7 +95,7 @@ include_directories(${${PROJ}_INCLUDE_DIRS}) link_directories(${${PROJ}_LIBRARY_DIRS}) # -D add_definitions(-DLOCALEDIR=\"${LOCALEDIR}\" - -DPACKAGE_VERSION=\"${PROJ_VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\" + -DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\" -DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\" -DMAJOR_VERSION=\"${MAJOR_VESION}\") @@ -105,7 +105,7 @@ target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES}) set(PCFILE "${CMAKE_BINARY_DIR}/${PROJ}.pc") configure_file("${PROJ}.pc.in" ${PCFILE} @ONLY) -set_target_properties(${PROJ} PROPERTIES VERSION ${PROJ_VERSION}) +set_target_properties(${PROJ} PROPERTIES VERSION ${VERSION}) set_target_properties(${PROJ} PROPERTIES PUBLIC_HEADER ${LIBHEADER}) # Installation of the program diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..8b3dfa6 --- /dev/null +++ b/Changelog @@ -0,0 +1,7 @@ +Wed Dec 23 17:22:39 MSK 2020 + +VERSION 0.1.1: +add tty_timeout() +fix read_tty() for disconnect +add logging +add sl_libversion() diff --git a/Snippets.config b/Snippets.config deleted file mode 100644 index e3e2368..0000000 --- a/Snippets.config +++ /dev/null @@ -1,3 +0,0 @@ -// Add predefined macros for your project here. For example: -// #define THE_ANSWER 42 -#define EBUG 1 diff --git a/Snippets.creator b/Snippets.creator deleted file mode 100644 index e94cbbd..0000000 --- a/Snippets.creator +++ /dev/null @@ -1 +0,0 @@ -[General] diff --git a/Snippets.creator.user b/Snippets.creator.user deleted file mode 100644 index d9b768e..0000000 --- a/Snippets.creator.user +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - EnvironmentId - {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - KOI8-R - false - 4 - false - 80 - true - true - 1 - true - false - 1 - true - true - 0 - 8 - true - 2 - true - false - true - false - - - - ProjectExplorer.Project.PluginSettings - - - true - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - {91347f2c-5221-46a7-80b1-0a054ca02f79} - 0 - 0 - 0 - - /home/eddy/Docs/SAO/C_diff/snippets_library - - - - all - - false - - - false - true - Сборка - - GenericProjectManager.GenericMakeStep - - 1 - Сборка - - ProjectExplorer.BuildSteps.Build - - - - - clean - - false - - - false - true - Сборка - - GenericProjectManager.GenericMakeStep - - 1 - Очистка - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - По умолчанию - По умолчанию - GenericProjectManager.GenericBuildConfiguration - - 1 - - - 0 - Установка - - ProjectExplorer.BuildSteps.Deploy - - 1 - Конфигурация установки - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - false - false - 1000 - - true - 2 - - - Особая программа - - ProjectExplorer.CustomExecutableRunConfiguration - - 3768 - false - true - false - false - true - - - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 20 - - - Version - 20 - - diff --git a/Snippets.files b/Snippets.files deleted file mode 100644 index 1595196..0000000 --- a/Snippets.files +++ /dev/null @@ -1,14 +0,0 @@ -CMakeLists.txt -daemon.c -examples/CMakeLists.txt -examples/cmdlnopts.c -examples/cmdlnopts.h -examples/fifo.c -examples/helloworld.c -examples/options.c -fifo_lifo.c -parseargs.c -term.c -term.h -usefull_macros.c -usefull_macros.h diff --git a/Snippets.includes b/Snippets.includes deleted file mode 100644 index 63f6562..0000000 --- a/Snippets.includes +++ /dev/null @@ -1,2 +0,0 @@ -. -examples diff --git a/TODO b/TODO new file mode 100644 index 0000000..f11464f --- /dev/null +++ b/TODO @@ -0,0 +1 @@ +Add prefixes sl_ to every function for solving further problems diff --git a/daemon.c b/daemon.c index 57b5139..c287ada 100644 --- a/daemon.c +++ b/daemon.c @@ -92,13 +92,13 @@ void check4running(char *selfname, char *pidfilename){ if(selfname){ // block self fself = fopen(selfname, "r"); // open self binary to lock if(!fself){ - WARN("fopen"); + WARN("fopen()"); goto selfpid; } memset(&fl, 0, sizeof(struct flock)); fl.l_type = F_WRLCK; if(fcntl(fileno(fself), F_GETLK, &fl) == -1){ // check locking - WARN("fcntl"); + WARN("fcntl()"); goto selfpid; } if(fl.l_type != F_UNLCK){ // file is locking - exit @@ -106,7 +106,7 @@ void check4running(char *selfname, char *pidfilename){ } fl.l_type = F_RDLCK; if(fcntl(fileno(fself), F_SETLKW, &fl) == -1){ - WARN("fcntl"); + WARN("fcntl()"); } } selfpid: @@ -115,7 +115,7 @@ void check4running(char *selfname, char *pidfilename){ ERR(PROC_BASE); } if(!(name = readPSname(self))){ // error reading self name - ERR("Can't read self name"); + ERR(_("Can't read self name")); } myname = strdup(name); if(pidfilename && stat(pidfilename, &s_buf) == 0){ // pidfile exists diff --git a/examples/cmdlnopts.c b/examples/cmdlnopts.c index e4db8cc..af414dc 100644 --- a/examples/cmdlnopts.c +++ b/examples/cmdlnopts.c @@ -51,6 +51,7 @@ static glob_pars const Gdefault = { static myoption cmdlnopts[] = { // common options {"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")}, {"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")}, diff --git a/examples/options.c b/examples/options.c index 35cf8c5..4ccc1d6 100644 --- a/examples/options.c +++ b/examples/options.c @@ -59,11 +59,11 @@ void signals(int sig){ signal(sig, SIG_IGN); DBG("Get signal %d, quit.\n", sig); } - putlog("Exit with status %d", sig); - if(GP->pidfile) // remove unnesessary PID file + LOGERR("Exit with status %d", sig); + if(GP && GP->pidfile) // remove unnesessary PID file unlink(GP->pidfile); restore_console(); - close_tty(&dev); + if(dev) close_tty(&dev); exit(sig); } @@ -81,38 +81,42 @@ int main(int argc, char *argv[]){ 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(); signal(SIGTERM, signals); // kill (-15) - quit signal(SIGHUP, SIG_IGN); // hup - ignore signal(SIGINT, signals); // ctrl+C - quit signal(SIGQUIT, signals); // ctrl+\ - quit signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z - if(GP->logfile) openlogfile(GP->logfile); - setup_con(); - putlog(("Start application...")); + if(GP->logfile) OPENLOG(GP->logfile, LOGLEVEL_ANY, 1); + LOGMSG("Start application..."); if(GP->rest_pars_num){ for(int i = 0; i < GP->rest_pars_num; ++i) printf("Extra argument: %s\n", GP->rest_pars[i]); } if(GP->device){ - putlog("Try to open serial %s", GP->device); - dev = new_tty(GP->device, GP->speed, 256); + LOGDBG("Try to open serial %s", GP->device); + dev = new_tty(GP->device, GP->speed, 4096); if(dev) dev = tty_open(dev, GP->exclusive); if(!dev){ - putlog("Can't open %s with speed %d. Exit.", GP->device, GP->speed); + LOGERR("Can't open %s with speed %d. Exit.", GP->device, GP->speed); signals(0); } } // main stuff goes here long seed = throw_random_seed(); - green("Now I will sleep for 10 seconds. Do whatever you want. Random seed: %ld\n", 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(); char b[2] = {0}; while(dtime() - t0 < 10.){ // read data from port and print in into terminal if(dev){ if(read_tty(dev)){ printf("Got %zd bytes from port: %s\n", dev->buflen, dev->buf); + LOGMSG("Got from serial: %s", dev->buf); t0 = dtime(); } int r = read_console(); @@ -120,10 +124,12 @@ int main(int argc, char *argv[]){ t0 = 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); } } // clean everything signals(0); + // never reached return 0; } diff --git a/locale/ru/LC_MESSAGES/usefull_macros.mo b/locale/ru/LC_MESSAGES/usefull_macros.mo index 2ad2e5d..9d9c048 100644 Binary files a/locale/ru/LC_MESSAGES/usefull_macros.mo and b/locale/ru/LC_MESSAGES/usefull_macros.mo differ diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 7e0efd7..6d0a30d 100644 --- a/locale/ru/messages.po +++ b/locale/ru/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-12-09 01:49+0300\n" +"POT-Creation-Date: 2020-12-24 12:22+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,138 +18,162 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #. / \n (pid=%d), .\n -#: /Big/Data/C_sources/snippets_library/daemon.c:70 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:70 #, c-format msgid "" "\n" "Found running process (pid=%d), exit.\n" msgstr "" +#. error reading self name +#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:118 +msgid "Can't read self name" +msgstr "" + #. / PID -#: /Big/Data/C_sources/snippets_library/daemon.c:143 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:143 msgid "Can't open PID file" msgstr "" #. amount of pcount and/or scount wrong #. / -#: /Big/Data/C_sources/snippets_library/parseargs.c:54 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:54 msgid "Wrong helpstring!" msgstr "" #. / -#: /Big/Data/C_sources/snippets_library/parseargs.c:84 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:84 msgid "Integer out of range" msgstr "" +#. / " !" +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:151 +msgid "Can't use multiple args with arg_none!" +msgstr "" + +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:252 +#, c-format +msgid "double long arguments: --%s" +msgstr "" + +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:258 +#, c-format +msgid "double short arguments: -%c" +msgstr "" + #. / : %s -#: /Big/Data/C_sources/snippets_library/parseargs.c:478 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:470 #, c-format msgid "Wrong parameter: %s" msgstr "" #. / %s: ! -#: /Big/Data/C_sources/snippets_library/parseargs.c:483 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:475 #, c-format -msgid "%s: argument needed!" +msgid "%s: need argument!" msgstr "" #. / \"%s\" \"%s\" -#: /Big/Data/C_sources/snippets_library/parseargs.c:488 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:480 #, c-format msgid "Wrong argument \"%s\" of parameter \"%s\"" msgstr "" -#: /Big/Data/C_sources/snippets_library/term.c:92 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:92 #, c-format msgid "Wrong speed value: %d!" msgstr "" #. / %s -#: /Big/Data/C_sources/snippets_library/term.c:105 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:105 #, c-format msgid "Can't use port %s" msgstr "" #. Get settings #. / -#: /Big/Data/C_sources/snippets_library/term.c:111 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:110 msgid "Can't get old TTY settings" msgstr "" #. / -#: /Big/Data/C_sources/snippets_library/term.c:123 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:121 msgid "Can't apply new TTY settings" msgstr "" #. / -#: /Big/Data/C_sources/snippets_library/term.c:129 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:128 msgid "Can't do exclusive open" msgstr "" #. / -#: /Big/Data/C_sources/snippets_library/term.c:168 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:164 msgid "Port name is missing" msgstr "" +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:170 +msgid "Need non-zero buffer for TTY device" +msgstr "" + #. / /dev/random -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:184 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:185 msgid "Can't open /dev/random" msgstr "" #. / /dev/random -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:189 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:190 msgid "Can't read /dev/random" msgstr "" #. / ! -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:232 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:241 msgid "No filename given!" msgstr "" #. / %s -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:237 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:246 #, c-format msgid "Can't open %s for reading" msgstr "" #. / stat %s -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:242 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:251 #, c-format msgid "Can't stat %s" msgstr "" #. / mmap -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:249 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:258 msgid "Mmap error for input" msgstr "" #. / mmap' -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:254 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:263 msgid "Can't close mmap'ed file" msgstr "" #. / munmap -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:268 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:277 msgid "Can't munmap" msgstr "" #. / -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:299 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:308 msgid "Can't setup console" msgstr "" #. / -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:374 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:383 msgid "Need filename for log file" msgstr "" #. / %s \n -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:378 +#: /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 "" #. / -#: /Big/Data/C_sources/snippets_library/usefull_macros.c:382 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:391 msgid "Can't open log file" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 13c75b7..872b72d 100644 --- a/locale/ru/ru.po +++ b/locale/ru/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2019-03-12 09:53+0300\n" + "POT-Creation-Date: 2020-12-24 12:22+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -25,34 +25,45 @@ msgstr "\n" " (pid=%d), .\n" #. / %s: ! -#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:483 -#, c-format -msgid "%s: argument needed!" +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:475 +#, fuzzy, c-format +msgid "%s: need argument!" msgstr "%s: !" +#. / +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:121 +msgid "Can't apply new TTY settings" +msgstr " " + #. / mmap' -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:262 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:263 msgid "Can't close mmap'ed file" msgstr " mmap' " #. / -#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:129 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:128 msgid "Can't do exclusive open" msgstr " " +#. Get settings +#. / +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:110 +msgid "Can't get old TTY settings" +msgstr " " + #. / munmap -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:276 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:277 msgid "Can't munmap" msgstr " munmap" #. / %s -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:245 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:246 #, c-format msgid "Can't open %s for reading" msgstr " %s " #. / /dev/random -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:184 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:185 msgid "Can't open /dev/random" msgstr " /dev/random" @@ -62,64 +73,80 @@ msgid "Can't open PID file" msgstr " PID " #. / -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:390 +#: /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:189 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:190 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 +msgid "Can't read self name" +msgstr " " + #. / -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:307 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:308 msgid "Can't setup console" msgstr " " #. / stat %s -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:250 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:251 #, c-format msgid "Can't stat %s" msgstr " stat %s" +#. / " !" +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:151 +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 +msgid "Can't use port %s" +msgstr " %s" + #. / #: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:84 msgid "Integer out of range" msgstr " " #. / mmap -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:257 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:258 msgid "Mmap error for input" msgstr " mmap" #. / -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:382 +#: /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/term.c:176 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:170 msgid "Need non-zero buffer for TTY device" - msgstr " " #. / ! -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:240 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:241 msgid "No filename given!" msgstr " !" #. / -#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:169 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/term.c:164 msgid "Port name is missing" msgstr " " #. / %s \n -#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:386 +#: /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" #. / \"%s\" \"%s\" -#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:488 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:480 #, c-format msgid "Wrong argument \"%s\" of parameter \"%s\"" msgstr " \"%s\" \"%s\"" @@ -131,7 +158,7 @@ msgid "Wrong helpstring!" msgstr " " #. / : %s -#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:478 +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:470 #, c-format msgid "Wrong parameter: %s" msgstr " : %s" @@ -140,3 +167,13 @@ msgstr " #, c-format msgid "Wrong speed value: %d!" msgstr " : %d!" + +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:252 +#, c-format +msgid "double long arguments: --%s" +msgstr " : --%s" + +#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:258 +#, c-format +msgid "double short arguments: -%c" +msgstr " : -%c" diff --git a/parseargs.c b/parseargs.c index 41aba75..00de3ab 100644 --- a/parseargs.c +++ b/parseargs.c @@ -148,7 +148,7 @@ void *get_aptr(void *paptr, argtype type){ default: case arg_none: /// " !" - ERRX("Can't use multiple args with arg_none!"); + ERRX(_("Can't use multiple args with arg_none!")); break; case arg_int: sz = sizeof(int); @@ -206,18 +206,14 @@ void parseargs(int *argc, char ***argv, myoption *options){ short_options = calloc(optsize * 3 + 1, 1); // multiply by three for '::' in case of args in opts long_options = calloc(optsize + 1, sizeof(struct option)); opts = options; loptr = long_options; soptr = short_options; - // in debug mode check the parameters are not repeated -#ifdef EBUG + // check the parameters are not repeated char **longlist = MALLOC(char*, optsize); char *shortlist = MALLOC(char, optsize); -#endif // fill short/long parameters and make a simple checking for(i = 0; i < optsize; i++, loptr++, opts++){ // check assert(opts->name); // check name -#ifdef EBUG longlist[i] = strdup(opts->name); -#endif if(opts->has_arg){ assert(opts->type != arg_none); // check error with arg type assert(opts->argptr); // check pointer @@ -232,9 +228,7 @@ void parseargs(int *argc, char ***argv, myoption *options){ loptr->val = opts->val; // fill short options if they are: if(!opts->flag && opts->val){ -#ifdef EBUG shortlist[i] = (char) opts->val; -#endif *soptr++ = opts->val; if(loptr->has_arg) // add ':' if option has required argument *soptr++ = ':'; @@ -243,7 +237,6 @@ void parseargs(int *argc, char ***argv, myoption *options){ } } // sort all lists & check for repeating -#ifdef EBUG int cmpstringp(const void *p1, const void *p2){ return strcmp(* (char * const *) p1, * (char * const *) p2); } @@ -256,18 +249,17 @@ void parseargs(int *argc, char ***argv, myoption *options){ for(i = 1; i < optsize; ++i){ if(longlist[i]){ if(prevl){ - if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl); + if(strcmp(prevl, longlist[i]) == 0) ERRX(_("double long arguments: --%s"), prevl); } prevl = longlist[i]; } if(shortlist[i]){ if(prevshrt){ - if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt); + if(prevshrt == shortlist[i]) ERRX(_("double short arguments: -%c"), prevshrt); } prevshrt = shortlist[i]; } } -#endif // now we have both long_options & short_options and can parse `getopt_long` while(1){ int opt; @@ -480,7 +472,7 @@ bool get_suboption(char *str, mysuboption *opt){ } if(noarg && opt[idx].has_arg == NEED_ARG){ /// %s: ! - WARNX(_("%s: argument needed!"), tok); + WARNX(_("%s: need argument!"), tok); goto returning; } if(!opt_setarg(opt, idx, val)){ diff --git a/term.c b/term.c index 4a045ba..f403f2c 100644 --- a/term.c +++ b/term.c @@ -99,13 +99,12 @@ tcflag_t conv_spd(int speed){ * @return 0 if all OK or error code */ static int tty_init(TTY_descr *descr){ - DBG("\nOpen port..."); // |O_NONBLOCK + // |O_NONBLOCK ? if ((descr->comfd = open(descr->portname, O_RDWR|O_NOCTTY)) < 0){ /// %s WARN(_("Can't use port %s"), descr->portname); return globErr ? globErr : 1; } - DBG("OK\nGet current settings..."); if(tcgetattr(descr->comfd, &descr->oldtty) < 0){ // Get settings /// WARN(_("Can't get old TTY settings")); @@ -128,7 +127,6 @@ static int tty_init(TTY_descr *descr){ /// WARN(_("Can't do exclusive open")); }} - DBG("OK"); return 0; } @@ -139,14 +137,12 @@ void close_tty(TTY_descr **descr){ if(descr == NULL || *descr == NULL) return; TTY_descr *d = *descr; if(d->comfd){ - DBG("close file.."); ioctl(d->comfd, TCSANOW, &d->oldtty); // return TTY to previous state close(d->comfd); } FREE(d->portname); FREE(d->buf); FREE(*descr); - DBG("done!\n"); } /** @@ -159,7 +155,6 @@ void close_tty(TTY_descr **descr){ TTY_descr *new_tty(char *comdev, int speed, size_t bufsz){ tcflag_t spd = conv_spd(speed); if(!spd) return NULL; - DBG("create %s with speed %d and buffer size %zd", comdev, speed, bufsz); TTY_descr *descr = MALLOC(TTY_descr, 1); descr->portname = strdup(comdev); descr->baudrate = spd; @@ -171,7 +166,6 @@ TTY_descr *new_tty(char *comdev, int speed, size_t bufsz){ if(bufsz){ descr->buf = MALLOC(char, bufsz+1); descr->bufsz = bufsz; - DBG("allocate buffer with size %zd", bufsz); return descr; }else WARNX(_("Need non-zero buffer for TTY device")); } @@ -187,7 +181,6 @@ TTY_descr *new_tty(char *comdev, int speed, size_t bufsz){ * @return pointer to TTY structure if all OK */ TTY_descr *tty_open(TTY_descr *d, int exclusive){ - DBG("open %s with speed %d%s", d->portname, d->speed, exclusive ? "" : " (exclusive)"); if(!d || !d->portname || !d->baudrate) return NULL; if(exclusive) d->exclusive = TRUE; else d->exclusive = FALSE; @@ -195,14 +188,31 @@ TTY_descr *tty_open(TTY_descr *d, int exclusive){ return d; } +static struct timeval tvdefault = {.tv_sec = 0, .tv_usec = 5000}; +/** + * @brief tty_timeout - 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){ + 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 read_tty - read data from TTY with 10ms timeout * @param buff (o) - buffer for data read * @param length - buffer len - * @return amount of bytes read + * @return amount of bytes read or -1 if disconnected */ -size_t read_tty(TTY_descr *d){ - if(d->comfd < 0) return 0; +int read_tty(TTY_descr *d){ + if(!d || d->comfd < 0) return 0; size_t L = 0; ssize_t l; size_t length = d->bufsz; @@ -214,31 +224,23 @@ size_t read_tty(TTY_descr *d){ l = 0; FD_ZERO(&rfds); FD_SET(d->comfd, &rfds); - // wait for 10ms - tv.tv_sec = 0; tv.tv_usec = 50000; + //memcpy(&tv, &tvdefault, sizeof(struct timeval)); + tv = tvdefault; retval = select(d->comfd + 1, &rfds, NULL, NULL, &tv); - if (!retval) break; + if(!retval) break; + if(retval < 0){ + if(errno == EINTR) continue; + return -1; + } if(FD_ISSET(d->comfd, &rfds)){ - if((l = read(d->comfd, ptr, length)) < 1){ - break; - } -#ifdef EBUG - char *s = ptr; -#endif + l = read(d->comfd, ptr, length); + if(l < 1) return -1; // disconnected ptr += l; L += l; -#ifdef EBUG - *ptr = 0; -#endif - //DBG("got %zd bytes: %s\nBUF[%zd](%d): %s", l, s, L, d->bufsz, d->buf); - DBG("FD %d got %zd bytes: %s\nsym: %d, BUF[%zd](%zd): %s", d->comfd, l, s, (int)s[0], L, d->bufsz, d->buf); length -= l; } }while(l && length); d->buflen = L; d->buf[L] = 0; -#ifdef EBUG - if(L) DBG("Got %zd bytes total: %s", d->buflen, d->buf); -#endif return (size_t)L; } @@ -249,7 +251,6 @@ size_t read_tty(TTY_descr *d){ * @return 0 if all OK */ int write_tty(int comfd, const char *buff, size_t length){ - DBG("comfd: %d, buff: \"%s\", len: %zd", comfd, buff, length); ssize_t L = write(comfd, buff, length); if((size_t)L != length){ /// " !" diff --git a/usefull_macros.c b/usefull_macros.c index f764901..7a95404 100644 --- a/usefull_macros.c +++ b/usefull_macros.c @@ -29,6 +29,7 @@ #include #include #include +#include // flock #include #include #include @@ -46,6 +47,14 @@ void __attribute__ ((weak)) signals(int sig){ exit(sig); } +/** + * @brief sl_libversion - version + * @return return string with library version + */ +const char *sl_libversion(){ + return PACKAGE_VERSION; +} + /** * @brief dtime - function for different purposes that need to know time intervals * @return double value: UNIX time in seconds @@ -366,7 +375,7 @@ int str2double(double *num, const char *str){ /******************************************************************************\ * Logging to file - * BE CAREFULL!!! There's only one log file per process! + * DEPRECATED!!! DEPRECATED!!! DEPRECATED!!! DEPRECATED!!! DEPRECATED!!! DEPRECATED!!! \******************************************************************************/ FILE *Flog = NULL; // log file descriptor char *logname = NULL; @@ -422,3 +431,106 @@ int putlog(const char *fmt, ...){ return i; } +/******************************************************************************\ + * Logging to file +\******************************************************************************/ +sl_log *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){ + if(level < LOGLEVEL_NONE || level > LOGLEVEL_ANY) return NULL; + if(!logpath) return NULL; + FILE *logfd = fopen(logpath, "a"); + if(!logfd){ + WARN("Can't open log file"); + return NULL; + } + fclose(logfd); + sl_log *log = MALLOC(sl_log, 1); + log->logpath = strdup(logpath); + if(!log->logpath){ + WARN("strdup()"); + FREE(log); + return NULL; + } + log->loglevel = level; + log->addprefix = prefix; + return log; +} + +void sl_deletelog(sl_log **log){ + if(!log || !*log) return; + FREE((*log)->logpath); + FREE(*log); +} + +/** + * @brief sl_putlog - put message to log file with/without timestamp + * @param timest - ==1 to put timestamp + * @param log - pointer to log structure + * @param lvl - message loglevel (if lvl > loglevel, message won't be printed) + * @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, ...){ + if(!log || !log->logpath) return 0; + if(lvl > log->loglevel) return 0; + int i = 0; + FILE *logfd = fopen(log->logpath, "a+"); + if(!logfd) return 0; + int lfd = fileno(logfd); + // try to lock file + double t0 = dtime(); + int locked = 0; + while(dtime() - t0 < 0.1){ // timeout for 0.1s + if(-1 == flock(lfd, LOCK_EX | LOCK_NB)) continue; + locked = 1; + break; + } + if(!locked) return 0; // can't lock + if(log->addprefix){ + const char *p; + switch(lvl){ + case LOGLEVEL_ERR: + p = "[ERR]"; + break; + case LOGLEVEL_WARN: + p = "[WARN]"; + break; + case LOGLEVEL_MSG: + p = "[MSG]"; + break; + case LOGLEVEL_DBG: + p = "[DBG]"; + break; + default: + p = NULL; + } + if(p) i += fprintf(logfd, "%s\t", p); + } + if(timest){ + char strtm[128]; + time_t t = time(NULL); + struct tm *curtm = localtime(&t); + strftime(strtm, 128, "%Y/%m/%d-%H:%M:%S", curtm); + i = fprintf(logfd, "%s", strtm); + } + i += fprintf(logfd, "\t"); + va_list ar; + va_start(ar, fmt); + i += vfprintf(logfd, fmt, ar); + va_end(ar); + fseek(logfd, -1, SEEK_CUR); + char c; + ssize_t r = fread(&c, 1, 1, logfd); + if(1 == r){ // add '\n' if there was no newline + if(c != '\n') i += fprintf(logfd, "\n"); + } + flock(lfd, LOCK_UN); + fclose(logfd); + return i; +} diff --git a/usefull_macros.h b/usefull_macros.h index c4e3c4d..06ebf4e 100644 --- a/usefull_macros.h +++ b/usefull_macros.h @@ -111,6 +111,9 @@ void WEAK signals(int sig); #define DBL_EPSILON (2.2204460492503131e-16) #endif +// library version +const char *sl_libversion(); + // double value of UNIX time double dtime(); @@ -160,16 +163,52 @@ typedef struct { 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); -size_t read_tty(TTY_descr *descr); +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); // convert string to double with checking int str2double(double *num, const char *str); -// logging -void openlogfile(char *name); -int putlog(const char *fmt, ...); +// logging (deprecated) +void __attribute__ ((deprecated)) openlogfile(char *name); +int __attribute__ ((deprecated)) putlog(const char *fmt, ...); + +/******************************************************************************\ + Logging +\******************************************************************************/ +typedef enum{ + LOGLEVEL_NONE, // no logs + LOGLEVEL_ERR, // only errors + LOGLEVEL_WARN, // only warnings and errors + LOGLEVEL_MSG, // all without debug + LOGLEVEL_DBG, // all messages + LOGLEVEL_ANY // all shit +} sl_loglevel; + +typedef struct{ + char *logpath; // full path to logfile + sl_loglevel loglevel; // loglevel + int addprefix; // if !=0 add record type to each line(e.g. [ERR]) +} sl_log; + +extern sl_log *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, ...); +// open "global" log +#define OPENLOG(nm, lvl, prefix) (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) /******************************************************************************\ The original parseargs.h @@ -276,7 +315,6 @@ void WEAK iffound_default(pid_t pid); void check4running(char *selfname, char *pidfilename); // read name of process by its PID char *readPSname(pid_t pid); -#endif // __USEFULL_MACROS_H__ /******************************************************************************\ The original fifo_lifo.h @@ -289,3 +327,7 @@ typedef struct buff_node{ List *list_push_tail(List **lst, void *v); List *list_push(List **lst, void *v); void *list_pop(List **lst); + + + +#endif // __USEFULL_MACROS_H__