int main(int argc, char** argv) { try { //std::string strLog = QDir::homePath().toStdString(); std::string strLog = QDir::tempPath().toStdString(); strLog += "/takin.log"; std::ofstream ofstrLog(strLog, std::ios_base::out|std::ios_base::app); if(add_logfile(&ofstrLog, 1)) tl::log_info("Logging to file \"", strLog, "\"."); tl::log_info("Starting up Takin version ", TAKIN_VER, "."); tl::log_debug("Using ", sizeof(t_real_glob)*8, " bit ", tl::get_typename<t_real_glob>(), "s as internal data type."); #if defined Q_WS_X11 && !defined NO_3D XInitThreads(); QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); #endif // qt needs to be able to copy these structs when emitting signals from a different thread qRegisterMetaType<TriangleOptions>("TriangleOptions"); qRegisterMetaType<CrystalOptions>("CrystalOptions"); qRegisterMetaType<std::string>("std::string"); qRegisterMetaType<CacheVal>("CacheVal"); std::unique_ptr<QApplication> app(new QApplication(argc, argv)); std::setlocale(LC_ALL, "C"); std::locale::global(std::locale::classic()); QLocale::setDefault(QLocale::English); QCoreApplication::setApplicationName("Takin"); QCoreApplication::setApplicationVersion(TAKIN_VER); std::string strApp = QCoreApplication::applicationDirPath().toStdString(); tl::log_info("Application path: ", strApp); add_resource_path(strApp); add_resource_path(strApp + "/.."); add_resource_path(strApp + "/resources"); add_resource_path(strApp + "/Resources"); add_resource_path(strApp + "/../resources"); add_resource_path(strApp + "/../Resources"); // ------------------------------------------------------------ // tlibs version check tl::log_info("Using tLibs version ", tl::get_tlibs_version(), "."); if(!tl::check_tlibs_version(TLIBS_VERSION)) { tl::log_crit("Version mismatch in tLibs. Please recompile."); tl::log_crit("tLibs versions: library: ", tl::get_tlibs_version(), ", headers: ", TLIBS_VERSION, "."); QMessageBox::critical(0, "Takin - Error", "Broken build: Mismatch in tlibs version."); return -1; } // check tables g_bHasScatlens = (find_resource("res/scatlens.xml") != ""); g_bHasFormfacts = (find_resource("res/ffacts.xml") != ""); g_bHasMagFormfacts = (find_resource("res/magffacts.xml") != ""); g_bHasSpaceGroups = (find_resource("res/sgroups.xml") != ""); if(!g_bHasScatlens) { const char* pcErr = "Scattering length table could not be found." TAKIN_CHECK; tl::log_err(pcErr); QMessageBox::critical(0, "Takin - Error", pcErr); return -1; } if(!g_bHasFormfacts) { const char* pcErr = "Atomic form factor coefficient table could not be found." TAKIN_CHECK; tl::log_err(pcErr); QMessageBox::critical(0, "Takin - Error", pcErr); return -1; } if(!g_bHasMagFormfacts) { const char* pcErr = "Magnetic form factor coefficient table could not be found." TAKIN_CHECK; tl::log_err(pcErr); QMessageBox::critical(0, "Takin - Error", pcErr); return -1; } if(!g_bHasSpaceGroups) { const char* pcErr = "Space group table could not be found!" TAKIN_CHECK; tl::log_err(pcErr); QMessageBox::critical(0, "Takin - Error", pcErr); return -1; } tl::init_spec_chars(); // check if icons are available if(find_resource("res/document-new.svg") == "") { const char* pcErr = "Takin resources could not be found!" TAKIN_CHECK; tl::log_err(pcErr); QMessageBox::critical(0, "Takin - Error", pcErr); return -1; } // ------------------------------------------------------------ #ifdef IS_EXPERIMENTAL_BUILD { QSettings settings("tobis_stuff", "takin"); int iPrevDaysSinceEpoch = 0; if(settings.contains("debug/last_warned")) iPrevDaysSinceEpoch = settings.value("debug/last_warned").toInt(); int iDaysSinceEpoch = tl::epoch_dur<tl::t_dur_days<int>>().count(); std::string strExp = "This " BOOST_PLATFORM " version of Takin is still experimental, " "does not include all features and may show unexpected behaviour. Please report " "bugs to [email protected]. Thanks!"; tl::log_warn(strExp); //tl::log_debug("Days since last warning: ", iDaysSinceEpoch-iPrevDaysSinceEpoch, "."); // show warning message box every 5 days if(iDaysSinceEpoch - iPrevDaysSinceEpoch > 5) { QMessageBox::warning(0, "Takin", strExp.c_str()); settings.setValue("debug/last_warned", iDaysSinceEpoch); } } #endif std::unique_ptr<TazDlg> dlg(new TazDlg(0)); if(argc > 1) dlg->Load(argv[1]); dlg->show(); int iRet = app->exec(); // ------------------------------------------------------------ tl::deinit_spec_chars(); tl::log_info("Shutting down Takin."); add_logfile(&ofstrLog, 0); return iRet; } catch(const std::system_error& err) { sys_err(err); } catch(const boost::system::system_error& err) { sys_err(err); } catch(const std::exception& ex) { tl::log_crit("Exception: ", ex.what()); tl::log_backtrace(); } return -1; }
/****************************************************************************** * * * Function: process_logrt * * * * Purpose: Get message from logfile with rotation * * * * Parameters: filename - logfile name (regular expression with a path) * * lastlogsize - offset for message * * mtime - last modification time of the file * * value - pointer for logged message * * * * Return value: returns SUCCEED on successful reading, * * FAIL on other cases * * * * Author: Dmitry Borovikov (logrotation) * * * * Comments: * * This function allocates memory for 'value', because use zbx_free. * * Return SUCCEED and NULL value if end of file received. * * * ******************************************************************************/ int process_logrt(char *filename, long *lastlogsize, int *mtime, char **value, const char *encoding) { int i = 0, nbytes, ret = FAIL, logfiles_num = 0, logfiles_alloc = 0, fd = 0, length = 0, j = 0; char buffer[MAX_BUFFER_LEN], *directory = NULL, *format = NULL, *logfile_candidate = NULL; struct stat file_buf; struct st_logfile *logfiles = NULL; #ifdef _WINDOWS char *find_path = NULL; intptr_t find_handle; struct _finddata_t find_data; #else DIR *dir = NULL; struct dirent *d_ent = NULL; #endif zabbix_log(LOG_LEVEL_DEBUG, "In process_logrt() filename [%s] lastlogsize [%li] mtime [%d]", filename, *lastlogsize, *mtime); /* splitting filename */ if (SUCCEED != split_filename(filename, &directory, &format)) { zabbix_log(LOG_LEVEL_WARNING, "filename [%s] does not contain a valid directory and/or format", filename); return FAIL; } #ifdef _WINDOWS /* try to "open" Windows directory */ find_path = zbx_dsprintf(find_path, "%s*", directory); find_handle = _findfirst((const char *)find_path, &find_data); if (-1 == find_handle) { zabbix_log(LOG_LEVEL_DEBUG, "cannot get entries from [%s] directory: %s", directory, zbx_strerror(errno)); zbx_free(directory); zbx_free(format); zbx_free(find_path); return FAIL; } zbx_free(find_path); zabbix_log(LOG_LEVEL_DEBUG, "we are in the Windows directory reading cycle"); do { logfile_candidate = zbx_dsprintf(logfile_candidate, "%s%s", directory, find_data.name); if (-1 == zbx_stat(logfile_candidate, &file_buf) || !S_ISREG(file_buf.st_mode)) { zabbix_log(LOG_LEVEL_DEBUG, "cannot process read entry [%s]", logfile_candidate); } else if (NULL != zbx_regexp_match(find_data.name, format, &length)) { zabbix_log(LOG_LEVEL_DEBUG, "adding the file [%s] to logfiles", logfile_candidate); add_logfile(&logfiles, &logfiles_alloc, &logfiles_num, find_data.name, (int)file_buf.st_mtime); } else zabbix_log(LOG_LEVEL_DEBUG, "[%s] does not match [%s]", logfile_candidate, format); zbx_free(logfile_candidate); } while (0 == _findnext(find_handle, &find_data)); #else /* _WINDOWS */ if (NULL == (dir = opendir(directory))) { zabbix_log(LOG_LEVEL_WARNING, "cannot open directory [%s] for reading: %s", directory, zbx_strerror(errno)); zbx_free(directory); zbx_free(format); return FAIL; } zabbix_log(LOG_LEVEL_DEBUG, "we are in the *nix directory reading cycle"); while (NULL != (d_ent = readdir(dir))) { logfile_candidate = zbx_dsprintf(logfile_candidate, "%s%s", directory, d_ent->d_name); if (-1 == zbx_stat(logfile_candidate, &file_buf) || !S_ISREG(file_buf.st_mode)) { zabbix_log(LOG_LEVEL_DEBUG, "cannot process read entry [%s]", logfile_candidate); } else if (NULL != zbx_regexp_match(d_ent->d_name, format, &length)) { zabbix_log(LOG_LEVEL_DEBUG, "adding the file [%s] to logfiles", logfile_candidate); add_logfile(&logfiles, &logfiles_alloc, &logfiles_num, d_ent->d_name, (int)file_buf.st_mtime); } else zabbix_log(LOG_LEVEL_DEBUG, "[%s] does not match [%s]", logfile_candidate, format); zbx_free(logfile_candidate); } #endif /*_WINDOWS*/ /* find the oldest file that match */ for (i = 0; i < logfiles_num; i++) { if (logfiles[i].mtime < *mtime) continue; /* not interested in mtimes less than the given mtime */ else break; /* the first occurrence is found */ } /* escaping those with the same mtime, taking the latest one (without exceptions!) */ for (j = i + 1; j < logfiles_num; j++) { if (logfiles[j].mtime == logfiles[i].mtime) i = j; /* moving to the newer one */ else break; /* all next mtimes are bigger */ } /* if all mtimes are less than the given one, take the latest file from existing ones */ if (0 < logfiles_num && i == logfiles_num) i = logfiles_num - 1; /* i cannot be bigger than logfiles_num */ /* processing matched or moving to the newer one and repeating the cycle */ for ( ; i < logfiles_num; i++) { logfile_candidate = zbx_dsprintf(logfile_candidate, "%s%s", directory, logfiles[i].filename); if (0 != zbx_stat(logfile_candidate, &file_buf))/* situation could have changed */ { zabbix_log(LOG_LEVEL_WARNING, "cannot stat [%s]: %s", logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } *mtime = (int)file_buf.st_mtime; /* must contain the latest mtime as possible */ if (file_buf.st_size < *lastlogsize) { *lastlogsize = 0; /* maintain backward compatibility */ } if (-1 == (fd = zbx_open(logfile_candidate, O_RDONLY))) { zabbix_log(LOG_LEVEL_WARNING, "cannot open [%s]: %s", logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } if ((off_t)-1 != lseek(fd, (off_t)*lastlogsize, SEEK_SET)) { if (-1 != (nbytes = zbx_read(fd, buffer, sizeof(buffer), encoding))) { if (0 != nbytes) { *lastlogsize += nbytes; *value = convert_to_utf8(buffer, nbytes, encoding); zbx_rtrim(*value, "\r\n "); ret = SUCCEED; break; /* return at this point */ } else /* EOF is reached, but there can be other files to try reading from */ { if (i == logfiles_num - 1) { ret = SUCCEED; /* EOF of the the most current file is reached */ break; } else { zbx_free(logfile_candidate); *lastlogsize = 0; close(fd); continue; /* try to read from more current file */ } } } else /* cannot read from the file */ { zabbix_log(LOG_LEVEL_WARNING, "cannot read from [%s]: %s", logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } } else /* cannot position in the file */ { zabbix_log(LOG_LEVEL_WARNING, "cannot set position to [%li] for [%s]: %s", *lastlogsize, logfile_candidate, zbx_strerror(errno)); break; /* must return, situation could have changed */ } } /* trying to read from logfiles */ if (0 == logfiles_num) { zabbix_log(LOG_LEVEL_WARNING, "there are no files matching [%s] in [%s]", format, directory); } free_logfiles(&logfiles, &logfiles_alloc, &logfiles_num); if (0 != fd && -1 == close(fd)) { zabbix_log(LOG_LEVEL_WARNING, "could not close the file [%s]: %s", logfile_candidate, zbx_strerror(errno)); } #ifdef _WINDOWS if (0 != find_handle && -1 == _findclose(find_handle)) { zabbix_log(LOG_LEVEL_WARNING, "could not close the find directory handle: %s", zbx_strerror(errno)); } #else if (NULL != dir && -1 == closedir(dir)) { zabbix_log(LOG_LEVEL_WARNING, "could not close directory [%s]: %s", directory, zbx_strerror(errno)); } #endif zbx_free(logfile_candidate); zbx_free(directory); zbx_free(format); return ret; }