From a936e0d81591706fa433966d0c828675c5685050 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Fri, 21 Feb 2020 08:48:42 +0300 Subject: [PATCH] Initial commit --- .gitignore | 27 - .../10micron_readme.koi8-r | 58 + Daemons/10micron_stellarium/Makefile | 24 + Daemons/10micron_stellarium/Readme | 1 + Daemons/10micron_stellarium/StelD.config | 3 + Daemons/10micron_stellarium/StelD.creator | 1 + Daemons/10micron_stellarium/StelD.files | 15 + Daemons/10micron_stellarium/StelD.includes | 1 + Daemons/10micron_stellarium/cmdlnopts.c | 96 + Daemons/10micron_stellarium/cmdlnopts.h | 43 + Daemons/10micron_stellarium/daemon.c | 144 + Daemons/10micron_stellarium/emulation.c | 103 + Daemons/10micron_stellarium/emulation.h | 30 + Daemons/10micron_stellarium/libsofa.c | 173 + Daemons/10micron_stellarium/libsofa.h | 71 + Daemons/10micron_stellarium/main.c | 432 ++ Daemons/10micron_stellarium/main.h | 42 + Daemons/10micron_stellarium/parseargs.c | 497 ++ Daemons/10micron_stellarium/parseargs.h | 124 + Daemons/10micron_stellarium/telescope.c | 219 + Daemons/10micron_stellarium/telescope.h | 32 + Daemons/10micron_stellarium/usefull_macros.c | 442 ++ Daemons/10micron_stellarium/usefull_macros.h | 144 + Daemons/Readme.md | 8 + Daemons/domedaemon/Makefile | 43 + Daemons/domedaemon/Readme.md | 13 + Daemons/domedaemon/cmdlnopts.c | 89 + Daemons/domedaemon/cmdlnopts.h | 44 + Daemons/domedaemon/dome_readme.koi8-r | 15 + Daemons/domedaemon/main.c | 83 + Daemons/domedaemon/parseargs.c | 497 ++ Daemons/domedaemon/parseargs.h | 124 + Daemons/domedaemon/socket.c | 330 ++ Daemons/domedaemon/socket.h | 34 + Daemons/domedaemon/term.c | 203 + Daemons/domedaemon/term.h | 38 + Daemons/domedaemon/usefull_macros.c | 437 ++ Daemons/domedaemon/usefull_macros.h | 144 + Daemons/netdaemon/Makefile | 43 + Daemons/netdaemon/Readme.md | 9 + Daemons/netdaemon/cmdlnopts.c | 89 + Daemons/netdaemon/cmdlnopts.h | 44 + Daemons/netdaemon/main.c | 81 + Daemons/netdaemon/netdaemon.c.tags | 5062 +++++++++++++++++ Daemons/netdaemon/parseargs.c | 497 ++ Daemons/netdaemon/parseargs.h | 124 + Daemons/netdaemon/socket.c | 308 + Daemons/netdaemon/socket.h | 34 + Daemons/netdaemon/term.c | 118 + Daemons/netdaemon/term.h | 36 + Daemons/netdaemon/usefull_macros.c | 434 ++ Daemons/netdaemon/usefull_macros.h | 140 + Daemons/netsocket/HWpoweroff | 25 + Daemons/netsocket/HWpoweron | 25 + Daemons/netsocket/MOUNTpoweronoff | 11 + Daemons/netsocket/poweron_readme.koi8-r | 15 + Daemons/teldaemon/Makefile | 43 + Daemons/teldaemon/Readme.md | 12 + Daemons/teldaemon/astrosib_readme.koi8-r | 13 + Daemons/teldaemon/cmdlnopts.c | 89 + Daemons/teldaemon/cmdlnopts.h | 44 + Daemons/teldaemon/main.c | 83 + Daemons/teldaemon/parseargs.c | 497 ++ Daemons/teldaemon/parseargs.h | 124 + Daemons/teldaemon/socket.c | 326 ++ Daemons/teldaemon/socket.h | 34 + Daemons/teldaemon/teldaemon | Bin 0 -> 38288 bytes Daemons/teldaemon/term.c | 193 + Daemons/teldaemon/term.h | 38 + Daemons/teldaemon/usefull_macros.c | 437 ++ Daemons/teldaemon/usefull_macros.h | 144 + Docs/Alignment/PROCESS | 11 + Docs/Alignment/Readme.md | 12 + Docs/Alignment/coordslist | 30 + Docs/Alignment/makelist | 43 + Docs/README_ASTROMETRY.koi8-r | 21 + Docs/README_POWER_management.koi8-r | 65 + Docs/Readme.md | 4 + Docs/focus | 14 + 79 files changed, 14169 insertions(+), 27 deletions(-) create mode 100644 Daemons/10micron_stellarium/10micron_readme.koi8-r create mode 100644 Daemons/10micron_stellarium/Makefile create mode 100644 Daemons/10micron_stellarium/Readme create mode 100644 Daemons/10micron_stellarium/StelD.config create mode 100644 Daemons/10micron_stellarium/StelD.creator create mode 100644 Daemons/10micron_stellarium/StelD.files create mode 100644 Daemons/10micron_stellarium/StelD.includes create mode 100644 Daemons/10micron_stellarium/cmdlnopts.c create mode 100644 Daemons/10micron_stellarium/cmdlnopts.h create mode 100644 Daemons/10micron_stellarium/daemon.c create mode 100644 Daemons/10micron_stellarium/emulation.c create mode 100644 Daemons/10micron_stellarium/emulation.h create mode 100644 Daemons/10micron_stellarium/libsofa.c create mode 100644 Daemons/10micron_stellarium/libsofa.h create mode 100644 Daemons/10micron_stellarium/main.c create mode 100644 Daemons/10micron_stellarium/main.h create mode 100644 Daemons/10micron_stellarium/parseargs.c create mode 100644 Daemons/10micron_stellarium/parseargs.h create mode 100644 Daemons/10micron_stellarium/telescope.c create mode 100644 Daemons/10micron_stellarium/telescope.h create mode 100644 Daemons/10micron_stellarium/usefull_macros.c create mode 100644 Daemons/10micron_stellarium/usefull_macros.h create mode 100644 Daemons/Readme.md create mode 100644 Daemons/domedaemon/Makefile create mode 100644 Daemons/domedaemon/Readme.md create mode 100644 Daemons/domedaemon/cmdlnopts.c create mode 100644 Daemons/domedaemon/cmdlnopts.h create mode 100644 Daemons/domedaemon/dome_readme.koi8-r create mode 100644 Daemons/domedaemon/main.c create mode 100644 Daemons/domedaemon/parseargs.c create mode 100644 Daemons/domedaemon/parseargs.h create mode 100644 Daemons/domedaemon/socket.c create mode 100644 Daemons/domedaemon/socket.h create mode 100644 Daemons/domedaemon/term.c create mode 100644 Daemons/domedaemon/term.h create mode 100644 Daemons/domedaemon/usefull_macros.c create mode 100644 Daemons/domedaemon/usefull_macros.h create mode 100644 Daemons/netdaemon/Makefile create mode 100644 Daemons/netdaemon/Readme.md create mode 100644 Daemons/netdaemon/cmdlnopts.c create mode 100644 Daemons/netdaemon/cmdlnopts.h create mode 100644 Daemons/netdaemon/main.c create mode 100644 Daemons/netdaemon/netdaemon.c.tags create mode 100644 Daemons/netdaemon/parseargs.c create mode 100644 Daemons/netdaemon/parseargs.h create mode 100644 Daemons/netdaemon/socket.c create mode 100644 Daemons/netdaemon/socket.h create mode 100644 Daemons/netdaemon/term.c create mode 100644 Daemons/netdaemon/term.h create mode 100644 Daemons/netdaemon/usefull_macros.c create mode 100644 Daemons/netdaemon/usefull_macros.h create mode 100755 Daemons/netsocket/HWpoweroff create mode 100755 Daemons/netsocket/HWpoweron create mode 100755 Daemons/netsocket/MOUNTpoweronoff create mode 100644 Daemons/netsocket/poweron_readme.koi8-r create mode 100644 Daemons/teldaemon/Makefile create mode 100644 Daemons/teldaemon/Readme.md create mode 100644 Daemons/teldaemon/astrosib_readme.koi8-r create mode 100644 Daemons/teldaemon/cmdlnopts.c create mode 100644 Daemons/teldaemon/cmdlnopts.h create mode 100644 Daemons/teldaemon/main.c create mode 100644 Daemons/teldaemon/parseargs.c create mode 100644 Daemons/teldaemon/parseargs.h create mode 100644 Daemons/teldaemon/socket.c create mode 100644 Daemons/teldaemon/socket.h create mode 100755 Daemons/teldaemon/teldaemon create mode 100644 Daemons/teldaemon/term.c create mode 100644 Daemons/teldaemon/term.h create mode 100644 Daemons/teldaemon/usefull_macros.c create mode 100644 Daemons/teldaemon/usefull_macros.h create mode 100644 Docs/Alignment/PROCESS create mode 100644 Docs/Alignment/Readme.md create mode 100644 Docs/Alignment/coordslist create mode 100755 Docs/Alignment/makelist create mode 100644 Docs/README_ASTROMETRY.koi8-r create mode 100644 Docs/README_POWER_management.koi8-r create mode 100644 Docs/Readme.md create mode 100755 Docs/focus diff --git a/.gitignore b/.gitignore index c6127b3..b76b42b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,6 @@ # Object files *.o -*.ko -*.obj -*.elf # Linker output *.ilk @@ -23,30 +20,6 @@ *.lo # Shared objects (inc. Windows DLLs) -*.dll *.so *.so.* -*.dylib -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf diff --git a/Daemons/10micron_stellarium/10micron_readme.koi8-r b/Daemons/10micron_stellarium/10micron_readme.koi8-r new file mode 100644 index 0000000..d6bf479 --- /dev/null +++ b/Daemons/10micron_stellarium/10micron_readme.koi8-r @@ -0,0 +1,58 @@ +# - очистить принимающий буфер + +:shutdown# - выключить монтировку + +:U2# - установить наивысшую точность + +Состояние гидирования (ACK): команда 0x06, ответ L/P - вкл/выкл +:AL# - выключить ведение (без ответа) +:AP# - включить + +GPS: +:gtg# - возвращает 1, если часы синхронизированы с GPS + +наведение на цель +:MS# - двигаться на цель, возврат: 0, если все в порядке, либо текст с ошибкой +:SrHH:MM:SS.SS# - установить RA цели (возврат 1 если ОК) +:SdsDD*MM:SS.S# - установить DECL цели (возврат 1 если ОК) +:D# - статус наведения, возврат: 0x7f, если в процессе, либо # +:NUDGEsXXX,sYYY# - скорректировать положение по RA/DEC на N угловых секунд +:STOP# - останов (:AP# - для возобновления гидирования) + +:Gstat# - состояние монтировки +:GT# - частота для гидирования (60.1643377745 по звездам) +:AL# - выкл. гидирование +:AP# - вкл +:Gpgc# - состояние гидирования +:GSC# - коррекция скорости гидирования на косинус h +:GTTRK# - возможно ли наведение на текущий объект +:pS# - с какой стороны монтировки телескоп (для перекладывания?) +:FLIP# - переложить монтировку + +:GVP# - название монтировки +:GTMP@# (@ - номер датчика) - температура датчика +:GREF# - состояние коррекции на рефракцию + +:GA# - высота телескопа над горизонтом +:GZ# - азимут +:GC# - дата +:GD# - склонение +:GR# - восхождение + +:GJD# - юлианская дата (GJD1 - с наивысшей точностью) +:GLDT# - местные дата и время +:GS# - звездное время + +парковка: стр. 20 + +ехать: +:Q# - прекратить наведение (а еще :Qe# - east и пр.) +:D# - состояние наведения +:NUDGEsXXXX,sYYYY# - коррекция положения на XXX/YYY секунд (RA/Dec) +:MA# - по введенным горизонтальным координатам цели +:MS# - ехать на цель +:Me$=#, :Mw#, :Mn#, :Ms# - движение в данную сторону +:MeXXX#, :MnXXX# и др. стороны - коррекция на XXX миллисекунд скорости гида + +модель наведения - стр. 44 +после определения центра изображения ввести его командами :Sr# и :Sd# и добавить точку командой :CMS# diff --git a/Daemons/10micron_stellarium/Makefile b/Daemons/10micron_stellarium/Makefile new file mode 100644 index 0000000..309c12d --- /dev/null +++ b/Daemons/10micron_stellarium/Makefile @@ -0,0 +1,24 @@ +PROGRAM = stellariumdaemon +LDFLAGS = -lsofa_c +SRCS = $(wildcard *.c) +CC = gcc +DEFINES = -D_GNU_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=1111 +DEFINES += -DCOM_SPD=B9600 +#DEFINES += -DEBUG +CXX = gcc +CFLAGS = -Wall -Werror -Wextra -Wno-trampolines $(DEFINES) +OBJS = $(SRCS:.c=.o) +all : $(PROGRAM) +$(PROGRAM) : $(OBJS) + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(PROGRAM) + +# some addition dependencies +# %.o: %.c +# $(CC) $(LDFLAGS) $(CFLAGS) $< -o $@ +#$(SRCS) : %.c : %.h $(INDEPENDENT_HEADERS) +# @touch $@ + +clean: + /bin/rm -f *.o *~ +depend: + $(CXX) -MM $(CXX.SRCS) diff --git a/Daemons/10micron_stellarium/Readme b/Daemons/10micron_stellarium/Readme new file mode 100644 index 0000000..d81b392 --- /dev/null +++ b/Daemons/10micron_stellarium/Readme @@ -0,0 +1 @@ +Stellarium control of 10-micron mount diff --git a/Daemons/10micron_stellarium/StelD.config b/Daemons/10micron_stellarium/StelD.config new file mode 100644 index 0000000..e3e2368 --- /dev/null +++ b/Daemons/10micron_stellarium/StelD.config @@ -0,0 +1,3 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 +#define EBUG 1 diff --git a/Daemons/10micron_stellarium/StelD.creator b/Daemons/10micron_stellarium/StelD.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/Daemons/10micron_stellarium/StelD.creator @@ -0,0 +1 @@ +[General] diff --git a/Daemons/10micron_stellarium/StelD.files b/Daemons/10micron_stellarium/StelD.files new file mode 100644 index 0000000..a32707f --- /dev/null +++ b/Daemons/10micron_stellarium/StelD.files @@ -0,0 +1,15 @@ +cmdlnopts.c +cmdlnopts.h +daemon.c +emulation.c +emulation.h +libsofa.c +libsofa.h +main.c +main.h +parseargs.c +parseargs.h +telescope.c +telescope.h +usefull_macros.c +usefull_macros.h diff --git a/Daemons/10micron_stellarium/StelD.includes b/Daemons/10micron_stellarium/StelD.includes new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/Daemons/10micron_stellarium/StelD.includes @@ -0,0 +1 @@ +. diff --git a/Daemons/10micron_stellarium/cmdlnopts.c b/Daemons/10micron_stellarium/cmdlnopts.c new file mode 100644 index 0000000..ce12256 --- /dev/null +++ b/Daemons/10micron_stellarium/cmdlnopts.c @@ -0,0 +1,96 @@ +/* geany_encoding=koi8-r + * cmdlnopts.c - the only function that parse cmdln args and returns glob parameters + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include "cmdlnopts.h" +#include "usefull_macros.h" + +/* + * here are global parameters initialisation + */ +int help; +glob_pars G; + +#define DEFAULT_COMDEV "/dev/ttyUSB0" +// port for connections +#define DEFAULT_PORT "10000" +// accept only local connections +//#define ACCEPT_IP "192.168.3.225" +// default PID filename: +#define DEFAULT_PIDFILE "/tmp/stellariumdaemon.pid" + +// DEFAULTS +// default global parameters +glob_pars const Gdefault = { + .device = DEFAULT_COMDEV, + .port = DEFAULT_PORT, + .pidfile = DEFAULT_PIDFILE, + .emulation = 0, + .logfile = NULL // don't save logs +}; + +/* + * Define command line options by filling structure: + * name has_arg flag val type argptr help +*/ +myoption cmdlnopts[] = { +// common options + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, + {"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), _("serial device name (default: " DEFAULT_COMDEV ")")}, + {"emulation",NO_ARGS, NULL, 'e', arg_int, APTR(&G.emulation), _("run in emulation mode")}, + //{"hostname",NEED_ARG, NULL, 'H', arg_string, APTR(&G.hostname), _("hostname to connect (default: localhost)")}, + {"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 ")")}, + {"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("port to connect (default: " DEFAULT_PORT ")")}, + end_option +}; + +/** + * Parse command line options and return dynamically allocated structure + * to global parameters + * @param argc - copy of argc from main + * @param argv - copy of argv from main + * @return allocated structure with global parameters + */ +glob_pars *parse_args(int argc, char **argv){ + int i; + void *ptr; + ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); + size_t hlen = 1024; + 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); + // parse arguments + parseargs(&argc, &argv, cmdlnopts); + if(help) showhelp(-1, cmdlnopts); + if(argc > 0){ + G.rest_pars_num = argc; + G.rest_pars = calloc(argc, sizeof(char*)); + for (i = 0; i < argc; i++) + G.rest_pars[i] = strdup(argv[i]); + } + return &G; +} + diff --git a/Daemons/10micron_stellarium/cmdlnopts.h b/Daemons/10micron_stellarium/cmdlnopts.h new file mode 100644 index 0000000..cfcafee --- /dev/null +++ b/Daemons/10micron_stellarium/cmdlnopts.h @@ -0,0 +1,43 @@ +/* geany_encoding=koi8-r + * cmdlnopts.h - comand line options for parceargs + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __CMDLNOPTS_H__ +#define __CMDLNOPTS_H__ + +#include "parseargs.h" + +/* + * here are some typedef's for global data + */ +typedef struct{ + char *device; // serial device name + char *port; // port to connect + char *pidfile; // name of PID file + char *logfile; // logging to this file + int emulation; // run in emulation mode + int rest_pars_num; // number of rest parameters + char** rest_pars; // the rest parameters: array of char* +} glob_pars; + + +glob_pars *parse_args(int argc, char **argv); +#endif // __CMDLNOPTS_H__ diff --git a/Daemons/10micron_stellarium/daemon.c b/Daemons/10micron_stellarium/daemon.c new file mode 100644 index 0000000..fbb6200 --- /dev/null +++ b/Daemons/10micron_stellarium/daemon.c @@ -0,0 +1,144 @@ +/* + * daemon.c - functions for running in background like a daemon + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#define PROC_BASE "/proc" + +#include // printf, fopen, ... +#include // getpid +#include // perror +#include // opendir +#include // opendir +#include // stat +#include // fcntl +#include // exit +#include // memset + +/** + * 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 *readname(pid_t pid){ + static char name[256]; + char *pp = name, byte, path[256]; + FILE *file; + int cntr = 0; + size_t sz; + snprintf (path, 255, PROC_BASE "/%d/cmdline", pid); + file = fopen(path, "r"); + if(!file) return NULL; // there's no such file + do{ // read basename + sz = fread(&byte, 1, 1, file); + if(sz != 1) break; + if(byte != '/') *pp++ = byte; + else{ + pp = name; + cntr = 0; + } + }while(byte && cntr++ < 255); + name[cntr] = 0; + fclose(file); + return name; +} + +void iffound_default(pid_t pid){ + fprintf(stderr, "\nFound running process (pid=%d), exit.\n", pid); + exit(0); +} + +/** + * check wether there is a same running process + * exit if there is a running process or error + * Checking have 3 steps: + * 1) lock executable file + * 2) check pidfile (if you run a copy?) + * 3) check /proc for executables with the same name (no/wrong pidfile) + * @param selfname - argv[0] or NULL for non-locking + * @param pidfilename - name of pidfile or NULL if none + * @param iffound - action to run if file found or NULL for exit(0) + */ +void check4running(char *selfname, char *pidfilename, void (*iffound)(pid_t pid)){ + DIR *dir; + FILE *pidfile, *fself; + struct dirent *de; + struct stat s_buf; + pid_t pid = 0, self; + struct flock fl; + char *name, *myname; + if(!iffound) iffound = iffound_default; + if(selfname){ // block self + fself = fopen(selfname, "r"); // open self binary to lock + if(!fself){ + perror("fopen"); + goto selfpid; + } + memset(&fl, 0, sizeof(struct flock)); + fl.l_type = F_WRLCK; + if(fcntl(fileno(fself), F_GETLK, &fl) == -1){ // check locking + perror("fcntl"); + goto selfpid; + } + if(fl.l_type != F_UNLCK){ // file is locking - exit + printf("Found locker, PID = %d!\n", fl.l_pid); + exit(1); + } + fl.l_type = F_RDLCK; + if(fcntl(fileno(fself), F_SETLKW, &fl) == -1){ + perror("fcntl"); + } + } + selfpid: + self = getpid(); // get self PID + if(!(dir = opendir(PROC_BASE))){ // open /proc directory + perror(PROC_BASE); + } + if(!(name = readname(self))){ // error reading self name + perror("Can't read self name"); + exit(1); + } + myname = strdup(name); + if(pidfilename && stat(pidfilename, &s_buf) == 0){ // pidfile exists + pidfile = fopen(pidfilename, "r"); + if(pidfile){ + if(fscanf(pidfile, "%d", &pid) > 0){ // read PID of (possibly) running process + if((name = readname(pid)) && strncmp(name, myname, 255) == 0) + iffound(pid); + } + fclose(pidfile); + } + } + // There is no pidfile or it consists a wrong record + 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 = readname(pid)) && strncmp(name, myname, 255) == 0) + iffound(pid); + } + closedir(dir); + if(pidfilename){ + pidfile = fopen(pidfilename, "w"); + fprintf(pidfile, "%d\n", self); // write self PID to pidfile + fclose(pidfile); + } + free(myname); +} diff --git a/Daemons/10micron_stellarium/emulation.c b/Daemons/10micron_stellarium/emulation.c new file mode 100644 index 0000000..a96640f --- /dev/null +++ b/Daemons/10micron_stellarium/emulation.c @@ -0,0 +1,103 @@ +/* + * geany_encoding=koi8-r + * emulation.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "math.h" +#include "emulation.h" +#include "usefull_macros.h" + +// emulation speed over RA & DEC (0.5 degr per sec) +#define RA_SPEED (0.033) +#define DECL_SPEED (0.5) + +// current coordinates +static double RA = 0., DECL = 0.; +// target coordinates +static double RAtarg = 0., DECLtarg = 0.; +// coordinates @ guiding start +static double RA0 = 0., DECL0 = 0.; +static double raspeed = 0.; +// ==1 if pointing +static int pointing = 0; +// pointing start time +static double tstart = -1.; + +/** + * send coordinates to telescope emulation + * @param ra - right ascention (hours) + * @param decl - declination (degrees) + * @return 1 if all OK + */ +int point_emulation(double ra, double decl){ + DBG("(emul) Send ra=%g, decl=%g", ra, decl); + putlog("(emul) Send ra=%g, decl=%g", ra, decl); + RAtarg = ra; DECLtarg = decl; + RA0 = RA; DECL0 = DECL; + raspeed = (RAtarg > RA) ? RA_SPEED : -RA_SPEED; + if(fabs(RAtarg - RA) > 12.){ // go to opposite direction + raspeed = -raspeed; + } + tstart = dtime(); + pointing = 1; + return 0; +} + +static double getradiff(){ + double diff = RAtarg - RA; + if(raspeed < 0.) diff = -diff; + if(diff > 12.) diff -= 24.; + else if(diff < -12.) diff += 24.; + return fabs(diff); +} + +/** + * get coordinates (emulation) + * @return 1 if all OK + */ +int get_emul_coords(double *ra, double *decl){ + if(pointing){ + DBG("RA/DEC: targ: %g/%g, cur: %g/%g, start: %g/%g", RAtarg, DECLtarg, RA, DECL, RA0, DECL0); + // diff < speed? stop + if((fabs(RAtarg - RA) < RA_SPEED && fabs(DECLtarg - DECL) < DECL_SPEED)){ + RA = RAtarg; + DECL = DECLtarg; + pointing = 0; // guiding + DBG("@ target"); + }else{ // calculate new coordinates + double radiff = getradiff(), decldiff = fabs(DECLtarg - DECL); + double tdiff = dtime() - tstart; + RA = RA0 + raspeed * tdiff; + DBG("RA=%g", RA); + if(getradiff() > radiff) RA = RAtarg; + DBG("RA=%g", RA); + if(RA < 0.) RA += 24.; + else if(RA > 24.) RA -= 24.; + DBG("RA=%g", RA); + double sign = (DECLtarg > DECL) ? 1. : -1.; + DECL = DECL0 + sign * DECL_SPEED * tdiff; + if(fabs(DECLtarg - DECL) > decldiff) DECL = DECLtarg; + DBG("RA/DEC: targ: %g/%g, cur: %g/%g, start: %g/%g", RAtarg, DECLtarg, RA, DECL, RA0, DECL0); + } + } + if(ra) *ra = RA; + if(decl) *decl = DECL; + return 1; +} diff --git a/Daemons/10micron_stellarium/emulation.h b/Daemons/10micron_stellarium/emulation.h new file mode 100644 index 0000000..c15fa71 --- /dev/null +++ b/Daemons/10micron_stellarium/emulation.h @@ -0,0 +1,30 @@ +/* + * geany_encoding=koi8-r + * emulation.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __EMULATION_H__ +#define __EMULATION_H__ + +int point_emulation(double ra, double decl); +int get_emul_coords(double *ra, double *decl); + +#endif // __EMULATION_H__ diff --git a/Daemons/10micron_stellarium/libsofa.c b/Daemons/10micron_stellarium/libsofa.c new file mode 100644 index 0000000..f51b0b9 --- /dev/null +++ b/Daemons/10micron_stellarium/libsofa.c @@ -0,0 +1,173 @@ +/* + * This file is part of the StelD project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "libsofa.h" +#include "usefull_macros.h" + +#ifdef EBUG +void reprd(char* s, double ra, double dc){ + char pm; + int i[4]; + printf ( "%s:", s ); + iauA2tf ( 7, ra, &pm, i ); + printf ( " %2.2d %2.2d %2.2d.%7.7d", i[0],i[1],i[2],i[3] ); + iauA2af ( 6, dc, &pm, i ); + printf ( " %c%2.2d %2.2d %2.2d.%6.6d\n", pm, i[0],i[1],i[2],i[3] ); +} +void radtodeg(double r){ + int i[4]; char pm; + int rem = (int)(r / D2PI); + if(rem) r -= D2PI * rem; + if(r > DPI) r -= D2PI; + else if(r < -DPI) r += D2PI; + iauA2af (2, r, &pm, i); + printf("%c%02d %02d %02d.%2.d", pm, i[0],i[1],i[2],i[3]); +} +#define REP(a,b,c) reprd(a,b,c) +#else +#define REP(a,b,c) +#endif + +// temporal stubs for weather/place data; return 0 if all OK +static int getPlace(placeData *p){ + if(!p) return 0; + /* Site longitude, latitude (radians) and height above the geoid (m). */ + p->slong = 0.7232763200; + p->slat = 0.7618977414; +/* + iauAf2a('+', 41, 26, 26.45, &p->slong); // longitude + iauAf2a('+', 43, 39, 12.69, &p->slat); // latitude + */ + p->salt = 2070.0; // altitude + //DBG("long: %.10f, lat: %.10f", p->slong, p->slat); + return 0; +} +static int getWeath(placeWeather *w){ + if(!w) return 0; + w->relhum = 0.7; + w->tc = 0.; + w->php = 780.; + return 0; +} +static int getDUT(almDut *a){ + if(!a) return 0; + a->px = a->py = a->DUT1 = 0.; + return 0; +} + +/** + * @brief get_MJDt - calculate MJD of date from argument + * @param tval (i) - given date (or NULL for current) + * @param MJD (o) - time + * @return 0 if all OK + */ +int get_MJDt(struct timeval *tval, sMJD *MJD){ + struct tm tms; + double tSeconds; + if(!tval){ + DBG("MJD for current time"); + struct timeval currentTime; + gettimeofday(¤tTime, NULL); + gmtime_r(¤tTime.tv_sec, &tms); + tSeconds = tms.tm_sec + ((double)currentTime.tv_usec)/1e6; + }else{ + gmtime_r(&tval->tv_sec, &tms); + tSeconds = tms.tm_sec + ((double)tval->tv_usec)/1e6; + } + int y, m, d; + y = 1900 + tms.tm_year; + m = tms.tm_mon + 1; + d = tms.tm_mday; + double utc1, utc2; + /* UTC date. */ + if(iauDtf2d("UTC", y, m, d, tms.tm_hour, tms.tm_min, tSeconds, &utc1, &utc2) < 0) return -1; + if(!MJD) return 0; + MJD->MJD = utc1 - 2400000.5 + utc2; + MJD->utc1 = utc1; + MJD->utc2 = utc2; + DBG("UTC(m): %g, %.8f\n", utc1 - 2400000.5, utc2); + if(iauUtctai(utc1, utc2, &MJD->tai1, &MJD->tai2)) return -1; + DBG("TAI"); + if(iauTaitt(MJD->tai1, MJD->tai2, &MJD->tt1, &MJD->tt2)) return -1; + DBG("TT"); + return 0; +} + +/** + * @brief get_ObsPlace - calculate observed place (without PM etc) for given date @550nm + * @param tval (i) - time + * @param p2000 (i) - polar coordinates for J2000 (only ra/dec used) + * @param pnow (o) - polar coordinates for given epoch (or NULL) + * @param hnow (o) - horizontal coordinates for given epoch (or NULL) + * @return 0 if all OK + */ +int get_ObsPlace(struct timeval *tval, polarCrds *p2000, polarCrds *pnow, horizCrds *hnow){ + double pr = 0.0; // RA proper motion (radians/year; Note 2) + double pd = 0.0; // Dec proper motion (radians/year) + double px = 0.0; // parallax (arcsec) + double rv = 0.0; // radial velocity (km/s, positive if receding) + sMJD MJD; + if(get_MJDt(tval, &MJD)) return -1; + if(!p2000) return -1; + placeData p; + placeWeather w; + almDut d; + if(getPlace(&p)) return -1; + if(getWeath(&w)) return -1; + if(getDUT(&d)) return -1; + /* Effective wavelength (microns) */ + double wl = 0.55; + /* ICRS to observed. */ + double aob, zob, hob, dob, rob, eo; +/* + DBG("iauAtco13(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)", + p2000->ra, p2000->dec, pr, pd, px, rv, MJD.utc1, MJD.utc2, d.DUT1, p.slong, p.slat, p.salt, + d.px, d.py, w.php, w.tc, w.relhum, wl); +*/ + if(iauAtco13(p2000->ra, p2000->dec, + pr, pd, px, rv, + MJD.utc1, MJD.utc2, + d.DUT1, + p.slong, p.slat, p.salt, + d.px, d.py, + w.php, w.tc, w.relhum, + wl, + &aob, &zob, + &hob, &dob, &rob, &eo)) return -1; + REP("ICRS->observed", rob, dob); + if(pnow){ + pnow->eo = eo; + pnow->ha = hob; + pnow->ra = rob; + pnow->dec = dob; + } + if(hnow){ + hnow->az = aob; + hnow->zd = zob; + } +#ifdef EBUG + printf("A(bta)/Z: "); + radtodeg(aob); + printf("("); radtodeg(DPI-aob); + printf(")/"); radtodeg(zob); + printf("\n"); +#endif + return 0; +} diff --git a/Daemons/10micron_stellarium/libsofa.h b/Daemons/10micron_stellarium/libsofa.h new file mode 100644 index 0000000..4bb47fc --- /dev/null +++ b/Daemons/10micron_stellarium/libsofa.h @@ -0,0 +1,71 @@ +/* + * This file is part of the StelD project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#ifndef LIBSOFA_H__ +#define LIBSOFA_H__ + +#include +#include +#include + +typedef struct{ + double utc1; double utc2; // UTC JD, commonly used MJD = utc1+utc2-2400000.5 + double MJD; + double tai1; double tai2; // TAI JD + double tt1; double tt2; // TT JD +} sMJD; + +// polar coordinates & equation of origins (all in radians) +typedef struct{ + double ha; // hour angle + double dec; // declination + double ra; // right ascension + double eo; // equation of origins +} polarCrds; + +// horizontal coordinates (all in radians) +typedef struct{ + double az; // azimuth, 0 @ south, positive clockwise + double zd; // zenith distance +} horizCrds; + +// observational place coordinates and altitude; all coordinates are in radians! +typedef struct{ + double slong; // longitude + double slat; // lattitude + double salt; // altitude, m +} placeData; + +// place weather data +typedef struct{ + double relhum; // rel. humidity, 0..1 + double php; // atm. pressure (hectopascales) + double tc; // temperature, degrC +} placeWeather; + +// DUT/polar almanach data +typedef struct{ + double DUT1; // UT1-UTC, sec + double px; // polar coordinates, arcsec + double py; +} almDut; + +int get_MJDt(struct timeval *tval, sMJD *MJD); +int get_ObsPlace(struct timeval *tval, polarCrds *p2000, polarCrds *pnow, horizCrds *hnow); + +#endif // LIBSOFA_H__ diff --git a/Daemons/10micron_stellarium/main.c b/Daemons/10micron_stellarium/main.c new file mode 100644 index 0000000..3732426 --- /dev/null +++ b/Daemons/10micron_stellarium/main.c @@ -0,0 +1,432 @@ +/* + * main.c + * + * Copyright 2014 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmdlnopts.h" +#include "emulation.h" +#include "libsofa.h" +#include "telescope.h" +#include "usefull_macros.h" + +// daemon.c +extern void check4running(char *self, char *pidfilename, void (*iffound)(pid_t pid)); + +// Max amount of connections +#define BACKLOG (1) +#define BUFLEN (1024) +// pause for incoming message waiting (out coordinates sent after that timeout) +#define SOCK_TMOUT (1) + +static uint8_t buff[BUFLEN+1]; +// global parameters +static glob_pars *GP = NULL; + +static volatile int global_quit = 0; +// quit by signal +void signals(int sig){ + signal(sig, SIG_IGN); + restore_console(); + restore_tty(); + DBG("Get signal %d, quit.\n", sig); + global_quit = 1; + sleep(1); + putlog("PID %d exit with status %d", getpid(), sig); + exit(sig); +} + +// search a first word after needle without spaces +char* stringscan(char *str, char *needle){ + char *a, *e; + char *end = str + strlen(str); + a = strstr(str, needle); + if(!a) return NULL; + a += strlen(needle); + while (a < end && (*a == ' ' || *a == '\r' || *a == '\t')) a++; + if(a >= end) return NULL; + e = strchr(a, ' '); + if(e) *e = 0; + return a; +} + +/** + * Send data to user + * @param data - data to send + * @param dlen - data length + * @param sockfd - socket fd for sending data + * @return 0 if failed + */ +int send_data(uint8_t *data, size_t dlen, int sockfd){ + size_t sent = write(sockfd, data, dlen); + if(sent != dlen){ + WARN("write()"); + return 0; + } + return 1; +} + +//read: 0x14 0x0 0x0 0x0 0x5b 0x5a 0x2e 0xc6 0x8c 0x23 0x5 0x0 0x23 0x9 0xe5 0xaf 0x23 0x2e 0x34 0xed +// command: goto 16h29 24.45 -26d25 55.62 +/* + LITTLE-ENDIAN!!! + from client: +LENGTH (2 bytes, integer): length of the message +TYPE (2 bytes, integer): 0 +TIME (8 bytes, integer): current time on the server computer in microseconds + since 1970.01.01 UT. Currently unused. +RA (4 bytes, unsigned integer): right ascension of the telescope (J2000) + a value of 0x100000000 = 0x0 means 24h=0h, + a value of 0x80000000 means 12h +DEC (4 bytes, signed integer): declination of the telescope (J2000) + a value of -0x40000000 means -90degrees, + a value of 0x0 means 0degrees, + a value of 0x40000000 means 90degrees + +to client: +LENGTH (2 bytes, integer): length of the message +TYPE (2 bytes, integer): 0 +TIME (8 bytes, integer): current time on the server computer in microseconds + since 1970.01.01 UT. Currently unused. +RA (4 bytes, unsigned integer): right ascension of the telescope (J2000) + a value of 0x100000000 = 0x0 means 24h=0h, + a value of 0x80000000 means 12h +DEC (4 bytes, signed integer): declination of the telescope (J2000) + a value of -0x40000000 means -90degrees, + a value of 0x0 means 0degrees, + a value of 0x40000000 means 90degrees +STATUS (4 bytes, signed integer): status of the telescope, currently unused. + status=0 means ok, status<0 means some error +*/ + +#define DEG2DEC(degr) ((int32_t)(degr / 90. * ((double)0x40000000))) +#define HRS2RA(hrs) ((uint32_t)(hrs / 12. * ((double)0x80000000))) +#define DEC2DEG(i32) (((double)i32)*90./((double)0x40000000)) +#define RA2HRS(u32) (((double)u32)*12. /((double)0x80000000)) + +typedef struct __attribute__((__packed__)){ + uint16_t len; + uint16_t type; + uint64_t time; + uint32_t ra; + int32_t dec; +} indata; + +typedef struct __attribute__((__packed__)){ + uint16_t len; + uint16_t type; + uint64_t time; + uint32_t ra; + int32_t dec; + int32_t status; +} outdata; + +/** + * convert RA/DEC to string in forman RA: HH:MM:SS.SS, DEC: DD:MM:SS.S + */ +char *radec2str(double ra, double dec){ + static char buf[1024]; + char sign = '+'; + if(dec < 0){ + sign = '-'; + dec = -dec; + } + + int h = (int)ra; + ra -= h; ra *= 60.; + int m = (int)ra; + ra -= m; ra *= 60.; + + int d = (int) dec; + dec -= d; dec *= 60.; + int dm = (int)dec; + dec -= dm; dec *= 60.; + snprintf(buf, 1024, "%d:%d:%.2f %c%d:%d:%.1f", h,m,ra, sign,d,dm,dec); + return buf; +} + +/** + * send input RA/Decl (j2000!) coordinates to tel + * ra in hours (0..24), decl in degrees (-90..90) + * @return 1 if all OK + */ +int setCoords(double ra, double dec){ + char *radec = radec2str(ra, dec); + DBG("Set RA/Decl to %s", radec); + putlog("try to set RA/Decl to %s", radec); + int (*pointfunction)(double, double) = point_telescope; + if(GP->emulation) pointfunction = point_emulation; + return pointfunction(ra, dec); +} + +// return 1 if all OK +int proc_data(uint8_t *data, ssize_t len){ + FNAME(); + if(len != sizeof(indata)){ + WARNX("Bad data size: got %zd instead of %zd!", len, sizeof(indata)); + return 0; + } + indata *dat = (indata*)data; + uint16_t L, T; + //uint64_t tim; + uint32_t ra; + int32_t dec; +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + L = le16toh(dat->len); T = le16toh(dat->type); + //tim = le64toh(dat->time); + ra = le32toh(dat->ra); + dec = (int32_t)le32toh((uint32_t)dat->dec); +#else + L = dat->len; T = dat->type; + //tim = dat->time; + ra = dat->ra; dec = dat->dec; +#endif + DBG("got message with len %u & type %u", L, T); + if(L != len){ + WARNX("Length of message != msg->len"); + return 0; + } + if(T){ + WARNX("Wrong message type"); + return 0; + } + // convert RA/DEC to hours/degrees + double tagRA = RA2HRS(ra), tagDec = DEC2DEG(dec); + DBG("RA: %u (%g), DEC: %d (%g)", ra, tagRA, dec, tagDec); + // check RA/DEC + horizCrds h; + polarCrds p; + p.ra = tagRA/12. * M_PI; + p.dec = tagDec * DD2R; + if(get_ObsPlace(NULL, &p, NULL, &h)){ + WARNX("Can't convert coordinates to horiz"); + return 0; + } +#ifdef EBUG + int i[4], j[4]; char pm, pm1; + iauA2af(2, h.az, &pm, i); + iauA2af(2, h.zd, &pm1, j); + DBG("az: %c%02d %02d %02d.%2.d, zd: %c%02d %02d %02d.%2.d", + pm, i[0],i[1],i[2],i[3], + pm1,j[0],j[1],j[2],j[3]); + iauA2af(2, M_PI_2 - h.zd, &pm, i); + DBG("h: %c%02d %02d %02d.%2.d", pm, i[0],i[1],i[2],i[3]); +#endif + if(h.zd > 80.*DD2R){ + WARNX("Z > 80degr, stop telescope"); + putlog("Z>80 - stop!"); + stop_telescope(); + return 0; + } + if(!setCoords(tagRA, tagDec)) return 0; + return 1; +} + +/** + * main socket service procedure + */ +void handle_socket(int sock){ + FNAME(); + if(global_quit) return; + ssize_t rd; + outdata dout; + dout.len = htole16(sizeof(outdata)); + dout.type = 0; + dout.status = 0; + int (*getcoords)(double*, double*) = get_telescope_coords; + if(GP->emulation) getcoords = get_emul_coords; + while(!global_quit){ + // get coordinates + double RA = 0., Decl = 0.; + if(!getcoords(&RA, &Decl)){ + WARNX("Error: can't get coordinates"); + // continue; + } + DBG("got : %g/%g", RA, Decl); + dout.ra = htole32(HRS2RA(RA)); + dout.dec = (int32_t)htole32(DEG2DEC(Decl)); + if(!send_data((uint8_t*)&dout, sizeof(outdata), sock)) break; + DBG("sent ra = %g, dec = %g", RA2HRS(dout.ra), DEC2DEG(dout.dec)); + fd_set readfds; + struct timeval timeout; + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + timeout.tv_sec = SOCK_TMOUT; // wait not more than SOCK_TMOUT second + timeout.tv_usec = 0; + int sel = select(sock + 1 , &readfds , NULL , NULL , &timeout); + if(sel < 0){ + if(errno != EINTR) + WARN("select()"); + continue; + } + if(!(FD_ISSET(sock, &readfds))) continue; + // fill incoming buffer + rd = read(sock, buff, BUFLEN); + buff[rd] = 0; + DBG("read %zd (%s)", rd, buff); + if(rd <= 0){ // error or disconnect + DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); + break; + } + /************************************** + * DO SOMETHING WITH DATA * + **************************************/ + if(!proc_data(buff, rd)) dout.status = -1; + else dout.status = 0; + } + close(sock); +} + +static inline void main_proc(){ + int sock; + int reuseaddr = 1; + // connect to telescope + if(!GP->emulation){ + if(!connect_telescope(GP->device)){ + ERRX(_("Can't connect to telescope device")); + } + } + // open socket + struct addrinfo hints, *res, *p; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + DBG("try to open port %s", GP->port); + if(getaddrinfo(NULL, GP->port, &hints, &res) != 0){ + ERR("getaddrinfo"); + } + struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN); + // loop through all the results and bind to the first we can + for(p = res; p != NULL; p = p->ai_next){ + if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){ + WARN("socket"); + continue; + } + if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ + ERR("setsockopt"); + } + if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){ + close(sock); + WARN("bind"); + continue; + } + break; // if we get here, we must have connected successfully + } + // Listen + if(listen(sock, BACKLOG) == -1){ + putlog("listen() error"); + ERR("listen"); + } + DBG("listen at %s", GP->port); + putlog("listen at %s", GP->port); + //freeaddrinfo(res); + // Main loop + while(!global_quit){ + socklen_t size = sizeof(struct sockaddr_in); + struct sockaddr_in myaddr; + int newsock; + newsock = accept(sock, (struct sockaddr*)&myaddr, &size); + if(newsock <= 0){ + WARN("accept()"); + continue; + } + struct sockaddr_in peer; + socklen_t peer_len = sizeof(peer); + if (getpeername(newsock, &peer, &peer_len) == -1) { + WARN("getpeername()"); + close(newsock); + continue; + } + char *peerIP = inet_ntoa(peer.sin_addr); + putlog("Got connection from %s", peerIP); + DBG("Peer's IP address is: %s\n", peerIP); + /*if(strcmp(peerIP, ACCEPT_IP) && strcmp(peerIP, "127.0.0.1")){ + WARNX("Wrong IP"); + close(newsock); + continue; + }*/ + handle_socket(newsock); + } + close(sock); +} + +int main(int argc, char **argv){ + char *self = strdup(argv[0]); + GP = parse_args(argc, argv); + initial_setup(); + check4running(self, GP->pidfile, NULL); + if(GP->logfile) openlogfile(GP->logfile); + + 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 + + printf(_("Start socket\n")); + putlog("Starting, master PID=%d", getpid()); +#ifndef EBUG // daemonize only in release mode + if(daemon(1, 0)){ + putlog("Err: daemon()"); + ERR("daemon()"); + } +#endif // EBUG + + while(1){ + pid_t childpid = fork(); + if(childpid < 0){ + putlog("fork() error"); + ERR("ERROR on fork"); + } + if(childpid){ + putlog("Created child with PID %d\n", childpid); + DBG("Created child with PID %d\n", childpid); + wait(NULL); + putlog("Child %d died\n", childpid); + DBG("Child %d died\n", childpid); + }else{ + prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies + main_proc(); + return 0; + } + } + + return 0; +} diff --git a/Daemons/10micron_stellarium/main.h b/Daemons/10micron_stellarium/main.h new file mode 100644 index 0000000..ec6d9c1 --- /dev/null +++ b/Daemons/10micron_stellarium/main.h @@ -0,0 +1,42 @@ +/* + * main.h + * + * Copyright 2014 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmdlnopts.h" +#include "usefull_macros.h" + +// global parameters +extern glob_pars *Global_parameters; + +#endif // __MAIN_H__ diff --git a/Daemons/10micron_stellarium/parseargs.c b/Daemons/10micron_stellarium/parseargs.c new file mode 100644 index 0000000..b235752 --- /dev/null +++ b/Daemons/10micron_stellarium/parseargs.c @@ -0,0 +1,497 @@ +/* geany_encoding=koi8-r + * parseargs.c - parsing command line arguments & print help + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include // printf +#include // getopt_long +#include // calloc, exit, strtoll +#include // assert +#include // strdup, strchr, strlen +#include // strcasecmp +#include // INT_MAX & so on +#include // gettext +#include // isalpha +#include "parseargs.h" +#include "usefull_macros.h" + +char *helpstring = "%s\n"; + +/** + * Change standard help header + * MAY consist ONE "%s" for progname + * @param str (i) - new format + */ +void change_helpstring(char *s){ + int pcount = 0, scount = 0; + char *str = s; + // check `helpstring` and set it to default in case of error + for(; pcount < 2; str += 2){ + if(!(str = strchr(str, '%'))) break; + if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" + else{ + str += 2; // pass next '%' + continue; + } + if(str[1] == 's') scount++; // increment "%s" counter + }; + if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong + /// "Неправильный формат строки помощи" + ERRX(_("Wrong helpstring!")); + } + helpstring = s; +} + +/** + * Carefull atoll/atoi + * @param num (o) - returning value (or NULL if you wish only check number) - allocated by user + * @param str (i) - string with number must not be NULL + * @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 sone without errors, FALSE otherwise + */ +static bool myatoll(void *num, char *str, argtype t){ + long long tmp, *llptr; + int *iptr; + char *endptr; + assert(str); + assert(num); + tmp = strtoll(str, &endptr, 0); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_longlong: + llptr = (long long*) num; + *llptr = tmp; + break; + case arg_int: + default: + if(tmp < INT_MIN || tmp > INT_MAX){ + /// "Целое вне допустимого диапазона" + WARNX(_("Integer out of range")); + return FALSE; + } + iptr = (int*)num; + *iptr = (int)tmp; + } + return TRUE; +} + +// 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){ + double tmp, *dptr; + float *fptr; + char *endptr; + assert(str); + tmp = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_double: + dptr = (double *) num; + *dptr = tmp; + break; + case arg_float: + default: + fptr = (float *) num; + *fptr = (float)tmp; + break; + } + return TRUE; +} + +/** + * 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){ + int oind; + myoption *opts = options; + assert(opts); + for(oind = 0; opts->name && opts->val != opt; oind++, opts++); + if(!opts->name || opts->val != opt) // no such parameter + showhelp(-1, options); + return oind; +} + +/** + * reallocate new value in array of multiple repeating arguments + * @arg paptr - address of pointer to array (**void) + * @arg type - its type (for realloc) + * @return pointer to new (next) value + */ +void *get_aptr(void *paptr, argtype type){ + int i = 1; + void **aptr = *((void***)paptr); + if(aptr){ // there's something in array + void **p = aptr; + while(*p++) ++i; + } + size_t sz = 0; + switch(type){ + default: + case arg_none: + /// "Не могу использовать несколько параметров без аргументов!" + ERRX("Can't use multiple args with arg_none!"); + break; + case arg_int: + sz = sizeof(int); + break; + case arg_longlong: + sz = sizeof(long long); + break; + case arg_double: + sz = sizeof(double); + break; + case arg_float: + sz = sizeof(float); + break; + case arg_string: + sz = 0; + break; + /* case arg_function: + sz = sizeof(argfn *); + break;*/ + } + aptr = realloc(aptr, (i + 1) * sizeof(void*)); + *((void***)paptr) = aptr; + aptr[i] = NULL; + if(sz){ + aptr[i - 1] = malloc(sz); + }else + aptr[i - 1] = &aptr[i - 1]; + return aptr[i - 1]; +} + + +/** + * 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` + * @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt` + * BE CAREFUL! if you wanna use full argc & argv, save their original values before + * calling this function + * @param options (i) - array of `myoption` for arguments parcing + * + * @exit: in case of error this function show help & make `exit(-1)` + */ +void parseargs(int *argc, char ***argv, myoption *options){ + char *short_options, *soptr; + struct option *long_options, *loptr; + size_t optsize, i; + myoption *opts = options; + // check whether there is at least one options + assert(opts); + assert(opts[0].name); + // first we count how much values are in opts + for(optsize = 0; opts->name; optsize++, opts++); + // now we can allocate memory + 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 + 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 + } + if(opts->type != arg_none) // if there is a flag without arg, check its pointer + assert(opts->argptr); + // fill long_options + // don't do memcmp: what if there would be different alignment? + loptr->name = opts->name; + loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; + loptr->flag = opts->flag; + 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++ = ':'; + if(loptr->has_arg == 2) // add '::' if option has optional argument + *soptr++ = ':'; + } + } + // sort all lists & check for repeating +#ifdef EBUG + int cmpstringp(const void *p1, const void *p2){ + return strcmp(* (char * const *) p1, * (char * const *) p2); + } + int cmpcharp(const void *p1, const void *p2){ + return (int)(*(char * const)p1 - *(char *const)p2); + } + qsort(longlist, optsize, sizeof(char *), cmpstringp); + qsort(shortlist,optsize, sizeof(char), cmpcharp); + char *prevl = longlist[0], prevshrt = shortlist[0]; + for(i = 1; i < optsize; ++i){ + if(longlist[i]){ + if(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); + } + prevshrt = shortlist[i]; + } + } +#endif + // 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); + 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; + else optind = get_optind(opt, options); + } + opts = &options[optind]; + // if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag + // now check option + if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) + if(!optarg) 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; + // even if there is no argument, but argptr != NULL, think that optarg = "1" + if(!optarg) optarg = "1"; + switch(opts->type){ + default: + case arg_none: + if(opts->argptr) *((int*)aptr) += 1; // increment value + break; + case arg_int: + result = myatoll(aptr, optarg, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, optarg, arg_longlong); + break; + case arg_double: + result = myatod(aptr, optarg, arg_double); + break; + case arg_float: + result = myatod(aptr, optarg, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(optarg)); + break; + case arg_function: + result = ((argfn)aptr)(optarg); + break; + } + if(!result){ + showhelp(optind, options); + } + } + *argc -= optind; + *argv += optind; +} + +/** + * compare function for qsort + * 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 char *l1 = o1->name, *l2 = o2->name; + int s1 = o1->val, s2 = o2->val; + int *f1 = o1->flag, *f2 = o2->flag; + // check if both options has short arg + if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg + return (s1 - s2); + }else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long + return strcmp(l1, l2); + }else{ // only one have short arg -- return it + if(f2 || !s2) return -1; // a1 have short - it is 'lesser' + else return 1; + } +} + +/** + * 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` + * + * @exit: run `exit(-1)` !!! + */ +void showhelp(int oindex, myoption *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; + assert(opts); + assert(opts[0].name); // check whether there is at least one options + if(oindex > -1){ // print only one message + opts = &options[oindex]; + printf(" "); + if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); + printf("--%s", opts->name); + if(opts->has_arg == 1) printf("=arg"); + else if(opts->has_arg == 2) printf("[=arg]"); + printf(" %s\n", _(opts->help)); + exit(-1); + } + // header, by default is just "progname\n" + printf("\n"); + if(strstr(helpstring, "%s")) // print progname + printf(helpstring, __progname); + else // only text + printf("%s", helpstring); + printf("\n"); + // count max_opt_len + do{ + int L = strlen(opts->name); + if(max_opt_len < L) max_opt_len = L; + }while((++opts)->name); + max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols + opts = options; + // count amount of options + int N; for(N = 0; opts->name; ++N, ++opts); + if(N == 0) exit(-2); + // Now print all help (sorted) + opts = options; + qsort(opts, N, sizeof(myoption), argsort); + do{ + int p = sprintf(buf, " "); // a little indent + if(!opts->flag && opts->val) // .val is short argument + p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); + p += snprintf(buf+p, bufsz-p, "--%s", opts->name); + if(opts->has_arg == 1) // required argument + p += snprintf(buf+p, bufsz-p, "=arg"); + else if(opts->has_arg == 2) // optional argument + p += snprintf(buf+p, bufsz-p, "[=arg]"); + assert(p < max_opt_len); // there would be magic if p >= max_opt_len + printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after + ++opts; + }while(--N); + printf("\n\n"); + exit(-1); +} + +/** + * 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 idx = 0; + if(!par) return -1; + while(so[idx].name){ + if(strcasecmp(par, so[idx].name) == 0) return idx; + ++idx; + } + return -1; // badarg + } + bool opt_setarg(mysuboption *so, int idx, char *val){ + mysuboption *soptr = &so[idx]; + bool result = FALSE; + void *aptr = soptr->argptr; + switch(soptr->type){ + default: + case arg_none: + if(soptr->argptr) *((int*)aptr) += 1; // increment value + result = TRUE; + break; + case arg_int: + result = myatoll(aptr, val, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, val, arg_longlong); + break; + case arg_double: + result = myatod(aptr, val, arg_double); + break; + case arg_float: + result = myatod(aptr, val, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(val)); + break; + case arg_function: + result = ((argfn)aptr)(val); + break; + } + return result; + } + char *tok; + bool ret = FALSE; + char *tmpbuf; + tok = strtok_r(str, ":,", &tmpbuf); + do{ + char *val = strchr(tok, '='); + int noarg = 0; + if(val == NULL){ // no args + val = "1"; + noarg = 1; + }else{ + *val++ = '\0'; + if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = + val = "1"; noarg = 1; + } + } + int idx = findsubopt(tok, opt); + if(idx < 0){ + /// "Неправильный параметр: %s" + WARNX(_("Wrong parameter: %s"), tok); + goto returning; + } + if(noarg && opt[idx].has_arg == NEED_ARG){ + /// "%s: необходим аргумент!" + WARNX(_("%s: argument needed!"), tok); + goto returning; + } + if(!opt_setarg(opt, idx, val)){ + /// "Неправильный аргумент \"%s\" параметра \"%s\"" + WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); + goto returning; + } + }while((tok = strtok_r(NULL, ":,", &tmpbuf))); + ret = TRUE; +returning: + return ret; +} diff --git a/Daemons/10micron_stellarium/parseargs.h b/Daemons/10micron_stellarium/parseargs.h new file mode 100644 index 0000000..537fc5b --- /dev/null +++ b/Daemons/10micron_stellarium/parseargs.h @@ -0,0 +1,124 @@ +/* geany_encoding=koi8-r + * parseargs.h - headers for parsing command line arguments + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __PARSEARGS_H__ +#define __PARSEARGS_H__ + +#include // bool +#include + +#ifndef TRUE + #define TRUE true +#endif + +#ifndef FALSE + #define FALSE false +#endif + +// macro for argptr +#define APTR(x) ((void*)x) + +// if argptr is a function: +typedef bool(*argfn)(void *arg); + +/* + * type of getopt's argument + * WARNING! + * My function change value of flags by pointer, so if you want to use another type + * make a latter conversion, example: + * char charg; + * int iarg; + * myoption opts[] = { + * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; + * ..(parse args).. + * charg = (char) iarg; + */ +typedef enum { + arg_none = 0, // no arg + arg_int, // integer + arg_longlong, // long long + arg_double, // double + arg_float, // float + arg_string, // char * + arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` +} argtype; + +/* + * Structure for getopt_long & help + * BE CAREFUL: .argptr is pointer to data or pointer to function, + * conversion depends on .type + * + * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext, + * but you can redefine it before `#include "parseargs.h"` + * + * if arg is string, then value wil be strdup'ed like that: + * char *str; + * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; + * *(opts[1].str) = strdup(optarg); + * in other cases argptr should be address of some variable (or pointer to allocated memory) + * + * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr + * + * !!!LAST VALUE OF ARRAY SHOULD BE `end_option` or ZEROS !!! + * + */ +typedef enum{ + NO_ARGS = 0, // first three are the same as in getopt_long + NEED_ARG = 1, + OPT_ARG = 2, + MULT_PAR +} hasarg; + +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) + 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)` + const char *help; // help string which would be shown in function `showhelp` or NULL +} myoption; + +/* + * Suboptions structure, almost the same like myoption + * used in parse_subopts() + */ +typedef struct{ + const char *name; + hasarg has_arg; + argtype type; + void *argptr; +} mysuboption; + +// last string of array (all zeros) +#define end_option {0,0,0,0,0,0,0} +#define end_suboption {0,0,0,0} + +extern const char *__progname; + +void showhelp(int oindex, myoption *options); +void parseargs(int *argc, char ***argv, myoption *options); +void change_helpstring(char *s); +bool get_suboption(char *str, mysuboption *opt); + +#endif // __PARSEARGS_H__ diff --git a/Daemons/10micron_stellarium/telescope.c b/Daemons/10micron_stellarium/telescope.c new file mode 100644 index 0000000..3180d22 --- /dev/null +++ b/Daemons/10micron_stellarium/telescope.c @@ -0,0 +1,219 @@ +/* + * geany_encoding=koi8-r + * telescope.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "telescope.h" +#include "usefull_macros.h" + +// polling timeout for answer from mount +#ifndef T_POLLING_TMOUT +#define T_POLLING_TMOUT (1.5) +#endif +#ifndef WAIT_TMOUT +#define WAIT_TMOUT (0.5) +#endif + + +#define BUFLEN 80 + +/** + * read strings from terminal (ending with '\n') with timeout + * @return NULL if nothing was read or pointer to static buffer + */ +static char *read_string(){ + static char buf[BUFLEN]; + size_t r = 0, l; + int LL = BUFLEN - 1; + char *ptr = NULL; + static char *optr = NULL; + if(optr && *optr){ + ptr = optr; + optr = strchr(optr, '\n'); + if(optr) ++optr; + return ptr; + } + ptr = buf; + double d0 = dtime(); + do{ + if((l = read_tty(ptr, LL))){ + r += l; LL -= l; ptr += l; + if(ptr[-1] == '\n') break; + d0 = dtime(); + } + }while(dtime() - d0 < WAIT_TMOUT && LL); + if(r){ + buf[r] = 0; + optr = strchr(buf, '\n'); + if(optr) ++optr; + return buf; + } + return NULL; +} + +/** + * write command + * @return answer or NULL if error occured (or no answer) + */ +static char *write_cmd(const char *cmd){ + DBG("Write %s", cmd); + if(write_tty(cmd, strlen(cmd))) return NULL; + double t0 = dtime(); + static char *ans; + while(dtime() - t0 < T_POLLING_TMOUT){ // read answer + if((ans = read_string())){ // parse new data + DBG("got answer: %s", ans); + return ans; + } + } + return NULL; +} + +/** + * connect telescope device + * @param dev (i) - device name to connect + * @return 1 if all OK + */ +int connect_telescope(char *dev){ + if(!dev) return 0; + DBG("Connection to device %s...", dev); + putlog("Try to connect to device %s...", dev); + char tmpbuf[4096]; + fflush(stdout); + #ifndef COM_SPEED + #define COM_SPEED B9600 + #endif + tty_init(dev, COM_SPEED); + read_tty(tmpbuf, 4096); // clear rbuf + write_cmd(":U2#"); + write_cmd(":U2#"); +// if(!write_cmd(":GR#")) return 0; + putlog("connected", dev); + DBG("connected"); + return 1; +} + +/* +:MS# - move to target, return: 0 if all OK or text with error +:SrHH:MM:SS.SS# - set target RA (return 1 if all OK) +:SdsDD*MM:SS.S# - set target DECL (return 1 if all OK) +*/ + +/** + * send coordinates to telescope + * @param ra - right ascention (hours) + * @param dec - declination (degrees) + * @return 1 if all OK + */ +int point_telescope(double ra, double dec){ + DBG("try to send ra=%g, decl=%g", ra, dec); + int err = 0; + static char buf[80]; + char sign = '+'; + if(dec < 0){ + sign = '-'; + dec = -dec; + } + + int h = (int)ra; + ra -= h; ra *= 60.; + int m = (int)ra; + ra -= m; ra *= 60.; + + int d = (int) dec; + dec -= d; dec *= 60.; + int dm = (int)dec; + dec -= dm; dec *= 60.; + snprintf(buf, 80, ":Sr%d:%d:%.2f#", h,m,ra); + char *ans = write_cmd(buf); + if(!ans || *ans != '1'){ + err = 1; + goto ret; + } + snprintf(buf, 80, ":Sd%c%d:%d:%.1f#", sign,d,dm,dec); + ans = write_cmd(buf); + if(!ans || *ans != '1'){ + err = 2; + goto ret; + } + ans = write_cmd(":MS#"); + if(!ans || *ans != '0'){ + putlog("move error, answer: %s", ans); + err = 2; + goto ret; + } + ret: + if(err){ + putlog("error sending coordinates (err = %d: RA/DEC/MOVE)!", err); + return 0; + }else{ + putlog("Send ra=%g, dec=%g", ra, dec); + } + return 1; +} + +/** + * convert str into RA/DEC coordinate + * @param str (i) - string with angle + * @param val (o) - output angle value + * @return 1 if all OK + */ +static int str2coord(char *str, double *val){ + if(!str || !val) return 0; + int d, m; + float s; + int sign = 1; + if(*str == '+') ++str; + else if(*str == '-'){ + sign = -1; + ++str; + } + int n = sscanf(str, "%d:%d:%f#", &d, &m, &s); + if(n != 3) return 0; + double ang = d + ((double)m)/60. + s/3600.; + if(sign == -1) *val = -ang; + else *val = ang; + return 1; +} + +/** + * get coordinates + * @return 1 if all OK + */ +int get_telescope_coords(double *ra, double *decl){ + double r, d; + char *ans; + // :GR# -> 11:05:26.16# + ans = write_cmd(":GR#"); + if(!str2coord(ans, &r)) return 0; + // :GD# -> +44:14:10.7# + ans = write_cmd(":GD#"); + if(!str2coord(ans, &d)) return 0; + if(ra) *ra = r; + if(decl) *decl = d; + return 1; +} + +void stop_telescope(){ + for(int i = 0; i < 3; ++i){ + if(write_cmd(":STOP#")) return; + } + putlog("Can't send command STOP"); +} diff --git a/Daemons/10micron_stellarium/telescope.h b/Daemons/10micron_stellarium/telescope.h new file mode 100644 index 0000000..38956fb --- /dev/null +++ b/Daemons/10micron_stellarium/telescope.h @@ -0,0 +1,32 @@ +/* + * geany_encoding=koi8-r + * telescope.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __TELESCOPE_H__ +#define __TELESCOPE_H__ + +int connect_telescope(char *dev); +int point_telescope(double ra, double decl); +int get_telescope_coords(double *ra, double *decl); +void stop_telescope(); + +#endif // __TELESCOPE_H__ diff --git a/Daemons/10micron_stellarium/usefull_macros.c b/Daemons/10micron_stellarium/usefull_macros.c new file mode 100644 index 0000000..ac70ffa --- /dev/null +++ b/Daemons/10micron_stellarium/usefull_macros.c @@ -0,0 +1,442 @@ +/* geany_encoding=koi8-r + * usefull_macros.h - a set of usefull functions: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "usefull_macros.h" +#include // PATH_MAX + +/** + * function for different purposes that need to know time intervals + * @return double value: time in seconds + */ +double dtime(){ + double t; + struct timeval tv; + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1e6; + return t; +} + +/******************************************************************************\ + * Coloured terminal +\******************************************************************************/ +int globErr = 0; // errno for WARN/ERR + +// pointers to coloured output printf +int (*red)(const char *fmt, ...); +int (*green)(const char *fmt, ...); +int (*_WARN)(const char *fmt, ...); + +/* + * format red / green messages + * name: r_pr_, g_pr_ + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(RED); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +int g_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(GREEN); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +/* + * print red error/warning messages (if output is a tty) + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_WARN(const char *fmt, ...){ + va_list ar; int i = 1; + fprintf(stderr, RED); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = vfprintf(stderr, fmt, ar); + va_end(ar); + i++; + fprintf(stderr, OLDCOLOR "\n"); + return i; +} + +static const char stars[] = "****************************************"; +/* + * notty variants of coloured printf + * name: s_WARN, r_pr_notty + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int s_WARN(const char *fmt, ...){ + va_list ar; int i; + i = fprintf(stderr, "\n%s\n", stars); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = +vfprintf(stderr, fmt, ar); + va_end(ar); + i += fprintf(stderr, "\n%s\n", stars); + i += fprintf(stderr, "\n"); + return i; +} +int r_pr_notty(const char *fmt, ...){ + va_list ar; int i; + i = printf("\n%s\n", stars); + va_start(ar, fmt); + i += vprintf(fmt, ar); + va_end(ar); + i += printf("\n%s\n", stars); + return i; +} + +/** + * Run this function in the beginning of main() to setup locale & coloured output + */ +void initial_setup(){ + // setup coloured output + if(isatty(STDOUT_FILENO)){ // make color output in tty + red = r_pr_; green = g_pr_; + }else{ // no colors in case of pipe + red = r_pr_notty; green = printf; + } + if(isatty(STDERR_FILENO)) _WARN = r_WARN; + else _WARN = s_WARN; + // Setup locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#if defined GETTEXT_PACKAGE && defined LOCALEDIR + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); +#endif +} + +/******************************************************************************\ + * Memory +\******************************************************************************/ +/* + * 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 *p = calloc(N, S); + if(!p) ERR("malloc"); + //assert(p); + return p; +} + +/** + * 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){ + int fd; + char *ptr; + size_t Mlen; + struct stat statbuf; + /// "Не задано имя файла!" + if(!filename){ + WARNX(_("No filename given!")); + return NULL; + } + if((fd = open(filename, O_RDONLY)) < 0){ + /// "Не могу открыть %s для чтения" + WARN(_("Can't open %s for reading"), filename); + return NULL; + } + if(fstat (fd, &statbuf) < 0){ + /// "Не могу выполнить stat %s" + WARN(_("Can't stat %s"), filename); + close(fd); + return NULL; + } + Mlen = statbuf.st_size; + if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){ + /// "Ошибка mmap" + WARN(_("Mmap error for input")); + close(fd); + return NULL; + } + /// "Не могу закрыть mmap'нутый файл" + if(close(fd)) WARN(_("Can't close mmap'ed file")); + mmapbuf *ret = MALLOC(mmapbuf, 1); + ret->data = ptr; + ret->len = Mlen; + return ret; +} + +void My_munmap(mmapbuf *b){ + if(munmap(b->data, b->len)){ + /// "Не могу munmap" + ERR(_("Can't munmap")); + } + FREE(b); +} + + +/******************************************************************************\ + * Terminal in no-echo mode +\******************************************************************************/ +static struct termios oldt, newt; // terminal flags +static int console_changed = 0; +// run on exit: +void restore_console(){ + if(console_changed) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state + console_changed = 0; +} + +// initial setup: +void setup_con(){ + if(console_changed) return; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ + /// "Не могу настроить консоль" + WARN(_("Can't setup console")); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + signals(0); //quit? + } + console_changed = 1; +} + +/** + * Read character from console without echo + * @return char readed + */ +int read_console(){ + int rb; + struct timeval tv; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(1, &rfds, NULL, NULL, &tv); + if(!retval) rb = 0; + else { + if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); + else rb = 0; + } + return rb; +} + +/** + * getchar() without echo + * wait until at least one character pressed + * @return character readed + */ +int mygetchar(){ // getchar() without need of pressing ENTER + int ret; + do ret = read_console(); + while(ret == 0); + return ret; +} + + +/******************************************************************************\ + * TTY with select() +\******************************************************************************/ +static struct termio oldtty, tty; // TTY flags +static int comfd = -1; // TTY fd + +// run on exit: +void restore_tty(){ + if(comfd == -1) return; + ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state + close(comfd); + comfd = -1; +} + +#ifndef BAUD_RATE +#define BAUD_RATE B9600 +#endif +// init: (speed = B9600 etc) +void tty_init(char *comdev, tcflag_t speed){ + if(comfd == -1){ // not opened + if(!comdev){ + WARNX("comdev == NULL"); + signals(11); + } + DBG("Open port..."); + do{ + comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK); + }while (comfd == -1 && errno == EINTR); + if(comfd < 0){ + WARN(_("Can't open port %s"),comdev); + signals(2); + } + /* DBG("OK\nGet current settings..."); + if(ioctl(comfd, TCGETA, &oldtty) < 0){ // Get settings + /// "Не могу получить настройки" + WARN(_("Can't get settings")); + signals(2); + }*/ + DBG("Make exclusive"); + // make exclusive open + if(ioctl(comfd, TIOCEXCL)){ + WARN(_("Can't do exclusive open")); + close(comfd); + signals(2); + } + } + tty = oldtty; + tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) + tty.c_oflag = 0; + tty.c_cflag = speed|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl + tty.c_cc[VMIN] = 0; // non-canonical mode + tty.c_cc[VTIME] = 5; + if(ioctl(comfd, TCSETA, &tty) < 0){ + /// "Не могу установить настройки" + WARN(_("Can't set settings")); + signals(0); + } + DBG("OK"); +} + +/** + * Read data from TTY + * @param buff (o) - buffer for data read + * @param length - buffer len + * @return amount of bytes read + */ +size_t read_tty(char *buff, size_t length){ + if(comfd < 0) return 0; + ssize_t L = 0, l; + char *ptr = buff; + fd_set rfds; + struct timeval tv; + int retval; + do{ + l = 0; + FD_ZERO(&rfds); + FD_SET(comfd, &rfds); + // wait for 10ms + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(comfd + 1, &rfds, NULL, NULL, &tv); + if (!retval) break; + if(FD_ISSET(comfd, &rfds)){ + if((l = read(comfd, ptr, length)) < 1){ + return 0; + } + ptr += l; L += l; + length -= l; + } + }while(l); + return (size_t)L; +} + +int write_tty(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; +} + +/** + * 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){ + double res; + char *endptr; + if(!str) return 0; + res = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0'){ + /// "Неправильный формат числа double!" + WARNX("Wrong double number format!"); + return FALSE; + } + if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number + return TRUE; +} + +FILE *Flog = NULL; // log file descriptor +char *logname = NULL; +time_t log_open_time = 0; +/** + * Try to open log file + * if failed show warning message + */ +void openlogfile(char *name){ + if(!name){ + WARNX(_("Need filename for log file")); + return; + } + 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; + } + DBG("here"); + 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, "\n\t\t%s", ctime(&t_now)); + va_list ar; + va_start(ar, fmt); + i = vfprintf(Flog, fmt, ar); + va_end(ar); + fprintf(Flog, "\n"); + fflush(Flog); + return i; +} diff --git a/Daemons/10micron_stellarium/usefull_macros.h b/Daemons/10micron_stellarium/usefull_macros.h new file mode 100644 index 0000000..7d88ac5 --- /dev/null +++ b/Daemons/10micron_stellarium/usefull_macros.h @@ -0,0 +1,144 @@ +/* geany_encoding=koi8-r + * usefull_macros.h - a set of usefull macros: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __USEFULL_MACROS_H__ +#define __USEFULL_MACROS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined GETTEXT_PACKAGE && defined LOCALEDIR +/* + * GETTEXT + */ +#include +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) +#else +#define _(String) (String) +#define N_(String) (String) +#endif +#include +#include +#include +#include +#include +#include +#include + + +// unused arguments with -Wall -Werror +#define _U_ __attribute__((__unused__)) + +/* + * Coloured messages output + */ +#define RED "\033[1;31;40m" +#define GREEN "\033[1;32;40m" +#define OLDCOLOR "\033[0;0;0m" + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +/* + * ERROR/WARNING messages + */ +extern int globErr; +extern void signals(int sig); +#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) +#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0) +#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) +#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) + +/* + * print function name, debug messages + * debug mode, -DEBUG + */ +#ifdef EBUG + #define FNAME() do{ fprintf(stderr, OLDCOLOR); \ + fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__);} while(0) + #define DBG(...) do{ fprintf(stderr, OLDCOLOR); \ + fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) +#else + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) +#endif //EBUG + +/* + * 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 FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0) + +#ifndef DBL_EPSILON +#define DBL_EPSILON (2.2204460492503131e-16) +#endif + +double 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, ...); +void * my_alloc(size_t N, size_t S); +void initial_setup(); + +// mmap file +typedef struct{ + char *data; + size_t len; +} mmapbuf; +mmapbuf *My_mmap(char *filename); +void My_munmap(mmapbuf *b); + +void restore_console(); +void setup_con(); +int read_console(); +int mygetchar(); + +void restore_tty(); +void tty_init(char *comdev, tcflag_t speed); +size_t read_tty(char *buff, size_t length); +int write_tty(const char *buff, size_t length); + +int str2double(double *num, const char *str); + +void openlogfile(char *name); +int putlog(const char *fmt, ...); + +#endif // __USEFULL_MACROS_H__ diff --git a/Daemons/Readme.md b/Daemons/Readme.md new file mode 100644 index 0000000..234d752 --- /dev/null +++ b/Daemons/Readme.md @@ -0,0 +1,8 @@ +Different daemons +================= + +- *10micron_stellarium* - simple daemon for 10-micron mount management from stellarium interface +- *domedaemon* - open/close dome by network query +- *netdaemon* - template for net-daemons +- *teldaemon* - open/close Astrosib-500 scope covers by network query +- *netsocket* - scripts for management of network 220V-socket diff --git a/Daemons/domedaemon/Makefile b/Daemons/domedaemon/Makefile new file mode 100644 index 0000000..1e31352 --- /dev/null +++ b/Daemons/domedaemon/Makefile @@ -0,0 +1,43 @@ +# run `make DEF=...` to add extra defines +PROGRAM := domedaemon +LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -pthread +SRCS := $(wildcard *.c) +DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 +#DEFINES += -DEBUG +# baudrate for USB<->UART converter +DEFINES += -DBAUD_RATE=B9600 +OBJDIR := mk +CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines +OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) +DEPS := $(OBJS:.o=.d) +CC = gcc + +all : $(OBJDIR) $(PROGRAM) + +$(PROGRAM) : $(OBJS) + @echo -e "\t\tLD $(PROGRAM)" + $(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM) + +$(OBJDIR): + mkdir $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + +$(OBJDIR)/%.o: %.c + @echo -e "\t\tCC $<" + $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< + +clean: + @echo -e "\t\tCLEAN" + @rm -f $(OBJS) $(DEPS) + @rmdir $(OBJDIR) 2>/dev/null || true + +xclean: clean + @rm -f $(PROGRAM) + +gentags: + CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null + +.PHONY: gentags clean xclean diff --git a/Daemons/domedaemon/Readme.md b/Daemons/domedaemon/Readme.md new file mode 100644 index 0000000..df10745 --- /dev/null +++ b/Daemons/domedaemon/Readme.md @@ -0,0 +1,13 @@ +Baader all-sky dome control network daemon +================== + +Open a socket at given port (default: 55555), works with http & direct requests. + +**Protocol** + +Send requests over socket (by curl or something else) or http requests (in browser). + +* *open* - open dome; +* *close* - close dome; +* *status* - dome state (return "opened", "closed" or "intermediate"); +* *weather* - weather status (good weather or rain/clouds). diff --git a/Daemons/domedaemon/cmdlnopts.c b/Daemons/domedaemon/cmdlnopts.c new file mode 100644 index 0000000..fecb72a --- /dev/null +++ b/Daemons/domedaemon/cmdlnopts.c @@ -0,0 +1,89 @@ +/* geany_encoding=koi8-r + * cmdlnopts.c - the only function that parse cmdln args and returns glob parameters + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include "cmdlnopts.h" +#include "usefull_macros.h" + +/* + * here are global parameters initialisation + */ +int help; +static glob_pars G; + +// default values for Gdefault & help +#define DEFAULT_PORT "55555" + +// DEFAULTS +// default global parameters +glob_pars const Gdefault = { + .device = NULL, + .port = DEFAULT_PORT, + .terminal = 0, + .echo = 0, + .logfile = NULL, + .rest_pars = NULL, + .rest_pars_num = 0 +}; + +/* + * Define command line options by filling structure: + * name has_arg flag val type argptr help +*/ +myoption cmdlnopts[] = { +// common options + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, + {"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), _("serial device name (default: none)")}, + {"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("network port to connect (default: " DEFAULT_PORT ")")}, + {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("save logs to file (default: none)")}, + {"terminal",NO_ARGS, NULL, 't', arg_int, APTR(&G.terminal), _("run as terminal")}, + {"echo", NO_ARGS, NULL, 'e', arg_int, APTR(&G.echo), _("echo users commands back")}, + end_option +}; + +/** + * Parse command line options and return dynamically allocated structure + * to global parameters + * @param argc - copy of argc from main + * @param argv - copy of argv from main + * @return allocated structure with global parameters + */ +glob_pars *parse_args(int argc, char **argv){ + int i; + void *ptr; + ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); + // format of help: "Usage: progname [args]\n" + change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n"); + // parse arguments + parseargs(&argc, &argv, cmdlnopts); + if(help) showhelp(-1, cmdlnopts); + if(argc > 0){ + G.rest_pars_num = argc; + G.rest_pars = calloc(argc, sizeof(char*)); + for (i = 0; i < argc; i++) + G.rest_pars[i] = strdup(argv[i]); + } + return &G; +} + diff --git a/Daemons/domedaemon/cmdlnopts.h b/Daemons/domedaemon/cmdlnopts.h new file mode 100644 index 0000000..712e140 --- /dev/null +++ b/Daemons/domedaemon/cmdlnopts.h @@ -0,0 +1,44 @@ +/* geany_encoding=koi8-r + * cmdlnopts.h - comand line options for parceargs + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __CMDLNOPTS_H__ +#define __CMDLNOPTS_H__ + +#include "parseargs.h" +#include "term.h" + +/* + * here are some typedef's for global data + */ +typedef struct{ + char *device; // serial device name + char *port; // port to connect + char *logfile; // logfile name + int terminal; // run as terminal + int echo; // echo user commands back + int rest_pars_num; // number of rest parameters + char** rest_pars; // the rest parameters: array of char* (path to logfile and thrash) +} glob_pars; + + +glob_pars *parse_args(int argc, char **argv); +#endif // __CMDLNOPTS_H__ diff --git a/Daemons/domedaemon/dome_readme.koi8-r b/Daemons/domedaemon/dome_readme.koi8-r new file mode 100644 index 0000000..f2a4d59 --- /dev/null +++ b/Daemons/domedaemon/dome_readme.koi8-r @@ -0,0 +1,15 @@ +Протокол управления куполом + +в случае ошибки коммуникации ответ - d#comerro -> повторить запрос +в случае ошибки купола ответ - d#domerro + +d#opendom - открыть +d#closdom - закрыть +d#get_dom - текущее положение + ответ: d#posXXXX, X=0 - движение или промежуточное положение, 1 - сегмент полностью открыт, 2 - сегмент полностью закрыт +d#warning - состояние ошибок + ответ: d#erro123, позиции: 1 - дождь, 2 - таймаут, 3 - отключение питания (висит на упсе) + значение: 0 - все в порядке, 1 - тревога (купол закрывается) +d#ask_wea - погодный датчик + ответ: d#weaX000, X==1 - дождь или облака + diff --git a/Daemons/domedaemon/main.c b/Daemons/domedaemon/main.c new file mode 100644 index 0000000..fbcd8d6 --- /dev/null +++ b/Daemons/domedaemon/main.c @@ -0,0 +1,83 @@ +/* geany_encoding=koi8-r + * main.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "usefull_macros.h" +#include +#include // wait +#include //prctl +#include "cmdlnopts.h" +#include "socket.h" + +// dome @ /dev/ttyS2 + +glob_pars *GP; + +void signals(int signo){ + restore_console(); + restore_tty(); + putlog("exit with status %d", signo); + exit(signo); +} + +int main(int argc, char **argv){ + initial_setup(); + 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 + GP = parse_args(argc, argv); + if(GP->terminal){ + if(!GP->device) ERRX(_("Point serial device name")); + try_connect(GP->device); + run_terminal(); + signals(0); // never reached! + } + if(GP->logfile) + openlogfile(GP->logfile); + #ifndef EBUG + if(daemon(1, 0)){ + ERR("daemon()"); + } + while(1){ // guard for dead processes + pid_t childpid = fork(); + if(childpid){ + putlog("create child with PID %d\n", childpid); + DBG("Created child with PID %d\n", childpid); + wait(NULL); + putlog("child %d died\n", childpid); + WARNX("Child %d died\n", childpid); + sleep(1); + }else{ + prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies + break; // go out to normal functional + } + } + #endif + + if(GP->device) try_connect(GP->device); + if(ping()){ + putlog("Can't write command PING"); + ERRX(_("Can't write command PING")); + } + daemonize(GP->port); + signals(0); // newer reached + return 0; +} diff --git a/Daemons/domedaemon/parseargs.c b/Daemons/domedaemon/parseargs.c new file mode 100644 index 0000000..b235752 --- /dev/null +++ b/Daemons/domedaemon/parseargs.c @@ -0,0 +1,497 @@ +/* geany_encoding=koi8-r + * parseargs.c - parsing command line arguments & print help + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include // printf +#include // getopt_long +#include // calloc, exit, strtoll +#include // assert +#include // strdup, strchr, strlen +#include // strcasecmp +#include // INT_MAX & so on +#include // gettext +#include // isalpha +#include "parseargs.h" +#include "usefull_macros.h" + +char *helpstring = "%s\n"; + +/** + * Change standard help header + * MAY consist ONE "%s" for progname + * @param str (i) - new format + */ +void change_helpstring(char *s){ + int pcount = 0, scount = 0; + char *str = s; + // check `helpstring` and set it to default in case of error + for(; pcount < 2; str += 2){ + if(!(str = strchr(str, '%'))) break; + if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" + else{ + str += 2; // pass next '%' + continue; + } + if(str[1] == 's') scount++; // increment "%s" counter + }; + if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong + /// "Неправильный формат строки помощи" + ERRX(_("Wrong helpstring!")); + } + helpstring = s; +} + +/** + * Carefull atoll/atoi + * @param num (o) - returning value (or NULL if you wish only check number) - allocated by user + * @param str (i) - string with number must not be NULL + * @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 sone without errors, FALSE otherwise + */ +static bool myatoll(void *num, char *str, argtype t){ + long long tmp, *llptr; + int *iptr; + char *endptr; + assert(str); + assert(num); + tmp = strtoll(str, &endptr, 0); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_longlong: + llptr = (long long*) num; + *llptr = tmp; + break; + case arg_int: + default: + if(tmp < INT_MIN || tmp > INT_MAX){ + /// "Целое вне допустимого диапазона" + WARNX(_("Integer out of range")); + return FALSE; + } + iptr = (int*)num; + *iptr = (int)tmp; + } + return TRUE; +} + +// 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){ + double tmp, *dptr; + float *fptr; + char *endptr; + assert(str); + tmp = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_double: + dptr = (double *) num; + *dptr = tmp; + break; + case arg_float: + default: + fptr = (float *) num; + *fptr = (float)tmp; + break; + } + return TRUE; +} + +/** + * 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){ + int oind; + myoption *opts = options; + assert(opts); + for(oind = 0; opts->name && opts->val != opt; oind++, opts++); + if(!opts->name || opts->val != opt) // no such parameter + showhelp(-1, options); + return oind; +} + +/** + * reallocate new value in array of multiple repeating arguments + * @arg paptr - address of pointer to array (**void) + * @arg type - its type (for realloc) + * @return pointer to new (next) value + */ +void *get_aptr(void *paptr, argtype type){ + int i = 1; + void **aptr = *((void***)paptr); + if(aptr){ // there's something in array + void **p = aptr; + while(*p++) ++i; + } + size_t sz = 0; + switch(type){ + default: + case arg_none: + /// "Не могу использовать несколько параметров без аргументов!" + ERRX("Can't use multiple args with arg_none!"); + break; + case arg_int: + sz = sizeof(int); + break; + case arg_longlong: + sz = sizeof(long long); + break; + case arg_double: + sz = sizeof(double); + break; + case arg_float: + sz = sizeof(float); + break; + case arg_string: + sz = 0; + break; + /* case arg_function: + sz = sizeof(argfn *); + break;*/ + } + aptr = realloc(aptr, (i + 1) * sizeof(void*)); + *((void***)paptr) = aptr; + aptr[i] = NULL; + if(sz){ + aptr[i - 1] = malloc(sz); + }else + aptr[i - 1] = &aptr[i - 1]; + return aptr[i - 1]; +} + + +/** + * 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` + * @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt` + * BE CAREFUL! if you wanna use full argc & argv, save their original values before + * calling this function + * @param options (i) - array of `myoption` for arguments parcing + * + * @exit: in case of error this function show help & make `exit(-1)` + */ +void parseargs(int *argc, char ***argv, myoption *options){ + char *short_options, *soptr; + struct option *long_options, *loptr; + size_t optsize, i; + myoption *opts = options; + // check whether there is at least one options + assert(opts); + assert(opts[0].name); + // first we count how much values are in opts + for(optsize = 0; opts->name; optsize++, opts++); + // now we can allocate memory + 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 + 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 + } + if(opts->type != arg_none) // if there is a flag without arg, check its pointer + assert(opts->argptr); + // fill long_options + // don't do memcmp: what if there would be different alignment? + loptr->name = opts->name; + loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; + loptr->flag = opts->flag; + 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++ = ':'; + if(loptr->has_arg == 2) // add '::' if option has optional argument + *soptr++ = ':'; + } + } + // sort all lists & check for repeating +#ifdef EBUG + int cmpstringp(const void *p1, const void *p2){ + return strcmp(* (char * const *) p1, * (char * const *) p2); + } + int cmpcharp(const void *p1, const void *p2){ + return (int)(*(char * const)p1 - *(char *const)p2); + } + qsort(longlist, optsize, sizeof(char *), cmpstringp); + qsort(shortlist,optsize, sizeof(char), cmpcharp); + char *prevl = longlist[0], prevshrt = shortlist[0]; + for(i = 1; i < optsize; ++i){ + if(longlist[i]){ + if(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); + } + prevshrt = shortlist[i]; + } + } +#endif + // 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); + 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; + else optind = get_optind(opt, options); + } + opts = &options[optind]; + // if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag + // now check option + if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) + if(!optarg) 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; + // even if there is no argument, but argptr != NULL, think that optarg = "1" + if(!optarg) optarg = "1"; + switch(opts->type){ + default: + case arg_none: + if(opts->argptr) *((int*)aptr) += 1; // increment value + break; + case arg_int: + result = myatoll(aptr, optarg, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, optarg, arg_longlong); + break; + case arg_double: + result = myatod(aptr, optarg, arg_double); + break; + case arg_float: + result = myatod(aptr, optarg, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(optarg)); + break; + case arg_function: + result = ((argfn)aptr)(optarg); + break; + } + if(!result){ + showhelp(optind, options); + } + } + *argc -= optind; + *argv += optind; +} + +/** + * compare function for qsort + * 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 char *l1 = o1->name, *l2 = o2->name; + int s1 = o1->val, s2 = o2->val; + int *f1 = o1->flag, *f2 = o2->flag; + // check if both options has short arg + if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg + return (s1 - s2); + }else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long + return strcmp(l1, l2); + }else{ // only one have short arg -- return it + if(f2 || !s2) return -1; // a1 have short - it is 'lesser' + else return 1; + } +} + +/** + * 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` + * + * @exit: run `exit(-1)` !!! + */ +void showhelp(int oindex, myoption *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; + assert(opts); + assert(opts[0].name); // check whether there is at least one options + if(oindex > -1){ // print only one message + opts = &options[oindex]; + printf(" "); + if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); + printf("--%s", opts->name); + if(opts->has_arg == 1) printf("=arg"); + else if(opts->has_arg == 2) printf("[=arg]"); + printf(" %s\n", _(opts->help)); + exit(-1); + } + // header, by default is just "progname\n" + printf("\n"); + if(strstr(helpstring, "%s")) // print progname + printf(helpstring, __progname); + else // only text + printf("%s", helpstring); + printf("\n"); + // count max_opt_len + do{ + int L = strlen(opts->name); + if(max_opt_len < L) max_opt_len = L; + }while((++opts)->name); + max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols + opts = options; + // count amount of options + int N; for(N = 0; opts->name; ++N, ++opts); + if(N == 0) exit(-2); + // Now print all help (sorted) + opts = options; + qsort(opts, N, sizeof(myoption), argsort); + do{ + int p = sprintf(buf, " "); // a little indent + if(!opts->flag && opts->val) // .val is short argument + p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); + p += snprintf(buf+p, bufsz-p, "--%s", opts->name); + if(opts->has_arg == 1) // required argument + p += snprintf(buf+p, bufsz-p, "=arg"); + else if(opts->has_arg == 2) // optional argument + p += snprintf(buf+p, bufsz-p, "[=arg]"); + assert(p < max_opt_len); // there would be magic if p >= max_opt_len + printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after + ++opts; + }while(--N); + printf("\n\n"); + exit(-1); +} + +/** + * 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 idx = 0; + if(!par) return -1; + while(so[idx].name){ + if(strcasecmp(par, so[idx].name) == 0) return idx; + ++idx; + } + return -1; // badarg + } + bool opt_setarg(mysuboption *so, int idx, char *val){ + mysuboption *soptr = &so[idx]; + bool result = FALSE; + void *aptr = soptr->argptr; + switch(soptr->type){ + default: + case arg_none: + if(soptr->argptr) *((int*)aptr) += 1; // increment value + result = TRUE; + break; + case arg_int: + result = myatoll(aptr, val, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, val, arg_longlong); + break; + case arg_double: + result = myatod(aptr, val, arg_double); + break; + case arg_float: + result = myatod(aptr, val, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(val)); + break; + case arg_function: + result = ((argfn)aptr)(val); + break; + } + return result; + } + char *tok; + bool ret = FALSE; + char *tmpbuf; + tok = strtok_r(str, ":,", &tmpbuf); + do{ + char *val = strchr(tok, '='); + int noarg = 0; + if(val == NULL){ // no args + val = "1"; + noarg = 1; + }else{ + *val++ = '\0'; + if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = + val = "1"; noarg = 1; + } + } + int idx = findsubopt(tok, opt); + if(idx < 0){ + /// "Неправильный параметр: %s" + WARNX(_("Wrong parameter: %s"), tok); + goto returning; + } + if(noarg && opt[idx].has_arg == NEED_ARG){ + /// "%s: необходим аргумент!" + WARNX(_("%s: argument needed!"), tok); + goto returning; + } + if(!opt_setarg(opt, idx, val)){ + /// "Неправильный аргумент \"%s\" параметра \"%s\"" + WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); + goto returning; + } + }while((tok = strtok_r(NULL, ":,", &tmpbuf))); + ret = TRUE; +returning: + return ret; +} diff --git a/Daemons/domedaemon/parseargs.h b/Daemons/domedaemon/parseargs.h new file mode 100644 index 0000000..537fc5b --- /dev/null +++ b/Daemons/domedaemon/parseargs.h @@ -0,0 +1,124 @@ +/* geany_encoding=koi8-r + * parseargs.h - headers for parsing command line arguments + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __PARSEARGS_H__ +#define __PARSEARGS_H__ + +#include // bool +#include + +#ifndef TRUE + #define TRUE true +#endif + +#ifndef FALSE + #define FALSE false +#endif + +// macro for argptr +#define APTR(x) ((void*)x) + +// if argptr is a function: +typedef bool(*argfn)(void *arg); + +/* + * type of getopt's argument + * WARNING! + * My function change value of flags by pointer, so if you want to use another type + * make a latter conversion, example: + * char charg; + * int iarg; + * myoption opts[] = { + * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; + * ..(parse args).. + * charg = (char) iarg; + */ +typedef enum { + arg_none = 0, // no arg + arg_int, // integer + arg_longlong, // long long + arg_double, // double + arg_float, // float + arg_string, // char * + arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` +} argtype; + +/* + * Structure for getopt_long & help + * BE CAREFUL: .argptr is pointer to data or pointer to function, + * conversion depends on .type + * + * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext, + * but you can redefine it before `#include "parseargs.h"` + * + * if arg is string, then value wil be strdup'ed like that: + * char *str; + * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; + * *(opts[1].str) = strdup(optarg); + * in other cases argptr should be address of some variable (or pointer to allocated memory) + * + * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr + * + * !!!LAST VALUE OF ARRAY SHOULD BE `end_option` or ZEROS !!! + * + */ +typedef enum{ + NO_ARGS = 0, // first three are the same as in getopt_long + NEED_ARG = 1, + OPT_ARG = 2, + MULT_PAR +} hasarg; + +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) + 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)` + const char *help; // help string which would be shown in function `showhelp` or NULL +} myoption; + +/* + * Suboptions structure, almost the same like myoption + * used in parse_subopts() + */ +typedef struct{ + const char *name; + hasarg has_arg; + argtype type; + void *argptr; +} mysuboption; + +// last string of array (all zeros) +#define end_option {0,0,0,0,0,0,0} +#define end_suboption {0,0,0,0} + +extern const char *__progname; + +void showhelp(int oindex, myoption *options); +void parseargs(int *argc, char ***argv, myoption *options); +void change_helpstring(char *s); +bool get_suboption(char *str, mysuboption *opt); + +#endif // __PARSEARGS_H__ diff --git a/Daemons/domedaemon/socket.c b/Daemons/domedaemon/socket.c new file mode 100644 index 0000000..4eedb7a --- /dev/null +++ b/Daemons/domedaemon/socket.c @@ -0,0 +1,330 @@ +/* + * geany_encoding=koi8-r + * socket.c - socket IO + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "usefull_macros.h" +#include "socket.h" +#include "term.h" +#include // addrinfo +#include // inet_ntop +#include +#include // INT_xxx +#include // pthread_kill +#include // daemon +#include // syscall + +#include "cmdlnopts.h" // glob_pars + +#define BUFLEN (10240) +// Max amount of connections +#define BACKLOG (30) + +extern glob_pars *GP; + +static char *status; // global variable with device status +static char weather[32]; + +typedef enum{ + CMD_OPEN, + CMD_CLOSE, + CMD_NONE +} commands; + +static commands cmd = CMD_NONE; + +/* + * Define global data buffers here + */ + +/**************** COMMON FUNCTIONS ****************/ +/** + * wait for answer from socket + * @param sock - socket fd + * @return 0 in case of error or timeout, 1 in case of socket ready + */ +static int waittoread(int sock){ + fd_set fds; + struct timeval timeout; + int rc; + timeout.tv_sec = 1; // wait not more than 1 second + timeout.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(sock, &fds); + do{ + rc = select(sock+1, &fds, NULL, NULL, &timeout); + if(rc < 0){ + if(errno != EINTR){ + WARN("select()"); + return 0; + } + continue; + } + break; + }while(1); + if(FD_ISSET(sock, &fds)) return 1; + return 0; +} + +/**************** SERVER FUNCTIONS ****************/ +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +/** + * Send data over socket + * @param sock - socket fd + * @param webquery - ==1 if this is web query + * @param textbuf - zero-trailing buffer with data to send + * @return 1 if all OK + */ +static int send_data(int sock, int webquery, const char *textbuf){ + ssize_t L, Len; + char tbuf[BUFLEN]; + Len = strlen(textbuf); + // OK buffer ready, prepare to send it + if(webquery){ + L = snprintf((char*)tbuf, BUFLEN, + "HTTP/2.0 200 OK\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Methods: GET, POST\r\n" + "Access-Control-Allow-Credentials: true\r\n" + "Content-type: text/plain\r\nContent-Length: %zd\r\n\r\n", Len); + if(L < 0){ + WARN("sprintf()"); + return 0; + } + if(L != write(sock, tbuf, L)){ + WARN("write"); + return 0; + } + } + // send data + //DBG("send %zd bytes\nBUF: %s", Len, buf); + if(Len != write(sock, textbuf, Len)){ + WARN("write()"); + return 0; + } + return 1; +} + +// search a first word after needle without spaces +static char* stringscan(char *str, char *needle){ + char *a, *e; + char *end = str + strlen(str); + a = strstr(str, needle); + if(!a) return NULL; + a += strlen(needle); + while (a < end && (*a == ' ' || *a == '\r' || *a == '\t' || *a == '\r')) a++; + if(a >= end) return NULL; + e = strchr(a, ' '); + if(e) *e = 0; + return a; +} + +static void *handle_socket(void *asock){ + FNAME(); + int sock = *((int*)asock); + int webquery = 0; // whether query is web or regular + char buff[BUFLEN]; + ssize_t rd; + double t0 = dtime(); + while(dtime() - t0 < SOCKET_TIMEOUT){ + if(!waittoread(sock)){ // no data incoming + continue; + } + if(!(rd = read(sock, buff, BUFLEN-1))){ + break; + } + DBG("Got %zd bytes", rd); + if(rd < 0){ // error + DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); + break; + } + // add trailing zero to be on the safe side + buff[rd] = 0; + // now we should check what do user want + char *got, *found = buff; + if((got = stringscan(buff, "GET")) || (got = stringscan(buff, "POST"))){ // web query + webquery = 1; + char *slash = strchr(got, '/'); + if(slash) found = slash + 1; + // web query have format GET /some.resource + } + // here we can process user data + DBG("user send: %s\nfound=%s", buff, found); + if(GP->echo){ + if(!send_data(sock, webquery, found)){ + putlog("can't send data, some error occured"); + } + } + pthread_mutex_lock(&mutex); + const char *proto = "Commands: open, close, status"; + if(strstr(found, "open")){ + DBG("User asks 2 open"); + putlog("User asks to open"); + cmd = CMD_OPEN; + send_data(sock, webquery, "OK\n"); + }else if(strstr(found, "close")){ + DBG("User asks 2 close"); + putlog("User asks to close"); + cmd = CMD_CLOSE; + send_data(sock, webquery, "OK\n"); + }else if(strstr(found, "weather")){ + send_data(sock, webquery, weather); + }else if(strstr(found, "status")){ + DBG("User asks 4 status"); + send_data(sock, webquery, status); + }else send_data(sock, webquery, proto); + pthread_mutex_unlock(&mutex); + break; + } + close(sock); + pthread_exit(NULL); + return NULL; +} + +// main socket server +static void *server(void *asock){ + putlog("server(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); + int sock = *((int*)asock); + if(listen(sock, BACKLOG) == -1){ + putlog("listen() failed"); + WARN("listen"); + return NULL; + } + while(1){ + socklen_t size = sizeof(struct sockaddr_in); + struct sockaddr_in their_addr; + int newsock; + if(!waittoread(sock)) continue; + newsock = accept(sock, (struct sockaddr*)&their_addr, &size); + if(newsock <= 0){ + putlog("accept() failed"); + WARN("accept()"); + continue; + } + struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&their_addr; + struct in_addr ipAddr = pV4Addr->sin_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); + putlog("Got connection from %s", str); + DBG("Got connection from %s\n", str); + pthread_t handler_thread; + if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){ + putlog("server(): pthread_create() failed"); + WARN("pthread_create()"); + }else{ + DBG("Thread created, detouch"); + pthread_detach(handler_thread); // don't care about thread state + } + } + putlog("server(): UNREACHABLE CODE REACHED!"); +} + +// data gathering & socket management +static void daemon_(int sock){ + if(sock < 0) return; + pthread_t sock_thread; + if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ + putlog("daemon_(): pthread_create() failed"); + ERR("pthread_create()"); + } + double tgot = 0.; + sprintf(weather, "unknown"); + do{ + if(pthread_kill(sock_thread, 0) == ESRCH){ // died + WARNX("Sockets thread died"); + putlog("Sockets thread died"); + pthread_join(sock_thread, NULL); + if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ + putlog("daemon_(): new pthread_create() failed"); + ERR("pthread_create()"); + } + } + usleep(1000); // sleep a little or thread's won't be able to lock mutex + if(dtime() - tgot < T_INTERVAL) continue; + tgot = dtime(); + // copy temporary buffers to main + pthread_mutex_lock(&mutex); + char *pollans = poll_device(weather); + if(pollans) status = pollans; + if(cmd != CMD_NONE){ + switch (cmd){ + case CMD_OPEN: + DBG("received command: open"); + if(write_cmd("d#opendom")) cmd = CMD_NONE; + break; + case CMD_CLOSE: + DBG("received command: close"); + if(write_cmd("d#closdom")) cmd = CMD_NONE; + break; + default: + DBG("WTF?"); + } + } + pthread_mutex_unlock(&mutex); + }while(1); + putlog("daemon_(): UNREACHABLE CODE REACHED!"); +} + +/** + * Run daemon service + */ +void daemonize(char *port){ + FNAME(); + int sock = -1; + struct addrinfo hints, *res, *p; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if(getaddrinfo(NULL, port, &hints, &res) != 0){ + ERR("getaddrinfo"); + } + struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN); + // loop through all the results and bind to the first we can + for(p = res; p != NULL; p = p->ai_next){ + if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){ + WARN("socket"); + continue; + } + int reuseaddr = 1; + if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ + ERR("setsockopt"); + } + if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){ + close(sock); + WARN("bind"); + continue; + } + break; // if we get here, we have a successfull connection + } + if(p == NULL){ + putlog("failed to bind socket, exit"); + // looped off the end of the list with no successful bind + ERRX("failed to bind socket"); + } + freeaddrinfo(res); + daemon_(sock); + close(sock); + putlog("socket closed, exit"); + signals(0); +} + diff --git a/Daemons/domedaemon/socket.h b/Daemons/domedaemon/socket.h new file mode 100644 index 0000000..5d0c407 --- /dev/null +++ b/Daemons/domedaemon/socket.h @@ -0,0 +1,34 @@ +/* + * geany_encoding=koi8-r + * socket.h + * + * Copyright 2017 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __SOCKET_H__ +#define __SOCKET_H__ + +// timeout for socket closing +#define SOCKET_TIMEOUT (5.0) +// time interval for data polling (seconds) +#define T_INTERVAL (2.) + +void daemonize(char *port); + +#endif // __SOCKET_H__ diff --git a/Daemons/domedaemon/term.c b/Daemons/domedaemon/term.c new file mode 100644 index 0000000..0d34688 --- /dev/null +++ b/Daemons/domedaemon/term.c @@ -0,0 +1,203 @@ +/* geany_encoding=koi8-r + * client.c - terminal parser + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "usefull_macros.h" +#include "term.h" +#include // strncasecmp +#include // time(NULL) +#include // INT_MAX, INT_MIN + +#define BUFLEN 1024 + +static char buf[BUFLEN]; + +/** + * read strings from terminal (ending with '\n') with timeout + * @return NULL if nothing was read or pointer to static buffer + */ +static char *read_string(){ + //FNAME(); + size_t r = 0, l; + int LL = BUFLEN - 1; + char *ptr = NULL; + static char *optr = NULL; + if(optr && *optr){ + ptr = optr; + optr = strchr(optr, '\n'); + if(optr) ++optr; + //DBG("got data, roll to next; ptr=%s\noptr=%s",ptr,optr); + return ptr; + } + ptr = buf; + double d0 = dtime(); + do{ + if((l = read_tty(ptr, LL))){ + r += l; LL -= l; ptr += l; + //DBG("got: %s", buf); + if(ptr[-1] == '\n') break; + d0 = dtime(); + } + }while(dtime() - d0 < WAIT_TMOUT && LL); + if(r){ + buf[r] = 0; + //DBG("r=%zd, got string: %s", r, buf); + optr = strchr(buf, '\n'); + if(optr) ++optr; + return buf; + } + return NULL; +} + +/** + * Try to connect to `device` at BAUD_RATE speed + * @return connection speed if success or 0 + */ +void try_connect(char *device){ + if(!device) return; + char tmpbuf[4096]; + fflush(stdout); + tty_init(device); + read_tty(tmpbuf, 4096); // clear rbuf + putlog("Connected to %s", device); + DBG("connected"); +} + +static void con_sig(int rb){ + static char buf[256]; + static int L = 0; + if(rb < 1) return; + if(rb != '\n'){ + if(rb == 127 && L > 0){ + printf("\b \b"); + fflush(stdout); + --L; + }else{ + if(1 != write(1, &rb, 1)) + printf("%c", (char)rb); + buf[L++] = (char)rb; + if(L >= 250){ + printf("\nbuffer overrun!\n"); + L = 0; + } + } + }else{ + //buf[L++] = '\r'; + //buf[L++] = '\n'; + buf[L] = 0; + printf("\n\t\tSend %s\n", buf); + write_tty(buf, L); + L = 0; + } +} + +/** + * run terminal emulation: send user's commands and show answers + */ +void run_terminal(){ + green(_("Work in terminal mode without echo\n")); + int rb; + char buf[BUFLEN]; + size_t l; + setup_con(); + while(1){ + if((l = read_tty(buf, BUFLEN - 1))){ + buf[l] = 0; + printf("%s", buf); + } + if((rb = read_console())){ + con_sig(rb); + } + } +} + +/** + * write command + * @return answer or NULL if error occured (or no answer) + */ +char *write_cmd(const char *cmd){ + DBG("Write %s", cmd); + if(write_tty(cmd, strlen(cmd))) return NULL; + double t0 = dtime(); + static char *ans; + while(dtime() - t0 < T_POLLING_TMOUT){ // read answer + if((ans = read_string())){ // parse new data + DBG("got answer: %s", ans); + return ans; + } + } + return NULL; +} + +/** + * Poll serial port for new dataportion + * @return: NULL if no data received, pointer to string if valid data received + */ +char *poll_device(char *wea){ + char *ans; + static char pollbuf[32]; + const char *cmdstat = "d#get_dom"; + const char *cmdweat = "d#ask_wea"; + const char *getweat = "d#wea"; + const char *cmdget = "d#pos"; + #define CMDGETLEN (5) + #define CMDWEALEN (5) + while(read_string()); // clear receiving buffer + if(!(ans = write_cmd(cmdstat))) return NULL; // error writing command + if(strstr(ans, cmdget) == NULL){ + DBG("no %s found in %s", cmdstat, ans); + return NULL; // ? + } + ans += CMDGETLEN; + if(strstr(ans, "1111")){ + sprintf(pollbuf, "opened\n"); + DBG("dome opened"); + }else if(strstr(ans, "2222")){ + sprintf(pollbuf, "closed\n"); + DBG("dome closed"); + }else sprintf(pollbuf, "intermediate\n"); + if(!wea || !(ans = write_cmd(cmdweat))) return pollbuf; + DBG("poll weather answer"); + if(strstr(ans, getweat) == NULL){ + DBG("no %s found in %s", getweat, ans); + return pollbuf; // ? + } + ans += CMDWEALEN; + if(*ans == '0'){ + sprintf(wea, "good weather\n"); + DBG("good weather"); + }else if(*ans == '1'){ + sprintf(wea, "rain or clouds\n"); + DBG("bad weather"); + }else sprintf(wea, "unknown\n"); + return pollbuf; +} + +/** + * ping device + * @return 0 if all OK + */ +int ping(){ + FNAME(); + while(read_string()); // clear receiving buffer + char *ans = write_cmd("d#get_dom"); + if(!ans) return 1; + if(strstr(ans, "d#pos")) return 0; + return 1; +} diff --git a/Daemons/domedaemon/term.h b/Daemons/domedaemon/term.h new file mode 100644 index 0000000..00acfb6 --- /dev/null +++ b/Daemons/domedaemon/term.h @@ -0,0 +1,38 @@ +/* geany_encoding=koi8-r + * term.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __TERM_H__ +#define __TERM_H__ + +#define FRAME_MAX_LENGTH (300) +#define MAX_MEMORY_DUMP_SIZE (0x800 * 4) +// Terminal timeout (seconds) +#define WAIT_TMOUT (0.5) +// Terminal polling timeout - 1 second +#define T_POLLING_TMOUT (1.0) + +void run_terminal(); +void try_connect(char *device); +char *poll_device(char *wea); +int ping(); +char *write_cmd(const char *cmd); + +#endif // __TERM_H__ diff --git a/Daemons/domedaemon/usefull_macros.c b/Daemons/domedaemon/usefull_macros.c new file mode 100644 index 0000000..da08cfe --- /dev/null +++ b/Daemons/domedaemon/usefull_macros.c @@ -0,0 +1,437 @@ +/* + * usefull_macros.h - a set of usefull functions: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "usefull_macros.h" +#include +#include // PATH_MAX + +/** + * function for different purposes that need to know time intervals + * @return double value: time in seconds + */ +double dtime(){ + double t; + struct timeval tv; + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1e6; + return t; +} + +/******************************************************************************\ + * Coloured terminal +\******************************************************************************/ +int globErr = 0; // errno for WARN/ERR + +// pointers to coloured output printf +int (*red)(const char *fmt, ...); +int (*green)(const char *fmt, ...); +int (*_WARN)(const char *fmt, ...); + +/* + * format red / green messages + * name: r_pr_, g_pr_ + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(RED); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +int g_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(GREEN); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +/* + * print red error/warning messages (if output is a tty) + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_WARN(const char *fmt, ...){ + va_list ar; int i = 1; + fprintf(stderr, RED); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = vfprintf(stderr, fmt, ar); + va_end(ar); + i++; + fprintf(stderr, OLDCOLOR "\n"); + return i; +} + +static const char stars[] = "****************************************"; +/* + * notty variants of coloured printf + * name: s_WARN, r_pr_notty + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int s_WARN(const char *fmt, ...){ + va_list ar; int i; + i = fprintf(stderr, "\n%s\n", stars); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = +vfprintf(stderr, fmt, ar); + va_end(ar); + i += fprintf(stderr, "\n%s\n", stars); + i += fprintf(stderr, "\n"); + return i; +} +int r_pr_notty(const char *fmt, ...){ + va_list ar; int i; + i = printf("\n%s\n", stars); + va_start(ar, fmt); + i += vprintf(fmt, ar); + va_end(ar); + i += printf("\n%s\n", stars); + return i; +} + +/** + * Run this function in the beginning of main() to setup locale & coloured output + */ +void initial_setup(){ + // setup coloured output + if(isatty(STDOUT_FILENO)){ // make color output in tty + red = r_pr_; green = g_pr_; + }else{ // no colors in case of pipe + red = r_pr_notty; green = printf; + } + if(isatty(STDERR_FILENO)) _WARN = r_WARN; + else _WARN = s_WARN; + // Setup locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#if defined GETTEXT_PACKAGE && defined LOCALEDIR + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); +#endif +} + +/******************************************************************************\ + * Memory +\******************************************************************************/ +/* + * 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 *p = calloc(N, S); + if(!p) ERR("malloc"); + //assert(p); + return p; +} + +/** + * 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){ + int fd; + char *ptr; + size_t Mlen; + struct stat statbuf; + /// "Не задано имя файла!" + if(!filename){ + WARNX(_("No filename given!")); + return NULL; + } + if((fd = open(filename, O_RDONLY)) < 0){ + /// "Не могу открыть %s для чтения" + WARN(_("Can't open %s for reading"), filename); + return NULL; + } + if(fstat (fd, &statbuf) < 0){ + /// "Не могу выполнить stat %s" + WARN(_("Can't stat %s"), filename); + close(fd); + return NULL; + } + Mlen = statbuf.st_size; + if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){ + /// "Ошибка mmap" + WARN(_("Mmap error for input")); + close(fd); + return NULL; + } + /// "Не могу закрыть mmap'нутый файл" + if(close(fd)) WARN(_("Can't close mmap'ed file")); + mmapbuf *ret = MALLOC(mmapbuf, 1); + ret->data = ptr; + ret->len = Mlen; + return ret; +} + +void My_munmap(mmapbuf *b){ + if(munmap(b->data, b->len)){ + /// "Не могу munmap" + ERR(_("Can't munmap")); + } + FREE(b); +} + + +/******************************************************************************\ + * Terminal in no-echo mode +\******************************************************************************/ +static struct termios oldt, newt; // terminal flags +static int console_changed = 0; +// run on exit: +void restore_console(){ + if(console_changed) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state + console_changed = 0; +} + +// initial setup: +void setup_con(){ + if(console_changed) return; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ + /// "Не могу настроить консоль" + WARN(_("Can't setup console")); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + signals(0); //quit? + } + console_changed = 1; +} + +/** + * Read character from console without echo + * @return char readed + */ +int read_console(){ + int rb; + struct timeval tv; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(1, &rfds, NULL, NULL, &tv); + if(!retval) rb = 0; + else { + if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); + else rb = 0; + } + return rb; +} + +/** + * getchar() without echo + * wait until at least one character pressed + * @return character readed + */ +int mygetchar(){ // getchar() without need of pressing ENTER + int ret; + do ret = read_console(); + while(ret == 0); + return ret; +} + + +/******************************************************************************\ + * TTY with select() +\******************************************************************************/ +static struct termio oldtty, tty; // TTY flags +static int comfd = -1; // TTY fd + +// run on exit: +void restore_tty(){ + if(comfd == -1) return; + ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state + close(comfd); + comfd = -1; +} + +#ifndef BAUD_RATE +#define BAUD_RATE B4800 +#endif +#pragma message("Baudrate: " STR(BAUD_RATE) " (default: " STR(B4800) ")") +// init: +void tty_init(char *comdev){ + DBG("\nOpen port %s ...\n", comdev); + do{ + comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK); + }while (comfd == -1 && errno == EINTR); + if(comfd < 0){ + WARN("Can't use port %s\n",comdev); + signals(-1); // quit? + } + // make exclusive open + if(ioctl(comfd, TIOCEXCL)){ + WARN(_("Can't do exclusive open")); + close(comfd); + signals(2); + } + DBG(" OK\nGet current settings... "); + if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings + /// "Не могу получить настройки" + WARN(_("Can't get settings")); + signals(-1); + } + tty = oldtty; + tty.c_lflag = 0; + tty.c_oflag = 0; + tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl + tty.c_cc[VMIN] = 20; + tty.c_cc[VTIME] = 5; + if(ioctl(comfd,TCSETA,&tty) < 0){ + /// "Не могу установить настройки" + WARN(_("Can't set settings")); + signals(-1); + } + DBG(" OK\n"); +} + +/** + * Read data from TTY + * @param buff (o) - buffer for data read + * @param length - buffer len + * @return amount of bytes read + */ +size_t read_tty(char *buff, size_t length){ + ssize_t L = 0, l; + char *ptr = buff; + fd_set rfds; + struct timeval tv; + int retval; + do{ + l = 0; + FD_ZERO(&rfds); + FD_SET(comfd, &rfds); + // wait for 100ms + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(comfd + 1, &rfds, NULL, NULL, &tv); + if (!retval) break; + if(FD_ISSET(comfd, &rfds)){ + //DBG("ISSET"); + if((l = read(comfd, ptr, length)) < 1){ + return 0; + } + //DBG("got %zd", l); + ptr += l; L += l; + length -= l; + } + }while(l); + return (size_t)L; +} + +int write_tty(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; +} + + +/** + * 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){ + double res; + char *endptr; + if(!str) return 0; + res = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0'){ + /// "Неправильный формат числа double!" + WARNX("Wrong double number format!"); + return FALSE; + } + if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number + return TRUE; +} + +FILE *Flog = NULL; // log file descriptor +char *logname = NULL; +time_t log_open_time = 0; +/** + * Try to open log file + * if failed show warning message + */ +void openlogfile(char *name){ + if(!name){ + WARNX(_("Need filename")); + return; + } + green(_("Try to open log file %s in append mode\n"), name); + 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, "\n\t\t%s", ctime(&t_now)); + va_list ar; + va_start(ar, fmt); + i = vfprintf(Flog, fmt, ar); + va_end(ar); + fprintf(Flog, "\n"); + fflush(Flog); + return i; +} diff --git a/Daemons/domedaemon/usefull_macros.h b/Daemons/domedaemon/usefull_macros.h new file mode 100644 index 0000000..0d62e3c --- /dev/null +++ b/Daemons/domedaemon/usefull_macros.h @@ -0,0 +1,144 @@ +/* + * usefull_macros.h - a set of usefull macros: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __USEFULL_MACROS_H__ +#define __USEFULL_MACROS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined GETTEXT_PACKAGE && defined LOCALEDIR +/* + * GETTEXT + */ +#include +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) +#else +#define _(String) (String) +#define N_(String) (String) +#endif + +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) + +#include +#include +#include +#include +#include +#include + + +// unused arguments with -Wall -Werror +#define _U_ __attribute__((__unused__)) + +/* + * Coloured messages output + */ +#define RED "\033[1;31;40m" +#define GREEN "\033[1;32;40m" +#define OLDCOLOR "\033[0;0;0m" + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +/* + * ERROR/WARNING messages + */ +extern int globErr; +extern void signals(int sig); +#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) +#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0) +#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) +#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) + +/* + * print function name, debug messages + * debug mode, -DEBUG + */ +#ifdef EBUG + #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) +#else + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) +#endif //EBUG + +/* + * 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 FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0) + +#ifndef DBL_EPSILON +#define DBL_EPSILON (2.2204460492503131e-16) +#endif + +double 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, ...); +void * my_alloc(size_t N, size_t S); +void initial_setup(); + +// mmap file +typedef struct{ + char *data; + size_t len; +} mmapbuf; +mmapbuf *My_mmap(char *filename); +void My_munmap(mmapbuf *b); + +void restore_console(); +void setup_con(); +int read_console(); +int mygetchar(); + +void restore_tty(); +void tty_init(char *comdev); +size_t read_tty(char *buff, size_t length); +int write_tty(const char *buff, size_t length); + +int str2double(double *num, const char *str); + +void openlogfile(char *name); +int putlog(const char *fmt, ...); +#endif // __USEFULL_MACROS_H__ diff --git a/Daemons/netdaemon/Makefile b/Daemons/netdaemon/Makefile new file mode 100644 index 0000000..bc11a20 --- /dev/null +++ b/Daemons/netdaemon/Makefile @@ -0,0 +1,43 @@ +# run `make DEF=...` to add extra defines +PROGRAM := netdaemon +LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -pthread +SRCS := $(wildcard *.c) +DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 +DEFINES += -DEBUG +# baudrate for USB<->UART converter +DEFINES += -DBAUD_RATE=B115200 +OBJDIR := mk +CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines +OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) +DEPS := $(OBJS:.o=.d) +CC = gcc + +all : $(OBJDIR) $(PROGRAM) + +$(PROGRAM) : $(OBJS) + @echo -e "\t\tLD $(PROGRAM)" + $(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM) + +$(OBJDIR): + mkdir $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + +$(OBJDIR)/%.o: %.c + @echo -e "\t\tCC $<" + $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< + +clean: + @echo -e "\t\tCLEAN" + @rm -f $(OBJS) $(DEPS) + @rmdir $(OBJDIR) 2>/dev/null || true + +xclean: clean + @rm -f $(PROGRAM) + +gentags: + CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null + +.PHONY: gentags clean xclean diff --git a/Daemons/netdaemon/Readme.md b/Daemons/netdaemon/Readme.md new file mode 100644 index 0000000..24d6bef --- /dev/null +++ b/Daemons/netdaemon/Readme.md @@ -0,0 +1,9 @@ +Network daemon snippet +================== + +This isn't an end-product, but just a template for different net-daemons. + +Open a socket at given port (default: 4444), works with http & direct requests. +Can read and send commands over serial interface. + +Pieces with user code marked as 'INSERT CODE HERE'. diff --git a/Daemons/netdaemon/cmdlnopts.c b/Daemons/netdaemon/cmdlnopts.c new file mode 100644 index 0000000..229b0d3 --- /dev/null +++ b/Daemons/netdaemon/cmdlnopts.c @@ -0,0 +1,89 @@ +/* geany_encoding=koi8-r + * cmdlnopts.c - the only function that parse cmdln args and returns glob parameters + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include "cmdlnopts.h" +#include "usefull_macros.h" + +/* + * here are global parameters initialisation + */ +int help; +static glob_pars G; + +// default values for Gdefault & help +#define DEFAULT_PORT "4444" + +// DEFAULTS +// default global parameters +glob_pars const Gdefault = { + .device = NULL, + .port = DEFAULT_PORT, + .terminal = 0, + .echo = 0, + .logfile = NULL, + .rest_pars = NULL, + .rest_pars_num = 0 +}; + +/* + * Define command line options by filling structure: + * name has_arg flag val type argptr help +*/ +myoption cmdlnopts[] = { +// common options + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, + {"device", NEED_ARG, NULL, 'i', arg_string, APTR(&G.device), _("serial device name (default: none)")}, + {"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("network port to connect (default: " DEFAULT_PORT ")")}, + {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("save logs to file (default: none)")}, + {"terminal",NO_ARGS, NULL, 't', arg_int, APTR(&G.terminal), _("run as terminal")}, + {"echo", NO_ARGS, NULL, 'e', arg_int, APTR(&G.echo), _("echo users commands back")}, + end_option +}; + +/** + * Parse command line options and return dynamically allocated structure + * to global parameters + * @param argc - copy of argc from main + * @param argv - copy of argv from main + * @return allocated structure with global parameters + */ +glob_pars *parse_args(int argc, char **argv){ + int i; + void *ptr; + ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); + // format of help: "Usage: progname [args]\n" + change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n"); + // parse arguments + parseargs(&argc, &argv, cmdlnopts); + if(help) showhelp(-1, cmdlnopts); + if(argc > 0){ + G.rest_pars_num = argc; + G.rest_pars = calloc(argc, sizeof(char*)); + for (i = 0; i < argc; i++) + G.rest_pars[i] = strdup(argv[i]); + } + return &G; +} + diff --git a/Daemons/netdaemon/cmdlnopts.h b/Daemons/netdaemon/cmdlnopts.h new file mode 100644 index 0000000..712e140 --- /dev/null +++ b/Daemons/netdaemon/cmdlnopts.h @@ -0,0 +1,44 @@ +/* geany_encoding=koi8-r + * cmdlnopts.h - comand line options for parceargs + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __CMDLNOPTS_H__ +#define __CMDLNOPTS_H__ + +#include "parseargs.h" +#include "term.h" + +/* + * here are some typedef's for global data + */ +typedef struct{ + char *device; // serial device name + char *port; // port to connect + char *logfile; // logfile name + int terminal; // run as terminal + int echo; // echo user commands back + int rest_pars_num; // number of rest parameters + char** rest_pars; // the rest parameters: array of char* (path to logfile and thrash) +} glob_pars; + + +glob_pars *parse_args(int argc, char **argv); +#endif // __CMDLNOPTS_H__ diff --git a/Daemons/netdaemon/main.c b/Daemons/netdaemon/main.c new file mode 100644 index 0000000..ecc757c --- /dev/null +++ b/Daemons/netdaemon/main.c @@ -0,0 +1,81 @@ +/* geany_encoding=koi8-r + * main.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "usefull_macros.h" +#include +#include // wait +#include //prctl +#include "cmdlnopts.h" +#include "socket.h" + +glob_pars *GP; + +void signals(int signo){ + restore_console(); + restore_tty(); + putlog("exit with status %d", signo); + exit(signo); +} + +int main(int argc, char **argv){ + initial_setup(); + 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 + GP = parse_args(argc, argv); + if(GP->terminal){ + if(!GP->device) ERRX(_("Point serial device name")); + try_connect(GP->device); + run_terminal(); + signals(0); // never reached! + } + if(GP->logfile) + openlogfile(GP->logfile); + #ifndef EBUG + if(daemon(1, 0)){ + ERR("daemon()"); + } + while(1){ // guard for dead processes + pid_t childpid = fork(); + if(childpid){ + putlog("create child with PID %d\n", childpid); + DBG("Created child with PID %d\n", childpid); + wait(NULL); + putlog("child %d died\n", childpid); + WARNX("Child %d died\n", childpid); + sleep(1); + }else{ + prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies + break; // go out to normal functional + } + } + #endif + + if(GP->device) try_connect(GP->device); + /* + * INSERT CODE HERE + * connection check & device validation + */ + //if(!G->terminal) signals(15); // there's not main controller connected to given terminal + daemonize(GP->port); + return 0; +} diff --git a/Daemons/netdaemon/netdaemon.c.tags b/Daemons/netdaemon/netdaemon.c.tags new file mode 100644 index 0000000..b86995e --- /dev/null +++ b/Daemons/netdaemon/netdaemon.c.tags @@ -0,0 +1,5062 @@ +# format=tagmanager +ACCESSPERMSл65536ж0 +ADJ_ESTERRORл65536ж0 +ADJ_FREQUENCYл65536ж0 +ADJ_MAXERRORл65536ж0 +ADJ_MICROл65536ж0 +ADJ_NANOл65536ж0 +ADJ_OFFSETл65536ж0 +ADJ_OFFSET_SINGLESHOTл65536ж0 +ADJ_OFFSET_SS_READл65536ж0 +ADJ_SETOFFSETл65536ж0 +ADJ_STATUSл65536ж0 +ADJ_TAIл65536ж0 +ADJ_TICKл65536ж0 +ADJ_TIMECONSTл65536ж0 +AF_ALGл65536ж0 +AF_APPLETALKл65536ж0 +AF_ASHл65536ж0 +AF_ATMPVCл65536ж0 +AF_ATMSVCл65536ж0 +AF_AX25л65536ж0 +AF_BLUETOOTHл65536ж0 +AF_BRIDGEл65536ж0 +AF_CAIFл65536ж0 +AF_CANл65536ж0 +AF_DECnetл65536ж0 +AF_ECONETл65536ж0 +AF_FILEл65536ж0 +AF_IBл65536ж0 +AF_IEEE802154л65536ж0 +AF_INETл65536ж0 +AF_INET6л65536ж0 +AF_IPXл65536ж0 +AF_IRDAл65536ж0 +AF_ISDNл65536ж0 +AF_IUCVл65536ж0 +AF_KCMл65536ж0 +AF_KEYл65536ж0 +AF_LLCл65536ж0 +AF_LOCALл65536ж0 +AF_MAXл65536ж0 +AF_MPLSл65536ж0 +AF_NETBEUIл65536ж0 +AF_NETLINKл65536ж0 +AF_NETROMл65536ж0 +AF_NFCл65536ж0 +AF_PACKETл65536ж0 +AF_PHONETл65536ж0 +AF_PPPOXл65536ж0 +AF_QIPCRTRл65536ж0 +AF_RDSл65536ж0 +AF_ROSEл65536ж0 +AF_ROUTEл65536ж0 +AF_RXRPCл65536ж0 +AF_SECURITYл65536ж0 +AF_SMCл65536ж0 +AF_SNAл65536ж0 +AF_TIPCл65536ж0 +AF_UNIXл65536ж0 +AF_UNSPECл65536ж0 +AF_VSOCKл65536ж0 +AF_WANPIPEл65536ж0 +AF_X25л65536ж0 +AIO_PRIO_DELTA_MAXл65536ж0 +AI_ADDRCONFIGл65536ж0 +AI_ALLл65536ж0 +AI_CANONIDNл65536ж0 +AI_CANONNAMEл65536ж0 +AI_IDNл65536ж0 +AI_IDN_ALLOW_UNASSIGNEDл65536ж0 +AI_IDN_USE_STD3_ASCII_RULESл65536ж0 +AI_NUMERICHOSTл65536ж0 +AI_NUMERICSERVл65536ж0 +AI_PASSIVEл65536ж0 +AI_V4MAPPEDл65536ж0 +ALLOCл131072м(type,var,size)ж0 +ALLPERMSл65536ж0 +APTRл131072м(x)ж0 +ARG_MAXл65536ж0 +AT_EACCESSл65536ж0 +AT_EMPTY_PATHл65536ж0 +AT_FDCWDл65536ж0 +AT_NO_AUTOMOUNTл65536ж0 +AT_REMOVEDIRл65536ж0 +AT_SYMLINK_FOLLOWл65536ж0 +AT_SYMLINK_NOFOLLOWл65536ж0 +B0л65536ж0 +B1000000л65536ж0 +B110л65536ж0 +B115200л65536ж0 +B1152000л65536ж0 +B1200л65536ж0 +B134л65536ж0 +B150л65536ж0 +B1500000л65536ж0 +B1800л65536ж0 +B19200л65536ж0 +B200л65536ж0 +B2000000л65536ж0 +B230400л65536ж0 +B2400л65536ж0 +B2500000л65536ж0 +B300л65536ж0 +B3000000л65536ж0 +B3500000л65536ж0 +B38400л65536ж0 +B4000000л65536ж0 +B460800л65536ж0 +B4800л65536ж0 +B50л65536ж0 +B500000л65536ж0 +B57600л65536ж0 +B576000л65536ж0 +B600л65536ж0 +B75л65536ж0 +B921600л65536ж0 +B9600л65536ж0 +BACKLOGл65536ж0 +BAUD_RATEл65536ж0 +BC_BASE_MAXл65536ж0 +BC_DIM_MAXл65536ж0 +BC_SCALE_MAXл65536ж0 +BC_STRING_MAXл65536ж0 +BIG_ENDIANл65536ж0 +BRKINTл65536ж0 +BS0л65536ж0 +BS1л65536ж0 +BSDLYл65536ж0 +BUFLENл65536ж0 +BUFSIZл65536ж0 +BUS_ADRALNл65536ж0 +BUS_ADRERRл65536ж0 +BUS_MCEERR_AOл65536ж0 +BUS_MCEERR_ARл65536ж0 +BUS_OBJERRл65536ж0 +BYTE_ORDERл65536ж0 +CBAUDл65536ж0 +CBAUDEXл65536ж0 +CBRKл65536ж0 +CCEQл131072м(val,c)ж0 +CDISCARDл65536ж0 +CDSUSPл65536ж0 +CEOFл65536ж0 +CEOLл65536ж0 +CEOTл65536ж0 +CERASEл65536ж0 +CFLUSHл65536ж0 +CHARCLASS_NAME_MAXл65536ж0 +CHAR_BITл65536ж0 +CHAR_MAXл65536ж0 +CHAR_MINл65536ж0 +CHAR_WIDTHл65536ж0 +CIBAUDл65536ж0 +CINTRл65536ж0 +CKILLл65536ж0 +CLD_CONTINUEDл65536ж0 +CLD_DUMPEDл65536ж0 +CLD_EXITEDл65536ж0 +CLD_KILLEDл65536ж0 +CLD_STOPPEDл65536ж0 +CLD_TRAPPEDл65536ж0 +CLNEXTл65536ж0 +CLOCALл65536ж0 +CLOCKS_PER_SECл65536ж0 +CLOCK_BOOTTIMEл65536ж0 +CLOCK_BOOTTIME_ALARMл65536ж0 +CLOCK_MONOTONICл65536ж0 +CLOCK_MONOTONIC_COARSEл65536ж0 +CLOCK_MONOTONIC_RAWл65536ж0 +CLOCK_PROCESS_CPUTIME_IDл65536ж0 +CLOCK_REALTIMEл65536ж0 +CLOCK_REALTIME_ALARMл65536ж0 +CLOCK_REALTIME_COARSEл65536ж0 +CLOCK_TAIл65536ж0 +CLOCK_THREAD_CPUTIME_IDл65536ж0 +CLONE_CHILD_CLEARTIDл65536ж0 +CLONE_CHILD_SETTIDл65536ж0 +CLONE_DETACHEDл65536ж0 +CLONE_FILESл65536ж0 +CLONE_FSл65536ж0 +CLONE_IOл65536ж0 +CLONE_NEWCGROUPл65536ж0 +CLONE_NEWIPCл65536ж0 +CLONE_NEWNETл65536ж0 +CLONE_NEWNSл65536ж0 +CLONE_NEWPIDл65536ж0 +CLONE_NEWUSERл65536ж0 +CLONE_NEWUTSл65536ж0 +CLONE_PARENTл65536ж0 +CLONE_PARENT_SETTIDл65536ж0 +CLONE_PTRACEл65536ж0 +CLONE_SETTLSл65536ж0 +CLONE_SIGHANDл65536ж0 +CLONE_SYSVSEMл65536ж0 +CLONE_THREADл65536ж0 +CLONE_UNTRACEDл65536ж0 +CLONE_VFORKл65536ж0 +CLONE_VMл65536ж0 +CMINл65536ж0 +CMSG_ALIGNл131072м(len)ж0 +CMSG_DATAл131072м(cmsg)ж0 +CMSG_FIRSTHDRл131072м(mhdr)ж0 +CMSG_LENл131072м(len)ж0 +CMSG_NXTHDRл131072м(mhdr,cmsg)ж0 +CMSG_SPACEл131072м(len)ж0 +CMSPARл65536ж0 +COLL_WEIGHTS_MAXл65536ж0 +CPU_ALLOCл131072м(count)ж0 +CPU_ALLOC_SIZEл131072м(count)ж0 +CPU_ANDл131072м(destset,srcset1,srcset2)ж0 +CPU_AND_Sл131072м(setsize,destset,srcset1,srcset2)ж0 +CPU_CLRл131072м(cpu,cpusetp)ж0 +CPU_CLR_Sл131072м(cpu,setsize,cpusetp)ж0 +CPU_COUNTл131072м(cpusetp)ж0 +CPU_COUNT_Sл131072м(setsize,cpusetp)ж0 +CPU_EQUALл131072м(cpusetp1,cpusetp2)ж0 +CPU_EQUAL_Sл131072м(setsize,cpusetp1,cpusetp2)ж0 +CPU_FREEл131072м(cpuset)ж0 +CPU_ISSETл131072м(cpu,cpusetp)ж0 +CPU_ISSET_Sл131072м(cpu,setsize,cpusetp)ж0 +CPU_ORл131072м(destset,srcset1,srcset2)ж0 +CPU_OR_Sл131072м(setsize,destset,srcset1,srcset2)ж0 +CPU_SETл131072м(cpu,cpusetp)ж0 +CPU_SETSIZEл65536ж0 +CPU_SET_Sл131072м(cpu,setsize,cpusetp)ж0 +CPU_XORл131072м(destset,srcset1,srcset2)ж0 +CPU_XOR_Sл131072м(setsize,destset,srcset1,srcset2)ж0 +CPU_ZEROл131072м(cpusetp)ж0 +CPU_ZERO_Sл131072м(setsize,cpusetp)ж0 +CQUITл65536ж0 +CR0л65536ж0 +CR1л65536ж0 +CR2л65536ж0 +CR3л65536ж0 +CRDLYл65536ж0 +CREADл65536ж0 +CREPRINTл65536ж0 +CRPRNTл65536ж0 +CRTSCTSл65536ж0 +CS5л65536ж0 +CS6л65536ж0 +CS7л65536ж0 +CS8л65536ж0 +CSIGNALл65536ж0 +CSIZEл65536ж0 +CSTARTл65536ж0 +CSTATUSл65536ж0 +CSTOPл65536ж0 +CSTOPBл65536ж0 +CSUSPл65536ж0 +CTIMEл65536ж0 +CTRLл131072м(x)ж0 +CWERASEл65536ж0 +DBGл131072м(...)ж0 +DBL_EPSILONл65536ж0 +DEFAULT_PORTл65536ж0 +DEFFILEMODEл65536ж0 +DELAYTIMER_MAXл65536ж0 +DN_ACCESSл65536ж0 +DN_ATTRIBл65536ж0 +DN_CREATEл65536ж0 +DN_DELETEл65536ж0 +DN_MODIFYл65536ж0 +DN_MULTISHOTл65536ж0 +DN_RENAMEл65536ж0 +DOMAINл65536ж0 +E2BIGл65536ж0 +EACCESл65536ж0 +EADDRINUSEл65536ж0 +EADDRNOTAVAILл65536ж0 +EADVл65536ж0 +EAFNOSUPPORTл65536ж0 +EAGAINл65536ж0 +EAI_ADDRFAMILYл65536ж0 +EAI_AGAINл65536ж0 +EAI_ALLDONEл65536ж0 +EAI_BADFLAGSл65536ж0 +EAI_CANCELEDл65536ж0 +EAI_FAILл65536ж0 +EAI_FAMILYл65536ж0 +EAI_IDN_ENCODEл65536ж0 +EAI_INPROGRESSл65536ж0 +EAI_INTRл65536ж0 +EAI_MEMORYл65536ж0 +EAI_NODATAл65536ж0 +EAI_NONAMEл65536ж0 +EAI_NOTCANCELEDл65536ж0 +EAI_OVERFLOWл65536ж0 +EAI_SERVICEл65536ж0 +EAI_SOCKTYPEл65536ж0 +EAI_SYSTEMл65536ж0 +EALREADYл65536ж0 +EBADEл65536ж0 +EBADFл65536ж0 +EBADFDл65536ж0 +EBADMSGл65536ж0 +EBADRл65536ж0 +EBADRQCл65536ж0 +EBADSLTл65536ж0 +EBFONTл65536ж0 +EBUGл65536ж0 +EBUSYл65536ж0 +ECANCELEDл65536ж0 +ECHILDл65536ж0 +ECHOл65536ж0 +ECHOCTLл65536ж0 +ECHOEл65536ж0 +ECHOKл65536ж0 +ECHOKEл65536ж0 +ECHONLл65536ж0 +ECHOPRTл65536ж0 +ECHRNGл65536ж0 +ECOMMл65536ж0 +ECONNABORTEDл65536ж0 +ECONNREFUSEDл65536ж0 +ECONNRESETл65536ж0 +EDEADLKл65536ж0 +EDEADLOCKл65536ж0 +EDESTADDRREQл65536ж0 +EDOMл65536ж0 +EDOTDOTл65536ж0 +EDQUOTл65536ж0 +EEXISTл65536ж0 +EFAULTл65536ж0 +EFBIGл65536ж0 +EHOSTDOWNл65536ж0 +EHOSTUNREACHл65536ж0 +EHWPOISONл65536ж0 +EIDRMл65536ж0 +EILSEQл65536ж0 +EINPROGRESSл65536ж0 +EINTRл65536ж0 +EINVALл65536ж0 +EIOл65536ж0 +EISCONNл65536ж0 +EISDIRл65536ж0 +EISNAMл65536ж0 +EKEYEXPIREDл65536ж0 +EKEYREJECTEDл65536ж0 +EKEYREVOKEDл65536ж0 +EL2HLTл65536ж0 +EL2NSYNCл65536ж0 +EL3HLTл65536ж0 +EL3RSTл65536ж0 +ELIBACCл65536ж0 +ELIBBADл65536ж0 +ELIBEXECл65536ж0 +ELIBMAXл65536ж0 +ELIBSCNл65536ж0 +ELNRNGл65536ж0 +ELOOPл65536ж0 +EMEDIUMTYPEл65536ж0 +EMFILEл65536ж0 +EMLINKл65536ж0 +EMSGSIZEл65536ж0 +EMULTIHOPл65536ж0 +ENAMETOOLONGл65536ж0 +ENAVAILл65536ж0 +ENETDOWNл65536ж0 +ENETRESETл65536ж0 +ENETUNREACHл65536ж0 +ENFILEл65536ж0 +ENOANOл65536ж0 +ENOBUFSл65536ж0 +ENOCSIл65536ж0 +ENODATAл65536ж0 +ENODEVл65536ж0 +ENOENTл65536ж0 +ENOEXECл65536ж0 +ENOKEYл65536ж0 +ENOLCKл65536ж0 +ENOLINKл65536ж0 +ENOMEDIUMл65536ж0 +ENOMEMл65536ж0 +ENOMSGл65536ж0 +ENONETл65536ж0 +ENOPKGл65536ж0 +ENOPROTOOPTл65536ж0 +ENOSPCл65536ж0 +ENOSRл65536ж0 +ENOSTRл65536ж0 +ENOSYSл65536ж0 +ENOTBLKл65536ж0 +ENOTCONNл65536ж0 +ENOTDIRл65536ж0 +ENOTEMPTYл65536ж0 +ENOTNAMл65536ж0 +ENOTRECOVERABLEл65536ж0 +ENOTSOCKл65536ж0 +ENOTSUPл65536ж0 +ENOTTYл65536ж0 +ENOTUNIQл65536ж0 +ENXIOл65536ж0 +EOFл65536ж0 +EOPNOTSUPPл65536ж0 +EOVERFLOWл65536ж0 +EOWNERDEADл65536ж0 +EPERMл65536ж0 +EPFNOSUPPORTл65536ж0 +EPIPEл65536ж0 +EPROTOл65536ж0 +EPROTONOSUPPORTл65536ж0 +EPROTOTYPEл65536ж0 +ERANGEл65536ж0 +EREMCHGл65536ж0 +EREMOTEл65536ж0 +EREMOTEIOл65536ж0 +ERESTARTл65536ж0 +ERFKILLл65536ж0 +EROFSл65536ж0 +ERRл131072м(...)ж0 +ERRXл131072м(...)ж0 +ESHUTDOWNл65536ж0 +ESOCKTNOSUPPORTл65536ж0 +ESPIPEл65536ж0 +ESRCHл65536ж0 +ESRMNTл65536ж0 +ESTALEл65536ж0 +ESTRPIPEл65536ж0 +ETIMEл65536ж0 +ETIMEDOUTл65536ж0 +ETOOMANYREFSл65536ж0 +ETXTBSYл65536ж0 +EUCLEANл65536ж0 +EUNATCHл65536ж0 +EUSERSл65536ж0 +EWOULDBLOCKл65536ж0 +EXDEVл65536ж0 +EXFULLл65536ж0 +EXIT_FAILUREл65536ж0 +EXIT_SUCCESSл65536ж0 +EXPR_NEST_MAXл65536ж0 +EXTAл65536ж0 +EXTBл65536ж0 +EXTPROCл65536ж0 +FALLOC_FL_COLLAPSE_RANGEл65536ж0 +FALLOC_FL_INSERT_RANGEл65536ж0 +FALLOC_FL_KEEP_SIZEл65536ж0 +FALLOC_FL_NO_HIDE_STALEл65536ж0 +FALLOC_FL_PUNCH_HOLEл65536ж0 +FALLOC_FL_UNSHARE_RANGEл65536ж0 +FALLOC_FL_ZERO_RANGEл65536ж0 +FALSEл65536ж0 +FAPPENDл65536ж0 +FASYNCл65536ж0 +FD_CLOEXECл65536ж0 +FD_CLRл131072м(fd,fdsetp)ж0 +FD_ISSETл131072м(fd,fdsetp)ж0 +FD_SETл131072м(fd,fdsetp)ж0 +FD_SETSIZEл65536ж0 +FD_ZEROл131072м(fdsetp)ж0 +FF0л65536ж0 +FF1л65536ж0 +FFDLYл65536ж0 +FFSYNCл65536ж0 +FILENAME_MAXл65536ж0 +FIOASYNCл65536ж0 +FIOCLEXл65536ж0 +FIOGETOWNл65536ж0 +FIONBIOл65536ж0 +FIONCLEXл65536ж0 +FIONREADл65536ж0 +FIOQSIZEл65536ж0 +FIOSETOWNл65536ж0 +FLUSHOл65536ж0 +FNAMEл131072м()ж0 +FNDELAYл65536ж0 +FNONBLOCKл65536ж0 +FOPEN_MAXл65536ж0 +FPE_FLTDIVл65536ж0 +FPE_FLTINVл65536ж0 +FPE_FLTOVFл65536ж0 +FPE_FLTRESл65536ж0 +FPE_FLTSUBл65536ж0 +FPE_FLTUNDл65536ж0 +FPE_INTDIVл65536ж0 +FPE_INTOVFл65536ж0 +FP_ILOGB0л65536ж0 +FP_ILOGBNANл65536ж0 +FP_INFINITEл65536ж0 +FP_INT_DOWNWARDл65536ж0 +FP_INT_TONEARESTл65536ж0 +FP_INT_TONEARESTFROMZEROл65536ж0 +FP_INT_TOWARDZEROл65536ж0 +FP_INT_UPWARDл65536ж0 +FP_LLOGB0л65536ж0 +FP_LLOGBNANл65536ж0 +FP_NANл65536ж0 +FP_NORMALл65536ж0 +FP_SUBNORMALл65536ж0 +FP_XSTATE_MAGIC1л65536ж0 +FP_XSTATE_MAGIC2л65536ж0 +FP_XSTATE_MAGIC2_SIZEл65536ж0 +FP_ZEROл65536ж0 +FRAME_MAX_LENGTHл65536ж0 +FREEл131072м(ptr)ж0 +F_DUPFDл65536ж0 +F_DUPFD_CLOEXECл65536ж0 +F_EXLCKл65536ж0 +F_GETFDл65536ж0 +F_GETFLл65536ж0 +F_GETLEASEл65536ж0 +F_GETLKл65536ж0 +F_GETLK64л65536ж0 +F_GETOWNл65536ж0 +F_GETOWN_EXл65536ж0 +F_GETPIPE_SZл65536ж0 +F_GETSIGл65536ж0 +F_LOCKл65536ж0 +F_NOTIFYл65536ж0 +F_OFD_GETLKл65536ж0 +F_OFD_SETLKл65536ж0 +F_OFD_SETLKWл65536ж0 +F_OKл65536ж0 +F_RDLCKл65536ж0 +F_SETFDл65536ж0 +F_SETFLл65536ж0 +F_SETLEASEл65536ж0 +F_SETLKл65536ж0 +F_SETLK64л65536ж0 +F_SETLKWл65536ж0 +F_SETLKW64л65536ж0 +F_SETOWNл65536ж0 +F_SETOWN_EXл65536ж0 +F_SETPIPE_SZл65536ж0 +F_SETSIGл65536ж0 +F_SHLCKл65536ж0 +F_TESTл65536ж0 +F_TLOCKл65536ж0 +F_ULOCKл65536ж0 +F_UNLCKл65536ж0 +F_WRLCKл65536ж0 +Flogл16384ж0оFILE * +Gл16384ж0оglob_pars +GAI_NOWAITл65536ж0 +GAI_WAITл65536ж0 +GPл16384ж0оglob_pars * +GPл32768ж0оglob_pars * +GREENл65536ж0 +GROUP_FILTER_SIZEл131072м(numsrc)ж0 +Gdefaultл16384ж0оglob_pars const +HOST_NAME_MAXл65536ж0 +HOST_NOT_FOUNDл65536ж0 +HUGEл65536ж0 +HUGE_VALл65536ж0 +HUGE_VALFл65536ж0 +HUGE_VALLл65536ж0 +HUGE_VAL_F128л65536ж0 +HUPCLл65536ж0 +ICANONл65536ж0 +ICRNLл65536ж0 +IEXTENл65536ж0 +IGNBRKл65536ж0 +IGNCRл65536ж0 +IGNPARл65536ж0 +ILL_BADSTKл65536ж0 +ILL_COPROCл65536ж0 +ILL_ILLADRл65536ж0 +ILL_ILLOPCл65536ж0 +ILL_ILLOPNл65536ж0 +ILL_ILLTRPл65536ж0 +ILL_PRVOPCл65536ж0 +ILL_PRVREGл65536ж0 +IMAXBELл65536ж0 +IN6ADDR_ANY_INITл65536ж0 +IN6ADDR_LOOPBACK_INITл65536ж0 +IN6_ARE_ADDR_EQUALл131072м(a,b)ж0 +IN6_IS_ADDR_LINKLOCALл131072м(a)ж0 +IN6_IS_ADDR_LOOPBACKл131072м(a)ж0 +IN6_IS_ADDR_MC_GLOBALл131072м(a)ж0 +IN6_IS_ADDR_MC_LINKLOCALл131072м(a)ж0 +IN6_IS_ADDR_MC_NODELOCALл131072м(a)ж0 +IN6_IS_ADDR_MC_ORGLOCALл131072м(a)ж0 +IN6_IS_ADDR_MC_SITELOCALл131072м(a)ж0 +IN6_IS_ADDR_MULTICASTл131072м(a)ж0 +IN6_IS_ADDR_SITELOCALл131072м(a)ж0 +IN6_IS_ADDR_UNSPECIFIEDл131072м(a)ж0 +IN6_IS_ADDR_V4COMPATл131072м(a)ж0 +IN6_IS_ADDR_V4MAPPEDл131072м(a)ж0 +INADDR_ALLHOSTS_GROUPл65536ж0 +INADDR_ALLRTRS_GROUPл65536ж0 +INADDR_ANYл65536ж0 +INADDR_BROADCASTл65536ж0 +INADDR_LOOPBACKл65536ж0 +INADDR_MAX_LOCAL_GROUPл65536ж0 +INADDR_NONEл65536ж0 +INADDR_UNSPEC_GROUPл65536ж0 +INET6_ADDRSTRLENл65536ж0 +INET_ADDRSTRLENл65536ж0 +INFINITYл65536ж0 +INLCRл65536ж0 +INPCKл65536ж0 +INT16_Cл131072м(c)ж0 +INT16_MAXл65536ж0 +INT16_MINл65536ж0 +INT16_WIDTHл65536ж0 +INT32_Cл131072м(c)ж0 +INT32_MAXл65536ж0 +INT32_MINл65536ж0 +INT32_WIDTHл65536ж0 +INT64_Cл131072м(c)ж0 +INT64_MAXл65536ж0 +INT64_MINл65536ж0 +INT64_WIDTHл65536ж0 +INT8_Cл131072м(c)ж0 +INT8_MAXл65536ж0 +INT8_MINл65536ж0 +INT8_WIDTHл65536ж0 +INTMAX_Cл131072м(c)ж0 +INTMAX_MAXл65536ж0 +INTMAX_MINл65536ж0 +INTMAX_WIDTHл65536ж0 +INTPTR_MAXл65536ж0 +INTPTR_MINл65536ж0 +INTPTR_WIDTHл65536ж0 +INT_FAST16_MAXл65536ж0 +INT_FAST16_MINл65536ж0 +INT_FAST16_WIDTHл65536ж0 +INT_FAST32_MAXл65536ж0 +INT_FAST32_MINл65536ж0 +INT_FAST32_WIDTHл65536ж0 +INT_FAST64_MAXл65536ж0 +INT_FAST64_MINл65536ж0 +INT_FAST64_WIDTHл65536ж0 +INT_FAST8_MAXл65536ж0 +INT_FAST8_MINл65536ж0 +INT_FAST8_WIDTHл65536ж0 +INT_LEAST16_MAXл65536ж0 +INT_LEAST16_MINл65536ж0 +INT_LEAST16_WIDTHл65536ж0 +INT_LEAST32_MAXл65536ж0 +INT_LEAST32_MINл65536ж0 +INT_LEAST32_WIDTHл65536ж0 +INT_LEAST64_MAXл65536ж0 +INT_LEAST64_MINл65536ж0 +INT_LEAST64_WIDTHл65536ж0 +INT_LEAST8_MAXл65536ж0 +INT_LEAST8_MINл65536ж0 +INT_LEAST8_WIDTHл65536ж0 +INT_MAXл65536ж0 +INT_MINл65536ж0 +INT_WIDTHл65536ж0 +IN_BADCLASSл131072м(a)ж0 +IN_CLASSAл131072м(a)ж0 +IN_CLASSA_HOSTл65536ж0 +IN_CLASSA_MAXл65536ж0 +IN_CLASSA_NETл65536ж0 +IN_CLASSA_NSHIFTл65536ж0 +IN_CLASSBл131072м(a)ж0 +IN_CLASSB_HOSTл65536ж0 +IN_CLASSB_MAXл65536ж0 +IN_CLASSB_NETл65536ж0 +IN_CLASSB_NSHIFTл65536ж0 +IN_CLASSCл131072м(a)ж0 +IN_CLASSC_HOSTл65536ж0 +IN_CLASSC_NETл65536ж0 +IN_CLASSC_NSHIFTл65536ж0 +IN_CLASSDл131072м(a)ж0 +IN_EXPERIMENTALл131072м(a)ж0 +IN_LOOPBACKNETл65536ж0 +IN_MULTICASTл131072м(a)ж0 +IOCSIZE_MASKл65536ж0 +IOCSIZE_SHIFTл65536ж0 +IOC_INл65536ж0 +IOC_INOUTл65536ж0 +IOC_OUTл65536ж0 +IOV_MAXл65536ж0 +IPPORT_RESERVEDл65536ж0 +IPPROTO_AHл65536ж0 +IPPROTO_BEETPHл65536ж0 +IPPROTO_COMPл65536ж0 +IPPROTO_DCCPл65536ж0 +IPPROTO_DSTOPTSл65536ж0 +IPPROTO_EGPл65536ж0 +IPPROTO_ENCAPл65536ж0 +IPPROTO_ESPл65536ж0 +IPPROTO_FRAGMENTл65536ж0 +IPPROTO_GREл65536ж0 +IPPROTO_HOPOPTSл65536ж0 +IPPROTO_ICMPл65536ж0 +IPPROTO_ICMPV6л65536ж0 +IPPROTO_IDPл65536ж0 +IPPROTO_IGMPл65536ж0 +IPPROTO_IPл65536ж0 +IPPROTO_IPIPл65536ж0 +IPPROTO_IPV6л65536ж0 +IPPROTO_MHл65536ж0 +IPPROTO_MPLSл65536ж0 +IPPROTO_MTPл65536ж0 +IPPROTO_NONEл65536ж0 +IPPROTO_PIMл65536ж0 +IPPROTO_PUPл65536ж0 +IPPROTO_RAWл65536ж0 +IPPROTO_ROUTINGл65536ж0 +IPPROTO_RSVPл65536ж0 +IPPROTO_SCTPл65536ж0 +IPPROTO_TCPл65536ж0 +IPPROTO_TPл65536ж0 +IPPROTO_UDPл65536ж0 +IPPROTO_UDPLITEл65536ж0 +IPV6_2292DSTOPTSл65536ж0 +IPV6_2292HOPLIMITл65536ж0 +IPV6_2292HOPOPTSл65536ж0 +IPV6_2292PKTINFOл65536ж0 +IPV6_2292PKTOPTIONSл65536ж0 +IPV6_2292RTHDRл65536ж0 +IPV6_ADDRFORMл65536ж0 +IPV6_ADDR_PREFERENCESл65536ж0 +IPV6_ADD_MEMBERSHIPл65536ж0 +IPV6_AUTHHDRл65536ж0 +IPV6_AUTOFLOWLABELл65536ж0 +IPV6_CHECKSUMл65536ж0 +IPV6_DONTFRAGл65536ж0 +IPV6_DROP_MEMBERSHIPл65536ж0 +IPV6_DSTOPTSл65536ж0 +IPV6_HDRINCLл65536ж0 +IPV6_HOPLIMITл65536ж0 +IPV6_HOPOPTSл65536ж0 +IPV6_IPSEC_POLICYл65536ж0 +IPV6_JOIN_ANYCASTл65536ж0 +IPV6_JOIN_GROUPл65536ж0 +IPV6_LEAVE_ANYCASTл65536ж0 +IPV6_LEAVE_GROUPл65536ж0 +IPV6_MINHOPCOUNTл65536ж0 +IPV6_MTUл65536ж0 +IPV6_MTU_DISCOVERл65536ж0 +IPV6_MULTICAST_HOPSл65536ж0 +IPV6_MULTICAST_IFл65536ж0 +IPV6_MULTICAST_LOOPл65536ж0 +IPV6_NEXTHOPл65536ж0 +IPV6_ORIGDSTADDRл65536ж0 +IPV6_PATHMTUл65536ж0 +IPV6_PKTINFOл65536ж0 +IPV6_PMTUDISC_DOл65536ж0 +IPV6_PMTUDISC_DONTл65536ж0 +IPV6_PMTUDISC_INTERFACEл65536ж0 +IPV6_PMTUDISC_OMITл65536ж0 +IPV6_PMTUDISC_PROBEл65536ж0 +IPV6_PMTUDISC_WANTл65536ж0 +IPV6_RECVDSTOPTSл65536ж0 +IPV6_RECVERRл65536ж0 +IPV6_RECVFRAGSIZEл65536ж0 +IPV6_RECVHOPLIMITл65536ж0 +IPV6_RECVHOPOPTSл65536ж0 +IPV6_RECVORIGDSTADDRл65536ж0 +IPV6_RECVPATHMTUл65536ж0 +IPV6_RECVPKTINFOл65536ж0 +IPV6_RECVRTHDRл65536ж0 +IPV6_RECVTCLASSл65536ж0 +IPV6_ROUTER_ALERTл65536ж0 +IPV6_RTHDRл65536ж0 +IPV6_RTHDRDSTOPTSл65536ж0 +IPV6_RTHDR_LOOSEл65536ж0 +IPV6_RTHDR_STRICTл65536ж0 +IPV6_RTHDR_TYPE_0л65536ж0 +IPV6_RXDSTOPTSл65536ж0 +IPV6_RXHOPOPTSл65536ж0 +IPV6_TCLASSл65536ж0 +IPV6_TRANSPARENTл65536ж0 +IPV6_UNICAST_HOPSл65536ж0 +IPV6_UNICAST_IFл65536ж0 +IPV6_V6ONLYл65536ж0 +IPV6_XFRM_POLICYл65536ж0 +IP_ADD_MEMBERSHIPл65536ж0 +IP_ADD_SOURCE_MEMBERSHIPл65536ж0 +IP_BIND_ADDRESS_NO_PORTл65536ж0 +IP_BLOCK_SOURCEл65536ж0 +IP_CHECKSUMл65536ж0 +IP_DEFAULT_MULTICAST_LOOPл65536ж0 +IP_DEFAULT_MULTICAST_TTLл65536ж0 +IP_DROP_MEMBERSHIPл65536ж0 +IP_DROP_SOURCE_MEMBERSHIPл65536ж0 +IP_FREEBINDл65536ж0 +IP_HDRINCLл65536ж0 +IP_IPSEC_POLICYл65536ж0 +IP_MAX_MEMBERSHIPSл65536ж0 +IP_MINTTLл65536ж0 +IP_MSFILTERл65536ж0 +IP_MSFILTER_SIZEл131072м(numsrc)ж0 +IP_MTUл65536ж0 +IP_MTU_DISCOVERл65536ж0 +IP_MULTICAST_ALLл65536ж0 +IP_MULTICAST_IFл65536ж0 +IP_MULTICAST_LOOPл65536ж0 +IP_MULTICAST_TTLл65536ж0 +IP_NODEFRAGл65536ж0 +IP_OPTIONSл65536ж0 +IP_ORIGDSTADDRл65536ж0 +IP_PASSSECл65536ж0 +IP_PKTINFOл65536ж0 +IP_PKTOPTIONSл65536ж0 +IP_PMTUDISCл65536ж0 +IP_PMTUDISC_DOл65536ж0 +IP_PMTUDISC_DONTл65536ж0 +IP_PMTUDISC_INTERFACEл65536ж0 +IP_PMTUDISC_OMITл65536ж0 +IP_PMTUDISC_PROBEл65536ж0 +IP_PMTUDISC_WANTл65536ж0 +IP_RECVERRл65536ж0 +IP_RECVFRAGSIZEл65536ж0 +IP_RECVOPTSл65536ж0 +IP_RECVORIGDSTADDRл65536ж0 +IP_RECVRETOPTSл65536ж0 +IP_RECVTOSл65536ж0 +IP_RECVTTLл65536ж0 +IP_RETOPTSл65536ж0 +IP_ROUTER_ALERTл65536ж0 +IP_TOSл65536ж0 +IP_TRANSPARENTл65536ж0 +IP_TTLл65536ж0 +IP_UNBLOCK_SOURCEл65536ж0 +IP_UNICAST_IFл65536ж0 +IP_XFRM_POLICYл65536ж0 +ISIGл65536ж0 +ISTRIPл65536ж0 +ITIMER_PROFл65536ж0 +ITIMER_REALл65536ж0 +ITIMER_VIRTUALл65536ж0 +IUCLCл65536ж0 +IUTF8л65536ж0 +IXANYл65536ж0 +IXOFFл65536ж0 +IXONл65536ж0 +LC_ADDRESSл65536ж0 +LC_ADDRESS_MASKл65536ж0 +LC_ALLл65536ж0 +LC_ALL_MASKл65536ж0 +LC_COLLATEл65536ж0 +LC_COLLATE_MASKл65536ж0 +LC_CTYPEл65536ж0 +LC_CTYPE_MASKл65536ж0 +LC_GLOBAL_LOCALEл65536ж0 +LC_IDENTIFICATIONл65536ж0 +LC_IDENTIFICATION_MASKл65536ж0 +LC_MEASUREMENTл65536ж0 +LC_MEASUREMENT_MASKл65536ж0 +LC_MESSAGESл65536ж0 +LC_MESSAGES_MASKл65536ж0 +LC_MONETARYл65536ж0 +LC_MONETARY_MASKл65536ж0 +LC_NAMEл65536ж0 +LC_NAME_MASKл65536ж0 +LC_NUMERICл65536ж0 +LC_NUMERIC_MASKл65536ж0 +LC_PAPERл65536ж0 +LC_PAPER_MASKл65536ж0 +LC_TELEPHONEл65536ж0 +LC_TELEPHONE_MASKл65536ж0 +LC_TIMEл65536ж0 +LC_TIME_MASKл65536ж0 +LINE_MAXл65536ж0 +LINK_MAXл65536ж0 +LITTLE_ENDIANл65536ж0 +LLONG_MAXл65536ж0 +LLONG_MINл65536ж0 +LLONG_WIDTHл65536ж0 +LOCK_EXл65536ж0 +LOCK_MANDл65536ж0 +LOCK_NBл65536ж0 +LOCK_READл65536ж0 +LOCK_RWл65536ж0 +LOCK_SHл65536ж0 +LOCK_UNл65536ж0 +LOCK_WRITEл65536ж0 +LOGIN_NAME_MAXл65536ж0 +LONG_BITл65536ж0 +LONG_LONG_MAXл65536ж0 +LONG_LONG_MINл65536ж0 +LONG_MAXл65536ж0 +LONG_MINл65536ж0 +LONG_WIDTHл65536ж0 +LT_OBJDIRл65536ж0 +L_INCRл65536ж0 +L_SETл65536ж0 +L_XTNDл65536ж0 +L_ctermidл65536ж0 +L_cuseridл65536ж0 +L_tmpnamл65536ж0 +MADV_DODUMPл65536ж0 +MADV_DOFORKл65536ж0 +MADV_DONTDUMPл65536ж0 +MADV_DONTFORKл65536ж0 +MADV_DONTNEEDл65536ж0 +MADV_FREEл65536ж0 +MADV_HUGEPAGEл65536ж0 +MADV_HWPOISONл65536ж0 +MADV_MERGEABLEл65536ж0 +MADV_NOHUGEPAGEл65536ж0 +MADV_NORMALл65536ж0 +MADV_RANDOMл65536ж0 +MADV_REMOVEл65536ж0 +MADV_SEQUENTIALл65536ж0 +MADV_UNMERGEABLEл65536ж0 +MADV_WILLNEEDл65536ж0 +MALLOCл131072м(type,size)ж0 +MAP_32BITл65536ж0 +MAP_ANONл65536ж0 +MAP_ANONYMOUSл65536ж0 +MAP_DENYWRITEл65536ж0 +MAP_EXECUTABLEл65536ж0 +MAP_FAILEDл65536ж0 +MAP_FILEл65536ж0 +MAP_FIXEDл65536ж0 +MAP_GROWSDOWNл65536ж0 +MAP_HUGETLBл65536ж0 +MAP_HUGE_MASKл65536ж0 +MAP_HUGE_SHIFTл65536ж0 +MAP_LOCKEDл65536ж0 +MAP_NONBLOCKл65536ж0 +MAP_NORESERVEл65536ж0 +MAP_POPULATEл65536ж0 +MAP_PRIVATEл65536ж0 +MAP_SHAREDл65536ж0 +MAP_STACKл65536ж0 +MAP_TYPEл65536ж0 +MATH_ERREXCEPTл65536ж0 +MATH_ERRNOл65536ж0 +MAX_CANONл65536ж0 +MAX_HANDLE_SZл65536ж0 +MAX_INPUTл65536ж0 +MAX_MEMORY_DUMP_SIZEл65536ж0 +MB_CUR_MAXл65536ж0 +MB_LEN_MAXл65536ж0 +MCAST_BLOCK_SOURCEл65536ж0 +MCAST_EXCLUDEл65536ж0 +MCAST_INCLUDEл65536ж0 +MCAST_JOIN_GROUPл65536ж0 +MCAST_JOIN_SOURCE_GROUPл65536ж0 +MCAST_LEAVE_GROUPл65536ж0 +MCAST_LEAVE_SOURCE_GROUPл65536ж0 +MCAST_MSFILTERл65536ж0 +MCAST_UNBLOCK_SOURCEл65536ж0 +MCL_CURRENTл65536ж0 +MCL_FUTUREл65536ж0 +MCL_ONFAULTл65536ж0 +MINSIGSTKSZл65536ж0 +MOD_CLKAл65536ж0 +MOD_CLKBл65536ж0 +MOD_ESTERRORл65536ж0 +MOD_FREQUENCYл65536ж0 +MOD_MAXERRORл65536ж0 +MOD_MICROл65536ж0 +MOD_NANOл65536ж0 +MOD_OFFSETл65536ж0 +MOD_STATUSл65536ж0 +MOD_TAIл65536ж0 +MOD_TIMECONSTл65536ж0 +MQ_PRIO_MAXл65536ж0 +MREMAP_FIXEDл65536ж0 +MREMAP_MAYMOVEл65536ж0 +MSG_BATCHл65536ж0 +MSG_CMSG_CLOEXECл65536ж0 +MSG_CONFIRMл65536ж0 +MSG_CTRUNCл65536ж0 +MSG_DONTROUTEл65536ж0 +MSG_DONTWAITл65536ж0 +MSG_EORл65536ж0 +MSG_ERRQUEUEл65536ж0 +MSG_FASTOPENл65536ж0 +MSG_FINл65536ж0 +MSG_MOREл65536ж0 +MSG_NOSIGNALл65536ж0 +MSG_OOBл65536ж0 +MSG_PEEKл65536ж0 +MSG_PROXYл65536ж0 +MSG_RSTл65536ж0 +MSG_SYNл65536ж0 +MSG_TRUNCл65536ж0 +MSG_TRYHARDл65536ж0 +MSG_WAITALLл65536ж0 +MSG_WAITFORONEл65536ж0 +MS_ASYNCл65536ж0 +MS_INVALIDATEл65536ж0 +MS_SYNCл65536ж0 +MULT_PARл4нanon_enum_1ж0 +M_1_PIл65536ж0 +M_1_PIf128л65536ж0 +M_1_PIlл65536ж0 +M_2_PIл65536ж0 +M_2_PIf128л65536ж0 +M_2_PIlл65536ж0 +M_2_SQRTPIл65536ж0 +M_2_SQRTPIf128л65536ж0 +M_2_SQRTPIlл65536ж0 +M_Eл65536ж0 +M_Ef128л65536ж0 +M_Elл65536ж0 +M_LN10л65536ж0 +M_LN10f128л65536ж0 +M_LN10lл65536ж0 +M_LN2л65536ж0 +M_LN2f128л65536ж0 +M_LN2lл65536ж0 +M_LOG10Eл65536ж0 +M_LOG10Ef128л65536ж0 +M_LOG10Elл65536ж0 +M_LOG2Eл65536ж0 +M_LOG2Ef128л65536ж0 +M_LOG2Elл65536ж0 +M_PIл65536ж0 +M_PI_2л65536ж0 +M_PI_2f128л65536ж0 +M_PI_2lл65536ж0 +M_PI_4л65536ж0 +M_PI_4f128л65536ж0 +M_PI_4lл65536ж0 +M_PIf128л65536ж0 +M_PIlл65536ж0 +M_SQRT1_2л65536ж0 +M_SQRT1_2f128л65536ж0 +M_SQRT1_2lл65536ж0 +M_SQRT2л65536ж0 +M_SQRT2f128л65536ж0 +M_SQRT2lл65536ж0 +My_mmapл16м(char *filename)ж0оmmapbuf * +My_mmapл1024м(char *filename)ж0оmmapbuf * +My_munmapл16м(mmapbuf *b)ж0оvoid +My_munmapл1024м(mmapbuf *b)ж0оvoid +NAME_MAXл65536ж0 +NANл65536ж0 +NCCл65536ж0 +NCCSл65536ж0 +NEED_ARGл4нanon_enum_1ж0 +NETDB_INTERNALл65536ж0 +NETDB_SUCCESSл65536ж0 +NFDBITSл65536ж0 +NGREGл65536ж0 +NGROUPS_MAXл65536ж0 +NI_DGRAMл65536ж0 +NI_IDNл65536ж0 +NI_IDN_ALLOW_UNASSIGNEDл65536ж0 +NI_IDN_USE_STD3_ASCII_RULESл65536ж0 +NI_MAXHOSTл65536ж0 +NI_MAXSERVл65536ж0 +NI_NAMEREQDл65536ж0 +NI_NOFQDNл65536ж0 +NI_NUMERICHOSTл65536ж0 +NI_NUMERICSERVл65536ж0 +NL0л65536ж0 +NL1л65536ж0 +NLDLYл65536ж0 +NL_ARGMAXл65536ж0 +NL_LANGMAXл65536ж0 +NL_MSGMAXл65536ж0 +NL_NMAXл65536ж0 +NL_SETMAXл65536ж0 +NL_TEXTMAXл65536ж0 +NOFLSHл65536ж0 +NO_ADDRESSл65536ж0 +NO_ARGSл4нanon_enum_1ж0 +NO_DATAл65536ж0 +NO_RECOVERYл65536ж0 +NR_OPENл65536ж0 +NSIGл65536ж0 +NULLл65536ж0 +NZEROл65536ж0 +N_л131072м(String)ж0 +N_6PACKл65536ж0 +N_AX25л65536ж0 +N_HCIл65536ж0 +N_HDLCл65536ж0 +N_IRDAл65536ж0 +N_MASCл65536ж0 +N_MOUSEл65536ж0 +N_PPPл65536ж0 +N_PROFIBUS_FDLл65536ж0 +N_R3964л65536ж0 +N_SLIPл65536ж0 +N_SMSBLOCKл65536ж0 +N_STRIPл65536ж0 +N_SYNC_PPPл65536ж0 +N_TTYл65536ж0 +N_X25л65536ж0 +OCRNLл65536ж0 +OFDELл65536ж0 +OFILLл65536ж0 +OLCUCл65536ж0 +OLDCOLORл65536ж0 +ONLCRл65536ж0 +ONLRETл65536ж0 +ONOCRл65536ж0 +OPEN_MAXл65536ж0 +OPOSTл65536ж0 +OPT_ARGл4нanon_enum_1ж0 +OVERFLOWл65536ж0 +O_ACCMODEл65536ж0 +O_APPENDл65536ж0 +O_ASYNCл65536ж0 +O_CLOEXECл65536ж0 +O_CREATл65536ж0 +O_DIRECTл65536ж0 +O_DIRECTORYл65536ж0 +O_DSYNCл65536ж0 +O_EXCLл65536ж0 +O_FSYNCл65536ж0 +O_LARGEFILEл65536ж0 +O_NDELAYл65536ж0 +O_NOATIMEл65536ж0 +O_NOCTTYл65536ж0 +O_NOFOLLOWл65536ж0 +O_NONBLOCKл65536ж0 +O_PATHл65536ж0 +O_RDONLYл65536ж0 +O_RDWRл65536ж0 +O_RSYNCл65536ж0 +O_SYNCл65536ж0 +O_TMPFILEл65536ж0 +O_TRUNCл65536ж0 +O_WRONLYл65536ж0 +PARENBл65536ж0 +PARMRKл65536ж0 +PARODDл65536ж0 +PATH_MAXл65536ж0 +PDP_ENDIANл65536ж0 +PENDINл65536ж0 +PF_ALGл65536ж0 +PF_APPLETALKл65536ж0 +PF_ASHл65536ж0 +PF_ATMPVCл65536ж0 +PF_ATMSVCл65536ж0 +PF_AX25л65536ж0 +PF_BLUETOOTHл65536ж0 +PF_BRIDGEл65536ж0 +PF_CAIFл65536ж0 +PF_CANл65536ж0 +PF_DECnetл65536ж0 +PF_ECONETл65536ж0 +PF_FILEл65536ж0 +PF_IBл65536ж0 +PF_IEEE802154л65536ж0 +PF_INETл65536ж0 +PF_INET6л65536ж0 +PF_IPXл65536ж0 +PF_IRDAл65536ж0 +PF_ISDNл65536ж0 +PF_IUCVл65536ж0 +PF_KCMл65536ж0 +PF_KEYл65536ж0 +PF_LLCл65536ж0 +PF_LOCALл65536ж0 +PF_MAXл65536ж0 +PF_MPLSл65536ж0 +PF_NETBEUIл65536ж0 +PF_NETLINKл65536ж0 +PF_NETROMл65536ж0 +PF_NFCл65536ж0 +PF_PACKETл65536ж0 +PF_PHONETл65536ж0 +PF_PPPOXл65536ж0 +PF_QIPCRTRл65536ж0 +PF_RDSл65536ж0 +PF_ROSEл65536ж0 +PF_ROUTEл65536ж0 +PF_RXRPCл65536ж0 +PF_SECURITYл65536ж0 +PF_SMCл65536ж0 +PF_SNAл65536ж0 +PF_TIPCл65536ж0 +PF_UNIXл65536ж0 +PF_UNSPECл65536ж0 +PF_VSOCKл65536ж0 +PF_WANPIPEл65536ж0 +PF_X25л65536ж0 +PIPE_BUFл65536ж0 +PLOSSл65536ж0 +POLL_ERRл65536ж0 +POLL_HUPл65536ж0 +POLL_INл65536ж0 +POLL_MSGл65536ж0 +POLL_OUTл65536ж0 +POLL_PRIл65536ж0 +POSIX_FADV_DONTNEEDл65536ж0 +POSIX_FADV_NOREUSEл65536ж0 +POSIX_FADV_NORMALл65536ж0 +POSIX_FADV_RANDOMл65536ж0 +POSIX_FADV_SEQUENTIALл65536ж0 +POSIX_FADV_WILLNEEDл65536ж0 +POSIX_MADV_DONTNEEDл65536ж0 +POSIX_MADV_NORMALл65536ж0 +POSIX_MADV_RANDOMл65536ж0 +POSIX_MADV_SEQUENTIALл65536ж0 +POSIX_MADV_WILLNEEDл65536ж0 +PROT_EXECл65536ж0 +PROT_GROWSDOWNл65536ж0 +PROT_GROWSUPл65536ж0 +PROT_NONEл65536ж0 +PROT_READл65536ж0 +PROT_WRITEл65536ж0 +PR_CAPBSET_DROPл65536ж0 +PR_CAPBSET_READл65536ж0 +PR_CAP_AMBIENTл65536ж0 +PR_CAP_AMBIENT_CLEAR_ALLл65536ж0 +PR_CAP_AMBIENT_IS_SETл65536ж0 +PR_CAP_AMBIENT_LOWERл65536ж0 +PR_CAP_AMBIENT_RAISEл65536ж0 +PR_ENDIAN_BIGл65536ж0 +PR_ENDIAN_LITTLEл65536ж0 +PR_ENDIAN_PPC_LITTLEл65536ж0 +PR_FPEMU_NOPRINTл65536ж0 +PR_FPEMU_SIGFPEл65536ж0 +PR_FP_EXC_ASYNCл65536ж0 +PR_FP_EXC_DISABLEDл65536ж0 +PR_FP_EXC_DIVл65536ж0 +PR_FP_EXC_INVл65536ж0 +PR_FP_EXC_NONRECOVл65536ж0 +PR_FP_EXC_OVFл65536ж0 +PR_FP_EXC_PRECISEл65536ж0 +PR_FP_EXC_RESл65536ж0 +PR_FP_EXC_SW_ENABLEл65536ж0 +PR_FP_EXC_UNDл65536ж0 +PR_FP_MODE_FRл65536ж0 +PR_FP_MODE_FREл65536ж0 +PR_GET_CHILD_SUBREAPERл65536ж0 +PR_GET_DUMPABLEл65536ж0 +PR_GET_ENDIANл65536ж0 +PR_GET_FPEMUл65536ж0 +PR_GET_FPEXCл65536ж0 +PR_GET_FP_MODEл65536ж0 +PR_GET_KEEPCAPSл65536ж0 +PR_GET_NAMEл65536ж0 +PR_GET_NO_NEW_PRIVSл65536ж0 +PR_GET_PDEATHSIGл65536ж0 +PR_GET_SECCOMPл65536ж0 +PR_GET_SECUREBITSл65536ж0 +PR_GET_THP_DISABLEл65536ж0 +PR_GET_TID_ADDRESSл65536ж0 +PR_GET_TIMERSLACKл65536ж0 +PR_GET_TIMINGл65536ж0 +PR_GET_TSCл65536ж0 +PR_GET_UNALIGNл65536ж0 +PR_MCE_KILLл65536ж0 +PR_MCE_KILL_CLEARл65536ж0 +PR_MCE_KILL_DEFAULTл65536ж0 +PR_MCE_KILL_EARLYл65536ж0 +PR_MCE_KILL_GETл65536ж0 +PR_MCE_KILL_LATEл65536ж0 +PR_MCE_KILL_SETл65536ж0 +PR_MPX_DISABLE_MANAGEMENTл65536ж0 +PR_MPX_ENABLE_MANAGEMENTл65536ж0 +PR_SET_CHILD_SUBREAPERл65536ж0 +PR_SET_DUMPABLEл65536ж0 +PR_SET_ENDIANл65536ж0 +PR_SET_FPEMUл65536ж0 +PR_SET_FPEXCл65536ж0 +PR_SET_FP_MODEл65536ж0 +PR_SET_KEEPCAPSл65536ж0 +PR_SET_MMл65536ж0 +PR_SET_MM_ARG_ENDл65536ж0 +PR_SET_MM_ARG_STARTл65536ж0 +PR_SET_MM_AUXVл65536ж0 +PR_SET_MM_BRKл65536ж0 +PR_SET_MM_END_CODEл65536ж0 +PR_SET_MM_END_DATAл65536ж0 +PR_SET_MM_ENV_ENDл65536ж0 +PR_SET_MM_ENV_STARTл65536ж0 +PR_SET_MM_EXE_FILEл65536ж0 +PR_SET_MM_MAPл65536ж0 +PR_SET_MM_MAP_SIZEл65536ж0 +PR_SET_MM_START_BRKл65536ж0 +PR_SET_MM_START_CODEл65536ж0 +PR_SET_MM_START_DATAл65536ж0 +PR_SET_MM_START_STACKл65536ж0 +PR_SET_NAMEл65536ж0 +PR_SET_NO_NEW_PRIVSл65536ж0 +PR_SET_PDEATHSIGл65536ж0 +PR_SET_PTRACERл65536ж0 +PR_SET_PTRACER_ANYл65536ж0 +PR_SET_SECCOMPл65536ж0 +PR_SET_SECUREBITSл65536ж0 +PR_SET_THP_DISABLEл65536ж0 +PR_SET_TIMERSLACKл65536ж0 +PR_SET_TIMINGл65536ж0 +PR_SET_TSCл65536ж0 +PR_SET_UNALIGNл65536ж0 +PR_TASK_PERF_EVENTS_DISABLEл65536ж0 +PR_TASK_PERF_EVENTS_ENABLEл65536ж0 +PR_TIMING_STATISTICALл65536ж0 +PR_TIMING_TIMESTAMPл65536ж0 +PR_TSC_ENABLEл65536ж0 +PR_TSC_SIGSEGVл65536ж0 +PR_UNALIGN_NOPRINTл65536ж0 +PR_UNALIGN_SIGBUSл65536ж0 +PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NPл65536ж0 +PTHREAD_BARRIER_SERIAL_THREADл65536ж0 +PTHREAD_CANCELEDл65536ж0 +PTHREAD_CANCEL_ASYNCHRONOUSл4нanon_enum_18ж0 +PTHREAD_CANCEL_ASYNCHRONOUSл65536ж0 +PTHREAD_CANCEL_DEFERREDл4нanon_enum_18ж0 +PTHREAD_CANCEL_DEFERREDл65536ж0 +PTHREAD_CANCEL_DISABLEл4нanon_enum_17ж0 +PTHREAD_CANCEL_DISABLEл65536ж0 +PTHREAD_CANCEL_ENABLEл4нanon_enum_17ж0 +PTHREAD_CANCEL_ENABLEл65536ж0 +PTHREAD_COND_INITIALIZERл65536ж0 +PTHREAD_CREATE_DETACHEDл4нanon_enum_9ж0 +PTHREAD_CREATE_DETACHEDл65536ж0 +PTHREAD_CREATE_JOINABLEл4нanon_enum_9ж0 +PTHREAD_CREATE_JOINABLEл65536ж0 +PTHREAD_DESTRUCTOR_ITERATIONSл65536ж0 +PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NPл65536ж0 +PTHREAD_EXPLICIT_SCHEDл4нanon_enum_14ж0 +PTHREAD_EXPLICIT_SCHEDл65536ж0 +PTHREAD_INHERIT_SCHEDл4нanon_enum_14ж0 +PTHREAD_INHERIT_SCHEDл65536ж0 +PTHREAD_KEYS_MAXл65536ж0 +PTHREAD_MUTEX_ADAPTIVE_NPл4нanon_enum_10ж0 +PTHREAD_MUTEX_DEFAULTл4нanon_enum_10ж0 +PTHREAD_MUTEX_ERRORCHECKл4нanon_enum_10ж0 +PTHREAD_MUTEX_ERRORCHECK_NPл4нanon_enum_10ж0 +PTHREAD_MUTEX_FAST_NPл4нanon_enum_10ж0 +PTHREAD_MUTEX_INITIALIZERл65536ж0 +PTHREAD_MUTEX_NORMALл4нanon_enum_10ж0 +PTHREAD_MUTEX_RECURSIVEл4нanon_enum_10ж0 +PTHREAD_MUTEX_RECURSIVE_NPл4нanon_enum_10ж0 +PTHREAD_MUTEX_ROBUSTл4нanon_enum_11ж0 +PTHREAD_MUTEX_ROBUST_NPл4нanon_enum_11ж0 +PTHREAD_MUTEX_STALLEDл4нanon_enum_11ж0 +PTHREAD_MUTEX_STALLED_NPл4нanon_enum_11ж0 +PTHREAD_MUTEX_TIMED_NPл4нanon_enum_10ж0 +PTHREAD_ONCE_INITл65536ж0 +PTHREAD_PRIO_INHERITл4нanon_enum_12ж0 +PTHREAD_PRIO_NONEл4нanon_enum_12ж0 +PTHREAD_PRIO_PROTECTл4нanon_enum_12ж0 +PTHREAD_PROCESS_PRIVATEл4нanon_enum_16ж0 +PTHREAD_PROCESS_PRIVATEл65536ж0 +PTHREAD_PROCESS_SHAREDл4нanon_enum_16ж0 +PTHREAD_PROCESS_SHAREDл65536ж0 +PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NPл65536ж0 +PTHREAD_RWLOCK_DEFAULT_NPл4нanon_enum_13ж0 +PTHREAD_RWLOCK_INITIALIZERл65536ж0 +PTHREAD_RWLOCK_PREFER_READER_NPл4нanon_enum_13ж0 +PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NPл4нanon_enum_13ж0 +PTHREAD_RWLOCK_PREFER_WRITER_NPл4нanon_enum_13ж0 +PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NPл65536ж0 +PTHREAD_SCOPE_PROCESSл4нanon_enum_15ж0 +PTHREAD_SCOPE_PROCESSл65536ж0 +PTHREAD_SCOPE_SYSTEMл4нanon_enum_15ж0 +PTHREAD_SCOPE_SYSTEMл65536ж0 +PTHREAD_STACK_MINл65536ж0 +PTHREAD_THREADS_MAXл65536ж0 +PTRDIFF_MAXл65536ж0 +PTRDIFF_MINл65536ж0 +PTRDIFF_WIDTHл65536ж0 +P_tmpdirл65536ж0 +RAND_MAXл65536ж0 +REDл65536ж0 +REG_CR2л65536ж0 +REG_CSGSFSл65536ж0 +REG_EFLл65536ж0 +REG_ERRл65536ж0 +REG_OLDMASKл65536ж0 +REG_R10л65536ж0 +REG_R11л65536ж0 +REG_R12л65536ж0 +REG_R13л65536ж0 +REG_R14л65536ж0 +REG_R15л65536ж0 +REG_R8л65536ж0 +REG_R9л65536ж0 +REG_RAXл65536ж0 +REG_RBPл65536ж0 +REG_RBXл65536ж0 +REG_RCXл65536ж0 +REG_RDIл65536ж0 +REG_RDXл65536ж0 +REG_RIPл65536ж0 +REG_RSIл65536ж0 +REG_RSPл65536ж0 +REG_TRAPNOл65536ж0 +RE_DUP_MAXл65536ж0 +RTSIG_MAXл65536ж0 +R_OKл65536ж0 +SA_INTERRUPTл65536ж0 +SA_NOCLDSTOPл65536ж0 +SA_NOCLDWAITл65536ж0 +SA_NODEFERл65536ж0 +SA_NOMASKл65536ж0 +SA_ONESHOTл65536ж0 +SA_ONSTACKл65536ж0 +SA_RESETHANDл65536ж0 +SA_RESTARTл65536ж0 +SA_SIGINFOл65536ж0 +SA_STACKл65536ж0 +SCHAR_MAXл65536ж0 +SCHAR_MINл65536ж0 +SCHAR_WIDTHл65536ж0 +SCHED_BATCHл65536ж0 +SCHED_DEADLINEл65536ж0 +SCHED_FIFOл65536ж0 +SCHED_IDLEл65536ж0 +SCHED_ISOл65536ж0 +SCHED_OTHERл65536ж0 +SCHED_RESET_ON_FORKл65536ж0 +SCHED_RRл65536ж0 +SCM_CREDENTIALSл65536ж0 +SCM_RIGHTSл65536ж0 +SCM_SRCRTл65536ж0 +SCM_TIMESTAMPл65536ж0 +SCM_TIMESTAMPINGл65536ж0 +SCM_TIMESTAMPING_OPT_STATSл65536ж0 +SCM_TIMESTAMPING_PKTINFOл65536ж0 +SCM_TIMESTAMPNSл65536ж0 +SCM_WIFI_STATUSл65536ж0 +SCOPE_DELIMITERл65536ж0 +SEEK_CURл65536ж0 +SEEK_DATAл65536ж0 +SEEK_ENDл65536ж0 +SEEK_HOLEл65536ж0 +SEEK_SETл65536ж0 +SEGV_ACCERRл65536ж0 +SEGV_MAPERRл65536ж0 +SEM_VALUE_MAXл65536ж0 +SHRT_MAXл65536ж0 +SHRT_MINл65536ж0 +SHRT_WIDTHл65536ж0 +SHUT_RDл65536ж0 +SHUT_RDWRл65536ж0 +SHUT_WRл65536ж0 +SIGABRTл65536ж0 +SIGALRMл65536ж0 +SIGBUSл65536ж0 +SIGCHLDл65536ж0 +SIGCLDл65536ж0 +SIGCONTл65536ж0 +SIGEV_NONEл65536ж0 +SIGEV_SIGNALл65536ж0 +SIGEV_THREADл65536ж0 +SIGEV_THREAD_IDл65536ж0 +SIGFPEл65536ж0 +SIGHUPл65536ж0 +SIGILLл65536ж0 +SIGINTл65536ж0 +SIGIOл65536ж0 +SIGIOTл65536ж0 +SIGKILLл65536ж0 +SIGPIPEл65536ж0 +SIGPOLLл65536ж0 +SIGPROFл65536ж0 +SIGPWRл65536ж0 +SIGQUITл65536ж0 +SIGRTMAXл65536ж0 +SIGRTMINл65536ж0 +SIGSEGVл65536ж0 +SIGSTKFLTл65536ж0 +SIGSTKSZл65536ж0 +SIGSTOPл65536ж0 +SIGSYSл65536ж0 +SIGTERMл65536ж0 +SIGTRAPл65536ж0 +SIGTSTPл65536ж0 +SIGTTINл65536ж0 +SIGTTOUл65536ж0 +SIGURGл65536ж0 +SIGUSR1л65536ж0 +SIGUSR2л65536ж0 +SIGVTALRMл65536ж0 +SIGWINCHл65536ж0 +SIGXCPUл65536ж0 +SIGXFSZл65536ж0 +SIG_ATOMIC_MAXл65536ж0 +SIG_ATOMIC_MINл65536ж0 +SIG_ATOMIC_WIDTHл65536ж0 +SIG_BLOCKл65536ж0 +SIG_DFLл65536ж0 +SIG_ERRл65536ж0 +SIG_HOLDл65536ж0 +SIG_IGNл65536ж0 +SIG_SETMASKл65536ж0 +SIG_UNBLOCKл65536ж0 +SINGл65536ж0 +SIOCADDDLCIл65536ж0 +SIOCADDMULTIл65536ж0 +SIOCADDRTл65536ж0 +SIOCATMARKл65536ж0 +SIOCDARPл65536ж0 +SIOCDELDLCIл65536ж0 +SIOCDELMULTIл65536ж0 +SIOCDELRTл65536ж0 +SIOCDEVPRIVATEл65536ж0 +SIOCDIFADDRл65536ж0 +SIOCDRARPл65536ж0 +SIOCGARPл65536ж0 +SIOCGIFADDRл65536ж0 +SIOCGIFBRл65536ж0 +SIOCGIFBRDADDRл65536ж0 +SIOCGIFCONFл65536ж0 +SIOCGIFCOUNTл65536ж0 +SIOCGIFDSTADDRл65536ж0 +SIOCGIFENCAPл65536ж0 +SIOCGIFFLAGSл65536ж0 +SIOCGIFHWADDRл65536ж0 +SIOCGIFINDEXл65536ж0 +SIOCGIFMAPл65536ж0 +SIOCGIFMEMл65536ж0 +SIOCGIFMETRICл65536ж0 +SIOCGIFMTUл65536ж0 +SIOCGIFNAMEл65536ж0 +SIOCGIFNETMASKл65536ж0 +SIOCGIFPFLAGSл65536ж0 +SIOCGIFSLAVEл65536ж0 +SIOCGIFTXQLENл65536ж0 +SIOCGPGRPл65536ж0 +SIOCGRARPл65536ж0 +SIOCGSTAMPл65536ж0 +SIOCGSTAMPNSл65536ж0 +SIOCPROTOPRIVATEл65536ж0 +SIOCRTMSGл65536ж0 +SIOCSARPл65536ж0 +SIOCSIFADDRл65536ж0 +SIOCSIFBRл65536ж0 +SIOCSIFBRDADDRл65536ж0 +SIOCSIFDSTADDRл65536ж0 +SIOCSIFENCAPл65536ж0 +SIOCSIFFLAGSл65536ж0 +SIOCSIFHWADDRл65536ж0 +SIOCSIFHWBROADCASTл65536ж0 +SIOCSIFLINKл65536ж0 +SIOCSIFMAPл65536ж0 +SIOCSIFMEMл65536ж0 +SIOCSIFMETRICл65536ж0 +SIOCSIFMTUл65536ж0 +SIOCSIFNAMEл65536ж0 +SIOCSIFNETMASKл65536ж0 +SIOCSIFPFLAGSл65536ж0 +SIOCSIFSLAVEл65536ж0 +SIOCSIFTXQLENл65536ж0 +SIOCSPGRPл65536ж0 +SIOCSRARPл65536ж0 +SIOGIFINDEXл65536ж0 +SIZE_MAXл65536ж0 +SIZE_WIDTHл65536ж0 +SI_ASYNCIOл65536ж0 +SI_ASYNCNLл65536ж0 +SI_KERNELл65536ж0 +SI_MESGQл65536ж0 +SI_QUEUEл65536ж0 +SI_SIGIOл65536ж0 +SI_TIMERл65536ж0 +SI_TKILLл65536ж0 +SI_USERл65536ж0 +SNANл65536ж0 +SNANFл65536ж0 +SNANF128л65536ж0 +SNANLл65536ж0 +SOCKET_TIMEOUTл65536ж0 +SOCK_CLOEXECл65536ж0 +SOCK_DCCPл65536ж0 +SOCK_DGRAMл65536ж0 +SOCK_NONBLOCKл65536ж0 +SOCK_PACKETл65536ж0 +SOCK_RAWл65536ж0 +SOCK_RDMл65536ж0 +SOCK_SEQPACKETл65536ж0 +SOCK_STREAMл65536ж0 +SOL_AALл65536ж0 +SOL_ALGл65536ж0 +SOL_ATMл65536ж0 +SOL_BLUETOOTHл65536ж0 +SOL_CAIFл65536ж0 +SOL_DCCPл65536ж0 +SOL_DECNETл65536ж0 +SOL_ICMPV6л65536ж0 +SOL_IPл65536ж0 +SOL_IPV6л65536ж0 +SOL_IRDAл65536ж0 +SOL_IUCVл65536ж0 +SOL_KCMл65536ж0 +SOL_LLCл65536ж0 +SOL_NETBEUIл65536ж0 +SOL_NETLINKл65536ж0 +SOL_NFCл65536ж0 +SOL_PACKETл65536ж0 +SOL_PNPIPEл65536ж0 +SOL_PPPOL2TPл65536ж0 +SOL_RAWл65536ж0 +SOL_RDSл65536ж0 +SOL_RXRPCл65536ж0 +SOL_SOCKETл65536ж0 +SOL_TIPCл65536ж0 +SOL_X25л65536ж0 +SOMAXCONNл65536ж0 +SO_ACCEPTCONNл65536ж0 +SO_ATTACH_BPFл65536ж0 +SO_ATTACH_FILTERл65536ж0 +SO_ATTACH_REUSEPORT_CBPFл65536ж0 +SO_ATTACH_REUSEPORT_EBPFл65536ж0 +SO_BINDTODEVICEл65536ж0 +SO_BPF_EXTENSIONSл65536ж0 +SO_BROADCASTл65536ж0 +SO_BSDCOMPATл65536ж0 +SO_BUSY_POLLл65536ж0 +SO_CNX_ADVICEл65536ж0 +SO_COOKIEл65536ж0 +SO_DEBUGл65536ж0 +SO_DETACH_BPFл65536ж0 +SO_DETACH_FILTERл65536ж0 +SO_DOMAINл65536ж0 +SO_DONTROUTEл65536ж0 +SO_ERRORл65536ж0 +SO_GET_FILTERл65536ж0 +SO_INCOMING_CPUл65536ж0 +SO_INCOMING_NAPI_IDл65536ж0 +SO_KEEPALIVEл65536ж0 +SO_LINGERл65536ж0 +SO_LOCK_FILTERл65536ж0 +SO_MARKл65536ж0 +SO_MAX_PACING_RATEл65536ж0 +SO_MEMINFOл65536ж0 +SO_NOFCSл65536ж0 +SO_NO_CHECKл65536ж0 +SO_OOBINLINEл65536ж0 +SO_PASSCREDл65536ж0 +SO_PASSSECл65536ж0 +SO_PEEK_OFFл65536ж0 +SO_PEERCREDл65536ж0 +SO_PEERGROUPSл65536ж0 +SO_PEERNAMEл65536ж0 +SO_PEERSECл65536ж0 +SO_PRIORITYл65536ж0 +SO_PROTOCOLл65536ж0 +SO_RCVBUFл65536ж0 +SO_RCVBUFFORCEл65536ж0 +SO_RCVLOWATл65536ж0 +SO_RCVTIMEOл65536ж0 +SO_REUSEADDRл65536ж0 +SO_REUSEPORTл65536ж0 +SO_RXQ_OVFLл65536ж0 +SO_SECURITY_AUTHENTICATIONл65536ж0 +SO_SECURITY_ENCRYPTION_NETWORKл65536ж0 +SO_SECURITY_ENCRYPTION_TRANSPORTл65536ж0 +SO_SELECT_ERR_QUEUEл65536ж0 +SO_SNDBUFл65536ж0 +SO_SNDBUFFORCEл65536ж0 +SO_SNDLOWATл65536ж0 +SO_SNDTIMEOл65536ж0 +SO_TIMESTAMPл65536ж0 +SO_TIMESTAMPINGл65536ж0 +SO_TIMESTAMPNSл65536ж0 +SO_TYPEл65536ж0 +SO_WIFI_STATUSл65536ж0 +SPLICE_F_GIFTл65536ж0 +SPLICE_F_MOREл65536ж0 +SPLICE_F_MOVEл65536ж0 +SPLICE_F_NONBLOCKл65536ж0 +SSIZE_MAXл65536ж0 +SS_DISABLEл65536ж0 +SS_ONSTACKл65536ж0 +STA_CLKл65536ж0 +STA_CLOCKERRл65536ж0 +STA_DELл65536ж0 +STA_FLLл65536ж0 +STA_FREQHOLDл65536ж0 +STA_INSл65536ж0 +STA_MODEл65536ж0 +STA_NANOл65536ж0 +STA_PLLл65536ж0 +STA_PPSERRORл65536ж0 +STA_PPSFREQл65536ж0 +STA_PPSJITTERл65536ж0 +STA_PPSSIGNALл65536ж0 +STA_PPSTIMEл65536ж0 +STA_PPSWANDERл65536ж0 +STA_RONLYл65536ж0 +STA_UNSYNCл65536ж0 +STDC_HEADERSл65536ж0 +STDERR_FILENOл65536ж0 +STDIN_FILENOл65536ж0 +STDOUT_FILENOл65536ж0 +SYNC_FILE_RANGE_WAIT_AFTERл65536ж0 +SYNC_FILE_RANGE_WAIT_BEFOREл65536ж0 +SYNC_FILE_RANGE_WRITEл65536ж0 +SYS__sysctlл65536ж0 +SYS_acceptл65536ж0 +SYS_accept4л65536ж0 +SYS_accessл65536ж0 +SYS_acctл65536ж0 +SYS_add_keyл65536ж0 +SYS_adjtimexл65536ж0 +SYS_afs_syscallл65536ж0 +SYS_alarmл65536ж0 +SYS_arch_prctlл65536ж0 +SYS_bindл65536ж0 +SYS_bpfл65536ж0 +SYS_brkл65536ж0 +SYS_capgetл65536ж0 +SYS_capsetл65536ж0 +SYS_chdirл65536ж0 +SYS_chmodл65536ж0 +SYS_chownл65536ж0 +SYS_chrootл65536ж0 +SYS_clock_adjtimeл65536ж0 +SYS_clock_getresл65536ж0 +SYS_clock_gettimeл65536ж0 +SYS_clock_nanosleepл65536ж0 +SYS_clock_settimeл65536ж0 +SYS_cloneл65536ж0 +SYS_closeл65536ж0 +SYS_connectл65536ж0 +SYS_copy_file_rangeл65536ж0 +SYS_creatл65536ж0 +SYS_create_moduleл65536ж0 +SYS_delete_moduleл65536ж0 +SYS_dupл65536ж0 +SYS_dup2л65536ж0 +SYS_dup3л65536ж0 +SYS_epoll_createл65536ж0 +SYS_epoll_create1л65536ж0 +SYS_epoll_ctlл65536ж0 +SYS_epoll_ctl_oldл65536ж0 +SYS_epoll_pwaitл65536ж0 +SYS_epoll_waitл65536ж0 +SYS_epoll_wait_oldл65536ж0 +SYS_eventfdл65536ж0 +SYS_eventfd2л65536ж0 +SYS_execveл65536ж0 +SYS_execveatл65536ж0 +SYS_exitл65536ж0 +SYS_exit_groupл65536ж0 +SYS_faccessatл65536ж0 +SYS_fadvise64л65536ж0 +SYS_fallocateл65536ж0 +SYS_fanotify_initл65536ж0 +SYS_fanotify_markл65536ж0 +SYS_fchdirл65536ж0 +SYS_fchmodл65536ж0 +SYS_fchmodatл65536ж0 +SYS_fchownл65536ж0 +SYS_fchownatл65536ж0 +SYS_fcntlл65536ж0 +SYS_fdatasyncл65536ж0 +SYS_fgetxattrл65536ж0 +SYS_finit_moduleл65536ж0 +SYS_flistxattrл65536ж0 +SYS_flockл65536ж0 +SYS_forkл65536ж0 +SYS_fremovexattrл65536ж0 +SYS_fsetxattrл65536ж0 +SYS_fstatл65536ж0 +SYS_fstatfsл65536ж0 +SYS_fsyncл65536ж0 +SYS_ftruncateл65536ж0 +SYS_futexл65536ж0 +SYS_futimesatл65536ж0 +SYS_get_kernel_symsл65536ж0 +SYS_get_mempolicyл65536ж0 +SYS_get_robust_listл65536ж0 +SYS_get_thread_areaл65536ж0 +SYS_getcpuл65536ж0 +SYS_getcwdл65536ж0 +SYS_getdentsл65536ж0 +SYS_getdents64л65536ж0 +SYS_getegidл65536ж0 +SYS_geteuidл65536ж0 +SYS_getgidл65536ж0 +SYS_getgroupsл65536ж0 +SYS_getitimerл65536ж0 +SYS_getpeernameл65536ж0 +SYS_getpgidл65536ж0 +SYS_getpgrpл65536ж0 +SYS_getpidл65536ж0 +SYS_getpmsgл65536ж0 +SYS_getppidл65536ж0 +SYS_getpriorityл65536ж0 +SYS_getrandomл65536ж0 +SYS_getresgidл65536ж0 +SYS_getresuidл65536ж0 +SYS_getrlimitл65536ж0 +SYS_getrusageл65536ж0 +SYS_getsidл65536ж0 +SYS_getsocknameл65536ж0 +SYS_getsockoptл65536ж0 +SYS_gettidл65536ж0 +SYS_gettimeofdayл65536ж0 +SYS_getuidл65536ж0 +SYS_getxattrл65536ж0 +SYS_init_moduleл65536ж0 +SYS_inotify_add_watchл65536ж0 +SYS_inotify_initл65536ж0 +SYS_inotify_init1л65536ж0 +SYS_inotify_rm_watchл65536ж0 +SYS_io_cancelл65536ж0 +SYS_io_destroyл65536ж0 +SYS_io_geteventsл65536ж0 +SYS_io_setupл65536ж0 +SYS_io_submitл65536ж0 +SYS_ioctlл65536ж0 +SYS_iopermл65536ж0 +SYS_ioplл65536ж0 +SYS_ioprio_getл65536ж0 +SYS_ioprio_setл65536ж0 +SYS_kcmpл65536ж0 +SYS_kexec_file_loadл65536ж0 +SYS_kexec_loadл65536ж0 +SYS_keyctlл65536ж0 +SYS_killл65536ж0 +SYS_lchownл65536ж0 +SYS_lgetxattrл65536ж0 +SYS_linkл65536ж0 +SYS_linkatл65536ж0 +SYS_listenл65536ж0 +SYS_listxattrл65536ж0 +SYS_llistxattrл65536ж0 +SYS_lookup_dcookieл65536ж0 +SYS_lremovexattrл65536ж0 +SYS_lseekл65536ж0 +SYS_lsetxattrл65536ж0 +SYS_lstatл65536ж0 +SYS_madviseл65536ж0 +SYS_mbindл65536ж0 +SYS_membarrierл65536ж0 +SYS_memfd_createл65536ж0 +SYS_migrate_pagesл65536ж0 +SYS_mincoreл65536ж0 +SYS_mkdirл65536ж0 +SYS_mkdiratл65536ж0 +SYS_mknodл65536ж0 +SYS_mknodatл65536ж0 +SYS_mlockл65536ж0 +SYS_mlock2л65536ж0 +SYS_mlockallл65536ж0 +SYS_mmapл65536ж0 +SYS_modify_ldtл65536ж0 +SYS_mountл65536ж0 +SYS_move_pagesл65536ж0 +SYS_mprotectл65536ж0 +SYS_mq_getsetattrл65536ж0 +SYS_mq_notifyл65536ж0 +SYS_mq_openл65536ж0 +SYS_mq_timedreceiveл65536ж0 +SYS_mq_timedsendл65536ж0 +SYS_mq_unlinkл65536ж0 +SYS_mremapл65536ж0 +SYS_msgctlл65536ж0 +SYS_msggetл65536ж0 +SYS_msgrcvл65536ж0 +SYS_msgsndл65536ж0 +SYS_msyncл65536ж0 +SYS_munlockл65536ж0 +SYS_munlockallл65536ж0 +SYS_munmapл65536ж0 +SYS_name_to_handle_atл65536ж0 +SYS_nanosleepл65536ж0 +SYS_newfstatatл65536ж0 +SYS_nfsservctlл65536ж0 +SYS_openл65536ж0 +SYS_open_by_handle_atл65536ж0 +SYS_openatл65536ж0 +SYS_pauseл65536ж0 +SYS_perf_event_openл65536ж0 +SYS_personalityл65536ж0 +SYS_pipeл65536ж0 +SYS_pipe2л65536ж0 +SYS_pivot_rootл65536ж0 +SYS_pkey_allocл65536ж0 +SYS_pkey_freeл65536ж0 +SYS_pkey_mprotectл65536ж0 +SYS_pollл65536ж0 +SYS_ppollл65536ж0 +SYS_prctlл65536ж0 +SYS_pread64л65536ж0 +SYS_preadvл65536ж0 +SYS_preadv2л65536ж0 +SYS_prlimit64л65536ж0 +SYS_process_vm_readvл65536ж0 +SYS_process_vm_writevл65536ж0 +SYS_pselect6л65536ж0 +SYS_ptraceл65536ж0 +SYS_putpmsgл65536ж0 +SYS_pwrite64л65536ж0 +SYS_pwritevл65536ж0 +SYS_pwritev2л65536ж0 +SYS_query_moduleл65536ж0 +SYS_quotactlл65536ж0 +SYS_readл65536ж0 +SYS_readaheadл65536ж0 +SYS_readlinkл65536ж0 +SYS_readlinkatл65536ж0 +SYS_readvл65536ж0 +SYS_rebootл65536ж0 +SYS_recvfromл65536ж0 +SYS_recvmmsgл65536ж0 +SYS_recvmsgл65536ж0 +SYS_remap_file_pagesл65536ж0 +SYS_removexattrл65536ж0 +SYS_renameл65536ж0 +SYS_renameatл65536ж0 +SYS_renameat2л65536ж0 +SYS_request_keyл65536ж0 +SYS_restart_syscallл65536ж0 +SYS_rmdirл65536ж0 +SYS_rt_sigactionл65536ж0 +SYS_rt_sigpendingл65536ж0 +SYS_rt_sigprocmaskл65536ж0 +SYS_rt_sigqueueinfoл65536ж0 +SYS_rt_sigreturnл65536ж0 +SYS_rt_sigsuspendл65536ж0 +SYS_rt_sigtimedwaitл65536ж0 +SYS_rt_tgsigqueueinfoл65536ж0 +SYS_sched_get_priority_maxл65536ж0 +SYS_sched_get_priority_minл65536ж0 +SYS_sched_getaffinityл65536ж0 +SYS_sched_getattrл65536ж0 +SYS_sched_getparamл65536ж0 +SYS_sched_getschedulerл65536ж0 +SYS_sched_rr_get_intervalл65536ж0 +SYS_sched_setaffinityл65536ж0 +SYS_sched_setattrл65536ж0 +SYS_sched_setparamл65536ж0 +SYS_sched_setschedulerл65536ж0 +SYS_sched_yieldл65536ж0 +SYS_seccompл65536ж0 +SYS_securityл65536ж0 +SYS_selectл65536ж0 +SYS_semctlл65536ж0 +SYS_semgetл65536ж0 +SYS_semopл65536ж0 +SYS_semtimedopл65536ж0 +SYS_sendfileл65536ж0 +SYS_sendmmsgл65536ж0 +SYS_sendmsgл65536ж0 +SYS_sendtoл65536ж0 +SYS_set_mempolicyл65536ж0 +SYS_set_robust_listл65536ж0 +SYS_set_thread_areaл65536ж0 +SYS_set_tid_addressл65536ж0 +SYS_setdomainnameл65536ж0 +SYS_setfsgidл65536ж0 +SYS_setfsuidл65536ж0 +SYS_setgidл65536ж0 +SYS_setgroupsл65536ж0 +SYS_sethostnameл65536ж0 +SYS_setitimerл65536ж0 +SYS_setnsл65536ж0 +SYS_setpgidл65536ж0 +SYS_setpriorityл65536ж0 +SYS_setregidл65536ж0 +SYS_setresgidл65536ж0 +SYS_setresuidл65536ж0 +SYS_setreuidл65536ж0 +SYS_setrlimitл65536ж0 +SYS_setsidл65536ж0 +SYS_setsockoptл65536ж0 +SYS_settimeofdayл65536ж0 +SYS_setuidл65536ж0 +SYS_setxattrл65536ж0 +SYS_shmatл65536ж0 +SYS_shmctlл65536ж0 +SYS_shmdtл65536ж0 +SYS_shmgetл65536ж0 +SYS_shutdownл65536ж0 +SYS_sigaltstackл65536ж0 +SYS_signalfdл65536ж0 +SYS_signalfd4л65536ж0 +SYS_socketл65536ж0 +SYS_socketpairл65536ж0 +SYS_spliceл65536ж0 +SYS_statл65536ж0 +SYS_statfsл65536ж0 +SYS_statxл65536ж0 +SYS_swapoffл65536ж0 +SYS_swaponл65536ж0 +SYS_symlinkл65536ж0 +SYS_symlinkatл65536ж0 +SYS_syncл65536ж0 +SYS_sync_file_rangeл65536ж0 +SYS_syncfsл65536ж0 +SYS_sysfsл65536ж0 +SYS_sysinfoл65536ж0 +SYS_syslogл65536ж0 +SYS_teeл65536ж0 +SYS_tgkillл65536ж0 +SYS_timeл65536ж0 +SYS_timer_createл65536ж0 +SYS_timer_deleteл65536ж0 +SYS_timer_getoverrunл65536ж0 +SYS_timer_gettimeл65536ж0 +SYS_timer_settimeл65536ж0 +SYS_timerfd_createл65536ж0 +SYS_timerfd_gettimeл65536ж0 +SYS_timerfd_settimeл65536ж0 +SYS_timesл65536ж0 +SYS_tkillл65536ж0 +SYS_truncateл65536ж0 +SYS_tuxcallл65536ж0 +SYS_umaskл65536ж0 +SYS_umount2л65536ж0 +SYS_unameл65536ж0 +SYS_unlinkл65536ж0 +SYS_unlinkatл65536ж0 +SYS_unshareл65536ж0 +SYS_uselibл65536ж0 +SYS_userfaultfdл65536ж0 +SYS_ustatл65536ж0 +SYS_utimeл65536ж0 +SYS_utimensatл65536ж0 +SYS_utimesл65536ж0 +SYS_vforkл65536ж0 +SYS_vhangupл65536ж0 +SYS_vmspliceл65536ж0 +SYS_vserverл65536ж0 +SYS_wait4л65536ж0 +SYS_waitidл65536ж0 +SYS_writeл65536ж0 +SYS_writevл65536ж0 +S_BLKSIZEл65536ж0 +S_IEXECл65536ж0 +S_IFBLKл65536ж0 +S_IFCHRл65536ж0 +S_IFDIRл65536ж0 +S_IFIFOл65536ж0 +S_IFLNKл65536ж0 +S_IFMTл65536ж0 +S_IFREGл65536ж0 +S_IFSOCKл65536ж0 +S_IREADл65536ж0 +S_IRGRPл65536ж0 +S_IROTHл65536ж0 +S_IRUSRл65536ж0 +S_IRWXGл65536ж0 +S_IRWXOл65536ж0 +S_IRWXUл65536ж0 +S_ISBLKл131072м(mode)ж0 +S_ISCHRл131072м(mode)ж0 +S_ISDIRл131072м(mode)ж0 +S_ISFIFOл131072м(mode)ж0 +S_ISGIDл65536ж0 +S_ISLNKл131072м(mode)ж0 +S_ISREGл131072м(mode)ж0 +S_ISSOCKл131072м(mode)ж0 +S_ISUIDл65536ж0 +S_ISVTXл65536ж0 +S_IWGRPл65536ж0 +S_IWOTHл65536ж0 +S_IWRITEл65536ж0 +S_IWUSRл65536ж0 +S_IXGRPл65536ж0 +S_IXOTHл65536ж0 +S_IXUSRл65536ж0 +S_TYPEISMQл131072м(buf)ж0 +S_TYPEISSEMл131072м(buf)ж0 +S_TYPEISSHMл131072м(buf)ж0 +TAB0л65536ж0 +TAB1л65536ж0 +TAB2л65536ж0 +TAB3л65536ж0 +TABDLYл65536ж0 +TCFLSHл65536ж0 +TCGETAл65536ж0 +TCGETSл65536ж0 +TCGETS2л65536ж0 +TCGETXл65536ж0 +TCIFLUSHл65536ж0 +TCIOFFл65536ж0 +TCIOFLUSHл65536ж0 +TCIONл65536ж0 +TCOFLUSHл65536ж0 +TCOOFFл65536ж0 +TCOONл65536ж0 +TCSADRAINл65536ж0 +TCSAFLUSHл65536ж0 +TCSANOWл65536ж0 +TCSBRKл65536ж0 +TCSBRKPл65536ж0 +TCSETAл65536ж0 +TCSETAFл65536ж0 +TCSETAWл65536ж0 +TCSETSл65536ж0 +TCSETS2л65536ж0 +TCSETSFл65536ж0 +TCSETSF2л65536ж0 +TCSETSWл65536ж0 +TCSETSW2л65536ж0 +TCSETXл65536ж0 +TCSETXFл65536ж0 +TCSETXWл65536ж0 +TCXONCл65536ж0 +TEMP_FAILURE_RETRYл131072м(expression)ж0 +TIMER_ABSTIMEл65536ж0 +TIMESPEC_TO_TIMEVALл131072м(tv,ts)ж0 +TIMEVAL_TO_TIMESPECл131072м(tv,ts)ж0 +TIME_UTCл65536ж0 +TIOCCBRKл65536ж0 +TIOCCONSл65536ж0 +TIOCEXCLл65536ж0 +TIOCGDEVл65536ж0 +TIOCGETDл65536ж0 +TIOCGEXCLл65536ж0 +TIOCGICOUNTл65536ж0 +TIOCGLCKTRMIOSл65536ж0 +TIOCGPGRPл65536ж0 +TIOCGPKTл65536ж0 +TIOCGPTLCKл65536ж0 +TIOCGPTNл65536ж0 +TIOCGPTPEERл65536ж0 +TIOCGRS485л65536ж0 +TIOCGSERIALл65536ж0 +TIOCGSIDл65536ж0 +TIOCGSOFTCARл65536ж0 +TIOCGWINSZл65536ж0 +TIOCINQл65536ж0 +TIOCLINUXл65536ж0 +TIOCMBICл65536ж0 +TIOCMBISл65536ж0 +TIOCMGETл65536ж0 +TIOCMIWAITл65536ж0 +TIOCMSETл65536ж0 +TIOCM_CARл65536ж0 +TIOCM_CDл65536ж0 +TIOCM_CTSл65536ж0 +TIOCM_DSRл65536ж0 +TIOCM_DTRл65536ж0 +TIOCM_LEл65536ж0 +TIOCM_RIл65536ж0 +TIOCM_RNGл65536ж0 +TIOCM_RTSл65536ж0 +TIOCM_SRл65536ж0 +TIOCM_STл65536ж0 +TIOCNOTTYл65536ж0 +TIOCNXCLл65536ж0 +TIOCOUTQл65536ж0 +TIOCPKTл65536ж0 +TIOCPKT_DATAл65536ж0 +TIOCPKT_DOSTOPл65536ж0 +TIOCPKT_FLUSHREADл65536ж0 +TIOCPKT_FLUSHWRITEл65536ж0 +TIOCPKT_IOCTLл65536ж0 +TIOCPKT_NOSTOPл65536ж0 +TIOCPKT_STARTл65536ж0 +TIOCPKT_STOPл65536ж0 +TIOCSBRKл65536ж0 +TIOCSCTTYл65536ж0 +TIOCSERCONFIGл65536ж0 +TIOCSERGETLSRл65536ж0 +TIOCSERGETMULTIл65536ж0 +TIOCSERGSTRUCTл65536ж0 +TIOCSERGWILDл65536ж0 +TIOCSERSETMULTIл65536ж0 +TIOCSERSWILDл65536ж0 +TIOCSER_TEMTл65536ж0 +TIOCSETDл65536ж0 +TIOCSIGл65536ж0 +TIOCSLCKTRMIOSл65536ж0 +TIOCSPGRPл65536ж0 +TIOCSPTLCKл65536ж0 +TIOCSRS485л65536ж0 +TIOCSSERIALл65536ж0 +TIOCSSOFTCARл65536ж0 +TIOCSTIл65536ж0 +TIOCSWINSZл65536ж0 +TIOCVHANGUPл65536ж0 +TLOSSл65536ж0 +TMP_MAXл65536ж0 +TOSTOPл65536ж0 +TRAP_BRKPTл65536ж0 +TRAP_TRACEл65536ж0 +TRUEл65536ж0 +TRY_AGAINл65536ж0 +TTYDEF_CFLAGл65536ж0 +TTYDEF_IFLAGл65536ж0 +TTYDEF_LFLAGл65536ж0 +TTYDEF_OFLAGл65536ж0 +TTYDEF_SPEEDл65536ж0 +TTY_NAME_MAXл65536ж0 +T_INTERVALл65536ж0 +T_POLLING_TMOUTл65536ж0 +UCHAR_MAXл65536ж0 +UCHAR_WIDTHл65536ж0 +UINT16_Cл131072м(c)ж0 +UINT16_MAXл65536ж0 +UINT16_WIDTHл65536ж0 +UINT32_Cл131072м(c)ж0 +UINT32_MAXл65536ж0 +UINT32_WIDTHл65536ж0 +UINT64_Cл131072м(c)ж0 +UINT64_MAXл65536ж0 +UINT64_WIDTHл65536ж0 +UINT8_Cл131072м(c)ж0 +UINT8_MAXл65536ж0 +UINT8_WIDTHл65536ж0 +UINTMAX_Cл131072м(c)ж0 +UINTMAX_MAXл65536ж0 +UINTMAX_WIDTHл65536ж0 +UINTPTR_MAXл65536ж0 +UINTPTR_WIDTHл65536ж0 +UINT_FAST16_MAXл65536ж0 +UINT_FAST16_WIDTHл65536ж0 +UINT_FAST32_MAXл65536ж0 +UINT_FAST32_WIDTHл65536ж0 +UINT_FAST64_MAXл65536ж0 +UINT_FAST64_WIDTHл65536ж0 +UINT_FAST8_MAXл65536ж0 +UINT_FAST8_WIDTHл65536ж0 +UINT_LEAST16_MAXл65536ж0 +UINT_LEAST16_WIDTHл65536ж0 +UINT_LEAST32_MAXл65536ж0 +UINT_LEAST32_WIDTHл65536ж0 +UINT_LEAST64_MAXл65536ж0 +UINT_LEAST64_WIDTHл65536ж0 +UINT_LEAST8_MAXл65536ж0 +UINT_LEAST8_WIDTHл65536ж0 +UINT_MAXл65536ж0 +UINT_WIDTHл65536ж0 +ULLONG_MAXл65536ж0 +ULLONG_WIDTHл65536ж0 +ULONG_LONG_MAXл65536ж0 +ULONG_MAXл65536ж0 +ULONG_WIDTHл65536ж0 +UNDERFLOWл65536ж0 +USHRT_MAXл65536ж0 +USHRT_WIDTHл65536ж0 +UTIME_NOWл65536ж0 +UTIME_OMITл65536ж0 +VDISCARDл65536ж0 +VEOFл65536ж0 +VEOLл65536ж0 +VEOL2л65536ж0 +VERASEл65536ж0 +VINTRл65536ж0 +VKILLл65536ж0 +VLNEXTл65536ж0 +VMINл65536ж0 +VQUITл65536ж0 +VREPRINTл65536ж0 +VSTARTл65536ж0 +VSTOPл65536ж0 +VSUSPл65536ж0 +VSWTCл65536ж0 +VT0л65536ж0 +VT1л65536ж0 +VTDLYл65536ж0 +VTIMEл65536ж0 +VWERASEл65536ж0 +WAIT_ANYл65536ж0 +WAIT_MYPGRPл65536ж0 +WAIT_TMOUTл65536ж0 +WARNл131072м(...)ж0 +WARNXл131072м(...)ж0 +WCHAR_MAXл65536ж0 +WCHAR_MINл65536ж0 +WCHAR_WIDTHл65536ж0 +WCONTINUEDл65536ж0 +WCOREDUMPл131072м(status)ж0 +WCOREFLAGл65536ж0 +WEXITEDл65536ж0 +WEXITSTATUSл131072м(status)ж0 +WIFCONTINUEDл131072м(status)ж0 +WIFEXITEDл131072м(status)ж0 +WIFSIGNALEDл131072м(status)ж0 +WIFSTOPPEDл131072м(status)ж0 +WINT_MAXл65536ж0 +WINT_MINл65536ж0 +WINT_WIDTHл65536ж0 +WNOHANGл65536ж0 +WNOWAITл65536ж0 +WORD_BITл65536ж0 +WSTOPPEDл65536ж0 +WSTOPSIGл131072м(status)ж0 +WTERMSIGл131072м(status)ж0 +WUNTRACEDл65536ж0 +W_EXITCODEл131072м(ret,sig)ж0 +W_OKл65536ж0 +W_STOPCODEл131072м(sig)ж0 +XATTR_LIST_MAXл65536ж0 +XATTR_NAME_MAXл65536ж0 +XATTR_SIZE_MAXл65536ж0 +XCASEл65536ж0 +XTABSл65536ж0 +X_OKл65536ж0 +X_TLOSSл65536ж0 +_л131072м(String)ж0 +_ALLOCA_Hл65536ж0 +_ANSI_STDARG_H_л65536ж0 +_ARPA_INET_Hл65536ж0 +_ASM_GENERIC_ERRNO_BASE_Hл65536ж0 +_ASM_GENERIC_ERRNO_Hл65536ж0 +_ASM_GENERIC_INT_LL64_Hл65536ж0 +_ASM_GENERIC_IOCTL_Hл65536ж0 +_ASM_GENERIC_TYPES_Hл65536ж0 +_ASM_X86_POSIX_TYPES_64_Hл65536ж0 +_ASM_X86_TYPES_Hл65536ж0 +_ASM_X86_UNISTD_64_Hл65536ж0 +_ASM_X86_UNISTD_Hл65536ж0 +_ASSERT_Hл65536ж0 +_ATFILE_SOURCEл65536ж0 +_BITS_BYTESWAP_Hл65536ж0 +_BITS_CPU_SET_Hл65536ж0 +_BITS_ERRNO_Hл65536ж0 +_BITS_FLOATN_Hл65536ж0 +_BITS_LIBM_SIMD_DECL_STUBS_Hл65536ж0 +_BITS_LOCALE_Hл65536ж0 +_BITS_POSIX1_LIM_Hл65536ж0 +_BITS_POSIX2_LIM_Hл65536ж0 +_BITS_POSIX_OPT_Hл65536ж0 +_BITS_PTHREADTYPES_ARCH_Hл65536ж0 +_BITS_PTHREADTYPES_COMMON_Hл65536ж0 +_BITS_SCHED_Hл65536ж0 +_BITS_SETJMP_Hл65536ж0 +_BITS_SIGCONTEXT_Hл65536ж0 +_BITS_SIGEVENT_CONSTS_Hл65536ж0 +_BITS_SIGINFO_ARCH_Hл65536ж0 +_BITS_SIGINFO_CONSTS_ARCH_Hл65536ж0 +_BITS_SIGINFO_CONSTS_Hл65536ж0 +_BITS_SIGNUM_GENERIC_Hл65536ж0 +_BITS_SIGNUM_Hл65536ж0 +_BITS_SIGSTACK_Hл65536ж0 +_BITS_SIGTHREAD_Hл65536ж0 +_BITS_SOCKADDR_Hл65536ж0 +_BITS_SS_FLAGS_Hл65536ж0 +_BITS_STAT_Hл65536ж0 +_BITS_STDINT_INTN_Hл65536ж0 +_BITS_STDINT_UINTN_Hл65536ж0 +_BITS_STDIO_LIM_Hл65536ж0 +_BITS_STRING_FORTIFIED_Hл65536ж0 +_BITS_TIMEX_Hл65536ж0 +_BITS_TIME_Hл65536ж0 +_BITS_TYPESIZES_Hл65536ж0 +_BITS_TYPES_Hл65536ж0 +_BITS_TYPES_LOCALE_T_Hл65536ж0 +_BITS_TYPES___LOCALE_T_Hл65536ж0 +_BITS_UINTN_IDENTITY_Hл65536ж0 +_BITS_UIO_LIM_Hл65536ж0 +_BITS_WCHAR_Hл65536ж0 +_BSD_SIZE_T_л65536ж0 +_BSD_SIZE_T_DEFINED_л65536ж0 +_BSD_WCHAR_T_л65536ж0 +_Boolл65536ж0 +_CPP_TYPE_TRAITS_Hл65536ж0 +_CS_GNU_LIBC_VERSIONл65536ж0 +_CS_GNU_LIBPTHREAD_VERSIONл65536ж0 +_CS_LFS64_CFLAGSл65536ж0 +_CS_LFS64_LDFLAGSл65536ж0 +_CS_LFS64_LIBSл65536ж0 +_CS_LFS64_LINTFLAGSл65536ж0 +_CS_LFS_CFLAGSл65536ж0 +_CS_LFS_LDFLAGSл65536ж0 +_CS_LFS_LIBSл65536ж0 +_CS_LFS_LINTFLAGSл65536ж0 +_CS_PATHл65536ж0 +_CS_POSIX_V5_WIDTH_RESTRICTED_ENVSл65536ж0 +_CS_POSIX_V6_ILP32_OFF32_CFLAGSл65536ж0 +_CS_POSIX_V6_ILP32_OFF32_LDFLAGSл65536ж0 +_CS_POSIX_V6_ILP32_OFF32_LIBSл65536ж0 +_CS_POSIX_V6_ILP32_OFF32_LINTFLAGSл65536ж0 +_CS_POSIX_V6_ILP32_OFFBIG_CFLAGSл65536ж0 +_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGSл65536ж0 +_CS_POSIX_V6_ILP32_OFFBIG_LIBSл65536ж0 +_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGSл65536ж0 +_CS_POSIX_V6_LP64_OFF64_CFLAGSл65536ж0 +_CS_POSIX_V6_LP64_OFF64_LDFLAGSл65536ж0 +_CS_POSIX_V6_LP64_OFF64_LIBSл65536ж0 +_CS_POSIX_V6_LP64_OFF64_LINTFLAGSл65536ж0 +_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGSл65536ж0 +_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGSл65536ж0 +_CS_POSIX_V6_LPBIG_OFFBIG_LIBSл65536ж0 +_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGSл65536ж0 +_CS_POSIX_V6_WIDTH_RESTRICTED_ENVSл65536ж0 +_CS_POSIX_V7_ILP32_OFF32_CFLAGSл65536ж0 +_CS_POSIX_V7_ILP32_OFF32_LDFLAGSл65536ж0 +_CS_POSIX_V7_ILP32_OFF32_LIBSл65536ж0 +_CS_POSIX_V7_ILP32_OFF32_LINTFLAGSл65536ж0 +_CS_POSIX_V7_ILP32_OFFBIG_CFLAGSл65536ж0 +_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGSл65536ж0 +_CS_POSIX_V7_ILP32_OFFBIG_LIBSл65536ж0 +_CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGSл65536ж0 +_CS_POSIX_V7_LP64_OFF64_CFLAGSл65536ж0 +_CS_POSIX_V7_LP64_OFF64_LDFLAGSл65536ж0 +_CS_POSIX_V7_LP64_OFF64_LIBSл65536ж0 +_CS_POSIX_V7_LP64_OFF64_LINTFLAGSл65536ж0 +_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGSл65536ж0 +_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGSл65536ж0 +_CS_POSIX_V7_LPBIG_OFFBIG_LIBSл65536ж0 +_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGSл65536ж0 +_CS_POSIX_V7_WIDTH_RESTRICTED_ENVSл65536ж0 +_CS_V5_WIDTH_RESTRICTED_ENVSл65536ж0 +_CS_V6_ENVл65536ж0 +_CS_V6_WIDTH_RESTRICTED_ENVSл65536ж0 +_CS_V7_ENVл65536ж0 +_CS_V7_WIDTH_RESTRICTED_ENVSл65536ж0 +_CS_XBS5_ILP32_OFF32_CFLAGSл65536ж0 +_CS_XBS5_ILP32_OFF32_LDFLAGSл65536ж0 +_CS_XBS5_ILP32_OFF32_LIBSл65536ж0 +_CS_XBS5_ILP32_OFF32_LINTFLAGSл65536ж0 +_CS_XBS5_ILP32_OFFBIG_CFLAGSл65536ж0 +_CS_XBS5_ILP32_OFFBIG_LDFLAGSл65536ж0 +_CS_XBS5_ILP32_OFFBIG_LIBSл65536ж0 +_CS_XBS5_ILP32_OFFBIG_LINTFLAGSл65536ж0 +_CS_XBS5_LP64_OFF64_CFLAGSл65536ж0 +_CS_XBS5_LP64_OFF64_LDFLAGSл65536ж0 +_CS_XBS5_LP64_OFF64_LIBSл65536ж0 +_CS_XBS5_LP64_OFF64_LINTFLAGSл65536ж0 +_CS_XBS5_LPBIG_OFFBIG_CFLAGSл65536ж0 +_CS_XBS5_LPBIG_OFFBIG_LDFLAGSл65536ж0 +_CS_XBS5_LPBIG_OFFBIG_LIBSл65536ж0 +_CS_XBS5_LPBIG_OFFBIG_LINTFLAGSл65536ж0 +_CTYPE_Hл65536ж0 +_DEFAULT_SOURCEл65536ж0 +_ENDIAN_Hл65536ж0 +_ERRNO_Hл65536ж0 +_ERR_Hл65536ж0 +_EXTERN_INLINEл65536ж0 +_EXT_TYPE_TRAITSл65536ж0 +_Exitл65536ж0 +_FALLOC_H_л65536ж0 +_FCNTL_Hл65536ж0 +_FEATURES_Hл65536ж0 +_FORTIFY_SOURCEл65536ж0 +_GCC_LIMITS_H_л65536ж0 +_GCC_NEXT_LIMITS_Hл65536ж0 +_GCC_SIZE_Tл65536ж0 +_GCC_WCHAR_Tл65536ж0 +_GCC_WRAP_STDINT_Hл65536ж0 +_GETOPT_CORE_Hл65536ж0 +_GETOPT_EXT_Hл65536ж0 +_GETOPT_Hл65536ж0 +_GETOPT_POSIX_Hл65536ж0 +_GLIBCXX11_USE_C99_COMPLEXл65536ж0 +_GLIBCXX11_USE_C99_MATHл65536ж0 +_GLIBCXX11_USE_C99_STDIOл65536ж0 +_GLIBCXX11_USE_C99_STDLIBл65536ж0 +_GLIBCXX11_USE_C99_WCHARл65536ж0 +_GLIBCXX14_CONSTEXPRл65536ж0 +_GLIBCXX98_USE_C99_COMPLEXл65536ж0 +_GLIBCXX98_USE_C99_MATHл65536ж0 +_GLIBCXX98_USE_C99_STDIOл65536ж0 +_GLIBCXX98_USE_C99_STDLIBл65536ж0 +_GLIBCXX98_USE_C99_WCHARл65536ж0 +_GLIBCXX_ABI_TAG_CXX11л65536ж0 +_GLIBCXX_ATOMIC_BUILTINSл65536ж0 +_GLIBCXX_BEGIN_EXTERN_Cл65536ж0 +_GLIBCXX_BEGIN_NAMESPACE_ALGOл65536ж0 +_GLIBCXX_BEGIN_NAMESPACE_CONTAINERл65536ж0 +_GLIBCXX_BEGIN_NAMESPACE_CXX11л65536ж0 +_GLIBCXX_BEGIN_NAMESPACE_LDBLл65536ж0 +_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11л65536ж0 +_GLIBCXX_BEGIN_NAMESPACE_VERSIONл65536ж0 +_GLIBCXX_CMATHл65536ж0 +_GLIBCXX_CONSTл65536ж0 +_GLIBCXX_CONSTEXPRл65536ж0 +_GLIBCXX_CPU_DEFINESл65536ж0 +_GLIBCXX_CSTDLIBл65536ж0 +_GLIBCXX_CXX_CONFIG_Hл65536ж0 +_GLIBCXX_DEFAULT_ABI_TAGл65536ж0 +_GLIBCXX_DEPRECATEDл65536ж0 +_GLIBCXX_END_EXTERN_Cл65536ж0 +_GLIBCXX_END_NAMESPACE_ALGOл65536ж0 +_GLIBCXX_END_NAMESPACE_CONTAINERл65536ж0 +_GLIBCXX_END_NAMESPACE_CXX11л65536ж0 +_GLIBCXX_END_NAMESPACE_LDBLл65536ж0 +_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11л65536ж0 +_GLIBCXX_END_NAMESPACE_VERSIONл65536ж0 +_GLIBCXX_EXTERN_TEMPLATEл65536ж0 +_GLIBCXX_FAST_MATHл65536ж0 +_GLIBCXX_FULLY_DYNAMIC_STRINGл65536ж0 +_GLIBCXX_HAS_GTHREADSл65536ж0 +_GLIBCXX_HAVE_ACOSFл65536ж0 +_GLIBCXX_HAVE_ACOSLл65536ж0 +_GLIBCXX_HAVE_ASINFл65536ж0 +_GLIBCXX_HAVE_ASINLл65536ж0 +_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVEл65536ж0 +_GLIBCXX_HAVE_ATAN2Fл65536ж0 +_GLIBCXX_HAVE_ATAN2Lл65536ж0 +_GLIBCXX_HAVE_ATANFл65536ж0 +_GLIBCXX_HAVE_ATANLл65536ж0 +_GLIBCXX_HAVE_ATTRIBUTE_VISIBILITYл65536ж0 +_GLIBCXX_HAVE_AT_QUICK_EXITл65536ж0 +_GLIBCXX_HAVE_CEILFл65536ж0 +_GLIBCXX_HAVE_CEILLл65536ж0 +_GLIBCXX_HAVE_COMPLEX_Hл65536ж0 +_GLIBCXX_HAVE_COSFл65536ж0 +_GLIBCXX_HAVE_COSHFл65536ж0 +_GLIBCXX_HAVE_COSHLл65536ж0 +_GLIBCXX_HAVE_COSLл65536ж0 +_GLIBCXX_HAVE_DIRENT_Hл65536ж0 +_GLIBCXX_HAVE_DLFCN_Hл65536ж0 +_GLIBCXX_HAVE_EBADMSGл65536ж0 +_GLIBCXX_HAVE_ECANCELEDл65536ж0 +_GLIBCXX_HAVE_ECHILDл65536ж0 +_GLIBCXX_HAVE_EIDRMл65536ж0 +_GLIBCXX_HAVE_ENDIAN_Hл65536ж0 +_GLIBCXX_HAVE_ENODATAл65536ж0 +_GLIBCXX_HAVE_ENOLINKл65536ж0 +_GLIBCXX_HAVE_ENOSPCл65536ж0 +_GLIBCXX_HAVE_ENOSRл65536ж0 +_GLIBCXX_HAVE_ENOSTRл65536ж0 +_GLIBCXX_HAVE_ENOTRECOVERABLEл65536ж0 +_GLIBCXX_HAVE_ENOTSUPл65536ж0 +_GLIBCXX_HAVE_EOVERFLOWл65536ж0 +_GLIBCXX_HAVE_EOWNERDEADл65536ж0 +_GLIBCXX_HAVE_EPERMл65536ж0 +_GLIBCXX_HAVE_EPROTOл65536ж0 +_GLIBCXX_HAVE_ETIMEл65536ж0 +_GLIBCXX_HAVE_ETIMEDOUTл65536ж0 +_GLIBCXX_HAVE_ETXTBSYл65536ж0 +_GLIBCXX_HAVE_EWOULDBLOCKл65536ж0 +_GLIBCXX_HAVE_EXECINFO_Hл65536ж0 +_GLIBCXX_HAVE_EXPFл65536ж0 +_GLIBCXX_HAVE_EXPLл65536ж0 +_GLIBCXX_HAVE_FABSFл65536ж0 +_GLIBCXX_HAVE_FABSLл65536ж0 +_GLIBCXX_HAVE_FCNTL_Hл65536ж0 +_GLIBCXX_HAVE_FENV_Hл65536ж0 +_GLIBCXX_HAVE_FINITEл65536ж0 +_GLIBCXX_HAVE_FINITEFл65536ж0 +_GLIBCXX_HAVE_FINITELл65536ж0 +_GLIBCXX_HAVE_FLOAT_Hл65536ж0 +_GLIBCXX_HAVE_FLOORFл65536ж0 +_GLIBCXX_HAVE_FLOORLл65536ж0 +_GLIBCXX_HAVE_FMODFл65536ж0 +_GLIBCXX_HAVE_FMODLл65536ж0 +_GLIBCXX_HAVE_FREXPFл65536ж0 +_GLIBCXX_HAVE_FREXPLл65536ж0 +_GLIBCXX_HAVE_GETIPINFOл65536ж0 +_GLIBCXX_HAVE_GETSл65536ж0 +_GLIBCXX_HAVE_HYPOTл65536ж0 +_GLIBCXX_HAVE_HYPOTFл65536ж0 +_GLIBCXX_HAVE_HYPOTLл65536ж0 +_GLIBCXX_HAVE_ICONVл65536ж0 +_GLIBCXX_HAVE_INT64_Tл65536ж0 +_GLIBCXX_HAVE_INT64_T_LONGл65536ж0 +_GLIBCXX_HAVE_INTTYPES_Hл65536ж0 +_GLIBCXX_HAVE_ISINFFл65536ж0 +_GLIBCXX_HAVE_ISINFLл65536ж0 +_GLIBCXX_HAVE_ISNANFл65536ж0 +_GLIBCXX_HAVE_ISNANLл65536ж0 +_GLIBCXX_HAVE_ISWBLANKл65536ж0 +_GLIBCXX_HAVE_LC_MESSAGESл65536ж0 +_GLIBCXX_HAVE_LDEXPFл65536ж0 +_GLIBCXX_HAVE_LDEXPLл65536ж0 +_GLIBCXX_HAVE_LIBINTL_Hл65536ж0 +_GLIBCXX_HAVE_LIMIT_ASл65536ж0 +_GLIBCXX_HAVE_LIMIT_DATAл65536ж0 +_GLIBCXX_HAVE_LIMIT_FSIZEл65536ж0 +_GLIBCXX_HAVE_LIMIT_RSSл65536ж0 +_GLIBCXX_HAVE_LIMIT_VMEMл65536ж0 +_GLIBCXX_HAVE_LINUX_FUTEXл65536ж0 +_GLIBCXX_HAVE_LOCALE_Hл65536ж0 +_GLIBCXX_HAVE_LOG10Fл65536ж0 +_GLIBCXX_HAVE_LOG10Lл65536ж0 +_GLIBCXX_HAVE_LOGFл65536ж0 +_GLIBCXX_HAVE_LOGLл65536ж0 +_GLIBCXX_HAVE_MBSTATE_Tл65536ж0 +_GLIBCXX_HAVE_MEMORY_Hл65536ж0 +_GLIBCXX_HAVE_MODFл65536ж0 +_GLIBCXX_HAVE_MODFFл65536ж0 +_GLIBCXX_HAVE_MODFLл65536ж0 +_GLIBCXX_HAVE_POLLл65536ж0 +_GLIBCXX_HAVE_POWFл65536ж0 +_GLIBCXX_HAVE_POWLл65536ж0 +_GLIBCXX_HAVE_QUICK_EXITл65536ж0 +_GLIBCXX_HAVE_SETENVл65536ж0 +_GLIBCXX_HAVE_SINCOSл65536ж0 +_GLIBCXX_HAVE_SINCOSFл65536ж0 +_GLIBCXX_HAVE_SINCOSLл65536ж0 +_GLIBCXX_HAVE_SINFл65536ж0 +_GLIBCXX_HAVE_SINHFл65536ж0 +_GLIBCXX_HAVE_SINHLл65536ж0 +_GLIBCXX_HAVE_SINLл65536ж0 +_GLIBCXX_HAVE_SQRTFл65536ж0 +_GLIBCXX_HAVE_SQRTLл65536ж0 +_GLIBCXX_HAVE_STDALIGN_Hл65536ж0 +_GLIBCXX_HAVE_STDBOOL_Hл65536ж0 +_GLIBCXX_HAVE_STDINT_Hл65536ж0 +_GLIBCXX_HAVE_STDLIB_Hл65536ж0 +_GLIBCXX_HAVE_STRERROR_Lл65536ж0 +_GLIBCXX_HAVE_STRERROR_Rл65536ж0 +_GLIBCXX_HAVE_STRINGS_Hл65536ж0 +_GLIBCXX_HAVE_STRING_Hл65536ж0 +_GLIBCXX_HAVE_STRTOFл65536ж0 +_GLIBCXX_HAVE_STRTOLDл65536ж0 +_GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPEл65536ж0 +_GLIBCXX_HAVE_STRXFRM_Lл65536ж0 +_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORTл65536ж0 +_GLIBCXX_HAVE_SYS_IOCTL_Hл65536ж0 +_GLIBCXX_HAVE_SYS_IPC_Hл65536ж0 +_GLIBCXX_HAVE_SYS_PARAM_Hл65536ж0 +_GLIBCXX_HAVE_SYS_RESOURCE_Hл65536ж0 +_GLIBCXX_HAVE_SYS_SEM_Hл65536ж0 +_GLIBCXX_HAVE_SYS_STATVFS_Hл65536ж0 +_GLIBCXX_HAVE_SYS_STAT_Hл65536ж0 +_GLIBCXX_HAVE_SYS_SYSINFO_Hл65536ж0 +_GLIBCXX_HAVE_SYS_TIME_Hл65536ж0 +_GLIBCXX_HAVE_SYS_TYPES_Hл65536ж0 +_GLIBCXX_HAVE_SYS_UIO_Hл65536ж0 +_GLIBCXX_HAVE_S_ISREGл65536ж0 +_GLIBCXX_HAVE_TANFл65536ж0 +_GLIBCXX_HAVE_TANHFл65536ж0 +_GLIBCXX_HAVE_TANHLл65536ж0 +_GLIBCXX_HAVE_TANLл65536ж0 +_GLIBCXX_HAVE_TGMATH_Hл65536ж0 +_GLIBCXX_HAVE_TLSл65536ж0 +_GLIBCXX_HAVE_UCHAR_Hл65536ж0 +_GLIBCXX_HAVE_UNISTD_Hл65536ж0 +_GLIBCXX_HAVE_UTIME_Hл65536ж0 +_GLIBCXX_HAVE_VFWSCANFл65536ж0 +_GLIBCXX_HAVE_VSWSCANFл65536ж0 +_GLIBCXX_HAVE_VWSCANFл65536ж0 +_GLIBCXX_HAVE_WCHAR_Hл65536ж0 +_GLIBCXX_HAVE_WCSTOFл65536ж0 +_GLIBCXX_HAVE_WCTYPE_Hл65536ж0 +_GLIBCXX_HAVE_WRITEVл65536ж0 +_GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPLл65536ж0 +_GLIBCXX_HOSTEDл65536ж0 +_GLIBCXX_ICONV_CONSTл65536ж0 +_GLIBCXX_INCLUDE_NEXT_C_HEADERSл65536ж0 +_GLIBCXX_INLINE_VERSIONл65536ж0 +_GLIBCXX_LONG_DOUBLE_COMPATл65536ж0 +_GLIBCXX_MANGLE_SIZE_Tл65536ж0 +_GLIBCXX_MATH_Hл65536ж0 +_GLIBCXX_NAMESPACE_CXX11л65536ж0 +_GLIBCXX_NAMESPACE_LDBLл65536ж0 +_GLIBCXX_NAMESPACE_LDBL_OR_CXX11л65536ж0 +_GLIBCXX_NOEXCEPTл65536ж0 +_GLIBCXX_NOEXCEPT_IFл131072м(_COND)ж0 +_GLIBCXX_NORETURNл65536ж0 +_GLIBCXX_NOTHROWл65536ж0 +_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMICл65536ж0 +_GLIBCXX_OS_DEFINESл65536ж0 +_GLIBCXX_PACKAGE_BUGREPORTл65536ж0 +_GLIBCXX_PACKAGE_NAMEл65536ж0 +_GLIBCXX_PACKAGE_STRINGл65536ж0 +_GLIBCXX_PACKAGE_TARNAMEл65536ж0 +_GLIBCXX_PACKAGE_URLл65536ж0 +_GLIBCXX_PACKAGE__GLIBCXX_VERSIONл65536ж0 +_GLIBCXX_PSEUDO_VISIBILITYл131072м(V)ж0 +_GLIBCXX_PUREл65536ж0 +_GLIBCXX_RES_LIMITSл65536ж0 +_GLIBCXX_STDIO_EOFл65536ж0 +_GLIBCXX_STDIO_SEEK_CURл65536ж0 +_GLIBCXX_STDIO_SEEK_ENDл65536ж0 +_GLIBCXX_STDLIB_Hл65536ж0 +_GLIBCXX_STD_Aл65536ж0 +_GLIBCXX_STD_Cл65536ж0 +_GLIBCXX_SYMVERл65536ж0 +_GLIBCXX_SYMVER_GNUл65536ж0 +_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTERл131072м(A)ж0 +_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFOREл131072м(A)ж0 +_GLIBCXX_THROWл131072м(_EXC)ж0 +_GLIBCXX_THROW_OR_ABORTл131072м(_EXC)ж0 +_GLIBCXX_TXN_SAFEл65536ж0 +_GLIBCXX_TXN_SAFE_DYNл65536ж0 +_GLIBCXX_USE_ALLOCATOR_NEWл65536ж0 +_GLIBCXX_USE_C11_UCHAR_CXX11л65536ж0 +_GLIBCXX_USE_C99л65536ж0 +_GLIBCXX_USE_C99_COMPLEXл65536ж0 +_GLIBCXX_USE_C99_COMPLEX_TR1л65536ж0 +_GLIBCXX_USE_C99_CTYPE_TR1л65536ж0 +_GLIBCXX_USE_C99_FENV_TR1л65536ж0 +_GLIBCXX_USE_C99_INTTYPES_TR1л65536ж0 +_GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1л65536ж0 +_GLIBCXX_USE_C99_MATHл65536ж0 +_GLIBCXX_USE_C99_MATH_TR1л65536ж0 +_GLIBCXX_USE_C99_STDINT_TR1л65536ж0 +_GLIBCXX_USE_C99_STDIOл65536ж0 +_GLIBCXX_USE_C99_STDLIBл65536ж0 +_GLIBCXX_USE_C99_WCHARл65536ж0 +_GLIBCXX_USE_CLOCK_MONOTONICл65536ж0 +_GLIBCXX_USE_CLOCK_REALTIMEл65536ж0 +_GLIBCXX_USE_CONSTEXPRл65536ж0 +_GLIBCXX_USE_CXX11_ABIл65536ж0 +_GLIBCXX_USE_DECIMAL_FLOATл65536ж0 +_GLIBCXX_USE_DEPRECATEDл65536ж0 +_GLIBCXX_USE_DUAL_ABIл65536ж0 +_GLIBCXX_USE_FCHMODл65536ж0 +_GLIBCXX_USE_FCHMODATл65536ж0 +_GLIBCXX_USE_FLOAT128л65536ж0 +_GLIBCXX_USE_GETTIMEOFDAYл65536ж0 +_GLIBCXX_USE_GET_NPROCSл65536ж0 +_GLIBCXX_USE_INT128л65536ж0 +_GLIBCXX_USE_LFSл65536ж0 +_GLIBCXX_USE_LONG_LONGл65536ж0 +_GLIBCXX_USE_NANOSLEEPл65536ж0 +_GLIBCXX_USE_NLSл65536ж0 +_GLIBCXX_USE_NOEXCEPTл65536ж0 +_GLIBCXX_USE_PTHREAD_RWLOCK_Tл65536ж0 +_GLIBCXX_USE_RANDOM_TR1л65536ж0 +_GLIBCXX_USE_REALPATHл65536ж0 +_GLIBCXX_USE_SCHED_YIELDл65536ж0 +_GLIBCXX_USE_SC_NPROCESSORS_ONLNл65536ж0 +_GLIBCXX_USE_SENDFILEл65536ж0 +_GLIBCXX_USE_ST_MTIMл65536ж0 +_GLIBCXX_USE_TMPNAMл65536ж0 +_GLIBCXX_USE_UTIMENSATл65536ж0 +_GLIBCXX_USE_WCHAR_Tл65536ж0 +_GLIBCXX_USE_WEAK_REFл65536ж0 +_GLIBCXX_VERBOSEл65536ж0 +_GLIBCXX_VISIBILITYл131072м(V)ж0 +_GLIBCXX_WEAK_DEFINITIONл65536ж0 +_GLIBCXX_X86_RDRANDл65536ж0 +_GNU_SOURCEл65536ж0 +_GTHREAD_USE_MUTEX_TIMEDLOCKл65536ж0 +_G_BUFSIZл65536ж0 +_G_HAVE_MMAPл65536ж0 +_G_HAVE_MREMAPл65536ж0 +_G_HAVE_ST_BLKSIZEл65536ж0 +_G_IO_IO_FILE_VERSIONл65536ж0 +_G_config_hл65536ж0 +_G_va_listл65536ж0 +_HAVE_STRUCT_TERMIOS_C_ISPEEDл65536ж0 +_HAVE_STRUCT_TERMIOS_C_OSPEEDл65536ж0 +_IOл131072м(type,nr)ж0 +_IOCл131072м(dir,type,nr,size)ж0 +_IOC_DIRл131072м(nr)ж0 +_IOC_DIRBITSл65536ж0 +_IOC_DIRMASKл65536ж0 +_IOC_DIRSHIFTл65536ж0 +_IOC_NONEл65536ж0 +_IOC_NRл131072м(nr)ж0 +_IOC_NRBITSл65536ж0 +_IOC_NRMASKл65536ж0 +_IOC_NRSHIFTл65536ж0 +_IOC_READл65536ж0 +_IOC_SIZEл131072м(nr)ж0 +_IOC_SIZEBITSл65536ж0 +_IOC_SIZEMASKл65536ж0 +_IOC_SIZESHIFTл65536ж0 +_IOC_TYPEл131072м(nr)ж0 +_IOC_TYPEBITSл65536ж0 +_IOC_TYPECHECKл131072м(t)ж0 +_IOC_TYPEMASKл65536ж0 +_IOC_TYPESHIFTл65536ж0 +_IOC_WRITEл65536ж0 +_IOFBFл65536ж0 +_IOLBFл65536ж0 +_IONBFл65536ж0 +_IORл131072м(type,nr,size)ж0 +_IOR_BADл131072м(type,nr,size)ж0 +_IOS_APPENDл65536ж0 +_IOS_ATENDл65536ж0 +_IOS_BINл65536ж0 +_IOS_INPUTл65536ж0 +_IOS_NOCREATEл65536ж0 +_IOS_NOREPLACEл65536ж0 +_IOS_OUTPUTл65536ж0 +_IOS_TRUNCл65536ж0 +_IOT_termiosл65536ж0 +_IOWл131072м(type,nr,size)ж0 +_IOWRл131072м(type,nr,size)ж0 +_IOWR_BADл131072м(type,nr,size)ж0 +_IOW_BADл131072м(type,nr,size)ж0 +_IO_BAD_SEENл65536ж0 +_IO_BEл131072м(expr,res)ж0 +_IO_BOOLALPHAл65536ж0 +_IO_BUFSIZл65536ж0 +_IO_CURRENTLY_PUTTINGл65536ж0 +_IO_DECл65536ж0 +_IO_DELETE_DONT_CLOSEл65536ж0 +_IO_DONT_CLOSEл65536ж0 +_IO_EOF_SEENл65536ж0 +_IO_ERR_SEENл65536ж0 +_IO_FIXEDл65536ж0 +_IO_FLAGS2_MMAPл65536ж0 +_IO_FLAGS2_NOTCANCELл65536ж0 +_IO_FLAGS2_USER_WBUFл65536ж0 +_IO_HAVE_ST_BLKSIZEл65536ж0 +_IO_HEXл65536ж0 +_IO_INTERNALл65536ж0 +_IO_IN_BACKUPл65536ж0 +_IO_IS_APPENDINGл65536ж0 +_IO_IS_FILEBUFл65536ж0 +_IO_LEFTл65536ж0 +_IO_LINE_BUFл65536ж0 +_IO_LINKEDл65536ж0 +_IO_MAGICл65536ж0 +_IO_MAGIC_MASKл65536ж0 +_IO_NO_READSл65536ж0 +_IO_NO_WRITESл65536ж0 +_IO_OCTл65536ж0 +_IO_PENDING_OUTPUT_COUNTл131072м(_fp)ж0 +_IO_RIGHTл65536ж0 +_IO_SCIENTIFICл65536ж0 +_IO_SHOWBASEл65536ж0 +_IO_SHOWPOINTл65536ж0 +_IO_SHOWPOSл65536ж0 +_IO_SKIPWSл65536ж0 +_IO_STDIOл65536ж0 +_IO_STDIO_Hл65536ж0 +_IO_TIED_PUT_GETл65536ж0 +_IO_UNBUFFEREDл65536ж0 +_IO_UNIFIED_JUMPTABLESл65536ж0 +_IO_UNITBUFл65536ж0 +_IO_UPPERCASEл65536ж0 +_IO_USER_BUFл65536ж0 +_IO_USER_LOCKл65536ж0 +_IO_cleanup_region_endл131072м(_Doit)ж0 +_IO_cleanup_region_startл131072м(_fct,_fp)ж0 +_IO_feof_unlockedл131072м(__fp)ж0 +_IO_ferror_unlockedл131072м(__fp)ж0 +_IO_file_flagsл65536ж0 +_IO_flockfileл131072м(_fp)ж0 +_IO_fpos64_tл65536ж0 +_IO_fpos_tл65536ж0 +_IO_ftrylockfileл131072м(_fp)ж0 +_IO_funlockfileл131072м(_fp)ж0 +_IO_getc_unlockedл131072м(_fp)ж0 +_IO_iconv_tл65536ж0 +_IO_need_lockл131072м(_fp)ж0 +_IO_off64_tл65536ж0 +_IO_off_tл65536ж0 +_IO_peekcл131072м(_fp)ж0 +_IO_peekc_unlockedл131072м(_fp)ж0 +_IO_pid_tл65536ж0 +_IO_putc_unlockedл131072м(_ch,_fp)ж0 +_IO_size_tл65536ж0 +_IO_ssize_tл65536ж0 +_IO_stderrл65536ж0 +_IO_stdinл65536ж0 +_IO_stdoutл65536ж0 +_IO_uid_tл65536ж0 +_IO_va_listл65536ж0 +_IO_wint_tл65536ж0 +_ISOC11_SOURCEл65536ж0 +_ISOC95_SOURCEл65536ж0 +_ISOC99_SOURCEл65536ж0 +_ISbitл131072м(bit)ж0 +_LARGEFILE64_SOURCEл65536ж0 +_LARGEFILE_SOURCEл65536ж0 +_LFS64_ASYNCHRONOUS_IOл65536ж0 +_LFS64_LARGEFILEл65536ж0 +_LFS64_STDIOл65536ж0 +_LFS_ASYNCHRONOUS_IOл65536ж0 +_LFS_LARGEFILEл65536ж0 +_LIBC_LIMITS_H_л65536ж0 +_LIBINTL_Hл65536ж0 +_LIMITS_H___л65536ж0 +_LINUX_IOCTL_Hл65536ж0 +_LINUX_LIMITS_Hл65536ж0 +_LINUX_POSIX_TYPES_Hл65536ж0 +_LINUX_PRCTL_Hл65536ж0 +_LINUX_TYPES_Hл65536ж0 +_LOCALE_Hл65536ж0 +_LP64л65536ж0 +_MATH_Hл65536ж0 +_MKNOD_VERл65536ж0 +_MKNOD_VER_LINUXл65536ж0 +_Mdouble_л65536ж0 +_Mfloat128_л65536ж0 +_Mfloat_л65536ж0 +_Mlong_double_л65536ж0 +_NETDB_Hл65536ж0 +_NETINET_IN_Hл65536ж0 +_NSIGл65536ж0 +_OLD_STDIO_MAGICл65536ж0 +_PATH_HEQUIVл65536ж0 +_PATH_HOSTSл65536ж0 +_PATH_NETWORKSл65536ж0 +_PATH_NSSWITCH_CONFл65536ж0 +_PATH_PROTOCOLSл65536ж0 +_PATH_SERVICESл65536ж0 +_PC_2_SYMLINKSл65536ж0 +_PC_ALLOC_SIZE_MINл65536ж0 +_PC_ASYNC_IOл65536ж0 +_PC_CHOWN_RESTRICTEDл65536ж0 +_PC_FILESIZEBITSл65536ж0 +_PC_LINK_MAXл65536ж0 +_PC_MAX_CANONл65536ж0 +_PC_MAX_INPUTл65536ж0 +_PC_NAME_MAXл65536ж0 +_PC_NO_TRUNCл65536ж0 +_PC_PATH_MAXл65536ж0 +_PC_PIPE_BUFл65536ж0 +_PC_PRIO_IOл65536ж0 +_PC_REC_INCR_XFER_SIZEл65536ж0 +_PC_REC_MAX_XFER_SIZEл65536ж0 +_PC_REC_MIN_XFER_SIZEл65536ж0 +_PC_REC_XFER_ALIGNл65536ж0 +_PC_SOCK_MAXBUFл65536ж0 +_PC_SYMLINK_MAXл65536ж0 +_PC_SYNC_IOл65536ж0 +_PC_VDISABLEл65536ж0 +_POSIX2_BC_BASE_MAXл65536ж0 +_POSIX2_BC_DIM_MAXл65536ж0 +_POSIX2_BC_SCALE_MAXл65536ж0 +_POSIX2_BC_STRING_MAXл65536ж0 +_POSIX2_CHARCLASS_NAME_MAXл65536ж0 +_POSIX2_CHAR_TERMл65536ж0 +_POSIX2_COLL_WEIGHTS_MAXл65536ж0 +_POSIX2_C_BINDл65536ж0 +_POSIX2_C_DEVл65536ж0 +_POSIX2_C_VERSIONл65536ж0 +_POSIX2_EXPR_NEST_MAXл65536ж0 +_POSIX2_LINE_MAXл65536ж0 +_POSIX2_LOCALEDEFл65536ж0 +_POSIX2_RE_DUP_MAXл65536ж0 +_POSIX2_SW_DEVл65536ж0 +_POSIX2_VERSIONл65536ж0 +_POSIX_ADVISORY_INFOл65536ж0 +_POSIX_AIO_LISTIO_MAXл65536ж0 +_POSIX_AIO_MAXл65536ж0 +_POSIX_ARG_MAXл65536ж0 +_POSIX_ASYNCHRONOUS_IOл65536ж0 +_POSIX_ASYNC_IOл65536ж0 +_POSIX_BARRIERSл65536ж0 +_POSIX_CHILD_MAXл65536ж0 +_POSIX_CHOWN_RESTRICTEDл65536ж0 +_POSIX_CLOCKRES_MINл65536ж0 +_POSIX_CLOCK_SELECTIONл65536ж0 +_POSIX_CPUTIMEл65536ж0 +_POSIX_C_SOURCEл65536ж0 +_POSIX_DELAYTIMER_MAXл65536ж0 +_POSIX_FD_SETSIZEл65536ж0 +_POSIX_FSYNCл65536ж0 +_POSIX_HIWATл65536ж0 +_POSIX_HOST_NAME_MAXл65536ж0 +_POSIX_IPV6л65536ж0 +_POSIX_JOB_CONTROLл65536ж0 +_POSIX_LINK_MAXл65536ж0 +_POSIX_LOGIN_NAME_MAXл65536ж0 +_POSIX_MAPPED_FILESл65536ж0 +_POSIX_MAX_CANONл65536ж0 +_POSIX_MAX_INPUTл65536ж0 +_POSIX_MEMLOCKл65536ж0 +_POSIX_MEMLOCK_RANGEл65536ж0 +_POSIX_MEMORY_PROTECTIONл65536ж0 +_POSIX_MESSAGE_PASSINGл65536ж0 +_POSIX_MONOTONIC_CLOCKл65536ж0 +_POSIX_MQ_OPEN_MAXл65536ж0 +_POSIX_MQ_PRIO_MAXл65536ж0 +_POSIX_NAME_MAXл65536ж0 +_POSIX_NGROUPS_MAXл65536ж0 +_POSIX_NO_TRUNCл65536ж0 +_POSIX_OPEN_MAXл65536ж0 +_POSIX_PATH_MAXл65536ж0 +_POSIX_PIPE_BUFл65536ж0 +_POSIX_PRIORITIZED_IOл65536ж0 +_POSIX_PRIORITY_SCHEDULINGл65536ж0 +_POSIX_QLIMITл65536ж0 +_POSIX_RAW_SOCKETSл65536ж0 +_POSIX_READER_WRITER_LOCKSл65536ж0 +_POSIX_REALTIME_SIGNALSл65536ж0 +_POSIX_REENTRANT_FUNCTIONSл65536ж0 +_POSIX_REGEXPл65536ж0 +_POSIX_RE_DUP_MAXл65536ж0 +_POSIX_RTSIG_MAXл65536ж0 +_POSIX_SAVED_IDSл65536ж0 +_POSIX_SEMAPHORESл65536ж0 +_POSIX_SEM_NSEMS_MAXл65536ж0 +_POSIX_SEM_VALUE_MAXл65536ж0 +_POSIX_SHARED_MEMORY_OBJECTSл65536ж0 +_POSIX_SHELLл65536ж0 +_POSIX_SIGQUEUE_MAXл65536ж0 +_POSIX_SOURCEл65536ж0 +_POSIX_SPAWNл65536ж0 +_POSIX_SPIN_LOCKSл65536ж0 +_POSIX_SPORADIC_SERVERл65536ж0 +_POSIX_SSIZE_MAXл65536ж0 +_POSIX_STREAM_MAXл65536ж0 +_POSIX_SYMLINK_MAXл65536ж0 +_POSIX_SYMLOOP_MAXл65536ж0 +_POSIX_SYNCHRONIZED_IOл65536ж0 +_POSIX_THREADSл65536ж0 +_POSIX_THREAD_ATTR_STACKADDRл65536ж0 +_POSIX_THREAD_ATTR_STACKSIZEл65536ж0 +_POSIX_THREAD_CPUTIMEл65536ж0 +_POSIX_THREAD_DESTRUCTOR_ITERATIONSл65536ж0 +_POSIX_THREAD_KEYS_MAXл65536ж0 +_POSIX_THREAD_PRIORITY_SCHEDULINGл65536ж0 +_POSIX_THREAD_PRIO_INHERITл65536ж0 +_POSIX_THREAD_PRIO_PROTECTл65536ж0 +_POSIX_THREAD_PROCESS_SHAREDл65536ж0 +_POSIX_THREAD_ROBUST_PRIO_INHERITл65536ж0 +_POSIX_THREAD_ROBUST_PRIO_PROTECTл65536ж0 +_POSIX_THREAD_SAFE_FUNCTIONSл65536ж0 +_POSIX_THREAD_SPORADIC_SERVERл65536ж0 +_POSIX_THREAD_THREADS_MAXл65536ж0 +_POSIX_TIMEOUTSл65536ж0 +_POSIX_TIMERSл65536ж0 +_POSIX_TIMER_MAXл65536ж0 +_POSIX_TRACEл65536ж0 +_POSIX_TRACE_EVENT_FILTERл65536ж0 +_POSIX_TRACE_INHERITл65536ж0 +_POSIX_TRACE_LOGл65536ж0 +_POSIX_TTY_NAME_MAXл65536ж0 +_POSIX_TYPED_MEMORY_OBJECTSл65536ж0 +_POSIX_TZNAME_MAXл65536ж0 +_POSIX_UIO_MAXIOVл65536ж0 +_POSIX_V6_LP64_OFF64л65536ж0 +_POSIX_V6_LPBIG_OFFBIGл65536ж0 +_POSIX_V7_LP64_OFF64л65536ж0 +_POSIX_V7_LPBIG_OFFBIGл65536ж0 +_POSIX_VDISABLEл65536ж0 +_POSIX_VERSIONл65536ж0 +_PTHREAD_Hл65536ж0 +_RPC_NETDB_Hл65536ж0 +_SCHED_Hл65536ж0 +_SC_2_CHAR_TERMл65536ж0 +_SC_2_C_BINDл65536ж0 +_SC_2_C_DEVл65536ж0 +_SC_2_C_VERSIONл65536ж0 +_SC_2_FORT_DEVл65536ж0 +_SC_2_FORT_RUNл65536ж0 +_SC_2_LOCALEDEFл65536ж0 +_SC_2_PBSл65536ж0 +_SC_2_PBS_ACCOUNTINGл65536ж0 +_SC_2_PBS_CHECKPOINTл65536ж0 +_SC_2_PBS_LOCATEл65536ж0 +_SC_2_PBS_MESSAGEл65536ж0 +_SC_2_PBS_TRACKл65536ж0 +_SC_2_SW_DEVл65536ж0 +_SC_2_UPEл65536ж0 +_SC_2_VERSIONл65536ж0 +_SC_ADVISORY_INFOл65536ж0 +_SC_AIO_LISTIO_MAXл65536ж0 +_SC_AIO_MAXл65536ж0 +_SC_AIO_PRIO_DELTA_MAXл65536ж0 +_SC_ARG_MAXл65536ж0 +_SC_ASYNCHRONOUS_IOл65536ж0 +_SC_ATEXIT_MAXл65536ж0 +_SC_AVPHYS_PAGESл65536ж0 +_SC_BARRIERSл65536ж0 +_SC_BASEл65536ж0 +_SC_BC_BASE_MAXл65536ж0 +_SC_BC_DIM_MAXл65536ж0 +_SC_BC_SCALE_MAXл65536ж0 +_SC_BC_STRING_MAXл65536ж0 +_SC_CHARCLASS_NAME_MAXл65536ж0 +_SC_CHAR_BITл65536ж0 +_SC_CHAR_MAXл65536ж0 +_SC_CHAR_MINл65536ж0 +_SC_CHILD_MAXл65536ж0 +_SC_CLK_TCKл65536ж0 +_SC_CLOCK_SELECTIONл65536ж0 +_SC_COLL_WEIGHTS_MAXл65536ж0 +_SC_CPUTIMEл65536ж0 +_SC_C_LANG_SUPPORTл65536ж0 +_SC_C_LANG_SUPPORT_Rл65536ж0 +_SC_DELAYTIMER_MAXл65536ж0 +_SC_DEVICE_IOл65536ж0 +_SC_DEVICE_SPECIFICл65536ж0 +_SC_DEVICE_SPECIFIC_Rл65536ж0 +_SC_EQUIV_CLASS_MAXл65536ж0 +_SC_EXPR_NEST_MAXл65536ж0 +_SC_FD_MGMTл65536ж0 +_SC_FIFOл65536ж0 +_SC_FILE_ATTRIBUTESл65536ж0 +_SC_FILE_LOCKINGл65536ж0 +_SC_FILE_SYSTEMл65536ж0 +_SC_FSYNCл65536ж0 +_SC_GETGR_R_SIZE_MAXл65536ж0 +_SC_GETPW_R_SIZE_MAXл65536ж0 +_SC_HOST_NAME_MAXл65536ж0 +_SC_INT_MAXл65536ж0 +_SC_INT_MINл65536ж0 +_SC_IOV_MAXл65536ж0 +_SC_IPV6л65536ж0 +_SC_JOB_CONTROLл65536ж0 +_SC_LEVEL1_DCACHE_ASSOCл65536ж0 +_SC_LEVEL1_DCACHE_LINESIZEл65536ж0 +_SC_LEVEL1_DCACHE_SIZEл65536ж0 +_SC_LEVEL1_ICACHE_ASSOCл65536ж0 +_SC_LEVEL1_ICACHE_LINESIZEл65536ж0 +_SC_LEVEL1_ICACHE_SIZEл65536ж0 +_SC_LEVEL2_CACHE_ASSOCл65536ж0 +_SC_LEVEL2_CACHE_LINESIZEл65536ж0 +_SC_LEVEL2_CACHE_SIZEл65536ж0 +_SC_LEVEL3_CACHE_ASSOCл65536ж0 +_SC_LEVEL3_CACHE_LINESIZEл65536ж0 +_SC_LEVEL3_CACHE_SIZEл65536ж0 +_SC_LEVEL4_CACHE_ASSOCл65536ж0 +_SC_LEVEL4_CACHE_LINESIZEл65536ж0 +_SC_LEVEL4_CACHE_SIZEл65536ж0 +_SC_LINE_MAXл65536ж0 +_SC_LOGIN_NAME_MAXл65536ж0 +_SC_LONG_BITл65536ж0 +_SC_MAPPED_FILESл65536ж0 +_SC_MB_LEN_MAXл65536ж0 +_SC_MEMLOCKл65536ж0 +_SC_MEMLOCK_RANGEл65536ж0 +_SC_MEMORY_PROTECTIONл65536ж0 +_SC_MESSAGE_PASSINGл65536ж0 +_SC_MONOTONIC_CLOCKл65536ж0 +_SC_MQ_OPEN_MAXл65536ж0 +_SC_MQ_PRIO_MAXл65536ж0 +_SC_MULTI_PROCESSл65536ж0 +_SC_NETWORKINGл65536ж0 +_SC_NGROUPS_MAXл65536ж0 +_SC_NL_ARGMAXл65536ж0 +_SC_NL_LANGMAXл65536ж0 +_SC_NL_MSGMAXл65536ж0 +_SC_NL_NMAXл65536ж0 +_SC_NL_SETMAXл65536ж0 +_SC_NL_TEXTMAXл65536ж0 +_SC_NPROCESSORS_CONFл65536ж0 +_SC_NPROCESSORS_ONLNл65536ж0 +_SC_NZEROл65536ж0 +_SC_OPEN_MAXл65536ж0 +_SC_PAGESIZEл65536ж0 +_SC_PAGE_SIZEл65536ж0 +_SC_PASS_MAXл65536ж0 +_SC_PHYS_PAGESл65536ж0 +_SC_PIIл65536ж0 +_SC_PII_INTERNETл65536ж0 +_SC_PII_INTERNET_DGRAMл65536ж0 +_SC_PII_INTERNET_STREAMл65536ж0 +_SC_PII_OSIл65536ж0 +_SC_PII_OSI_CLTSл65536ж0 +_SC_PII_OSI_COTSл65536ж0 +_SC_PII_OSI_Mл65536ж0 +_SC_PII_SOCKETл65536ж0 +_SC_PII_XTIл65536ж0 +_SC_PIPEл65536ж0 +_SC_POLLл65536ж0 +_SC_PRIORITIZED_IOл65536ж0 +_SC_PRIORITY_SCHEDULINGл65536ж0 +_SC_RAW_SOCKETSл65536ж0 +_SC_READER_WRITER_LOCKSл65536ж0 +_SC_REALTIME_SIGNALSл65536ж0 +_SC_REGEXPл65536ж0 +_SC_REGEX_VERSIONл65536ж0 +_SC_RE_DUP_MAXл65536ж0 +_SC_RTSIG_MAXл65536ж0 +_SC_SAVED_IDSл65536ж0 +_SC_SCHAR_MAXл65536ж0 +_SC_SCHAR_MINл65536ж0 +_SC_SELECTл65536ж0 +_SC_SEMAPHORESл65536ж0 +_SC_SEM_NSEMS_MAXл65536ж0 +_SC_SEM_VALUE_MAXл65536ж0 +_SC_SHARED_MEMORY_OBJECTSл65536ж0 +_SC_SHELLл65536ж0 +_SC_SHRT_MAXл65536ж0 +_SC_SHRT_MINл65536ж0 +_SC_SIGNALSл65536ж0 +_SC_SIGQUEUE_MAXл65536ж0 +_SC_SINGLE_PROCESSл65536ж0 +_SC_SPAWNл65536ж0 +_SC_SPIN_LOCKSл65536ж0 +_SC_SPORADIC_SERVERл65536ж0 +_SC_SSIZE_MAXл65536ж0 +_SC_SS_REPL_MAXл65536ж0 +_SC_STREAMSл65536ж0 +_SC_STREAM_MAXл65536ж0 +_SC_SYMLOOP_MAXл65536ж0 +_SC_SYNCHRONIZED_IOл65536ж0 +_SC_SYSTEM_DATABASEл65536ж0 +_SC_SYSTEM_DATABASE_Rл65536ж0 +_SC_THREADSл65536ж0 +_SC_THREAD_ATTR_STACKADDRл65536ж0 +_SC_THREAD_ATTR_STACKSIZEл65536ж0 +_SC_THREAD_CPUTIMEл65536ж0 +_SC_THREAD_DESTRUCTOR_ITERATIONSл65536ж0 +_SC_THREAD_KEYS_MAXл65536ж0 +_SC_THREAD_PRIORITY_SCHEDULINGл65536ж0 +_SC_THREAD_PRIO_INHERITл65536ж0 +_SC_THREAD_PRIO_PROTECTл65536ж0 +_SC_THREAD_PROCESS_SHAREDл65536ж0 +_SC_THREAD_ROBUST_PRIO_INHERITл65536ж0 +_SC_THREAD_ROBUST_PRIO_PROTECTл65536ж0 +_SC_THREAD_SAFE_FUNCTIONSл65536ж0 +_SC_THREAD_SPORADIC_SERVERл65536ж0 +_SC_THREAD_STACK_MINл65536ж0 +_SC_THREAD_THREADS_MAXл65536ж0 +_SC_TIMEOUTSл65536ж0 +_SC_TIMERSл65536ж0 +_SC_TIMER_MAXл65536ж0 +_SC_TRACEл65536ж0 +_SC_TRACE_EVENT_FILTERл65536ж0 +_SC_TRACE_EVENT_NAME_MAXл65536ж0 +_SC_TRACE_INHERITл65536ж0 +_SC_TRACE_LOGл65536ж0 +_SC_TRACE_NAME_MAXл65536ж0 +_SC_TRACE_SYS_MAXл65536ж0 +_SC_TRACE_USER_EVENT_MAXл65536ж0 +_SC_TTY_NAME_MAXл65536ж0 +_SC_TYPED_MEMORY_OBJECTSл65536ж0 +_SC_TZNAME_MAXл65536ж0 +_SC_T_IOV_MAXл65536ж0 +_SC_UCHAR_MAXл65536ж0 +_SC_UINT_MAXл65536ж0 +_SC_UIO_MAXIOVл65536ж0 +_SC_ULONG_MAXл65536ж0 +_SC_USER_GROUPSл65536ж0 +_SC_USER_GROUPS_Rл65536ж0 +_SC_USHRT_MAXл65536ж0 +_SC_V6_ILP32_OFF32л65536ж0 +_SC_V6_ILP32_OFFBIGл65536ж0 +_SC_V6_LP64_OFF64л65536ж0 +_SC_V6_LPBIG_OFFBIGл65536ж0 +_SC_V7_ILP32_OFF32л65536ж0 +_SC_V7_ILP32_OFFBIGл65536ж0 +_SC_V7_LP64_OFF64л65536ж0 +_SC_V7_LPBIG_OFFBIGл65536ж0 +_SC_VERSIONл65536ж0 +_SC_WORD_BITл65536ж0 +_SC_XBS5_ILP32_OFF32л65536ж0 +_SC_XBS5_ILP32_OFFBIGл65536ж0 +_SC_XBS5_LP64_OFF64л65536ж0 +_SC_XBS5_LPBIG_OFFBIGл65536ж0 +_SC_XOPEN_CRYPTл65536ж0 +_SC_XOPEN_ENH_I18Nл65536ж0 +_SC_XOPEN_LEGACYл65536ж0 +_SC_XOPEN_REALTIMEл65536ж0 +_SC_XOPEN_REALTIME_THREADSл65536ж0 +_SC_XOPEN_SHMл65536ж0 +_SC_XOPEN_STREAMSл65536ж0 +_SC_XOPEN_UNIXл65536ж0 +_SC_XOPEN_VERSIONл65536ж0 +_SC_XOPEN_XCU_VERSIONл65536ж0 +_SC_XOPEN_XPG2л65536ж0 +_SC_XOPEN_XPG3л65536ж0 +_SC_XOPEN_XPG4л65536ж0 +_SIGNAL_Hл65536ж0 +_SIGSET_NWORDSл65536ж0 +_SIZET_л65536ж0 +_SIZE_Tл65536ж0 +_SIZE_T_л65536ж0 +_SIZE_T_DECLAREDл65536ж0 +_SIZE_T_DEFINEDл65536ж0 +_SIZE_T_DEFINED_л65536ж0 +_SS_PADSIZEл65536ж0 +_SS_SIZEл65536ж0 +_STATBUF_ST_BLKSIZEл65536ж0 +_STATBUF_ST_NSECл65536ж0 +_STATBUF_ST_RDEVл65536ж0 +_STAT_VERл65536ж0 +_STAT_VER_KERNELл65536ж0 +_STAT_VER_LINUXл65536ж0 +_STDARG_Hл65536ж0 +_STDBOOL_Hл65536ж0 +_STDC_PREDEF_Hл65536ж0 +_STDINT_Hл65536ж0 +_STDIO_Hл65536ж0 +_STDIO_USES_IOSTREAMл65536ж0 +_STDLIB_Hл65536ж0 +_STRINGS_Hл65536ж0 +_STRING_Hл65536ж0 +_SYSCALL_Hл65536ж0 +_SYS_CDEFS_Hл65536ж0 +_SYS_IOCTL_Hл65536ж0 +_SYS_MMAN_Hл65536ж0 +_SYS_PRCTL_Hл65536ж0 +_SYS_SELECT_Hл65536ж0 +_SYS_SIZE_T_Hл65536ж0 +_SYS_SOCKET_Hл65536ж0 +_SYS_STAT_Hл65536ж0 +_SYS_TIME_Hл65536ж0 +_SYS_TTYDEFAULTS_H_л65536ж0 +_SYS_TYPES_Hл65536ж0 +_SYS_UCONTEXT_Hл65536ж0 +_SYS_WAIT_Hл65536ж0 +_TERMIOS_Hл65536ж0 +_THREAD_SHARED_TYPES_Hл65536ж0 +_TIME_Hл65536ж0 +_T_SIZEл65536ж0 +_T_SIZE_л65536ж0 +_T_WCHARл65536ж0 +_T_WCHAR_л65536ж0 +_UNISTD_Hл65536ж0 +_U_л65536ж0 +_VA_LISTл65536ж0 +_VA_LIST_л65536ж0 +_VA_LIST_DEFINEDл65536ж0 +_VA_LIST_T_Hл65536ж0 +_WARNл1024м(const char *fmt, ...)ж0оint +_WCHAR_Tл65536ж0 +_WCHAR_T_л65536ж0 +_WCHAR_T_DECLAREDл65536ж0 +_WCHAR_T_DEFINEDл65536ж0 +_WCHAR_T_DEFINED_л65536ж0 +_WCHAR_T_Hл65536ж0 +_XBS5_LP64_OFF64л65536ж0 +_XBS5_LPBIG_OFFBIGл65536ж0 +_XOPEN_CRYPTл65536ж0 +_XOPEN_ENH_I18Nл65536ж0 +_XOPEN_IOV_MAXл65536ж0 +_XOPEN_LEGACYл65536ж0 +_XOPEN_LIM_Hл65536ж0 +_XOPEN_REALTIMEл65536ж0 +_XOPEN_REALTIME_THREADSл65536ж0 +_XOPEN_SHMл65536ж0 +_XOPEN_SOURCEл65536ж0 +_XOPEN_SOURCE_EXTENDEDл65536ж0 +_XOPEN_UNIXл65536ж0 +_XOPEN_VERSIONл65536ж0 +_XOPEN_XCU_VERSIONл65536ж0 +_XOPEN_XPG2л65536ж0 +_XOPEN_XPG3л65536ж0 +_XOPEN_XPG4л65536ж0 +__ASMNAMEл131072м(cname)ж0 +__ASMNAME2л131072м(prefix,cname)ж0 +__ASM_GENERIC_BITS_PER_LONGл65536ж0 +__ASM_GENERIC_IOCTLS_Hл65536ж0 +__ASM_GENERIC_POSIX_TYPES_Hл65536ж0 +__ASM_GENERIC_SOCKET_Hл65536ж0 +__ASM_GENERIC_SOCKIOS_Hл65536ж0 +__ASM_X86_BITSPERLONG_Hл65536ж0 +__ASSERT_FUNCTIONл65536ж0 +__ASSERT_VOID_CASTл65536ж0 +__ATOMIC_ACQUIREл65536ж0 +__ATOMIC_ACQ_RELл65536ж0 +__ATOMIC_CONSUMEл65536ж0 +__ATOMIC_HLE_ACQUIREл65536ж0 +__ATOMIC_HLE_RELEASEл65536ж0 +__ATOMIC_RELAXEDл65536ж0 +__ATOMIC_RELEASEл65536ж0 +__ATOMIC_SEQ_CSTл65536ж0 +__BEGIN_DECLSл65536ж0 +__BIGGEST_ALIGNMENT__л65536ж0 +__BIG_ENDIANл65536ж0 +__BITS_PER_LONGл65536ж0 +__BITS_SOCKET_Hл65536ж0 +__BIT_TYPES_DEFINED__л65536ж0 +__BLKCNT64_T_TYPEл65536ж0 +__BLKCNT_T_TYPEл65536ж0 +__BLKSIZE_T_TYPEл65536ж0 +__BYTE_ORDERл65536ж0 +__BYTE_ORDER__л65536ж0 +__CFLOAT128л65536ж0 +__CHAR16_TYPE__л65536ж0 +__CHAR32_TYPE__л65536ж0 +__CHAR_BIT__л65536ж0 +__CLOCKID_T_TYPEл65536ж0 +__CLOCK_T_TYPEл65536ж0 +__CMDLNOPTS_H__л65536ж0 +__COMPAR_FN_Tл65536ж0 +__CONCATл131072м(x,y)ж0 +__CONST_SOCKADDR_ARGл65536ж0 +__CORRECT_ISO_CPP_STRINGS_H_PROTOл65536ж0 +__CORRECT_ISO_CPP_STRING_H_PROTOл65536ж0 +__CPUELTл131072м(cpu)ж0 +__CPUMASKл131072м(cpu)ж0 +__CPU_ALLOCл131072м(count)ж0 +__CPU_ALLOC_SIZEл131072м(count)ж0 +__CPU_CLR_Sл131072м(cpu,setsize,cpusetp)ж0 +__CPU_COUNT_Sл131072м(setsize,cpusetp)ж0 +__CPU_EQUAL_Sл131072м(setsize,cpusetp1,cpusetp2)ж0 +__CPU_FREEл131072м(cpuset)ж0 +__CPU_ISSET_Sл131072м(cpu,setsize,cpusetp)ж0 +__CPU_MASK_TYPEл65536ж0 +__CPU_OP_Sл131072м(setsize,destset,srcset1,srcset2,op)ж0 +__CPU_SETSIZEл65536ж0 +__CPU_SET_Sл131072м(cpu,setsize,cpusetp)ж0 +__CPU_ZERO_Sл131072м(setsize,cpusetp)ж0 +__DADDR_T_TYPEл65536ж0 +__DBL_DECIMAL_DIG__л65536ж0 +__DBL_DENORM_MIN__л65536ж0 +__DBL_DIG__л65536ж0 +__DBL_EPSILON__л65536ж0 +__DBL_HAS_DENORM__л65536ж0 +__DBL_HAS_INFINITY__л65536ж0 +__DBL_HAS_QUIET_NAN__л65536ж0 +__DBL_MANT_DIG__л65536ж0 +__DBL_MAX_10_EXP__л65536ж0 +__DBL_MAX_EXP__л65536ж0 +__DBL_MAX__л65536ж0 +__DBL_MIN_10_EXP__л65536ж0 +__DBL_MIN_EXP__л65536ж0 +__DBL_MIN__л65536ж0 +__DEC128_EPSILON__л65536ж0 +__DEC128_MANT_DIG__л65536ж0 +__DEC128_MAX_EXP__л65536ж0 +__DEC128_MAX__л65536ж0 +__DEC128_MIN_EXP__л65536ж0 +__DEC128_MIN__л65536ж0 +__DEC128_SUBNORMAL_MIN__л65536ж0 +__DEC32_EPSILON__л65536ж0 +__DEC32_MANT_DIG__л65536ж0 +__DEC32_MAX_EXP__л65536ж0 +__DEC32_MAX__л65536ж0 +__DEC32_MIN_EXP__л65536ж0 +__DEC32_MIN__л65536ж0 +__DEC32_SUBNORMAL_MIN__л65536ж0 +__DEC64_EPSILON__л65536ж0 +__DEC64_MANT_DIG__л65536ж0 +__DEC64_MAX_EXP__л65536ж0 +__DEC64_MAX__л65536ж0 +__DEC64_MIN_EXP__л65536ж0 +__DEC64_MIN__л65536ж0 +__DEC64_SUBNORMAL_MIN__л65536ж0 +__DECIMAL_BID_FORMAT__л65536ж0 +__DECIMAL_DIG__л65536ж0 +__DECL_SIMD_cosл65536ж0 +__DECL_SIMD_cosfл65536ж0 +__DECL_SIMD_cosf128л65536ж0 +__DECL_SIMD_coslл65536ж0 +__DECL_SIMD_expл65536ж0 +__DECL_SIMD_expfл65536ж0 +__DECL_SIMD_expf128л65536ж0 +__DECL_SIMD_explл65536ж0 +__DECL_SIMD_logл65536ж0 +__DECL_SIMD_logfл65536ж0 +__DECL_SIMD_logf128л65536ж0 +__DECL_SIMD_loglл65536ж0 +__DECL_SIMD_powл65536ж0 +__DECL_SIMD_powfл65536ж0 +__DECL_SIMD_powf128л65536ж0 +__DECL_SIMD_powlл65536ж0 +__DECL_SIMD_sinл65536ж0 +__DECL_SIMD_sincosл65536ж0 +__DECL_SIMD_sincosfл65536ж0 +__DECL_SIMD_sincosf128л65536ж0 +__DECL_SIMD_sincoslл65536ж0 +__DECL_SIMD_sinfл65536ж0 +__DECL_SIMD_sinf128л65536ж0 +__DECL_SIMD_sinlл65536ж0 +__DEC_EVAL_METHOD__л65536ж0 +__DEPRECATEDл65536ж0 +__DEV_T_TYPEл65536ж0 +__ELF__л65536ж0 +__END_DECLSл65536ж0 +__EXCEPTIONSл65536ж0 +__FDS_BITSл131072м(set)ж0 +__FD_CLRл131072м(d,set)ж0 +__FD_ELTл65536ж0 +__FD_ELTл131072м(d)ж0 +__FD_ISSETл131072м(d,set)ж0 +__FD_MASKл131072м(d)ж0 +__FD_SETл131072м(d,set)ж0 +__FD_SETSIZEл65536ж0 +__FD_ZEROл131072м(fdsp)ж0 +__FD_ZERO_STOSл65536ж0 +__FILE_definedл65536ж0 +__FINITE_MATH_ONLY__л65536ж0 +__FLOAT_WORD_ORDERл65536ж0 +__FLOAT_WORD_ORDER__л65536ж0 +__FLT_DECIMAL_DIG__л65536ж0 +__FLT_DENORM_MIN__л65536ж0 +__FLT_DIG__л65536ж0 +__FLT_EPSILON__л65536ж0 +__FLT_EVAL_METHOD__л65536ж0 +__FLT_HAS_DENORM__л65536ж0 +__FLT_HAS_INFINITY__л65536ж0 +__FLT_HAS_QUIET_NAN__л65536ж0 +__FLT_MANT_DIG__л65536ж0 +__FLT_MAX_10_EXP__л65536ж0 +__FLT_MAX_EXP__л65536ж0 +__FLT_MAX__л65536ж0 +__FLT_MIN_10_EXP__л65536ж0 +__FLT_MIN_EXP__л65536ж0 +__FLT_MIN__л65536ж0 +__FLT_RADIX__л65536ж0 +__FP_LOGB0_IS_MINл65536ж0 +__FP_LOGBNAN_IS_MINл65536ж0 +__FP_LONG_MAXл65536ж0 +__FSBLKCNT64_T_TYPEл65536ж0 +__FSBLKCNT_T_TYPEл65536ж0 +__FSFILCNT64_T_TYPEл65536ж0 +__FSFILCNT_T_TYPEл65536ж0 +__FSID_T_TYPEл65536ж0 +__FSWORD_T_TYPEл65536ж0 +__FXSR__л65536ж0 +__F_GETOWNл65536ж0 +__F_GETOWN_EXл65536ж0 +__F_GETSIGл65536ж0 +__F_SETOWNл65536ж0 +__F_SETOWN_EXл65536ж0 +__F_SETSIGл65536ж0 +__GCC_ASM_FLAG_OUTPUTS__л65536ж0 +__GCC_ATOMIC_BOOL_LOCK_FREEл65536ж0 +__GCC_ATOMIC_CHAR16_T_LOCK_FREEл65536ж0 +__GCC_ATOMIC_CHAR32_T_LOCK_FREEл65536ж0 +__GCC_ATOMIC_CHAR_LOCK_FREEл65536ж0 +__GCC_ATOMIC_INT_LOCK_FREEл65536ж0 +__GCC_ATOMIC_LLONG_LOCK_FREEл65536ж0 +__GCC_ATOMIC_LONG_LOCK_FREEл65536ж0 +__GCC_ATOMIC_POINTER_LOCK_FREEл65536ж0 +__GCC_ATOMIC_SHORT_LOCK_FREEл65536ж0 +__GCC_ATOMIC_TEST_AND_SET_TRUEVALл65536ж0 +__GCC_ATOMIC_WCHAR_T_LOCK_FREEл65536ж0 +__GCC_HAVE_DWARF2_CFI_ASMл65536ж0 +__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1л65536ж0 +__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2л65536ж0 +__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4л65536ж0 +__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8л65536ж0 +__GCC_IEC_559л65536ж0 +__GCC_IEC_559_COMPLEXл65536ж0 +__GID_T_TYPEл65536ж0 +__GLIBCXX_BITSIZE_INT_N_0л65536ж0 +__GLIBCXX_TYPE_INT_N_0л65536ж0 +__GLIBCXX__л65536ж0 +__GLIBC_FLT_EVAL_METHODл65536ж0 +__GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATIONл65536ж0 +__GLIBC_MINOR__л65536ж0 +__GLIBC_PREREQл131072м(maj,min)ж0 +__GLIBC_USEл131072м(F)ж0 +__GLIBC_USE_DEPRECATED_GETSл65536ж0 +__GLIBC_USE_IEC_60559_BFP_EXTл65536ж0 +__GLIBC_USE_IEC_60559_FUNCS_EXTл65536ж0 +__GLIBC_USE_IEC_60559_TYPES_EXTл65536ж0 +__GLIBC_USE_LIB_EXT2л65536ж0 +__GLIBC__л65536ж0 +__GNUC_MINOR__л65536ж0 +__GNUC_PATCHLEVEL__л65536ж0 +__GNUC_PREREQл131072м(maj,min)ж0 +__GNUC_STDC_INLINE__л65536ж0 +__GNUC_VA_LISTл65536ж0 +__GNUC__л65536ж0 +__GNUG__л65536ж0 +__GNU_GETTEXT_SUPPORTED_REVISIONл131072м(major)ж0 +__GNU_LIBRARY__л65536ж0 +__GXX_ABI_VERSIONл65536ж0 +__GXX_EXPERIMENTAL_CXX0X__л65536ж0 +__GXX_RTTIл65536ж0 +__GXX_WEAK__л65536ж0 +__HAVE_COLUMNл65536ж0 +__HAVE_DISTINCT_FLOAT128л65536ж0 +__HAVE_FLOAT128л65536ж0 +__HAVE_GENERIC_SELECTIONл65536ж0 +__ID_T_TYPEл65536ж0 +__ILP32_OFF32_CFLAGSл65536ж0 +__ILP32_OFF32_LDFLAGSл65536ж0 +__ILP32_OFFBIG_CFLAGSл65536ж0 +__ILP32_OFFBIG_LDFLAGSл65536ж0 +__INO64_T_TYPEл65536ж0 +__INO_T_MATCHES_INO64_Tл65536ж0 +__INO_T_TYPEл65536ж0 +__INT16_Cл131072м(c)ж0 +__INT16_MAX__л65536ж0 +__INT16_TYPE__л65536ж0 +__INT32_Cл131072м(c)ж0 +__INT32_MAX__л65536ж0 +__INT32_TYPE__л65536ж0 +__INT64_Cл131072м(c)ж0 +__INT64_MAX__л65536ж0 +__INT64_TYPE__л65536ж0 +__INT8_Cл131072м(c)ж0 +__INT8_MAX__л65536ж0 +__INT8_TYPE__л65536ж0 +__INTMAX_Cл131072м(c)ж0 +__INTMAX_MAX__л65536ж0 +__INTMAX_TYPE__л65536ж0 +__INTPTR_MAX__л65536ж0 +__INTPTR_TYPE__л65536ж0 +__INT_FAST16_MAX__л65536ж0 +__INT_FAST16_TYPE__л65536ж0 +__INT_FAST32_MAX__л65536ж0 +__INT_FAST32_TYPE__л65536ж0 +__INT_FAST64_MAX__л65536ж0 +__INT_FAST64_TYPE__л65536ж0 +__INT_FAST8_MAX__л65536ж0 +__INT_FAST8_TYPE__л65536ж0 +__INT_LEAST16_MAX__л65536ж0 +__INT_LEAST16_TYPE__л65536ж0 +__INT_LEAST32_MAX__л65536ж0 +__INT_LEAST32_TYPE__л65536ж0 +__INT_LEAST64_MAX__л65536ж0 +__INT_LEAST64_TYPE__л65536ж0 +__INT_LEAST8_MAX__л65536ж0 +__INT_LEAST8_TYPE__л65536ж0 +__INT_MAX__л65536ж0 +__INT_Nл65536ж0 +__INT_Nл131072м(TYPE)ж0 +__INT_WCHAR_T_Hл65536ж0 +__IOV_MAXл65536ж0 +__KERNEL_STRICT_NAMESл65536ж0 +__KEY_T_TYPEл65536ж0 +__LC_ADDRESSл65536ж0 +__LC_ALLл65536ж0 +__LC_COLLATEл65536ж0 +__LC_CTYPEл65536ж0 +__LC_IDENTIFICATIONл65536ж0 +__LC_MEASUREMENTл65536ж0 +__LC_MESSAGESл65536ж0 +__LC_MONETARYл65536ж0 +__LC_NAMEл65536ж0 +__LC_NUMERICл65536ж0 +__LC_PAPERл65536ж0 +__LC_TELEPHONEл65536ж0 +__LC_TIMEл65536ж0 +__LDBL_DENORM_MIN__л65536ж0 +__LDBL_DIG__л65536ж0 +__LDBL_EPSILON__л65536ж0 +__LDBL_HAS_DENORM__л65536ж0 +__LDBL_HAS_INFINITY__л65536ж0 +__LDBL_HAS_QUIET_NAN__л65536ж0 +__LDBL_MANT_DIG__л65536ж0 +__LDBL_MAX_10_EXP__л65536ж0 +__LDBL_MAX_EXP__л65536ж0 +__LDBL_MAX__л65536ж0 +__LDBL_MIN_10_EXP__л65536ж0 +__LDBL_MIN_EXP__л65536ж0 +__LDBL_MIN__л65536ж0 +__LDBL_REDIRл131072м(name,proto)ж0 +__LDBL_REDIR1л131072м(name,proto,alias)ж0 +__LDBL_REDIR1_NTHл131072м(name,proto,alias)ж0 +__LDBL_REDIR_DECLл131072м(name)ж0 +__LDBL_REDIR_NTHл131072м(name,proto)ж0 +__LEAFл65536ж0 +__LEAF_ATTRл65536ж0 +__LITTLE_ENDIANл65536ж0 +__LOCK_ALIGNMENTл65536ж0 +__LONG_LONG_MAX__л65536ж0 +__LONG_LONG_PAIRл131072м(HI,LO)ж0 +__LONG_MAX__л65536ж0 +__LP64_OFF64_CFLAGSл65536ж0 +__LP64_OFF64_LDFLAGSл65536ж0 +__LP64__л65536ж0 +__MATHCALLл65536ж0 +__MATHCALLл131072м(function,suffix,args)ж0 +__MATHCALLXл131072м(function,suffix,args,attrib)ж0 +__MATHCALL_VECл131072м(function,suffix,args)ж0 +__MATHDECLл65536ж0 +__MATHDECLл131072м(type,function,suffix,args)ж0 +__MATHDECLXл131072м(type,function,suffix,args,attrib)ж0 +__MATHDECL_1л65536ж0 +__MATHDECL_1л131072м(type,function,suffix,args)ж0 +__MATHDECL_VECл131072м(type,function,suffix,args)ж0 +__MATH_DECLARE_LDOUBLEл65536ж0 +__MATH_DECLARING_DOUBLEл65536ж0 +__MATH_DECLARING_FLOATNл65536ж0 +__MATH_EVAL_FMT2л131072м(x,y)ж0 +__MATH_INLINEл65536ж0 +__MATH_PRECNAMEл65536ж0 +__MATH_PRECNAMEл131072м(name,r)ж0 +__MATH_TGл131072м(TG_ARG,FUNC,ARGS)ж0 +__MAX_BAUDл65536ж0 +__MMX__л65536ж0 +__MODE_T_TYPEл65536ж0 +__Nл131072м(msgid)ж0 +__NCPUBITSл65536ж0 +__NFDBITSл65536ж0 +__NGREGл65536ж0 +__NLINK_T_TYPEл65536ж0 +__NO_CTYPEл65536ж0 +__NR__sysctlл65536ж0 +__NR_acceptл65536ж0 +__NR_accept4л65536ж0 +__NR_accessл65536ж0 +__NR_acctл65536ж0 +__NR_add_keyл65536ж0 +__NR_adjtimexл65536ж0 +__NR_afs_syscallл65536ж0 +__NR_alarmл65536ж0 +__NR_arch_prctlл65536ж0 +__NR_bindл65536ж0 +__NR_bpfл65536ж0 +__NR_brkл65536ж0 +__NR_capgetл65536ж0 +__NR_capsetл65536ж0 +__NR_chdirл65536ж0 +__NR_chmodл65536ж0 +__NR_chownл65536ж0 +__NR_chrootл65536ж0 +__NR_clock_adjtimeл65536ж0 +__NR_clock_getresл65536ж0 +__NR_clock_gettimeл65536ж0 +__NR_clock_nanosleepл65536ж0 +__NR_clock_settimeл65536ж0 +__NR_cloneл65536ж0 +__NR_closeл65536ж0 +__NR_connectл65536ж0 +__NR_copy_file_rangeл65536ж0 +__NR_creatл65536ж0 +__NR_create_moduleл65536ж0 +__NR_delete_moduleл65536ж0 +__NR_dupл65536ж0 +__NR_dup2л65536ж0 +__NR_dup3л65536ж0 +__NR_epoll_createл65536ж0 +__NR_epoll_create1л65536ж0 +__NR_epoll_ctlл65536ж0 +__NR_epoll_ctl_oldл65536ж0 +__NR_epoll_pwaitл65536ж0 +__NR_epoll_waitл65536ж0 +__NR_epoll_wait_oldл65536ж0 +__NR_eventfdл65536ж0 +__NR_eventfd2л65536ж0 +__NR_execveл65536ж0 +__NR_execveatл65536ж0 +__NR_exitл65536ж0 +__NR_exit_groupл65536ж0 +__NR_faccessatл65536ж0 +__NR_fadvise64л65536ж0 +__NR_fallocateл65536ж0 +__NR_fanotify_initл65536ж0 +__NR_fanotify_markл65536ж0 +__NR_fchdirл65536ж0 +__NR_fchmodл65536ж0 +__NR_fchmodatл65536ж0 +__NR_fchownл65536ж0 +__NR_fchownatл65536ж0 +__NR_fcntlл65536ж0 +__NR_fdatasyncл65536ж0 +__NR_fgetxattrл65536ж0 +__NR_finit_moduleл65536ж0 +__NR_flistxattrл65536ж0 +__NR_flockл65536ж0 +__NR_forkл65536ж0 +__NR_fremovexattrл65536ж0 +__NR_fsetxattrл65536ж0 +__NR_fstatл65536ж0 +__NR_fstatfsл65536ж0 +__NR_fsyncл65536ж0 +__NR_ftruncateл65536ж0 +__NR_futexл65536ж0 +__NR_futimesatл65536ж0 +__NR_get_kernel_symsл65536ж0 +__NR_get_mempolicyл65536ж0 +__NR_get_robust_listл65536ж0 +__NR_get_thread_areaл65536ж0 +__NR_getcpuл65536ж0 +__NR_getcwdл65536ж0 +__NR_getdentsл65536ж0 +__NR_getdents64л65536ж0 +__NR_getegidл65536ж0 +__NR_geteuidл65536ж0 +__NR_getgidл65536ж0 +__NR_getgroupsл65536ж0 +__NR_getitimerл65536ж0 +__NR_getpeernameл65536ж0 +__NR_getpgidл65536ж0 +__NR_getpgrpл65536ж0 +__NR_getpidл65536ж0 +__NR_getpmsgл65536ж0 +__NR_getppidл65536ж0 +__NR_getpriorityл65536ж0 +__NR_getrandomл65536ж0 +__NR_getresgidл65536ж0 +__NR_getresuidл65536ж0 +__NR_getrlimitл65536ж0 +__NR_getrusageл65536ж0 +__NR_getsidл65536ж0 +__NR_getsocknameл65536ж0 +__NR_getsockoptл65536ж0 +__NR_gettidл65536ж0 +__NR_gettimeofdayл65536ж0 +__NR_getuidл65536ж0 +__NR_getxattrл65536ж0 +__NR_init_moduleл65536ж0 +__NR_inotify_add_watchл65536ж0 +__NR_inotify_initл65536ж0 +__NR_inotify_init1л65536ж0 +__NR_inotify_rm_watchл65536ж0 +__NR_io_cancelл65536ж0 +__NR_io_destroyл65536ж0 +__NR_io_geteventsл65536ж0 +__NR_io_setupл65536ж0 +__NR_io_submitл65536ж0 +__NR_ioctlл65536ж0 +__NR_iopermл65536ж0 +__NR_ioplл65536ж0 +__NR_ioprio_getл65536ж0 +__NR_ioprio_setл65536ж0 +__NR_kcmpл65536ж0 +__NR_kexec_file_loadл65536ж0 +__NR_kexec_loadл65536ж0 +__NR_keyctlл65536ж0 +__NR_killл65536ж0 +__NR_lchownл65536ж0 +__NR_lgetxattrл65536ж0 +__NR_linkл65536ж0 +__NR_linkatл65536ж0 +__NR_listenл65536ж0 +__NR_listxattrл65536ж0 +__NR_llistxattrл65536ж0 +__NR_lookup_dcookieл65536ж0 +__NR_lremovexattrл65536ж0 +__NR_lseekл65536ж0 +__NR_lsetxattrл65536ж0 +__NR_lstatл65536ж0 +__NR_madviseл65536ж0 +__NR_mbindл65536ж0 +__NR_membarrierл65536ж0 +__NR_memfd_createл65536ж0 +__NR_migrate_pagesл65536ж0 +__NR_mincoreл65536ж0 +__NR_mkdirл65536ж0 +__NR_mkdiratл65536ж0 +__NR_mknodл65536ж0 +__NR_mknodatл65536ж0 +__NR_mlockл65536ж0 +__NR_mlock2л65536ж0 +__NR_mlockallл65536ж0 +__NR_mmapл65536ж0 +__NR_modify_ldtл65536ж0 +__NR_mountл65536ж0 +__NR_move_pagesл65536ж0 +__NR_mprotectл65536ж0 +__NR_mq_getsetattrл65536ж0 +__NR_mq_notifyл65536ж0 +__NR_mq_openл65536ж0 +__NR_mq_timedreceiveл65536ж0 +__NR_mq_timedsendл65536ж0 +__NR_mq_unlinkл65536ж0 +__NR_mremapл65536ж0 +__NR_msgctlл65536ж0 +__NR_msggetл65536ж0 +__NR_msgrcvл65536ж0 +__NR_msgsndл65536ж0 +__NR_msyncл65536ж0 +__NR_munlockл65536ж0 +__NR_munlockallл65536ж0 +__NR_munmapл65536ж0 +__NR_name_to_handle_atл65536ж0 +__NR_nanosleepл65536ж0 +__NR_newfstatatл65536ж0 +__NR_nfsservctlл65536ж0 +__NR_openл65536ж0 +__NR_open_by_handle_atл65536ж0 +__NR_openatл65536ж0 +__NR_pauseл65536ж0 +__NR_perf_event_openл65536ж0 +__NR_personalityл65536ж0 +__NR_pipeл65536ж0 +__NR_pipe2л65536ж0 +__NR_pivot_rootл65536ж0 +__NR_pkey_allocл65536ж0 +__NR_pkey_freeл65536ж0 +__NR_pkey_mprotectл65536ж0 +__NR_pollл65536ж0 +__NR_ppollл65536ж0 +__NR_prctlл65536ж0 +__NR_pread64л65536ж0 +__NR_preadvл65536ж0 +__NR_preadv2л65536ж0 +__NR_prlimit64л65536ж0 +__NR_process_vm_readvл65536ж0 +__NR_process_vm_writevл65536ж0 +__NR_pselect6л65536ж0 +__NR_ptraceл65536ж0 +__NR_putpmsgл65536ж0 +__NR_pwrite64л65536ж0 +__NR_pwritevл65536ж0 +__NR_pwritev2л65536ж0 +__NR_query_moduleл65536ж0 +__NR_quotactlл65536ж0 +__NR_readл65536ж0 +__NR_readaheadл65536ж0 +__NR_readlinkл65536ж0 +__NR_readlinkatл65536ж0 +__NR_readvл65536ж0 +__NR_rebootл65536ж0 +__NR_recvfromл65536ж0 +__NR_recvmmsgл65536ж0 +__NR_recvmsgл65536ж0 +__NR_remap_file_pagesл65536ж0 +__NR_removexattrл65536ж0 +__NR_renameл65536ж0 +__NR_renameatл65536ж0 +__NR_renameat2л65536ж0 +__NR_request_keyл65536ж0 +__NR_restart_syscallл65536ж0 +__NR_rmdirл65536ж0 +__NR_rt_sigactionл65536ж0 +__NR_rt_sigpendingл65536ж0 +__NR_rt_sigprocmaskл65536ж0 +__NR_rt_sigqueueinfoл65536ж0 +__NR_rt_sigreturnл65536ж0 +__NR_rt_sigsuspendл65536ж0 +__NR_rt_sigtimedwaitл65536ж0 +__NR_rt_tgsigqueueinfoл65536ж0 +__NR_sched_get_priority_maxл65536ж0 +__NR_sched_get_priority_minл65536ж0 +__NR_sched_getaffinityл65536ж0 +__NR_sched_getattrл65536ж0 +__NR_sched_getparamл65536ж0 +__NR_sched_getschedulerл65536ж0 +__NR_sched_rr_get_intervalл65536ж0 +__NR_sched_setaffinityл65536ж0 +__NR_sched_setattrл65536ж0 +__NR_sched_setparamл65536ж0 +__NR_sched_setschedulerл65536ж0 +__NR_sched_yieldл65536ж0 +__NR_seccompл65536ж0 +__NR_securityл65536ж0 +__NR_selectл65536ж0 +__NR_semctlл65536ж0 +__NR_semgetл65536ж0 +__NR_semopл65536ж0 +__NR_semtimedopл65536ж0 +__NR_sendfileл65536ж0 +__NR_sendmmsgл65536ж0 +__NR_sendmsgл65536ж0 +__NR_sendtoл65536ж0 +__NR_set_mempolicyл65536ж0 +__NR_set_robust_listл65536ж0 +__NR_set_thread_areaл65536ж0 +__NR_set_tid_addressл65536ж0 +__NR_setdomainnameл65536ж0 +__NR_setfsgidл65536ж0 +__NR_setfsuidл65536ж0 +__NR_setgidл65536ж0 +__NR_setgroupsл65536ж0 +__NR_sethostnameл65536ж0 +__NR_setitimerл65536ж0 +__NR_setnsл65536ж0 +__NR_setpgidл65536ж0 +__NR_setpriorityл65536ж0 +__NR_setregidл65536ж0 +__NR_setresgidл65536ж0 +__NR_setresuidл65536ж0 +__NR_setreuidл65536ж0 +__NR_setrlimitл65536ж0 +__NR_setsidл65536ж0 +__NR_setsockoptл65536ж0 +__NR_settimeofdayл65536ж0 +__NR_setuidл65536ж0 +__NR_setxattrл65536ж0 +__NR_shmatл65536ж0 +__NR_shmctlл65536ж0 +__NR_shmdtл65536ж0 +__NR_shmgetл65536ж0 +__NR_shutdownл65536ж0 +__NR_sigaltstackл65536ж0 +__NR_signalfdл65536ж0 +__NR_signalfd4л65536ж0 +__NR_socketл65536ж0 +__NR_socketpairл65536ж0 +__NR_spliceл65536ж0 +__NR_statл65536ж0 +__NR_statfsл65536ж0 +__NR_statxл65536ж0 +__NR_swapoffл65536ж0 +__NR_swaponл65536ж0 +__NR_symlinkл65536ж0 +__NR_symlinkatл65536ж0 +__NR_syncл65536ж0 +__NR_sync_file_rangeл65536ж0 +__NR_syncfsл65536ж0 +__NR_sysfsл65536ж0 +__NR_sysinfoл65536ж0 +__NR_syslogл65536ж0 +__NR_teeл65536ж0 +__NR_tgkillл65536ж0 +__NR_timeл65536ж0 +__NR_timer_createл65536ж0 +__NR_timer_deleteл65536ж0 +__NR_timer_getoverrunл65536ж0 +__NR_timer_gettimeл65536ж0 +__NR_timer_settimeл65536ж0 +__NR_timerfd_createл65536ж0 +__NR_timerfd_gettimeл65536ж0 +__NR_timerfd_settimeл65536ж0 +__NR_timesл65536ж0 +__NR_tkillл65536ж0 +__NR_truncateл65536ж0 +__NR_tuxcallл65536ж0 +__NR_umaskл65536ж0 +__NR_umount2л65536ж0 +__NR_unameл65536ж0 +__NR_unlinkл65536ж0 +__NR_unlinkatл65536ж0 +__NR_unshareл65536ж0 +__NR_uselibл65536ж0 +__NR_userfaultfdл65536ж0 +__NR_ustatл65536ж0 +__NR_utimeл65536ж0 +__NR_utimensatл65536ж0 +__NR_utimesл65536ж0 +__NR_vforkл65536ж0 +__NR_vhangupл65536ж0 +__NR_vmspliceл65536ж0 +__NR_vserverл65536ж0 +__NR_wait4л65536ж0 +__NR_waitidл65536ж0 +__NR_writeл65536ж0 +__NR_writevл65536ж0 +__NTHл131072м(fct)ж0 +__NTHNLл131072м(fct)ж0 +__OFF64_T_TYPEл65536ж0 +__OFF_T_MATCHES_OFF64_Tл65536ж0 +__OFF_T_TYPEл65536ж0 +__ONCE_ALIGNMENTл65536ж0 +__OPEN_NEEDS_MODEл131072м(oflag)ж0 +__OPTIMIZE__л65536ж0 +__ORDER_BIG_ENDIAN__л65536ж0 +__ORDER_LITTLE_ENDIAN__л65536ж0 +__ORDER_PDP_ENDIAN__л65536ж0 +__O_CLOEXECл65536ж0 +__O_DIRECTл65536ж0 +__O_DIRECTORYл65536ж0 +__O_DSYNCл65536ж0 +__O_LARGEFILEл65536ж0 +__O_NOATIMEл65536ж0 +__O_NOFOLLOWл65536ж0 +__O_PATHл65536ж0 +__O_TMPFILEл65536ж0 +__Pл65536ж0 +__Pл131072м(args)ж0 +__PARSEARGS_H__л65536ж0 +__PDP_ENDIANл65536ж0 +__PIC__л65536ж0 +__PID_T_TYPEл65536ж0 +__PIE__л65536ж0 +__PMTл65536ж0 +__PMTл131072м(args)ж0 +__POSIX2_THIS_VERSIONл65536ж0 +__POSIX_FADV_DONTNEEDл65536ж0 +__POSIX_FADV_NOREUSEл65536ж0 +__PRAGMA_REDEFINE_EXTNAMEл65536ж0 +__PTHREAD_COMPAT_PADDING_ENDл65536ж0 +__PTHREAD_COMPAT_PADDING_MIDл65536ж0 +__PTHREAD_MUTEX_HAVE_PREVл65536ж0 +__PTHREAD_MUTEX_LOCK_ELISIONл65536ж0 +__PTHREAD_MUTEX_NUSERS_AFTER_KINDл65536ж0 +__PTHREAD_MUTEX_USE_UNIONл65536ж0 +__PTHREAD_RWLOCK_ELISION_EXTRAл65536ж0 +__PTHREAD_RWLOCK_INT_FLAGS_SHAREDл65536ж0 +__PTHREAD_SPINSл65536ж0 +__PTHREAD_SPINS_DATAл65536ж0 +__PTRDIFF_MAX__л65536ж0 +__PTRDIFF_TYPE__л65536ж0 +__REDIRECTл131072м(name,proto,alias)ж0 +__REDIRECT_LDBLл131072м(name,proto,alias)ж0 +__REDIRECT_NTHл131072м(name,proto,alias)ж0 +__REDIRECT_NTHNLл131072м(name,proto,alias)ж0 +__REDIRECT_NTH_LDBLл131072м(name,proto,alias)ж0 +__REGISTER_PREFIX__л65536ж0 +__RLIM64_T_TYPEл65536ж0 +__RLIM_T_MATCHES_RLIM64_Tл65536ж0 +__RLIM_T_TYPEл65536ж0 +__S16_TYPEл65536ж0 +__S32_TYPEл65536ж0 +__S64_TYPEл65536ж0 +__SCHAR_MAX__л65536ж0 +__SEG_FSл65536ж0 +__SEG_GSл65536ж0 +__SHRT_MAX__л65536ж0 +__SIGEV_MAX_SIZEл65536ж0 +__SIGEV_PAD_SIZEл65536ж0 +__SIGRTMAXл65536ж0 +__SIGRTMINл65536ж0 +__SIG_ATOMIC_MAX__л65536ж0 +__SIG_ATOMIC_MIN__л65536ж0 +__SIG_ATOMIC_TYPE__л65536ж0 +__SIMD_DECLл131072м(function)ж0 +__SIZEOF_DOUBLE__л65536ж0 +__SIZEOF_FLOAT128__л65536ж0 +__SIZEOF_FLOAT80__л65536ж0 +__SIZEOF_FLOAT__л65536ж0 +__SIZEOF_INT128__л65536ж0 +__SIZEOF_INT__л65536ж0 +__SIZEOF_LONG_DOUBLE__л65536ж0 +__SIZEOF_LONG_LONG__л65536ж0 +__SIZEOF_LONG__л65536ж0 +__SIZEOF_POINTER__л65536ж0 +__SIZEOF_PTHREAD_ATTR_Tл65536ж0 +__SIZEOF_PTHREAD_BARRIERATTR_Tл65536ж0 +__SIZEOF_PTHREAD_BARRIER_Tл65536ж0 +__SIZEOF_PTHREAD_CONDATTR_Tл65536ж0 +__SIZEOF_PTHREAD_COND_Tл65536ж0 +__SIZEOF_PTHREAD_MUTEXATTR_Tл65536ж0 +__SIZEOF_PTHREAD_MUTEX_Tл65536ж0 +__SIZEOF_PTHREAD_RWLOCKATTR_Tл65536ж0 +__SIZEOF_PTHREAD_RWLOCK_Tл65536ж0 +__SIZEOF_PTRDIFF_T__л65536ж0 +__SIZEOF_SHORT__л65536ж0 +__SIZEOF_SIZE_T__л65536ж0 +__SIZEOF_WCHAR_T__л65536ж0 +__SIZEOF_WINT_T__л65536ж0 +__SIZE_MAX__л65536ж0 +__SIZE_Tл65536ж0 +__SIZE_TYPE__л65536ж0 +__SIZE_T__л65536ж0 +__SI_ALIGNMENTл65536ж0 +__SI_ASYNCIO_AFTER_SIGIOл65536ж0 +__SI_BAND_TYPEл65536ж0 +__SI_CLOCK_Tл65536ж0 +__SI_ERRNO_THEN_CODEл65536ж0 +__SI_HAVE_SIGSYSл65536ж0 +__SI_MAX_SIZEл65536ж0 +__SI_PAD_SIZEл65536ж0 +__SI_SIGFAULT_ADDLл65536ж0 +__SLONG32_TYPEл65536ж0 +__SLONGWORD_TYPEл65536ж0 +__SOCKADDR_ARGл65536ж0 +__SOCKADDR_COMMONл131072м(sa_prefix)ж0 +__SOCKADDR_COMMON_SIZEл65536ж0 +__SOCKET_H__л65536ж0 +__SQUAD_TYPEл65536ж0 +__SSE2_MATH__л65536ж0 +__SSE2__л65536ж0 +__SSE_MATH__л65536ж0 +__SSE__л65536ж0 +__SSIZE_T_TYPEл65536ж0 +__SSP_STRONG__л65536ж0 +__STDC_CONSTANT_MACROSл65536ж0 +__STDC_HOSTED__л65536ж0 +__STDC_IEC_559_COMPLEX__л65536ж0 +__STDC_IEC_559__л65536ж0 +__STDC_ISO_10646__л65536ж0 +__STDC_LIMIT_MACROSл65536ж0 +__STDC_NO_THREADS__л65536ж0 +__STDC_UTF_16__л65536ж0 +__STDC_UTF_32__л65536ж0 +__STDC__л65536ж0 +__STDIO_INLINEл65536ж0 +__STDLIB_MB_LEN_MAXл65536ж0 +__STD_TYPEл65536ж0 +__STRINGл131072м(x)ж0 +__STRINGS_FORTIFIEDл65536ж0 +__SUSECONDS_T_TYPEл65536ж0 +__SWORD_TYPEл65536ж0 +__SYSCALL_SLONG_TYPEл65536ж0 +__SYSCALL_ULONG_TYPEл65536ж0 +__SYSCALL_WORDSIZEл65536ж0 +__S_IEXECл65536ж0 +__S_IFBLKл65536ж0 +__S_IFCHRл65536ж0 +__S_IFDIRл65536ж0 +__S_IFIFOл65536ж0 +__S_IFLNKл65536ж0 +__S_IFMTл65536ж0 +__S_IFREGл65536ж0 +__S_IFSOCKл65536ж0 +__S_IREADл65536ж0 +__S_ISGIDл65536ж0 +__S_ISTYPEл131072м(mode,mask)ж0 +__S_ISUIDл65536ж0 +__S_ISVTXл65536ж0 +__S_IWRITEл65536ж0 +__S_TYPEISMQл131072м(buf)ж0 +__S_TYPEISSEMл131072м(buf)ж0 +__S_TYPEISSHMл131072м(buf)ж0 +__TERM_H__л65536ж0 +__THROWл65536ж0 +__THROWNLл65536ж0 +__TIMER_T_TYPEл65536ж0 +__TIME_T_TYPEл65536ж0 +__U16_TYPEл65536ж0 +__U32_TYPEл65536ж0 +__U64_TYPEл65536ж0 +__UID_T_TYPEл65536ж0 +__UINT16_Cл131072м(c)ж0 +__UINT16_MAX__л65536ж0 +__UINT16_TYPE__л65536ж0 +__UINT32_Cл131072м(c)ж0 +__UINT32_MAX__л65536ж0 +__UINT32_TYPE__л65536ж0 +__UINT64_Cл131072м(c)ж0 +__UINT64_MAX__л65536ж0 +__UINT64_TYPE__л65536ж0 +__UINT8_Cл131072м(c)ж0 +__UINT8_MAX__л65536ж0 +__UINT8_TYPE__л65536ж0 +__UINTMAX_Cл131072м(c)ж0 +__UINTMAX_MAX__л65536ж0 +__UINTMAX_TYPE__л65536ж0 +__UINTPTR_MAX__л65536ж0 +__UINTPTR_TYPE__л65536ж0 +__UINT_FAST16_MAX__л65536ж0 +__UINT_FAST16_TYPE__л65536ж0 +__UINT_FAST32_MAX__л65536ж0 +__UINT_FAST32_TYPE__л65536ж0 +__UINT_FAST64_MAX__л65536ж0 +__UINT_FAST64_TYPE__л65536ж0 +__UINT_FAST8_MAX__л65536ж0 +__UINT_FAST8_TYPE__л65536ж0 +__UINT_LEAST16_MAX__л65536ж0 +__UINT_LEAST16_TYPE__л65536ж0 +__UINT_LEAST32_MAX__л65536ж0 +__UINT_LEAST32_TYPE__л65536ж0 +__UINT_LEAST64_MAX__л65536ж0 +__UINT_LEAST64_TYPE__л65536ж0 +__UINT_LEAST8_MAX__л65536ж0 +__UINT_LEAST8_TYPE__л65536ж0 +__ULONG32_TYPEл65536ж0 +__ULONGWORD_TYPEл65536ж0 +__UQUAD_TYPEл65536ж0 +__USECONDS_T_TYPEл65536ж0 +__USEFULL_MACROS_H__л65536ж0 +__USER_LABEL_PREFIX__л65536ж0 +__USE_ATFILEл65536ж0 +__USE_EXTERN_INLINESл65536ж0 +__USE_FILE_OFFSET64л65536ж0 +__USE_FORTIFY_LEVELл65536ж0 +__USE_GNUл65536ж0 +__USE_GNU_GETTEXTл65536ж0 +__USE_ISOC11л65536ж0 +__USE_ISOC95л65536ж0 +__USE_ISOC99л65536ж0 +__USE_ISOCXX11л65536ж0 +__USE_KERNEL_IPV6_DEFSл65536ж0 +__USE_LARGEFILEл65536ж0 +__USE_LARGEFILE64л65536ж0 +__USE_MISCл65536ж0 +__USE_POSIXл65536ж0 +__USE_POSIX199309л65536ж0 +__USE_POSIX199506л65536ж0 +__USE_POSIX2л65536ж0 +__USE_UNIX98л65536ж0 +__USE_XOPENл65536ж0 +__USE_XOPEN2Kл65536ж0 +__USE_XOPEN2K8л65536ж0 +__USE_XOPEN2K8XSIл65536ж0 +__USE_XOPEN2KXSIл65536ж0 +__USE_XOPEN_EXTENDEDл65536ж0 +__UWORD_TYPEл65536ж0 +__VERSION__л65536ж0 +__WALLл65536ж0 +__WCHAR_MAXл65536ж0 +__WCHAR_MAX__л65536ж0 +__WCHAR_MINл65536ж0 +__WCHAR_MIN__л65536ж0 +__WCHAR_Tл65536ж0 +__WCHAR_TYPE__л65536ж0 +__WCHAR_T__л65536ж0 +__WCLONEл65536ж0 +__WCOREDUMPл131072м(status)ж0 +__WCOREFLAGл65536ж0 +__WEXITSTATUSл131072м(status)ж0 +__WIFCONTINUEDл131072м(status)ж0 +__WIFEXITEDл131072м(status)ж0 +__WIFSIGNALEDл131072м(status)ж0 +__WIFSTOPPEDл131072м(status)ж0 +__WINT_MAX__л65536ж0 +__WINT_MIN__л65536ж0 +__WINT_TYPE__л65536ж0 +__WNOTHREADл65536ж0 +__WORDSIZEл65536ж0 +__WORDSIZE_TIME64_COMPAT32л65536ж0 +__WSTOPSIGл131072м(status)ж0 +__WTERMSIGл131072м(status)ж0 +__W_CONTINUEDл65536ж0 +__W_EXITCODEл131072м(ret,sig)ж0 +__W_STOPCODEл131072м(sig)ж0 +__X32_SYSCALL_BITл65536ж0 +____FILE_definedл65536ж0 +____mbstate_t_definedл65536ж0 +____sigset_t_definedл65536ж0 +___int_size_t_hл65536ж0 +___int_wchar_t_hл65536ж0 +__aligned_be64л65536ж0 +__aligned_le64л65536ж0 +__aligned_u64л65536ж0 +__always_inlineл65536ж0 +__amd64л65536ж0 +__amd64__л65536ж0 +__argл64н_pthread_cleanup_bufferж0оvoid * +__attribute_alloc_size__л131072м(params)ж0 +__attribute_artificial__л65536ж0 +__attribute_const__л65536ж0 +__attribute_deprecated__л65536ж0 +__attribute_deprecated_msg__л131072м(msg)ж0 +__attribute_format_arg__л131072м(x)ж0 +__attribute_format_strfmon__л131072м(a,b)ж0 +__attribute_malloc__л65536ж0 +__attribute_noinline__л65536ж0 +__attribute_pure__л65536ж0 +__attribute_used__л65536ж0 +__attribute_warn_unused_result__л65536ж0 +__be16л4096ж0о__u16 +__be32л4096ж0о__u32 +__be64л4096ж0о__u64 +__bitsл64нanon_struct_8ж0о__cpu_mask +__bitwiseл65536ж0 +__bitwise__л65536ж0 +__blkcnt_t_definedл65536ж0 +__blksize_t_definedл65536ж0 +__bool_true_false_are_definedл65536ж0 +__bosл131072м(ptr)ж0 +__bos0л131072м(ptr)ж0 +__bswap_16л131072м(x)ж0 +__bswap_constant_16л131072м(x)ж0 +__bswap_constant_32л131072м(x)ж0 +__bswap_constant_64л131072м(x)ж0 +__builtin_copysignf128л65536ж0 +__builtin_fabsf128л65536ж0 +__builtin_huge_valf128л131072м()ж0 +__builtin_inff128л131072м()ж0 +__builtin_nanf128л131072м(x)ж0 +__builtin_nansf128л131072м(x)ж0 +__canceltypeл64н_pthread_cleanup_bufferж0оint +__cleanup_fct_attributeл65536ж0 +__clock_t_definedл65536ж0 +__clockid_t_definedл65536ж0 +__code_model_small__л65536ж0 +__cplusplusл65536ж0 +__cpp_aggregate_nsdmiл65536ж0 +__cpp_alias_templatesл65536ж0 +__cpp_attributesл65536ж0 +__cpp_binary_literalsл65536ж0 +__cpp_constexprл65536ж0 +__cpp_decltypeл65536ж0 +__cpp_decltype_autoл65536ж0 +__cpp_delegating_constructorsл65536ж0 +__cpp_digit_separatorsл65536ж0 +__cpp_exceptionsл65536ж0 +__cpp_generic_lambdasл65536ж0 +__cpp_hex_floatл65536ж0 +__cpp_inheriting_constructorsл65536ж0 +__cpp_init_capturesл65536ж0 +__cpp_initializer_listsл65536ж0 +__cpp_lambdasл65536ж0 +__cpp_nsdmiл65536ж0 +__cpp_range_based_forл65536ж0 +__cpp_raw_stringsл65536ж0 +__cpp_ref_qualifiersл65536ж0 +__cpp_return_type_deductionл65536ж0 +__cpp_rttiл65536ж0 +__cpp_runtime_arraysл65536ж0 +__cpp_rvalue_referenceл65536ж0 +__cpp_rvalue_referencesл65536ж0 +__cpp_sized_deallocationл65536ж0 +__cpp_static_assertл65536ж0 +__cpp_unicode_charactersл65536ж0 +__cpp_unicode_literalsл65536ж0 +__cpp_user_defined_literalsл65536ж0 +__cpp_variable_templatesл65536ж0 +__cpp_variadic_templatesл65536ж0 +__cpu_maskл4096ж0оunsigned long int +__ctxл65536ж0 +__ctxл131072м(fld)ж0 +__daddr_t_definedл65536ж0 +__dev_t_definedл65536ж0 +__error_t_definedл65536ж0 +__errordeclл131072м(name,msg)ж0 +__exctypeл131072м(name)ж0 +__exctype_lл131072м(name)ж0 +__extern_always_inlineл65536ж0 +__extern_inlineл65536ж0 +__f128л131072м(x)ж0 +__flexarrл65536ж0 +__fortify_functionл65536ж0 +__fsblkcnt_t_definedл65536ж0 +__fsfilcnt_t_definedл65536ж0 +__getopt_argv_constл65536ж0 +__gid_t_definedл65536ж0 +__glibc_c99_flexarr_availableл65536ж0 +__glibc_clang_has_extensionл131072м(ext)ж0 +__glibc_clang_prereqл131072м(maj,min)ж0 +__glibc_likelyл131072м(cond)ж0 +__glibc_macro_warningл131072м(message)ж0 +__glibc_macro_warning1л131072м(message)ж0 +__glibc_unlikelyл131072м(cond)ж0 +__glibcxx_assertл131072м(_Condition)ж0 +__gnu_linux__л65536ж0 +__has_includeл131072м(STR)ж0 +__has_include_nextл131072м(STR)ж0 +__have_pthread_attr_tл65536ж0 +__id_t_definedл65536ж0 +__ino64_t_definedл65536ж0 +__ino_t_definedл65536ж0 +__intptr_t_definedл65536ж0 +__iovec_definedл65536ж0 +__isasciiл131072м(c)ж0 +__iscanonicalл131072м(x)ж0 +__iscanonicalfл131072м(x)ж0 +__iscanonicalf128л131072м(x)ж0 +__isctype_fл131072м(type)ж0 +__isctype_lл131072м(c,type,locale)ж0 +__isleapл131072м(year)ж0 +__itimerspec_definedл65536ж0 +__jmp_bufл4096ж0оlong int +__k8л65536ж0 +__k8__л65536ж0 +__kernel_caddr_tл4096ж0оchar * +__kernel_clock_tл4096ж0о__kernel_long_t +__kernel_clockid_tл4096ж0оint +__kernel_daddr_tл4096ж0оint +__kernel_fd_setл4096ж0оanon_struct_5 +__kernel_fsid_tл4096ж0оanon_struct_6 +__kernel_gid16_tл4096ж0оunsigned short +__kernel_gid32_tл4096ж0оunsigned int +__kernel_gid_tл4096ж0оunsigned int +__kernel_ino_tл4096ж0о__kernel_ulong_t +__kernel_ipc_pid_tл4096ж0оint +__kernel_key_tл4096ж0оint +__kernel_loff_tл4096ж0оlong long +__kernel_long_tл4096ж0оlong +__kernel_mode_tл4096ж0оunsigned int +__kernel_mqd_tл4096ж0оint +__kernel_off_tл4096ж0о__kernel_long_t +__kernel_old_dev_tл4096ж0оunsigned long +__kernel_old_dev_tл65536ж0 +__kernel_old_gid_tл4096ж0оunsigned short +__kernel_old_uid_tл4096ж0оunsigned short +__kernel_old_uid_tл65536ж0 +__kernel_pid_tл4096ж0оint +__kernel_ptrdiff_tл4096ж0о__kernel_long_t +__kernel_sighandler_tл4096ж0оtypedef void +__kernel_size_tл4096ж0о__kernel_ulong_t +__kernel_ssize_tл4096ж0о__kernel_long_t +__kernel_suseconds_tл4096ж0о__kernel_long_t +__kernel_time_tл4096ж0о__kernel_long_t +__kernel_timer_tл4096ж0оint +__kernel_uid16_tл4096ж0оunsigned short +__kernel_uid32_tл4096ж0оunsigned int +__kernel_uid_tл4096ж0оunsigned int +__kernel_ulong_tл4096ж0оunsigned long +__key_t_definedл65536ж0 +__ldiv_t_definedл65536ж0 +__le16л4096ж0о__u16 +__le32л4096ж0о__u32 +__le64л4096ж0о__u64 +__linuxл65536ж0 +__linux__л65536ж0 +__lldiv_t_definedл65536ж0 +__long_double_tл65536ж0 +__mode_t_definedл65536ж0 +__need_NULLл65536ж0 +__need___va_listл65536ж0 +__need_size_tл65536ж0 +__need_wchar_tл65536ж0 +__nlink_t_definedл65536ж0 +__nonnullл131072м(params)ж0 +__off64_t_definedл65536ж0 +__off_t_definedл65536ж0 +__osockaddr_definedл65536ж0 +__pic__л65536ж0 +__pid_t_definedл65536ж0 +__pie__л65536ж0 +__prevл64н_pthread_cleanup_bufferж0о_pthread_cleanup_buffer +__prognameл32768ж0оconst char * +__ptr_tл65536ж0 +__restrict_arrл65536ж0 +__routineл1024м(void *)н_pthread_cleanup_bufferж0оvoid +__s16л4096ж0о__signed__short +__s32л4096ж0о__signed__int +__s64л4096ж0о__extension__ +__s8л4096ж0о__signed__char +__sched_priorityл65536ж0 +__sig_atomic_t_definedл65536ж0 +__sigevent_t_definedл65536ж0 +__siginfo_t_definedл65536ж0 +__sigset_t_definedл65536ж0 +__sigstack_definedл65536ж0 +__sigval_t_definedл65536ж0 +__size_tл65536ж0 +__size_t__л65536ж0 +__socklen_t_definedл65536ж0 +__ss_aligntypeл65536ж0 +__ssize_t_definedл65536ж0 +__stack_t_definedл65536ж0 +__struct_tm_definedл65536ж0 +__stub___compat_bdflushл65536ж0 +__stub_chflagsл65536ж0 +__stub_fattachл65536ж0 +__stub_fchflagsл65536ж0 +__stub_fdetachл65536ж0 +__stub_getmsgл65536ж0 +__stub_gttyл65536ж0 +__stub_lchmodл65536ж0 +__stub_putmsgл65536ж0 +__stub_revokeл65536ж0 +__stub_setloginл65536ж0 +__stub_sigreturnл65536ж0 +__stub_sstkл65536ж0 +__stub_sttyл65536ж0 +__sum16л4096ж0о__u16 +__suseconds_t_definedл65536ж0 +__time_t_definedл65536ж0 +__timer_t_definedл65536ж0 +__timespec_definedл65536ж0 +__timeval_definedл65536ж0 +__toasciiл131072м(c)ж0 +__tobodyл131072м(c,f,a,args)ж0 +__u16л4096ж0оunsigned short +__u32л4096ж0оunsigned int +__u64л4096ж0о__extension__unsigned long long +__u8л4096ж0оunsigned char +__u_char_definedл65536ж0 +__u_intN_tл131072м(N,MODE)ж0 +__uid_t_definedл65536ж0 +__undef_ARG_MAXл65536ж0 +__undef_LINK_MAXл65536ж0 +__undef_NR_OPENл65536ж0 +__undef_OPEN_MAXл65536ж0 +__unixл65536ж0 +__unix__л65536ж0 +__useconds_t_definedл65536ж0 +__va_arg_packл131072м()ж0 +__va_arg_pack_lenл131072м()ж0 +__va_copyл131072м(d,s)ж0 +__va_list__л65536ж0 +__warnattrл131072м(msg)ж0 +__warndeclл131072м(name,msg)ж0 +__wchar_t__л65536ж0 +__wsumл4096ж0о__u32 +__wurл65536ж0 +__x86_64л65536ж0 +__x86_64__л65536ж0 +_pthread_cleanup_bufferл2048ж0 +abortл64нstdж0оusing +abortл65536ж0 +absл64нstdж0оusing +absл65536ж0 +acosл64нstdж0оusing +acosл65536ж0 +acoshл64нstdж0оusing +acoshл65536ж0 +acoshfл65536ж0 +acoshlл65536ж0 +allocaл65536ж0 +allocaл131072м(size)ж0 +anon_enum_0л2ж0 +anon_enum_1л2ж0 +anon_enum_10л2ж0 +anon_enum_11л2ж0 +anon_enum_12л2ж0 +anon_enum_13л2ж0 +anon_enum_14л2ж0 +anon_enum_15л2ж0 +anon_enum_16л2ж0 +anon_enum_17л2ж0 +anon_enum_18л2ж0 +anon_enum_9л2ж0 +anon_struct_2л2048ж0 +anon_struct_3л2048ж0 +anon_struct_4л2048ж0 +anon_struct_5л2048ж0 +anon_struct_6л2048ж0 +anon_struct_7л2048ж0 +anon_struct_8л2048ж0 +arg_doubleл4нanon_enum_0ж0 +arg_endл64нprctl_mm_mapж0о__u64 +arg_floatл4нanon_enum_0ж0 +arg_functionл4нanon_enum_0ж0 +arg_intл4нanon_enum_0ж0 +arg_longlongл4нanon_enum_0ж0 +arg_noneл4нanon_enum_0ж0 +arg_startл64нprctl_mm_mapж0о__u64 +arg_stringл4нanon_enum_0ж0 +argfnл4096ж0оtypedef bool +argptrл64нanon_struct_2ж0оvoid * +argptrл64нanon_struct_3ж0оvoid * +argsortл16м(const void *a1, const void *a2)ж0оint +argtypeл4096ж0оanon_enum_0 +asinл64нstdж0оusing +asinл65536ж0 +asinhл64нstdж0оusing +asinhл65536ж0 +asinhfл65536ж0 +asinhlл65536ж0 +assertл65536ж0 +assertл131072м(expr)ж0 +assert_perrorл65536ж0 +assert_perrorл131072м(errnum)ж0 +at_quick_exitл64нstdж0оusing +at_quick_exitл65536ж0 +atanл64нstdж0оusing +atanл65536ж0 +atan2л64нstdж0оusing +atan2л65536ж0 +atanhл64нstdж0оusing +atanhл65536ж0 +atanhfл65536ж0 +atanhlл65536ж0 +atexitл64нstdж0оusing +atexitл65536ж0 +atofл64нstdж0оusing +atofл65536ж0 +atoiл64нstdж0оusing +atoiл65536ж0 +atolл64нstdж0оusing +atolл65536ж0 +atollл65536ж0 +auxvл64нprctl_mm_mapж0о__u64 * +auxv_sizeл64нprctl_mm_mapж0о__u32 +be16tohл131072м(x)ж0 +be32tohл131072м(x)ж0 +be64tohл131072м(x)ж0 +brkл64нprctl_mm_mapж0о__u64 +bsearchл64нstdж0оusing +bsearchл65536ж0 +bufл16384ж0оchar +calcntл64нtimexж0о__syscall_slong_t +callocл64нstdж0оusing +callocл65536ж0 +cbrtл64нstdж0оusing +cbrtл65536ж0 +cbrtfл65536ж0 +cbrtlл65536ж0 +ceilл64нstdж0оusing +ceilл65536ж0 +change_helpstringл16м(char *s)ж0оvoid +change_helpstringл1024м(char *s)ж0оvoid +cmdlnoptsл16384ж0оmyoption +comfdл16384ж0оint +console_changedл16384ж0оint +constantл64нtimexж0о__syscall_slong_t +copysignл64нstdж0оusing +copysignл65536ж0 +copysignfл65536ж0 +copysignlл65536ж0 +cosл64нstdж0оusing +cosл65536ж0 +coshл64нstdж0оusing +coshл65536ж0 +cpu_set_tл4096ж0оanon_struct_8 +daemon_л16м(int sock)ж0оvoid +daemonizeл16м(char *port)ж0оvoid +daemonizeл1024м(char *port)ж0оvoid +dataл64нanon_struct_4ж0оchar * +deviceл64нanon_struct_7ж0оchar * +divл64нstdж0оusing +divл65536ж0 +div_tл64нstdж0оusing +dtimeл16м()ж0оdouble +dtimeл1024м()ж0оdouble +echoл64нanon_struct_7ж0оint +end_codeл64нprctl_mm_mapж0о__u64 +end_dataл64нprctl_mm_mapж0о__u64 +end_optionл65536ж0 +end_suboptionл65536ж0 +env_endл64нprctl_mm_mapж0о__u64 +env_startл64нprctl_mm_mapж0о__u64 +erfл64нstdж0оusing +erfл65536ж0 +erfcл64нstdж0оusing +erfcл65536ж0 +erfcfл65536ж0 +erfclл65536ж0 +erffл65536ж0 +erflл65536ж0 +errcntл64нtimexж0о__syscall_slong_t +errnoл65536ж0 +esterrorл64нtimexж0о__syscall_slong_t +exe_fdл64нprctl_mm_mapж0о__u32 +exitл64нstdж0оusing +exitл65536ж0 +expл64нstdж0оusing +expл65536ж0 +exp2л64нstdж0оusing +exp2л65536ж0 +exp2fл65536ж0 +exp2lл65536ж0 +expm1л64нstdж0оusing +expm1л65536ж0 +expm1fл65536ж0 +expm1lл65536ж0 +fabsл64нstdж0оusing +fabsл65536ж0 +fdimл64нstdж0оusing +fdimл65536ж0 +fdimfл65536ж0 +fdimlл65536ж0 +fds_bitsл64нanon_struct_5ж0оunsigned long +flagл64нanon_struct_2ж0оint * +floorл64нstdж0оusing +floorл65536ж0 +fmaл64нstdж0оusing +fmaл65536ж0 +fmafл65536ж0 +fmalл65536ж0 +fmaxл64нstdж0оusing +fmaxл65536ж0 +fmaxfл65536ж0 +fmaxlл65536ж0 +fminл64нstdж0оusing +fminл65536ж0 +fminfл65536ж0 +fminlл65536ж0 +fmodл64нstdж0оusing +fmodл65536ж0 +fpclassifyл64нstdж0оusing +fpclassifyл65536ж0 +fpclassifyл131072м(x)ж0 +fread_unlockedл65536ж0 +freeл64нstdж0оusing +freeл65536ж0 +freqл64нtimexж0о__syscall_slong_t +frexpл64нstdж0оusing +frexpл65536ж0 +g_pr_л16м(const char *fmt, ...)ж0оint +get_aptrл16м(void *paptr, argtype type)ж0оvoid * +get_optindл16м(int opt, myoption *options)ж0оint +get_suboptionл16м(char *str, mysuboption *opt)ж0оbool +get_suboptionл1024м(char *str, mysuboption *opt)ж0оbool +getcл131072м(_fp)ж0 +getenvл64нstdж0оusing +getenvл65536ж0 +globErrл16384ж0оint +globErrл32768ж0оint +glob_parsл4096ж0оanon_struct_7 +greenл1024м(const char *fmt, ...)ж0оint +h_addrл65536ж0 +h_errnoл65536ж0 +handle_socketл16м(void *asock)ж0оvoid * +has_argл64нanon_struct_2ж0оhasarg +has_argл64нanon_struct_3ж0оhasarg +hasargл4096ж0оanon_enum_1 +helpл64нanon_struct_2ж0оconst char * +helpл16384ж0оint +helpstringл16384ж0оchar * +htobe16л131072м(x)ж0 +htobe32л131072м(x)ж0 +htobe64л131072м(x)ж0 +htole16л131072м(x)ж0 +htole32л131072м(x)ж0 +htole64л131072м(x)ж0 +htonlл131072м(x)ж0 +htonsл131072м(x)ж0 +hypotл64нstdж0оusing +hypotл65536ж0 +hypotfл65536ж0 +hypotlл65536ж0 +ilogbл64нstdж0оusing +ilogbл65536ж0 +ilogbfл65536ж0 +ilogblл65536ж0 +initial_setupл16м()ж0оvoid +initial_setupл1024м()ж0оvoid +int_fast16_tл4096ж0оlong int +int_fast32_tл4096ж0оlong int +int_fast64_tл4096ж0оlong int +int_fast8_tл4096ж0оsigned char +int_least16_tл4096ж0оshort int +int_least32_tл4096ж0оint +int_least64_tл4096ж0оlong int +int_least8_tл4096ж0оsigned char +intmax_tл4096ж0о__intmax_t +isfiniteл64нstdж0оusing +isfiniteл65536ж0 +isfiniteл131072м(x)ж0 +isgreaterл64нstdж0оusing +isgreaterл65536ж0 +isgreaterл131072м(x,y)ж0 +isgreaterequalл64нstdж0оusing +isgreaterequalл65536ж0 +isgreaterequalл131072м(x,y)ж0 +isinfл64нstdж0оusing +isinfл65536ж0 +isinfл131072м(x)ж0 +islessл64нstdж0оusing +islessл65536ж0 +islessл131072м(x,y)ж0 +islessequalл64нstdж0оusing +islessequalл65536ж0 +islessequalл131072м(x,y)ж0 +islessgreaterл64нstdж0оusing +islessgreaterл65536ж0 +islessgreaterл131072м(x,y)ж0 +isnanл64нstdж0оusing +isnanл65536ж0 +isnanл131072м(x)ж0 +isnormalл64нstdж0оusing +isnormalл65536ж0 +isnormalл131072м(x)ж0 +issubnormalл131072м(x)ж0 +isunorderedл64нstdж0оusing +isunorderedл65536ж0 +isunorderedл131072м(u,v)ж0 +it_intervalл64нitimerspecж0оtimespec +it_valueл64нitimerspecж0оtimespec +itimerspecл2048ж0 +jitcntл64нtimexж0о__syscall_slong_t +jitterл64нtimexж0о__syscall_slong_t +labsл64нstdж0оusing +labsл65536ж0 +ldexpл64нstdж0оusing +ldexpл65536ж0 +ldivл64нstdж0оusing +ldivл65536ж0 +ldiv_tл64нstdж0оusing +le16tohл131072м(x)ж0 +le32tohл131072м(x)ж0 +le64tohл131072м(x)ж0 +lenл64нanon_struct_4ж0оsize_t +lgammaл64нstdж0оusing +lgammaл65536ж0 +lgammafл65536ж0 +lgammalл65536ж0 +linuxл65536ж0 +llabsл65536ж0 +lldivл65536ж0 +llrintл64нstdж0оusing +llrintл65536ж0 +llrintfл65536ж0 +llrintlл65536ж0 +llroundл64нstdж0оusing +llroundл65536ж0 +llroundfл65536ж0 +llroundlл65536ж0 +logл64нstdж0оusing +logл65536ж0 +log10л64нstdж0оusing +log10л65536ж0 +log1pл64нstdж0оusing +log1pл65536ж0 +log1pfл65536ж0 +log1plл65536ж0 +log2л64нstdж0оusing +log2л65536ж0 +log2fл65536ж0 +log2lл65536ж0 +log_open_timeл16384ж0оtime_t +logbл64нstdж0оusing +logbл65536ж0 +logbfл65536ж0 +logblл65536ж0 +logfileл64нanon_struct_7ж0оchar * +lognameл16384ж0оchar * +lrintл64нstdж0оusing +lrintл65536ж0 +lrintfл65536ж0 +lrintlл65536ж0 +lroundл64нstdж0оusing +lroundл65536ж0 +lroundfл65536ж0 +lroundlл65536ж0 +mainл16м(int argc, char **argv)ж0оint +mallocл64нstdж0оusing +mallocл65536ж0 +math_errhandlingл65536ж0 +maxл65536ж0 +maxerrorл64нtimexж0о__syscall_slong_t +mblenл64нstdж0оusing +mblenл65536ж0 +mbstowcsл64нstdж0оusing +mbstowcsл65536ж0 +mbtowcл64нstdж0оusing +mbtowcл65536ж0 +minл65536ж0 +mmapbufл4096ж0оanon_struct_4 +modesл64нtimexж0оunsigned int +modfл64нstdж0оusing +modfл65536ж0 +mutexл16384ж0оpthread_mutex_t +my_allocл16м(size_t N, size_t S)ж0оvoid * +my_allocл1024м(size_t N, size_t S)ж0оvoid * +myatodл16м(void *num, const char *str, argtype t)ж0оbool +myatollл16м(void *num, char *str, argtype t)ж0оbool +mygetcharл16м()ж0оint +mygetcharл1024м()ж0оint +myoptionл4096ж0оanon_struct_2 +mysuboptionл4096ж0оanon_struct_3 +n_addrtypeл64нnetentж0оint +n_aliasesл64нnetentж0оchar * * +n_nameл64нnetentж0оchar * +n_netл64нnetentж0оuint32_t +nameл64нanon_struct_2ж0оconst char * +nameл64нanon_struct_3ж0оconst char * +nanл65536ж0 +nanfл65536ж0 +nanlл65536ж0 +nearbyintл64нstdж0оusing +nearbyintл65536ж0 +nearbyintfл65536ж0 +nearbyintlл65536ж0 +netentл2048ж0 +newtл16384ж0оtermios +nextafterл64нstdж0оusing +nextafterл65536ж0 +nextafterfл65536ж0 +nextafterlл65536ж0 +nexttowardл64нstdж0оusing +nexttowardл65536ж0 +nexttowardfл65536ж0 +nexttowardlл65536ж0 +no_argumentл65536ж0 +ntohlл131072м(x)ж0 +ntohsл131072м(x)ж0 +offsetл64нtimexж0о__syscall_slong_t +oldtл16384ж0оtermios +oldttyл16384ж0оtermio +openlogfileл16м(char *name)ж0оvoid +openlogfileл1024м(char *name)ж0оvoid +optional_argumentл65536ж0 +parse_argsл16м(int argc, char **argv)ж0оglob_pars * +parse_argsл1024м(int argc, char **argv)ж0оglob_pars * +parseargsл16м(int *argc, char ***argv, myoption *options)ж0оvoid +parseargsл1024м(int *argc, char ***argv, myoption *options)ж0оvoid +poll_deviceл16м()ж0оchar * +poll_deviceл1024м()ж0оchar * +portл64нanon_struct_7ж0оchar * +powл64нstdж0оusing +powл65536ж0 +ppsfreqл64нtimexж0о__syscall_slong_t +prctl_mm_mapл2048ж0 +precisionл64нtimexж0о__syscall_slong_t +pthread_cleanup_popл131072м(execute)ж0 +pthread_cleanup_pop_restore_npл131072м(execute)ж0 +pthread_cleanup_pushл131072м(routine,arg)ж0 +pthread_cleanup_push_defer_npл131072м(routine,arg)ж0 +putcл131072м(_ch,_fp)ж0 +putlogл16м(const char *fmt, ...)ж0оint +putlogл1024м(const char *fmt, ...)ж0оint +qsortл64нstdж0оusing +qsortл65536ж0 +quick_exitл64нstdж0оusing +quick_exitл65536ж0 +r_WARNл16м(const char *fmt, ...)ж0оint +r_pr_л16м(const char *fmt, ...)ж0оint +r_pr_nottyл16м(const char *fmt, ...)ж0оint +randл64нstdж0оusing +randл65536ж0 +read_consoleл16м()ж0оint +read_consoleл1024м()ж0оint +read_stringл16м()ж0оchar * +read_ttyл16м(char *buff, size_t length)ж0оsize_t +read_ttyл1024м(char *buff, size_t length)ж0оsize_t +reallocл64нstdж0оusing +reallocл65536ж0 +redл1024м(const char *fmt, ...)ж0оint +remainderл64нstdж0оusing +remainderл65536ж0 +remainderfл65536ж0 +remainderlл65536ж0 +remquoл64нstdж0оusing +remquoл65536ж0 +remquofл65536ж0 +remquolл65536ж0 +required_argumentл65536ж0 +rest_parsл64нanon_struct_7ж0оchar * * +rest_pars_numл64нanon_struct_7ж0оint +restore_consoleл16м()ж0оvoid +restore_consoleл1024м()ж0оvoid +restore_ttyл16м()ж0оvoid +restore_ttyл1024м()ж0оvoid +rintл64нstdж0оusing +rintл65536ж0 +rintfл65536ж0 +rintlл65536ж0 +roundл64нstdж0оusing +roundл65536ж0 +roundfл65536ж0 +roundlл65536ж0 +run_terminalл16м()ж0оvoid +run_terminalл1024м()ж0оvoid +s6_addrл65536ж0 +s6_addr16л65536ж0 +s6_addr32л65536ж0 +s_WARNл16м(const char *fmt, ...)ж0оint +sa_handlerл65536ж0 +sa_sigactionл65536ж0 +scalblnл64нstdж0оusing +scalblnл65536ж0 +scalblnfл65536ж0 +scalblnlл65536ж0 +scalbnл64нstdж0оusing +scalbnл65536ж0 +scalbnfл65536ж0 +scalbnlл65536ж0 +sched_paramл2048ж0 +sched_priorityл64нsched_paramж0оint +sched_priorityл65536ж0 +send_dataл16м(int sock, int webquery, char *textbuf)ж0оint +serverл16м(void *asock)ж0оvoid * +setup_conл16м()ж0оvoid +setup_conл1024м()ж0оvoid +shiftл64нtimexж0оint +showhelpл16м(int oindex, myoption *options)ж0оvoid +showhelpл1024м(int oindex, myoption *options)ж0оvoid +si_addrл65536ж0 +si_addr_lsbл65536ж0 +si_archл65536ж0 +si_bandл65536ж0 +si_call_addrл65536ж0 +si_fdл65536ж0 +si_intл65536ж0 +si_lowerл65536ж0 +si_overrunл65536ж0 +si_pidл65536ж0 +si_pkeyл65536ж0 +si_ptrл65536ж0 +si_statusл65536ж0 +si_stimeл65536ж0 +si_syscallл65536ж0 +si_timeridл65536ж0 +si_uidл65536ж0 +si_upperл65536ж0 +si_utimeл65536ж0 +si_valueл65536ж0 +sigev_notify_attributesл65536ж0 +sigev_notify_functionл65536ж0 +sigeventл32768ж0 +sigmaskл131072м(sig)ж0 +signalsл16м(int signo)ж0оvoid +signalsл1024м(int sig)ж0оvoid +signbitл64нstdж0оusing +signbitл65536ж0 +signbitл131072м(x)ж0 +sinл64нstdж0оusing +sinл65536ж0 +sinhл64нstdж0оusing +sinhл65536ж0 +size_tл4096ж0оlong unsigned int +sqrtл64нstdж0оusing +sqrtл65536ж0 +srandл64нstdж0оusing +srandл65536ж0 +st_atimeл65536ж0 +st_ctimeл65536ж0 +st_mtimeл65536ж0 +stabilл64нtimexж0о__syscall_slong_t +starsл16384ж0оconst char +start_brkл64нprctl_mm_mapж0о__u64 +start_codeл64нprctl_mm_mapж0о__u64 +start_dataл64нprctl_mm_mapж0о__u64 +start_stackл64нprctl_mm_mapж0о__u64 +statusл64нtimexж0оint +stbcntл64нtimexж0о__syscall_slong_t +stderrл65536ж0 +stdinл65536ж0 +stdoutл65536ж0 +str2doubleл16м(double *num, const char *str)ж0оint +str2doubleл1024м(double *num, const char *str)ж0оint +strdupaл131072м(s)ж0 +stringscanл16м(char *str, char *needle)ж0оchar * +strndupaл131072м(s,n)ж0 +strtodл64нstdж0оusing +strtodл65536ж0 +strtofл65536ж0 +strtolл64нstdж0оusing +strtolл65536ж0 +strtoldл65536ж0 +strtollл65536ж0 +strtoulл64нstdж0оusing +strtoulл65536ж0 +strtoullл65536ж0 +systemл64нstdж0оusing +systemл65536ж0 +taiл64нtimexж0оint +tanл64нstdж0оusing +tanл65536ж0 +tanhл64нstdж0оusing +tanhл65536ж0 +terminalл64нanon_struct_7ж0оint +tgammaл64нstdж0оusing +tgammaл65536ж0 +tgammafл65536ж0 +tgammalл65536ж0 +tickл64нtimexж0о__syscall_slong_t +timeл64нtimexж0оtimeval +timeraddл131072м(a,b,result)ж0 +timerclearл131072м(tvp)ж0 +timercmpл131072м(a,b,CMP)ж0 +timerissetл131072м(tvp)ж0 +timersubл131072м(a,b,result)ж0 +timexл2048ж0 +tmл2048ж0 +tm_gmtoffл64нtmж0оlong int +tm_hourл64нtmж0оint +tm_isdstл64нtmж0оint +tm_mdayл64нtmж0оint +tm_minл64нtmж0оint +tm_monл64нtmж0оint +tm_secл64нtmж0оint +tm_wdayл64нtmж0оint +tm_ydayл64нtmж0оint +tm_yearл64нtmж0оint +tm_zoneл64нtmж0оconst char * +toleranceл64нtimexж0о__syscall_slong_t +truncл64нstdж0оusing +truncл65536ж0 +truncfл65536ж0 +trunclл65536ж0 +try_connectл16м(char *device)ж0оvoid +try_connectл1024м(char *device)ж0оvoid +ttyл16384ж0оtermio +tty_initл16м(char *comdev)ж0оvoid +tty_initл1024м(char *comdev)ж0оvoid +typeл64нanon_struct_2ж0оargtype +typeл64нanon_struct_3ж0оargtype +uint16_tл4096ж0о__uint16_t +uint32_tл4096ж0о__uint32_t +uint64_tл4096ж0о__uint64_t +uint8_tл4096ж0о__uint8_t +uint_fast16_tл4096ж0оunsigned long int +uint_fast32_tл4096ж0оunsigned long int +uint_fast64_tл4096ж0оunsigned long int +uint_fast8_tл4096ж0оunsigned char +uint_least16_tл4096ж0оunsigned short int +uint_least32_tл4096ж0оunsigned int +uint_least64_tл4096ж0оunsigned long int +uint_least8_tл4096ж0оunsigned char +uintmax_tл4096ж0о__uintmax_t +uintptr_tл4096ж0оunsigned long int +unixл65536ж0 +va_argл131072м(v,l)ж0 +va_copyл131072м(d,s)ж0 +va_endл131072м(v)ж0 +va_startл131072м(v,l)ж0 +valл64нanon_struct_2ж0оint +valл64нanon_struct_6ж0оint +waittoreadл16м(int sock)ж0оint +wcstombsл64нstdж0оusing +wcstombsл65536ж0 +wctombл64нstdж0оusing +wctombл65536ж0 +write_ttyл16м(char *buff, size_t length)ж0оint +write_ttyл1024м(char *buff, size_t length)ж0оint diff --git a/Daemons/netdaemon/parseargs.c b/Daemons/netdaemon/parseargs.c new file mode 100644 index 0000000..b235752 --- /dev/null +++ b/Daemons/netdaemon/parseargs.c @@ -0,0 +1,497 @@ +/* geany_encoding=koi8-r + * parseargs.c - parsing command line arguments & print help + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include // printf +#include // getopt_long +#include // calloc, exit, strtoll +#include // assert +#include // strdup, strchr, strlen +#include // strcasecmp +#include // INT_MAX & so on +#include // gettext +#include // isalpha +#include "parseargs.h" +#include "usefull_macros.h" + +char *helpstring = "%s\n"; + +/** + * Change standard help header + * MAY consist ONE "%s" for progname + * @param str (i) - new format + */ +void change_helpstring(char *s){ + int pcount = 0, scount = 0; + char *str = s; + // check `helpstring` and set it to default in case of error + for(; pcount < 2; str += 2){ + if(!(str = strchr(str, '%'))) break; + if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" + else{ + str += 2; // pass next '%' + continue; + } + if(str[1] == 's') scount++; // increment "%s" counter + }; + if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong + /// "Неправильный формат строки помощи" + ERRX(_("Wrong helpstring!")); + } + helpstring = s; +} + +/** + * Carefull atoll/atoi + * @param num (o) - returning value (or NULL if you wish only check number) - allocated by user + * @param str (i) - string with number must not be NULL + * @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 sone without errors, FALSE otherwise + */ +static bool myatoll(void *num, char *str, argtype t){ + long long tmp, *llptr; + int *iptr; + char *endptr; + assert(str); + assert(num); + tmp = strtoll(str, &endptr, 0); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_longlong: + llptr = (long long*) num; + *llptr = tmp; + break; + case arg_int: + default: + if(tmp < INT_MIN || tmp > INT_MAX){ + /// "Целое вне допустимого диапазона" + WARNX(_("Integer out of range")); + return FALSE; + } + iptr = (int*)num; + *iptr = (int)tmp; + } + return TRUE; +} + +// 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){ + double tmp, *dptr; + float *fptr; + char *endptr; + assert(str); + tmp = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_double: + dptr = (double *) num; + *dptr = tmp; + break; + case arg_float: + default: + fptr = (float *) num; + *fptr = (float)tmp; + break; + } + return TRUE; +} + +/** + * 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){ + int oind; + myoption *opts = options; + assert(opts); + for(oind = 0; opts->name && opts->val != opt; oind++, opts++); + if(!opts->name || opts->val != opt) // no such parameter + showhelp(-1, options); + return oind; +} + +/** + * reallocate new value in array of multiple repeating arguments + * @arg paptr - address of pointer to array (**void) + * @arg type - its type (for realloc) + * @return pointer to new (next) value + */ +void *get_aptr(void *paptr, argtype type){ + int i = 1; + void **aptr = *((void***)paptr); + if(aptr){ // there's something in array + void **p = aptr; + while(*p++) ++i; + } + size_t sz = 0; + switch(type){ + default: + case arg_none: + /// "Не могу использовать несколько параметров без аргументов!" + ERRX("Can't use multiple args with arg_none!"); + break; + case arg_int: + sz = sizeof(int); + break; + case arg_longlong: + sz = sizeof(long long); + break; + case arg_double: + sz = sizeof(double); + break; + case arg_float: + sz = sizeof(float); + break; + case arg_string: + sz = 0; + break; + /* case arg_function: + sz = sizeof(argfn *); + break;*/ + } + aptr = realloc(aptr, (i + 1) * sizeof(void*)); + *((void***)paptr) = aptr; + aptr[i] = NULL; + if(sz){ + aptr[i - 1] = malloc(sz); + }else + aptr[i - 1] = &aptr[i - 1]; + return aptr[i - 1]; +} + + +/** + * 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` + * @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt` + * BE CAREFUL! if you wanna use full argc & argv, save their original values before + * calling this function + * @param options (i) - array of `myoption` for arguments parcing + * + * @exit: in case of error this function show help & make `exit(-1)` + */ +void parseargs(int *argc, char ***argv, myoption *options){ + char *short_options, *soptr; + struct option *long_options, *loptr; + size_t optsize, i; + myoption *opts = options; + // check whether there is at least one options + assert(opts); + assert(opts[0].name); + // first we count how much values are in opts + for(optsize = 0; opts->name; optsize++, opts++); + // now we can allocate memory + 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 + 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 + } + if(opts->type != arg_none) // if there is a flag without arg, check its pointer + assert(opts->argptr); + // fill long_options + // don't do memcmp: what if there would be different alignment? + loptr->name = opts->name; + loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; + loptr->flag = opts->flag; + 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++ = ':'; + if(loptr->has_arg == 2) // add '::' if option has optional argument + *soptr++ = ':'; + } + } + // sort all lists & check for repeating +#ifdef EBUG + int cmpstringp(const void *p1, const void *p2){ + return strcmp(* (char * const *) p1, * (char * const *) p2); + } + int cmpcharp(const void *p1, const void *p2){ + return (int)(*(char * const)p1 - *(char *const)p2); + } + qsort(longlist, optsize, sizeof(char *), cmpstringp); + qsort(shortlist,optsize, sizeof(char), cmpcharp); + char *prevl = longlist[0], prevshrt = shortlist[0]; + for(i = 1; i < optsize; ++i){ + if(longlist[i]){ + if(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); + } + prevshrt = shortlist[i]; + } + } +#endif + // 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); + 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; + else optind = get_optind(opt, options); + } + opts = &options[optind]; + // if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag + // now check option + if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) + if(!optarg) 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; + // even if there is no argument, but argptr != NULL, think that optarg = "1" + if(!optarg) optarg = "1"; + switch(opts->type){ + default: + case arg_none: + if(opts->argptr) *((int*)aptr) += 1; // increment value + break; + case arg_int: + result = myatoll(aptr, optarg, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, optarg, arg_longlong); + break; + case arg_double: + result = myatod(aptr, optarg, arg_double); + break; + case arg_float: + result = myatod(aptr, optarg, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(optarg)); + break; + case arg_function: + result = ((argfn)aptr)(optarg); + break; + } + if(!result){ + showhelp(optind, options); + } + } + *argc -= optind; + *argv += optind; +} + +/** + * compare function for qsort + * 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 char *l1 = o1->name, *l2 = o2->name; + int s1 = o1->val, s2 = o2->val; + int *f1 = o1->flag, *f2 = o2->flag; + // check if both options has short arg + if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg + return (s1 - s2); + }else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long + return strcmp(l1, l2); + }else{ // only one have short arg -- return it + if(f2 || !s2) return -1; // a1 have short - it is 'lesser' + else return 1; + } +} + +/** + * 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` + * + * @exit: run `exit(-1)` !!! + */ +void showhelp(int oindex, myoption *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; + assert(opts); + assert(opts[0].name); // check whether there is at least one options + if(oindex > -1){ // print only one message + opts = &options[oindex]; + printf(" "); + if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); + printf("--%s", opts->name); + if(opts->has_arg == 1) printf("=arg"); + else if(opts->has_arg == 2) printf("[=arg]"); + printf(" %s\n", _(opts->help)); + exit(-1); + } + // header, by default is just "progname\n" + printf("\n"); + if(strstr(helpstring, "%s")) // print progname + printf(helpstring, __progname); + else // only text + printf("%s", helpstring); + printf("\n"); + // count max_opt_len + do{ + int L = strlen(opts->name); + if(max_opt_len < L) max_opt_len = L; + }while((++opts)->name); + max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols + opts = options; + // count amount of options + int N; for(N = 0; opts->name; ++N, ++opts); + if(N == 0) exit(-2); + // Now print all help (sorted) + opts = options; + qsort(opts, N, sizeof(myoption), argsort); + do{ + int p = sprintf(buf, " "); // a little indent + if(!opts->flag && opts->val) // .val is short argument + p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); + p += snprintf(buf+p, bufsz-p, "--%s", opts->name); + if(opts->has_arg == 1) // required argument + p += snprintf(buf+p, bufsz-p, "=arg"); + else if(opts->has_arg == 2) // optional argument + p += snprintf(buf+p, bufsz-p, "[=arg]"); + assert(p < max_opt_len); // there would be magic if p >= max_opt_len + printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after + ++opts; + }while(--N); + printf("\n\n"); + exit(-1); +} + +/** + * 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 idx = 0; + if(!par) return -1; + while(so[idx].name){ + if(strcasecmp(par, so[idx].name) == 0) return idx; + ++idx; + } + return -1; // badarg + } + bool opt_setarg(mysuboption *so, int idx, char *val){ + mysuboption *soptr = &so[idx]; + bool result = FALSE; + void *aptr = soptr->argptr; + switch(soptr->type){ + default: + case arg_none: + if(soptr->argptr) *((int*)aptr) += 1; // increment value + result = TRUE; + break; + case arg_int: + result = myatoll(aptr, val, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, val, arg_longlong); + break; + case arg_double: + result = myatod(aptr, val, arg_double); + break; + case arg_float: + result = myatod(aptr, val, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(val)); + break; + case arg_function: + result = ((argfn)aptr)(val); + break; + } + return result; + } + char *tok; + bool ret = FALSE; + char *tmpbuf; + tok = strtok_r(str, ":,", &tmpbuf); + do{ + char *val = strchr(tok, '='); + int noarg = 0; + if(val == NULL){ // no args + val = "1"; + noarg = 1; + }else{ + *val++ = '\0'; + if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = + val = "1"; noarg = 1; + } + } + int idx = findsubopt(tok, opt); + if(idx < 0){ + /// "Неправильный параметр: %s" + WARNX(_("Wrong parameter: %s"), tok); + goto returning; + } + if(noarg && opt[idx].has_arg == NEED_ARG){ + /// "%s: необходим аргумент!" + WARNX(_("%s: argument needed!"), tok); + goto returning; + } + if(!opt_setarg(opt, idx, val)){ + /// "Неправильный аргумент \"%s\" параметра \"%s\"" + WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); + goto returning; + } + }while((tok = strtok_r(NULL, ":,", &tmpbuf))); + ret = TRUE; +returning: + return ret; +} diff --git a/Daemons/netdaemon/parseargs.h b/Daemons/netdaemon/parseargs.h new file mode 100644 index 0000000..537fc5b --- /dev/null +++ b/Daemons/netdaemon/parseargs.h @@ -0,0 +1,124 @@ +/* geany_encoding=koi8-r + * parseargs.h - headers for parsing command line arguments + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __PARSEARGS_H__ +#define __PARSEARGS_H__ + +#include // bool +#include + +#ifndef TRUE + #define TRUE true +#endif + +#ifndef FALSE + #define FALSE false +#endif + +// macro for argptr +#define APTR(x) ((void*)x) + +// if argptr is a function: +typedef bool(*argfn)(void *arg); + +/* + * type of getopt's argument + * WARNING! + * My function change value of flags by pointer, so if you want to use another type + * make a latter conversion, example: + * char charg; + * int iarg; + * myoption opts[] = { + * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; + * ..(parse args).. + * charg = (char) iarg; + */ +typedef enum { + arg_none = 0, // no arg + arg_int, // integer + arg_longlong, // long long + arg_double, // double + arg_float, // float + arg_string, // char * + arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` +} argtype; + +/* + * Structure for getopt_long & help + * BE CAREFUL: .argptr is pointer to data or pointer to function, + * conversion depends on .type + * + * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext, + * but you can redefine it before `#include "parseargs.h"` + * + * if arg is string, then value wil be strdup'ed like that: + * char *str; + * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; + * *(opts[1].str) = strdup(optarg); + * in other cases argptr should be address of some variable (or pointer to allocated memory) + * + * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr + * + * !!!LAST VALUE OF ARRAY SHOULD BE `end_option` or ZEROS !!! + * + */ +typedef enum{ + NO_ARGS = 0, // first three are the same as in getopt_long + NEED_ARG = 1, + OPT_ARG = 2, + MULT_PAR +} hasarg; + +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) + 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)` + const char *help; // help string which would be shown in function `showhelp` or NULL +} myoption; + +/* + * Suboptions structure, almost the same like myoption + * used in parse_subopts() + */ +typedef struct{ + const char *name; + hasarg has_arg; + argtype type; + void *argptr; +} mysuboption; + +// last string of array (all zeros) +#define end_option {0,0,0,0,0,0,0} +#define end_suboption {0,0,0,0} + +extern const char *__progname; + +void showhelp(int oindex, myoption *options); +void parseargs(int *argc, char ***argv, myoption *options); +void change_helpstring(char *s); +bool get_suboption(char *str, mysuboption *opt); + +#endif // __PARSEARGS_H__ diff --git a/Daemons/netdaemon/socket.c b/Daemons/netdaemon/socket.c new file mode 100644 index 0000000..c249aff --- /dev/null +++ b/Daemons/netdaemon/socket.c @@ -0,0 +1,308 @@ +/* + * geany_encoding=koi8-r + * socket.c - socket IO + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "usefull_macros.h" +#include "socket.h" +#include "term.h" +#include // addrinfo +#include // inet_ntop +#include +#include // INT_xxx +#include // pthread_kill +#include // daemon +#include // syscall + +#include "cmdlnopts.h" // glob_pars + +#define BUFLEN (10240) +// Max amount of connections +#define BACKLOG (30) + +extern glob_pars *GP; + +/* + * Define global data buffers here + */ + +/**************** COMMON FUNCTIONS ****************/ +/** + * wait for answer from socket + * @param sock - socket fd + * @return 0 in case of error or timeout, 1 in case of socket ready + */ +static int waittoread(int sock){ + fd_set fds; + struct timeval timeout; + int rc; + timeout.tv_sec = 1; // wait not more than 1 second + timeout.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(sock, &fds); + do{ + rc = select(sock+1, &fds, NULL, NULL, &timeout); + if(rc < 0){ + if(errno != EINTR){ + WARN("select()"); + return 0; + } + continue; + } + break; + }while(1); + if(FD_ISSET(sock, &fds)) return 1; + return 0; +} + +/**************** SERVER FUNCTIONS ****************/ +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +/** + * Send data over socket + * @param sock - socket fd + * @param webquery - ==1 if this is web query + * @param textbuf - zero-trailing buffer with data to send + * @return 1 if all OK + */ +static int send_data(int sock, int webquery, char *textbuf){ + ssize_t L, Len; + char tbuf[BUFLEN]; + Len = strlen(textbuf); + // OK buffer ready, prepare to send it + if(webquery){ + L = snprintf((char*)tbuf, BUFLEN, + "HTTP/2.0 200 OK\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Methods: GET, POST\r\n" + "Access-Control-Allow-Credentials: true\r\n" + "Content-type: text/plain\r\nContent-Length: %zd\r\n\r\n", Len); + if(L < 0){ + WARN("sprintf()"); + return 0; + } + if(L != write(sock, tbuf, L)){ + WARN("write"); + return 0; + } + } + // send data + //DBG("send %zd bytes\nBUF: %s", Len, buf); + if(Len != write(sock, textbuf, Len)){ + WARN("write()"); + return 0; + } + return 1; +} + +// search a first word after needle without spaces +static char* stringscan(char *str, char *needle){ + char *a, *e; + char *end = str + strlen(str); + a = strstr(str, needle); + if(!a) return NULL; + a += strlen(needle); + while (a < end && (*a == ' ' || *a == '\r' || *a == '\t' || *a == '\r')) a++; + if(a >= end) return NULL; + e = strchr(a, ' '); + if(e) *e = 0; + return a; +} + +static void *handle_socket(void *asock){ + //putlog("handle_socket(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); + FNAME(); + int sock = *((int*)asock); + int webquery = 0; // whether query is web or regular + char buff[BUFLEN]; + ssize_t rd; + double t0 = dtime(); + /* + * INSERT CODE HERE + * change to while(1) if socket shouldn't be closed after data transmission + */ + while(dtime() - t0 < SOCKET_TIMEOUT){ + if(!waittoread(sock)){ // no data incoming + continue; + } + if(!(rd = read(sock, buff, BUFLEN-1))){ + //putlog("socket closed. Exit"); + break; + } + //putlog("client send %zd bytes", rd); + DBG("Got %zd bytes", rd); + if(rd < 0){ // error + //putlog("some error occured"); + DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); + break; + } + // add trailing zero to be on the safe side + buff[rd] = 0; + // now we should check what do user want + char *got, *found = buff; + if((got = stringscan(buff, "GET")) || (got = stringscan(buff, "POST"))){ // web query + webquery = 1; + char *slash = strchr(got, '/'); + if(slash) found = slash + 1; + // web query have format GET /some.resource + } + // here we can process user data + DBG("user send: %s\nfound=%s", buff, found); + if(GP->echo){ + if(!send_data(sock, webquery, found)){ + putlog("can't send data, some error occured"); + } + } + pthread_mutex_lock(&mutex); + /* + * INSERT CODE HERE + * Process user commands here & send him an answer + * remove trailing break if socket shouldn't be closed after server sent data + */ + pthread_mutex_unlock(&mutex); + break; + } + close(sock); + //DBG("closed"); + //putlog("socket closed, exit"); + pthread_exit(NULL); + return NULL; +} + +// main socket server +static void *server(void *asock){ + putlog("server(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); + int sock = *((int*)asock); + if(listen(sock, BACKLOG) == -1){ + putlog("listen() failed"); + WARN("listen"); + return NULL; + } + while(1){ + socklen_t size = sizeof(struct sockaddr_in); + struct sockaddr_in their_addr; + int newsock; + if(!waittoread(sock)) continue; + newsock = accept(sock, (struct sockaddr*)&their_addr, &size); + if(newsock <= 0){ + putlog("accept() failed"); + WARN("accept()"); + continue; + } + struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&their_addr; + struct in_addr ipAddr = pV4Addr->sin_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); + //putlog("get connection from %s", str); + DBG("Got connection from %s\n", str); + pthread_t handler_thread; + if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){ + putlog("server(): pthread_create() failed"); + WARN("pthread_create()"); + }else{ + DBG("Thread created, detouch"); + pthread_detach(handler_thread); // don't care about thread state + } + } + putlog("server(): UNREACHABLE CODE REACHED!"); +} + +// data gathering & socket management +static void daemon_(int sock){ + if(sock < 0) return; + pthread_t sock_thread; + if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ + putlog("daemon_(): pthread_create() failed"); + ERR("pthread_create()"); + } + double tgot = 0.; + do{ + if(pthread_kill(sock_thread, 0) == ESRCH){ // died + WARNX("Sockets thread died"); + putlog("Sockets thread died"); + pthread_join(sock_thread, NULL); + if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ + putlog("daemon_(): new pthread_create() failed"); + ERR("pthread_create()"); + } + } + usleep(1000); // sleep a little or thread's won't be able to lock mutex + if(dtime() - tgot < T_INTERVAL) continue; + tgot = dtime(); + /* + * INSERT CODE HERE + * Gather data (poll_device) + */ + // copy temporary buffers to main + pthread_mutex_lock(&mutex); + /* + * INSERT CODE HERE + * fill global data buffers + */ + pthread_mutex_unlock(&mutex); + }while(1); + putlog("daemon_(): UNREACHABLE CODE REACHED!"); +} + +/** + * Run daemon service + */ +void daemonize(char *port){ + FNAME(); + int sock = -1; + struct addrinfo hints, *res, *p; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if(getaddrinfo(NULL, port, &hints, &res) != 0){ + ERR("getaddrinfo"); + } + struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN); + // loop through all the results and bind to the first we can + for(p = res; p != NULL; p = p->ai_next){ + if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){ + WARN("socket"); + continue; + } + int reuseaddr = 1; + if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ + ERR("setsockopt"); + } + if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){ + close(sock); + WARN("bind"); + continue; + } + break; // if we get here, we have a successfull connection + } + if(p == NULL){ + putlog("failed to bind socket, exit"); + // looped off the end of the list with no successful bind + ERRX("failed to bind socket"); + } + freeaddrinfo(res); + daemon_(sock); + close(sock); + putlog("socket closed, exit"); + signals(0); +} + diff --git a/Daemons/netdaemon/socket.h b/Daemons/netdaemon/socket.h new file mode 100644 index 0000000..f8b1add --- /dev/null +++ b/Daemons/netdaemon/socket.h @@ -0,0 +1,34 @@ +/* + * geany_encoding=koi8-r + * socket.h + * + * Copyright 2017 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __SOCKET_H__ +#define __SOCKET_H__ + +// timeout for socket closing +#define SOCKET_TIMEOUT (5.0) +// time interval for data polling (seconds) +#define T_INTERVAL (10.) + +void daemonize(char *port); + +#endif // __SOCKET_H__ diff --git a/Daemons/netdaemon/term.c b/Daemons/netdaemon/term.c new file mode 100644 index 0000000..d4261e3 --- /dev/null +++ b/Daemons/netdaemon/term.c @@ -0,0 +1,118 @@ +/* geany_encoding=koi8-r + * client.c - terminal parser + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "usefull_macros.h" +#include "term.h" +#include // strncasecmp +#include // time(NULL) +#include // INT_MAX, INT_MIN + +#define BUFLEN 1024 + +static char buf[BUFLEN]; + +/** + * read strings from terminal (ending with '\n') with timeout + * @return NULL if nothing was read or pointer to static buffer + */ +static char *read_string(){ + size_t r = 0, l; + int LL = BUFLEN - 1; + char *ptr = NULL; + static char *optr = NULL; + if(optr && *optr){ + ptr = optr; + optr = strchr(optr, '\n'); + if(optr) ++optr; + //DBG("got data, roll to next; ptr=%s\noptr=%s",ptr,optr); + return ptr; + } + ptr = buf; + double d0 = dtime(); + do{ + if((l = read_tty(ptr, LL))){ + r += l; LL -= l; ptr += l; + if(ptr[-1] == '\n') break; + d0 = dtime(); + } + }while(dtime() - d0 < WAIT_TMOUT && LL); + if(r){ + buf[r] = 0; + //DBG("r=%zd, got string: %s", r, buf); + optr = strchr(buf, '\n'); + if(optr) ++optr; + return buf; + } + return NULL; +} + +/** + * Try to connect to `device` at BAUD_RATE speed + * @return connection speed if success or 0 + */ +void try_connect(char *device){ + if(!device) return; + char tmpbuf[4096]; + fflush(stdout); + tty_init(device); + read_tty(tmpbuf, 4096); // clear rbuf + putlog("Connected to %s", device); +} + +/** + * run terminal emulation: send user's commands and show answers + */ +void run_terminal(){ + green(_("Work in terminal mode without echo\n")); + int rb; + char buf[BUFLEN]; + size_t l; + setup_con(); + while(1){ + if((l = read_tty(buf, BUFLEN - 1))){ + buf[l] = 0; + printf("%s", buf); + } + if((rb = read_console())){ + buf[0] = (char) rb; + write_tty(buf, 1); + } + } +} + +/** + * Poll serial port for new dataportion + * @return: NULL if no data received, pointer to string if valid data received + */ +char *poll_device(){ + char *ans; + double t0 = dtime(); + while(dtime() - t0 < T_POLLING_TMOUT){ + if((ans = read_string())){ // parse new data + DBG("got %s", ans); + /* + * INSERT CODE HERE + * (data validation) + */ + return ans; + } + } + return NULL; +} diff --git a/Daemons/netdaemon/term.h b/Daemons/netdaemon/term.h new file mode 100644 index 0000000..9c64ac8 --- /dev/null +++ b/Daemons/netdaemon/term.h @@ -0,0 +1,36 @@ +/* geany_encoding=koi8-r + * term.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __TERM_H__ +#define __TERM_H__ + +#define FRAME_MAX_LENGTH (300) +#define MAX_MEMORY_DUMP_SIZE (0x800 * 4) +// Terminal timeout (seconds) +#define WAIT_TMOUT (0.5) +// Terminal polling timeout - 1 second +#define T_POLLING_TMOUT (1.0) + +void run_terminal(); +void try_connect(char *device); +char *poll_device(); + +#endif // __TERM_H__ diff --git a/Daemons/netdaemon/usefull_macros.c b/Daemons/netdaemon/usefull_macros.c new file mode 100644 index 0000000..8e24425 --- /dev/null +++ b/Daemons/netdaemon/usefull_macros.c @@ -0,0 +1,434 @@ +/* + * usefull_macros.h - a set of usefull functions: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "usefull_macros.h" +#include +#include // PATH_MAX + +/** + * function for different purposes that need to know time intervals + * @return double value: time in seconds + */ +double dtime(){ + double t; + struct timeval tv; + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1e6; + return t; +} + +/******************************************************************************\ + * Coloured terminal +\******************************************************************************/ +int globErr = 0; // errno for WARN/ERR + +// pointers to coloured output printf +int (*red)(const char *fmt, ...); +int (*green)(const char *fmt, ...); +int (*_WARN)(const char *fmt, ...); + +/* + * format red / green messages + * name: r_pr_, g_pr_ + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(RED); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +int g_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(GREEN); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +/* + * print red error/warning messages (if output is a tty) + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_WARN(const char *fmt, ...){ + va_list ar; int i = 1; + fprintf(stderr, RED); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = vfprintf(stderr, fmt, ar); + va_end(ar); + i++; + fprintf(stderr, OLDCOLOR "\n"); + return i; +} + +static const char stars[] = "****************************************"; +/* + * notty variants of coloured printf + * name: s_WARN, r_pr_notty + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int s_WARN(const char *fmt, ...){ + va_list ar; int i; + i = fprintf(stderr, "\n%s\n", stars); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = +vfprintf(stderr, fmt, ar); + va_end(ar); + i += fprintf(stderr, "\n%s\n", stars); + i += fprintf(stderr, "\n"); + return i; +} +int r_pr_notty(const char *fmt, ...){ + va_list ar; int i; + i = printf("\n%s\n", stars); + va_start(ar, fmt); + i += vprintf(fmt, ar); + va_end(ar); + i += printf("\n%s\n", stars); + return i; +} + +/** + * Run this function in the beginning of main() to setup locale & coloured output + */ +void initial_setup(){ + // setup coloured output + if(isatty(STDOUT_FILENO)){ // make color output in tty + red = r_pr_; green = g_pr_; + }else{ // no colors in case of pipe + red = r_pr_notty; green = printf; + } + if(isatty(STDERR_FILENO)) _WARN = r_WARN; + else _WARN = s_WARN; + // Setup locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#if defined GETTEXT_PACKAGE && defined LOCALEDIR + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); +#endif +} + +/******************************************************************************\ + * Memory +\******************************************************************************/ +/* + * 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 *p = calloc(N, S); + if(!p) ERR("malloc"); + //assert(p); + return p; +} + +/** + * 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){ + int fd; + char *ptr; + size_t Mlen; + struct stat statbuf; + /// "Не задано имя файла!" + if(!filename){ + WARNX(_("No filename given!")); + return NULL; + } + if((fd = open(filename, O_RDONLY)) < 0){ + /// "Не могу открыть %s для чтения" + WARN(_("Can't open %s for reading"), filename); + return NULL; + } + if(fstat (fd, &statbuf) < 0){ + /// "Не могу выполнить stat %s" + WARN(_("Can't stat %s"), filename); + close(fd); + return NULL; + } + Mlen = statbuf.st_size; + if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){ + /// "Ошибка mmap" + WARN(_("Mmap error for input")); + close(fd); + return NULL; + } + /// "Не могу закрыть mmap'нутый файл" + if(close(fd)) WARN(_("Can't close mmap'ed file")); + mmapbuf *ret = MALLOC(mmapbuf, 1); + ret->data = ptr; + ret->len = Mlen; + return ret; +} + +void My_munmap(mmapbuf *b){ + if(munmap(b->data, b->len)){ + /// "Не могу munmap" + ERR(_("Can't munmap")); + } + FREE(b); +} + + +/******************************************************************************\ + * Terminal in no-echo mode +\******************************************************************************/ +static struct termios oldt, newt; // terminal flags +static int console_changed = 0; +// run on exit: +void restore_console(){ + if(console_changed) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state + console_changed = 0; +} + +// initial setup: +void setup_con(){ + if(console_changed) return; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ + /// "Не могу настроить консоль" + WARN(_("Can't setup console")); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + signals(0); //quit? + } + console_changed = 1; +} + +/** + * Read character from console without echo + * @return char readed + */ +int read_console(){ + int rb; + struct timeval tv; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(1, &rfds, NULL, NULL, &tv); + if(!retval) rb = 0; + else { + if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); + else rb = 0; + } + return rb; +} + +/** + * getchar() without echo + * wait until at least one character pressed + * @return character readed + */ +int mygetchar(){ // getchar() without need of pressing ENTER + int ret; + do ret = read_console(); + while(ret == 0); + return ret; +} + + +/******************************************************************************\ + * TTY with select() +\******************************************************************************/ +static struct termio oldtty, tty; // TTY flags +static int comfd = -1; // TTY fd + +// run on exit: +void restore_tty(){ + if(comfd == -1) return; + ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state + close(comfd); + comfd = -1; +} + +#ifndef BAUD_RATE +#define BAUD_RATE B4800 +#endif +// init: +void tty_init(char *comdev){ + DBG("\nOpen port %s ...\n", comdev); + do{ + comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK); + }while (comfd == -1 && errno == EINTR); + if(comfd < 0){ + WARN("Can't use port %s\n",comdev); + signals(-1); // quit? + } + // make exclusive open + if(ioctl(comfd, TIOCEXCL)){ + WARN(_("Can't do exclusive open")); + close(comfd); + signals(2); + } + DBG(" OK\nGet current settings... "); + if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings + /// "Не могу получить настройки" + WARN(_("Can't get settings")); + signals(-1); + } + tty = oldtty; + tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) + tty.c_oflag = 0; + tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl + tty.c_cc[VMIN] = 0; // non-canonical mode + tty.c_cc[VTIME] = 5; + if(ioctl(comfd,TCSETA,&tty) < 0){ + /// "Не могу установить настройки" + WARN(_("Can't set settings")); + signals(-1); + } + DBG(" OK\n"); +} + +/** + * Read data from TTY + * @param buff (o) - buffer for data read + * @param length - buffer len + * @return amount of bytes read + */ +size_t read_tty(char *buff, size_t length){ + ssize_t L = 0, l; + char *ptr = buff; + fd_set rfds; + struct timeval tv; + int retval; + do{ + l = 0; + FD_ZERO(&rfds); + FD_SET(comfd, &rfds); + // wait for 100ms + tv.tv_sec = 0; tv.tv_usec = 100000; + retval = select(comfd + 1, &rfds, NULL, NULL, &tv); + if (!retval) break; + if(FD_ISSET(comfd, &rfds)){ + if((l = read(comfd, ptr, length)) < 1){ + return 0; + } + ptr += l; L += l; + length -= l; + } + }while(l); + return (size_t)L; +} + +int write_tty(char *buff, size_t length){ + ssize_t L = write(comfd, buff, length); + if((size_t)L != length){ + /// "Ошибка записи!" + WARN("Write error"); + return 1; + } + return 0; +} + + +/** + * 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){ + double res; + char *endptr; + if(!str) return 0; + res = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0'){ + /// "Неправильный формат числа double!" + WARNX("Wrong double number format!"); + return FALSE; + } + if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number + return TRUE; +} + +FILE *Flog = NULL; // log file descriptor +char *logname = NULL; +time_t log_open_time = 0; +/** + * Try to open log file + * if failed show warning message + */ +void openlogfile(char *name){ + if(!name){ + WARNX(_("Need filename")); + return; + } + green(_("Try to open log file %s in append mode\n"), name); + 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, "\n\t\t%s", ctime(&t_now)); + va_list ar; + va_start(ar, fmt); + i = vfprintf(Flog, fmt, ar); + va_end(ar); + fprintf(Flog, "\n"); + fflush(Flog); + return i; +} diff --git a/Daemons/netdaemon/usefull_macros.h b/Daemons/netdaemon/usefull_macros.h new file mode 100644 index 0000000..00b6140 --- /dev/null +++ b/Daemons/netdaemon/usefull_macros.h @@ -0,0 +1,140 @@ +/* + * usefull_macros.h - a set of usefull macros: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __USEFULL_MACROS_H__ +#define __USEFULL_MACROS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined GETTEXT_PACKAGE && defined LOCALEDIR +/* + * GETTEXT + */ +#include +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) +#else +#define _(String) (String) +#define N_(String) (String) +#endif +#include +#include +#include +#include +#include +#include + + +// unused arguments with -Wall -Werror +#define _U_ __attribute__((__unused__)) + +/* + * Coloured messages output + */ +#define RED "\033[1;31;40m" +#define GREEN "\033[1;32;40m" +#define OLDCOLOR "\033[0;0;0m" + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +/* + * ERROR/WARNING messages + */ +extern int globErr; +extern void signals(int sig); +#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) +#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0) +#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) +#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) + +/* + * print function name, debug messages + * debug mode, -DEBUG + */ +#ifdef EBUG + #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) +#else + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) +#endif //EBUG + +/* + * 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 FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0) + +#ifndef DBL_EPSILON +#define DBL_EPSILON (2.2204460492503131e-16) +#endif + +double 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, ...); +void * my_alloc(size_t N, size_t S); +void initial_setup(); + +// mmap file +typedef struct{ + char *data; + size_t len; +} mmapbuf; +mmapbuf *My_mmap(char *filename); +void My_munmap(mmapbuf *b); + +void restore_console(); +void setup_con(); +int read_console(); +int mygetchar(); + +void restore_tty(); +void tty_init(char *comdev); +size_t read_tty(char *buff, size_t length); +int write_tty(char *buff, size_t length); + +int str2double(double *num, const char *str); + +void openlogfile(char *name); +int putlog(const char *fmt, ...); +#endif // __USEFULL_MACROS_H__ diff --git a/Daemons/netsocket/HWpoweroff b/Daemons/netsocket/HWpoweroff new file mode 100755 index 0000000..fba79d7 --- /dev/null +++ b/Daemons/netsocket/HWpoweroff @@ -0,0 +1,25 @@ +#!/bin/bash + +COMDEV=/dev/ttyUSB0 +stty -F $COMDEV -hupcl -opost -onlcr -isig -iexten -echo -echoe -echok -echoctl -echoke -icanon min 0 time 5 + +# A - turn off triac0 +# B - turn off triac1 +# c/C - check in0/1 +# i/I - show current ampl. (ADU) +# k/K - set/reset PKEY1 +# l/L - set/reset NKEY1 +# m/M - set/reset NKEY2 +# n/o - activate out0/1 +# N/O - deactivate out0/1 +# s/S - show all statistic +# y/Y - turn on/off relay0 +# z/Z - turn on/off relay1 + +echo "Turn OFF devices" +echo ":Z#" > $COMDEV +cat $COMDEV +sleep 3 +echo "Turn OFF PC" +echo ":Y#" > $COMDEV +cat $COMDEV diff --git a/Daemons/netsocket/HWpoweron b/Daemons/netsocket/HWpoweron new file mode 100755 index 0000000..0f8374a --- /dev/null +++ b/Daemons/netsocket/HWpoweron @@ -0,0 +1,25 @@ +#!/bin/bash + +COMDEV=/dev/ttyUSB0 +stty -F $COMDEV -hupcl -opost -onlcr -isig -iexten -echo -echoe -echok -echoctl -echoke -icanon min 0 time 5 + +# A - turn off triac0 +# B - turn off triac1 +# c/C - check in0/1 +# i/I - show current ampl. (ADU) +# k/K - set/reset PKEY1 +# l/L - set/reset NKEY1 +# m/M - set/reset NKEY2 +# n/o - activate out0/1 +# N/O - deactivate out0/1 +# s/S - show all statistic +# y/Y - turn on/off relay0 +# z/Z - turn on/off relay1 + +echo "Turn ON PC" +echo ":y#" > $COMDEV +cat $COMDEV +sleep 3 +echo "Turn ON devices" +echo ":z#" > $COMDEV +cat $COMDEV diff --git a/Daemons/netsocket/MOUNTpoweronoff b/Daemons/netsocket/MOUNTpoweronoff new file mode 100755 index 0000000..e910e4e --- /dev/null +++ b/Daemons/netsocket/MOUNTpoweronoff @@ -0,0 +1,11 @@ +#!/bin/bash + +COMDEV=/dev/ttyUSB0 +stty -F $COMDEV -hupcl -opost -onlcr -isig -iexten -echo -echoe -echok -echoctl -echoke -icanon min 0 time 5 + +echo "Turn ON/OFF mount" +echo ":o#" > $COMDEV +cat $COMDEV +sleep 1.4 +echo ":O#" > $COMDEV +cat $COMDEV diff --git a/Daemons/netsocket/poweron_readme.koi8-r b/Daemons/netsocket/poweron_readme.koi8-r new file mode 100644 index 0000000..5a9288e --- /dev/null +++ b/Daemons/netsocket/poweron_readme.koi8-r @@ -0,0 +1,15 @@ +ssh на 192.168.70.34 +client_term/client +:y# - включить питание компьютера и второго реле +:z# - включить питание оборудования + +включить монтировку: +:o# на полторы секунды, следом :O# +аналогично отключить. +замыкание опторазвязкой, джек аудио 3.5мм, в центре плюс, кончик - минус, общий не используется. + +Питание выключать через 30 секунд после отключения (и проверить, что монтировка ничего не отвечает). + +:Z# - выключить питание оборудования +:Y# - выключить питание компьютера (после того, как выполнится poweroff) + diff --git a/Daemons/teldaemon/Makefile b/Daemons/teldaemon/Makefile new file mode 100644 index 0000000..efc0459 --- /dev/null +++ b/Daemons/teldaemon/Makefile @@ -0,0 +1,43 @@ +# run `make DEF=...` to add extra defines +PROGRAM := teldaemon +LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -pthread +SRCS := $(wildcard *.c) +DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 +#DEFINES += -DEBUG +# baudrate for USB<->UART converter +DEFINES += -DBAUD_RATE=B9600 +OBJDIR := mk +CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines +OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) +DEPS := $(OBJS:.o=.d) +CC = gcc + +all : $(OBJDIR) $(PROGRAM) + +$(PROGRAM) : $(OBJS) + @echo -e "\t\tLD $(PROGRAM)" + $(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM) + +$(OBJDIR): + mkdir $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + +$(OBJDIR)/%.o: %.c + @echo -e "\t\tCC $<" + $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< + +clean: + @echo -e "\t\tCLEAN" + @rm -f $(OBJS) $(DEPS) + @rmdir $(OBJDIR) 2>/dev/null || true + +xclean: clean + @rm -f $(PROGRAM) + +gentags: + CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null + +.PHONY: gentags clean xclean diff --git a/Daemons/teldaemon/Readme.md b/Daemons/teldaemon/Readme.md new file mode 100644 index 0000000..6b2084f --- /dev/null +++ b/Daemons/teldaemon/Readme.md @@ -0,0 +1,12 @@ +Astrosib telescope control network daemon +================== + +Open a socket at given port (default: 4444), works with http & direct requests. + +**Protocol** + +Send requests over socket (by curl or something else) or http requests (in browser). + +* *open* - open telescope shutters; +* *close* - close shutters; +* *status* - shutters' state (return "open", "closed" or "intermediate"). diff --git a/Daemons/teldaemon/astrosib_readme.koi8-r b/Daemons/teldaemon/astrosib_readme.koi8-r new file mode 100644 index 0000000..9f3a647 --- /dev/null +++ b/Daemons/teldaemon/astrosib_readme.koi8-r @@ -0,0 +1,13 @@ +SHUTTEROPEN?1,1,1,1,1 - открыть створки +SHUTTERCLOSE?1,1,1,1,1 - закрыть +SHUTTERSTATUS? - состояние, ответ: SHUTTERSTATUS?x,x,x,x,x (0 - закрыто, 1 - открыто) + +охлаждение зеркала: +COOLERON?x, x - мощность вентиляторов в процентах +COOLEROFF? - выключить +COOLERT? - температура, ответ COOLERT?x,x,x - температуры зеркала, окружающего воздуха и зеркало минус воздух +COOLERSTATUS? - состояние охлаждения, ответ COOLERPWM?x,x,x - 0/1 - выкл/вкл, 0..100 - мощность, 0/1 - автоохлаждение выкл/вкл +COOLERAUTOON? - вкл. автоохлаждение +COOLERAUTOOFF? + +PING? - ответ OK, если есть diff --git a/Daemons/teldaemon/cmdlnopts.c b/Daemons/teldaemon/cmdlnopts.c new file mode 100644 index 0000000..b8c24d3 --- /dev/null +++ b/Daemons/teldaemon/cmdlnopts.c @@ -0,0 +1,89 @@ +/* geany_encoding=koi8-r + * cmdlnopts.c - the only function that parse cmdln args and returns glob parameters + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include "cmdlnopts.h" +#include "usefull_macros.h" + +/* + * here are global parameters initialisation + */ +int help; +static glob_pars G; + +// default values for Gdefault & help +#define DEFAULT_PORT "4444" + +// DEFAULTS +// default global parameters +glob_pars const Gdefault = { + .device = NULL, + .port = DEFAULT_PORT, + .terminal = 0, + .echo = 0, + .logfile = NULL, + .rest_pars = NULL, + .rest_pars_num = 0 +}; + +/* + * Define command line options by filling structure: + * name has_arg flag val type argptr help +*/ +myoption cmdlnopts[] = { +// common options + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, + {"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), _("serial device name (default: none)")}, + {"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("network port to connect (default: " DEFAULT_PORT ")")}, + {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("save logs to file (default: none)")}, + {"terminal",NO_ARGS, NULL, 't', arg_int, APTR(&G.terminal), _("run as terminal")}, + {"echo", NO_ARGS, NULL, 'e', arg_int, APTR(&G.echo), _("echo users commands back")}, + end_option +}; + +/** + * Parse command line options and return dynamically allocated structure + * to global parameters + * @param argc - copy of argc from main + * @param argv - copy of argv from main + * @return allocated structure with global parameters + */ +glob_pars *parse_args(int argc, char **argv){ + int i; + void *ptr; + ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); + // format of help: "Usage: progname [args]\n" + change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n"); + // parse arguments + parseargs(&argc, &argv, cmdlnopts); + if(help) showhelp(-1, cmdlnopts); + if(argc > 0){ + G.rest_pars_num = argc; + G.rest_pars = calloc(argc, sizeof(char*)); + for (i = 0; i < argc; i++) + G.rest_pars[i] = strdup(argv[i]); + } + return &G; +} + diff --git a/Daemons/teldaemon/cmdlnopts.h b/Daemons/teldaemon/cmdlnopts.h new file mode 100644 index 0000000..712e140 --- /dev/null +++ b/Daemons/teldaemon/cmdlnopts.h @@ -0,0 +1,44 @@ +/* geany_encoding=koi8-r + * cmdlnopts.h - comand line options for parceargs + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __CMDLNOPTS_H__ +#define __CMDLNOPTS_H__ + +#include "parseargs.h" +#include "term.h" + +/* + * here are some typedef's for global data + */ +typedef struct{ + char *device; // serial device name + char *port; // port to connect + char *logfile; // logfile name + int terminal; // run as terminal + int echo; // echo user commands back + int rest_pars_num; // number of rest parameters + char** rest_pars; // the rest parameters: array of char* (path to logfile and thrash) +} glob_pars; + + +glob_pars *parse_args(int argc, char **argv); +#endif // __CMDLNOPTS_H__ diff --git a/Daemons/teldaemon/main.c b/Daemons/teldaemon/main.c new file mode 100644 index 0000000..373f77c --- /dev/null +++ b/Daemons/teldaemon/main.c @@ -0,0 +1,83 @@ +/* geany_encoding=koi8-r + * main.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "usefull_macros.h" +#include +#include // wait +#include //prctl +#include "cmdlnopts.h" +#include "socket.h" + +// telescope @ /dev/ttyS0 + +glob_pars *GP; + +void signals(int signo){ + restore_console(); + restore_tty(); + putlog("exit with status %d", signo); + exit(signo); +} + +int main(int argc, char **argv){ + initial_setup(); + 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 + GP = parse_args(argc, argv); + if(GP->terminal){ + if(!GP->device) ERRX(_("Point serial device name")); + try_connect(GP->device); + run_terminal(); + signals(0); // never reached! + } + if(GP->logfile) + openlogfile(GP->logfile); + #ifndef EBUG + if(daemon(1, 0)){ + ERR("daemon()"); + } + while(1){ // guard for dead processes + pid_t childpid = fork(); + if(childpid){ + putlog("create child with PID %d\n", childpid); + DBG("Created child with PID %d\n", childpid); + wait(NULL); + putlog("child %d died\n", childpid); + WARNX("Child %d died\n", childpid); + sleep(1); + }else{ + prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies + break; // go out to normal functional + } + } + #endif + + if(GP->device) try_connect(GP->device); + if(ping()){ + putlog("Can't write command PING"); + ERRX(_("Can't write command PING")); + } + daemonize(GP->port); + signals(0); // newer reached + return 0; +} diff --git a/Daemons/teldaemon/parseargs.c b/Daemons/teldaemon/parseargs.c new file mode 100644 index 0000000..b235752 --- /dev/null +++ b/Daemons/teldaemon/parseargs.c @@ -0,0 +1,497 @@ +/* geany_encoding=koi8-r + * parseargs.c - parsing command line arguments & print help + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include // printf +#include // getopt_long +#include // calloc, exit, strtoll +#include // assert +#include // strdup, strchr, strlen +#include // strcasecmp +#include // INT_MAX & so on +#include // gettext +#include // isalpha +#include "parseargs.h" +#include "usefull_macros.h" + +char *helpstring = "%s\n"; + +/** + * Change standard help header + * MAY consist ONE "%s" for progname + * @param str (i) - new format + */ +void change_helpstring(char *s){ + int pcount = 0, scount = 0; + char *str = s; + // check `helpstring` and set it to default in case of error + for(; pcount < 2; str += 2){ + if(!(str = strchr(str, '%'))) break; + if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" + else{ + str += 2; // pass next '%' + continue; + } + if(str[1] == 's') scount++; // increment "%s" counter + }; + if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong + /// "Неправильный формат строки помощи" + ERRX(_("Wrong helpstring!")); + } + helpstring = s; +} + +/** + * Carefull atoll/atoi + * @param num (o) - returning value (or NULL if you wish only check number) - allocated by user + * @param str (i) - string with number must not be NULL + * @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 sone without errors, FALSE otherwise + */ +static bool myatoll(void *num, char *str, argtype t){ + long long tmp, *llptr; + int *iptr; + char *endptr; + assert(str); + assert(num); + tmp = strtoll(str, &endptr, 0); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_longlong: + llptr = (long long*) num; + *llptr = tmp; + break; + case arg_int: + default: + if(tmp < INT_MIN || tmp > INT_MAX){ + /// "Целое вне допустимого диапазона" + WARNX(_("Integer out of range")); + return FALSE; + } + iptr = (int*)num; + *iptr = (int)tmp; + } + return TRUE; +} + +// 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){ + double tmp, *dptr; + float *fptr; + char *endptr; + assert(str); + tmp = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_double: + dptr = (double *) num; + *dptr = tmp; + break; + case arg_float: + default: + fptr = (float *) num; + *fptr = (float)tmp; + break; + } + return TRUE; +} + +/** + * 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){ + int oind; + myoption *opts = options; + assert(opts); + for(oind = 0; opts->name && opts->val != opt; oind++, opts++); + if(!opts->name || opts->val != opt) // no such parameter + showhelp(-1, options); + return oind; +} + +/** + * reallocate new value in array of multiple repeating arguments + * @arg paptr - address of pointer to array (**void) + * @arg type - its type (for realloc) + * @return pointer to new (next) value + */ +void *get_aptr(void *paptr, argtype type){ + int i = 1; + void **aptr = *((void***)paptr); + if(aptr){ // there's something in array + void **p = aptr; + while(*p++) ++i; + } + size_t sz = 0; + switch(type){ + default: + case arg_none: + /// "Не могу использовать несколько параметров без аргументов!" + ERRX("Can't use multiple args with arg_none!"); + break; + case arg_int: + sz = sizeof(int); + break; + case arg_longlong: + sz = sizeof(long long); + break; + case arg_double: + sz = sizeof(double); + break; + case arg_float: + sz = sizeof(float); + break; + case arg_string: + sz = 0; + break; + /* case arg_function: + sz = sizeof(argfn *); + break;*/ + } + aptr = realloc(aptr, (i + 1) * sizeof(void*)); + *((void***)paptr) = aptr; + aptr[i] = NULL; + if(sz){ + aptr[i - 1] = malloc(sz); + }else + aptr[i - 1] = &aptr[i - 1]; + return aptr[i - 1]; +} + + +/** + * 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` + * @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt` + * BE CAREFUL! if you wanna use full argc & argv, save their original values before + * calling this function + * @param options (i) - array of `myoption` for arguments parcing + * + * @exit: in case of error this function show help & make `exit(-1)` + */ +void parseargs(int *argc, char ***argv, myoption *options){ + char *short_options, *soptr; + struct option *long_options, *loptr; + size_t optsize, i; + myoption *opts = options; + // check whether there is at least one options + assert(opts); + assert(opts[0].name); + // first we count how much values are in opts + for(optsize = 0; opts->name; optsize++, opts++); + // now we can allocate memory + 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 + 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 + } + if(opts->type != arg_none) // if there is a flag without arg, check its pointer + assert(opts->argptr); + // fill long_options + // don't do memcmp: what if there would be different alignment? + loptr->name = opts->name; + loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; + loptr->flag = opts->flag; + 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++ = ':'; + if(loptr->has_arg == 2) // add '::' if option has optional argument + *soptr++ = ':'; + } + } + // sort all lists & check for repeating +#ifdef EBUG + int cmpstringp(const void *p1, const void *p2){ + return strcmp(* (char * const *) p1, * (char * const *) p2); + } + int cmpcharp(const void *p1, const void *p2){ + return (int)(*(char * const)p1 - *(char *const)p2); + } + qsort(longlist, optsize, sizeof(char *), cmpstringp); + qsort(shortlist,optsize, sizeof(char), cmpcharp); + char *prevl = longlist[0], prevshrt = shortlist[0]; + for(i = 1; i < optsize; ++i){ + if(longlist[i]){ + if(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); + } + prevshrt = shortlist[i]; + } + } +#endif + // 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); + 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; + else optind = get_optind(opt, options); + } + opts = &options[optind]; + // if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag + // now check option + if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) + if(!optarg) 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; + // even if there is no argument, but argptr != NULL, think that optarg = "1" + if(!optarg) optarg = "1"; + switch(opts->type){ + default: + case arg_none: + if(opts->argptr) *((int*)aptr) += 1; // increment value + break; + case arg_int: + result = myatoll(aptr, optarg, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, optarg, arg_longlong); + break; + case arg_double: + result = myatod(aptr, optarg, arg_double); + break; + case arg_float: + result = myatod(aptr, optarg, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(optarg)); + break; + case arg_function: + result = ((argfn)aptr)(optarg); + break; + } + if(!result){ + showhelp(optind, options); + } + } + *argc -= optind; + *argv += optind; +} + +/** + * compare function for qsort + * 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 char *l1 = o1->name, *l2 = o2->name; + int s1 = o1->val, s2 = o2->val; + int *f1 = o1->flag, *f2 = o2->flag; + // check if both options has short arg + if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg + return (s1 - s2); + }else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long + return strcmp(l1, l2); + }else{ // only one have short arg -- return it + if(f2 || !s2) return -1; // a1 have short - it is 'lesser' + else return 1; + } +} + +/** + * 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` + * + * @exit: run `exit(-1)` !!! + */ +void showhelp(int oindex, myoption *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; + assert(opts); + assert(opts[0].name); // check whether there is at least one options + if(oindex > -1){ // print only one message + opts = &options[oindex]; + printf(" "); + if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); + printf("--%s", opts->name); + if(opts->has_arg == 1) printf("=arg"); + else if(opts->has_arg == 2) printf("[=arg]"); + printf(" %s\n", _(opts->help)); + exit(-1); + } + // header, by default is just "progname\n" + printf("\n"); + if(strstr(helpstring, "%s")) // print progname + printf(helpstring, __progname); + else // only text + printf("%s", helpstring); + printf("\n"); + // count max_opt_len + do{ + int L = strlen(opts->name); + if(max_opt_len < L) max_opt_len = L; + }while((++opts)->name); + max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols + opts = options; + // count amount of options + int N; for(N = 0; opts->name; ++N, ++opts); + if(N == 0) exit(-2); + // Now print all help (sorted) + opts = options; + qsort(opts, N, sizeof(myoption), argsort); + do{ + int p = sprintf(buf, " "); // a little indent + if(!opts->flag && opts->val) // .val is short argument + p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); + p += snprintf(buf+p, bufsz-p, "--%s", opts->name); + if(opts->has_arg == 1) // required argument + p += snprintf(buf+p, bufsz-p, "=arg"); + else if(opts->has_arg == 2) // optional argument + p += snprintf(buf+p, bufsz-p, "[=arg]"); + assert(p < max_opt_len); // there would be magic if p >= max_opt_len + printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after + ++opts; + }while(--N); + printf("\n\n"); + exit(-1); +} + +/** + * 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 idx = 0; + if(!par) return -1; + while(so[idx].name){ + if(strcasecmp(par, so[idx].name) == 0) return idx; + ++idx; + } + return -1; // badarg + } + bool opt_setarg(mysuboption *so, int idx, char *val){ + mysuboption *soptr = &so[idx]; + bool result = FALSE; + void *aptr = soptr->argptr; + switch(soptr->type){ + default: + case arg_none: + if(soptr->argptr) *((int*)aptr) += 1; // increment value + result = TRUE; + break; + case arg_int: + result = myatoll(aptr, val, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, val, arg_longlong); + break; + case arg_double: + result = myatod(aptr, val, arg_double); + break; + case arg_float: + result = myatod(aptr, val, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(val)); + break; + case arg_function: + result = ((argfn)aptr)(val); + break; + } + return result; + } + char *tok; + bool ret = FALSE; + char *tmpbuf; + tok = strtok_r(str, ":,", &tmpbuf); + do{ + char *val = strchr(tok, '='); + int noarg = 0; + if(val == NULL){ // no args + val = "1"; + noarg = 1; + }else{ + *val++ = '\0'; + if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = + val = "1"; noarg = 1; + } + } + int idx = findsubopt(tok, opt); + if(idx < 0){ + /// "Неправильный параметр: %s" + WARNX(_("Wrong parameter: %s"), tok); + goto returning; + } + if(noarg && opt[idx].has_arg == NEED_ARG){ + /// "%s: необходим аргумент!" + WARNX(_("%s: argument needed!"), tok); + goto returning; + } + if(!opt_setarg(opt, idx, val)){ + /// "Неправильный аргумент \"%s\" параметра \"%s\"" + WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); + goto returning; + } + }while((tok = strtok_r(NULL, ":,", &tmpbuf))); + ret = TRUE; +returning: + return ret; +} diff --git a/Daemons/teldaemon/parseargs.h b/Daemons/teldaemon/parseargs.h new file mode 100644 index 0000000..537fc5b --- /dev/null +++ b/Daemons/teldaemon/parseargs.h @@ -0,0 +1,124 @@ +/* geany_encoding=koi8-r + * parseargs.h - headers for parsing command line arguments + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __PARSEARGS_H__ +#define __PARSEARGS_H__ + +#include // bool +#include + +#ifndef TRUE + #define TRUE true +#endif + +#ifndef FALSE + #define FALSE false +#endif + +// macro for argptr +#define APTR(x) ((void*)x) + +// if argptr is a function: +typedef bool(*argfn)(void *arg); + +/* + * type of getopt's argument + * WARNING! + * My function change value of flags by pointer, so if you want to use another type + * make a latter conversion, example: + * char charg; + * int iarg; + * myoption opts[] = { + * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; + * ..(parse args).. + * charg = (char) iarg; + */ +typedef enum { + arg_none = 0, // no arg + arg_int, // integer + arg_longlong, // long long + arg_double, // double + arg_float, // float + arg_string, // char * + arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` +} argtype; + +/* + * Structure for getopt_long & help + * BE CAREFUL: .argptr is pointer to data or pointer to function, + * conversion depends on .type + * + * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext, + * but you can redefine it before `#include "parseargs.h"` + * + * if arg is string, then value wil be strdup'ed like that: + * char *str; + * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; + * *(opts[1].str) = strdup(optarg); + * in other cases argptr should be address of some variable (or pointer to allocated memory) + * + * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr + * + * !!!LAST VALUE OF ARRAY SHOULD BE `end_option` or ZEROS !!! + * + */ +typedef enum{ + NO_ARGS = 0, // first three are the same as in getopt_long + NEED_ARG = 1, + OPT_ARG = 2, + MULT_PAR +} hasarg; + +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) + 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)` + const char *help; // help string which would be shown in function `showhelp` or NULL +} myoption; + +/* + * Suboptions structure, almost the same like myoption + * used in parse_subopts() + */ +typedef struct{ + const char *name; + hasarg has_arg; + argtype type; + void *argptr; +} mysuboption; + +// last string of array (all zeros) +#define end_option {0,0,0,0,0,0,0} +#define end_suboption {0,0,0,0} + +extern const char *__progname; + +void showhelp(int oindex, myoption *options); +void parseargs(int *argc, char ***argv, myoption *options); +void change_helpstring(char *s); +bool get_suboption(char *str, mysuboption *opt); + +#endif // __PARSEARGS_H__ diff --git a/Daemons/teldaemon/socket.c b/Daemons/teldaemon/socket.c new file mode 100644 index 0000000..db13ca7 --- /dev/null +++ b/Daemons/teldaemon/socket.c @@ -0,0 +1,326 @@ +/* + * geany_encoding=koi8-r + * socket.c - socket IO + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "usefull_macros.h" +#include "socket.h" +#include "term.h" +#include // addrinfo +#include // inet_ntop +#include +#include // INT_xxx +#include // pthread_kill +#include // daemon +#include // syscall + +#include "cmdlnopts.h" // glob_pars + +#define BUFLEN (10240) +// Max amount of connections +#define BACKLOG (30) + +extern glob_pars *GP; + +static char *status; // global variable with device status + +typedef enum{ + CMD_OPEN, + CMD_CLOSE, + CMD_NONE +} commands; + +static commands cmd = CMD_NONE; + +/* + * Define global data buffers here + */ + +/**************** COMMON FUNCTIONS ****************/ +/** + * wait for answer from socket + * @param sock - socket fd + * @return 0 in case of error or timeout, 1 in case of socket ready + */ +static int waittoread(int sock){ + fd_set fds; + struct timeval timeout; + int rc; + timeout.tv_sec = 1; // wait not more than 1 second + timeout.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(sock, &fds); + do{ + rc = select(sock+1, &fds, NULL, NULL, &timeout); + if(rc < 0){ + if(errno != EINTR){ + WARN("select()"); + return 0; + } + continue; + } + break; + }while(1); + if(FD_ISSET(sock, &fds)) return 1; + return 0; +} + +/**************** SERVER FUNCTIONS ****************/ +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +/** + * Send data over socket + * @param sock - socket fd + * @param webquery - ==1 if this is web query + * @param textbuf - zero-trailing buffer with data to send + * @return 1 if all OK + */ +static int send_data(int sock, int webquery, const char *textbuf){ + ssize_t L, Len; + char tbuf[BUFLEN]; + Len = strlen(textbuf); + // OK buffer ready, prepare to send it + if(webquery){ + L = snprintf((char*)tbuf, BUFLEN, + "HTTP/2.0 200 OK\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Methods: GET, POST\r\n" + "Access-Control-Allow-Credentials: true\r\n" + "Content-type: text/plain\r\nContent-Length: %zd\r\n\r\n", Len); + if(L < 0){ + WARN("sprintf()"); + return 0; + } + if(L != write(sock, tbuf, L)){ + WARN("write"); + return 0; + } + } + // send data + //DBG("send %zd bytes\nBUF: %s", Len, buf); + if(Len != write(sock, textbuf, Len)){ + WARN("write()"); + return 0; + } + return 1; +} + +// search a first word after needle without spaces +static char* stringscan(char *str, char *needle){ + char *a, *e; + char *end = str + strlen(str); + a = strstr(str, needle); + if(!a) return NULL; + a += strlen(needle); + while (a < end && (*a == ' ' || *a == '\r' || *a == '\t' || *a == '\r')) a++; + if(a >= end) return NULL; + e = strchr(a, ' '); + if(e) *e = 0; + return a; +} + +static void *handle_socket(void *asock){ + FNAME(); + int sock = *((int*)asock); + int webquery = 0; // whether query is web or regular + char buff[BUFLEN]; + ssize_t rd; + double t0 = dtime(); + while(dtime() - t0 < SOCKET_TIMEOUT){ + if(!waittoread(sock)){ // no data incoming + continue; + } + if(!(rd = read(sock, buff, BUFLEN-1))){ + break; + } + DBG("Got %zd bytes", rd); + if(rd < 0){ // error + DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); + break; + } + // add trailing zero to be on the safe side + buff[rd] = 0; + // now we should check what do user want + char *got, *found = buff; + if((got = stringscan(buff, "GET")) || (got = stringscan(buff, "POST"))){ // web query + webquery = 1; + char *slash = strchr(got, '/'); + if(slash) found = slash + 1; + // web query have format GET /some.resource + } + // here we can process user data + DBG("user send: %s\nfound=%s", buff, found); + if(GP->echo){ + if(!send_data(sock, webquery, found)){ + putlog("can't send data, some error occured"); + } + } + pthread_mutex_lock(&mutex); + const char *proto = "Commands: open, close, status"; + if(strstr(found, "open")){ + DBG("User asks 2 open"); + putlog("User asks to open"); + cmd = CMD_OPEN; + send_data(sock, webquery, "OK\n"); + }else if(strstr(found, "close")){ + DBG("User asks 2 close"); + putlog("User asks to close"); + cmd = CMD_CLOSE; + send_data(sock, webquery, "OK\n"); + }else if(strstr(found, "status")){ + DBG("User asks 4 status"); + send_data(sock, webquery, status); + }else send_data(sock, webquery, proto); + pthread_mutex_unlock(&mutex); + break; + } + close(sock); + pthread_exit(NULL); + return NULL; +} + +// main socket server +static void *server(void *asock){ + putlog("server(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); + int sock = *((int*)asock); + if(listen(sock, BACKLOG) == -1){ + putlog("listen() failed"); + WARN("listen"); + return NULL; + } + while(1){ + socklen_t size = sizeof(struct sockaddr_in); + struct sockaddr_in their_addr; + int newsock; + if(!waittoread(sock)) continue; + newsock = accept(sock, (struct sockaddr*)&their_addr, &size); + if(newsock <= 0){ + putlog("accept() failed"); + WARN("accept()"); + continue; + } + struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&their_addr; + struct in_addr ipAddr = pV4Addr->sin_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); + putlog("Got connection from %s", str); + DBG("Got connection from %s\n", str); + pthread_t handler_thread; + if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){ + putlog("server(): pthread_create() failed"); + WARN("pthread_create()"); + }else{ + DBG("Thread created, detouch"); + pthread_detach(handler_thread); // don't care about thread state + } + } + putlog("server(): UNREACHABLE CODE REACHED!"); +} + +// data gathering & socket management +static void daemon_(int sock){ + if(sock < 0) return; + pthread_t sock_thread; + if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ + putlog("daemon_(): pthread_create() failed"); + ERR("pthread_create()"); + } + double tgot = 0.; + do{ + if(pthread_kill(sock_thread, 0) == ESRCH){ // died + WARNX("Sockets thread died"); + putlog("Sockets thread died"); + pthread_join(sock_thread, NULL); + if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){ + putlog("daemon_(): new pthread_create() failed"); + ERR("pthread_create()"); + } + } + usleep(1000); // sleep a little or thread's won't be able to lock mutex + if(dtime() - tgot < T_INTERVAL) continue; + tgot = dtime(); + // copy temporary buffers to main + pthread_mutex_lock(&mutex); + char *pollans = poll_device(); + if(pollans) status = pollans; + if(cmd != CMD_NONE){ + switch (cmd){ + case CMD_OPEN: + DBG("received command: open"); + if(write_cmd("SHUTTEROPEN?1,1,1,1,1") == 0) cmd = CMD_NONE; + break; + case CMD_CLOSE: + DBG("received command: close"); + if(write_cmd("SHUTTERCLOSE?1,1,1,1,1") == 0) cmd = CMD_NONE; + break; + default: + DBG("WTF?"); + } + } + pthread_mutex_unlock(&mutex); + }while(1); + putlog("daemon_(): UNREACHABLE CODE REACHED!"); +} + +/** + * Run daemon service + */ +void daemonize(char *port){ + FNAME(); + int sock = -1; + struct addrinfo hints, *res, *p; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if(getaddrinfo(NULL, port, &hints, &res) != 0){ + ERR("getaddrinfo"); + } + struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN); + // loop through all the results and bind to the first we can + for(p = res; p != NULL; p = p->ai_next){ + if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){ + WARN("socket"); + continue; + } + int reuseaddr = 1; + if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ + ERR("setsockopt"); + } + if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){ + close(sock); + WARN("bind"); + continue; + } + break; // if we get here, we have a successfull connection + } + if(p == NULL){ + putlog("failed to bind socket, exit"); + // looped off the end of the list with no successful bind + ERRX("failed to bind socket"); + } + freeaddrinfo(res); + daemon_(sock); + close(sock); + putlog("socket closed, exit"); + signals(0); +} + diff --git a/Daemons/teldaemon/socket.h b/Daemons/teldaemon/socket.h new file mode 100644 index 0000000..5d0c407 --- /dev/null +++ b/Daemons/teldaemon/socket.h @@ -0,0 +1,34 @@ +/* + * geany_encoding=koi8-r + * socket.h + * + * Copyright 2017 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __SOCKET_H__ +#define __SOCKET_H__ + +// timeout for socket closing +#define SOCKET_TIMEOUT (5.0) +// time interval for data polling (seconds) +#define T_INTERVAL (2.) + +void daemonize(char *port); + +#endif // __SOCKET_H__ diff --git a/Daemons/teldaemon/teldaemon b/Daemons/teldaemon/teldaemon new file mode 100755 index 0000000000000000000000000000000000000000..8bc4430b729dd3a0d5c18563f5ce149c666330a6 GIT binary patch literal 38288 zcmeHwdwf*Ywf~tUgCQiDhy+svJ?fyrhL`|BKq47P-~JQ9_w6v8r8PATF*=?#e!fFfm@G914b zDCaA~fZG|3rx$U6RDPTkq9sfg^hCfU{7p;Xgm^es@JT2&BuM319iOk}DH1A*$_SK? zbluRvP(YQPNLWURI6Bifl=(`b#K^S1zxwTQhaa<@MDQ z>+2f*trJ_PO`SM(O0KslcM_{N$tT`7A5zq0(j>dk)dA z#$P%9vd3*4JL3H>M{X}$_h8Mk%8cp9f@3G`{c_~f4}Ccj$wMAXA#kX~wNPLv`rQ`% z&q4Z7{BKy$pR$mDrv?AnpsV1O6N(RIpBxK0 z-?N~iK5`MCxEAqzXSSkSMske_TJ{|gI# z)xyr3Eacp2L4Ux4KGuTnu%HjK&~vqg9eOPIzqOEmsRjKK3wpOjxf4NG@fUwQVxi9# zFb>s!Z?T|vTF4n;L3crpiof_HY*DX!EacGiU?@Fb2meL!!hzRW$p6BE{%Z^QB^LVV z7IedcPE)|4^uGZ7XDeeA!>h7d$ob7WK~MH^x}1m1gdF1Ui{pPp&i z2>z3TU&>!9_?0+*1@n<+Uu}!0vYI9#c}hiT`NE27Pm5=5o!94SDPK6JzNyhuUb&{; zqg2daSFuDS%&D*RdOcpwKO{HFRD|pbucy97SzlS_i&8wTKq@LcEiH{r74=P3mA<;B z#%StIb@la8q`~j=v=YxvN@Z1*r+H9F6$3%=5L>Lt1l7m5*hstgc4oYMMwC{wuyJ)DRh3lr_9wHKxi}`RY(F6y4;9bx1*_ zrmDWl3!2AAMuRn!23}A_MV0U7W>3W$Y9lgJWy@O1indkiny7TxtkEPKER-Ep0YIk4 zwTjlp1jAZ1 zlVGS&=DAB} P{J1MsydOkUNmOn_G5+zQ~oq{-!fcbj@=J`p0)H4&J|B@J;<90zE z7L!W(2KmvQ1xC`$bUNpy&>5FYyqpWeFXNVZl9aO;9xuVB&_7(y;!nk&e@xwQy4orr z0XS^9n*0)w(&;#-t`1j#XDKeE6Yb|exeu2o!;}RAAH~w`$~6M_eUIcNDys#~EkoYisk142%19Q~l+Z;qpXCg`1U^!J3E`{U@J3;y0X`r4(eS(L6OZdbY% zmTgQaFPiA*5{<_L=B~Cc0sw&oR*lO!Rpsx*XSO4Ti4M zM5k+bc?^j95`Bpz0?Kin=)yES)u%E@bkT$im-7swmoWaE)zY=M1Rpl|DK87Yod=a(GQsD=b7kzCc0dkq-4WH zA7|npFwxI9(NCJ_7ntbE4^)PckMJ{wD#<4LMV!QbGfec0P4p}i-D#q$Ci-|2J=;XT z#6-_C(X&nTX(svv6TQepzsy9}O!V)Y=w&8)j)}h9M5k*;d8{_kb0rb5)s6TQepA288fCi+PeeYT0Nw5SXt z|1UPtlTGvz6FtL3pKGFLndq8{uA1njCVIAsKHo&oGtn2A=+jJew~1b4qAxVjH4}Z2 znI1TjtOe~0uTd4Pqsx~N>D2;zllMe9A_Z%Z6d7NQU&jSSI3v84(!+fb9OJJioQAk? zFTp)6f-eWB6r+Q*(ry8GaGr zG(`!oX80JwY3K@Nu ze@HkD9buK>w-8Q4MmU4vErioh5mp#}BjGeega=Mh{nrq#65hw~>j}S*@Lq;5A)JPY za2Lbp6HY@zcnia46HY@ycr(Li5KcouxRc?N2&W+++{Wi zx2*jM&m+8#;qMSmAw1m6@co2S=ni)={AI!?6TXGvy9u8{_-2N0BfNm{PKG~4IEChL z8^fO<{0hRG8U7IA6pF*E8U9PcDFlbh82(ejDfEVm7=91o6mr9P4F4hF6l%jN!*3y+ zrsUxahPMz-Avdfr{6@kl)P@JXVeLIpVFCm;lYPgHx^9i3r_!frG zCY(ZRcr(Li5KbXA+{y4sgi|ODw=w+Xt5v0@6F57TEzR%JztQwBGz2c=4*0zmDmWM2 zYbSM4V-=cg2L+>@^kXanigdbNx06DWQOF60i9j*Q$cbhcMd&z6*Z-~`G>*figJoHo zZZBP_DjoZM7iht0T1UjuPD_JEF(O2Mm+=CDh;bj}X~EVEr2Fi~N%Wrl6HEgwG%*8h zZTuW^5ng{_j76P-(7A8`E}`3>U!g)wB=acXP6}ei0*G>4py=J2{uv6GiJpf7{OF3v z^gd;JALQ{M1OFTF9(yw~(?Kbb%!f!6t3CC1V*!3Ty7WE%|6s)Yt{u!!)o5G9{RS}e zdO`1IL_x@Y9Kj5_=0pBQ$Oq*)R0!A|th5AC8kIGb%3^BYi%gI=j>&6HHj)sbq4(`X z4i$bniS&H&dafts{1)dt=k;Kz$#q=N&gzhVv{Zln22DSt1wI-mD|d(N@1QSgp)@Z8 zh2O%Ek<9xRtIFq&3*bc%{*$GuvP=uvI{`KQV{O7oEpRe@T_)7I0em#94PO=Mt6}`B z_RuIcSRV3U&GQ$O%KWFbU8fT@eL&k~%+hS#+Uuu%Sr9f|2utO{xW4i7+L$=Sf2kHI zbRYvX(?9m5YQe%5_^~k&>KhuWu&Udhjq+?z2epXN=Poyt4$M;gBf>X;lk1K0|FDQx zCQKqDy{p*x<|^{eYaabyzA49$J^TA zS;f1x(6R)5m*yz`RN18k{+4J=Cs*j`()2yPE8O}g#)Pkc+xBSF|F&*Mr{mc~eRtr{ zH*H@J_gy?w^l)WG zmwpOrYx-Z7>R*)VZ)$fP$v`}>)`CgnDXwdJyE7RlaJ&ak!g-I9X0zc51BlwC`mW~{ zmbi_4di8QS!H{uP@34lF^WFNt~j9wxze zzOex)>yt|{4Cwap%T?AVuOql$3vOiERBMw{nRS*V64^d2O+-;jq~ks?YD>@t`~^c71(Pt?nMFmr={?OuP@m3>6nl^ zQwe-9Yr^ZLZ+z??UcWaZ|E2u>3*qwm`^B(k4cWcx=J`g$2{KLKWRmZF-JS|<(O(Ks z1?s}nStYdKGfpZO_L;)$jvU?hX{@_<5J(*{=S*#%mBi==;Ry zx|VrJ`7*flH#@gM3<7IY#^7%IgC@IF^`%C0g2Haj znIbsv<$uEen3<=OX_7@M7c&Im$^f;{;cVz5%kNSr;9q~4I6Nxh02|I zCWk0?wo>T&3q`Jw+o|S9(DA0wqz!Ny)fX_2)mwwnsG{#6RYRv!N!DuC^H`tLg3Vc4 zpgYM}{150DTnUDbcOC6(G2x@mo*i788uTUyZ%r~bK@viOzR%H~3t_IUNhk;5V;hyr z=8<|2ip^%l{sGch{5X!(;L;2&=*>c#eSKVzpJD3U=2VSKNx`Ffy>qN%!@bDMLJS3) zY*=gzoPqlL2X18k+W@c1Eaa_meD*HpiEMWr_A z#-c}d{t3g)luC58{|v;P2C8WMf?TW1NJyuSCHvAdkVAcGeK(RmNrM3WAn$fYDd%rN z^N{bIg(>fA^Hn8ie^EnEIGNzPl={ijkRLc{^N)dR{Q*7Cn1pNgjxK*nkNpAgk-=zI zF!LC^paNbX^`u#BkNr<&Di{-T_sGMR>jg76n`O*x;0wnxEhw4-IoXO=@Ci;yU! z7sf~W*GNYJ`_BQ07_X2S;8d-MY)NcDb96ia%`vEv+nNJhnbhV>rp-}I_eh%yp^X+? zkxfq5(TNEk%6Nj8(TFmDZDm-G{W+Q-;=ueLXJY=3^27g0)5L%LT~zj4TpjE7O+x(c zD62}W-ykL$cS94%UC&ENMk&VAGWTSbyG-P6kLEsv_6u)7L9j$O@*8)_91pV`=ZhRm z0K+*jo3UCltY-|TFdwD*=0`>Tm_#0eLN9CPob$s;sz!A)#$Ne6T0;~9jw_Sqrh^zAA#xZZy}A(NF-eYdvO8CrnWAc=odqb&@D`S12Wr}fx> zj|9dS8fQRs|HFJ>o}uR`9RbV_bjK9HOaxkpDlBf7w#BMh?_;hsN)M zVWC+TdQGfmAW)kx#85`z`eWl=n6m#|RHmI(4;s9LCJLNXaLGA!2em4-i68I)OZ4hM6RF7T)vm@crkD?#pes0ywjf&wEq$sb#&c1*RkUptDV;>lM>?=T{BkY4GitDIQ!N(UPQc^@msS{Cn zVB%Ep*}{v#q*Y~J1_VR$o02Ou+ve&n&Q#J6yVKDQx;>dV?gtU>4jEw>RI4gDhBOr4 zUxKE36xHpqzXu8(A|SQVIT_jB4%wypS3B?=fbu;3z|`3Q?1F^N^J9!ot-z-B#->jx zETW-XOM;_mh>O443+r&ggE3co*YK;oV|2Cmexf$veIps#VM$=0?=p6MKvy`tq2(2h z;je_hkVY$3?csJq`Jr*W7s0eooF%&>&DT-?Uoe8~k{^PHb;*a3bebkUX!gHCWtw%p zMy3M(QvW^1e$=I=lh$)6Iv7h$VvCtwck#@)`t$z-hP{Rge}T`zv->Wl*$Mz!codRIsp&$g_i_0=9P~bw=${!E3VM#Vl^$F2RHvYQ$GtKK z&8*w^5|H6x&)}2?`MWRV`9C-Ps351ihDBDlGkurhmX@Vz}~!`k)lkWfNw7n3yHy2}*|X^e2?L;IxV=?UCJk z5lIY|JF^f8N3p?NKfq!k)eo_7kztO78^~bf8tbaJR{zd;+^*_w(kA*=~{Ym0K zt3Ql3=(|*ZjMe%nIKTlI=)cDSGOvRH&~nS6IroG6(JJ~L@`M3s0Z-UDi!4DG^~@7Y zF2H>v))OB8m@JW*z{T1i))sY$LWs5#=Q3q$$JEM;T(@tE4K_wr$OQQtG-C3e4qDz>o&$~tk7T=1U8UE{Fylu#9 zGM;hIN0CTqxlIeEZKjk^;YZ_8`fypg@iKL!c%PX96R|!+t9;}q#!`sE3L6$-bj*=H z`(pwG7@J@{7qr5;(*JAYGw=)=lg*!KzEP@w%Ps@|`+O|z3)B%l@j32$aTf{}K2!*s z9)-feiIa;}bQ-cPU07RN6)TZs)mvfJYUGAhu@=PS8B;!FJ{v4tKnbC=c3xmW7KnlA zF6yDd!pj&#=F3>xvF%}*k>)|#8Gcz1^-Ef2Kai!0&V zFfbT5LzU=!3TZhsP3e`if+(Egf>=8yjL9(xzg=%8^C<=ZF&)XzVG%f4!e?6E)SQi*{^ z_GE7Fpna2z^81Ey9J;V^iSk8^^GUm4W)E0U^cDaTrsUIrTXaav5&w2{H`MB~ns*xQP`V-c*`nM1E*-iw$#~_O@ zYhr0M!{kTpY~hz?reD&6Gc6&P>V3=`w1C^0VWZV*Wag{Y8J8kJq;V%1p5Ju>J;~-* zwcx#S`IryT{`27VRHU#s<^j`DJts2u?>Byp+6-z(^PAwf@zbzO@lC{cF--9%j1>7N z^n>V9hro)-O+P@7{S>?ceIv5MG*x5qh>v$@&HhY=8@C=Ldtt@f(V@YLxL=ll*huri ztDyod7VUwrL7eYR%(XUTah}w2826yjh{9-<;XbN#D03ER)3w9S6R+lp8!ki^c*{kU zxc~VVFsa!wjB&tIj#5Yt+S8F%qi24=0(9m9fEqpREy8sBegMaF_TvEE_E+#bs@uK? zz>eAB4#4~_ocxxZ81JJpaEkfl&lufcFXLD53x80v$RDOL6(gDTfWg9droz6#<6~%!3l+zvS0S^M))Bf(C+roA`&hhU zH(06)pD0k3KcYDmV+vKZ@Rz_B>L;n1@vg6bE$+Oeo*U?~v3oBxxqahM{!7~Ma@>H~ zZwx>NB2AuFRd_W78GU4e!nrs#XQsP0+8ZBg9V>AorGu7f-MDXa#$A{(q8phOtf>9+ zyZYZSu7zM3KlNjn@g2t!ZLsjYDJb;a_Yes7j;|O7k(dEBbnon1)(zu2rXfZKFG`qZ$5G*deRI;o)4jurjL6Q zILP||R*=8;*nc`xg@KVTRQOybbDZ%zK@$2Kue>XCd;*Cpbo*MQLCNvIVm$0N8lS)Q zW$^jiGtOx^)AW0tMGS6qYJhIsbSz_VqjNc+ugEc>-MJcPjtLu`%?#e_Y-8{NXD5S? zI5#u+q;m^{&p5jn-0tiJjPbW@5c0clPc%^Y)eO|f(M}cAc?6mriRG~ zFvx;%ON@C?1jN)lLCi94d57c|R3Yn5nuF?lj2>QO8A!&jNIL{+s)6Y$%F*#6Nw{lo zAL!&`Vx0gp4O;D1jW?Ls!c?yI!cj45ucO8e7Jf#N{g+^L2h-lgIhIBW!1%lZnasi1 z8W(0c2vFV46&!HAZ^=wG_4M}M~h2%it131Uh;@;D6;&;Qv=p52d9!7rV z%kN-yRJRvFFY;v{VE;Cw1WNGvDPOI`;=bKB5gqR~XDS@;@3d~KPjSLCM^J@=_9Hm} zy4}vP!yJpCbfooh>?@AF!?EKWdy`{Fff;yh15L_G$n@otyu-$OXf4e5k=*f;zeTG; zYDeUbB|E4Q^}^p#w(FoP=I5y>{!!xFf5&93k>nqx_0qGj%K8%!wIKY-*6+ftUoAK@ z8!H>hh7I|Or&m+P#5@0jU=4?`&jd4TJ{b=}1>rmymS-hlPT2}04i344>$xWXhLfSM zcbssv_mER`z@1My+8>~E{kThi3l&31(GNmH;}zD9qnz6GH+++@4(yxQHbe1ey8@>Y ze6zP9OWX4(5Dy^i)~3I_zDO@o_^m6cA8tA(!w>nr_+q`!zYaCY;!%#CKZs`Nf0N=J z8t)1;9^Hc|#XNzIName5>;F&8(sRizLj^W!UaTAfY%2waao+)G5K43K zG)i8NWMd?LP+subjNrVi;^15?a4*6GK>Ph;H8kD12;}FK;3vI!LYHaMK@8`Cd@eCf z0>f4sK7857W&Z&=MUwqtEr?rlv%>4BEasnE$v7r?Vs+g-Et9R`^TYbM)`In6d;Kk= z?``TrsZO-j^jCZrk@3g1O;`L`fm4aTsdOE{lsV?O{>9@i$Jwb)x(p;^iR_xraJlS?v1D~Iuio<}I<_b)M3#5~a* zynG=ZGHFjlyOjoR$4{sv+0p(v%4Q*}|14Gy{bk%vNDj@nX@S<0ihn?>dMR{$f)>j8 z6KSbcz3UEnPHMY8Obnd1ug5*L%nuRs^b=ZD(o>qPH_|89<50ohAf?A1EKn&YtKd$Y z^9qimHAek?x@9&S#x2!{Vd9ZZd~RExrn4y-?;EZga8DlV89OPGh%63d!QC}P4^u|t z7ck6xJ?Uba&YAP__S%VXjz}xwA6@(%!#xi8>`jq8&Grqy*z{B51#Zp2Kw3>1gXe(n z4aUbA%E1tvlZ-o-j&>h7a39mr{u0X9f=h81wqPrG87GF8Z14vD95K28*$`+x5IzgM1IF9WO2O!trd50 z1V-7%aR4jh+8b(^b3T1~cz_`y? zi7%AdgLGu#HLW^f{4ZWX=B6gLe~)8p6>P~UWhW#?j7K5d$VdBXRSOX3l@rC9ElJZ~ zcC`PH<{hDeB_>V&ik1%F$mt~}`Yxj1&gf}WB(iNtB~Tav*wz4>8RJki8vAaZT*s3? zreyjciE$d{K=N9iJf9~Yr{w!6`5;R!Y{DH7V^1%4>V9(NP{9DEc9;}OYZZ_#i`kqB z&;NIv@Xe&Y=esz+>&iQ@oOjHh+CQH4_vyD}`Oeb_w5ySZ{O_+*U zfWgXH+7YHp!E?BahYIDAN^NK|!wr=NBLd>j;PYL9BhyU508d%a9Adwty#f(N3y#q+ zZ=lCE@`0A>r|3dX?=8uXP=GDMRo0i(RThTULoIZb&lZGkTW8~Iann#{Y3R;`9q>I= z8ePE{57NSp6Qz0&q5z{BZvAUFjc@rU`aOdh76*&QV)%8m-$|3RKr1dZ+Lz%p@Ku7Q zk6Bk1)X@H|89lR;VQ|dRH2szgeSVhDP8U9Fa7zyA>{dy&(&;CBm0B>1RpKS|y`Ywi z!TrHt>sUNR-0?QW5PeLrHOn2;AR@T~p?H3V4tqbp5PZ*cytEL*hik(ON5@Dguuy-w ze>3d2A;r}_+cu*#usea)x9CoY6Ss<{k>P2QFXl<^AkNwN?bg344Nh^og16Je-wCZ1 zqvp?SDZ|lDpL+J^XQ@KsMK`E{3)JV;)?Y0`As`kPm17Rh^xi=m&OZUiFrBrUI!oDg32N=fHyX%fdsKsL1wrV+nekc0V;oDIN}wwus&xID9H_ z8pGU6$ROG$+#uy6Cu%Vod0l#UIEQ4iejT*m0=cdUC76rYo2ZCgeTk(uTs6S1+0mt7 zN5=p)Qef{i(@X%}J#9Fsp@J6?Y0%wuOaivO3r1trpP(e`H60i5NcSPq!1*BOyo)$L zBF@Rg8A{vBlkeooYbf~xN*=|N|D7kV=E*sf+(*e@yo$PhmB6}!qvJEGUia(->J^FM z^<=0}+KoKxc%Jn)0NY-rtlN+k$qRV$FrIunCBH(+ze2Jx6+hfgh*x@qrhr&dD%Ia| z;feI|z2~d+!1+XiOWhMbW;b7-ei>qSVIqAV&1B&lc*fyGG4e)6y(b@v{xoh%1-?Bf zlk!svoyQ+qd3o98lXCOaNqKqd;st3bE_}Gd>zz2KsnOTcR6o&$FI23bxVWWmZC&FG z^)id}g&tpRQ?+-7Idg8NlQ_@{0kM?6BPat3ib<(e~tquIPl4hb)J^&2{TlD zKmy<4K5}XTDt!pVQ!T#z5s!-xo(z)t2T-8Q zye6Mo)zsLCFNNU4DQZniQ-eC*8~xmg6tBQ^3RzBB1|8H&?@eCS*QBx!nk-(B5=-SD z_?Xkw&`{Y(W+$#3l~Hq4d>+H+_lo*dRW@GgQ@x(XYPGu3SBcc729Jslel)eHO;uHX zv(t$3~X2&#pif_URe5x(@tHwPoeyB}*2Ul`NW-pCkTB>Kymtr6ndZ z|85J{4K2XFCc`aB)uS??5`Eg`pQT}1&pyCXK@DovFs#NVzDCdbf6l8Yql$!?ir|IR zLY`{U3e9sZJ_DoHHNqcT8t5A(YC}`CM_peBKll4oPgQMGiju4*D=BOIH8p6jCU{$m zzwtsPW%%%=WbN_Z6lJ_OORU!s=yz)a&>@1Vp%(zWyn8t%)= zA`hCb1|5_cqEfI^zfkL&*0L04-tv~4Ww(kZKox50%4Tp^vxZKgW*qNb(uA($AwFu$ z+@|_!@r@gpm@z2IW&g!vux+sd)t>8G=B-?daEFpt;3GWVRVgXMudT(`oK(W_XuAtITHnS>(tR-)~o6$@IVnu&vpYp!hZ zdZ>1}?0Y^+qrX8ZMd)8ky$5}&sYY$7Y+UP6u5H10hFF#H*&nq1g{1PJ^E5!kx@Hu> zEJZz%&MK%7aOQm$iFDzwP5jaMQvBijMPB;ik#|Mjs$AwHs;W#JUzLO3iRkZzkfE%g z-&Kmre6v}dsWw!$R78V8?)AJxVh5TRIM<;zaB*;)Ayd(5w#vL+j)ss*4h*$2j{Qu zjzpfpxw|J4c@J%!Ae|W@7%c9WeFJ&LnNx+S`NqGeD2w>_k;2%IP;H!Ye1aT9TKJ;3T`^D{mPXayycpDx= zc#m*A$dH4{)VF|cz>S|kKHzpdiS#7kdw3%2Bfukg=8T@_sy`Bm%mmCi3O>MB0iOg+ zg-?vaB=gB*kOMgOcqCE}_$sEz+W~VwfiCw zs2M$|->$@8^NW$l!$h5(p0P2(m7aBXVsW|}NJ|dtoP#2 zK)&o_)8yI6W^g%$?p!-07QbiI3Y-(x-t2#lRD*7}?baIVa)Y$Avs$7gQpUG!L~Rb*bD3klqWw zSIGX*Uz7_wh;rvf%SAR@;&Tbs<&wN3kk^KOGe(pfqIzshM7ej9T?4RdQNnX6>Dg!@ zv=lez+!3{L6lP$m$4vCcGAz)n!?}XC3?$4;->fFAO-avi$#%#=60Jx+20r@6BGp5b zt3}IQmfj_OhxqRWzkvmrbmE8HyUA|?i7UXB@Kf$KkUuZl&U?ZCB37iP$MVBE2{m9Z zX6lrTNYJ9lf)UNpbM7zH4=Ap5A)buGxw0TVV^MlC^KU2UFM^&;bXHH^H)ev~hIsaN zY`F{4Ro;JA3VF=`Sibq`eYS)?vwg^p6u<6A-1=vHWS1ww*NipSq}cN2rw`Z?2BLQ1 z^`ZXv9{9@;2VKMuyPNypJY-6=!BMHDp&L35bNHEH9R+`@MciB~@`?6>R|r3um)@3; z=tO4fcqUIlUWysz$bUcL>vcF+&{q={r$~2T={}?%K>C9`JtF~)k?dy8$?SbE(w8GH zUrFgz=^59e9Z2qzptphk1<_ZeXCyolEB95TuSOjI8Kuul-(pMff?+NbO!y$|X6 zl+N0t36l9i_DV&ZR}lYcS)9^^-yvQkd=NEn@rZ=gK;{akqJBl=#{KU{A`^tY&giGG zfrt;x0lplvoAP)=dfp3ptr&k?IEVevuWpO#=>+K+q(6rA5T!$rKtjUYJ?Y8Sbha2L zL}u*|z6^|8-$(yAv;EsHO1w6v{aJ^ie4{XKC1YG0E$U;APt=?r!)r9@H5zZXnaJlx zz5(Q8{dTaQ$HtdXoY%}5Z1;`G--Yp$#S_S*gY=>CG#gKr{ecLBe$3(}=~HL+;ssnD zt3UE>K|baWEMGB=KXcglb3GbS6XVZvd5TztB1U06&cgUT$*MgE<2^;pr-p3KIU|~e zr1P-F>UA5+89+Ik(NC#f|72X5m)=K>$otnb$hREx2hx@NBcW)pACN!3iS);i{sjE} zU&t*^Z%+Je;*g3Cj-xa$NydvItEfDtX903w&pR?=0{?#RBrX@V)BL8p-d#51l$l zmDf7)@JqpxDq!39_z9k5Vn@7KiYXBU9MY<5xD$*J*^+mA=B~gk0!$9eqmS= zV8@H}XgdyEBC}&Fzr0igS*fRMQXKqh8rQ=dRq(id%pusYFr_lO5TiUM1dkHjxFluA zxdI*-$xkGGHJ(4DL+afs1Y>EN9kP5p^~dTXS@8e|!~5{G936P_gyB*TeA0yBQ$#wR zpJBMvgXj96^DFnUi`VE`;RxLVzAfNk0Z#}xOgO}70WT47s(^C^yhgwp0oMt5w}AHv z_^5!-3fL{++X5aI@PvTFgoBP2@Dc&13OHB5YXqzjaGij63wWP^j|%v#fZYPVE#P4R zPY5_nbb!$UULxRB0p|*Mjes=*t`qQX0q+y=Q30P7uv@^l1w1U^2?2+(#bZSoE#M^r zP8D#jfY%6EBj7p#?-uYr0Us6cSpmBRd|SZ70-g|X*!kRZMhh74N2^;@Mxy?Kz7mN~ z?=Fw0aJ&|PVwl{wLhe%`_oa~WP3ESxDT+06e+s!D#eN|_p1)b}%Y7*1z7ukviFp2c z!7ullko!vgm5}>L$bBP_6mxih5x?9&Lhct4!}MQ3@|L1}dp~*BE&`hkf8%z0+^u%bqH?iaOnj}TW`B=JLk>f!u zeV8KSW-R?IMaJ7$da@$pcr1OmBIA85Jw=h@UMzitvRTBlSbD0W4&m2{N}7^4Bt2b` z<7liLhoUYvQ}}rz-m{YXdzw=d@itk}ax+EpkBpAX=F~*xoalZsvGh^O{SB&_#Lg2j zs%{>VJ{tR+4#j_Nbbk`FutXZA#W);G|6X*znppbazF@I*5ll@)-v36PQ7;|P>H>FbcBkK9j2&fDl7`B3Fr?Js#fCV)fne`6uXfp|9*{{+x8 zl2sz5FvHX=NZKQH$eEX4woL^bcpR=I%TF~v7mycvM zjs5w^g8y4aPg4d8I6u3mjMGF5Iad3_PPX7*#ORP;%H^|rUN~KD!GDwB$4i#%VE1}) zc7=uhJ_|WNvY`K3$nPxT^4UF9oIWP#tFPj8c25?kzqgRH%YxnqI{902oIf14;Qw0i zZx{Y1{V)M1L$%{*3;Jaibb2M0^oig9aj6AA?R3H7c^mPoV7R5ps%z95KCCeqiAz z^z6Y<_UsdKR$sy8UMJ)qw%||3q?ziqc@bw^CHS)#T_7evUmYE)+_@I?>n-Tb7W9Ax zoz^KbV7Dychf<}t8Go9Rp>oRiMZ&*X$oVbkWdDJJ=#PU=<71n+UM$17MaR>OKTYW^ zNB5w?^m=Dl18D!7C63)$@nZW5dL07~)P(C{{!9q?J=wxSk z9gA+rjzTF%v=@731SyLJeY0ryF9g48;Xl_|l-oe%B96uT=gk)U_Yyz#i#UIvk4vgT z2Qzq@$w^b%M7y{|;tLk?-xmC3GdUxBb_u5k1%0(}G&!IAM9@1YbAI*=8csu)@C?=N z$1KWC0{=x^M9eQ&MY*#q=u0i=UJLq03;JdY`Zmz1z2yFf zK-uw{1wXcat!u3FRaCaLRNh>H=lGS1;_DW<7M9M5O<{Y-f;4Z@vWgO|V(t>x!jcND zc!^Rm&%JoI%U!W}?%bs%LGc?o52jLy|7=rf zzQu4XKijLB?VB7+XPf=TlK7U#v9y+oYh6ng(GJ9Qjj<_s@*hvb$I+tu8OPH33tq7_ zX*$}TIyR-kL+?Q;Ytcv*VyEO-2L2Ka?MaN+8RTRBcn&|7i*36cOQKh)pf_GYiKWv% z)aK2k2UDk*cUB%GQ%lf}$F(i7G}GqQg9-WI6=oEBArGdJAXq25Lvw6O%+A!YNrP`2 zux+7Z6R~qO>uY?s>DV;6=XNZWi9^@KYdmmtn3cB7jx*>PdppO9Sc`q38^wm%aVhmp zYf7+zHCe2oIW~=N>>Wqr`*X(<@u~&Xi=~Mzsbh)F*xDQ0uG2eL=u0uXO;=P@dz&h1 z@kSnA%wg|PRa7E%y~pyht-xD6USCs-r$WANX5J!xkey;6xV<1kTiWV8mJFAuZ$!J(+ejX4a?ju6VjI`T zGRgvP#M^$cDHZeARV?wWr9J3d=G4>n@?P;?S}b4m-6CJh&14pO!BM=Y8q0`1?eXGO z1-*xaUc_Ax4MTavM(?rw6&2+R=Twv|Dz2ar(zMI_ARF0vF7l;zB1mUW4DwaLXvci8obdKn~ZAXe=JQl z0Pk$|cu6%j9mUbBUlnUAkT#e!S@C=8J)XEoWZu_)ke5gLYP>ocM`Lfq#?q8r@68Rq z$~Az9U<}sEGxl}wW+fMv@#MN@mrnFmu2pi^Hu`gGE4{T!ZuQNL$jl-9o~7W0RWDvh zjzKDr*5awJqzvM$x!$MbvQUzX)7-U9K@9pYko!L z*`mLFI3wSe<;(l2y(0er3CBVGmkwEP>AxMInal5LQi%=sUl~xQaS;8L`6Ub^#hgES zf3}%tDU*&RB*=Uc9*fH_pWj&B!ZWlA{Y7>~l_vt81SDCq{(WARr5x}wpiKK0{(A~+ zR7AX;W&R7enCP!m#|-1D$aqhR@(0MdaE!y>h4_>8mhq4Jr_>#%(ZdMv(?c?YNRj1A V# + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "usefull_macros.h" +#include "term.h" +#include // strncasecmp +#include // time(NULL) +#include // INT_MAX, INT_MIN + +#define BUFLEN 1024 + +static char buf[BUFLEN]; + +/** + * read strings from terminal (ending with '\n') with timeout + * @return NULL if nothing was read or pointer to static buffer + */ +static char *read_string(){ + //FNAME(); + size_t r = 0, l; + int LL = BUFLEN - 1; + char *ptr = NULL; + static char *optr = NULL; + if(optr && *optr){ + ptr = optr; + optr = strchr(optr, '\n'); + if(optr) ++optr; + //DBG("got data, roll to next; ptr=%s\noptr=%s",ptr,optr); + return ptr; + } + ptr = buf; + double d0 = dtime(); + do{ + if((l = read_tty(ptr, LL))){ + r += l; LL -= l; ptr += l; + //DBG("got: %s", buf); + if(ptr[-1] == '\n') break; + d0 = dtime(); + } + }while(dtime() - d0 < WAIT_TMOUT && LL); + if(r){ + buf[r] = 0; + //DBG("r=%zd, got string: %s", r, buf); + optr = strchr(buf, '\n'); + if(optr) ++optr; + return buf; + } + return NULL; +} + +/** + * Try to connect to `device` at BAUD_RATE speed + * @return connection speed if success or 0 + */ +void try_connect(char *device){ + if(!device) return; + char tmpbuf[4096]; + fflush(stdout); + tty_init(device); + read_tty(tmpbuf, 4096); // clear rbuf + putlog("Connected to %s", device); + DBG("connected"); +} + +static void con_sig(int rb){ + static char buf[256]; + static int L = 0; + if(rb < 1) return; + if(rb != '\n'){ + if(rb == 127 && L > 0){ + printf("\b \b"); + --L; + }else{ + printf("%c", (char)rb); + buf[L++] = (char)rb; + if(L >= 255){ + printf("\nbuffer overrun!\n"); + L = 0; + } + } + }else{ + buf[L++] = 0x0d; + buf[L] = 0; + printf("\n\t\tSend %s\n", buf); + write_tty(buf, L); + L = 0; + } +} + +/** + * run terminal emulation: send user's commands and show answers + */ +void run_terminal(){ + green(_("Work in terminal mode without echo\n")); + int rb; + char buf[BUFLEN]; + size_t l; + setup_con(); + while(1){ + if((l = read_tty(buf, BUFLEN - 1))){ + buf[l] = 0; + printf("%s", buf); + } + if((rb = read_console())){ + con_sig(rb); + } + } +} + +/** + * write command with trailing "\r\n" + * @return 0 if all OK + */ +int write_cmd(const char *cmd){ + char buf[BUFLEN]; + if(snprintf(buf, BUFLEN, "%s\r", cmd) < 0) return 1; + DBG("Write %s", buf); + if(write_tty(buf, strlen(buf))) return 1; + double t0 = dtime(); + char *ans; + while(dtime() - t0 < T_POLLING_TMOUT){ // read answer + if((ans = read_string())){ // parse new data + DBG("got %s", ans); + if(strstr(ans, "OK")){ + DBG("Succesfull"); + return 0; + } + } + } + return 1; +} + +/** + * Poll serial port for new dataportion + * @return: NULL if no data received, pointer to string if valid data received + */ +char *poll_device(){ + char *ans; + static char pollbuf[32]; + double t0 = dtime(); + const char *cmdstat = "SHUTTERSTATUS?"; + const char *cmdget = "SHUTTERS?"; + #define CMDGETLEN (9) + while(read_string()); // clear receiving buffer + if(write_cmd(cmdstat)) return NULL; // error writing command + DBG("poll answer"); + while(dtime() - t0 < T_POLLING_TMOUT){ // read answer + if((ans = read_string())){ // parse new data + DBG("got %s", ans); + if(strstr(ans, cmdget) == NULL){ + DBG("no %s found in %s", cmdstat, ans); + return NULL; // ? + } + ans += CMDGETLEN; + if(strstr(ans, "1,1,1,1,1")){ + sprintf(pollbuf, "opened\n"); + DBG("shutters opened"); + }else if(strstr(ans, "0,0,0,0,0")){ + sprintf(pollbuf, "closed\n"); + DBG("shutters closed"); + }else sprintf(pollbuf, "intermediate\n"); + return pollbuf; + } + } + return NULL; +} + +/** + * ping device + * @return 0 if all OK + */ +int ping(){ + FNAME(); + if(write_cmd("PING?")) return 1; + return 0; +} diff --git a/Daemons/teldaemon/term.h b/Daemons/teldaemon/term.h new file mode 100644 index 0000000..5816c7b --- /dev/null +++ b/Daemons/teldaemon/term.h @@ -0,0 +1,38 @@ +/* geany_encoding=koi8-r + * term.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __TERM_H__ +#define __TERM_H__ + +#define FRAME_MAX_LENGTH (300) +#define MAX_MEMORY_DUMP_SIZE (0x800 * 4) +// Terminal timeout (seconds) +#define WAIT_TMOUT (0.5) +// Terminal polling timeout - 1 second +#define T_POLLING_TMOUT (1.0) + +void run_terminal(); +void try_connect(char *device); +char *poll_device(); +int ping(); +int write_cmd(const char *cmd); + +#endif // __TERM_H__ diff --git a/Daemons/teldaemon/usefull_macros.c b/Daemons/teldaemon/usefull_macros.c new file mode 100644 index 0000000..da08cfe --- /dev/null +++ b/Daemons/teldaemon/usefull_macros.c @@ -0,0 +1,437 @@ +/* + * usefull_macros.h - a set of usefull functions: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "usefull_macros.h" +#include +#include // PATH_MAX + +/** + * function for different purposes that need to know time intervals + * @return double value: time in seconds + */ +double dtime(){ + double t; + struct timeval tv; + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1e6; + return t; +} + +/******************************************************************************\ + * Coloured terminal +\******************************************************************************/ +int globErr = 0; // errno for WARN/ERR + +// pointers to coloured output printf +int (*red)(const char *fmt, ...); +int (*green)(const char *fmt, ...); +int (*_WARN)(const char *fmt, ...); + +/* + * format red / green messages + * name: r_pr_, g_pr_ + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(RED); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +int g_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(GREEN); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +/* + * print red error/warning messages (if output is a tty) + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_WARN(const char *fmt, ...){ + va_list ar; int i = 1; + fprintf(stderr, RED); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = vfprintf(stderr, fmt, ar); + va_end(ar); + i++; + fprintf(stderr, OLDCOLOR "\n"); + return i; +} + +static const char stars[] = "****************************************"; +/* + * notty variants of coloured printf + * name: s_WARN, r_pr_notty + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int s_WARN(const char *fmt, ...){ + va_list ar; int i; + i = fprintf(stderr, "\n%s\n", stars); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + }else + i = +vfprintf(stderr, fmt, ar); + va_end(ar); + i += fprintf(stderr, "\n%s\n", stars); + i += fprintf(stderr, "\n"); + return i; +} +int r_pr_notty(const char *fmt, ...){ + va_list ar; int i; + i = printf("\n%s\n", stars); + va_start(ar, fmt); + i += vprintf(fmt, ar); + va_end(ar); + i += printf("\n%s\n", stars); + return i; +} + +/** + * Run this function in the beginning of main() to setup locale & coloured output + */ +void initial_setup(){ + // setup coloured output + if(isatty(STDOUT_FILENO)){ // make color output in tty + red = r_pr_; green = g_pr_; + }else{ // no colors in case of pipe + red = r_pr_notty; green = printf; + } + if(isatty(STDERR_FILENO)) _WARN = r_WARN; + else _WARN = s_WARN; + // Setup locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#if defined GETTEXT_PACKAGE && defined LOCALEDIR + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); +#endif +} + +/******************************************************************************\ + * Memory +\******************************************************************************/ +/* + * 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 *p = calloc(N, S); + if(!p) ERR("malloc"); + //assert(p); + return p; +} + +/** + * 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){ + int fd; + char *ptr; + size_t Mlen; + struct stat statbuf; + /// "Не задано имя файла!" + if(!filename){ + WARNX(_("No filename given!")); + return NULL; + } + if((fd = open(filename, O_RDONLY)) < 0){ + /// "Не могу открыть %s для чтения" + WARN(_("Can't open %s for reading"), filename); + return NULL; + } + if(fstat (fd, &statbuf) < 0){ + /// "Не могу выполнить stat %s" + WARN(_("Can't stat %s"), filename); + close(fd); + return NULL; + } + Mlen = statbuf.st_size; + if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){ + /// "Ошибка mmap" + WARN(_("Mmap error for input")); + close(fd); + return NULL; + } + /// "Не могу закрыть mmap'нутый файл" + if(close(fd)) WARN(_("Can't close mmap'ed file")); + mmapbuf *ret = MALLOC(mmapbuf, 1); + ret->data = ptr; + ret->len = Mlen; + return ret; +} + +void My_munmap(mmapbuf *b){ + if(munmap(b->data, b->len)){ + /// "Не могу munmap" + ERR(_("Can't munmap")); + } + FREE(b); +} + + +/******************************************************************************\ + * Terminal in no-echo mode +\******************************************************************************/ +static struct termios oldt, newt; // terminal flags +static int console_changed = 0; +// run on exit: +void restore_console(){ + if(console_changed) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state + console_changed = 0; +} + +// initial setup: +void setup_con(){ + if(console_changed) return; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ + /// "Не могу настроить консоль" + WARN(_("Can't setup console")); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + signals(0); //quit? + } + console_changed = 1; +} + +/** + * Read character from console without echo + * @return char readed + */ +int read_console(){ + int rb; + struct timeval tv; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(1, &rfds, NULL, NULL, &tv); + if(!retval) rb = 0; + else { + if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); + else rb = 0; + } + return rb; +} + +/** + * getchar() without echo + * wait until at least one character pressed + * @return character readed + */ +int mygetchar(){ // getchar() without need of pressing ENTER + int ret; + do ret = read_console(); + while(ret == 0); + return ret; +} + + +/******************************************************************************\ + * TTY with select() +\******************************************************************************/ +static struct termio oldtty, tty; // TTY flags +static int comfd = -1; // TTY fd + +// run on exit: +void restore_tty(){ + if(comfd == -1) return; + ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state + close(comfd); + comfd = -1; +} + +#ifndef BAUD_RATE +#define BAUD_RATE B4800 +#endif +#pragma message("Baudrate: " STR(BAUD_RATE) " (default: " STR(B4800) ")") +// init: +void tty_init(char *comdev){ + DBG("\nOpen port %s ...\n", comdev); + do{ + comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK); + }while (comfd == -1 && errno == EINTR); + if(comfd < 0){ + WARN("Can't use port %s\n",comdev); + signals(-1); // quit? + } + // make exclusive open + if(ioctl(comfd, TIOCEXCL)){ + WARN(_("Can't do exclusive open")); + close(comfd); + signals(2); + } + DBG(" OK\nGet current settings... "); + if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings + /// "Не могу получить настройки" + WARN(_("Can't get settings")); + signals(-1); + } + tty = oldtty; + tty.c_lflag = 0; + tty.c_oflag = 0; + tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl + tty.c_cc[VMIN] = 20; + tty.c_cc[VTIME] = 5; + if(ioctl(comfd,TCSETA,&tty) < 0){ + /// "Не могу установить настройки" + WARN(_("Can't set settings")); + signals(-1); + } + DBG(" OK\n"); +} + +/** + * Read data from TTY + * @param buff (o) - buffer for data read + * @param length - buffer len + * @return amount of bytes read + */ +size_t read_tty(char *buff, size_t length){ + ssize_t L = 0, l; + char *ptr = buff; + fd_set rfds; + struct timeval tv; + int retval; + do{ + l = 0; + FD_ZERO(&rfds); + FD_SET(comfd, &rfds); + // wait for 100ms + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(comfd + 1, &rfds, NULL, NULL, &tv); + if (!retval) break; + if(FD_ISSET(comfd, &rfds)){ + //DBG("ISSET"); + if((l = read(comfd, ptr, length)) < 1){ + return 0; + } + //DBG("got %zd", l); + ptr += l; L += l; + length -= l; + } + }while(l); + return (size_t)L; +} + +int write_tty(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; +} + + +/** + * 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){ + double res; + char *endptr; + if(!str) return 0; + res = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0'){ + /// "Неправильный формат числа double!" + WARNX("Wrong double number format!"); + return FALSE; + } + if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number + return TRUE; +} + +FILE *Flog = NULL; // log file descriptor +char *logname = NULL; +time_t log_open_time = 0; +/** + * Try to open log file + * if failed show warning message + */ +void openlogfile(char *name){ + if(!name){ + WARNX(_("Need filename")); + return; + } + green(_("Try to open log file %s in append mode\n"), name); + 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, "\n\t\t%s", ctime(&t_now)); + va_list ar; + va_start(ar, fmt); + i = vfprintf(Flog, fmt, ar); + va_end(ar); + fprintf(Flog, "\n"); + fflush(Flog); + return i; +} diff --git a/Daemons/teldaemon/usefull_macros.h b/Daemons/teldaemon/usefull_macros.h new file mode 100644 index 0000000..0d62e3c --- /dev/null +++ b/Daemons/teldaemon/usefull_macros.h @@ -0,0 +1,144 @@ +/* + * usefull_macros.h - a set of usefull macros: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __USEFULL_MACROS_H__ +#define __USEFULL_MACROS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined GETTEXT_PACKAGE && defined LOCALEDIR +/* + * GETTEXT + */ +#include +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) +#else +#define _(String) (String) +#define N_(String) (String) +#endif + +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) + +#include +#include +#include +#include +#include +#include + + +// unused arguments with -Wall -Werror +#define _U_ __attribute__((__unused__)) + +/* + * Coloured messages output + */ +#define RED "\033[1;31;40m" +#define GREEN "\033[1;32;40m" +#define OLDCOLOR "\033[0;0;0m" + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +/* + * ERROR/WARNING messages + */ +extern int globErr; +extern void signals(int sig); +#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) +#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0) +#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) +#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) + +/* + * print function name, debug messages + * debug mode, -DEBUG + */ +#ifdef EBUG + #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) +#else + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) +#endif //EBUG + +/* + * 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 FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0) + +#ifndef DBL_EPSILON +#define DBL_EPSILON (2.2204460492503131e-16) +#endif + +double 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, ...); +void * my_alloc(size_t N, size_t S); +void initial_setup(); + +// mmap file +typedef struct{ + char *data; + size_t len; +} mmapbuf; +mmapbuf *My_mmap(char *filename); +void My_munmap(mmapbuf *b); + +void restore_console(); +void setup_con(); +int read_console(); +int mygetchar(); + +void restore_tty(); +void tty_init(char *comdev); +size_t read_tty(char *buff, size_t length); +int write_tty(const char *buff, size_t length); + +int str2double(double *num, const char *str); + +void openlogfile(char *name); +int putlog(const char *fmt, ...); +#endif // __USEFULL_MACROS_H__ diff --git a/Docs/Alignment/PROCESS b/Docs/Alignment/PROCESS new file mode 100644 index 0000000..059d406 --- /dev/null +++ b/Docs/Alignment/PROCESS @@ -0,0 +1,11 @@ +for f in *.fit; do solve-field --use-sextractor -p -L 1.2 -H 1.5 -u arcsecperpix $f; done +rm *.axy *.corr *.xyls *.match *.rdls *.solved *.wcs +makelist >> coordslist +convert UTC into sidereal time +while read l; do echo ":newalpt${l}#"; done < coordslist + +enter into mount terminal +:newalig# - start new +enter all strings :newalpt... +:endalig# - end +:modelsv0NAME# - save diff --git a/Docs/Alignment/Readme.md b/Docs/Alignment/Readme.md new file mode 100644 index 0000000..400b1e8 --- /dev/null +++ b/Docs/Alignment/Readme.md @@ -0,0 +1,12 @@ +Alignment +========= + +Alignment procedure: + +- make a set of star-field images +- calculate astrometry +- calculate astrometric image center position on sky (J2000) +- prepare table like `coordlist`: telcoords,hemisphere,realcoors,sidtime +- enter data into telescope mount + +You should store parameters RA2000, DEC2000 and SidTime of each FITS-file. diff --git a/Docs/Alignment/coordslist b/Docs/Alignment/coordslist new file mode 100644 index 0000000..6cdb0e7 --- /dev/null +++ b/Docs/Alignment/coordslist @@ -0,0 +1,30 @@ +01:21:59.5,+76:14:19.3,W,01:27:25.2,+75:24:09,04:48:40 +01:27:40.1,+45:24:23.7,W,01:28:2.2,+44:34:03,04:49:38 +01:45:23.8,+09:09:28.5,W,01:44:22.5,+08:17:57,04:50:39 +04:20:40.3,+65:08:25.3,W,04:19:56.8,+64:08:56,04:47:26 +04:37:14.8,+18:32:34.8,W,04:36:0.1,+17:33:03,04:45:15 +04:38:53.5,-12:07:23.6,W,04:37:36.8,-13:06:19,04:43:21 +04:42:22.3,+41:51:41.8,W,04:41:9.4,+40:52:06,04:46:32 +04:43:09.3,-30:45:57.5,E,04:41:41.3,-30:46:04,04:40:03 +05:40:48.0,-2:30:00.0,E,05:39:9.2,-02:30:17,05:12:45 +05:43:00.5,-2:18:45.0,E,05:41:21.5,-02:18:55,05:15:14 +06:23:38.9,+40:31:16.7,E,06:20:53.4,+40:33:15,04:35:30 +06:47:37.2,-08:59:54.6,E,06:46:8.8,-08:55:24,04:38:42 +07:00:04.4,+76:58:38.0,E,06:52:32.9,+77:01:35,05:06:03 +07:10:13.7,-4:14:09.2,E,07:08:38.9,-04:09:35,05:08:27 +07:24:08.5,+40:40:20.2,E,07:21:13.4,+40:45:24,05:07:16 +07:38:18.0,-25:21:53.4,E,07:37:16.4,-25:13:18,05:09:24 +08:40:24.0,+19:40:01.2,E,08:37:58.9,+19:56:34,05:33:05 +10:16:40.7,+13:43:41.6,E,10:14:28.9,+14:10:34,05:02:56 +10:35:05.3,+75:42:47.3,E,10:24:16.2,+76:10:12,05:05:00 +10:43:32.3,+46:12:14.1,E,10:39:33.3,+46:41:43,05:04:06 +13:18:14.4,+49:40:55.6,E,13:14:28.7,+50:30:53,05:01:55 +13:29:52.7,+47:11:42.9,E,13:26:15.5,+48:00:47,05:21:06 +13:42:23.7,+82:45:08.9,E,13:25:53.3,+83:35:40,05:00:55 +16:19:52.1,+83:41:50.6,E,16:13:49.9,+84:41:53,04:59:58 +16:40:55.1,+64:35:20.2,E,16:38:59.8,+65:36:38,04:58:46 +19:21:40.4,+79:36:09.5,W,19:29:1.7,+79:30:51,04:55:49 +19:38:41.4,+54:58:28.5,W,19:39:44.8,+54:53:10,04:56:50 +22:21:19.4,+28:19:49.9,W,22:21:16.9,+27:53:46,04:52:03 +22:29:10.3,+58:24:54.8,W,22:31:32.4,+57:56:50,04:52:58 +22:47:29.7,+83:09:13.7,W,23:04:7.6,+82:37:35,04:53:54 diff --git a/Docs/Alignment/makelist b/Docs/Alignment/makelist new file mode 100755 index 0000000..7a012c0 --- /dev/null +++ b/Docs/Alignment/makelist @@ -0,0 +1,43 @@ +#!/bin/bash + +T=local.m + +function procfile(){ +f=$1 +OLD=$(echo $f|sed -e 's/_/,/' -e 's/\.new//') +NEW=$(xy2sky -d $f 2076 2064) +NEWRA=$(echo $NEW | awk '{print $1}') +NEWDEC=$(echo $NEW | awk '{print $2}') + +cat > local.m << EOF +x=$NEWRA/15; c=''; if(x<0)c='-';x=-x;endif; +H=floor(x);x=(x-H)*60; +M=floor(x);x=(x-M)*60; +printf("%c%02d:%02d:%02.1f\n", c, H,M,x); +EOF + +NEWRA0=$(octave $T 2>/dev/null) + +cat > local.m << EOF +x=$NEWDEC; c='+'; if(x<0)c='-';x=-x;endif; +H=floor(x);x=(x-H)*60; +M=floor(x);x=(x-M)*60; +printf("%c%02d:%02d:%02d\n", c, H,M,round(x)); +EOF + +NEWDEC0=$(octave $T 2>/dev/null) + +TM=$(listhead $f|grep "DATE " | sed -e "s/.*'.*T\(.*\)'.*/\\1/") +#' +echo -e "${OLD},E,$NEWRA0,$NEWDEC0,$TM" + +rm -f $T +} + +if [ $# -gt 0 ]; then + procfile $* +else + for f in *.new; do + procfile $f + done +fi diff --git a/Docs/README_ASTROMETRY.koi8-r b/Docs/README_ASTROMETRY.koi8-r new file mode 100644 index 0000000..111c4ec --- /dev/null +++ b/Docs/README_ASTROMETRY.koi8-r @@ -0,0 +1,21 @@ +1. сделать астрометрию +2. вычислить координаты центра: + xy2sky wcs_file.fits Xc Yc +3. полученный ответ: RA0 DEC0 J2000 X Y, искомые разности: + INPRA0 - RA0 = dAlp + INPDEC0 - DEC0 = dDel +4. преобразовать в dA, dZ обе пары + calcAZhdeg(ra,dec,st) + получатся INPA,INPZ и A,Z +5. dA = INPA-A, dZ=INPZ-Z + +Определение INPRA/DEC: +INPRA0=$(echo "15*$(fitshdr $FIT |grep INPRA0| sed 's|.*= *\(.*\)/.*|\1|')" | bc -l) +INPDEC0=$(fitshdr $FIT |grep INPDEC0| sed 's|.*= *\(.*\)/.*|\1|') + +WCS=$(bsnm $FIT)_wcs.fits +solve-field --use-sextractor -p --ra $INPRA0 --dec $INPDEC0 -5 0.5 -L 0.29 -H 0.32 -u arcsecperpix -O -N $WCS $FIT +retval=$? +rm *.axy *.solved *.corr *.xyls *.match *.rdls + +process_FITS файл Xc Yc diff --git a/Docs/README_POWER_management.koi8-r b/Docs/README_POWER_management.koi8-r new file mode 100644 index 0000000..eea4bb8 --- /dev/null +++ b/Docs/README_POWER_management.koi8-r @@ -0,0 +1,65 @@ +1. Подключиться к "розетке": + ssh obs@192.168.70.34 (pass: 2open4me) +2. Включить питание компьютера: + HWpoweron +3. После загрузки компьютера 192.168.70.33 в соседней консоли зайти на него: + ssh obs@192.168.70.33 + Автоматически запущены демоны управления шторками телескопа, створками купола и демон для наведения телескопа + на цель при помощи stellarium + В директории ~/bin находится образец фокусировочного скрипта focus +4. Запустить монтировку (консоль с ssh на 192.168.70.34): + MOUNTpoweronoff + Вернуться в консоль с 192.168.70.33, далее (вплоть до отключения) работать в ней. +5. Для наблюдения за куполом открыть в браузере камеру: http://cam3.sao.ru , пользователь admin, пароль X98sXMHi92 + Чтобы работало видео, в Stream Type выбрать MJPEG (все остальное - нерабочее); при помощи PTZ control можно двигать камеру. +6. Пока включается монтировка, открыть купол: + либо из браузера http://192.168.70.33:55555/open (должен вернуться ответ OK) + либо из curl аналогично послав запрос + Проверка статуса купола: http://192.168.70.33:55555/status (opened/closed/intermediate) + Проверка статуса погоды (если включено питание метеостанции): http://192.168.70.33:55555/weather (good weather или rain/clouds) +7. Открыть створки телескопа (аналогично п.6: из браузера или curl): + http://192.168.70.33:4444/open (ответ: OK) + Аналогично запросом http://192.168.70.33:4444/status можно узнать состояние створок (opened/closed/intermediate) +8. Можно приступать к управлению: наведение при помощи stellarium и управление камерой, турелью и фокусером при помощи fli_control. +9. После окончания наблюдений припарковать телескоп (пока не реализовано -> навести на звезду около зенита). +10. После окончания движения телескопа отключить монтировку телескопа (из консоли с 192.168.70.34): + MOUNTpoweronoff + соединение с телескопом в stellarium будет нарушено и курсор, отмечающий текущее положение, исчезнет. +11. Закрыть створки телескопа и купол: + http://192.168.70.33:4444/close + http://192.168.70.33:55555/close +12. При необходимости снятия питания с компьютера и оборудования сначала выключить компьютер (консоль 192.168.70.34): + sudo poweroff + !!! Ни в коем случае нельзя отключать питание монтировки до ее полного выключения!!! После подачи команды MOUNTpoweronoff + и исчезновения курсора положения телескопа в stellarium выждать 30 секунд! + После отключения компьютера и монтировки можно выключить их питание (консоль 192.168.70.33): + HWpoweroff + +Компьютер 192.168.70.33 не выключать! + + + +Управление из stellarium +======================== + +Для того, чтобы stellarium не пытался выходить через прокси (он чхать хотел на переменную no_proxy), запускать его так: + http_proxy="" stellarium +В плагине "управление телескопом" нужно внести новый телескоп. Для этого в пункте "Телескоп управляется" отмечаем +"Внешнее ПО или удаленный компьютер", в "Свойства телескопа" пишем название, "задерка подключения" -> 0.5с (при плохой связи, +если указатель положения телескопа сильно дергается, можно увеличить это число), "Система координат" -> J2000. +"Настройки подключения": "узел" -> 192.168.70.33, "порт" 10000. +Далее выбираем в списке этот телескоп и жмем "подключить". + +Выбираем объект, щелкнув на нем ЛКМ, жмем ctrl+0 - появляется меню "навести телескоп на", там жмем кнопку "текущий объект" +и "навести". Если все в порядке, курсор, отмечающий положение телескопа начнет передвижение к объекту. После того, как телескоп +наведется и курсор будет совмещен с объектом, выждать еще около 10 секунд, чтобы монтировка точно перешла в режим гидирования. + +Парковка пока не реализована, поэтому после окончания наблюдений необходимо будет навести телескоп на объект вблизи зенита. + + +Камера +====== + +Доступ к поворотной камере: +http://cam3.sao.ru +admin, X98sXMHi92 diff --git a/Docs/Readme.md b/Docs/Readme.md new file mode 100644 index 0000000..bcb198e --- /dev/null +++ b/Docs/Readme.md @@ -0,0 +1,4 @@ +Docs +==== + +Different documentation & readme diff --git a/Docs/focus b/Docs/focus new file mode 100755 index 0000000..90a944b --- /dev/null +++ b/Docs/focus @@ -0,0 +1,14 @@ +#!/bin/bash +step=1000 +if [ $# -lt 1 -o $# -gt 3 ]; then + echo "USAGE: $0 start_foc end_foc [step - default 1000]" + exit 1 +fi + +[ $# = 3 ] && step=$3 +for f in $(seq $1 $step $2); do + echo "goto $f" + fli_control -g $f + fli_control -x 5000 --force focus_$(printf "%06d" $f) + fitsread -a "FOCUS = ${f}" --inplace -i $(ls -t *fit | head -n1) +done