#include #include #include #include #include #include #include #include #include #include "libuuid/uuid.h" char *baseindir = NULL; char *baseoutdir = NULL; char *config_file; int imhub = 0; struct msgarea_t { int id; int hub; char *basedir; int *links; int link_count; }; struct msg_t { int area; char from[32]; char to[32]; char subject[64]; uint32_t timedate; int oaddr; int daddr; int type; char reply[36]; } __attribute__ ((packed)); struct msgarea_t **areas; int area_count; int mynode = 0; int hubnode = 0; int copy_file(char *src, char *dest) { FILE *src_file; FILE *dest_file; char c; src_file = fopen(src, "rb"); if (!src_file) { return -1; } dest_file = fopen(dest, "wb"); if (!dest_file) { fclose(src_file); return -1; } while(1) { c = fgetc(src_file); if (!feof(src_file)) { fputc(c, dest_file); } else { break; } } fclose(src_file); fclose(dest_file); return 0; } size_t trimwhitespace(char *out, size_t len, const char *str) { if(len == 0) return 0; const char *end; size_t out_size; // Trim leading space while(isspace((unsigned char)*str)) str++; if(*str == 0) { *out = 0; return 1; } // Trim trailing space end = str + strlen(str) - 1; while(end > str && isspace((unsigned char)*end)) end--; end++; // Set output size to minimum of trimmed string length and buffer size minus 1 out_size = (end - str) < len-1 ? (end - str) : len-1; // Copy trimmed string and add null terminator memcpy(out, str, out_size); out[out_size] = 0; return out_size; } int parse_config_file(char *filename) { FILE *fptr; char buffer[256]; char bufferw[256]; char *ptr; struct msgarea_t *newarea; area_count = 0; fptr = fopen(filename, "r"); if (!fptr) { return 0; } fgets(buffer, 256, fptr); while (!feof(fptr)) { if (buffer[0] != ';') { if (buffer[strlen(buffer) - 1] == '\n'){ buffer[strlen(buffer) - 1] = '\0'; if (strncasecmp(buffer, "IMHUB", 5) == 0) { trimwhitespace(bufferw, 256, &buffer[6]); if (strcasecmp(bufferw, "TRUE") == 0) { imhub = 1; } } else if (strncasecmp(buffer, "UPLINK", 6) == 0) { trimwhitespace(bufferw, 256, &buffer[7]); hubnode = atoi(bufferw); } else if (strncasecmp(buffer, "INDIR", 5) == 0) { trimwhitespace(bufferw, 256, &buffer[6]); baseindir = strdup(bufferw); } else if (strncasecmp(buffer, "OUTDIR", 6) == 0) { trimwhitespace(bufferw, 256, &buffer[7]); baseoutdir = strdup(bufferw); } else if (strncasecmp(buffer, "MYNODE", 6) == 0) { trimwhitespace(bufferw, 256, &buffer[7]); mynode = atoi(bufferw); } else if (strncasecmp(buffer, "MSGAREA", 7) == 0) { newarea = NULL; ptr = strtok(&buffer[8], ","); if (ptr != NULL) { newarea = (struct msgarea_t *)malloc(sizeof(struct msgarea_t)); trimwhitespace(bufferw, 256, ptr); newarea->id = atoi(bufferw); newarea->link_count = 0; ptr = strtok(NULL, ","); if (ptr != NULL) { trimwhitespace(bufferw, 256, ptr); newarea->hub = atoi(bufferw); ptr = strtok(NULL, ","); if (ptr != NULL) { trimwhitespace(bufferw, 256, ptr); newarea->basedir = strdup(bufferw); ptr = strtok(NULL, ","); while (ptr != NULL) { trimwhitespace(bufferw, 256, ptr); if (newarea->link_count == 0) { newarea->links = (int *)malloc(sizeof(int)); } else { newarea->links = (int *)realloc(newarea->links, sizeof(int) * (newarea->link_count + 1)); } newarea->links[newarea->link_count] = atoi(bufferw); newarea->link_count++; ptr = strtok(NULL, ","); } } } } if (newarea != NULL) { if (area_count == 0) { areas = (struct msgarea_t **)malloc(sizeof(struct msgarea_t *)); } else { areas = (struct msgarea_t **)realloc(areas, sizeof(struct msgarea_t *) * (area_count + 1)); } areas[area_count] = newarea; area_count++; } } } else { fclose(fptr); return 0; } } fgets(buffer, 256, fptr); } fclose(fptr); return 1; } void remove_config_file_area(int areaid) { char backup[PATH_MAX]; char buffer[256]; char bufferc[256]; char bufferw[256]; FILE *fptr1; FILE *fptr2; char *ptr; int id; int i; snprintf(backup, PATH_MAX, "%s.bak", config_file); fptr1 = fopen(config_file, "r"); fptr2 = fopen(backup, "w"); fgets(buffer, 256, fptr1); while (!feof(fptr1)) { if (strncasecmp(buffer, "MSGAREA", 7) == 0) { strcpy(bufferc, buffer); ptr = strtok(&bufferc[8], ","); if (ptr != NULL) { trimwhitespace(bufferw, 256, ptr); id = atoi(bufferw); if (id != areaid) { fputs(buffer, fptr2); } } } else { fputs(buffer, fptr2); } fgets(buffer, 256, fptr1); } fclose(fptr1); fclose(fptr2); unlink(config_file); rename(backup, config_file); } int main(int argc, char **argv) { char buffer[PATH_MAX]; struct msg_t msg; uuid_t myuuid; char msgid[37]; FILE *fptr; struct stat st; if (argc != 6) { fprintf(stderr, "Usage ./mnetsubunsub [Configfile] [ADD/REMOVE] [AREA#] [HOST#] [JamBase]"); return -1; } if (!parse_config_file(argv[1])) { fprintf(stderr, "Error parsing config file: %s\n", argv[1]); return -1; } if (baseoutdir == NULL) { fprintf(stderr, "OUTDIR must be defined\n"); return -1; } config_file = argv[1]; if (strcasecmp(argv[2], "ADD") == 0) { // send add control message memset(&msg, 0, sizeof(struct msg_t)); msg.area = atoi(argv[3]); sprintf(msg.from, "SYSTEM"); sprintf(msg.to, "SYSTEM"); sprintf(msg.subject, "ADD Message"); msg.timedate = time(NULL); msg.oaddr = mynode; msg.daddr = atoi(argv[4]); msg.type = 1; if (imhub) { snprintf(buffer, PATH_MAX, "%s/%d/", baseoutdir, msg.daddr); } else { snprintf(buffer, PATH_MAX, "%s/%d/", baseoutdir, hubnode); } if (stat(buffer, &st) != 0) { if (mkdir(buffer, 0755) != 0) { fprintf(stderr, "Error making directory %s\n", buffer); return -1; } } memset(msgid, 0, 37); uuid_generate(myuuid); uuid_unparse_lower(myuuid, msgid); if (imhub) { snprintf(buffer, PATH_MAX, "%s/%d/%d-%s.message", baseoutdir, msg.daddr, msg.daddr, msgid); } else { snprintf(buffer, PATH_MAX, "%s/%d/%d-%s.message", baseoutdir, hubnode, msg.daddr, msgid); } fptr = fopen(buffer, "wb"); if (fptr == NULL) { fprintf(stderr, "Error creating file %s\n", buffer); return -1; } fwrite(&msg, sizeof(struct msg_t), 1, fptr); fwrite("ADD\r", 4, 1, fptr); fclose(fptr); // add config line fptr = fopen(argv[1], "a"); fprintf(fptr, "MSGAREA %d, %d, %s\n", msg.area, msg.daddr, argv[5]); fclose(fptr); } else if (strcasecmp(argv[2], "REMOVE") == 0) { // send remove control message memset(&msg, 0, sizeof(struct msg_t)); msg.area = atoi(argv[3]); sprintf(msg.from, "SYSTEM"); sprintf(msg.to, "SYSTEM"); sprintf(msg.subject, "REMOVE Message"); msg.timedate = time(NULL); msg.oaddr = mynode; msg.daddr = atoi(argv[4]); msg.type = 1; if (imhub) { snprintf(buffer, PATH_MAX, "%s/%d/", baseoutdir, msg.daddr); } else { snprintf(buffer, PATH_MAX, "%s/%d/", baseoutdir, hubnode); } if (stat(buffer, &st) != 0) { if (mkdir(buffer, 0755) != 0) { fprintf(stderr, "Error making directory %s\n", buffer); return -1; } } memset(msgid, 0, 37); uuid_generate(myuuid); uuid_unparse_lower(myuuid, msgid); if (imhub) { snprintf(buffer, PATH_MAX, "%s/%d/%d-%s.message", baseoutdir, msg.daddr, msg.daddr, msgid); } else { snprintf(buffer, PATH_MAX, "%s/%d/%d-%s.message", baseoutdir, hubnode, msg.daddr, msgid); } fptr = fopen(buffer, "wb"); if (fptr == NULL) { fprintf(stderr, "Error creating file %s\n", buffer); return -1; } fwrite(&msg, sizeof(struct msg_t), 1, fptr); fwrite("REMOVE\r", 7, 1, fptr); fclose(fptr); // remove config line remove_config_file_area(msg.area); } return 0; }