/* * Copyright (c) 2026, Chloe Moffett * Provided under the BSD-3 clause */ #include #include #include #include #include #include "libremail/file.h" #include "libremail/common.h" /* Maximum command components */ #define CMD_MAX_CNP 6 /* Mailutil version */ #define MAILUTIL_VERSION "0.0.1" /* * Macro used to assert that the command list count is not * zero to avoid code duplication. */ #define ASSERT_COUNT(CNT) \ if ((CNT) == 0) { \ printf("error: cmdlist count is zero\n"); \ return -1; \ } /* * Macro used to ensure that overflows don't happen */ #define ASSERT_COUNT_N(CNT, MAX) \ if ((CNT) < (MAX)) { \ printf("error: too few parameters for command\n"); \ return -1; \ } static void help(void) { printf("usage: ./mailutil [... flags] [verb] [...]\n"); printf("... [-h] Display this help menu\n"); printf("... [-v] Display the version\n"); } static void version(void) { printf("Version v%s\n", MAILUTIL_VERSION); } static int cmd_mailbox_list(void) { DIR *dir; struct dirent *dirent; if ((dir = opendir(MAILBOX_PREFIX)) == NULL) { perror("opendir"); return -1; } while ((dirent = readdir(dir)) != NULL) { if (dirent->d_name[0] == '.') { continue; } printf("[mailbox] :: %s\n", dirent->d_name); } closedir(dir); return 0; } /* * Parse a "mailbox rm" command * * @cmdlist: Command list to parse * @count: Number of entries inside command list * * Returns zero on success */ static int cmd_mailbox_rm(const char *cmdlist[CMD_MAX_CNP], size_t count) { char pathbuf[64]; ASSERT_COUNT_N(count, 3); snprintf(pathbuf, sizeof(pathbuf), "%s/%s", MAILBOX_PREFIX, cmdlist[2]); /* Destroy the mailbox */ if (rmdir(pathbuf) < 0) { perror("rmdir"); return -1; } printf("deleted mailbox '%s'\n", cmdlist[2]); return 0; } /* * Parse a "mailbox create" command * * @cmdlist: Command list to parse * @count: Number of entries inside command list * * Returns zero on success */ static int cmd_mailbox_create(const char *cmdlist[CMD_MAX_CNP], size_t count) { char pathbuf[64]; ASSERT_COUNT_N(count, 3); snprintf(pathbuf, sizeof(pathbuf), "%s/%s", MAILBOX_PREFIX, cmdlist[2]); /* Create the mailbox */ if (try_mkdir(pathbuf, DEFAULT_MAILBOX_MODE) < 0) { printf("fatal: failed to create mailbox\n"); perror("try_mkdir"); return -1; } printf("created mailbox '%s' @ %s\n", cmdlist[2], pathbuf); return 0; } /* * Parse a "mailbox" command * * @cmdlist: Command list to parse * @count: Number of entries inside command list * * Returns zero on success */ static int cmd_mailbox(const char *cmdlist[CMD_MAX_CNP], size_t count) { ASSERT_COUNT_N(count, 2); if (strcmp(cmdlist[1], "create") == 0) { return cmd_mailbox_create(cmdlist, count); } if (strcmp(cmdlist[1], "list") == 0) { return cmd_mailbox_list(); } if (strcmp(cmdlist[1], "rm") == 0) { return cmd_mailbox_rm(cmdlist, count); } printf("error: bad parameter\n"); return -1; } /* * Parse a command given from the command line * * @cmdlist: Command list to parse * @count: Number of entries inside command list * * Returns zero on success */ static int parse_cmd(const char *cmdlist[CMD_MAX_CNP], size_t count) { ASSERT_COUNT(count); if (strcmp(cmdlist[0], "mailbox") == 0) { return cmd_mailbox(cmdlist, count); } printf("error: bad parameter\n"); return -1; } int main(int argc, char **argv) { int opt; const char *cmdlist[CMD_MAX_CNP]; size_t cmdlist_i = 0; if (argc < 2) { printf("fatal: too few arguments\n"); help(); return -1; } while ((opt = getopt(argc, argv, "hv")) != -1) { switch (opt) { case 'h': help(); return -1; case 'v': version(); return 0; } } /* Accumulate command line parameters */ while (optind < argc) { cmdlist[cmdlist_i++] = argv[optind++]; } if (parse_cmd(cmdlist, cmdlist_i) < 0) { printf("fatal: error parsing command list\n"); return -1; } return 0; }