# HG changeset patch # User Michiel Broek # Date 1425829225 -3600 # Node ID 517e1719006aa203208f47ac3fd3ac54327a5134 # Parent 1713dc0cd20f4e11bd3e2b7d5324e8605f4225c9 Added ARCHIVE commands diff -r 1713dc0cd20f -r 517e1719006a thermferm/server.c --- a/thermferm/server.c Sat Mar 07 14:40:08 2015 +0100 +++ b/thermferm/server.c Sun Mar 08 16:40:25 2015 +0100 @@ -56,6 +56,25 @@ #define MAX_INTERVALS 6 const int GRAPH_INTERVAL[MAX_INTERVALS] = { 0, 1, 5, 15, 30, 60, }; const int GRAPH_DATALINES[MAX_INTERVALS] = { 0, 800, 3200, 12000, 24000, 48000, }; +const char MONTH[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + +typedef struct _ls_list { + struct _ls_list *next; /* Next record pointer */ + char d_name[256]; /* File name */ + mode_t mode; /* File mode */ + off_t size; /* File size */ + time_t mtime; /* File modification time */ +} ls_list; + + + +void tidy_lslist(ls_list **); +void fill_list(ls_list **, char *, mode_t, off_t, time_t); +int comp(ls_list **,ls_list **); +void sort_list(ls_list **); + + /* * Send message to client @@ -170,6 +189,225 @@ +void tidy_lslist(ls_list **lap) +{ + ls_list *tmp, *old; + + for (tmp = *lap; tmp; tmp = old) { + old = tmp->next; + free(tmp); + } + *lap = NULL; +} + + + +void fill_list(ls_list **lap, char *name, mode_t mode, off_t size, time_t mtime) +{ + ls_list **tmp; + + for (tmp = lap; *tmp; tmp = &((*tmp)->next)); + + *tmp = (ls_list *)malloc(sizeof(ls_list)); + (*tmp)->next = NULL; + strncpy((*tmp)->d_name, name, 256); + (*tmp)->mode = mode; + (*tmp)->size = size; + (*tmp)->mtime = mtime; + tmp = &((*tmp)->next); +} + + + +void sort_list(ls_list **lap) +{ + ls_list *ta, **vector; + size_t n = 0, i; + + if (*lap == NULL) + return; + + for (ta = *lap; ta; ta = ta->next) + n++; + vector = (ls_list **)malloc(n * sizeof(ls_list *)); + i = 0; + + for (ta = *lap; ta; ta = ta->next) { + vector[i++] = ta; + } + qsort(vector, n, sizeof(ls_list *), (int(*)(const void*, const void*))comp); + + (*lap) = vector[0]; + i = 1; + + for (ta = *lap; ta; ta = ta->next) { + if (i < n) + ta->next = vector[i++]; + else + ta->next = NULL; + } + + free(vector); + return; +} + + + +int comp(ls_list **lsp1, ls_list **lsp2) +{ + return strcmp((*lsp1)->d_name, (*lsp2)->d_name); +} + + + +/* + * ARCHIVE DIR + * ARCHIVE GET filename + * ARCHIVE HELP + */ +int cmd_archive(char *buf) +{ + char *opt, *param, *name = NULL, *filename = NULL, mbits[11], tstr[24]; + DIR *dd; + FILE *fp; + struct dirent entry, *result; + ls_list *lsx = NULL, *tmp; + struct stat sbuf; + struct tm *tbuf; + time_t ftime; + + opt = strtok(buf, " \0"); + opt = strtok(NULL, " \0"); + + if (opt == NULL) { + srv_send((char *)"501 Subcommand missing"); + return 1; + } + param = strtok(NULL, "\0"); + + if (strcmp(opt, (char *)"HELP") == 0) { + srv_send((char *)"100 Help text follows:"); + srv_send((char *)"Recognized commands:"); + srv_send((char *)"ARCHIVE DIR Archived logfiles directory"); + srv_send((char *)"ARCHIVE GET filename Archived logfile download"); + srv_send((char *)"."); + return 0; + } + + if (strcmp(opt, (char *)"DIR") == 0) { + + if (getenv((char *)"USER") == NULL) { + name = xstrcpy((char *)"/root"); + } else { + name = xstrcpy(getenv((char *)"HOME")); + } + name = xstrcat(name, (char *)"/.thermferm/log/"); + + if ((dd = opendir(name))) { + for (;;) { + if ((readdir_r(dd, &entry, &result)) != 0) { + syslog(LOG_NOTICE, "readdir_r: error=%d", errno); + break; + } + if (result == NULL) /* End of directory */ + break; + if (result->d_name[0] != '.') { + filename = xstrcpy(name); + filename = xstrcat(filename, result->d_name); + if ((stat(filename, &sbuf)) == 0) { + fill_list(&lsx, result->d_name, sbuf.st_mode, sbuf.st_size, sbuf.st_mtime); + } + free(filename); + filename = NULL; + } + } + closedir(dd); + } else { + syslog(LOG_NOTICE, "opendir: \"%s\" error=%d", name, errno); + } + + sort_list(&lsx); + + srv_send((char *)"212 Archive directory follows:"); + for (tmp = lsx; tmp; tmp = tmp->next) { + sprintf(mbits, "----------"); + if (tmp->mode & S_IRUSR) + mbits[1] = 'r'; + if (tmp->mode & S_IWUSR) + mbits[2] = 'w'; + if (tmp->mode & S_IXUSR) + mbits[3] = 'x'; + if (tmp->mode & S_IRGRP) + mbits[4] = 'r'; + if (tmp->mode & S_IWGRP) + mbits[5] = 'w'; + if (tmp->mode & S_IXGRP) + mbits[6] = 'x'; + if (tmp->mode & S_IROTH) + mbits[7] = 'r'; + if (tmp->mode & S_IWOTH) + mbits[8] = 'w'; + if (tmp->mode & S_IXOTH) + mbits[9] = 'x'; + ftime = tmp->mtime; + tbuf = localtime(&ftime); + sprintf(tstr, "%02d %s %04d %02d:%02d", tbuf->tm_mday, MONTH[tbuf->tm_mon], tbuf->tm_year+1900, tbuf->tm_hour, tbuf->tm_min); + srv_send((char *)"%s,%s,%d,%s", tmp->d_name, mbits, tmp->size, tstr); + } + srv_send((char *)"."); + tidy_lslist(&lsx); + + free(name); + name = NULL; + return 1; + } + + if (param == NULL) { + srv_send((char *)"502 Parameter missing"); + return 1; + } + + if (strcmp(opt, (char *)"GET") == 0) { + if (getenv((char *)"USER") == NULL) { + name = xstrcpy((char *)"/root"); + } else { + name = xstrcpy(getenv((char *)"HOME")); + } + name = xstrcat(name, (char *)"/.thermferm/log/"); + name = xstrcat(name, param); + + if ((fp = fopen(name, "r"))) { + char buffer[256]; + + srv_send((char *)"212 Archive file follows:"); + while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { + int i; + + for (i = 0; i < strlen(buffer); i++) { + if (buffer[i] == '\n') + buffer[i] = '\0'; + if (buffer[i] == '\r') + buffer[i] = '\0'; + } + srv_send(buffer); + } + srv_send((char *)"."); + fclose(fp); + } else { + srv_send((char *)"440 No such file"); + return 1; + } + + free(name); + name = NULL; + return 1; + } + + return 0; +} + + + int delete_Device(char *uuid) { devices_list *current = Config.devices; @@ -2112,7 +2350,9 @@ /* * Process commands from the client */ - if (strncmp(buf, "DEVICE", 6) == 0) { + if (strncmp(buf, "ARCHIVE", 7) == 0) { + cmd_archive(buf); + } else if (strncmp(buf, "DEVICE", 6) == 0) { if (cmd_device(buf) == 0) wrconfig(); } else if (strncmp(buf, "GLOBAL", 6) == 0) { @@ -2123,6 +2363,8 @@ srv_send((char *)"Recognized commands:"); srv_send((char *)""); // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + srv_send((char *)"ARCHIVE DIR Archived logfiles directory"); + srv_send((char *)"ARCHIVE GET filename Archived logfile download"); srv_send((char *)"DEVICE ADD type Add new Device type"); srv_send((char *)"DEVICE DEL uuid Delete Device by uuid"); srv_send((char *)"DEVICE LIST List Devices");