/* * Announce information about the file we are editing. * Return a likely place to set dot. */ int newfileinfo(int omsgCount) { struct message *mp; int u, n, mdot, d, s; char fname[PATHSIZE+1], zname[PATHSIZE+1], *ename; for (mp = &message[omsgCount]; mp < &message[msgCount]; mp++) if (mp->m_flag & MNEW) break; if (mp >= &message[msgCount]) for (mp = &message[omsgCount]; mp < &message[msgCount]; mp++) if ((mp->m_flag & MREAD) == 0) break; if (mp < &message[msgCount]) mdot = mp - &message[0] + 1; else mdot = omsgCount + 1; s = d = 0; for (mp = &message[0], n = 0, u = 0; mp < &message[msgCount]; mp++) { if (mp->m_flag & MNEW) n++; if ((mp->m_flag & MREAD) == 0) u++; if (mp->m_flag & MDELETED) d++; if (mp->m_flag & MSAVED) s++; } ename = mailname; if (getfold(fname, sizeof(fname) - 1) >= 0) { strcat(fname, "/"); if (strncmp(fname, mailname, strlen(fname)) == 0) { (void)snprintf(zname, sizeof(zname), "+%s", mailname + strlen(fname)); ename = zname; } } printf("\"%s\": ", ename); if (msgCount == 1) printf("1 message"); else printf("%d messages", msgCount); if (n > 0) printf(" %d new", n); if (u-n > 0) printf(" %d unread", u); if (d > 0) printf(" %d deleted", d); if (s > 0) printf(" %d saved", s); if (readonly) printf(" [Read only]"); printf("\n"); return (mdot); }
/* * List the folders the user currently has. */ int folders(void) { char dirname[PATHSIZE]; char *cmd; if (getfold(dirname, sizeof(dirname)) < 0) { printf("No value set for \"folder\"\n"); return (1); } if ((cmd = value("LISTER")) == NULL) cmd = "ls"; (void)run_command(cmd, 0, -1, -1, dirname, NULL, NULL); return (0); }
char * expand(char *name) { char xname[BUFSIZ]; char foldbuf[BUFSIZ]; register char *cp; register int l; wordexp_t wrdexp_buf; if (debug) fprintf(stderr, "expand(%s)=", name); cp = strchr(name, '\0') - 1; /* pointer to last char of name */ if (isspace(*cp)) { /* strip off trailing blanks */ while (cp > name && isspace(*cp)) cp--; l = *++cp; /* save char */ *cp = '\0'; name = savestr(name); *cp = (char)l; /* restore char */ } if (name[0] == '+' && getfold(foldbuf) >= 0) { snprintf(xname, sizeof (xname), "%s/%s", foldbuf, name + 1); cp = safeexpand(savestr(xname)); if (debug) fprintf(stderr, "%s\n", cp); return (cp); } if (!anyof(name, "~{[*?$`'\"\\")) { if (debug) fprintf(stderr, "%s\n", name); return (name); } if (wordexp(name, &wrdexp_buf, WRDE_NOCMD) != 0) { fprintf(stderr, gettext("Syntax error in \"%s\"\n"), name); fflush(stderr); return (NOSTR); } if (wrdexp_buf.we_wordc > 1) { fprintf(stderr, gettext("\"%s\": Ambiguous\n"), name); fflush(stderr); return (NOSTR); } if (debug) fprintf(stderr, "%s\n", wrdexp_buf.we_wordv[0]); return (savestr(wrdexp_buf.we_wordv[0])); }
/* * List the folders the user currently has. */ int folders(void *v) { char **argv = v; char dirname[PATHSIZE]; char *cmd, *name; if (*argv) name = expand(*argv); else if (getfold(dirname, sizeof dirname) < 0) { printf(catgets(catd, CATSET, 20, "No value set for \"folder\"\n")); return 1; } else name = dirname; if (which_protocol(name) == PROTO_IMAP) imap_folders(name, *argv == NULL); else { if ((cmd = value("LISTER")) == NULL) cmd = "ls"; run_command(cmd, 0, -1, -1, name, NULL, NULL); } return 0; }
/* * Evaluate the string given as a new mailbox name. * Supported meta characters: * % for my system mail box * %user for user's system mail box * # for previous file * & invoker's mbox file * +file file in folder directory * any shell meta character * Return the file name as a dynamic string. */ char * expand(char *name) { char xname[PATHSIZE]; char cmdbuf[PATHSIZE]; /* also used for file names */ int pid, l; char *cp, *sh; int pivec[2]; struct stat sbuf; /* * The order of evaluation is "%" and "#" expand into constants. * "&" can expand into "+". "+" can expand into shell meta characters. * Shell meta characters expand into constants. * This way, we make no recursive expansion. */ switch (*name) { case '%': findmail(name[1] ? name + 1 : myname, xname, sizeof(xname)); return (savestr(xname)); case '#': if (name[1] != 0) break; if (prevfile[0] == 0) { printf("No previous file\n"); return (NULL); } return (savestr(prevfile)); case '&': if (name[1] == 0 && (name = value("MBOX")) == NULL) name = "~/mbox"; /* fall through */ } if (name[0] == '+' && getfold(cmdbuf, sizeof(cmdbuf)) >= 0) { (void)snprintf(xname, sizeof(xname), "%s/%s", cmdbuf, name + 1); name = savestr(xname); } /* catch the most common shell meta character */ if (name[0] == '~' && homedir != NULL && (name[1] == '/' || name[1] == '\0')) { (void)snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1); name = savestr(xname); } if (!strpbrk(name, "~{[*?$`'\"\\")) return (name); if (pipe(pivec) < 0) { warn("pipe"); return (name); } (void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name); if ((sh = value("SHELL")) == NULL) sh = _PATH_CSHELL; pid = start_command(sh, 0, -1, pivec[1], "-c", cmdbuf, NULL); if (pid < 0) { (void)close(pivec[0]); (void)close(pivec[1]); return (NULL); } (void)close(pivec[1]); l = read(pivec[0], xname, BUFSIZ); (void)close(pivec[0]); if (wait_child(pid) < 0 && WIFSIGNALED(wait_status) && WTERMSIG(wait_status) != SIGPIPE) { fprintf(stderr, "\"%s\": Expansion failed.\n", name); return (NULL); } if (l < 0) { warn("read"); return (NULL); } if (l == 0) { fprintf(stderr, "\"%s\": No match.\n", name); return (NULL); } if (l == BUFSIZ) { fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name); return (NULL); } xname[l] = '\0'; for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) ; cp[1] = '\0'; if (strchr(xname, ' ') && stat(xname, &sbuf) < 0) { fprintf(stderr, "\"%s\": Ambiguous.\n", name); return (NULL); } return (savestr(xname)); }
/* * Evaluate the string given as a new mailbox name. * Supported meta characters: * % for my system mail box * %user for user's system mail box * # for previous file * & invoker's mbox file * +file file in folder directory * any shell meta character * Return the file name as a dynamic string. */ PUBLIC const char * expand(const char *name) { char xname[PATHSIZE]; char cmdbuf[PATHSIZE]; int e; wordexp_t we; sigset_t nset, oset; /* * The order of evaluation is "%" and "#" expand into constants. * "&" can expand into "+". "+" can expand into shell meta characters. * Shell meta characters expand into constants. * This way, we make no recursive expansion. */ switch (*name) { case '%': findmail(name[1] ? name + 1 : myname, xname, sizeof(xname)); return savestr(xname); case '#': if (name[1] != 0) break; if (prevfile[0] == 0) { warnx("No previous file"); return NULL; } return savestr(prevfile); case '&': if (name[1] == 0 && (name = value(ENAME_MBOX)) == NULL) name = "~/mbox"; /* fall through */ } if (name[0] == '+' && getfold(cmdbuf, sizeof(cmdbuf)) >= 0) { (void)snprintf(xname, sizeof(xname), "%s/%s", cmdbuf, name + 1); name = savestr(xname); } /* catch the most common shell meta character */ if (name[0] == '~' && (name[1] == '/' || name[1] == '\0')) { (void)snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1); name = savestr(xname); } if (strpbrk(name, "~{[*?$`'\"\\") == NULL) return name; *xname = '\0'; sigemptyset(&nset); sigaddset(&nset, SIGCHLD); sigprocmask(SIG_BLOCK, &nset, &oset); e = wordexp(name, &we, WRDE_NOCMD); sigprocmask(SIG_SETMASK, &oset, NULL); switch (e) { case 0: /* OK */ break; case WRDE_NOSPACE: warnx("Out of memory expanding `%s'", name); return NULL; case WRDE_BADVAL: case WRDE_BADCHAR: case WRDE_SYNTAX: warnx("Syntax error expanding `%s'", name); return NULL; case WRDE_CMDSUB: warnx("Command substitution not allowed expanding `%s'", name); return NULL; default: warnx("Unknown expansion error %d expanding `%s'", e, name); return NULL; } switch (we.we_wordc) { case 0: warnx("No match for `%s'", name); break; case 1: if (strlen(we.we_wordv[0]) >= PATHSIZE) warnx("Expansion too long for `%s'", name); strlcpy(xname, we.we_wordv[0], PATHSIZE); break; default: warnx("Ambiguous expansion for `%s'", name); break; } wordfree(&we); if (!*xname) return NULL; else return savestr(xname); }