diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2022-01-18 23:04:23 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2022-01-18 23:04:23 -0500 |
commit | fa3606a495e4df0c6231e433d3dffa19b7471a60 (patch) | |
tree | b82e449f91e4f9002decd9b4a6c1e24db1ada910 /main.c | |
parent | 76063b6148ee7f0d274799c562f896c0a2efa2cb (diff) | |
download | weekly-fa3606a495e4df0c6231e433d3dffa19b7471a60.tar.gz |
Refactor project structure
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 539 |
1 files changed, 2 insertions, 537 deletions
@@ -1,73 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#if defined(_WIN32) || defined(_WIN64) - #define HAVE_WINDOWS 1 -#else - #define HAVE_WINDOWS 0 -#endif - -#if HAVE_WINDOWS && (defined(_MSC_BUILD) || defined(_MSC_VER) || defined(_MSC_EXTENSIONS)) - #define HAVE_MSVC 1 -#else - #define HAVE_MSVC 0 -#endif - -#if HAVE_WINDOWS && (defined(__MINGW32__) || defined(__MINGW64__)) - #define HAVE_MINGW 1 -#else - #define HAVE_MINGW 0 -#endif - -#if HAVE_WINDOWS - #if HAVE_MSVC - #include <io.h> - #if !defined(F_OK) - #define F_OK 0 - #endif - typedef long long ssize_t; - typedef unsigned long long size_t; - #endif - - #if HAVE_MINGW - #include <dirent.h> - #endif - - #include <direct.h> - #include <windows.h> - #define DIRSEP_C '\\' - #define DIRSEP_S "\\" - #define PATHSEP_C ';' - #define PATHSEP_S ";" - #define PATHVAR "path" - #define mkdir(X, Y) mkdir(X) - #define mkstemp _mktemp -#else - #include <limits.h> - #include <dirent.h> - #include <sys/stat.h> - #include <unistd.h> - #include <pwd.h> - #include <errno.h> - #define DIRSEP_C '/' - #define DIRSEP_S "/" - #define PATHSEP_C ':' - #define PATHSEP_S ":" - #define PATHVAR "PATH" -#endif - -#if !defined(PATH_MAX) -#define PATH_MAX 1024 -#endif - -#define ARG(X) strcmp(argv[i], X) == 0 -#define ARG_VERIFY_NEXT() (argv[i+1] != NULL) -#define RECORD_STYLE_SHORT 0 -#define RECORD_STYLE_LONG 1 -#define RECORD_STYLE_CSV 2 -#define RECORD_STYLE_DICT 3 +#include "weekly.h" char *program_name; char *homedir; @@ -106,475 +37,9 @@ void usage() { printf(USAGE_STATEMENT, is_base ? name + 1 : program_name, VERSION); } -char *find_program(const char *name) { -#if HAVE_WINDOWS - int found_extension; -#endif - static char exe[PATH_MAX] = {0}; - char *token; - char *pathvar; - char *abs_prefix[] = { - "/", "./", ".\\" - }; - - for (size_t i = 0; i < sizeof(abs_prefix) / sizeof(char *); i++) { - if ((strlen(name) > 1 && name[1] == ':') || !strncmp(name, abs_prefix[i], strlen(abs_prefix[i]))) { - strcpy(exe, name); - return exe; - } - } - - pathvar = getenv(PATHVAR); - if (!pathvar) { - return NULL; - } - - token = strtok(pathvar, PATHSEP_S); - while (token != NULL) { - char filename[PATH_MAX] = {0}; - sprintf(filename, "%s%c%s", token, DIRSEP_C, name); -#if HAVE_WINDOWS - // I am aware of PATHEXT. Let's stick to binary executables and shell scripts - char *ext[] = {".bat", ".cmd", ".com", ".exe"}; - char filename_orig[PATH_MAX] = {0}; - - found_extension = 0; - for (size_t i = 0; i < sizeof(ext) / sizeof(char *); i++) { - if (strstr(filename, ext[i]) != NULL) { - found_extension = 1; - break; - } - } - if (!found_extension) { - for (size_t i = 0; i < sizeof(ext) / sizeof(char *); i++) { - strcpy(filename_orig, filename); - strcat(filename, ext[i]); - if (access(filename, F_OK) == 0) { - strcpy(exe, filename); - return exe; - } - strcpy(filename, filename_orig); - } - } else { - if (access(filename, F_OK) == 0) { - strcpy(exe, filename); - return exe; - } - } -#else - if (access(filename, F_OK) == 0) { - strcpy(exe, filename); - return exe; - } -#endif - token = strtok(NULL, PATHSEP_S); - } - return NULL; -} - -int edit_file(const char *filename) { - char editor[255] = {0}; - char editor_cmd[PATH_MAX] = {0}; - int result; - const char *user_editor; - - // Allow the user to override the default editor (vi/notepad) - user_editor = getenv("EDITOR"); - char *editor_path; - if (user_editor != NULL) { - sprintf(editor, "%s", user_editor); - } else { - editor_path = find_program("vim"); - if (editor_path != NULL) { - sprintf(editor, "\"%s\"", editor_path); - } -#if HAVE_WINDOWS - else { - strcpy(editor, "notepad"); - } -#endif - } - - if (!strlen(editor)) { - fprintf(stderr, "Unable to find editor: %s\n", editor); - exit(1); - } - - // Tell editor to jump to the end of the file (when supported) - // Standard 'vi' does not support '+' - if(strstr(editor, "vim")) { - strcat(editor, " +"); - } else if (strstr(editor, "nano") != NULL) { - strcat(editor, " +9999"); - } - - sprintf(editor_cmd, "%s %s", editor, filename); - result = system(editor_cmd); - return result; -} - -int make_path(char *basepath) { - return mkdir(basepath, 0755); -} - -char *make_output_path(char *basepath, char *path, int year, int week, int day_of_week) { - strcpy(path, basepath); - // Add trailing slash if it's not there - if (strlen(basepath) > 0 && strlen(basepath) - 1 != DIRSEP_C) { - strcat(path, DIRSEP_S); - } - - make_path(path); - // year - sprintf(path + strlen(path), "%d%c", year, DIRSEP_C); - make_path(path); - // week of year - sprintf(path + strlen(path), "%d%c", week, DIRSEP_C); - make_path(path); - // day of that week - sprintf(path + strlen(path), "%d", day_of_week); - - return path; -} - -ssize_t get_file_size(const char *filename) { - ssize_t result; - FILE *fp; - fp = fopen(filename, "r"); - if (!fp) { - return -1; - } - fseek(fp, 0, SEEK_END); - result = ftell(fp); - fclose(fp); - return result; -} - -char *init_tempfile(const char *basepath, const char *ident, char *data) { - FILE *fp; - char *filename; - filename = calloc(PATH_MAX, sizeof(char)); - sprintf(filename, "%s%cweekly_%s.XXXXXX", basepath, DIRSEP_C, ident); - if ((mkstemp(filename)) < 0) { - return NULL; - } - unlink(filename); - - fp = fopen(filename, "w+b"); - if (!fp) { - return NULL; - } - - if (data != NULL) { - fwrite(data, sizeof(char), strlen(data), fp); - //fprintf(fp, "%s\n", data); - } - fclose(fp); - - if (chmod(filename, 0600) < 0) { - return NULL; - } - return filename; -} - -int append_stdin(const char *filename) { - FILE *fp; - size_t bufsz; - char *buf; - - bufsz = BUFSIZ; - buf = malloc(bufsz); - if (!buf) { - return -1; - } - - fp = fopen(filename, "a"); - if (!fp) { - perror(filename); - free(buf); - return -1; - } - -#if HAVE_WINDOWS - while (fgets(buf, (int) bufsz, stdin) != NULL) { - fprintf(fp, "%s", buf); - } -#else - while (getline(&buf, &bufsz, stdin) >= 0) { - fprintf(fp, "%s", buf); - } -#endif - free(buf); - fclose(fp); - return 0; -} - -int append_contents(const char *dest, const char *src) { - char buf[BUFSIZ] = {0}; - FILE *fpi, *fpo; - - fpi = fopen(src, "rb+"); - if (!fpi) { - perror(src); - return -1; - } - - fpo = fopen(dest, "ab+"); - if (!fpo) { - perror(dest); - fclose(fpi); - return -1; - } - - // Append source file to destination file - while (fread(buf, sizeof(char), sizeof(buf), fpi) > 0) { - fwrite(buf, sizeof(char), strlen(buf), fpo); - } - buf[0] = '\n'; - fwrite(buf, sizeof(char), 1, fpo); - - fclose(fpo); - fclose(fpi); - return 0; -} - -struct Record { - char *date; - char *time; - char *user; - char *host; - char *data; -}; - -void record_free(struct Record *record) { - if (record != NULL) { - free(record->date); - free(record->time); - free(record->host); - free(record->user); - free(record->data); - free(record); - } -} - -struct Record *record_parse(const char *content) { - char *next; - struct Record *result; - - result = calloc(1, sizeof(*result)); - if (!result) { - perror("Unable to allocate record"); - return NULL; - } - - char *p = strdup(content); - next = strtok(p, "\n"); - while (next != NULL) { - char key[10] = {0}; - char value[255] = {0}; - - sscanf(next, "## %9[^: ]:%254s[^\n]", key, value); - if (strncmp(next, "## ", 2) != 0) { - break; - } - if (!strcmp(key, "date")) - result->date = strdup(value); - else if (!strcmp(key, "time")) - result->time = strdup(value); - else if (!strcmp(key, "author")) - result->user = strdup(value); - else if (!strcmp(key, "host")) - result->host = strdup(value); - - next = strtok(NULL, "\n"); - } - - if (next != NULL) { - if (memcmp(next, "\x02\x02\x02", 3) == 0) { - next += 4; - } - result->data = strdup(next); - } else { - // Empty data record, die - record_free(result); - result = NULL; - } - - free(p); - return result; -} - -struct Record *get_records(FILE **fp) { - ssize_t soh, sot, eot; - size_t record_size; - char task[2] = {0}; - char *buf = calloc(BUFSIZ, sizeof(char)); - - if (!buf) { - return NULL; - } - - if (!*fp) { - free(buf); - return NULL; - } - - // Start of header offset - soh = 0; - // Start of text offset - sot = 0; - // End of text offset - eot = 0; - - while (fread(task, sizeof(char), 1, *fp) > 0) { - if (task[0] == '\x01' && fread(task, sizeof(char), 2, *fp) > 0) { - // start header - if (memcmp(task, "\x01\x01", 2) == 0) { - soh = ftell(*fp); - } - } else if (task[0] == '\x02' && fread(task, sizeof(char), 2, *fp) > 0) { - if (memcmp(task, "\x02\x02", 2) == 0) { - sot = ftell(*fp); - } - // start of text - } else if (task[0] == '\x03' && fread(task, sizeof(char), 2, *fp) > 0) { - if (memcmp(task, "\x03\x03", 2) == 0) { - eot = ftell(*fp); - break; - } - } else { - continue; - } - memset(task, '\0', sizeof(task)); - } - - // Verify the record is not too small, and contained a start of text marker - record_size = eot - soh; - if (record_size < 1 && !sot) { - free(buf); - return NULL; - } - - // Go back to start of header - fseek(*fp, soh, SEEK_SET); - // Read the entire record - fread(buf, sizeof(char), record_size, *fp); - // Remove end of text marker - memset(buf + (record_size - 4), '\0', 4); - // Truncate buffer at end of line - buf[strlen(buf) - 1] = '\0'; - - // Emit record - struct Record *result; - result = record_parse(buf); - - free(buf); - - return result; -} - -void record_show(struct Record *record, int style) { - const char *fmt; - switch (style) { - case RECORD_STYLE_LONG: - fmt = "## Date: %s\n## Time: %s\n## User: %s\n## Host: %s\n%s\n"; - break; - case RECORD_STYLE_CSV: - fmt = "%s,%s,%s,%s,\"%s\""; // Trailing linefeed omitted for visual clarity - break; - case RECORD_STYLE_DICT: - fmt = "{" - "\"date\": \"%s\",\n" - "\"time\": \"%s\",\n" - "\"user\": \"%s\",\n" - "\"host\": \"%s\",\n" - "\"data\": \"%s\"}\n"; - break; - case RECORD_STYLE_SHORT: - default: - fmt = "%s - %s - %s (%s):\n%s\n"; - break; - } - printf(fmt, record->date, record->time, record->user, record->host, record->data); -} -int dump_file(const char *filename, int style) { - FILE *fp; - fp = fopen(filename, "r"); - if (!fp) { - return -1; - } - struct Record *record; - while ((record = get_records(&fp)) != NULL) { - record_show(record, style); - record_free(record); - puts(""); - } - fclose(fp); - return 0; -} - -#if HAVE_MSVC -int dir_empty (const char *path) { - HANDLE hd; - WIN32_FIND_DATA data; - size_t i; - char winpath[PATH_MAX] = {0}; - - i = 0; - sprintf(winpath, "%s%c*.*", path, DIRSEP_C); - if ((hd = FindFirstFile(path, &data)) != INVALID_HANDLE_VALUE) { - do { - i++; - } while (FindNextFile(hd, &data) != 0); - FindClose(hd); - } else { - return -1; - } - return i != 0; -} -#else -int dir_empty(const char *path) { - DIR *dir; - struct dirent *dp; - size_t i; - - dir = opendir(path); - if (!dir) { - return -1; - } - - i = 0; - while ((dp = readdir(dir)) != NULL) { - if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { - continue; - } - i++; - } - closedir(dir); - return i != 0; -} -#endif -int dump_week(const char *root, int year, int week, int style) { - char path_week[PATH_MAX] = {0}; - char path_year[PATH_MAX] = {0}; - const int max_days = 7; - sprintf(path_year, "%s%c%d", root, DIRSEP_C, year); - sprintf(path_week, "%s%c%d%c%d", root, DIRSEP_C, year, DIRSEP_C, week); - - if (!dir_empty(path_year)) { - return -1; - } - - for (int i = 0; i < max_days; i++) { - char tmp[PATH_MAX]; - sprintf(tmp, "%s%c%d", path_week, DIRSEP_C, i); - dump_file(tmp, style); - } - return 0; -} int main(int argc, char *argv[]) { // System info @@ -657,7 +122,7 @@ int main(int argc, char *argv[]) { strcpy(username, user->pw_name); } #endif - // Get data; + // Get date and time strftime(datestamp, sizeof(datestamp) - 1, "%m/%d/%Y", tm_); strftime(timestamp, sizeof(timestamp) - 1, "%H:%M:%S", tm_); |