fixed bugs with dead without net in bta_mirtemp

This commit is contained in:
eddyem 2020-08-21 12:44:07 +03:00
parent 6d471893c4
commit cfcea9b83d
11 changed files with 433 additions and 73 deletions

View File

@ -154,7 +154,11 @@ typedef struct __attribute__((__packed__)){
int32_t status; int32_t status;
} outdata; } outdata;
#define ACS_CMD(a) do{green(#a); printf("\n"); a; }while(0) #ifdef EBUG
#define ACS_CMD(a) do{green(#a); printf("\n"); }while(0)
#else
#define ACS_CMD(a) do{red(#a); printf("\n"); a; }while(0)
#endif
/** /**
* send input RA/Decl (j2000!) coordinates to tel * send input RA/Decl (j2000!) coordinates to tel
* both coords are in seconds (ra in time, dec in angular) * both coords are in seconds (ra in time, dec in angular)
@ -387,8 +391,10 @@ int main(_U_ int argc, char **argv){
if(fabs(M_time - last) < 0.02) if(fabs(M_time - last) < 0.02)
ERRX(_("Data stale!")); ERRX(_("Data stale!"));
get_cmd_queue(&ucmd, ClientSide); get_cmd_queue(&ucmd, ClientSide);
#ifndef EBUG
passhash pass = {0,0}; passhash pass = {0,0};
get_passhash(&pass); get_passhash(&pass);
#endif
printf(_("All OK, start socket\n")); printf(_("All OK, start socket\n"));

View File

@ -1,9 +1,8 @@
PROGRAM = bta_mirtemp PROGRAM = bta_mirtemp
LDFLAGS = -lcrypt LDFLAGS = -lcrypt
#-lm -lsla
SRCS = $(wildcard *.c) SRCS = $(wildcard *.c)
CC = gcc CC = gcc
DEFINES = -D_XOPEN_SOURCE=666 DEFINES = -D_XOPEN_SOURCE=1111 -D_GNU_SOURCE
# -DEBUG # -DEBUG
CXX = gcc CXX = gcc
CFLAGS = -Wall -Werror -Wextra $(DEFINES) -pthread CFLAGS = -Wall -Werror -Wextra $(DEFINES) -pthread

View File

@ -1,6 +1,8 @@
#include "bta_shdata.h" #include "bta_shdata.h"
#include "usefull_macros.h" #include "usefull_macros.h"
#include <crypt.h>
#pragma pack(push, 4) #pragma pack(push, 4)
// Main command channel (level 5) // Main command channel (level 5)
struct CMD_Queue mcmd = {{"Mcmd"}, 0200,0,-1,0}; struct CMD_Queue mcmd = {{"Mcmd"}, 0200,0,-1,0};

View File

@ -0,0 +1,2 @@
// Add predefined macros for your project here. For example:
// #define THE_ANSWER 42

View File

@ -0,0 +1 @@
[General]

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.8.2, 2020-08-21T12:33:04. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey"/>
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00-BTAmirtemp</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">false</value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">false</value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">По умолчанию</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">По умолчанию</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Установка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Конфигурация установки</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Особая программа</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="RunConfiguration.Arguments"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">20</value>
</data>
<data>
<variable>Version</variable>
<value type="int">20</value>
</data>
</qtcreator>

View File

@ -0,0 +1,5 @@
bta_shdata.c
bta_shdata.h
main.c
usefull_macros.c
usefull_macros.h

View File

@ -0,0 +1 @@
.

182
bta_mirtemp/main.c Normal file
View File

@ -0,0 +1,182 @@
#include <arpa/inet.h>
#include <errno.h>
#include <libgen.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h> //prctl
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h> // wait
#include <time.h>
#define __USE_BSD
#include <unistd.h>
#include "usefull_macros.h"
#include "bta_shdata.h"
#define HOST "mirtemp.sao.ru"
#define PORT "4444"
#define RESOURCE "Tmean"
static int gotsegm = 0;
void clear_flags(){
if(!gotsegm) return;
if(MeteoMode & NET_T3){ // clear "net" & "sensor" flags
MeteoMode &= ~NET_HMD;
if(MeteoMode & SENSOR_T3) MeteoMode &= ~SENSOR_T3;
}
}
void signals(int sig){
char ss[10];
signal(sig, SIG_IGN);
switch(sig){
case SIGHUP : strcpy(ss,"SIGHUP"); break;
case SIGINT : strcpy(ss,"SIGINT"); break;
case SIGQUIT: strcpy(ss,"SIGQUIT"); break;
case SIGFPE : strcpy(ss,"SIGFPE"); break;
case SIGPIPE: strcpy(ss,"SIGPIPE"); break;
case SIGSEGV: strcpy(ss,"SIGSEGV"); break;
case SIGTERM: strcpy(ss,"SIGTERM"); break;
default: sprintf(ss,"SIG_%d",sig); break;
}
switch(sig){
default:
case SIGHUP :
LOG("%s - Ignore ...", ss);
fflush(stderr);
signal(sig, signals);
return;
case SIGINT :
case SIGPIPE:
case SIGQUIT:
case SIGFPE :
case SIGSEGV:
case SIGTERM:
signal(SIGALRM, SIG_IGN);
LOG("%s - Stop!", ss);
clear_flags();
exit(sig);
}
}
/**
* get mirror temperature over network
* @return 0 if succeed
*/
int get_mirT(double *T){
int sockfd = 0;
char recvBuff[64];
memset(recvBuff, 0, sizeof(recvBuff));
struct addrinfo h, *r, *p;
memset(&h, 0, sizeof(h));
h.ai_family = AF_INET;
h.ai_socktype = SOCK_STREAM;
h.ai_flags = AI_CANONNAME;
char *host = HOST;
char *port = PORT;
if(getaddrinfo(host, port, &h, &r)) WARNX("getaddrinfo()");
for(p = r; p; p = p->ai_next){
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
WARN("socket()");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
WARN("connect()");
continue;
}
break; // if we get here, we must have connected successfully
}
if(p == NULL){
WARNX("failed to connect");
return 1;
}
freeaddrinfo(r);
if(send(sockfd, RESOURCE, sizeof(RESOURCE), 0) != sizeof(RESOURCE)){
WARN("send()");
return 1;
}
ssize_t rd = read(sockfd, recvBuff, sizeof(recvBuff)-1);
if(rd < 0){
WARN("read()");
return 1;
}else recvBuff[rd] = 0;
close(sockfd);
char *eptr;
*T = strtod(recvBuff, &eptr);
DBG("Got mirror T=%.1f", *T);
if(eptr == recvBuff) return 1;
return 0;
}
int main (int argc, char *argv[]){
initial_setup();
if(argc == 2){
printf("Log file: %s", argv[1]);
Cl_createlog(argv[1]);
}
signal(SIGHUP, signals);
signal(SIGINT, signals);
signal(SIGQUIT,signals);
signal(SIGFPE, signals);
signal(SIGPIPE,signals);
signal(SIGSEGV,signals);
signal(SIGTERM,signals);
LOG("\nStarted\n");
#ifndef EBUG
if(daemon(1, 0)){
ERR("daemon()");
}
while(1){ // guard for dead processes
pid_t childpid = fork();
if(childpid){
LOG("create child with PID %d", childpid);
wait(NULL);
LOG("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
time_t tlast = time(NULL);
while(1){
if(!gotsegm){
sdat.mode |= 0200;
sdat.atflag = 0;
gotsegm = get_shm_block( &sdat, ClientSide);
if(!gotsegm){
LOG("Can't find SHM segment");
} else get_cmd_queue( &ocmd, ClientSide);
}
double T;
if(time(NULL) - tlast > 900){ // no signal for 15 minutes - clear flags
LOG("15 minutes - no signal!");
tlast = time(NULL);
clear_flags();
}
if(get_mirT(&T)){
sleep(10);
continue;
}
if(gotsegm && 0 == (MeteoMode & INPUT_T3)){ // not manual mode - change Tmir value
val_T3 = T;
MeteoMode |= (SENSOR_T3|NET_T3);
DBG("Change T: %.2f", T);
}
sleep(60);
tlast = time(NULL);
}
return 0;
}

View File

@ -21,6 +21,8 @@
#include "usefull_macros.h" #include "usefull_macros.h"
#include <pthread.h>
/** /**
* function for different purposes that need to know time intervals * function for different purposes that need to know time intervals
* @return double value: time in seconds * @return double value: time in seconds
@ -247,77 +249,63 @@ int mygetchar(){ // getchar() without need of pressing ENTER
return ret; return ret;
} }
// logging
/******************************************************************************\
* TTY with select()
\******************************************************************************/
static struct termio oldtty, tty; // TTY flags
static int comfd = -1; // TTY fd
// run on exit: static Cl_log log = {0};
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:
void tty_init(char *comdev){
DBG("\nOpen port...\n");
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
WARN("Can't use port %s\n",comdev);
ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state
close(comfd);
signals(0); // quit?
}
DBG(" OK\nGet current settings... ");
if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings
WARN(_("Can't get settings"));
signals(0);
}
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(0);
}
DBG(" OK\n");
}
/** /**
* Read data from TTY * @brief Cl_createlog - create log file: init mutex, test file open ability
* @param buff (o) - buffer for data read * @param log - log structure
* @param length - buffer len * @return 0 if all OK
* @return amount of readed bytes
*/ */
size_t read_tty(uint8_t *buff, size_t length){ int Cl_createlog(char *logname){
ssize_t L = 0; if(log.logpath){
fd_set rfds; FREE(log.logpath);
struct timeval tv; pthread_mutex_destroy(&log.mutex);
int retval;
FD_ZERO(&rfds);
FD_SET(comfd, &rfds);
tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms
retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
if (!retval) return 0;
if(FD_ISSET(comfd, &rfds)){
if((L = read(comfd, buff, length)) < 1) return 0;
} }
return (size_t)L; FILE *logfd = fopen(logname, "a");
} if(!logfd){
WARN("Can't open log file");
int write_tty(uint8_t *buff, size_t length){ return 2;
ssize_t L = write(comfd, buff, length); }
if((size_t)L != length){ log.logpath = strdup(logname);
WARN("Write error!"); fclose(logfd);
return 1; if(pthread_mutex_init(&log.mutex, NULL)){
WARN("Can't init log mutes");
return 3;
} }
return 0; return 0;
} }
/**
* @brief Cl_putlog - put message to log file with/without timestamp
* @param timest - ==1 to put timestamp
* @param log - pointer to log structure
* @param lvl - message loglevel (if lvl > loglevel, message won't be printed)
* @param fmt - format and the rest part of message
* @return amount of symbols saved in file
*/
int Cl_putlogt(const char *fmt, ...){
if(pthread_mutex_lock(&log.mutex)){
WARN("Can't lock log mutex");
return 0;
}
int i = 0;
FILE *logfd = fopen(log.logpath, "a");
if(!logfd) goto rtn;
char strtm[128];
time_t t = time(NULL);
struct tm *curtm = localtime(&t);
strftime(strtm, 128, "%Y/%m/%d-%H:%M:%S", curtm);
i = fprintf(logfd, "%s\t", strtm);
va_list ar;
va_start(ar, fmt);
i += vfprintf(logfd, fmt, ar);
va_end(ar);
i += fprintf(logfd, "\n");
fclose(logfd);
rtn:
pthread_mutex_unlock(&log.mutex);
return i;
}

View File

@ -93,6 +93,7 @@ extern void signals(int sig);
#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) #define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type))) #define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type)))
#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0) #define FREE(ptr) do{free(ptr); ptr = NULL;}while(0)
#define LOG(...) do{Cl_putlogt(__VA_ARGS__); WARNX(__VA_ARGS__);}while(0)
double dtime(); double dtime();
@ -116,9 +117,12 @@ void setup_con();
int read_console(); int read_console();
int mygetchar(); int mygetchar();
void restore_tty(); typedef struct{
void tty_init(char *comdev); char *logpath; // full path to logfile
size_t read_tty(uint8_t *buff, size_t length); pthread_mutex_t mutex; // log mutex
int write_tty(uint8_t *buff, size_t length); } Cl_log;
int Cl_createlog(char *logname);
int Cl_putlogt(const char *fmt, ...);
#endif // __USEFULL_MACROS_H__ #endif // __USEFULL_MACROS_H__