diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | append.c | 63 | ||||
-rw-r--r-- | dump.c | 37 | ||||
-rw-r--r-- | edit.c | 42 | ||||
-rw-r--r-- | main.c | 539 | ||||
-rw-r--r-- | record.c | 153 | ||||
-rw-r--r-- | system.c | 174 | ||||
-rw-r--r-- | weekly.h | 101 |
8 files changed, 573 insertions, 538 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index cedc265..c81ef79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,4 +5,4 @@ if(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif() set(CMAKE_C_STANDARD 99) -add_executable(weekly main.c) +add_executable(weekly main.c system.c record.c edit.c dump.c append.c) diff --git a/append.c b/append.c new file mode 100644 index 0000000..61b6ef6 --- /dev/null +++ b/append.c @@ -0,0 +1,63 @@ +#include "weekly.h" + +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; +} + @@ -0,0 +1,37 @@ +#include "weekly.h" + +int dump_file(const char *filename, int style) { + FILE *fp; + fp = fopen(filename, "r"); + if (!fp) { + return -1; + } + struct Record *record; + while ((record = record_read(&fp)) != NULL) { + record_show(record, style); + record_free(record); + puts(""); + } + fclose(fp); + return 0; +} + +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; +} @@ -0,0 +1,42 @@ +#include "weekly.h" + +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; +} @@ -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_); diff --git a/record.c b/record.c new file mode 100644 index 0000000..cab4db5 --- /dev/null +++ b/record.c @@ -0,0 +1,153 @@ +#include "weekly.h" + +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 *record_read(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); +} diff --git a/system.c b/system.c new file mode 100644 index 0000000..39f40cc --- /dev/null +++ b/system.c @@ -0,0 +1,174 @@ +#include "weekly.h" + +#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 + +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; +} + +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 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; +} + diff --git a/weekly.h b/weekly.h new file mode 100644 index 0000000..3ed45bb --- /dev/null +++ b/weekly.h @@ -0,0 +1,101 @@ +#ifndef WEEKLY_H +#define WEEKLY_H +#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 + +struct Record { + char *date; + char *time; + char *user; + char *host; + char *data; +}; + +int edit_file(const char *filename); + +void record_free(struct Record *record); +struct Record *record_parse(const char *content); +struct Record *record_read(FILE **fp); +void record_show(struct Record *record, int style); +int dump_file(const char *filename, int style); +int dump_week(const char *root, int year, int week, int style); + +char *init_tempfile(const char *basepath, const char *ident, char *data); +ssize_t get_file_size(const char *filename); +int append_stdin(const char *filename); +int append_contents(const char *dest, const char *src); + +int dir_empty(const char *path); +char *find_program(const char *name); +int make_path(char *basepath); +char *make_output_path(char *basepath, char *path, int year, int week, int day_of_week); + +#endif // WEEKLY_H
\ No newline at end of file |