#include #include #include #include #include #include "platform.h" #include "config.h" int ensure_directory_exists(const char *path) { struct stat st; if (stat(path, &st) == 0) { /* Path exists, check if it's a directory */ #if defined(__MSDOS__) || defined(__DOS__) /* DOS/Turbo C: use bit test because S_ISDIR macro may be missing */ if ((st.st_mode & S_IFMT) == S_IFDIR) { return 1; } #else /* Unix/Linux/Windows modern: use standard POSIX macro */ if (S_ISDIR(st.st_mode)) { return 1; } #endif else { fprintf(stderr, "Error: %s exists but is not a directory\n", path); return 0; } } /* Directory doesn't exist, try to create it */ if (mkdir_portable(path) != 0) { fprintf(stderr, "Error: Cannot create directory %s\n", path); return 0; } return 1; } int get_cnotes_path(char *buffer, size_t bufsize) { const char *custom_path; const char *home; size_t len; /* First check for CNOTES_PATH environment variable override */ custom_path = getenv(CNOTES_PATH_ENV); if (custom_path != NULL && strlen(custom_path) > 0) { if (strlen(custom_path) >= bufsize) { fprintf(stderr, "Error: Path too long\n"); return 0; } strcpy(buffer, custom_path); return 1; } /* Fall back to HOME_ENV + CNOTES_DIR */ home = getenv(HOME_ENV); if (home == NULL) { fprintf(stderr, "Error: %s environment variable not set\n", HOME_ENV); fprintf(stderr, "Hint: Set %s to specify notes directory\n", CNOTES_PATH_ENV); return 0; } /* Build path: $HOME/CNOTES_DIR (or just $HOME if CNOTES_DIR is empty) */ len = strlen(home); if (strlen(CNOTES_DIR) == 0) { /* DOS mode: use home directory directly */ if (len >= bufsize) { fprintf(stderr, "Error: Path too long\n"); return 0; } strcpy(buffer, home); } else { /* Unix/Windows: append CNOTES_DIR to home */ if (len + strlen(CNOTES_DIR) + 2 > bufsize) { fprintf(stderr, "Error: Path too long\n"); return 0; } sprintf(buffer, "%s" PATH_SEP_STR "%s", home, CNOTES_DIR); } return 1; } int write_entry(const char *category, const char *message) { char dir_path[512]; char file_path[600]; FILE *file; time_t now; struct tm *tm_info; char date[11]; char time_str[6]; char padded_category[CATEGORY_LENGTH + 1]; char truncated_message[FREETEXT_MAX_LENGTH + 1]; int i; /* Get current date and time */ now = time(NULL); if (now == -1) { fprintf(stderr, "Error: Cannot get current time\n"); return 0; } tm_info = localtime(&now); if (tm_info == NULL) { fprintf(stderr, "Error: Cannot convert time\n"); return 0; } /* Format date as YYYY-MM-DD */ strftime(date, sizeof(date), "%Y-%m-%d", tm_info); /* Format time as HH:MM */ strftime(time_str, sizeof(time_str), "%H:%M", tm_info); /* Pad category to 10 characters */ strncpy(padded_category, category, CATEGORY_LENGTH); padded_category[CATEGORY_LENGTH] = '\0'; for (i = (int)strlen(padded_category); i < CATEGORY_LENGTH; i++) { padded_category[i] = ' '; } padded_category[CATEGORY_LENGTH] = '\0'; /* Truncate message to 80 characters */ strncpy(truncated_message, message, FREETEXT_MAX_LENGTH); truncated_message[FREETEXT_MAX_LENGTH] = '\0'; /* Get cnotes directory path */ if (!get_cnotes_path(dir_path, sizeof(dir_path))) { return 0; } /* Ensure directory exists */ if (!ensure_directory_exists(dir_path)) { return 0; } /* Build full file path */ sprintf(file_path, "%s" PATH_SEP_STR "%s", dir_path, CNOTES_FILE); /* Open file in append mode */ file = fopen(file_path, "a"); if (file == NULL) { fprintf(stderr, "Error: Cannot open file %s\n", file_path); return 0; } /* Write entry */ fprintf(file, "%s,%s,%s,\"%s\"\n", date, time_str, padded_category, truncated_message); fclose(file); printf("Entry added to %s\n", file_path); return 1; } void print_usage(const char *prog_name) { fprintf(stderr, "Usage: %s [-c category] message\n", prog_name); fprintf(stderr, " -c category Optional category (max 10 chars, default: %s)\n", DEFAULT_CATEGORY); fprintf(stderr, " message Required message text (max 80 chars). Wrapped in double-quotes.\n"); } int main(int argc, char *argv[]) { const char *category; const char *message; int i; category = DEFAULT_CATEGORY; message = NULL; /* Parse command-line arguments */ i = 1; while (i < argc) { if (strcmp(argv[i], "-c") == 0) { if (i + 1 >= argc) { fprintf(stderr, "Error: -c option requires an argument\n"); print_usage(argv[0]); return 1; } category = argv[i + 1]; i += 2; } else { message = argv[i]; i++; break; /* Only take first non-option as message */ } } /* Validate arguments */ if (message == NULL || strlen(message) == 0) { fprintf(stderr, "Error: Message is required\n"); print_usage(argv[0]); return 1; } /* Write entry */ if (!write_entry(category, message)) { return 1; } return 0; }