Index: mail/fio.c =================================================================== --- mail/fio.c (revision 302798) +++ mail/fio.c (working copy) @@ -42,6 +42,7 @@ #include #include #include +#include #include "extern.h" /* @@ -253,7 +254,7 @@ } /* - * Delete a file, but only if the file is a plain file. + * Delete or truncate a file, but only if the file is a plain file. */ int rm(char *name) @@ -266,7 +267,13 @@ errno = EISDIR; return (-1); } - return (unlink(name)); + if (unlink(name) == -1) { + if (errno == EPERM) + return(truncate(name, 0)); + else + return(-1); + } + return(0); } static int sigdepth; /* depth of holdsigs() */ @@ -326,12 +333,11 @@ char * expand(char *name) { + const int flags = GLOB_BRACE|GLOB_TILDE|GLOB_NOSORT; char xname[PATHSIZE]; char cmdbuf[PATHSIZE]; /* also used for file names */ - int pid, l; - char *cp, *sh; - int pivec[2]; - struct stat sbuf; + char *match = NULL; + glob_t names; /* * The order of evaluation is "%" and "#" expand into constants. @@ -342,15 +348,15 @@ switch (*name) { case '%': findmail(name[1] ? name + 1 : myname, xname, sizeof(xname)); - return (savestr(xname)); + return(savestr(xname)); case '#': if (name[1] != 0) break; if (prevfile[0] == 0) { - printf("No previous file\n"); - return (NULL); + puts("No previous file"); + return(NULL); } - return (savestr(prevfile)); + return(savestr(prevfile)); case '&': if (name[1] == 0 && (name = value("MBOX")) == NULL) name = "~/mbox"; @@ -361,55 +367,33 @@ name = savestr(xname); } /* catch the most common shell meta character */ - if (name[0] == '~' && homedir != NULL && - (name[1] == '/' || name[1] == '\0')) { + if (name[0] == '~' && homedir && (name[1] == '/' || name[1] == '\0')) { (void)snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1); name = savestr(xname); } - if (!strpbrk(name, "~{[*?$`'\"\\")) - return (savestr(name)); - if (pipe(pivec) < 0) { - warn("pipe"); - return (NULL); - } - (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) { + if (strpbrk(name, "~{[*?\\") == NULL) + return(savestr(name)); + + /* XXX - does not expand enviroment variables. */ + switch (glob(name, flags, NULL, &names)) { + case 0: + if (names.gl_pathc == 1) + match = savestr(names.gl_pathv[0]); + else + fprintf(stderr, "\"%s\": Ambiguous.\n", name); + break; + case GLOB_NOSPACE: + fprintf(stderr, "\"%s\": Out of memory.\n", name); + break; + case GLOB_NOMATCH: + fprintf(stderr, "\"%s\": No match.\n", name); + break; + default: fprintf(stderr, "\"%s\": Expansion failed.\n", name); - return (NULL); + break; } - 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)); + globfree(&names); + return(match); } /*