diff --git a/allsky_logger/cmdlnopts.c b/allsky_logger/cmdlnopts.c index 1577f92..94258a9 100644 --- a/allsky_logger/cmdlnopts.c +++ b/allsky_logger/cmdlnopts.c @@ -41,6 +41,7 @@ glob_pars const Gdefault = { .server = NULL, // server name .filename = NULL, // input file name .min_storage_time = 60.,// minimal storage period + .logfile = NULL, }; /* @@ -54,6 +55,7 @@ myoption cmdlnopts[] = { {"address", NEED_ARG, NULL, 'a', arg_string, APTR(&G.server), _("server name")}, {"filename",NEED_ARG, NULL, 'i', arg_string, APTR(&G.filename), _("input FITS file name")}, {"mindt", NEED_ARG, NULL, 't', arg_double, APTR(&G.min_storage_time), _("minimal time interval (in seconds) for image storage (default: 60s)")}, + {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("save log to this file")}, end_option }; @@ -85,4 +87,3 @@ glob_pars *parse_args(int argc, char **argv){ } return &G; } - diff --git a/allsky_logger/cmdlnopts.h b/allsky_logger/cmdlnopts.h index 384478f..1bc488e 100644 --- a/allsky_logger/cmdlnopts.h +++ b/allsky_logger/cmdlnopts.h @@ -34,6 +34,7 @@ typedef struct{ char *server; // server name char *filename; // input file name double min_storage_time;// minimal storage period + char *logfile; // filename of log } glob_pars; diff --git a/allsky_logger/imfunctions.c b/allsky_logger/imfunctions.c index 8f18797..11aeba8 100644 --- a/allsky_logger/imfunctions.c +++ b/allsky_logger/imfunctions.c @@ -104,15 +104,21 @@ rtn: static void mymkdir(char *name){ if(mkdir(name, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)){ - if(errno != EEXIST) + if(errno != EEXIST){ + putlog("error: mkdir(%s)", name); ERR("mkdir()"); + } } + putlog("directory %s created", name); DBG("mkdir(%s)", name); } static void gotodir(char *relpath){ // create directory structure if(chdir(relpath)){ // can't chdir -> test - if(errno != ENOENT) ERR("Can't chdir"); + if(errno != ENOENT){ + putlog("can't chdir(%s)", relpath); + ERR("Can't chdir"); + } }else return; // no such directory -> create it char *p = relpath; @@ -124,7 +130,10 @@ static void gotodir(char *relpath){ // create directory structure } } mymkdir(relpath); - if(-1 == chdir(relpath)) ERR("chdir()"); + if(-1 == chdir(relpath)){ + putlog("can't chdir(%s) to created directory", relpath); + ERR("chdir()"); + } } /** diff --git a/allsky_logger/main.c b/allsky_logger/main.c index 0278c19..92c8ad7 100644 --- a/allsky_logger/main.c +++ b/allsky_logger/main.c @@ -40,6 +40,7 @@ int main(int argc, char **argv){ glob_pars *G = parse_args(argc, argv); if(!G->server) ERRX(_("Please, specify server name")); if(!G->filename) ERRX(_("Please, specify the name of input FITS file")); + if(G->logfile) openlogfile(G->logfile); daemonize(G); return 0; } diff --git a/allsky_logger/socket.c b/allsky_logger/socket.c index 48c2474..17f37e6 100644 --- a/allsky_logger/socket.c +++ b/allsky_logger/socket.c @@ -186,15 +186,27 @@ int watch_fits(char *name){ inotify_rm_watch(fd, wd); wd = -1; } - if(!test_fits(name)) ERRX(_("File %s is not FITS file with 2D image!"), name); - if(fd < 0) + if(!test_fits(name)){ + putlog("File %s is not FITS file with 2D image!", name); + ERRX(_("File %s is not FITS file with 2D image!"), name); + } + if(fd < 0){ fd = inotify_init1(IN_NONBLOCK); - if(fd == -1) ERR("inotify_init1()"); + } + if(fd == -1){ + putlog("inotify_init1() error"); + ERR("inotify_init1()"); + } FILE* f = fopen(name, "r"); - if(!f) ERR("fopen()"); // WTF??? + if(!f){ + putlog("can't open %s", name); + ERR("fopen()"); // WTF??? + } fclose(f); - if((wd = inotify_add_watch(fd, name, IN_CLOSE_WRITE)) < 0) + if((wd = inotify_add_watch(fd, name, IN_CLOSE_WRITE)) < 0){ + putlog("inotify_add_watch() error"); ERR("inotify_add_watch()"); + } DBG("file %s added to inotify", name); return fd; } @@ -204,9 +216,15 @@ int watch_fits(char *name){ */ static void test_path(char *path){ if(path){ - if(chdir(path)) ERR("Can't chdir(%s)", path); + if(chdir(path)){ + putlog("Can't chdir(%s)", path); + ERR("Can't chdir(%s)", path); + } + } + if(access("./", W_OK)){ + putlog("access() error"); + ERR("access()"); } - if(access("./", W_OK)) ERR("access()"); DBG("OK, user can write to given path"); } @@ -239,29 +257,39 @@ static void client_(char *FITSpath, int infd, int sock){ } } DBG("Start polling"); + putlog("Start polling"); while(1){ poll_num = poll(&fds, 1, 1); if(poll_num == -1){ - if (errno == EINTR) - continue; - ERR("poll()"); - return; + if (errno == EINTR) + continue; + putlog("poll() error"); + ERR("poll()"); + return; } if(poll_num > 0){ DBG("changed?"); if(fds.revents & POLLIN){ ssize_t len = read(infd, &buf, sizeof(buf)); if (len == -1 && errno != EAGAIN){ - ERR("read"); + putlog("read() error"); + ERR("read"); }else{ DBG("file changed"); usleep(100000); // wait a little for file changes if(dtime() - lastTstorage > minstoragetime){ DBG("lastT: %.2g, now: %.2g", lastTstorage, dtime()); + putlog("store light frame, %.1f seconds since last storage", dtime()-lastTstorage); + if(!last_good_msrment) putlog("Boltwood's data is absent!"); lastTstorage = dtime(); store_fits(FITSpath, last_good_msrment); - }else if(fits_is_dark(FITSpath)) // save darks nevertheless time + last_good_msrment = NULL; // clear last data + }else if(fits_is_dark(FITSpath)){ // save darks nevertheless time + putlog("dark frame detected, store it"); + if(!last_good_msrment) putlog("Boltwood's data is absent!"); store_fits(FITSpath, last_good_msrment); + last_good_msrment = NULL; // clear last data + } } fds.fd = watch_fits(FITSpath); } @@ -271,14 +299,19 @@ static void client_(char *FITSpath, int infd, int sock){ do{ rlc(offset); ssize_t n = read(sock, &recvBuff[offset], Bufsiz - offset); - if(!n) break; + if(!n){ + putlog("socket disconnected"); + break; + } if(n < 0){ + putlog("read() error"); WARN("read"); break; } offset += n; }while(waittoread(sock)); if(!offset){ + putlog("socket disconnected"); WARN("Socket closed\n"); return; } @@ -303,14 +336,17 @@ void daemonize(glob_pars *G){ minstoragetime = G->min_storage_time; // run fork before socket opening to prevent daemon's death if there's no network #ifndef EBUG - green("Daemonize\n"); - if(daemon(1, 0)) + if(daemon(1, 0)){ + putlog("daemon() error"); ERR("daemon()"); + } while(1){ // guard for dead processes pid_t childpid = 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); WARNX("Child %d died\n", childpid); sleep(1); }else{ @@ -347,6 +383,7 @@ void daemonize(glob_pars *G){ break; // if we get here, we have a successfull connection } if(p == NULL){ + putlog("failed to bind socket"); // looped off the end of the list with no successful bind ERRX("failed to bind socket"); } diff --git a/allsky_logger/usefull_macros.c b/allsky_logger/usefull_macros.c index 334be15..8be27ed 100644 --- a/allsky_logger/usefull_macros.c +++ b/allsky_logger/usefull_macros.c @@ -20,6 +20,7 @@ */ #include "usefull_macros.h" +#include // PATH_MAX /** * function for different purposes that need to know time intervals @@ -383,3 +384,50 @@ int str2double(double *num, const char *str){ 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/allsky_logger/usefull_macros.h b/allsky_logger/usefull_macros.h index 1e2f325..3cc35e6 100644 --- a/allsky_logger/usefull_macros.h +++ b/allsky_logger/usefull_macros.h @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -137,4 +138,6 @@ int write_tty(const uint8_t *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/main.c b/main.c index 5b8fc9c..4a8452b 100644 --- a/main.c +++ b/main.c @@ -20,12 +20,15 @@ */ #include "usefull_macros.h" #include +#include // wait +#include //prctl #include "cmdlnopts.h" #include "socket.h" void signals(int signo){ restore_console(); restore_tty(); + putlog("exit with status %d", signo); exit(signo); } @@ -43,9 +46,26 @@ int main(int argc, char **argv){ 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 try_connect(G->device); - if(check_sensor()) signals(15); // there's not Boltwood sensor connected + if(check_sensor()){ + putlog("no Boltwood's sensors detected"); + signals(15); // there's not Boltwood sensor connected + } if(G->terminal) run_terminal(); else daemonize(G->port); return 0; diff --git a/socket.c b/socket.c index 3ff2c81..1868954 100644 --- a/socket.c +++ b/socket.c @@ -29,8 +29,6 @@ #include // INT_xxx #include // pthread_kill #include // daemon -#include // wait -#include //prctl #include // syscall #define BUFLEN (10240) @@ -276,22 +274,6 @@ static void daemon_(int sock){ */ void daemonize(char *port){ FNAME(); -#ifndef EBUG - 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 int sock = -1; struct addrinfo hints, *res, *p; memset(&hints, 0, sizeof(hints)); diff --git a/term.c b/term.c index 70ae783..8d0722b 100644 --- a/term.c +++ b/term.c @@ -135,12 +135,10 @@ int send_cmd(uint8_t cmd){ void try_connect(char *device){ if(!device) return; uint8_t tmpbuf[4096]; - green(_("Connecting to %s... "), device); fflush(stdout); tty_init(device); read_tty(tmpbuf, 4096); // clear rbuf - green("Ok!"); - printf("\n\n"); + putlog("Connected to %s", device); } // check CRC and return 0 if all OK diff --git a/usefull_macros.c b/usefull_macros.c index 24c6165..8836ab2 100644 --- a/usefull_macros.c +++ b/usefull_macros.c @@ -21,6 +21,7 @@ #include "usefull_macros.h" #include +#include // PATH_MAX /** * function for different purposes that need to know time intervals @@ -389,6 +390,8 @@ int str2double(double *num, const char *str){ } 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 @@ -399,16 +402,29 @@ void openlogfile(char *name){ return; } green(_("Try to open log file %s in append mode\n"), name); - if(!(Flog = fopen(name, "a"))) + if(!(Flog = fopen(name, "a"))){ WARN(_("Can't open log file")); + return; + } + log_open_time = time(NULL); + logname = name; } /** - * Save message to log file + * 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);