aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c269
1 files changed, 226 insertions, 43 deletions
diff --git a/main.c b/main.c
index 4ab8bb6..5c850c6 100644
--- a/main.c
+++ b/main.c
@@ -2,19 +2,75 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <pwd.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>
+ #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)
char *program_name;
-char journalroot[1024] = {0};
-char intermediates[1024] = {0};
+char *homedir;
+char journalroot[PATH_MAX] = {0};
+char intermediates[PATH_MAX] = {0};
const char *VERSION = "1.0.0";
const char *FMT_HEADER = "## date: %s\n"
+ "## time: %s\n"
"## author: %s\n"
"## host: %s\n";
const char *USAGE_STATEMENT = \
@@ -32,30 +88,99 @@ void usage() {
unsigned is_base;
is_base = 0;
- name = strrchr(program_name, '/');
+ name = strrchr(program_name, DIRSEP_C);
if (name != NULL) {
is_base = 1;
}
printf(USAGE_STATEMENT, is_base ? name + 1 : program_name, VERSION);
}
+int find_program(const char *name) {
+ char *token;
+ int found;
+ int found_extension;
+ char *pathvar;
+
+ pathvar = getenv(PATHVAR);
+ if (!pathvar) {
+ return -1;
+ }
+
+ found = 0;
+ 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) {
+ found = 1;
+ break;
+ }
+ strcpy(filename, filename_orig);
+ }
+ } else {
+ if (access(filename, F_OK) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ break;
+#else
+ if (access(filename, F_OK) == 0) {
+ found = 1;
+ break;
+ }
+#endif
+ token = strtok(NULL, PATHSEP_S);
+ }
+ return found;
+}
+
int edit_file(const char *filename) {
- char editor[255];
- char editor_cmd[1024];
+ 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)
+ // Allow the user to override the default editor (vi/notepad)
user_editor = getenv("EDITOR");
if (user_editor != NULL) {
strcpy(editor, user_editor);
} else {
- strcpy(editor, "vi");
+ if (find_program("vim")) {
+ strcpy(editor, "vim");
+ }
+#if HAVE_WINDOWS
+ else {
+ strcpy(editor, "notepad");
+ }
+#endif
+ }
+
+ if (!find_program(editor)) {
+ fprintf(stderr, "Unable to find editor: %s\n", editor);
+ exit(1);
}
// When using vi, set editor cursor to the end of the file
if(strstr(editor, "vim") || strstr(editor, "vi")) {
- strcat(editor, " +99999");
+ strcat(editor, " + -c \"set nobackup\" ");
}
sprintf(editor_cmd, "%s %s", editor, filename);
@@ -70,16 +195,16 @@ int make_path(char *basepath) {
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 != '/') {
- strcat(path, "/");
+ if (strlen(basepath) > 0 && strlen(basepath) - 1 != DIRSEP_C) {
+ strcat(path, DIRSEP_S);
}
make_path(path);
// year
- sprintf(path + strlen(path), "%d/", year);
+ sprintf(path + strlen(path), "%d%c", year, DIRSEP_C);
make_path(path);
// week of year
- sprintf(path + strlen(path), "%d/", week);
+ sprintf(path + strlen(path), "%d%c", week, DIRSEP_C);
make_path(path);
// day of that week
sprintf(path + strlen(path), "%d", day_of_week);
@@ -102,8 +227,8 @@ ssize_t get_file_size(const char *filename) {
char *init_tempfile(const char *basepath, char *data) {
FILE *fp;
- static char tempfile[1024];
- sprintf(tempfile, "%s/weekly.XXXXXX", basepath);
+ static char tempfile[PATH_MAX];
+ sprintf(tempfile, "%s%cweekly.XXXXXX", basepath, DIRSEP_C);
if ((mkstemp(tempfile)) < 0) {
return NULL;
}
@@ -126,7 +251,8 @@ int append_stdin(const char *filename) {
size_t bufsz;
char *buf;
- buf = malloc(BUFSIZ);
+ bufsz = BUFSIZ;
+ buf = malloc(bufsz);
if (!buf) {
return -1;
}
@@ -137,9 +263,15 @@ int append_stdin(const char *filename) {
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;
@@ -186,6 +318,26 @@ int dump_file(const char *filename) {
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;
@@ -206,22 +358,23 @@ int dir_empty(const char *path) {
closedir(dir);
return i != 0;
}
+#endif
int dump_week(const char *root, int year, int week) {
- char path_week[1024] = {0};
- char path_year[1024] = {0};
+ char path_week[PATH_MAX] = {0};
+ char path_year[PATH_MAX] = {0};
const int max_days = 7;
- sprintf(path_year, "%s/%d", root, year);
- sprintf(path_week, "%s/%d/%d", root, year, week);
+ 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)) {
+ if (!dir_empty(path_year)) {
return -1;
}
for (int i = 0; i < max_days; i++) {
- char tmp[1024];
- sprintf(tmp, "%s/%d", path_week, i);
+ char tmp[PATH_MAX];
+ sprintf(tmp, "%s%c%d", path_week, DIRSEP_C, i);
dump_file(tmp);
}
return 0;
@@ -229,20 +382,30 @@ int dump_week(const char *root, int year, int week) {
int main(int argc, char *argv[]) {
// System info
- struct passwd *user;
char sysname[255] = {0};
char username[255] = {0};
+#if HAVE_WINDOWS
+ DWORD usernamesz;
+ usernamesz = sizeof(username);
+ DWORD sysnamesz;
+ sysnamesz = sizeof(sysname);
+ homedir = getenv("USERPROFILE");
+#else
+ struct passwd *user;
+ homedir = getenv("HOME");
+#endif
- // Time and date
+ // Time and datestamp
time_t t;
struct tm *tm_;
int year, week, day_of_week;
- char date[255] = {0};
+ char datestamp[255] = {0};
+ char timestamp[255] = {0};
// Path and data buffers
char *tempfile;
- char journalfile[1024] = {0};
- char output[255];
+ char journalfile[PATH_MAX] = {0};
+ char header[255];
// Argument triggers
int do_stdin;
@@ -264,6 +427,18 @@ int main(int argc, char *argv[]) {
week = (tm_->tm_yday + 7 - (tm_->tm_wday ? (tm_->tm_wday - 1) : 6)) / 7;
day_of_week = tm_->tm_wday;
+#if HAVE_WINDOWS
+ // Get system name
+ if(!GetComputerName(sysname, &sysnamesz)) {
+ perror("Unable to get system host name");
+ strcpy(sysname, "unknown");
+ }
+ // Get user information
+ if(!GetUserName(username, &usernamesz)) {
+ perror("Unable to read account information");
+ strcpy(username, "unknown");
+ }
+#else
// Get system name
if (gethostname(sysname, sizeof(sysname) - 1) < 0) {
perror("Unable to get system host name");
@@ -278,13 +453,20 @@ int main(int argc, char *argv[]) {
} else {
strcpy(username, user->pw_name);
}
-
- strftime(date, sizeof(date) - 1, "%c", tm_);
+#endif
+ // Get data;
+ strftime(datestamp, sizeof(datestamp) - 1, "%m/%d/%Y", tm_);
+ strftime(timestamp, sizeof(timestamp) - 1, "%H:%M:%S", tm_);
// Populate header string
- sprintf(output, FMT_HEADER, date, user->pw_name, sysname);
- sprintf(journalroot, "%s/.weekly", getenv("HOME"));
- sprintf(intermediates, "%s/tmp", journalroot);
+#if HAVE_WINDOWS
+ sprintf(header, FMT_HEADER, datestamp, timestamp, username, sysname);
+ sprintf(journalroot, "%s%c.weekly", homedir, DIRSEP_C);
+#else
+ sprintf(header, FMT_HEADER, datestamp, timestamp, user->pw_name, sysname);
+ sprintf(journalroot, "%s%c.weekly", homedir, DIRSEP_C);
+#endif
+ sprintf(intermediates, "%s%ctmp", journalroot, DIRSEP_C);
// Prime argument triggers
do_stdin = 0;
@@ -359,15 +541,19 @@ int main(int argc, char *argv[]) {
exit(0);
}
+ // Create weekly root directory
+ make_path(journalroot);
+
// Write header string to temporary file
make_path(intermediates);
- if ((tempfile = init_tempfile(intermediates, output)) == NULL) {
+ if ((tempfile = init_tempfile(intermediates, header)) == NULL) {
perror("Unable to create temporary file");
exit(1);
}
// Create new weekly journalfile path
if (make_output_path(journalroot, journalfile, year, week, day_of_week) < 0) {
+ fprintf(stderr, "Unable to create output path: %s (%s)\n", journalfile, strerror(errno));
perror(journalfile);
unlink(tempfile);
exit(1);
@@ -395,25 +581,22 @@ int main(int argc, char *argv[]) {
ssize_t tempfile_newsize;
tempfile_newsize = get_file_size(tempfile);
if (tempfile_newsize <= tempfile_size) {
- fprintf(stderr, "Intermediate file unchanged, or smaller:\nOriginal size: %zi\nNew size: %zi\n",
- tempfile_size, tempfile_newsize);
+ fprintf(stderr, "Empty message, aborting.\n");
unlink(tempfile);
exit(1);
}
// Copy data from the temporary file to the weekly journal path
if (append_contents(journalfile, tempfile) < 0) {
- perror(journalfile);
+ fprintf(stderr, "Unable to append contents of '%s' to '%s' (%s)\n", tempfile, journalfile, strerror(errno));
exit(1);
}
// Nuke the temporary file
if (unlink(tempfile) < 0) {
- perror(tempfile);
+ fprintf(stderr, "Unable to remove temporary file: %s (%s)\n", tempfile, strerror(errno));
exit(1);
}
- // Inform the user
- printf("Wrote: %s\n", journalfile);
return 0;
}