/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2011-2019 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Mailutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Mailutils. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tesh.h" int sort_option; int prefix_len; static int compare_response (void const *a, void const *b) { struct mu_list_response const *ra = a; struct mu_list_response const *rb = b; if (ra->level < rb->level) return -1; if (ra->level > rb->level) return 1; return strcmp (ra->name, rb->name); } static int _print_list_entry (void *item, void *data) { struct mu_list_response *resp = item; int len = data ? *(int*) data : 0; mu_printf ("%c%c %c %4d %s\n", (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) ? 'd' : '-', (resp->type & MU_FOLDER_ATTRIBUTE_FILE) ? 'f' : '-', resp->separator ? resp->separator : ' ', resp->level, resp->name + len); return 0; } static int com_list (int argc, char **argv, mu_assoc_t options, void *env) { mu_folder_t folder = env; int rc; mu_list_t list; mu_printf ("listing '%s' '%s'\n", argv[1], argv[2]); rc = mu_folder_list (folder, argv[1], argv[2], 0, &list); if (rc) mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_list", argv[1], rc); else { if (sort_option) mu_list_sort (list, compare_response); mu_list_foreach (list, _print_list_entry, &prefix_len); mu_list_destroy (&list); } return 0; } static int com_lsub (int argc, char **argv, mu_assoc_t options, void *env) { mu_folder_t folder = env; int rc; mu_list_t list; mu_printf ("listing subscriptions for '%s' '%s'\n", argv[1], argv[2]); rc = mu_folder_lsub (folder, argv[1], argv[2], &list); if (rc) mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_lsub", argv[1], rc); else { if (sort_option) mu_list_sort (list, compare_response); mu_list_foreach (list, _print_list_entry, NULL); mu_list_destroy (&list); } return 0; } static int com_rename (int argc, char **argv, mu_assoc_t options, void *env) { int rc; mu_folder_t folder = env; mu_printf ("renaming %s to %s\n", argv[1], argv[2]); rc = mu_folder_rename (folder, argv[1], argv[2]); if (rc) mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_rename", argv[1], rc); else mu_printf ("rename successful\n"); return 0; } static int com_subscribe (int argc, char **argv, mu_assoc_t options, void *env) { mu_folder_t folder = env; int rc; mu_printf ("subscribing %s\n", argv[1]); rc = mu_folder_subscribe (folder, argv[1]); if (rc) mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_subscribe", argv[1], rc); else mu_printf ("subscribe successful\n"); return 0; } static int com_unsubscribe (int argc, char **argv, mu_assoc_t options, void *env) { mu_folder_t folder = env; int rc; mu_printf ("unsubscribing %s\n", argv[1]); rc = mu_folder_unsubscribe (folder, argv[1]); if (rc) mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_unsubscribe", argv[1], rc); else mu_printf ("unsubscribe successful\n"); return 0; } static int com_scan (int argc, char **argv, mu_assoc_t options, void *env) { mu_folder_t folder = env; struct mu_folder_scanner scn = MU_FOLDER_SCANNER_INITIALIZER; char *s; int rc; if (argc > 1) { scn.refname = argv[1]; if (argc == 3) scn.pattern = argv[2]; } mu_list_create (&scn.result); if (mu_assoc_lookup (options, "maxdepth", &s) == 0) { char *p; errno = 0; scn.max_level = strtoul (s, &p, 10); if (errno || *p) { mu_error ("-maxdepth=%s: invalid depth", s); return 0; } } if (mu_assoc_lookup (options, "type", &s) == 0) { mu_record_t rec; rc = mu_registrar_lookup_scheme (s, &rec); if (rc == 0) { if (!scn.records) MU_ASSERT (mu_list_create (&scn.records)); MU_ASSERT (mu_list_append (scn.records, rec)); } else { if (rc == MU_ERR_NOENT) mu_error ("%s: no such record found", s); else mu_diag_funcall (MU_DIAG_ERROR, "mu_registrar_lookup_scheme", NULL, rc); mu_list_destroy (&scn.records); return 0; } } rc = mu_folder_scan (folder, &scn); if (rc) mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_scan", NULL, rc); else { if (sort_option) mu_list_sort (scn.result, compare_response); mu_list_foreach (scn.result, _print_list_entry, &prefix_len); mu_list_destroy (&scn.result); } mu_list_destroy (&scn.records); return 0; } static struct mu_tesh_command comtab[] = { { "list", "REF MBX", com_list }, { "lsub", "REF MBX", com_lsub }, { "rename", "OLD NEW", com_rename }, { "subscribe", "MBX", com_subscribe }, { "unsubscribe", "MBX", com_unsubscribe }, { "scan", "[-maxdepth=N] [-type=TYPE] [REF PATTERN]", com_scan }, { NULL } }; static void usage (void) { mu_printf ( "usage: %s [-debug=SPEC] -name=URL [-sort] [-glob] OP ARG... [\\; OP ARG...]...]\n", mu_program_name); mu_printf ("OPerations and corresponding ARGuments are:\n"); mu_tesh_help (comtab, NULL); } static int _always_is_scheme (mu_record_t record, mu_url_t url, int flags) { int res = 0; char const *p; struct stat st; int rc = mu_url_sget_path (url, &p); if (rc) { mu_diag_funcall (MU_DIAG_ERROR, "mu_url_sget_path", NULL, rc); return 0; } if (lstat (p, &st)) { mu_diag_funcall (MU_DIAG_ERROR, "lstat", p, rc); return 0; } if (S_ISDIR (st.st_mode)) res |= MU_FOLDER_ATTRIBUTE_DIRECTORY; if (S_ISREG (st.st_mode)) res |= MU_FOLDER_ATTRIBUTE_FILE; if (S_ISLNK (st.st_mode)) res |= MU_FOLDER_ATTRIBUTE_LINK; return res & flags; } static struct _mu_record any_record = { 10, "any", MU_RECORD_LOCAL, MU_URL_SCHEME | MU_URL_PATH, MU_URL_PATH, mu_url_expand_path, /* URL init. */ NULL, /* Mailbox init. */ NULL, /* Mailer init. */ _mu_fsfolder_init, /* Folder init. */ NULL, /* No need for an back pointer. */ _always_is_scheme, /* _is_scheme method. */ NULL, /* _get_url method. */ NULL, /* _get_mailbox method. */ NULL, /* _get_mailer method. */ NULL /* _get_folder method. */ }; static int _reg_is_scheme (mu_record_t record, mu_url_t url, int flags) { return _always_is_scheme (record, url, flags) & MU_FOLDER_ATTRIBUTE_FILE; } static struct _mu_record reg_record = { 0, "reg", MU_RECORD_LOCAL, MU_URL_SCHEME | MU_URL_PATH, MU_URL_PATH, mu_url_expand_path, /* URL init. */ NULL, /* Mailbox init. */ NULL, /* Mailer init. */ _mu_fsfolder_init, /* Folder init. */ NULL, /* No need for an back pointer. */ _reg_is_scheme, /* _is_scheme method. */ NULL, /* _get_url method. */ NULL, /* _get_mailbox method. */ NULL, /* _get_mailer method. */ NULL /* _get_folder method. */ }; int main (int argc, char **argv) { int i; int rc; mu_folder_t folder; char *fname = NULL; int glob_option = 0; mu_tesh_init (argv[0]); mu_registrar_record (&any_record); mu_registrar_record (®_record); if (argc == 1) { usage (); exit (0); } for (i = 1; i < argc; i++) { if (strncmp (argv[i], "-debug=", 7) == 0) mu_debug_parse_spec (argv[i] + 7); else if (strncmp (argv[i], "-name=", 6) == 0) fname = argv[i] + 6; else if (strcmp (argv[i], "-sort") == 0) sort_option = 1; else if (strcmp (argv[i], "-glob") == 0) glob_option = 1; else break; } if (!fname) { mu_error ("name not specified"); exit (1); } if (fname[0] != '/') { char *cwd = mu_getcwd (); prefix_len = strlen (cwd); if (cwd[prefix_len-1] != '/') prefix_len++; fname = mu_make_file_name (cwd, fname); free (cwd); } rc = mu_folder_create (&folder, fname); if (rc) { mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", fname, rc); return 1; } rc = mu_folder_open (folder, MU_STREAM_READ); if (rc) { mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", fname, rc); return 1; } if (glob_option) mu_folder_set_match (folder, mu_folder_glob_match); mu_tesh_read_and_eval (argc - i, argv + i, comtab, folder); mu_folder_close (folder); mu_folder_destroy (&folder); return 0; }