void log_list_thread(void) { char buf[LOG_BUF_SIZE]; int last_count=ll_count(log_list), count, grow_count=0, write_count; do { LL_ITER it = ll_iter_create(log_list); struct s_log *log; write_count = 0; while ((log=ll_iter_next_remove(&it))) { int8_t do_flush = ll_count(log_list) == 0; //flush on writing last element cs_strncpy(buf, log->txt, LOG_BUF_SIZE); if (log->direct_log) cs_write_log(buf, do_flush); else write_to_log(buf, log, do_flush); free(log->txt); free(log); //If list is faster growing than we could write to file, drop list: write_count++; if (write_count%10000 == 0) { //check every 10000 writes: count = ll_count(log_list); if (count > last_count) { grow_count++; if (grow_count > 5) { //5 times still growing cs_write_log("------------->logging temporary disabled (30s) - too much data!\n", 1); cfg.disablelog = 1; ll_iter_reset(&it); while ((log=ll_iter_next_remove(&it))) { //clear log free(log->txt); free(log); } cs_sleepms(30*1000); cfg.disablelog = 0; grow_count = 0; last_count = 0; break; } } else grow_count = 0; last_count = count; } } cs_sleepms(250); } while(1); }
void log_list_thread(void) { char buf[LOG_BUF_SIZE]; log_running = 1; set_thread_name(__func__); do { log_list_queued = 0; LL_ITER it = ll_iter_create(log_list); struct s_log *log; while((log = ll_iter_next_remove(&it))) { int8_t do_flush = ll_count(log_list) == 0; //flush on writing last element cs_strncpy(buf, log->txt, LOG_BUF_SIZE); if(log->direct_log) { cs_write_log(buf, do_flush); } else { write_to_log(buf, log, do_flush); } NULLFREE(log->txt); NULLFREE(log); } if(!log_list_queued) // The list is empty, sleep until new data comes in and we are woken up sleepms_on_cond(&log_thread_sleep_cond_mutex, &log_thread_sleep_cond, 60 * 1000); } while(log_running); ll_destroy(log_list); log_list = NULL; }
static void cs_write_log_int(char *txt) { if(exit_oscam == 1) { cs_write_log(txt, 1); } else { struct s_log * log = cs_malloc(&log, sizeof(struct s_log), 0); log->txt = strnew(txt); log->header_len = 0; log->direct_log = 1; ll_append(log_list, log); } }
static void log_list_add(struct s_log *log) { int32_t count = ll_count(log_list); log_list_queued++; if(count < MAX_LOG_LIST_BACKLOG) { ll_append(log_list, log); } else // We have too much backlog { NULLFREE(log->txt); NULLFREE(log); cs_write_log("-------------> Too much data in log_list, dropping log message.\n", 1); } pthread_cond_signal(&log_thread_sleep_cond); }
static void cs_write_log_int(char *txt) { if(exit_oscam == 1) { cs_write_log(txt, 1); } else { char *newtxt = cs_strdup(txt); if (!newtxt) return; struct s_log *log; if (!cs_malloc(&log, sizeof(struct s_log))) { free(newtxt); return; } log->txt = newtxt; log->header_len = 0; log->direct_log = 1; ll_append(log_list, log); } }
static void log_list_add(struct s_log *log) { if(logStarted == 0) { return; } int32_t count = ll_count(log_list); log_list_queued++; if(count < MAX_LOG_LIST_BACKLOG) { ll_append(log_list, log); } else // We have too much backlog { NULLFREE(log->txt); NULLFREE(log); cs_write_log("-------------> Too much data in log_list, dropping log message.\n", 1, 0, 0); } SAFE_COND_SIGNAL_NOLOG(&log_thread_sleep_cond); }
void log_list_thread() { char buf[LOG_BUF_SIZE]; while (1) { LL_ITER it = ll_iter_create(log_list); struct s_log *log; while ((log=ll_iter_next_remove(&it))) { int8_t do_flush = ll_count(log_list) == 0; //flush on writing last element cs_strncpy(buf, log->txt, LOG_BUF_SIZE); if (log->direct_log) cs_write_log(buf, do_flush); else write_to_log(buf, log, do_flush); free(log->txt); free(log); } cs_sleepms(50); } }
static void cs_write_log_int(char *txt) { if(exit_oscam == 1) { cs_write_log(txt, 1, 0, 0); } else { char *newtxt = cs_strdup(txt); if(!newtxt) { return; } struct s_log *log; if(!cs_malloc(&log, sizeof(struct s_log))) { NULLFREE(newtxt); return; } log->txt = newtxt; log->header_len = 0; log->direct_log = 1; log_list_add(log); } }
static void write_to_log(char *txt, struct s_log *log, int8_t do_flush) { char sbuf[16]; #ifdef CS_ANTICASC if (!strncmp(txt + log->header_len, "acasc:", 6)) { strcat(txt, "\n"); switch_log(cfg.ac_logfile, &fpa, ac_init_log); if (fpa) { fputs(txt + 8, fpa); if (do_flush) fflush(fpa); } } else #endif { if (cfg.logtosyslog) syslog(LOG_INFO, "%s", txt+24); strcat(txt, "\n"); } cs_write_log(txt + 8, do_flush); #if defined(WEBIF) || defined(MODULE_MONITOR) if (loghist && exit_oscam != 1) { char *usrtxt = log->cl_text; char *target_ptr = NULL; int32_t target_len = strlen(usrtxt) + (strlen(txt) - 8) + 1; cs_writelock(&loghistory_lock); char *lastpos = loghist + (cfg.loghistorysize) - 1; if(loghist + target_len + 1 >= lastpos){ strncpy(txt + 39, "Log entry too long!", strlen(txt) - 39); // we can assume that the min loghistorysize is always 1024 so we don't need to check if this new string fits into it! target_len = strlen(usrtxt) + (strlen(txt) - 8) + 1; } if (!loghistptr) loghistptr = loghist; if (loghistptr + target_len + 1 > lastpos) { *loghistptr='\0'; loghistptr=loghist + target_len + 1; *loghistptr='\0'; target_ptr=loghist; } else { target_ptr = loghistptr; loghistptr=loghistptr + target_len + 1; *loghistptr='\0'; } cs_writeunlock(&loghistory_lock); snprintf(target_ptr, target_len + 1, "%s\t%s", usrtxt, txt + 8); } #endif struct s_client *cl; for (cl=first_client; cl ; cl=cl->next) { if ((cl->typ == 'm') && (cl->monlvl>0) && cl->log) //this variable is only initialized for cl->typ = 'm' { if (cl->monlvl<2) { if (log->cl_typ != 'c' && log->cl_typ != 'm') continue; if (log->cl_usr && cl->account && strcmp(log->cl_usr, cl->account->usr)) continue; } snprintf(sbuf, sizeof(sbuf), "%03d", cl->logcounter); cl->logcounter = (cl->logcounter+1) % 1000; memcpy(txt + 4, sbuf, 3); #ifdef MODULE_MONITOR monitor_send_idx(cl, txt); #endif } } }
static void write_to_log(char *txt, struct s_log *log, int8_t do_flush) { if(logStarted == 0) { return; } (void)log; // Prevent warning when WEBIF, MODULE_MONITOR and CS_ANTICASC are disabled // anticascading messages go to their own log if (!anticasc_logging(txt + log->header_date_offset)) { if(cfg.logtosyslog) { syslog(LOG_INFO, "%s", txt + log->header_info_offset); } if (cfg.sysloghost != NULL && syslog_socket != -1) { char tmp[128+LOG_BUF_SIZE]; static char hostname[64]; static uint8_t have_hostname = 0; time_t walltime; struct tm lt; char timebuf[32]; if(!have_hostname) { if(gethostname(hostname, 64) != 0) { cs_strncpy(hostname, "unknown", 64); } have_hostname = 1; } walltime = cs_time(); localtime_r(&walltime, <); if(strftime(timebuf, 32, "%b %d %H:%M:%S", <) == 0) { cs_strncpy(timebuf, "unknown", 32); } snprintf(tmp, sizeof(tmp), "%s %s oscam[%u]: %s", timebuf, hostname, getpid(), txt + log->header_info_offset); sendto(syslog_socket, tmp, strlen(tmp), 0, (struct sockaddr*) &syslog_addr, sizeof(syslog_addr)); } } strcat(txt, "\n"); cs_write_log(txt, do_flush, log->header_date_offset, log->header_time_offset); #if defined(WEBIF) || defined(MODULE_MONITOR) if(loghist && !exit_oscam && cfg.loghistorysize) { char *usrtxt = log->cl_text; char *target_ptr = NULL; int32_t target_len = strlen(usrtxt) + strlen(txt+log->header_date_offset) + 1; cs_writelock_nolog(__func__, &loghistory_lock); char *lastpos = loghist + (cfg.loghistorysize) - 1; if(loghist + target_len + 1 >= lastpos) { // we can assume that the min loghistorysize is always 1024 so we don't need to check if this new string fits into it! strncpy(txt + log->header_len, "Log entry too long!", strlen(txt) - log->header_len); target_len = strlen(usrtxt) + strlen(txt+log->header_date_offset) + 1; } if(!loghistptr) { loghistptr = loghist; } if(loghistptr + target_len + 1 > lastpos) { *loghistptr = '\0'; loghistptr = loghist + target_len + 1; *loghistptr = '\0'; target_ptr = loghist; } else { target_ptr = loghistptr; loghistptr = loghistptr + target_len + 1; *loghistptr = '\0'; } ++counter; snprintf(target_ptr, target_len + 1, "%s\t%s", usrtxt, txt + log->header_date_offset); ull2b_buf(counter, (uchar *)(loghistid + ((target_ptr-loghist)/3))); cs_writeunlock_nolog(__func__, &loghistory_lock); } #endif #if defined(MODULE_MONITOR) char sbuf[16]; struct s_client *cl; for(cl = first_client; cl ; cl = cl->next) { if((cl->typ == 'm') && (cl->monlvl > 0) && cl->log) //this variable is only initialized for cl->typ = 'm' { if(cl->monlvl < 2) { if(log->cl_typ != 'c' && log->cl_typ != 'm') { continue; } if(log->cl_usr && cl->account && strcmp(log->cl_usr, cl->account->usr)) { continue; } } if(log->header_len > 0) { snprintf(sbuf, sizeof(sbuf), "%03d", cl->logcounter); cl->logcounter = (cl->logcounter + 1) % 1000; memcpy(txt + log->header_logcount_offset, sbuf, 3); monitor_send_idx(cl, txt); } else { char tmp_log[8+LOG_BUF_SIZE]; snprintf(tmp_log, sizeof(tmp_log), "[LOG%03d]%s", cl->logcounter, txt); cl->logcounter = (cl->logcounter + 1) % 1000; monitor_send_idx(cl, tmp_log); } } } #endif }