diary

Text-based journaling program
git clone https://git.in0rdr.ch/diary.git
Log | Files | Refs | README | LICENSE

commit 7265315d86624fcf1cc1dcc4ddf6da2a500aea8d
parent ae94c615a96576e137e9c2db74ddcafe35f70643
Author: in0rdr <andreas.gruhler@uzh.ch>
Date:   Thu, 24 Nov 2016 01:13:20 +0800

Improves (file) path handling, reading and writing

Diffstat:
Mdiary.c | 158++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 109 insertions(+), 49 deletions(-)

diff --git a/diary.c b/diary.c @@ -23,7 +23,9 @@ struct tm cal_end; static const char* WEEKDAYS[] = {"Mo","Tu","We","Th","Fr","Sa","Su", NULL}; -void get_date_str(struct tm* date, char* date_str, int date_str_size) { +void fpath(char* dir, size_t dir_size, struct tm* date, char* rpath, size_t rpath_size); + +void get_date_str(struct tm* date, char* date_str, size_t date_str_size) { strftime(date_str, date_str_size, "%Y-%m-%d", date); } @@ -36,21 +38,28 @@ void draw_wdays(WINDOW* head) { wrefresh(head); } -void draw_calendar(WINDOW* number_pad, WINDOW* month_pad, char* diary_dir) { +void draw_calendar(WINDOW* number_pad, WINDOW* month_pad, char* diary_dir, size_t diary_dir_size) { struct tm i = cal_start; char month[10]; + char epath[100]; bool has_entry; while (mktime(&i) <= mktime(&cal_end)) { - has_entry = access(fpath(dirary_dir, &i), F_OK) != -1); - getyx(number_pad, cy, cx); + // get entry path and check for existence + fpath(diary_dir, diary_dir_size, &i, epath, sizeof epath); + has_entry = (access(epath, F_OK) != -1); + if (has_entry) wattron(number_pad, A_BOLD); + wprintw(number_pad, "%2i", i.tm_mday); + if (has_entry) wattroff(number_pad, A_BOLD); + waddch(number_pad, ' '); + // print month in sidebar if (i.tm_mday == 1) { strftime(month, sizeof month, "%b", &i); getyx(number_pad, cy, cx); @@ -65,38 +74,71 @@ void draw_calendar(WINDOW* number_pad, WINDOW* month_pad, char* diary_dir) { void update_date(WINDOW* dh) { char dstr[16]; mktime(&curs_date); - get_date_str(&curs_date, dstr, sizeof(dstr)); + get_date_str(&curs_date, dstr, sizeof dstr); mvwaddstr(dh, 0, 0, dstr); wrefresh(dh); } -char* fpath(char* dir, struct tm* date) { - char path[100]; - char dstr[16]; +void fpath(char* dir, size_t dir_size, struct tm* date, char* rpath, size_t rpath_size) { + // check size of result path + if (dir_size + 1 > rpath_size) { + fprintf(stderr, "Directory path too long"); + rpath == NULL; + return; + } + + // add path of the diary dir to result path + strcpy(rpath, dir); - // add path of the diary dir - strcpy(path, dir); - if (dir[strlen(dir) - 1] != '/') - strcat(path, "/"); + // check for terminating '/' in path + if (dir[dir_size - 1] != '/') { + // check size again to accomodate '/' + if (dir_size + 1 > rpath_size) { + fprintf(stderr, "Directory path too long"); + rpath == NULL; + return; + } + strcat(rpath, "/"); + } - // append date to the path - get_date_str(date, dstr, sizeof(dstr)); - strcat(path, dstr); + char dstr[16]; + get_date_str(date, dstr, sizeof dstr); - return path; + // append date to the result path + if (strlen(rpath) + sizeof dstr > rpath_size) { + fprintf(stderr, "File path too long"); + rpath == NULL; + return; + } + strcat(rpath, dstr); } -char* edit_cmd(char* dir, struct tm* date) { - static char ecmd[150]; +void edit_cmd(char* dir, size_t dir_size, struct tm* date, char* rcmd, size_t rcmd_size) { + // get editor from environment char* editor = getenv("EDITOR"); - if (editor == NULL) - return NULL; + if (editor == NULL) { + fprintf(stderr, "'EDITOR' environment variable not set"); + return; + } + + // set the edit command to env editor + if (strlen(editor) + 2 > rcmd_size) { + fprintf(stderr, "Binary path of default editor too long"); + return; + } + strcpy(rcmd, editor); + strcat(rcmd, " "); - strcpy(ecmd, editor); - strcat(ecmd, " "); - strcat(ecmd, fpath(dir, date)); + // get path of entry + char path[100]; + fpath(dir, dir_size, date, path, sizeof path); - return ecmd; + // concatenate editor command with entry path + if (strlen(rcmd) + strlen(path) + 1 > rcmd_size) { + fprintf(stderr, "Edit command too long"); + return; + } + strcat(rcmd, path); } bool is_leap(int year) { @@ -106,11 +148,14 @@ bool is_leap(int year) { return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); } -WINDOW* read_diary(char* dir, struct tm* date, WINDOW* prev, int width) { +WINDOW* read_diary(char* dir, size_t dir_size, struct tm* date, WINDOW* prev, int width) { wclear(prev); char buff[width]; + char path[100]; int i = 0; - char* path = fpath(dir, date); + + // get entry path + fpath(dir, dir_size, date, path, sizeof path); FILE* fp = fopen(path, "r"); if (fp != NULL) { @@ -138,13 +183,13 @@ bool go_to(WINDOW* calendar, WINDOW* month_sidebar, time_t date, int* cur_pad_po getyx(calendar, cy, cx); - // Remove the STANDOUT attribute from the day we are leaving + // remove the STANDOUT attribute from the day we are leaving chtype current_attrs = mvwinch(calendar, cy, cx) & A_ATTRIBUTES; - // Leave every attr as is, but turn off STANDOUT + // leave every attr as is, but turn off STANDOUT current_attrs &= ~A_STANDOUT; mvwchgat(calendar, cy, cx, 2, current_attrs, 0, NULL); - // Add the STANDOUT attribute to the day we are entering + // add the STANDOUT attribute to the day we are entering chtype new_attrs = mvwinch(calendar, diff_weeks, diff_wdays * 3) & A_ATTRIBUTES; new_attrs |= A_STANDOUT; mvwchgat(calendar, diff_weeks, diff_wdays * 3, 2, new_attrs, 0, NULL); @@ -153,8 +198,8 @@ bool go_to(WINDOW* calendar, WINDOW* month_sidebar, time_t date, int* cur_pad_po *cur_pad_pos = diff_weeks; if (diff_weeks > *cur_pad_pos + LINES - 2) *cur_pad_pos = diff_weeks - LINES + 2; - prefresh(month_sidebar, *cur_pad_pos, 0, 1, 0, LINES - 1, ASIDE_WIDTH); - prefresh(calendar, *cur_pad_pos, 0, 1, ASIDE_WIDTH, LINES - 1, ASIDE_WIDTH + CAL_WIDTH); + prefresh(month_sidebar, *cur_pad_pos, 0, 1, 0, LINES - 1, ASIDE_WIDTH); + prefresh(calendar, *cur_pad_pos, 0, 1, ASIDE_WIDTH, LINES - 1, ASIDE_WIDTH + CAL_WIDTH); return true; } @@ -186,24 +231,38 @@ void setup_cal_timeframe() { } int main(int argc, char** argv) { - // Get the diary directory via environment variable or argument - // If both are given, the argument takes precedence - char* diary_dir = NULL; + char diary_dir[80]; + char* env_var; + + // get the diary directory via environment variable or argument + // if both are given, the argument takes precedence if (argc < 2) { - diary_dir = getenv("DIARY_DIR"); - if (diary_dir == NULL) { + // the diary directory is not specified via command line argument + // use the environment variable if available + env_var = getenv("DIARY_DIR"); + if (env_var == NULL) { fprintf(stderr, "The diary directory must ge given as command line " "argument or in the DIARY_DIR environment variable\n"); return 1; } + + if (strlen(env_var) + 1 > sizeof diary_dir) { + fprintf(stderr, "Diary directory path too long\n"); + return 1; + } + strcpy(diary_dir, env_var); } else { - diary_dir = argv[1]; + if (strlen(argv[1]) + 1 > sizeof diary_dir) { + fprintf(stderr, "Diary directory path too long\n"); + return 1; + } + strcpy(diary_dir, argv[1]); } - // Check if that directory exists + // check if that directory exists DIR* diary_dir_ptr = opendir(diary_dir); if (diary_dir_ptr) { - // Directory exists, continue + // directory exists, continue closedir(diary_dir_ptr); } else if (errno == ENOENT) { fprintf(stderr, "The directory '%s' does not exist\n", diary_dir); @@ -228,7 +287,7 @@ int main(int argc, char** argv) { WINDOW* aside = newpad((YEAR_RANGE * 2 + 1) * 12 * MAX_MONTH_HEIGHT, ASIDE_WIDTH); WINDOW* cal = newpad((YEAR_RANGE * 2 + 1) * 12 * MAX_MONTH_HEIGHT, CAL_WIDTH); keypad(cal, TRUE); - draw_calendar(cal, aside, diary_dir); + draw_calendar(cal, aside, diary_dir, sizeof diary_dir); int ch, pad_pos = 0; struct tm new_date; @@ -236,21 +295,22 @@ int main(int argc, char** argv) { int prev_height = LINES - 1; bool ret = go_to(cal, aside, raw_time, &pad_pos); - // Mark current day + // mark current day chtype atrs = winch(cal) & A_ATTRIBUTES; wchgat(cal, 2, atrs | A_UNDERLINE, 0, NULL); prefresh(cal, pad_pos, 0, 1, ASIDE_WIDTH, LINES - 1, ASIDE_WIDTH + CAL_WIDTH); WINDOW* prev = newwin(prev_height, prev_width, 1, ASIDE_WIDTH + CAL_WIDTH); - prev = read_diary(diary_dir, &today, prev, prev_width); + prev = read_diary(diary_dir, sizeof diary_dir, &today, prev, prev_width); do { ch = wgetch(cal); new_date = curs_date; - char* ecmd = edit_cmd(diary_dir, &new_date); + char ecmd[150]; + edit_cmd(diary_dir, sizeof diary_dir, &new_date, ecmd, sizeof ecmd); switch(ch) { - // Basic movements + // basic movements case 'j': case KEY_DOWN: new_date.tm_mday += 7; @@ -272,7 +332,7 @@ int main(int argc, char** argv) { ret = go_to(cal, aside, mktime(&new_date), &pad_pos); break; - // Jump to top/bottom of page + // jump to top/bottom of page case 'g': ret = go_to(cal, aside, mktime(&cal_start), &pad_pos); break; @@ -280,7 +340,7 @@ int main(int argc, char** argv) { ret = go_to(cal, aside, mktime(&cal_end), &pad_pos); break; - // Jump backward/forward by a month + // jump backward/forward by a month case 'K': if (new_date.tm_mday == 1) new_date.tm_mon--; @@ -293,12 +353,12 @@ int main(int argc, char** argv) { ret = go_to(cal, aside, mktime(&new_date), &pad_pos); break; - // Today shortcut + // today shortcut case 't': new_date = today; ret = go_to(cal, aside, raw_time, &pad_pos); break; - // Edit/create a diary entry + // edit/create a diary entry case 'e': case '\n': if (ecmd) { @@ -317,7 +377,7 @@ int main(int argc, char** argv) { prev_width = COLS - ASIDE_WIDTH - CAL_WIDTH; wresize(prev, prev_height, prev_width); - prev = read_diary(diary_dir, &curs_date, prev, prev_width); + prev = read_diary(diary_dir, sizeof diary_dir, &curs_date, prev, prev_width); } } while (ch != 'q');