/* syslog for the trli project. This program does not write to disk. All in memory. */ #include #include #include #include #include #include #include #include #include #include #include "trlitool.h" using namespace std; enum CONNECT_TYPE { TYPE_NONE, TYPE_CONTROL, TYPE_CLIENT }; struct HANDLE_INFO: public ARRAY_OBJ{ CONNECT_TYPE type; REQUEST_INFO req; STREAMP_BUF buf; }; #include "proto/trli_syslog_control.protoh" struct LOGLINE{ string line; bool is_error = false; LOGLINE(const string &_line, bool _is_error) :line(_line),is_error(_is_error) {} }; static void copy_lines (const deque &logs, unsigned offset, unsigned nblines, vector &tb, bool only_errors) { size_t size = logs.size(); if (offset < size && nblines > 0){ for (auto l = logs.begin() + offset; l != logs.end() && nblines > 0; l++, nblines--){ if (!only_errors || l->is_error) tb.push_back(l->line); } } } int main (int argc, char *argv[]) { glocal const char *control = "/var/run/blackhole/trli-syslog.sock"; glocal const char *logport = "/dev/trli.log"; glocal const char *pidfile = "/var/run/trli-syslog.pid"; glocal const char *user = "trli"; glocal bool daemon = false; glocal int ret = -1; glocal.ret = (argc,argv); setproginfo ("trli-syslog",VERSION,"Syslog for trli applications"); setarg ('c',"control","Unix socket to control the application",glocal.control,false); setarg ('l',"logport","Unix socket used to retrieve log messages",glocal.logport,false); setgrouparg ("Daemon mode"); setarg (' ',"daemon","Runs in background",glocal.daemon,false); setarg (' ',"user","Runs as this user",glocal.user,false); setarg (' ',"pidfile","PID file",glocal.pidfile,false); int ret = -1; glocal time_t lastmsg = (time_t)0; glocal time_t lasterror = (time_t)0; glocal unsigned nberrors = 0; glocal deque logs; glocal function append_line; glocal.append_line = [&](const char *line, int len){ string tmp(line,len); strip_end (tmp); if (tmp.size() > 0){ glocal.lastmsg = time(NULL); bool is_error = false; if (strncmp(line,"<11>",4)==0){ glocal.nberrors++; glocal.lasterror = glocal.lastmsg; is_error = true; } glocal.logs.emplace_back(tmp,is_error); if (glocal.logs.size() > 1000) glocal.logs.pop_front(); } }; (string_f("unix:%s",glocal.logport),5); if (strncmp(info.port,"unix:",5)==0i){ const char *port5 = info.port+5; if (strcmp(port5,glocal.logport)==0){ HANDLE_INFO *n = new HANDLE_INFO; n->type = TYPE_CLIENT; info.data = n; }else if (strcmp(port5,glocal.control)==0){ HANDLE_INFO *n = new HANDLE_INFO; n->type = TYPE_CONTROL; info.data = n; }else{ tlmp_error ("Unknown connection\n"); endclient = true; } }else{ tlmp_error ("Unknown connection\n"); endclient = true; } HANDLE_INFO *c = (HANDLE_INFO*)info.data; if (c->type == TYPE_CLIENT){ (c->buf,"",0); const char *line = (const char *)buf; glocal.append_line(line,len); return len; } HANDLE_INFO *c = (HANDLE_INFO*)info.data; if (c->type == TYPE_CONTROL){ (this,c->req,line,info.linelen, endserver, endclient, no,c); vector tb; tb.push_back(string_f("Version: %s",VERSION)); DATEASC date; fdpass_asctime (glocal.lastmsg,date); tb.push_back(string_f("last message: %s",date.buf)); fdpass_asctime (glocal.lasterror,date); tb.push_back(string_f("last error: %s",date.buf)); tb.push_back(string_f("errors: %u",glocal.nberrors)); rep_status(tb); rep_report(VERSION,glocal.nberrors,glocal.lastmsg,glocal.lasterror); glocal.nberrors = 0; glocal.lasterror = (time_t)0; glocal.logs.clear(); vector tb; size_t size = glocal.logs.size(); copy_lines (glocal.logs,offset,nblines,tb,false); rep_logs (tb,size); vector tb; size_t size = glocal.logs.size(); copy_lines (glocal.logs,offset,nblines,tb,true); rep_logerrs (tb,size); vector tb; size_t size = glocal.logs.size(); unsigned nblines = 10; unsigned offset = size-10; if (size < 10){ offset = 0; nblines = size; } copy_lines (glocal.logs,offset,nblines,tb,false); rep_tail (tb,size,glocal.lastmsg); endserver = true; if (on){ debug_seton(); }else{ debug_setoff(); } debug_setfdebug (filename); endclient = true; }else if (c->type == TYPE_CLIENT){ //string tmp; //for (int i=0; i(c->buf,line,info.linelen); int ret = 0; const char *line = (const char *)buf; const char *pt = line; const char *endbuf = line + len; while (pt < endbuf){ if (*pt == '\0'){ ret = (pt - line)+1; break; } pt++; } if (ret > 0){ glocal.append_line (line,ret-1); } return ret; } if (o.is_ok()){ if (fdpass_setcontrol(o,glocal.control,glocal.user)==-1){ tlmp_error ("Can't setup control socket %s, ending\n",glocal.control); exit (-1); } o.setrawmode (true); ret = 0; if (glocal.daemon){ daemon_init (glocal.pidfile,glocal.user); } o.loop(); }else{ tlmp_error ("Can't bind to %s (%s)\n",glocal.logport,strerror(errno)); } return ret; return glocal.ret; }