827 lines
17 KiB
C
Executable File
827 lines
17 KiB
C
Executable File
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
#ident "@(#)fio.c 1.40 95/07/19 SMI" /* from SVr4.0 1.13.2.2 */
|
|
|
|
#include "rcv.h"
|
|
#include <locale.h>
|
|
#include <wordexp.h>
|
|
|
|
/*
|
|
* mailx -- a modified version of a University of California at Berkeley
|
|
* mail program
|
|
*
|
|
* File I/O.
|
|
*/
|
|
|
|
static int getln(char *line, int max, FILE *f);
|
|
static int linecount(char *lp, long size);
|
|
|
|
/*
|
|
* Set up the input pointers while copying the mail file into
|
|
* /tmp.
|
|
*/
|
|
|
|
void
|
|
setptr(register FILE *ibuf)
|
|
{
|
|
int n, newline = 1, blankline = 1;
|
|
int StartNewMsg = TRUE;
|
|
int ToldUser = FALSE;
|
|
long clen = -1L;
|
|
int hdr = 0;
|
|
int cflg = 0; /* found Content-length in header */
|
|
register char *cp;
|
|
register int l;
|
|
register long s;
|
|
off_t offset;
|
|
char linebuf[LINESIZE];
|
|
int inhead, newmail, Odot;
|
|
short flag;
|
|
|
|
if (!space) {
|
|
msgCount = 0;
|
|
offset = 0;
|
|
space = 32;
|
|
newmail = 0;
|
|
message =
|
|
(struct message *)calloc(space, sizeof(struct message));
|
|
if (message == NULL) {
|
|
fprintf(stderr, gettext(
|
|
"calloc: insufficient memory for %d messages\n"),
|
|
space);
|
|
exit(1);
|
|
/* NOTREACHED */
|
|
}
|
|
dot = message;
|
|
} else {
|
|
newmail = 1;
|
|
offset = fsize(otf);
|
|
}
|
|
s = 0L;
|
|
l = 0;
|
|
/*
|
|
* Set default flags. When reading from
|
|
* a folder, assume the message has been
|
|
* previously read.
|
|
*/
|
|
if (edit)
|
|
flag = MUSED|MREAD;
|
|
else
|
|
flag = MUSED|MNEW;
|
|
|
|
inhead = 0;
|
|
while ((n = getln(linebuf, sizeof linebuf, ibuf)) > 0) {
|
|
if (!newline) {
|
|
goto putout;
|
|
}
|
|
top:
|
|
hdr = inhead && (headerp(linebuf) ||
|
|
(linebuf[0] == ' ' || linebuf[0] == '\t'));
|
|
if (!hdr && cflg) { /* nonheader, Content-length seen */
|
|
if (clen > 0 && clen < n) { /* read too much */
|
|
/*
|
|
* NB: this only can happen if there is a
|
|
* small content that is NOT \n terminated
|
|
* and has no leading blank line, i.e., never.
|
|
*/
|
|
if (fwrite(linebuf, 1, (int)clen, otf) != clen) {
|
|
fclose(ibuf);
|
|
fflush(otf);
|
|
} else {
|
|
l += linecount(linebuf, clen);
|
|
}
|
|
offset += clen;
|
|
s += clen;
|
|
n -= (int)clen;
|
|
/* shift line to the left, copy null as well */
|
|
memcpy(linebuf, linebuf+clen, n+1);
|
|
cflg = 0;
|
|
message[msgCount-1].m_clen = clen + 1;
|
|
blankline = 1;
|
|
StartNewMsg = TRUE;
|
|
goto top;
|
|
}
|
|
/* here, clen == 0 or clen >= n */
|
|
if (n == 1 && linebuf[0] == '\n') {
|
|
/* leading empty line */
|
|
clen++; /* cheat */
|
|
inhead = 0;
|
|
}
|
|
offset += clen;
|
|
s += (long)clen;
|
|
message[msgCount-1].m_clen = clen;
|
|
for (;;) {
|
|
if (fwrite(linebuf, 1, n, otf) != n) {
|
|
fclose(ibuf);
|
|
fflush(otf);
|
|
} else {
|
|
l += linecount(linebuf, n);
|
|
}
|
|
clen -= n;
|
|
if (clen <= 0) {
|
|
break;
|
|
}
|
|
n = clen < sizeof linebuf ?
|
|
(int)clen : (int)sizeof linebuf;
|
|
if ((n = fread (linebuf, 1, n, ibuf)) <= 0) {
|
|
fprintf(stderr, gettext(
|
|
"%s:\tYour mailfile was found to be corrupted.\n"),
|
|
progname);
|
|
fprintf(stderr, gettext(
|
|
"\t(Unexpected end-of-file).\n"));
|
|
fprintf(stderr, gettext(
|
|
"\tMessage #%d may be truncated.\n\n"),
|
|
msgCount);
|
|
offset -= clen;
|
|
s -= clen;
|
|
clen = 0; /* stop the loop */
|
|
}
|
|
}
|
|
/* All done, go to top for next message */
|
|
cflg = 0;
|
|
blankline = 1;
|
|
StartNewMsg = TRUE;
|
|
continue;
|
|
}
|
|
|
|
/* Look for a From line that starts a new message */
|
|
if (blankline && linebuf[0] == 'F' && ishead(linebuf)) {
|
|
if (msgCount > 0 && !newmail) {
|
|
message[msgCount-1].m_size = s;
|
|
message[msgCount-1].m_lines = l;
|
|
message[msgCount-1].m_flag = flag;
|
|
}
|
|
if (msgCount >= space) {
|
|
/*
|
|
* Limit the speed at which the
|
|
* allocated space grows.
|
|
*/
|
|
if (space < 512)
|
|
space = space*2;
|
|
else
|
|
space += 512;
|
|
errno = 0;
|
|
Odot = dot - &(message[0]);
|
|
message = (struct message *)
|
|
realloc(message,
|
|
space*(sizeof (struct message)));
|
|
if (message == NULL) {
|
|
perror("realloc failed");
|
|
fprintf(stderr, gettext(
|
|
"realloc: insufficient memory for %d messages\n"),
|
|
space);
|
|
exit(1);
|
|
}
|
|
dot = &message[Odot];
|
|
}
|
|
message[msgCount].m_offset = offset;
|
|
message[msgCount].m_text = TRUE;
|
|
message[msgCount].m_clen = 0;
|
|
newmail = 0;
|
|
msgCount++;
|
|
if (edit)
|
|
flag = MUSED|MREAD;
|
|
else
|
|
flag = MUSED|MNEW;
|
|
inhead = 1;
|
|
s = 0L;
|
|
l = 0;
|
|
StartNewMsg = FALSE;
|
|
ToldUser = FALSE;
|
|
goto putout;
|
|
}
|
|
|
|
/* if didn't get a header line, we're no longer in the header */
|
|
if (!hdr)
|
|
inhead = 0;
|
|
if (!inhead)
|
|
goto putout;
|
|
|
|
/*
|
|
* Look for Status: line. Do quick check for second character,
|
|
* many headers start with "S" but few have "t" as second char.
|
|
*/
|
|
if ((linebuf[1] == 't' || linebuf[1] == 'T') &&
|
|
ishfield(linebuf, "status")) {
|
|
cp = hcontents(linebuf);
|
|
flag = MUSED|MNEW;
|
|
if (strchr(cp, 'R'))
|
|
flag |= MREAD;
|
|
if (strchr(cp, 'O'))
|
|
flag &= ~MNEW;
|
|
}
|
|
/*
|
|
* Look for Content-Length and Content-Type headers. Like
|
|
* above, do a quick check for the "-", which is rare.
|
|
*/
|
|
if (linebuf[7] == '-') {
|
|
if (ishfield(linebuf, "content-length")) {
|
|
if (!cflg) {
|
|
clen = atol(hcontents(linebuf));
|
|
cflg = clen >= 0;
|
|
}
|
|
} else if (ishfield(linebuf, "content-type")) {
|
|
char word[LINESIZE];
|
|
char *cp2;
|
|
|
|
cp = hcontents(linebuf);
|
|
cp2 = word;
|
|
while (!isspace(*cp))
|
|
*cp2++ = *cp++;
|
|
*cp2 = '\0';
|
|
if (icequal(word, "binary"))
|
|
message[msgCount-1].m_text = FALSE;
|
|
}
|
|
}
|
|
putout:
|
|
offset += n;
|
|
s += (long)n;
|
|
if (fwrite(linebuf,1,n,otf) != n) {
|
|
fclose(ibuf);
|
|
fflush(otf);
|
|
} else {
|
|
l++;
|
|
}
|
|
if (ferror(otf)) {
|
|
perror("/tmp");
|
|
exit(1);
|
|
}
|
|
if (msgCount == 0) {
|
|
fclose(ibuf);
|
|
fflush(otf);
|
|
}
|
|
if (linebuf[n-1] == '\n') {
|
|
blankline = newline && n == 1;
|
|
newline = 1;
|
|
if (n == 1) {
|
|
/* Blank line. Skip StartNewMsg check below */
|
|
continue;
|
|
}
|
|
} else {
|
|
newline = 0;
|
|
}
|
|
if (StartNewMsg && !ToldUser) {
|
|
fprintf(stderr, gettext(
|
|
"%s:\tYour mailfile was found to be corrupted\n"),
|
|
progname);
|
|
fprintf(stderr,
|
|
gettext("\t(Content-length mismatch).\n"));
|
|
fprintf(stderr, gettext(
|
|
"\tMessage #%d may be truncated,\n"), msgCount);
|
|
fprintf(stderr, gettext(
|
|
"\twith another message concatenated to it.\n\n"));
|
|
ToldUser = TRUE;
|
|
}
|
|
}
|
|
|
|
if (n == 0) {
|
|
fflush(otf);
|
|
if (fferror(otf)) {
|
|
perror("/tmp");
|
|
exit(1);
|
|
}
|
|
if (msgCount) {
|
|
message[msgCount-1].m_size = s;
|
|
message[msgCount-1].m_lines = l;
|
|
message[msgCount-1].m_flag = flag;
|
|
}
|
|
fclose(ibuf);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Compute the content length of a message and set it into m_clen.
|
|
*/
|
|
|
|
void
|
|
setclen(register struct message *mp)
|
|
{
|
|
long c;
|
|
FILE *ibuf;
|
|
char line[LINESIZE];
|
|
int fline, nread;
|
|
|
|
ibuf = setinput(mp);
|
|
c = mp->m_size;
|
|
fline = 1;
|
|
while (c > 0L) {
|
|
nread = getln(line, sizeof (line), ibuf);
|
|
c -= nread;
|
|
/*
|
|
* First line is the From line, so no headers
|
|
* there to worry about.
|
|
*/
|
|
if (fline) {
|
|
fline = 0;
|
|
continue;
|
|
}
|
|
/*
|
|
* If line is blank, we've reached end of headers.
|
|
*/
|
|
if (line[0] == '\n')
|
|
break;
|
|
/*
|
|
* If this line is a continuation
|
|
* of a previous header field, keep going.
|
|
*/
|
|
if (isspace(line[0]))
|
|
continue;
|
|
/*
|
|
* If we are no longer looking at real
|
|
* header lines, we're done.
|
|
* This happens in uucp style mail where
|
|
* there are no headers at all.
|
|
*/
|
|
if (!headerp(line)) {
|
|
c += nread;
|
|
break;
|
|
}
|
|
}
|
|
if (c == 0)
|
|
c = 1;
|
|
mp->m_clen = c;
|
|
}
|
|
|
|
static int
|
|
getln(char *line, int max, FILE *f)
|
|
{
|
|
register int c;
|
|
register char *cp, *ecp;
|
|
|
|
cp = line;
|
|
ecp = cp + max - 1;
|
|
while (cp < ecp && (c = getc(f)) != EOF)
|
|
if ((*cp++ = (char)c) == '\n')
|
|
break;
|
|
*cp = '\0';
|
|
return(cp - line);
|
|
}
|
|
|
|
/*
|
|
* Read up a line from the specified input into the line
|
|
* buffer. Return the number of characters read. Do not
|
|
* include the newline at the end.
|
|
*/
|
|
|
|
readline(FILE *ibuf, char *linebuf)
|
|
{
|
|
register char *cp;
|
|
register int c;
|
|
int seennulls = 0;
|
|
|
|
clearerr(ibuf);
|
|
c = getc(ibuf);
|
|
for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) {
|
|
if (c == 0) {
|
|
if (!seennulls) {
|
|
fprintf(stderr,
|
|
gettext("mailx: NUL changed to @\n"));
|
|
seennulls++;
|
|
}
|
|
c = '@';
|
|
}
|
|
if (cp - linebuf < LINESIZE-2)
|
|
*cp++ = (char)c;
|
|
}
|
|
*cp = 0;
|
|
if (c == EOF && cp == linebuf)
|
|
return(0);
|
|
return(cp - linebuf + 1);
|
|
}
|
|
|
|
/*
|
|
* linecount - determine the number of lines in a printable file.
|
|
*/
|
|
|
|
static int
|
|
linecount(char *lp, long size)
|
|
{
|
|
register char *cp, *ecp;
|
|
register int count;
|
|
|
|
count = 0;
|
|
cp = lp;
|
|
ecp = cp + size;
|
|
while (cp < ecp)
|
|
if (*cp++ == '\n')
|
|
count++;
|
|
return(count);
|
|
}
|
|
|
|
/*
|
|
* Return a file buffer all ready to read up the
|
|
* passed message pointer.
|
|
*/
|
|
|
|
FILE *
|
|
setinput(register struct message *mp)
|
|
{
|
|
fflush(otf);
|
|
if (fseek(itf, mp->m_offset, 0) < 0) {
|
|
perror("fseek");
|
|
panic("temporary file seek");
|
|
}
|
|
return(itf);
|
|
}
|
|
|
|
|
|
/*
|
|
* Delete a file, but only if the file is a plain file.
|
|
*/
|
|
|
|
int
|
|
removefile(char name[])
|
|
{
|
|
struct stat statb;
|
|
extern int errno;
|
|
|
|
if (stat(name, &statb) < 0)
|
|
if (errno == ENOENT)
|
|
return(0); /* it's already gone, no error */
|
|
else
|
|
return(-1);
|
|
if ((statb.st_mode & S_IFMT) != S_IFREG) {
|
|
errno = EISDIR;
|
|
return(-1);
|
|
}
|
|
return(unlink(name));
|
|
}
|
|
|
|
/*
|
|
* Terminate an editing session by attempting to write out the user's
|
|
* file from the temporary. Save any new stuff appended to the file.
|
|
*/
|
|
int
|
|
edstop(
|
|
int noremove /* don't allow the file to be removed, trunc instead */
|
|
)
|
|
{
|
|
register int gotcha, c;
|
|
register struct message *mp;
|
|
FILE *obuf, *ibuf, *tbuf = 0, *readstat;
|
|
struct stat statb;
|
|
char tempname[30], *id;
|
|
|
|
if (readonly)
|
|
return(0);
|
|
holdsigs();
|
|
if (Tflag != NOSTR) {
|
|
if ((readstat = fopen(Tflag, "w")) == NULL)
|
|
Tflag = NOSTR;
|
|
}
|
|
for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
|
|
if (mp->m_flag & MNEW) {
|
|
mp->m_flag &= ~MNEW;
|
|
mp->m_flag |= MSTATUS;
|
|
}
|
|
if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
|
|
gotcha++;
|
|
if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
|
|
if ((id = hfield("article-id", mp, addone)) != NOSTR)
|
|
fprintf(readstat, "%s\n", id);
|
|
}
|
|
}
|
|
if (Tflag != NOSTR)
|
|
fclose(readstat);
|
|
if (!gotcha || Tflag != NOSTR)
|
|
goto done;
|
|
if ((ibuf = fopen(editfile, "r+")) == NULL) {
|
|
perror(editfile);
|
|
relsesigs();
|
|
longjmp(srbuf, 1);
|
|
}
|
|
lock(ibuf, "r+", 1);
|
|
if (fstat(fileno(ibuf), &statb) >= 0 && statb.st_size > mailsize) {
|
|
strcpy(tempname, "/tmp/mboxXXXXXX");
|
|
mktemp(tempname);
|
|
if ((obuf = fopen(tempname, "w")) == NULL) {
|
|
perror(tempname);
|
|
fclose(ibuf);
|
|
relsesigs();
|
|
longjmp(srbuf, 1);
|
|
}
|
|
fseek(ibuf, mailsize, 0);
|
|
while ((c = getc(ibuf)) != EOF)
|
|
putc(c, obuf);
|
|
fclose(obuf);
|
|
if ((tbuf = fopen(tempname, "r")) == NULL) {
|
|
perror(tempname);
|
|
fclose(ibuf);
|
|
removefile(tempname);
|
|
relsesigs();
|
|
longjmp(srbuf, 1);
|
|
}
|
|
removefile(tempname);
|
|
}
|
|
if ((obuf = fopen(editfile, "r+")) == NULL) {
|
|
if ((obuf = fopen(editfile, "w")) == NULL) {
|
|
perror(editfile);
|
|
fclose(ibuf);
|
|
if (tbuf)
|
|
fclose(tbuf);
|
|
relsesigs();
|
|
longjmp(srbuf, 1);
|
|
}
|
|
} else
|
|
trunc(obuf);
|
|
printf("\"%s\" ", editfile);
|
|
flush();
|
|
c = 0;
|
|
for (mp = &message[0]; mp < &message[msgCount]; mp++) {
|
|
if ((mp->m_flag & MDELETED) != 0)
|
|
continue;
|
|
c++;
|
|
if (msend(mp, obuf, 0, fputs) < 0) {
|
|
perror(editfile);
|
|
fclose(ibuf);
|
|
fclose(obuf);
|
|
if (tbuf)
|
|
fclose(tbuf);
|
|
relsesigs();
|
|
longjmp(srbuf, 1);
|
|
}
|
|
}
|
|
gotcha = (c == 0 && tbuf == NULL);
|
|
if (tbuf != NULL) {
|
|
while ((c = getc(tbuf)) != EOF)
|
|
putc(c, obuf);
|
|
fclose(tbuf);
|
|
}
|
|
fflush(obuf);
|
|
if (fferror(obuf)) {
|
|
perror(editfile);
|
|
fclose(ibuf);
|
|
fclose(obuf);
|
|
relsesigs();
|
|
longjmp(srbuf, 1);
|
|
}
|
|
if (gotcha && !noremove && (value("keep") == NOSTR)) {
|
|
removefile(editfile);
|
|
printf(gettext("removed.\n"));
|
|
}
|
|
else
|
|
printf(gettext("updated.\n"));
|
|
fclose(ibuf);
|
|
fclose(obuf);
|
|
flush();
|
|
|
|
done:
|
|
relsesigs();
|
|
return(1);
|
|
}
|
|
|
|
# ifndef OLD_BSD_SIGS
|
|
static int sigdepth = 0; /* depth of holdsigs() */
|
|
#ifdef VMUNIX
|
|
static int omask = 0;
|
|
#else
|
|
static sigset_t mask, omask;
|
|
#endif
|
|
# endif
|
|
/*
|
|
* Hold signals SIGHUP - SIGQUIT.
|
|
*/
|
|
void
|
|
holdsigs(void)
|
|
{
|
|
# ifndef OLD_BSD_SIGS
|
|
if (sigdepth++ == 0) {
|
|
#ifdef VMUNIX
|
|
omask = sigblock(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT));
|
|
#else
|
|
sigemptyset(&mask);
|
|
sigaddset(&mask, SIGHUP);
|
|
sigaddset(&mask, SIGINT);
|
|
sigaddset(&mask, SIGQUIT);
|
|
sigprocmask(SIG_BLOCK, &mask, &omask);
|
|
#endif
|
|
}
|
|
# else
|
|
sighold(SIGHUP);
|
|
sighold(SIGINT);
|
|
sighold(SIGQUIT);
|
|
# endif
|
|
}
|
|
|
|
/*
|
|
* Release signals SIGHUP - SIGQUIT
|
|
*/
|
|
void
|
|
relsesigs(void)
|
|
{
|
|
# ifndef OLD_BSD_SIGS
|
|
if (--sigdepth == 0)
|
|
#ifdef VMUNIX
|
|
sigsetmask(omask);
|
|
#else
|
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
|
#endif
|
|
# else
|
|
sigrelse(SIGHUP);
|
|
sigrelse(SIGINT);
|
|
sigrelse(SIGQUIT);
|
|
# endif
|
|
}
|
|
|
|
#if !defined(OLD_BSD_SIGS) && !defined(VMUNIX)
|
|
void
|
|
(*sigset(int sig, void (*act)(int)))(int)
|
|
{
|
|
struct sigaction sa, osa;
|
|
|
|
sa.sa_handler = (void (*)())act;
|
|
sigemptyset(&sa.sa_mask);
|
|
sa.sa_flags = SA_RESTART;
|
|
if (sigaction(sig, &sa, &osa) < 0)
|
|
return ((void (*)(int))-1);
|
|
return ((void (*)(int))osa.sa_handler);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Flush the standard output.
|
|
*/
|
|
|
|
void
|
|
flush(void)
|
|
{
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
}
|
|
|
|
/*
|
|
* Determine the size of the file possessed by
|
|
* the passed buffer.
|
|
*/
|
|
|
|
off_t
|
|
fsize(FILE *iob)
|
|
{
|
|
register int f;
|
|
struct stat sbuf;
|
|
|
|
f = fileno(iob);
|
|
if (fstat(f, &sbuf) < 0)
|
|
return(0);
|
|
return(sbuf.st_size);
|
|
}
|
|
|
|
/*
|
|
* Check for either a stdio recognized error, or
|
|
* a possibly delayed write error (in case it's
|
|
* an NFS file, for instance).
|
|
*/
|
|
|
|
int
|
|
fferror(FILE *iob)
|
|
{
|
|
return(ferror(iob) || fsync(fileno(iob)) < 0);
|
|
}
|
|
|
|
/*
|
|
* Take a file name, possibly with shell meta characters
|
|
* in it and expand it by using wordexp().
|
|
* Return the file name as a dynamic string.
|
|
* If the name cannot be expanded (for whatever reason)
|
|
* return NULL.
|
|
*/
|
|
|
|
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) {
|
|
sprintf(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, 0) != 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]));
|
|
}
|
|
|
|
/*
|
|
* Take a file name, possibly with shell meta characters
|
|
* in it and expand it by using "sh -c echo filename"
|
|
* Return the file name as a dynamic string.
|
|
* If the name cannot be expanded (for whatever reason)
|
|
* return the original file name.
|
|
*/
|
|
|
|
char *
|
|
safeexpand(char name[])
|
|
{
|
|
char *t = expand(name);
|
|
return t ? t : savestr(name);
|
|
}
|
|
|
|
/*
|
|
* Determine the current folder directory name.
|
|
*/
|
|
getfold(char *name)
|
|
{
|
|
char *folder;
|
|
|
|
if ((folder = value("folder")) == NOSTR || *folder == '\0')
|
|
return(-1);
|
|
/*
|
|
* If name looks like a folder name, don't try
|
|
* to expand it, to prevent infinite recursion.
|
|
*/
|
|
if (*folder != '+' && (folder = expand(folder)) == NOSTR ||
|
|
*folder == '\0')
|
|
return(-1);
|
|
if (*folder == '/')
|
|
strcpy(name, folder);
|
|
else
|
|
sprintf(name, "%s/%s", homedir, folder);
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* A nicer version of Fdopen, which allows us to fclose
|
|
* without losing the open file.
|
|
*/
|
|
|
|
FILE *
|
|
Fdopen(int fildes, char *mode)
|
|
{
|
|
register int f;
|
|
|
|
f = dup(fildes);
|
|
if (f < 0) {
|
|
perror("dup");
|
|
return(NULL);
|
|
}
|
|
return(fdopen(f, mode));
|
|
}
|
|
|
|
/*
|
|
* return the filename associated with "s". This function always
|
|
* returns a non-null string (no error checking is done on the receiving end)
|
|
*/
|
|
char *
|
|
Getf(register char *s)
|
|
{
|
|
register char *cp;
|
|
static char defbuf[PATHSIZE];
|
|
|
|
if (((cp = value(s)) != 0) && *cp) {
|
|
return safeexpand(cp);
|
|
} else if (strcmp(s, "MBOX")==0) {
|
|
strcpy(defbuf, Getf("HOME"));
|
|
strcat(defbuf, "/");
|
|
strcat(defbuf, "mbox");
|
|
return(defbuf);
|
|
} else if (strcmp(s, "DEAD")==0) {
|
|
strcpy(defbuf, Getf("HOME"));
|
|
strcat(defbuf, "/");
|
|
strcat(defbuf, "dead.letter");
|
|
return(defbuf);
|
|
} else if (strcmp(s, "MAILRC")==0) {
|
|
strcpy(defbuf, Getf("HOME"));
|
|
strcat(defbuf, "/");
|
|
strcat(defbuf, ".mailrc");
|
|
return(defbuf);
|
|
} else if (strcmp(s, "HOME")==0) {
|
|
/* no recursion allowed! */
|
|
return(".");
|
|
}
|
|
return("DEAD"); /* "cannot happen" */
|
|
}
|