diff --git a/Makefile b/Makefile index ee4301c..c012f47 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ BINDIR = ./bin CC = gcc -g -Os -Wall SRC = \ - $(SRCDIR)/activity.c \ + $(SRCDIR)/action.c \ $(SRCDIR)/args.c \ $(SRCDIR)/db.c \ $(SRCDIR)/pager.c \ @@ -22,11 +22,10 @@ SRC = \ $(SRCDIR)/project.c \ $(SRCDIR)/table.c \ $(SRCDIR)/task.c \ - $(SRCDIR)/user.c \ $(SRCDIR)/util.c OBJ = \ - $(OBJDIR)/activity.o \ + $(OBJDIR)/action.o \ $(OBJDIR)/args.o \ $(OBJDIR)/db.o \ $(OBJDIR)/pager.o \ @@ -34,7 +33,6 @@ OBJ = \ $(OBJDIR)/project.o \ $(OBJDIR)/table.o \ $(OBJDIR)/task.o \ - $(OBJDIR)/user.o \ $(OBJDIR)/util.o APP = pit @@ -48,8 +46,8 @@ $(OBJDIR): $(APP): $(OBJ) $(CC) -o $(BINDIR)/$(APP) $(OBJ) -$(OBJDIR)/activity.o: $(SRCDIR)/activity.c $(SRCDIR)/pit.h $(SRCDIR)/object.h $(SRCDIR)/table.h - $(CC) -o $(OBJDIR)/activity.o -c $(SRCDIR)/activity.c +$(OBJDIR)/action.o: $(SRCDIR)/action.c $(SRCDIR)/pit.h $(SRCDIR)/object.h $(SRCDIR)/table.h + $(CC) -o $(OBJDIR)/action.o -c $(SRCDIR)/action.c $(OBJDIR)/args.o: $(SRCDIR)/args.c $(SRCDIR)/pit.h $(SRCDIR)/object.h $(SRCDIR)/table.h $(CC) -o $(OBJDIR)/args.o -c $(SRCDIR)/args.c @@ -72,9 +70,6 @@ $(OBJDIR)/table.o: $(SRCDIR)/table.c $(SRCDIR)/pit.h $(SRCDIR)/object.h $(SRCDIR $(OBJDIR)/task.o: $(SRCDIR)/task.c $(SRCDIR)/pit.h $(SRCDIR)/object.h $(SRCDIR)/table.h $(CC) -o $(OBJDIR)/task.o -c $(SRCDIR)/task.c -$(OBJDIR)/user.o: $(SRCDIR)/user.c $(SRCDIR)/pit.h $(SRCDIR)/object.h $(SRCDIR)/table.h - $(CC) -o $(OBJDIR)/user.o -c $(SRCDIR)/user.c - $(OBJDIR)/util.o: $(SRCDIR)/util.c $(SRCDIR)/pit.h $(SRCDIR)/object.h $(SRCDIR)/table.h $(CC) -o $(OBJDIR)/util.o -c $(SRCDIR)/util.c diff --git a/src/action.c b/src/action.c new file mode 100644 index 0000000..691f987 --- /dev/null +++ b/src/action.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include "pit.h" + +static void action_list() +{ + PAction pa; + PPager ppager; + + pit_db_load(); + if (actions->number_of_records > 0) { + ppager = pit_pager_initialize(PAGER_ACTION, actions->number_of_records); + for_each_action(pa) { + pit_pager_print(ppager, (uchar *)pa); + } + pit_pager_flush(ppager); + } +} + +uchar *pit_action(ulong id, char *subject, char *message) +{ + static Action action; + + memset(&action, 0, sizeof(action)); + + action.subject_id = id; + strncpy(action.subject, subject, sizeof(action.subject) - 1); + strncpy(action.username, current_user(), sizeof(action.username) - 1); + strncpy(action.message, message, sizeof(action.message) - 1); + + return pit_table_insert(actions, (uchar *)&action); +} + +int pit_log(char *argv[]) +{ + action_list(); + return 1; +} \ No newline at end of file diff --git a/src/activity.c b/src/activity.c deleted file mode 100644 index cf542d2..0000000 --- a/src/activity.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include "pit.h" - -ulong subject_id; /* Reference to the specific Project, Task, or Note. */ -char subject[16]; /* Project, Task, or Note. */ -char message[255]; /* Log message. */ -ulong created_by; /* Who added log message? */ -time_t created_at; /* When log message was added? */ - -PActivity pit_add_activity(ulong id, char *subject, char *message, ulong user_id) { - static Activity activity; - - memset(&activity, 0, sizeof(activity)); - - activity.subject_id = id; - activity.created_by = user_id; - activity.created_at = time(NULL); - strncpy(activity.subject, subject, sizeof(activity.subject) - 1); - strncpy(activity.message, message, sizeof(activity.message) - 1); - - return &activity; -} diff --git a/src/args.c b/src/args.c index d46dd91..7696b6a 100644 --- a/src/args.c +++ b/src/args.c @@ -46,7 +46,7 @@ ulong pit_arg_number(char **arg, char *required) // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm); // time_t mktime ( struct tm * timeptr ); -time_t pit_arg_time(char **arg, char *required) +time_t pit_arg_date(char **arg, char *required) { time_t seconds = (time_t)-1; struct tm tm; @@ -100,4 +100,31 @@ time_t pit_arg_time(char **arg, char *required) } return seconds; -} \ No newline at end of file +} + +time_t pit_arg_time(char **arg, char *required) +{ + time_t seconds = (time_t)-1; + char *format; + struct tm tm; + + if (required && (!*arg || pit_arg_is_option(arg))) { + die("missing %s", required); + } else { + memset(&tm, 0, sizeof(tm)); /* Suppored time formats are HH, HH:MM, and :MM */ + if (**arg == ':') { + format = ":%M"; /* Minutes only */ + } else if (strchr(*arg, ':')) { + format = "%H:%M"; /* Hours and minutes */ + } else { + format = "%H"; /* Hours only */ + } + if (strptime(*arg, format, &tm)) { + seconds = mktime(&tm); + } else { + die("invalid time format: %s", *arg); + } + } + + return seconds; +} diff --git a/src/db.c b/src/db.c index 85a2e77..8dd2587 100644 --- a/src/db.c +++ b/src/db.c @@ -18,6 +18,35 @@ static char *pit_file_name() return file_name; } +static void read_header(FILE *file) +{ + Header hd; + + if (fread(&hd, sizeof(hd), 1, file)) { + if (hd.signature[0] != 0x50 || hd.signature[1] != 0x49 || hd.signature[2] != 0x54) { + die("invalid pit file"); + } + if (hd.schema_version != 0x01) { + die("invalid pit file version"); + } + } else { + die("couldn't read header"); + } +} + +static void write_header(FILE *file) +{ + Header hd; + + hd.signature[0] = 0x50; hd.signature[1] = 0x49; hd.signature[2] = 0x54; + hd.schema_version = 0x01; + memset(&hd.reserved, 0, sizeof(hd.reserved)); + + if (!fwrite(&hd, sizeof(hd), 1, file)) { + die("couldn't write header"); + } +} + int pit_init(char *argv[]) { char **arg = &argv[1]; char *file_name = pit_file_name(); @@ -44,24 +73,22 @@ void pit_db_load() { if (!file) { perish(file_name); } else { - projects = pit_table_load(file); - tasks = pit_table_load(file); - notes = pit_table_load(file); - activities = pit_table_load(file); - users = pit_table_load(file); + read_header(file); + projects = pit_table_load(file); + tasks = pit_table_load(file); + notes = pit_table_load(file); + actions = pit_table_load(file); fclose(file); } } void pit_db_initialize() { - projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); - tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); - notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); - activities = pit_table_initialize(sizeof(Activity), TABLE_HAS_CREATED_AT); - users = pit_table_initialize(sizeof(User), TABLE_HAS_ID); + projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); + tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); + notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); + actions = pit_table_initialize(sizeof(Action), TABLE_HAS_CREATED_AT); - pit_table_insert(users, (uchar *)pit_current_user()); - pit_table_insert(activities, (uchar *)pit_add_activity(0, "", "Initialized pit", 1)); + pit_action(0, "pit", "Initialized pit"); pit_db_save(); } @@ -73,11 +100,11 @@ void pit_db_save() { if (!file) { perish(file_name); } else { + write_header(file); pit_table_save(file, projects); pit_table_save(file, tasks); pit_table_save(file, notes); - pit_table_save(file, activities); - pit_table_save(file, users); + pit_table_save(file, actions); fclose(file); } } diff --git a/src/object.h b/src/object.h index 7056501..05f8843 100644 --- a/src/object.h +++ b/src/object.h @@ -1,16 +1,20 @@ #if !defined(__MODELS_H__) #define __MODELS_H__ +typedef struct _Header { + char signature[3]; + char schema_version; + char reserved[16]; +} Header, *PHeader; + typedef struct _Project { ulong id; + char username[32]; /* User the project belongs to. */ char name[128]; /* Project name. */ char status[16]; /* Project status. */ - ulong number_of_open_tasks; /* Number of open tasks. */ - ulong number_of_closed_tasks; /* Number of closed tasks. */ - ulong closed_by; /* Who closed the project? */ + ulong number_of_tasks; /* Number of tasks for the project. */ ulong created_by; /* Who created the project? */ ulong updated_by; /* Who last updated the project? */ - time_t closed_at; /* When the project was closed? */ time_t created_at; /* When the project was created? */ time_t updated_at; /* When the project was last updated? */ } Project, *PProject; @@ -18,15 +22,13 @@ typedef struct _Project { typedef struct _Task { ulong id; ulong project_id; /* Which project the task belongs to? */ + char username[32]; /* User the task belongs to. */ char name[128]; /* Task name. */ char status[16]; /* Task status. */ char priority[16]; /* Task priority. */ - time_t deadline; /* Task deadline. */ - ulong number_of_notes; /* Number of notes. */ - ulong closed_by; /* Who closed the task? */ - ulong created_by; /* Who created the task? */ - ulong updated_by; /* Who last updated the task? */ - time_t closed_at; /* When the task was closed? */ + time_t date; /* Generic date/time, ex: task deadline. */ + time_t time; /* Generic time, ex: time spent on the task. */ + ulong number_of_notes; /* Number of notes for the task. */ time_t created_at; /* When the task was created? */ time_t updated_at; /* When the task was last updated? */ } Task, *PTask; @@ -34,25 +36,18 @@ typedef struct _Task { typedef struct _Note { ulong id; ulong task_id; /* Task the note belongs to. */ + char username[32]; /* User the note belongs to. */ char message[255]; /* The body of the note. */ - ulong created_by; /* Who created the note? */ - ulong updated_by; /* Who last updated the note? */ time_t created_at; /* When the note was created? */ time_t updated_at; /* When the note was last updated? */ } Note, *PNote; -typedef struct _Activity { +typedef struct _Action { ulong subject_id; /* Reference to the specific Project, Task, or Note. */ char subject[16]; /* Project, Task, or Note. */ + char username[32]; /* Who added the log message? */ char message[255]; /* Log message. */ - ulong created_by; /* Who added log message? */ time_t created_at; /* When log message was added? */ -} Activity, *PActivity; - -typedef struct _User { - ulong id; - char username[32]; /* Username. */ - char email[32]; /* User's email. */ -} User, *PUser; +} Action, *PAction; #endif diff --git a/src/pager.c b/src/pager.c index a7aa463..e588658 100644 --- a/src/pager.c +++ b/src/pager.c @@ -27,6 +27,7 @@ void pit_pager_print(PPager ppager, uchar *entry) case PAGER_TASK: sprintf(str, "%lu", ((PTask)*pentry)->id); ppager->max.task.id = max(ppager->max.task.id, strlen(str)); + ppager->max.task.username = max(ppager->max.task.username, strlen(((PTask)*pentry)->username)); ppager->max.task.name = max(ppager->max.task.name, strlen(((PTask)*pentry)->name)); ppager->max.task.status = max(ppager->max.task.status, strlen(((PTask)*pentry)->status)); ppager->max.task.priority = max(ppager->max.task.priority, strlen(((PTask)*pentry)->priority)); @@ -34,9 +35,14 @@ void pit_pager_print(PPager ppager, uchar *entry) case PAGER_PROJECT: sprintf(str, "%lu", ((PProject)*pentry)->id); ppager->max.project.id = max(ppager->max.project.id, strlen(str)); + ppager->max.project.username = max(ppager->max.project.username, strlen(((PProject)*pentry)->username)); ppager->max.project.name = max(ppager->max.project.name, strlen(((PProject)*pentry)->name)); ppager->max.project.status = max(ppager->max.project.status, strlen(((PProject)*pentry)->status)); break; + case PAGER_ACTION: + ppager->max.action.username = max(ppager->max.action.username, strlen(((PAction)*pentry)->username)); + ppager->max.action.subject = max(ppager->max.action.subject, strlen(((PAction)*pentry)->subject)); + break; default: die("invalid pager type: %d\n", ppager->type); } @@ -46,17 +52,18 @@ void pit_pager_print(PPager ppager, uchar *entry) void pit_pager_flush(PPager ppager) { uchar **pentry; - char format[64]; + char format[64], timestamp[32]; switch(ppager->type) { case PAGER_TASK: - sprintf(format, "%%c %%%dlu: %%-%ds %%-%ds %%-%ds (%%lu note%%s)\n", - ppager->max.task.id, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.name + sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds (%%lu note%%s)\n", + ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.name ); for_each_entry(ppager, pentry) { printf(format, (((PTask)*pentry)->id == tasks->current ? '*' : ' '), ((PTask)*pentry)->id, + ((PTask)*pentry)->username, ((PTask)*pentry)->status, ((PTask)*pentry)->priority, ((PTask)*pentry)->name, @@ -66,21 +73,32 @@ void pit_pager_flush(PPager ppager) } break; case PAGER_PROJECT: - sprintf(format, "%%c %%%dlu: %%-%ds %%-%ds (%%lu open, %%lu closed task%%s)\n", - ppager->max.project.id, ppager->max.project.status, ppager->max.project.name + sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] %%-%ds (%%lu task%%s)\n", + ppager->max.project.id, ppager->max.project.username, ppager->max.project.status, ppager->max.project.name ); for_each_entry(ppager, pentry) { printf(format, (((PProject)*pentry)->id == projects->current ? '*' : ' '), ((PProject)*pentry)->id, + ((PProject)*pentry)->username, ((PProject)*pentry)->status, ((PProject)*pentry)->name, - ((PProject)*pentry)->number_of_open_tasks, - ((PProject)*pentry)->number_of_closed_tasks, + ((PProject)*pentry)->number_of_tasks, (projects->number_of_records != 1 ? "s" : "") ); } break; + case PAGER_ACTION: + sprintf(format, "%%s (%%-%ds): %%s\n", ppager->max.action.username); + for_each_entry(ppager, pentry) { + strftime(timestamp, sizeof(timestamp), "%b %d, %Y %H:%M", localtime(&((PAction)*pentry)->created_at)); + printf(format, + timestamp, + ((PAction)*pentry)->username, + ((PAction)*pentry)->message + ); + } + break; default: pit_pager_free(ppager); die("invalid pager type: %d\n", ppager->type); diff --git a/src/pager.h b/src/pager.h index 4714adc..cd5b539 100644 --- a/src/pager.h +++ b/src/pager.h @@ -1,11 +1,10 @@ #if !defined(__PAGER_H__) #define __PAGER_H__ -#define PAGER_ACTIVITY 1 -#define PAGER_PROJECT 2 -#define PAGER_TASK 4 -#define PAGER_NOTE 8 -#define PAGER_USER 16 +#define PAGER_ACTION 1 +#define PAGER_PROJECT 2 +#define PAGER_TASK 4 +#define PAGER_NOTE 8 typedef struct _Pager { ulong type; @@ -14,16 +13,23 @@ typedef struct _Pager { union { struct { int id; + int username; int name; int status; } project; struct { int id; + int username; int name; int status; int priority; - int deadline; + int date; + int time; } task; + struct { + int username; + int subject; + } action; } max; } Pager, *PPager; diff --git a/src/pit.c b/src/pit.c index 956938e..fb5ee04 100644 --- a/src/pit.c +++ b/src/pit.c @@ -7,8 +7,7 @@ PTable projects; PTable tasks; PTable notes; -PTable activities; -PTable users; +PTable actions; static int usage() { printf("usage...\n"); @@ -62,7 +61,7 @@ int main(int argc, char *argv[]) { } else if (strstr(commands[2], argv[1]) == commands[2]) { return 1; /* pit_note(&argv[1]); */ } else if (strstr(commands[3], argv[1]) == commands[3]) { - return 1; /* pit_log(&argv[1]); */ + return pit_log(&argv[1]); } else if (strstr(commands[4], argv[1]) == commands[4]) { return pit_init(&argv[1]); } diff --git a/src/pit.h b/src/pit.h index f26270b..664c998 100644 --- a/src/pit.h +++ b/src/pit.h @@ -28,24 +28,23 @@ typedef int bool; #define max(a,b) ((a) > (b) ? (a) : (b)) #endif -#define for_each_activity(ptr) for (ptr = (PActivity)activities->slots; (ptr - (PActivity)activities->slots) < activities->number_of_records; ptr++) -#define for_each_project(ptr) for (ptr = (PProject)projects->slots; (ptr - (PProject)projects->slots) < projects->number_of_records; ptr++) -#define for_each_note(ptr) for (ptr = (PNote)notes->slots; (ptr - (PNote)notes->slots) < notes->number_of_records; ptr++) -#define for_each_task(ptr) for (ptr = (PTask)tasks->slots; (ptr - (PTask)tasks->slots) < tasks->number_of_records; ptr++) -#define for_each_user(ptr) for (ptr = (PUser)users->slots; (ptr - (PUser)users->slots) < users->number_of_records; ptr++) +#define for_each_project(ptr) for (ptr = (PProject)projects->slots; (ptr - (PProject)projects->slots) < projects->number_of_records; ptr++) +#define for_each_task(ptr) for (ptr = (PTask)tasks->slots; (ptr - (PTask)tasks->slots) < tasks->number_of_records; ptr++) +#define for_each_note(ptr) for (ptr = (PNote)notes->slots; (ptr - (PNote)notes->slots) < notes->number_of_records; ptr++) +#define for_each_action(ptr) for (ptr = (PAction)actions->slots; (ptr - (PAction)actions->slots) < actions->number_of_records; ptr++) /* Externals. */ -extern PTable activities; +extern PTable actions; extern PTable notes; extern PTable projects; extern PTable tasks; -extern PTable users; /* args.c */ int pit_arg_is_option(char **arg); int pit_arg_option(char **arg); char *pit_arg_string(char **arg, char *required); ulong pit_arg_number(char **arg, char *required); +time_t pit_arg_date(char **arg, char *required); time_t pit_arg_time(char **arg, char *required); /* db.c */ @@ -54,18 +53,19 @@ void pit_db_load(); void pit_db_save(); void pit_db_initialize(); -/* activity.c project.c task.c user.c */ -int pit_project(char *argv[]); -int pit_task(char *argv[]); -char *pit_current_user(); -PActivity pit_add_activity(ulong id, char *subject, char *message, ulong user_id); +/* log.c project.c task.c user.c */ +int pit_project(char *argv[]); +int pit_task(char *argv[]); +int pit_log(char *argv[]); +char *pit_current_user(); +uchar *pit_action(ulong id, char *subject, char *message); /* util.c */ -void die(char *msg, ...); -void perish(char *prefix); +void die(char *msg, ...); +void perish(char *prefix); char *mem2str(char *mem, int len); +char *current_user(); char *home_dir(char *username, int len); char *expand_path(char *path, char *expanded); - #endif diff --git a/src/project.c b/src/project.c index ced2f00..b993ea0 100644 --- a/src/project.c +++ b/src/project.c @@ -42,19 +42,13 @@ static void create_project(char *name, char *status) memset(&p, 0, sizeof(p)); - if (!status) { - status = "active"; - } + if (!status) status = "active"; printf("creating project [%s], status [%s]\n", name, status); strncpy(p.name, name, sizeof(p.name) - 1); strncpy(p.status, status, sizeof(p.status) - 1); - p.number_of_open_tasks = 0; - p.number_of_closed_tasks = 0; - p.closed_by = 0; - p.created_by = p.updated_by = 1; // TODO - p.closed_at = 0; - p.created_at = p.updated_at = time(NULL); + strncpy(p.username, current_user(), sizeof(p.username) - 1); + pp = (PProject)pit_table_insert(projects, (uchar *)&p); pit_table_mark(projects, pp->id); pit_db_save(); @@ -68,18 +62,13 @@ static int show_project(ulong number) pit_db_load(); pp = (PProject)pit_table_find(projects, number); if (pp) { - printf("%lu: %s (%s, %lu open task%s, %lu closed task%s)\n", - pp->id, pp->name, pp->status, - pp->number_of_open_tasks, (pp->number_of_open_tasks != 1 ? "s" : ""), - pp->number_of_closed_tasks, (pp->number_of_closed_tasks != 1 ? "s" : "")); - if (pp->number_of_open_tasks > 0) { + printf("%lu: %s (%s, %lu task%s)\n", + pp->id, pp->name, pp->status, pp->number_of_tasks, (pp->number_of_tasks != 1 ? "s" : "")); + if (pp->number_of_tasks > 0) { PTask pt = (PTask)tasks->slots; - puts("Open tasks:"); + puts("Tasks:"); for_each_task(pt) { - if (pt->closed_at) { - continue; - } printf(" %c %lu: %s (%lu notes)\n", (pt->id == tasks->current ? '*' : ' '), pt->id, pt->name, pt->number_of_notes); } } diff --git a/src/task.c b/src/task.c index 9c30602..a98b46a 100644 --- a/src/task.c +++ b/src/task.c @@ -1,21 +1,23 @@ #include #include +#include #include #include "pit.h" -static void task_list(char *name, char *status, char *priority, time_t deadline); -static void task_create(char *name, char *status, char *priority, time_t deadline); +static void task_list(char *name, char *status, char *priority, time_t date, time_t time); +static void task_create(char *name, char *status, char *priority, time_t date, time_t time); static void task_show(ulong number); static void task_delete(ulong number); -static void task_update(ulong number, char *name, char *status, char *priority, time_t deadline); -static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *deadline); +static void task_update(ulong number, char *name, char *status, char *priority, time_t date, time_t time); +static void task_log(char *message, ulong id, ...); +static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *date, time_t *time); /* ** CREATING TASKS: -** pit task -c name [-s status] [-d deadline] [-p priority] +** pit task -c name [-s status] [-p priority] [-d date] [-t time] ** ** UPDATING TASKS: -** pit task -u [number] [-n name] [-s status] [-d deadline] [-p priority] +** pit task -u [number] [-n name] [-s status] [-p priority] [-d date] [-t time] ** ** DELETING TASKS: ** pit task -d [number] @@ -24,10 +26,10 @@ static void task_parse_options(char **arg, char **name, char **status, char **pr ** pit task [[-q] number] ** ** LISTING TASKS: -** pit task -q [-s status] [-d deadline] [-p priority] +** pit task -q [-s status] [-p priority] [-d date] [-t time] */ -static void task_list(char *name, char *status, char *priority, time_t deadline) +static void task_list(char *name, char *status, char *priority, time_t date, time_t time) { PProject pp; PTask pt; @@ -47,7 +49,7 @@ static void task_list(char *name, char *status, char *priority, time_t deadline) } } -static void task_create(char *name, char *status, char *priority, time_t deadline) +static void task_create(char *name, char *status, char *priority, time_t date, time_t time) { pit_db_load(); @@ -60,29 +62,24 @@ static void task_create(char *name, char *status, char *priority, time_t deadlin memset(&t, 0, sizeof(t)); - if (!status) { - status = "open"; - } - if (!priority) { - priority = "normal"; - } + if (!status) status = "open"; + if (!priority) priority = "normal"; - printf("creating task: %s, status: %s, priority: %s, deadline: %s", name, status, priority, ctime(&deadline)); + printf("creating task: %s, status: %s, priority: %s, date: %s", name, status, priority, ctime(&date)); strncpy(t.name, name, sizeof(t.name) - 1); strncpy(t.status, status, sizeof(t.status) - 1); strncpy(t.priority, priority, sizeof(t.priority) - 1); + strncpy(t.username, current_user(), sizeof(t.username) - 1); t.project_id = pp->id; - t.deadline = deadline; - t.number_of_notes = 0; - t.closed_by = 0; - t.created_by = t.updated_by = 1; // TODO - t.closed_at = 0; - t.created_at = t.updated_at = time(NULL); + t.date = date; + t.time = 0; /* TODO */ pt = (PTask)pit_table_insert(tasks, (uchar *)&t); pit_table_mark(tasks, pt->id); - pp->number_of_open_tasks++; + pp->number_of_tasks++; + // pit_action(pit->id, "task", "created task #%d: %s (status: %s, priority: %s, date: %s)", pt->id, name, status, priority, (date ? ctime(&date) : "n/a")); + task_log("created task #%d: %s (status: %s, priority: %s, date: %s)", pt->id, name, status, priority, (date ? ctime(&date) : "n/a")); pit_db_save(); } } @@ -97,12 +94,23 @@ static void task_delete(ulong number) printf("task_delete(%lu)\n", number); } -static void task_update(ulong number, char *name, char *status, char *priority, time_t deadline) +static void task_update(ulong number, char *name, char *status, char *priority, time_t date, time_t time) { - printf("task_update: #%lu, name: %s, status: %s, priority: %s, deadline: %s", number, name, status, priority, ctime(&deadline)); + printf("task_update: #%lu, name: %s, status: %s, priority: %s, date: %s", number, name, status, priority, ctime(&date)); } -static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *deadline) +static void task_log(char *message, ulong id, ...) +{ + char str[128]; + va_list params; + + va_start(params, id); + vsnprintf(str, sizeof(str), (char *)&id, params); + pit_action(id, "task", str); + va_end(params); +} + +static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *date, time_t *time) { while(*++arg) { switch(pit_arg_option(arg)) { @@ -113,7 +121,10 @@ static void task_parse_options(char **arg, char **name, char **status, char **pr *priority = pit_arg_string(++arg, "task priority"); break; case 'd': - *deadline = pit_arg_time(++arg, "task deadline"); + *date = pit_arg_date(++arg, "task date"); + break; + case 't': + *time = pit_arg_time(++arg, "task time"); break; case 'n': if (name) { @@ -130,46 +141,47 @@ int pit_task(char *argv[]) { char **arg = &argv[1]; char *name = NULL, *status = NULL, *priority = NULL; - time_t deadline = (time_t)0; + time_t date = (time_t)0; + time_t time = (time_t)0; ulong number = 0L; if (!*arg) { - task_list(NULL, NULL, NULL, 0); /* List all tasks (with default paramaters). */ + task_list(NULL, NULL, NULL, 0, 0); /* List all tasks (with default paramaters). */ } else { /* pit task [number] */ number = pit_arg_number(arg, NULL); if (number) { task_show(number); } else { switch(pit_arg_option(arg)) { - case 'c': /* pit task -c name [-s status] [-p priority] [-d deadline] */ + case 'c': /* pit task -c name [-s status] [-p priority] [-d date] [-t time] */ name = pit_arg_string(++arg, "task name"); - task_parse_options(arg, NULL, &status, &priority, &deadline); - task_create(name, status, priority, deadline); + task_parse_options(arg, NULL, &status, &priority, &date, &time); + task_create(name, status, priority, date, time); break; - case 'u': /* pit task -u [number] [-n name] [-s status] [-d deadline] [-p priority] */ + case 'u': /* pit task -u [number] [-n name] [-s status] [-p priority] [-d date] [-t time]*/ number = pit_arg_number(++arg, NULL); if (!number) --arg; - task_parse_options(arg, &name, &status, &priority, &deadline); - if (!name && !status && !priority && !deadline) { + task_parse_options(arg, &name, &status, &priority, &date, &time); + if (!name && !status && !priority && !date && !time) { die("nothing to update"); } else { - task_update(number, name, status, priority, deadline); + task_update(number, name, status, priority, date, time); } break; case 'd': /* pit task -d [number] */ number = pit_arg_number(++arg, NULL); task_delete(number); break; - case 'q': /* pit task -q [number | [-n name] [-s status] [-d deadline] [-p priority]] */ + case 'q': /* pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]] */ number = pit_arg_number(++arg, NULL); if (number) { task_show(number); } else { - task_parse_options(--arg, &name, &status, &priority, &deadline); - if (!name && !status && !priority && !deadline) { + task_parse_options(--arg, &name, &status, &priority, &date, &time); + if (!name && !status && !priority && !date && !time) { task_show(0); } else { - task_list(name, status, priority, deadline); + task_list(name, status, priority, date, time); } } break; diff --git a/src/user.c b/src/user.c deleted file mode 100644 index 5dc6e84..0000000 --- a/src/user.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include -#include -#include "pit.h" - -char *pit_current_user() { - return getlogin(); -} \ No newline at end of file diff --git a/src/util.c b/src/util.c index 4a62752..118acac 100644 --- a/src/util.c +++ b/src/util.c @@ -14,6 +14,20 @@ char *mem2str(char *mem, int len) { return str; } +char *current_user() { + static char *username = NULL; + + if (!username) { + struct passwd *pws = getpwuid(geteuid()); + if (!pws) { + perish("no username?!"); + } else { + username = pws->pw_name; + } + } + return username; +} + char *home_dir(char *username, int len) { char *str = mem2str(username, len); struct passwd *pw = getpwnam(str); @@ -47,3 +61,11 @@ char *expand_path(char *path, char *expanded) { return expanded; } + +#ifdef TEST +int main(int argc, char *argv[]) { + printf("your username: %s\n", current_user()); + printf("your (cached) username: %s\n", current_user()); + return 1; +} +#endif