new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / shared / read-agents.c
old mode 100755 (executable)
new mode 100644 (file)
index 2164da4..43c40f8
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/shared/read-agents.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All right reserved.
  *
 #include "read-agents.h"
 #include "os_net/os_net.h"
 
+#ifndef WIN32
+static int _do_print_attrs_syscheck(const char *prev_attrs, const char *attrs, int csv_output, cJSON *json_output,
+                                    int is_win, int number_of_changes) __attribute__((nonnull(2)));
+static int _do_print_file_syscheck(FILE *fp, const char *fname, int update_counter,
+                                   int csv_output, cJSON *json_output) __attribute__((nonnull(1)));
+static int _do_print_syscheck(FILE *fp, int all_files, int csv_output, cJSON *json_output) __attribute__((nonnull(1)));
+static int _do_get_rootcheckscan(FILE *fp) __attribute__((nonnull));
+static int _do_print_rootcheck(FILE *fp, int resolved, time_t time_last_scan,
+                               int csv_output, cJSON *json_output, int show_last) __attribute__((nonnull(1)));
 
-/* Free the agent list in memory
- */
+#endif /* !WIN32*/
+
+static int _get_time_rkscan(const char *agent_name, const char *agent_ip, agent_info *agt_info) __attribute__((nonnull(2, 3)));
+static char *_get_agent_keepalive(const char *agent_name, const char *agent_ip) __attribute__((nonnull(2)));
+static int _get_agent_os(const char *agent_name, const char *agent_ip, agent_info *agt_info) __attribute__((nonnull(2, 3)));
+
+
+/* Free the agent list in memory */
 void free_agents(char **agent_list)
 {
     int i;
-    if(!agent_list)
+    if (!agent_list) {
         return;
+    }
 
-    for(i = 0;;i++)
-    {
-        if(agent_list[i] == NULL)
+    for (i = 0;; i++) {
+        if (agent_list[i] == NULL) {
             break;
+        }
 
         free(agent_list[i]);
         agent_list[i] = NULL;
@@ -36,28 +49,30 @@ void free_agents(char **agent_list)
     agent_list = NULL;
 }
 
-
 #ifndef WIN32
 
-/* Print syscheck attributes. */
+/* Print syscheck attributes */
 #define sk_strchr(x,y,z) z = strchr(x, y); if(z == NULL) return(0); else { *z = '\0'; z++; }
-int _do_print_attrs_syscheck(char *prev_attrs, char *attrs, int csv_output,
-                             int is_win, int number_of_changes)
+
+static int _do_print_attrs_syscheck(const char *prev_attrs, const char *attrs, __attribute__((unused)) int csv_output,
+                                    cJSON *json_output, int is_win, int number_of_changes)
 {
-    char *p_size, *p_perm, *p_uid, *p_gid, *p_md5, *p_sha1;
-    char *size, *perm, *uid, *gid, *md5, *sha1;
-    int perm_int;
+    const char *p_size, *size;
+    char *p_perm, *p_uid, *p_gid, *p_md5, *p_sha1;
+    char *perm, *uid, *gid, *md5, *sha1;
     char perm_str[36];
 
 
-    /* a deleted file has no attributes */
-    if(strcmp(attrs, "-1") == 0)
-    {
-        printf("File deleted.\n");
-        return(0);
+    /* A deleted file has no attributes */
+    if (strcmp(attrs, "-1") == 0) {
+        if (json_output)
+            cJSON_AddStringToObject(json_output, "event", "deleted");
+        else
+            printf("File deleted.\n");
+        return (0);
     }
 
-    /* Setting each value. */
+    /* Set each value */
     size = attrs;
     sk_strchr(size, ':', perm);
     sk_strchr(perm, ':', uid);
@@ -72,321 +87,294 @@ int _do_print_attrs_syscheck(char *prev_attrs, char *attrs, int csv_output,
     p_md5 = md5;
     p_sha1 = sha1;
 
-    if(prev_attrs && (strcmp(prev_attrs, "-1") == 0))
-    {
-        printf("File restored. ");
-    }
-    else if(prev_attrs)
-    {
-        printf("File changed. ");
+    if (prev_attrs && (strcmp(prev_attrs, "-1") == 0)) {
+        if (json_output)
+            cJSON_AddStringToObject(json_output, "event", "restored");
+        else
+            printf("File restored. ");
+    } else if (prev_attrs) {
+        if (json_output)
+            cJSON_AddStringToObject(json_output, "event", "modified");
+        else
+            printf("File changed. ");
+
         p_size = prev_attrs;
         sk_strchr(p_size, ':', p_perm);
         sk_strchr(p_perm, ':', p_uid);
         sk_strchr(p_uid, ':', p_gid);
         sk_strchr(p_gid, ':', p_md5);
         sk_strchr(p_md5, ':', p_sha1);
-    }
-    else
-    {
-        printf("File added to the database. ");
-    }
-
-
-    /* Fixing number of changes. */
-    if(prev_attrs && !number_of_changes)
-    {
-        number_of_changes = 1;
+    } else {
+        if (json_output)
+            cJSON_AddStringToObject(json_output, "event", "added");
+        else
+            printf("File added to the database. ");
     }
 
+    if (!json_output) {
+        /* Fix number of changes */
+        if (prev_attrs && !number_of_changes) {
+            number_of_changes = 1;
+        }
 
-    if(number_of_changes)
-    {
-        switch(number_of_changes)
-        {
-            case 1:
-                printf("- 1st time modified.\n");
-                break;
-            case 2:
-                printf("- 2nd time modified.\n");
-                break;
-            case 3:
-                printf("- 3rd time modified.\n");
-                break;
-            default:
-                printf("- Being ignored (3 or more changes).\n");
-                break;
+        if (number_of_changes) {
+            switch (number_of_changes) {
+                case 1:
+                    printf("- 1st time modified.\n");
+                    break;
+                case 2:
+                    printf("- 2nd time modified.\n");
+                    break;
+                case 3:
+                    printf("- 3rd time modified.\n");
+                    break;
+                default:
+                    printf("- Being ignored (3 or more changes).\n");
+                    break;
+            }
+        } else {
+            printf("\n");
         }
     }
-    else
-    {
-        printf("\n");
-    }
-
 
     perm_str[35] = '\0';
-    perm_int = atoi(perm);
-    snprintf(perm_str, 35,
-             "%c%c%c%c%c%c%c%c%c",
-             (perm_int & S_IRUSR)? 'r' : '-',
-             (perm_int & S_IWUSR)? 'w' : '-',
-
-             (perm_int & S_ISUID)? 's' :
-             (perm_int & S_IXUSR)? 'x' : '-',
-
-
-             (perm_int & S_IRGRP)? 'r' : '-',
-             (perm_int & S_IWGRP)? 'w' : '-',
-
-             (perm_int & S_ISGID)? 's' :
-             (perm_int & S_IXGRP)? 'x' : '-',
-
-
-             (perm_int & S_IROTH)? 'r' : '-',
-             (perm_int & S_IWOTH)? 'w' : '-',
-             (perm_int & S_ISVTX)? 't' :
-             (perm_int & S_IXOTH)? 'x' : '-');
-
-
-    printf("Integrity checking values:\n");
-    printf("   Size:%s%s\n", (strcmp(size,p_size) == 0)? " ": " >", size);
-    if(!is_win)
-    {
-      printf("   Perm:%s%s\n", (strcmp(perm,p_perm) == 0)? " ": " >", perm_str);
-      printf("   Uid: %s%s\n", (strcmp(uid,p_uid) == 0)? " ": " >", uid);
-      printf("   Gid: %s%s\n", (strcmp(gid,p_gid) == 0)? " ": " >", gid);
+    snprintf(perm_str, 35, "%9.9s", agent_file_perm(perm));
+
+    if (json_output) {
+        cJSON_AddStringToObject(json_output, "size", size);
+       // Legacy
+        //cJSON_AddNumberToObject(json_output, "mode", is_win ? 0 : perm_int);
+        cJSON_AddStringToObject(json_output, "perm", is_win ? "" : perm_str);
+        cJSON_AddStringToObject(json_output, "uid", is_win ? "" : uid);
+        cJSON_AddStringToObject(json_output, "gid", is_win ? "" : gid);
+        cJSON_AddStringToObject(json_output, "md5", md5);
+        cJSON_AddStringToObject(json_output, "sha1", sha1);
+
+    } else{
+        printf("Integrity checking values:\n");
+        printf("   Size:%s%s\n", (strcmp(size, p_size) == 0) ? " " : " >", size);
+        if (!is_win) {
+            printf("   Perm:%s%s\n", (strcmp(perm, p_perm) == 0) ? " " : " >", perm_str);
+            printf("   Uid: %s%s\n", (strcmp(uid, p_uid) == 0) ? " " : " >", uid);
+            printf("   Gid: %s%s\n", (strcmp(gid, p_gid) == 0) ? " " : " >", gid);
+        }
+        printf("   Md5: %s%s\n", (strcmp(md5, p_md5) == 0) ? " " : " >", md5);
+        printf("   Sha1:%s%s\n", (strcmp(sha1, p_sha1) == 0) ? " " : " >", sha1);
     }
-    printf("   Md5: %s%s\n", (strcmp(md5,p_md5) == 0)? " ": " >", md5);
-    printf("   Sha1:%s%s\n", (strcmp(sha1,p_sha1) == 0)? " ": " >", sha1);
 
-
-    /* Fixing entries. */
+    /* Fix entries */
     perm[-1] = ':';
     uid[-1] = ':';
     gid[-1] = ':';
     md5[-1] = ':';
     sha1[-1] = ':';
 
-    return(0);
+    return (0);
 }
 
-
-
-/* Print information about a specific file. */
-int _do_print_file_syscheck(FILE *fp, char *fname,
-                            int update_counter, int csv_output)
+/* Print information about a specific file */
+static int _do_print_file_syscheck(FILE *fp, const char *fname, int update_counter,
+                                   int csv_output, cJSON *json_output)
 {
     int f_found = 0;
     struct tm *tm_time;
-
-    char read_day[24 +1];
+    char read_day[24 + 1];
     char buf[OS_MAXSTR + 1];
-
     OSMatch reg;
-    OSStore *files_list;
-
+    OSStore *files_list = NULL;
     fpos_t init_pos;
+    cJSON *json_entry = NULL, *json_attrs = NULL;
 
     buf[OS_MAXSTR] = '\0';
     read_day[24] = '\0';
 
-
     /* If the compilation failed, we don't need to free anything */
-    if(!OSMatch_Compile(fname, &reg, 0))
-    {
-        printf("\n** ERROR: Invalid file name: '%s'\n", fname);
-        return(0);
+    if (!OSMatch_Compile(fname, &reg, 0)) {
+        if (!(csv_output || json_output))
+            printf("\n** ERROR: Invalid file name: '%s'\n", fname);
+        return (0);
     }
 
-
-    /* Creating list with files. */
+    /* Create list with files */
     files_list = OSStore_Create();
-    if(!files_list)
-    {
+    if (!files_list) {
         OSMatch_FreePattern(&reg);
-        return(0);
+        goto cleanup;
     }
 
-
-    /* Getting initial position. */
-    if(fgetpos(fp, &init_pos) != 0)
-    {
-        printf("\n** ERROR: fgetpos failed.\n");
-        return(0);
+    /* Get initial position */
+    if (fgetpos(fp, &init_pos) != 0) {
+        if (!(csv_output || json_output))
+            printf("\n** ERROR: fgetpos failed.\n");
+        goto cleanup;
     }
 
-
-    while(fgets(buf, OS_MAXSTR, fp) != NULL)
-    {
-        if(buf[0] == '!' || buf[0] == '#' || buf[0] == '+')
-        {
+    while (fgets(buf, OS_MAXSTR, fp) != NULL) {
+        if (buf[0] == '!' || buf[0] == '#' || buf[0] == '+') {
             int number_changes = 0;
             time_t change_time = 0;
             char *changed_file_name;
             char *changed_attrs;
             char *prev_attrs;
 
-
-            if(strlen(buf) < 16)
-            {
+            if (strlen(buf) < 16) {
                 fgetpos(fp, &init_pos);
                 continue;
             }
 
-            /* Removing new line. */
-            buf[strlen(buf) -1] = '\0';
-
+            /* Remove newline */
+            buf[strlen(buf) - 1] = '\0';
 
-            /* with update counter, we only modify the last entry. */
-            if(update_counter && buf[0] == '#')
-            {
+            /* With update counter, we only modify the last entry */
+            if (update_counter && buf[0] == '#') {
                 fgetpos(fp, &init_pos);
                 continue;
             }
 
-
-            /* Checking number of changes. */
-            if(buf[1] == '!')
-            {
+            /* Check the number of changes */
+            if (buf[1] == '!') {
                 number_changes = 2;
-                if(buf[2] == '!')
-                {
+                if (buf[2] == '!') {
                     number_changes = 3;
-                }
-                else if(buf[2] == '?')
-                {
+                } else if (buf[2] == '?') {
                     number_changes = 4;
                 }
             }
 
             changed_attrs = buf + 3;
 
-
             changed_file_name = strchr(changed_attrs, '!');
-            if(!changed_file_name)
-            {
+            if (!changed_file_name) {
                 fgetpos(fp, &init_pos);
                 continue;
             }
 
-
-            /* Getting time of change. */
+            /* Get time of change */
             changed_file_name[-1] = '\0';
             changed_file_name++;
             change_time = (time_t)atoi(changed_file_name);
 
             changed_file_name = strchr(changed_file_name, ' ');
+            if (!changed_file_name) {
+                if (!(csv_output || json_output))
+                    printf("\n** ERROR: Invalid line: '%s'.\n", buf);
+                goto cleanup;
+            }
             changed_file_name++;
 
-
-            /* Checking if the name should be printed. */
-            if(!OSMatch_Execute(changed_file_name, strlen(changed_file_name),
-                                &reg))
-            {
+            /* Check if the name should be printed */
+            if (!OSMatch_Execute(changed_file_name, strlen(changed_file_name),
+                                 &reg)) {
                 fgetpos(fp, &init_pos);
                 continue;
             }
 
-
             f_found = 1;
 
-
-            /* Reset the values. */
-            if(update_counter)
-            {
-                if(fsetpos(fp, &init_pos) != 0)
-                {
-                    printf("\n** ERROR: fsetpos failed (unable to update "
-                           "counter).\n");
-                    return(0);
+            /* Reset the values */
+            if (update_counter) {
+                if (fsetpos(fp, &init_pos) != 0) {
+                    if (!(csv_output || json_output))
+                        printf("\n** ERROR: fsetpos failed (unable to update "
+                               "counter).\n");
+                    goto cleanup;
                 }
 
-                if(update_counter == 2)
-                {
-                    if(fprintf(fp, "!!?") <= 0)
-                    {
-                        printf("\n** ERROR: fputs failed (unable to update "
-                                "counter).\n");
-                        return(0);
+                if (update_counter == 2) {
+                    if (fprintf(fp, "!!?") <= 0) {
+                        if (!(csv_output || json_output))
+                            printf("\n** ERROR: fputs failed (unable to update "
+                                   "counter).\n");
+                        goto cleanup;
                     }
                 }
 
-                else
-                {
-                    if(fprintf(fp, "!++") <= 0)
-                    {
-                        printf("\n** ERROR: fputs failed (unable to update "
-                                "counter).\n");
-                        return(0);
+                else {
+                    if (fprintf(fp, "!++") <= 0) {
+                        if (!(csv_output || json_output))
+                            printf("\n** ERROR: fputs failed (unable to update "
+                                   "counter).\n");
+                        goto cleanup;
                     }
                 }
 
-                printf("\n**Counter updated for file '%s'\n\n",
-                       changed_file_name);
-                return(0);
+                if (!(csv_output || json_output))
+                    printf("\n**Counter updated for file '%s'\n\n",
+                           changed_file_name);
+                goto cleanup;
             }
 
-
             tm_time = localtime(&change_time);
             strftime(read_day, 23, "%Y %h %d %T", tm_time);
 
-            if(!csv_output)
-                printf("\n%s,%d - %s\n", read_day, number_changes,
-                                       changed_file_name);
-            else
+            if (json_output) {
+                json_entry = cJSON_CreateObject();
+                json_attrs = cJSON_CreateObject();
+
+                cJSON_AddStringToObject(json_entry, "readDay", read_day);
+                cJSON_AddStringToObject(json_entry, "file", changed_file_name);
+                cJSON_AddNumberToObject(json_entry, "changes", number_changes);
+
+            } else if (csv_output)
                 printf("%s,%s,%d\n", read_day, changed_file_name,
-                                     number_changes);
+                       number_changes);
+            else
+                printf("\n%s,%d - %s\n", read_day, number_changes,
+                       changed_file_name);
 
+            prev_attrs = (char *) OSStore_Get(files_list, changed_file_name);
 
-            prev_attrs = OSStore_Get(files_list, changed_file_name);
-            if(prev_attrs)
-            {
+            if (prev_attrs) {
                 char *new_attrs;
                 os_strdup(changed_attrs, new_attrs);
                 _do_print_attrs_syscheck(prev_attrs, changed_attrs,
-                                         csv_output,
-                                         changed_file_name[0] == '/'?0:1,
+                                         csv_output, json_attrs,
+                                         changed_file_name[0] == '/' ? 0 : 1,
                                          number_changes);
 
                 free(files_list->cur_node->data);
                 files_list->cur_node->data = new_attrs;
-            }
-            else
-            {
-                char *new_name;
+            } else {
                 char *new_attrs;
 
                 os_strdup(changed_attrs, new_attrs);
-                os_strdup(changed_file_name, new_name);
-                OSStore_Put(files_list, new_name, new_attrs);
+                OSStore_Put(files_list, changed_file_name, new_attrs);
                 _do_print_attrs_syscheck(NULL,
-                                         changed_attrs, csv_output,
-                                         changed_file_name[0] == '/'?0:1,
+                                         changed_attrs, csv_output, json_attrs,
+                                         changed_file_name[0] == '/' ? 0 : 1,
                                          number_changes);
             }
 
+            if (json_output) {
+                cJSON_AddItemToObject(json_entry, "attrs", json_attrs);
+                cJSON_AddItemToArray(json_output, json_entry);
+            }
+
             fgetpos(fp, &init_pos);
         }
     }
 
-    if(!f_found)
-    {
+    if (!f_found) {
         printf("\n** No entries found.\n");
     }
+
+cleanup:
     OSMatch_FreePattern(&reg);
+    if (files_list) {
+        OSStore_Free(files_list);
+    }
 
-    return(0);
+    return (0);
 }
 
-
-
-/* Print syscheck db (of modified files. */
-int _do_print_syscheck(FILE *fp, int all_files, int csv_output)
+/* Print syscheck db (of modified files) */
+static int _do_print_syscheck(FILE *fp, __attribute__((unused)) int all_files, int csv_output, cJSON *json_output)
 {
     int f_found = 0;
     struct tm *tm_time;
 
-    char read_day[24 +1];
-    char saved_read_day[24 +1];
+    char read_day[24 + 1];
+    char saved_read_day[24 + 1];
     char buf[OS_MAXSTR + 1];
 
     buf[OS_MAXSTR] = '\0';
@@ -394,341 +382,315 @@ int _do_print_syscheck(FILE *fp, int all_files, int csv_output)
     saved_read_day[0] = '\0';
     saved_read_day[24] = '\0';
 
-    while(fgets(buf, OS_MAXSTR, fp) != NULL)
-    {
-        if(buf[0] == '!' || buf[0] == '#')
-        {
+    while (fgets(buf, OS_MAXSTR, fp) != NULL) {
+        if (buf[0] == '!' || buf[0] == '#') {
             int number_changes = 0;
             time_t change_time = 0;
             char *changed_file_name;
 
-
-            if(strlen(buf) < 16)
+            if (strlen(buf) < 16) {
                 continue;
+            }
 
-            /* Removing new line. */
-            buf[strlen(buf) -1] = '\0';
-
+            /* Remove newline */
+            buf[strlen(buf) - 1] = '\0';
 
-            /* Checking number of changes. */
-            if(buf[1] == '!')
-            {
+            /* Check the number of changes */
+            if (buf[1] == '!') {
                 number_changes = 2;
-                if(buf[2] == '!')
-                {
+                if (buf[2] == '!') {
                     number_changes = 3;
-                }
-                else if(buf[2] == '?')
-                {
+                } else if (buf[2] == '?') {
                     number_changes = 4;
                 }
             }
 
-
-            changed_file_name = strchr(buf +3, '!');
-            if(!changed_file_name)
+            changed_file_name = strchr(buf + 3, '!');
+            if (!changed_file_name) {
                 continue;
-
+            }
 
             f_found = 1;
 
-
-            /* Getting time of change. */
+            /* Get time of change */
             changed_file_name++;
             change_time = atoi(changed_file_name);
 
             changed_file_name = strchr(changed_file_name, ' ');
+            if (!changed_file_name) {
+                if (!(csv_output || json_output))
+                    printf("\n** ERROR: Invalid line: '%s'.\n", buf);
+                return (-1);
+            }
             changed_file_name++;
 
             tm_time = localtime(&change_time);
             strftime(read_day, 23, "%Y %h %d", tm_time);
-            if(strcmp(read_day, saved_read_day) != 0)
-            {
-                if(!csv_output)
+            if (strcmp(read_day, saved_read_day) != 0) {
+                if (!(csv_output || json_output)) {
                     printf("\nChanges for %s:\n", read_day);
+                }
                 strncpy(saved_read_day, read_day, 23);
             }
             strftime(read_day, 23, "%Y %h %d %T", tm_time);
 
-            if(!csv_output)
-                printf("%s,%d - %s\n", read_day, number_changes,
-                                       changed_file_name);
-            else
+            if (json_output) {
+                cJSON *entry = cJSON_CreateObject();
+                cJSON_AddStringToObject(entry, "readDay", read_day);
+                cJSON_AddStringToObject(entry, "file", changed_file_name);
+                cJSON_AddNumberToObject(entry, "changes", number_changes);
+                cJSON_AddItemToArray(json_output, entry);
+            } else if (csv_output)
                 printf("%s,%s,%d\n", read_day, changed_file_name,
-                                     number_changes);
+                       number_changes);
+            else
+                printf("%s,%d - %s\n", read_day, number_changes,
+                       changed_file_name);
         }
     }
 
-    if(!f_found && !csv_output)
-    {
+    if (!(f_found || csv_output || json_output)) {
         printf("\n** No entries found.\n");
     }
 
-    return(0);
+    return (0);
 }
 
-
-/* Print syscheck db (of modified files. */
-int print_syscheck(char *sk_name, char *sk_ip, char *fname, int print_registry,
-                   int all_files, int csv_output, int update_counter)
+/* Print syscheck db (of modified files) */
+int print_syscheck(const char *sk_name, const char *sk_ip, const char *fname,
+                   int print_registry, int all_files, int csv_output,
+                   cJSON *json_output, int update_counter)
 {
     FILE *fp;
     char tmp_file[513];
 
     tmp_file[512] = '\0';
 
-
-    if(sk_name == NULL)
-    {
-        /* Printing database */
+    if (sk_name == NULL) {
+        /* Print database */
         snprintf(tmp_file, 512, "%s/syscheck",
-                SYSCHECK_DIR);
+                 SYSCHECK_DIR);
 
         fp = fopen(tmp_file, "r+");
     }
 
-    else if(sk_ip == NULL)
-    {
-        /* Printing database */
-        snprintf(tmp_file, 512, "%s/%s->syscheck",SYSCHECK_DIR, sk_name);
+    else if (sk_ip == NULL) {
+        /* Print database */
+        snprintf(tmp_file, 512, "%s/%s->syscheck", SYSCHECK_DIR, sk_name);
 
         fp = fopen(tmp_file, "r+");
     }
 
-    else if(!print_registry)
-    {
-        /* Printing database */
+    else if (!print_registry) {
+        /* Print database */
         snprintf(tmp_file, 512, "%s/(%s) %s->syscheck",
-                SYSCHECK_DIR,
-                sk_name,
-                sk_ip);
+                 SYSCHECK_DIR,
+                 sk_name,
+                 sk_ip);
 
         fp = fopen(tmp_file, "r+");
     }
 
-    else
-    {
-        /* Printing database for the windows registry. */
+    else {
+        /* Print database for the Windows registry */
         snprintf(tmp_file, 512, "%s/(%s) %s->syscheck-registry",
-                SYSCHECK_DIR,
-                sk_name,
-                sk_ip);
+                 SYSCHECK_DIR,
+                 sk_name,
+                 sk_ip);
 
         fp = fopen(tmp_file, "r+");
     }
 
-
-    if(fp)
-    {
-        if(!fname)
-        {
-            _do_print_syscheck(fp, all_files, csv_output);
-        }
-        else
-        {
-            _do_print_file_syscheck(fp, fname, update_counter, csv_output);
+    if (fp) {
+        if (!fname) {
+            _do_print_syscheck(fp, all_files, csv_output, json_output);
+        } else {
+            _do_print_file_syscheck(fp, fname, update_counter, csv_output, json_output);
         }
         fclose(fp);
     }
 
-    return(0);
+    return (0);
 }
 
-
-
-int _do_get_rootcheckscan(FILE *fp)
+static int _do_get_rootcheckscan(FILE *fp)
 {
     char *tmp_str;
     char buf[OS_MAXSTR + 1];
 
-    while(fgets(buf, OS_MAXSTR, fp) != NULL)
-    {
+    while (fgets(buf, OS_MAXSTR, fp) != NULL) {
         tmp_str = strstr(buf, "Starting rootcheck scan");
-        if(tmp_str)
-        {
+        if (tmp_str) {
             time_t s_time = 0;
             tmp_str = buf + 1;
 
             s_time = (time_t)atoi(tmp_str);
 
-            return((int)s_time);
+            return ((int)s_time);
         }
     }
 
-    return((int)time(NULL));
+    return ((int)time(NULL));
 }
 
-
-
-/* Print syscheck db (of modified files. */
-int _do_print_rootcheck(FILE *fp, int resolved, int time_last_scan,
-                        int csv_output, int show_last)
+/* Print syscheck db (of modified files) */
+static int _do_print_rootcheck(FILE *fp, int resolved, time_t time_last_scan,
+                               int csv_output, cJSON *json_output, int show_last)
 {
     int i = 0;
     int f_found = 0;
 
-   /* Time from the message. */
+    /* Time from the message */
     time_t s_time = 0;
     time_t i_time = 0;
     struct tm *tm_time;
 
-    char old_day[24 +1];
-    char read_day[24 +1];
+    char old_day[24 + 1];
+    char read_day[24 + 1];
     char buf[OS_MAXSTR + 1];
     char *tmp_str;
 
+    const char *(ig_events[]) = {"Starting rootcheck scan",
+                                 "Ending rootcheck scan",
+                                 "Starting syscheck scan",
+                                 "Ending syscheck scan",
+                                 NULL
+                                };
 
-    char *(ig_events[]) = {"Starting rootcheck scan",
-                           "Ending rootcheck scan",
-                           "Starting syscheck scan",
-                           "Ending syscheck scan",
-                           NULL};
-
-    char *(ns_events[]) = {"Application Found:",
-                           "Windows Audit:",
-                           "Windows Malware:",
-                           NULL};
-
+    const char *(ns_events[]) = {"Application Found:",
+                                 "Windows Audit:",
+                                 "Windows Malware:",
+                                 NULL
+                                };
 
     buf[OS_MAXSTR] = '\0';
     old_day[24] = '\0';
     read_day[24] = '\0';
 
-
     fseek(fp, 0, SEEK_SET);
 
-
-    if(!csv_output)
-    {
-        if(show_last)
-        {
-            tm_time = localtime((time_t *)&time_last_scan);
+    if (!(csv_output || json_output)) {
+        if (show_last) {
+            tm_time = localtime(&time_last_scan);
             strftime(read_day, 23, "%Y %h %d %T", tm_time);
 
             printf("\nLast scan: %s\n\n", read_day);
-        }
-        else if(resolved)
+        } else if (resolved) {
             printf("\nResolved events: \n\n");
-        else
+        } else {
             printf("\nOutstanding events: \n\n");
+        }
     }
 
-
-    while(fgets(buf, OS_MAXSTR, fp) != NULL)
-    {
-        /* Removing first ! */
+    while (fgets(buf, OS_MAXSTR, fp) != NULL) {
+        /* Remove first ! */
         tmp_str = buf + 1;
         s_time = (time_t)atoi(tmp_str);
 
-
-        /* Removing new line. */
+        /* Remove newline */
         tmp_str = strchr(buf, '\n');
-        if(tmp_str)
+        if (tmp_str) {
             *tmp_str = '\0';
+        }
 
-
-        /* Getting initial time. */
+        /* Get initial time */
         tmp_str = strchr(buf + 1, '!');
-        if(!tmp_str)
+        if (!tmp_str) {
             continue;
+        }
         tmp_str++;
 
         i_time = (time_t)atoi(tmp_str);
 
-
-        /* Getting the actual message. */
+        /* Get the actual message */
         tmp_str = strchr(tmp_str, ' ');
-        if(!tmp_str)
+        if (!tmp_str) {
             continue;
+        }
         tmp_str++;
 
-
-
-        /* Checking for resolved. */
-        if(time_last_scan > (s_time + 86400))
-        {
-            if(!resolved)
-            {
+        /* Check for resolved */
+        if (time_last_scan > (s_time + 86400)) {
+            if (!resolved) {
                 continue;
             }
-        }
-        else
-        {
-            if(resolved)
-            {
+        } else {
+            if (resolved) {
                 continue;
             }
         }
 
-
-        /* Checking events to ignore. */
+        /* Check events to ignore */
         i = 0;
-        while(ig_events[i])
-        {
-            if(strncmp(tmp_str, ig_events[i], strlen(ig_events[i]) -1) == 0)
+        while (ig_events[i]) {
+            if (strncmp(tmp_str, ig_events[i], strlen(ig_events[i]) - 1) == 0) {
                 break;
+            }
             i++;
         }
-        if(ig_events[i])
+        if (ig_events[i]) {
             continue;
+        }
 
-
-        /* Checking events that are not system audit. */
+        /* Check events that are not system audit */
         i = 0;
-        while(ns_events[i])
-        {
-            if(strncmp(tmp_str, ns_events[i], strlen(ns_events[i]) -1) == 0)
+        while (ns_events[i]) {
+            if (strncmp(tmp_str, ns_events[i], strlen(ns_events[i]) - 1) == 0) {
                 break;
+            }
             i++;
         }
 
-
         tm_time = localtime((time_t *)&s_time);
         strftime(read_day, 23, "%Y %h %d %T", tm_time);
         tm_time = localtime((time_t *)&i_time);
         strftime(old_day, 23, "%Y %h %d %T", tm_time);
 
+        if (json_output) {
+            cJSON *event = cJSON_CreateObject();
+            cJSON_AddStringToObject(event, "status", resolved == 0 ? "outstanding" : "resolved");
+            cJSON_AddStringToObject(event, "readDay", read_day);
+            cJSON_AddStringToObject(event, "oldDay", old_day);
+
+            if (ns_events[i])
+                cJSON_AddStringToObject(event, "event", tmp_str);
+            else {
+                char json_buffer[OS_MAXSTR + 1];
+                snprintf(json_buffer, OS_MAXSTR, "%s%s", ns_events[i], tmp_str);
+                cJSON_AddStringToObject(event, "event", json_buffer);
+            }
 
-        if(!csv_output)
-        {
-            if(!show_last)
+            cJSON_AddItemToArray(json_output, event);
+        } else if (csv_output) {
+            printf("%s,%s,%s,%s%s\n", resolved == 0 ? "outstanding" : "resolved",
+                   read_day, old_day,
+                  ns_events[i] != NULL ? "" : "System Audit: ",
+                   tmp_str);
+        } else {
+            if (!show_last) {
                 printf("%s (first time detected: %s)\n", read_day, old_day);
+            }
 
-            if(ns_events[i])
-            {
+            if (ns_events[i]) {
                 printf("%s\n\n", tmp_str);
-            }
-            else
-            {
+            } else {
                 printf("System Audit: %s\n\n", tmp_str);
             }
         }
-        else
-        {
-            printf("%s,%s,%s,%s%s\n", resolved == 0?"outstanding":"resolved",
-                                       read_day, old_day,
-                                       ns_events[i] != NULL?"":"System Audit: ",
-                                       tmp_str);
-        }
-
-
 
         f_found++;
     }
 
-    if(!f_found && !csv_output)
-    {
+    if (!f_found && !(csv_output || json_output)) {
         printf("** No entries found.\n");
     }
 
-    return(0);
+    return (0);
 }
 
-
-
 /* Print rootcheck db */
-int print_rootcheck(char *sk_name, char *sk_ip, char *fname, int resolved,
-                    int csv_output, int show_last)
+int print_rootcheck(const char *sk_name, const char *sk_ip, const char *fname,
+                    int resolved, int csv_output, cJSON *json_output, int show_last)
 {
     int ltime = 0;
     FILE *fp;
@@ -736,350 +698,322 @@ int print_rootcheck(char *sk_name, char *sk_ip, char *fname, int resolved,
 
     tmp_file[512] = '\0';
 
-
-    if(sk_name == NULL)
-    {
-        /* Printing database */
+    if (sk_name == NULL) {
+        /* Print database */
         snprintf(tmp_file, 512, "%s/rootcheck",
-                ROOTCHECK_DIR);
+                 ROOTCHECK_DIR);
 
         fp = fopen(tmp_file, "r+");
-    }
-
-    else
-    {
-        /* Printing database */
+    } else {
+        /* Print database */
         snprintf(tmp_file, 512, "%s/(%s) %s->rootcheck",
-                ROOTCHECK_DIR,
-                sk_name,
-                sk_ip);
+                 ROOTCHECK_DIR,
+                 sk_name,
+                 sk_ip);
 
         fp = fopen(tmp_file, "r+");
     }
 
-
-    if(fp)
-    {
-        /* Getting last time of scan. */
+    if (fp) {
+        /* Get last time of scan */
         ltime = _do_get_rootcheckscan(fp);
-        if(!fname)
-        {
-            if(resolved == 1)
-            {
-                _do_print_rootcheck(fp, 1, ltime, csv_output, 0);
-            }
-            else if(resolved == 2)
-            {
-                _do_print_rootcheck(fp, 0, ltime, csv_output, show_last);
-            }
-            else
-            {
-                _do_print_rootcheck(fp, 1, ltime, csv_output, 0);
-                _do_print_rootcheck(fp, 0, ltime, csv_output, show_last);
+        if (!fname) {
+            if (resolved == 1) {
+                _do_print_rootcheck(fp, 1, ltime, csv_output, json_output, 0);
+            } else if (resolved == 2) {
+                _do_print_rootcheck(fp, 0, ltime, csv_output, json_output, show_last);
+            } else {
+                _do_print_rootcheck(fp, 1, ltime, csv_output, json_output, 0);
+                _do_print_rootcheck(fp, 0, ltime, csv_output, json_output, show_last);
+
             }
         }
-        else
-        {
-        }
         fclose(fp);
     }
 
-    return(0);
+    return (0);
 }
 
 #endif
 
-
 /* Delete syscheck db */
-int delete_syscheck(char *sk_name, char *sk_ip, int full_delete)
+int delete_syscheck(const char *sk_name, const char *sk_ip, int full_delete)
 {
     FILE *fp;
     char tmp_file[513];
 
     tmp_file[512] = '\0';
 
-    /* Deleting related files */
+    /* Delete related files */
     snprintf(tmp_file, 512, "%s/(%s) %s->syscheck",
-            SYSCHECK_DIR,
-            sk_name,
-            sk_ip);
+             SYSCHECK_DIR,
+             sk_name,
+             sk_ip);
 
     fp = fopen(tmp_file, "w");
-    if(fp)
+    if (fp) {
         fclose(fp);
+    }
 
-    if(full_delete)
+    if (full_delete) {
         unlink(tmp_file);
+    }
 
-
-    /* Deleting cpt files */
+    /* Delete cpt files */
     snprintf(tmp_file, 512, "%s/.(%s) %s->syscheck.cpt",
-            SYSCHECK_DIR,
-            sk_name,
-            sk_ip);
+             SYSCHECK_DIR,
+             sk_name,
+             sk_ip);
 
     fp = fopen(tmp_file, "w");
-    if(fp)
+    if (fp) {
         fclose(fp);
+    }
     unlink(tmp_file);
 
-
-    /* Deleting registry entries */
+    /* Delete registry entries */
     snprintf(tmp_file, 512, "%s/(%s) %s->syscheck-registry",
-            SYSCHECK_DIR,
-            sk_name,
-            sk_ip);
+             SYSCHECK_DIR,
+             sk_name,
+             sk_ip);
 
     fp = fopen(tmp_file, "w");
-    if(fp)
+    if (fp) {
         fclose(fp);
-    if(full_delete)
+    }
+    if (full_delete) {
         unlink(tmp_file);
+    }
 
-
-    /* Deleting cpt files */
+    /* Delete cpt files */
     snprintf(tmp_file, 512, "%s/.(%s) %s->syscheck-registry.cpt",
-            SYSCHECK_DIR,
-            sk_name,
-            sk_ip);
+             SYSCHECK_DIR,
+             sk_name,
+             sk_ip);
 
     fp = fopen(tmp_file, "w");
-    if(fp)
+    if (fp) {
         fclose(fp);
+    }
     unlink(tmp_file);
 
-    return(1);
+    return (1);
 }
 
-
-
 /* Delete rootcheck db */
-int delete_rootcheck(char *sk_name, char *sk_ip, int full_delete)
+int delete_rootcheck(const char *sk_name, const char *sk_ip, int full_delete)
 {
     FILE *fp;
     char tmp_file[513];
 
     tmp_file[512] = '\0';
 
-    /* Deleting related files */
+    /* Delete related files */
     snprintf(tmp_file, 512, "%s/(%s) %s->rootcheck",
-            ROOTCHECK_DIR,
-            sk_name,
-            sk_ip);
+             ROOTCHECK_DIR,
+             sk_name,
+             sk_ip);
 
     fp = fopen(tmp_file, "w");
-    if(fp)
+    if (fp) {
         fclose(fp);
+    }
 
-    if(full_delete)
+    if (full_delete) {
         unlink(tmp_file);
+    }
 
-
-    return(1);
+    return (1);
 }
 
-
-
-/* Delete agent.
- */
-int delete_agentinfo(char *name)
+/* Delete agent */
+int delete_agentinfo(const char *name)
 {
-    char *sk_name;
+    const char *sk_name;
     char *sk_ip;
     char tmp_file[513];
 
     tmp_file[512] = '\0';
 
-
-    /* Deleting agent info */
+    /* Delete agent info */
     snprintf(tmp_file, 512, "%s/%s", AGENTINFO_DIR, name);
     unlink(tmp_file);
 
-
-    /* Deleting syscheck */
+    /* Delete syscheck */
     sk_name = name;
     sk_ip = strrchr(name, '-');
-    if(!sk_ip)
-        return(0);
+    if (!sk_ip) {
+        return (0);
+    }
 
     *sk_ip = '\0';
     sk_ip++;
 
-
-    /* Deleting syscheck */
+    /* Delete syscheck */
     delete_syscheck(sk_name, sk_ip, 1);
 
-    return(1);
-}
-
+    /* Delete rootcheck */
+    delete_rootcheck(sk_name, sk_ip, 1);
 
+    return (1);
+}
 
-/** char *print_agent_status(int status)
- * Prints the text representation of the agent status.
- */
-char *print_agent_status(int status)
+/* Print the text representation of the agent status */
+const char *print_agent_status(int status)
 {
-    char *status_str = "Never connected";
+    const char *status_str = "Never connected";
 
-    if(status == GA_STATUS_ACTIVE)
-    {
+    if (status == GA_STATUS_ACTIVE) {
         status_str = "Active";
-    }
-    else if(status == GA_STATUS_NACTIVE)
-    {
+    } else if (status == GA_STATUS_NACTIVE) {
         status_str = "Disconnected";
     }
 
-    return(status_str);
+    return (status_str);
 }
 
-
-/* non-windows functions from now on. */
 #ifndef WIN32
+/* Non-windows functions from now on */
 
-
-/** int send_msg_to_agent(int socket, char *msg)
- * Sends a message to an agent.
- * returns -1 on error.
+/* Send a message to an agent
+ * Returns -1 on error
  */
-int send_msg_to_agent(int msocket, char *msg, char *agt_id, char *exec)
+int send_msg_to_agent(int msocket, const char *msg, const char *agt_id, const char *exec)
 {
     int rc;
-    char agt_msg[OS_SIZE_1024 +1];
+    char agt_msg[OS_SIZE_1024 + 1];
 
     agt_msg[OS_SIZE_1024] = '\0';
 
-
-    if(!exec)
-    {
+    if (!exec) {
         snprintf(agt_msg, OS_SIZE_1024,
-                "%s %c%c%c %s %s",
-                "(msg_to_agent) []",
-                (agt_id == NULL)?ALL_AGENTS_C:NONE_C,
-                NO_AR_C,
-                (agt_id != NULL)?SPECIFIC_AGENT_C:NONE_C,
-                agt_id != NULL? agt_id: "(null)",
-                msg);
-    }
-    else
-    {
+                 "%s %c%c%c %s %s",
+                 "(msg_to_agent) []",
+                 (agt_id == NULL) ? ALL_AGENTS_C : NONE_C,
+                 NO_AR_C,
+                 (agt_id != NULL) ? SPECIFIC_AGENT_C : NONE_C,
+                 agt_id != NULL ? agt_id : "(null)",
+                 msg);
+    } else {
         snprintf(agt_msg, OS_SIZE_1024,
-                "%s %c%c%c %s %s - %s (from_the_server) (no_rule_id)",
-                "(msg_to_agent) []",
-                (agt_id == NULL)?ALL_AGENTS_C:NONE_C,
-                NONE_C,
-                (agt_id != NULL)?SPECIFIC_AGENT_C:NONE_C,
-                agt_id != NULL? agt_id: "(null)",
-                msg, exec);
+                 "%s %c%c%c %s %s - %s (from_the_server) (no_rule_id)",
+                 "(msg_to_agent) []",
+                 (agt_id == NULL) ? ALL_AGENTS_C : NONE_C,
+                 NONE_C,
+                 (agt_id != NULL) ? SPECIFIC_AGENT_C : NONE_C,
+                 agt_id != NULL ? agt_id : "(null)",
+                 msg, exec);
 
     }
 
-
-    if((rc = OS_SendUnix(msocket, agt_msg, 0)) < 0)
-    {
-        if(rc == OS_SOCKBUSY)
-        {
+    if ((rc = OS_SendUnix(msocket, agt_msg, 0)) < 0) {
+        if (rc == OS_SOCKBUSY) {
             merror("%s: ERROR: Remoted socket busy.", __local_name);
-        }
-        else
-        {
+        } else {
             merror("%s: ERROR: Remoted socket error.", __local_name);
         }
         merror("%s: Error communicating with remoted queue (%d).",
                __local_name, rc);
 
-        return(-1);
+        return (-1);
     }
 
-    return(0);
+    return (0);
 }
 
-
-
-/** int connect_to_remoted()
- * Connects to remoted to be able to send messages to the agents.
- * Returns the socket on success or -1 on failure.
+/* Connect to remoted to be able to send messages to the agents
+ * Returns the socket on success or -1 on failure
  */
 int connect_to_remoted()
 {
     int arq = -1;
 
-    if((arq = StartMQ(ARQUEUE, WRITE)) < 0)
-    {
+    if ((arq = StartMQ(ARQUEUE, WRITE)) < 0) {
         merror(ARQ_ERROR, __local_name);
-        return(-1);
+        return (-1);
     }
 
-    return(arq);
+    return (arq);
 }
 
+const char *agent_file_perm(char *perm)
+{
+       /* rwxrwxrwx0 -> 10 */
+       static char permissions[10];
+       mode_t mode = 0;
+
+       /* octal or decimal */
+       mode = (mode_t) strtoul(perm, 0, strlen(perm) == 3 ? 8 : 10);
+
+       permissions[0] = (mode & S_IRUSR) ? 'r' : '-';
+       permissions[1] = (mode & S_IWUSR) ? 'w' : '-';
+       permissions[2] = (mode & S_ISUID) ? 's' : (mode & S_IXUSR) ? 'x' : '-';
+       permissions[3] = (mode & S_IRGRP) ? 'r' : '-';
+       permissions[4] = (mode & S_IWGRP) ? 'w' : '-';
+       permissions[5] = (mode & S_ISGID) ? 's' : (mode & S_IXGRP) ? 'x' : '-';
+       permissions[6] = (mode & S_IROTH) ? 'r' : '-';
+       permissions[7] = (mode & S_IWOTH) ? 'w' : '-';
+       permissions[8] = (mode & S_ISVTX) ? 't' : (mode & S_IXOTH) ? 'x' : '-';
+    permissions[9] = '\0';
+
+       return &permissions[0];
+}
 
-#endif
-
+#endif /* !WIN32 */
 
-/* Internal funtion. Extract last time of scan from rootcheck/syscheck. */
-int _get_time_rkscan(char *agent_name, char *agent_ip, agent_info *agt_info)
+/* Internal function. Extract last time of scan from rootcheck/syscheck. */
+static int _get_time_rkscan(const char *agent_name, const char *agent_ip, agent_info *agt_info)
 {
     FILE *fp;
-    char buf[1024 +1];
-
+    char buf[1024 + 1];
 
-    /* Agent name of null, means it is the server info. */
-    if(agent_name == NULL)
-    {
+    /* Agent name of null, means it is the server info */
+    if (agent_name == NULL) {
         snprintf(buf, 1024, "%s/rootcheck",
-                      ROOTCHECK_DIR);
-    }
-    else
-    {
+                 ROOTCHECK_DIR);
+    } else {
         snprintf(buf, 1024, "%s/(%s) %s->rootcheck",
-                      ROOTCHECK_DIR, agent_name, agent_ip);
+                 ROOTCHECK_DIR, agent_name, agent_ip);
     }
 
-
-    /* If file is not there, set to unknown. */
+    /* If file is not there, set to unknown */
     fp = fopen(buf, "r");
-    if(!fp)
-    {
+    if (!fp) {
         os_strdup("Unknown", agt_info->rootcheck_time);
         os_strdup("Unknown", agt_info->rootcheck_endtime);
         os_strdup("Unknown", agt_info->syscheck_time);
         os_strdup("Unknown", agt_info->syscheck_endtime);
-        return(0);
+        return (0);
     }
 
-
-    while(fgets(buf, 1024, fp) != NULL)
-    {
+    while (fgets(buf, 1024, fp) != NULL) {
         char *tmp_str = NULL;
 
-        /* Removing new line. */
+        /* Remove newline */
         tmp_str = strchr(buf, '\n');
-        if(tmp_str)
+        if (tmp_str) {
             *tmp_str = '\0';
-
+        }
 
         tmp_str = strstr(buf, "Starting syscheck scan");
-        if(tmp_str)
-        {
+        if (tmp_str) {
             time_t s_time = 0;
             tmp_str = buf + 1;
 
             s_time = (time_t)atoi(tmp_str);
-
             os_strdup(ctime(&s_time), agt_info->syscheck_time);
 
-            /* Removing new line. */
+            /* Remove newline */
             tmp_str = strchr(agt_info->syscheck_time, '\n');
-            if(tmp_str)
+            if (tmp_str) {
                 *tmp_str = '\0';
+            }
 
             continue;
         }
 
         tmp_str = strstr(buf, "Ending syscheck scan");
-        if(tmp_str)
-        {
+        if (tmp_str) {
             time_t s_time = 0;
             tmp_str = buf + 1;
 
@@ -1087,18 +1021,17 @@ int _get_time_rkscan(char *agent_name, char *agent_ip, agent_info *agt_info)
 
             os_strdup(ctime(&s_time), agt_info->syscheck_endtime);
 
-            /* Removing new line. */
+            /* Remove newline */
             tmp_str = strchr(agt_info->syscheck_endtime, '\n');
-            if(tmp_str)
+            if (tmp_str) {
                 *tmp_str = '\0';
+            }
 
             continue;
         }
 
-
         tmp_str = strstr(buf, "Starting rootcheck scan");
-        if(tmp_str)
-        {
+        if (tmp_str) {
             time_t s_time = 0;
             tmp_str = buf + 1;
 
@@ -1106,157 +1039,125 @@ int _get_time_rkscan(char *agent_name, char *agent_ip, agent_info *agt_info)
 
             os_strdup(ctime(&s_time), agt_info->rootcheck_time);
 
-            /* Removing new line. */
+            /* Remove newline */
             tmp_str = strchr(agt_info->rootcheck_time, '\n');
-            if(tmp_str)
+            if (tmp_str) {
                 *tmp_str = '\0';
+            }
 
             continue;
         }
 
         tmp_str = strstr(buf, "Ending rootcheck scan");
-        if(tmp_str)
-        {
+        if (tmp_str) {
             time_t s_time = 0;
             tmp_str = buf + 1;
-
             s_time = (time_t)atoi(tmp_str);
-
             os_strdup(ctime(&s_time), agt_info->rootcheck_endtime);
 
-            /* Removing new line. */
+            /* Remove newline */
             tmp_str = strchr(agt_info->rootcheck_endtime, '\n');
-            if(tmp_str)
+            if (tmp_str) {
                 *tmp_str = '\0';
+            }
 
             continue;
         }
     }
 
-
-    /* Setting unknown values. */
-    if(!agt_info->rootcheck_time)
+    /* Set unknown values */
+    if (!agt_info->rootcheck_time) {
         os_strdup("Unknown", agt_info->rootcheck_time);
-    if(!agt_info->rootcheck_endtime)
+    }
+    if (!agt_info->rootcheck_endtime) {
         os_strdup("Unknown", agt_info->rootcheck_endtime);
-    if(!agt_info->syscheck_time)
+    }
+    if (!agt_info->syscheck_time) {
         os_strdup("Unknown", agt_info->syscheck_time);
-    if(!agt_info->syscheck_endtime)
+    }
+    if (!agt_info->syscheck_endtime) {
         os_strdup("Unknown", agt_info->syscheck_endtime);
+    }
 
     fclose(fp);
-    return(0);
+    return (0);
 }
 
-
-
-/* Internal funtion. Extract last time of scan from rootcheck/syscheck. */
-char *_get_agent_keepalive(char *agent_name, char *agent_ip)
+/* Internal function. Extract last time of scan from rootcheck/syscheck. */
+static char *_get_agent_keepalive(const char *agent_name, const char *agent_ip)
 {
-    char buf[1024 +1];
+    char buf[1024 + 1];
     struct stat file_status;
 
-
-    /* No keep alive for the server. */
-    if(!agent_name)
-    {
-        return(strdup("Not available"));
+    /* No keepalive for the server */
+    if (!agent_name) {
+        return (strdup("Not available"));
     }
 
     snprintf(buf, 1024, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip);
-    if(stat(buf, &file_status) < 0)
-    {
-        return(strdup("Unknown"));
+    if (stat(buf, &file_status) < 0) {
+        return (strdup("Unknown"));
     }
 
-
-    return(strdup(ctime(&file_status.st_mtime)));
+    return (strdup(ctime(&file_status.st_mtime)));
 }
 
-
-
-/* Internal funtion. Extracts operating system. */
-int _get_agent_os(char *agent_name, char *agent_ip, agent_info *agt_info)
+/* Internal function. Extract operating system. */
+static int _get_agent_os(const char *agent_name, const char *agent_ip, agent_info *agt_info)
 {
     FILE *fp;
-    char buf[1024 +1];
-
+    char buf[1024 + 1];
 
-    /* Getting server info. */
-    if(!agent_name)
-    {
+    /* Get server info */
+    if (!agent_name) {
         char *ossec_version = NULL;
         agt_info->os = getuname();
         os_strdup(__ossec_name " " __version, agt_info->version);
 
-
-        /* Removing new line. */
+        /* Remove newline */
         ossec_version = strchr(agt_info->os, '\n');
-        if(ossec_version)
+        if (ossec_version) {
             *ossec_version = '\0';
-
+        }
 
         ossec_version = strstr(agt_info->os, " - ");
-        if(ossec_version)
-        {
+        if (ossec_version) {
             *ossec_version = '\0';
         }
 
-
-        if(strlen(agt_info->os) > 55)
-        {
-            agt_info->os[52] = '.';
-            agt_info->os[53] = '.';
-            agt_info->os[54] = '\0';
-        }
-
-
-        return(0);
+        return (0);
     }
 
-
     snprintf(buf, 1024, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip);
     fp = fopen(buf, "r");
-    if(!fp)
-    {
+    if (!fp) {
         os_strdup("Unknown", agt_info->os);
         os_strdup("Unknown", agt_info->version);
-        return(0);
+        return (0);
     }
 
-
-    if(fgets(buf, 1024, fp))
-    {
+    if (fgets(buf, 1024, fp)) {
         char *ossec_version = NULL;
 
-        /* Removing new line. */
+        /* Remove newline */
         ossec_version = strchr(buf, '\n');
-        if(ossec_version)
+        if (ossec_version) {
             *ossec_version = '\0';
-
+        }
 
         ossec_version = strstr(buf, " - ");
-        if(ossec_version)
-        {
+        if (ossec_version) {
             *ossec_version = '\0';
             ossec_version += 3;
 
-            os_calloc(1024 +1, sizeof(char), agt_info->version);
+            os_calloc(1024 + 1, sizeof(char), agt_info->version);
             strncpy(agt_info->version, ossec_version, 1024);
         }
 
-
-        if(strlen(buf) > 55)
-        {
-            buf[52] = '.';
-            buf[53] = '.';
-            buf[54] = '\0';
-        }
-
         os_strdup(buf, agt_info->os);
         fclose(fp);
 
-        return(1);
+        return (1);
     }
 
     fclose(fp);
@@ -1264,33 +1165,26 @@ int _get_agent_os(char *agent_name, char *agent_ip, agent_info *agt_info)
     os_strdup("Unknown", agt_info->os);
     os_strdup("Unknown", agt_info->version);
 
-    return(0);
+    return (0);
 }
 
-
-
-/** agent_info *get_agent_info(char *agent_name, char *agent_ip)
- * Get information from an agent.
- */
-agent_info *get_agent_info(char *agent_name, char *agent_ip)
+/* Get information from an agent */
+agent_info *get_agent_info(const char *agent_name, const char *agent_ip)
 {
     char *agent_ip_pt = NULL;
     char *tmp_str = NULL;
 
     agent_info *agt_info = NULL;
 
-    /* Removing the  "/", since it is not present on the file. */
-    if((agent_ip_pt = strchr(agent_ip, '/')))
-    {
+    /* Remove the "/", since it is not present on the file */
+    if ((agent_ip_pt = strchr(agent_ip, '/'))) {
         *agent_ip_pt = '\0';
     }
 
+    /* Allocate memory for the info structure */
+    os_calloc(1, sizeof(agent_info), agt_info);
 
-    /* Allocating memory for the info structure. */
-    agt_info = calloc(1, sizeof(agent_info));
-
-
-    /* Zeroing the values. */
+    /* Zero the values */
     agt_info->rootcheck_time = NULL;
     agt_info->rootcheck_endtime = NULL;
     agt_info->syscheck_time = NULL;
@@ -1299,172 +1193,140 @@ agent_info *get_agent_info(char *agent_name, char *agent_ip)
     agt_info->version = NULL;
     agt_info->last_keepalive = NULL;
 
-
-    /* Getting information about the OS. */
+    /* Get information about the OS */
     _get_agent_os(agent_name, agent_ip, agt_info);
     _get_time_rkscan(agent_name, agent_ip, agt_info);
     agt_info->last_keepalive = _get_agent_keepalive(agent_name, agent_ip);
 
-
-    /* Removing new line from keep alive. */
+    /* Remove newline from keepalive */
     tmp_str = strchr(agt_info->last_keepalive, '\n');
-    if(tmp_str)
+    if (tmp_str) {
         *tmp_str = '\0';
+    }
 
-
-
-    /* Setting back the ip address. */
-    if(agent_ip_pt)
-    {
+    /* Set back the IP address */
+    if (agent_ip_pt) {
         *agent_ip_pt = '/';
     }
 
-
-    return(agt_info);
+    return (agt_info);
 }
 
-
-
-/** int get_agent_status(char *agent_name, char *agent_ip)
- * Gets the status of an agent, based on the name/ip.
- */
-int get_agent_status(char *agent_name, char *agent_ip)
+/* Gets the status of an agent, based on the name / IP address */
+int get_agent_status(const char *agent_name, const char *agent_ip)
 {
     char tmp_file[513];
     char *agent_ip_pt = NULL;
-
     struct stat file_status;
 
     tmp_file[512] = '\0';
 
-
-    /* Server info. */
-    if(agent_name == NULL)
-    {
-        return(GA_STATUS_ACTIVE);
+    /* Server info */
+    if (agent_name == NULL) {
+        return (GA_STATUS_ACTIVE);
     }
 
-
-    /* Removing the  "/", since it is not present on the file. */
-    if((agent_ip_pt = strchr(agent_ip, '/')))
-    {
+    /* Remove the  "/", since it is not present on the file */
+    if ((agent_ip_pt = strchr(agent_ip, '/'))) {
         *agent_ip_pt = '\0';
     }
 
     snprintf(tmp_file, 512, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip);
 
-
-    /* Setting back the ip address. */
-    if(agent_ip_pt)
-    {
+    /* Set back the IP address */
+    if (agent_ip_pt) {
         *agent_ip_pt = '/';
     }
 
-
-    if(stat(tmp_file, &file_status) < 0)
-    {
-        return(GA_STATUS_INV);
+    if (stat(tmp_file, &file_status) < 0) {
+        return (GA_STATUS_INV);
     }
 
-
-    if(file_status.st_mtime > (time(0) - (3*NOTIFY_TIME + 30)))
-    {
-        return(GA_STATUS_ACTIVE);
+    if (file_status.st_mtime > (time(0) - (3 * NOTIFY_TIME + 30))) {
+        return (GA_STATUS_ACTIVE);
     }
 
-    return(GA_STATUS_NACTIVE);
+    return (GA_STATUS_NACTIVE);
 }
 
-
-
-/* List available agents.
- */
-char **get_agents(int flag)
+/* List available agents with specified timeout */
+char **get_agents_with_timeout(int flag, int timeout)
 {
-    int f_size = 0;
-
+    size_t f_size = 0;
     char **f_files = NULL;
     DIR *dp;
-
     struct dirent *entry;
 
-    /* Opening the directory given */
+    /* Open the directory */
     dp = opendir(AGENTINFO_DIR);
-    if(!dp)
-    {
+    if (!dp) {
         merror("%s: Error opening directory: '%s': %s ",
-                __local_name,
-                AGENTINFO_DIR,
-                strerror(errno));
-        return(NULL);
+               __local_name,
+               AGENTINFO_DIR,
+               strerror(errno));
+        return (NULL);
     }
 
-
-    /* Reading directory */
-    while((entry = readdir(dp)) != NULL)
-    {
+    /* Read directory */
+    while ((entry = readdir(dp)) != NULL) {
         int status = 0;
         char tmp_file[513];
         tmp_file[512] = '\0';
 
-        /* Just ignore . and ..  */
-        if((strcmp(entry->d_name,".") == 0) ||
-           (strcmp(entry->d_name,"..") == 0))
+        /* Ignore . and ..  */
+        if ((strcmp(entry->d_name, ".") == 0) ||
+                (strcmp(entry->d_name, "..") == 0)) {
             continue;
+        }
 
         snprintf(tmp_file, 512, "%s/%s", AGENTINFO_DIR, entry->d_name);
 
-
-        if(flag != GA_ALL)
-        {
+        if (flag != GA_ALL) {
             struct stat file_status;
 
-            if(stat(tmp_file, &file_status) < 0)
+            if (stat(tmp_file, &file_status) < 0) {
                 continue;
+            }
 
-            if(file_status.st_mtime > (time(0) - (3*NOTIFY_TIME + 30)))
-            {
+            if (file_status.st_mtime > (time(0) - (3 * timeout + 30))) {
                 status = 1;
-                if(flag == GA_NOTACTIVE)
+                if (flag == GA_NOTACTIVE) {
                     continue;
-            }
-            else
-            {
-                if(flag == GA_ACTIVE)
+                }
+            } else {
+                if (flag == GA_ACTIVE) {
                     continue;
+                }
             }
         }
 
-        f_files = (char **)realloc(f_files, (f_size +2) * sizeof(char *));
-        if(!f_files)
-        {
-            ErrorExit(MEM_ERROR, __local_name);
+        f_files = (char **)realloc(f_files, (f_size + 2) * sizeof(char *));
+        if (!f_files) {
+            ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
         }
 
+        /* Add agent entry */
+        if (flag == GA_ALL_WSTATUS) {
+            char agt_stat[512];
 
-        /* Adding agent entry */
-        if(flag == GA_ALL_WSTATUS)
-        {
-           char agt_stat[512];
-
-           snprintf(agt_stat, sizeof(agt_stat) -1, "%s %s",
-                    entry->d_name, status == 1?"active":"disconnected");
+            snprintf(agt_stat, sizeof(agt_stat) - 1, "%s %s",
+                     entry->d_name, status == 1 ? "active" : "disconnected");
 
-           os_strdup(agt_stat, f_files[f_size]);
-        }
-        else
-        {
+            os_strdup(agt_stat, f_files[f_size]);
+        } else {
             os_strdup(entry->d_name, f_files[f_size]);
         }
 
-        f_files[f_size +1] = NULL;
+        f_files[f_size + 1] = NULL;
 
         f_size++;
     }
 
     closedir(dp);
-    return(f_files);
+    return (f_files);
 }
 
-
-/* EOF */
+/* List available agents */
+char **get_agents(int flag) {
+  return get_agents_with_timeout(flag, NOTIFY_TIME);
+}