Added ARCHIVE commands

Sun, 08 Mar 2015 16:40:25 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 08 Mar 2015 16:40:25 +0100
changeset 329
517e1719006a
parent 328
1713dc0cd20f
child 330
79001a992f4f

Added ARCHIVE commands

thermferm/server.c file | annotate | diff | comparison | revisions
--- 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");

mercurial