/** * Prints a service status into the given buffer. * @param S Service object * @param B StringBuffer object * @param L Status information level * @param V Format version */ static void status_service(Service_T S, StringBuffer_T B, short L, int V) { Event_T E = S->eventlist; if (V == 2) StringBuffer_append(B, "<service name=\"%s\"><type>%d</type>", S->name ? S->name : "", S->type); else StringBuffer_append(B, "<service type=\"%d\"><name>%s</name>", S->type, S->name ? S->name : ""); StringBuffer_append(B, "<collected_sec>%ld</collected_sec>" "<collected_usec>%ld</collected_usec>" "<status>%d</status>" "<status_hint>%d</status_hint>" "<monitor>%d</monitor>" "<monitormode>%d</monitormode>" "<pendingaction>%d</pendingaction>", S->collected.tv_sec, (long)S->collected.tv_usec, S->error, S->error_hint, S->monitor, S->mode, S->doaction); if (S->every.type != EVERY_CYCLE) { StringBuffer_append(B, "<every><type>%d</type>", S->every.type); if (S->every.type == 1) StringBuffer_append(B, "<counter>%d</counter><number>%d</number>", S->every.spec.cycle.counter, S->every.spec.cycle.number); else StringBuffer_append(B, "<cron><![CDATA[%s]]></cron>", S->every.spec.cron); StringBuffer_append(B, "</every>"); } /* if the service is in error state, display first active error message to provide more details */ while (E) { if ((E->state == STATE_FAILED || E->state == STATE_CHANGED) && (S->error & E->id) && E->message) { StringBuffer_append(B, "<status_message><![CDATA[%s]]></status_message>", E->message); break; } E = E->next; } if (L == LEVEL_FULL) { if (Util_hasServiceStatus(S)) { if (S->type == TYPE_FILE || S->type == TYPE_DIRECTORY || S->type == TYPE_FIFO || S->type == TYPE_FILESYSTEM) StringBuffer_append(B, "<mode>%o</mode><uid>%d</uid><gid>%d</gid>", S->inf->st_mode & 07777, (int)S->inf->st_uid, (int)S->inf->st_gid); if (S->type == TYPE_FILE || S->type == TYPE_FIFO || S->type == TYPE_DIRECTORY) StringBuffer_append(B, "<timestamp>%ld</timestamp>", (long)S->inf->timestamp); if (S->type == TYPE_FILE) { StringBuffer_append(B, "<size>%llu</size>", (unsigned long long) S->inf->priv.file.st_size); if (S->checksum) StringBuffer_append(B, "<checksum type=\"%s\">%s</checksum>", checksumnames[S->checksum->type], S->inf->priv.file.cs_sum); } if (S->type == TYPE_FILESYSTEM) { StringBuffer_append(B, "<flags>%d</flags>" "<block>" "<percent>%.1f</percent>" "<usage>%.1f</usage>" "<total>%.1f</total>" "</block>", S->inf->priv.filesystem.flags, S->inf->priv.filesystem.space_percent/10., S->inf->priv.filesystem.f_bsize > 0 ? (float)S->inf->priv.filesystem.space_total / (float)1048576 * (float)S->inf->priv.filesystem.f_bsize : 0, S->inf->priv.filesystem.f_bsize > 0 ? (float)S->inf->priv.filesystem.f_blocks / (float)1048576 * (float)S->inf->priv.filesystem.f_bsize : 0); if (S->inf->priv.filesystem.f_files > 0) { StringBuffer_append(B, "<inode>" "<percent>%.1f</percent>" "<usage>%ld</usage>" "<total>%ld</total>" "</inode>", S->inf->priv.filesystem.inode_percent/10., S->inf->priv.filesystem.inode_total, S->inf->priv.filesystem.f_files); } } if (S->type == TYPE_PROCESS) { StringBuffer_append(B, "<pid>%d</pid>" "<ppid>%d</ppid>" "<uptime>%ld</uptime>", S->inf->priv.process.pid, S->inf->priv.process.ppid, (long)S->inf->priv.process.uptime); if (Run.doprocess) { StringBuffer_append(B, "<children>%d</children>" "<memory>" "<percent>%.1f</percent>" "<percenttotal>%.1f</percenttotal>" "<kilobyte>%ld</kilobyte>" "<kilobytetotal>%ld</kilobytetotal>" "</memory>" "<cpu>" "<percent>%.1f</percent>" "<percenttotal>%.1f</percenttotal>" "</cpu>", S->inf->priv.process.children, S->inf->priv.process.mem_percent/10.0, S->inf->priv.process.total_mem_percent/10.0, S->inf->priv.process.mem_kbyte, S->inf->priv.process.total_mem_kbyte, S->inf->priv.process.cpu_percent/10.0, S->inf->priv.process.total_cpu_percent/10.0); } } if (S->type == TYPE_HOST && S->icmplist) { for (Icmp_T i = S->icmplist; i; i = i->next) { StringBuffer_append(B, "<icmp>" "<type>%s</type>" "<responsetime>%.3f</responsetime>" "</icmp>", icmpnames[i->type], i->is_available ? i->response : -1.); } } if ((S->type == TYPE_HOST || S->type == TYPE_PROCESS) && S-> portlist) { Port_T p; for (p = S->portlist; p; p = p->next) { if (p->family == AF_INET) StringBuffer_append(B, "<port>" "<hostname>%s</hostname>" "<portnumber>%d</portnumber>" "<request>%s</request>" "<protocol>%s</protocol>" "<type>%s</type>" "<responsetime>%.3f</responsetime>" "</port>", p->hostname?p->hostname:"", p->port, p->request?p->request:"", p->protocol->name?p->protocol->name:"", Util_portTypeDescription(p), p->is_available?p->response:-1.); else if (p->family == AF_UNIX) StringBuffer_append(B, "<unix>" "<path>%s</path>" "<protocol>%s</protocol>" "<responsetime>%.3f</responsetime>" "</unix>", p->pathname?p->pathname:"", p->protocol->name?p->protocol->name:"", p->is_available?p->response:-1.); } } if (S->type == TYPE_SYSTEM && Run.doprocess) { StringBuffer_append(B, "<system>" "<load>" "<avg01>%.2f</avg01>" "<avg05>%.2f</avg05>" "<avg15>%.2f</avg15>" "</load>" "<cpu>" "<user>%.1f</user>" "<system>%.1f</system>" #ifdef HAVE_CPU_WAIT "<wait>%.1f</wait>" #endif "</cpu>" "<memory>" "<percent>%.1f</percent>" "<kilobyte>%ld</kilobyte>" "</memory>" "<swap>" "<percent>%.1f</percent>" "<kilobyte>%ld</kilobyte>" "</swap>" "</system>", systeminfo.loadavg[0], systeminfo.loadavg[1], systeminfo.loadavg[2], systeminfo.total_cpu_user_percent > 0 ? systeminfo.total_cpu_user_percent/10. : 0, systeminfo.total_cpu_syst_percent > 0 ? systeminfo.total_cpu_syst_percent/10. : 0, #ifdef HAVE_CPU_WAIT systeminfo.total_cpu_wait_percent > 0 ? systeminfo.total_cpu_wait_percent/10. : 0, #endif systeminfo.total_mem_percent/10., systeminfo.total_mem_kbyte, systeminfo.total_swap_percent/10., systeminfo.total_swap_kbyte); } if (S->type == TYPE_PROGRAM && S->program->started) { StringBuffer_append(B, "<program>" "<started>%lu</started>" "<status>%d</status>" "</program>", (unsigned long)S->program->started, S->program->exitStatus); } } } StringBuffer_append(B, "</service>"); }
/** * Prints a service status into the given buffer. * @param S Service object * @param B StringBuffer object * @param L Status information level * @param V Format version */ static void status_service(Service_T S, StringBuffer_T B, Level_Type L, int V) { if (V == 2) StringBuffer_append(B, "<service name=\"%s\"><type>%d</type>", S->name ? S->name : "", S->type); else StringBuffer_append(B, "<service type=\"%d\"><name>%s</name>", S->type, S->name ? S->name : ""); StringBuffer_append(B, "<collected_sec>%lld</collected_sec>" "<collected_usec>%ld</collected_usec>" "<status>%d</status>" "<status_hint>%d</status_hint>" "<monitor>%d</monitor>" "<monitormode>%d</monitormode>" "<pendingaction>%d</pendingaction>", (long long)S->collected.tv_sec, (long)S->collected.tv_usec, S->error, S->error_hint, S->monitor, S->mode, S->doaction); if (S->every.type != Every_Cycle) { StringBuffer_append(B, "<every><type>%d</type>", S->every.type); if (S->every.type == 1) StringBuffer_append(B, "<counter>%d</counter><number>%d</number>", S->every.spec.cycle.counter, S->every.spec.cycle.number); else StringBuffer_append(B, "<cron>%s</cron>", S->every.spec.cron); StringBuffer_append(B, "</every>"); } if (L == Level_Full) { if (Util_hasServiceStatus(S)) { switch (S->type) { case Service_File: StringBuffer_append(B, "<mode>%o</mode>" "<uid>%d</uid>" "<gid>%d</gid>" "<timestamp>%lld</timestamp>" "<size>%llu</size>", S->inf->priv.file.mode & 07777, (int)S->inf->priv.file.uid, (int)S->inf->priv.file.gid, (long long)S->inf->priv.file.timestamp, (unsigned long long)S->inf->priv.file.size); if (S->checksum) StringBuffer_append(B, "<checksum type=\"%s\">%s</checksum>", checksumnames[S->checksum->type], S->inf->priv.file.cs_sum); break; case Service_Directory: StringBuffer_append(B, "<mode>%o</mode>" "<uid>%d</uid>" "<gid>%d</gid>" "<timestamp>%lld</timestamp>", S->inf->priv.directory.mode & 07777, (int)S->inf->priv.directory.uid, (int)S->inf->priv.directory.gid, (long long)S->inf->priv.directory.timestamp); break; case Service_Fifo: StringBuffer_append(B, "<mode>%o</mode>" "<uid>%d</uid>" "<gid>%d</gid>" "<timestamp>%lld</timestamp>", S->inf->priv.fifo.mode & 07777, (int)S->inf->priv.fifo.uid, (int)S->inf->priv.fifo.gid, (long long)S->inf->priv.fifo.timestamp); break; case Service_Filesystem: StringBuffer_append(B, "<mode>%o</mode>" "<uid>%d</uid>" "<gid>%d</gid>" "<flags>%d</flags>" "<block>" "<percent>%.1f</percent>" "<usage>%.1f</usage>" "<total>%.1f</total>" "</block>", S->inf->priv.filesystem.mode & 07777, (int)S->inf->priv.filesystem.uid, (int)S->inf->priv.filesystem.gid, S->inf->priv.filesystem.flags, S->inf->priv.filesystem.space_percent, S->inf->priv.filesystem.f_bsize > 0 ? (double)S->inf->priv.filesystem.space_total / 1048576. * (double)S->inf->priv.filesystem.f_bsize : 0., S->inf->priv.filesystem.f_bsize > 0 ? (double)S->inf->priv.filesystem.f_blocks / 1048576. * (double)S->inf->priv.filesystem.f_bsize : 0.); if (S->inf->priv.filesystem.f_files > 0) { StringBuffer_append(B, "<inode>" "<percent>%.1f</percent>" "<usage>%lld</usage>" "<total>%lld</total>" "</inode>", S->inf->priv.filesystem.inode_percent, S->inf->priv.filesystem.inode_total, S->inf->priv.filesystem.f_files); } break; case Service_Net: StringBuffer_append(B, "<link>" "<state>%d</state>" "<speed>%lld</speed>" "<duplex>%d</duplex>" "<download>" "<packets>" "<now>%lld</now>" "<total>%lld</total>" "</packets>" "<bytes>" "<now>%lld</now>" "<total>%lld</total>" "</bytes>" "<errors>" "<now>%lld</now>" "<total>%lld</total>" "</errors>" "</download>" "<upload>" "<packets>" "<now>%lld</now>" "<total>%lld</total>" "</packets>" "<bytes>" "<now>%lld</now>" "<total>%lld</total>" "</bytes>" "<errors>" "<now>%lld</now>" "<total>%lld</total>" "</errors>" "</upload>" "</link>", Link_getState(S->inf->priv.net.stats), Link_getSpeed(S->inf->priv.net.stats), Link_getDuplex(S->inf->priv.net.stats), Link_getPacketsInPerSecond(S->inf->priv.net.stats), Link_getPacketsInTotal(S->inf->priv.net.stats), Link_getBytesInPerSecond(S->inf->priv.net.stats), Link_getBytesInTotal(S->inf->priv.net.stats), Link_getErrorsInPerSecond(S->inf->priv.net.stats), Link_getErrorsInTotal(S->inf->priv.net.stats), Link_getPacketsOutPerSecond(S->inf->priv.net.stats), Link_getPacketsOutTotal(S->inf->priv.net.stats), Link_getBytesOutPerSecond(S->inf->priv.net.stats), Link_getBytesOutTotal(S->inf->priv.net.stats), Link_getErrorsOutPerSecond(S->inf->priv.net.stats), Link_getErrorsOutTotal(S->inf->priv.net.stats)); break; case Service_Process: StringBuffer_append(B, "<pid>%d</pid>" "<ppid>%d</ppid>" "<uid>%d</uid>" "<euid>%d</euid>" "<gid>%d</gid>" "<uptime>%lld</uptime>", S->inf->priv.process.pid, S->inf->priv.process.ppid, S->inf->priv.process.uid, S->inf->priv.process.euid, S->inf->priv.process.gid, (long long)S->inf->priv.process.uptime); if (Run.flags & Run_ProcessEngineEnabled) { StringBuffer_append(B, "<threads>%d</threads>" "<children>%d</children>" "<memory>" "<percent>%.1f</percent>" "<percenttotal>%.1f</percenttotal>" "<kilobyte>%llu</kilobyte>" "<kilobytetotal>%llu</kilobytetotal>" "</memory>" "<cpu>" "<percent>%.1f</percent>" "<percenttotal>%.1f</percenttotal>" "</cpu>", S->inf->priv.process.threads, S->inf->priv.process.children, S->inf->priv.process.mem_percent, S->inf->priv.process.total_mem_percent, (unsigned long long)((double)S->inf->priv.process.mem / 1024.), // Send as kB for backward compatibility (unsigned long long)((double)S->inf->priv.process.total_mem / 1024.), // Send as kB for backward compatibility S->inf->priv.process.cpu_percent, S->inf->priv.process.total_cpu_percent); } break; default: break; } for (Icmp_T i = S->icmplist; i; i = i->next) { StringBuffer_append(B, "<icmp>" "<type>%s</type>" "<responsetime>%.6f</responsetime>" "</icmp>", icmpnames[i->type], i->is_available == Connection_Ok ? i->response / 1000. : -1.); // We send the response time in [s] for backward compatibility (with microseconds precision) } for (Port_T p = S->portlist; p; p = p->next) { StringBuffer_append(B, "<port>" "<hostname>%s</hostname>" "<portnumber>%d</portnumber>" "<request><![CDATA[%s]]></request>" "<protocol>%s</protocol>" "<type>%s</type>" "<responsetime>%.6f</responsetime>" "</port>", p->hostname ? p->hostname : "", p->target.net.port, Util_portRequestDescription(p), p->protocol->name ? p->protocol->name : "", Util_portTypeDescription(p), p->is_available == Connection_Ok ? p->response / 1000. : -1.); // We send the response time in [s] for backward compatibility (with microseconds precision) } for (Port_T p = S->socketlist; p; p = p->next) { StringBuffer_append(B, "<unix>" "<path>%s</path>" "<protocol>%s</protocol>" "<responsetime>%.6f</responsetime>" "</unix>", p->target.unix.pathname ? p->target.unix.pathname : "", p->protocol->name ? p->protocol->name : "", p->is_available == Connection_Ok ? p->response / 1000. : -1.); // We send the response time in [s] for backward compatibility (with microseconds precision) } if (S->type == Service_System && (Run.flags & Run_ProcessEngineEnabled)) { StringBuffer_append(B, "<system>" "<load>" "<avg01>%.2f</avg01>" "<avg05>%.2f</avg05>" "<avg15>%.2f</avg15>" "</load>" "<cpu>" "<user>%.1f</user>" "<system>%.1f</system>" #ifdef HAVE_CPU_WAIT "<wait>%.1f</wait>" #endif "</cpu>" "<memory>" "<percent>%.1f</percent>" "<kilobyte>%llu</kilobyte>" "</memory>" "<swap>" "<percent>%.1f</percent>" "<kilobyte>%llu</kilobyte>" "</swap>" "</system>", systeminfo.loadavg[0], systeminfo.loadavg[1], systeminfo.loadavg[2], systeminfo.total_cpu_user_percent > 0. ? systeminfo.total_cpu_user_percent : 0., systeminfo.total_cpu_syst_percent > 0. ? systeminfo.total_cpu_syst_percent : 0., #ifdef HAVE_CPU_WAIT systeminfo.total_cpu_wait_percent > 0. ? systeminfo.total_cpu_wait_percent : 0., #endif systeminfo.total_mem_percent, (unsigned long long)((double)systeminfo.total_mem / 1024.), // Send as kB for backward compatibility systeminfo.total_swap_percent, (unsigned long long)((double)systeminfo.total_swap / 1024.)); // Send as kB for backward compatibility } if (S->type == Service_Program && S->program->started) { StringBuffer_append(B, "<program>" "<started>%lld</started>" "<status>%d</status>" "<output><![CDATA[", (long long)S->program->started, S->program->exitStatus); _escapeCDATA(B, StringBuffer_toString(S->program->output)); StringBuffer_append(B, "]]></output>" "</program>"); } } } StringBuffer_append(B, "</service>"); }