//usr/bin/env run.sh $0 "$@"; exit // : out wip /* I have the following spec, I need you to write a C program that fills this spec: - this program is called 'wip' and will record 'updates' - an 'update' is a line of text with a timestamp - this program should use 'argp.h' for processing command line arguments - The command line interface has two subcommands, "submit" and "review" - submit command: - takes a line of text and writes the timestamp and line of text separated by a tab to a file called 'wip.dat'. This represents one 'update' - the timestamp format should be "%Y-%m-%d %H:%M:%S" - review command: - reads the file 'wip.dat' and prints all the updates for the given week. - takes an flag '--period' for determining which week to report updates for - '--period' takes an argument which can be either 'thisweek' or 'lastweek', defaulting to 'thisweek' if not given Here is some example usage: $ wip submit "This is my update" $ wip submit "This is a second update" $ wip review Updates for this week: + This is my update + This is a second update $ wip review -p thisweek Updates for this week: + This is my update + This is a second update $ wip review --period lastweek + this was an update from last week */ #include #include #include #include #include #define WIP_FILENAME "wip.dat" #define TIMESTAMP_FORMAT "%Y-%m-%d %H:%M:%S" const char *argp_program_version = "wip 1.0"; const char *argp_program_bug_address = ""; static char doc[] = "A simple tool to record and review updates"; static struct argp_option options[] = { {"period", 'p', "PERIOD", 0, "Set the period for review (thisweek, lastweek)"}, {0} }; struct arguments { char *command; char *update; char *period; }; static error_t parse_opt (int key, char *arg, struct argp_state *state) { struct arguments *arguments = state->input; switch (key) { case 'p': arguments->period = arg; break; case ARGP_KEY_ARG: if (arguments->command == NULL) { arguments->command = arg; } else if (arguments->update == NULL) { arguments->update = arg; } break; default: return ARGP_ERR_UNKNOWN; } return 0; } static struct argp argp = { options, parse_opt, "COMMAND [UPDATE]", doc }; void submit_update (char *update) { FILE *file = fopen (WIP_FILENAME, "a"); if (file == NULL) { printf ("Could not open %s\n", WIP_FILENAME); return; } time_t now; time (&now); struct tm *timeinfo = localtime (&now); char timestamp[20]; strftime (timestamp, sizeof (timestamp), TIMESTAMP_FORMAT, timeinfo); fprintf (file, "%s\t%s\n", timestamp, update); fclose (file); } void review_updates (char *period) { FILE *file = fopen (WIP_FILENAME, "r"); if (file == NULL) { printf ("Could not open %s\n", WIP_FILENAME); return; } time_t now; time (&now); struct tm *timeinfo = localtime (&now); int current_week = timeinfo->tm_yday / 7; if (strcmp (period, "lastweek") == 0) { current_week--; } char line[256]; while (fgets (line, sizeof (line), file)) { struct tm timeinfo_line = { 0 }; strptime (line, TIMESTAMP_FORMAT, &timeinfo_line); int line_week = timeinfo_line.tm_yday / 7; if (line_week == current_week) { printf ("+ %s", strchr (line, '\t') + 1); } } fclose (file); } int main (int argc, char **argv) { struct arguments arguments; arguments.command = NULL; arguments.update = NULL; arguments.period = "thisweek"; argp_parse (&argp, argc, argv, 0, 0, &arguments); if (arguments.command == NULL) { printf ("No command provided. Expected 'submit' or 'review'.\n"); return 1; } if (strcmp (arguments.command, "submit") == 0) { if (arguments.update == NULL) { printf ("No update provided for 'submit' command.\n"); return 1; } submit_update (arguments.update); } else if (strcmp (arguments.command, "review") == 0) { review_updates (arguments.period); } else { printf ("Unknown command '%s'. Expected 'submit' or 'review'.\n", arguments.command); return 1; } return 0; }