version 1.5, 1997/05/30 08:51:39 |
version 1.6, 1997/07/13 21:21:12 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: fio.c,v 1.5 1996/06/08 19:48:22 christos Exp $ */ |
/* $NetBSD: fio.c,v 1.8 1997/07/07 22:57:55 phil Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1980, 1993 |
* Copyright (c) 1980, 1993 |
|
|
|
|
#ifndef lint |
#ifndef lint |
#if 0 |
#if 0 |
static char sccsid[] = "@(#)fio.c 8.1 (Berkeley) 6/6/93"; |
static char sccsid[] = "@(#)fio.c 8.2 (Berkeley) 4/20/95"; |
#else |
#else |
static char rcsid[] = "$OpenBSD$"; |
static char rcsid[] = "$OpenBSD$"; |
#endif |
#endif |
|
|
* Set up the input pointers while copying the mail file into /tmp. |
* Set up the input pointers while copying the mail file into /tmp. |
*/ |
*/ |
void |
void |
setptr(ibuf) |
setptr(ibuf, offset) |
register FILE *ibuf; |
register FILE *ibuf; |
|
off_t offset; |
{ |
{ |
extern char *tmpdir; |
extern char *tmpdir; |
register int c, count; |
register int c, count; |
register char *cp, *cp2; |
register char *cp, *cp2; |
struct message this; |
struct message this; |
FILE *mestmp; |
FILE *mestmp; |
off_t offset; |
|
int maybe, inhead; |
int maybe, inhead; |
char linebuf[LINESIZE], pathbuf[PATHSIZE]; |
char linebuf[LINESIZE], pathbuf[PATHSIZE]; |
|
int omsgCount; |
|
|
/* Get temporary file. */ |
/* Get temporary file. */ |
(void)snprintf(pathbuf, sizeof pathbuf, "%s/mail.XXXXXXXXXX", tmpdir); |
(void)snprintf(pathbuf, sizeof(pathbuf), "%s/mail.XXXXXXXXXX", tmpdir); |
if ((c = mkstemp(pathbuf)) == -1 || |
if ((c = mkstemp(pathbuf)) == -1 || (mestmp = Fdopen(c, "r+")) == NULL) |
(mestmp = Fdopen(c, "r+")) == NULL) { |
err(1, "can't open %s", pathbuf); |
(void)fprintf(stderr, "mail: can't open %s\n", pathbuf); |
|
exit(1); |
|
} |
|
(void)unlink(pathbuf); |
(void)unlink(pathbuf); |
|
|
msgCount = 0; |
if (offset == 0) { |
|
msgCount = 0; |
|
} else { |
|
/* Seek into the file to get to the new messages */ |
|
(void) fseek(ibuf, offset, 0); |
|
/* |
|
* We need to make "offset" a pointer to the end of |
|
* the temp file that has the copy of the mail file. |
|
* If any messages have been edited, this will be |
|
* different from the offset into the mail file. |
|
*/ |
|
(void) fseek(otf, 0L, SEEK_END); |
|
offset = ftell(otf); |
|
} |
|
omsgCount = msgCount; |
maybe = 1; |
maybe = 1; |
inhead = 0; |
inhead = 0; |
offset = 0; |
|
this.m_flag = MUSED|MNEW; |
this.m_flag = MUSED|MNEW; |
this.m_size = 0; |
this.m_size = 0; |
this.m_lines = 0; |
this.m_lines = 0; |
this.m_block = 0; |
this.m_block = 0; |
this.m_offset = 0; |
this.m_offset = 0; |
for (;;) { |
for (;;) { |
if (fgets(linebuf, LINESIZE, ibuf) == NULL) { |
if (fgets(linebuf, sizeof(linebuf), ibuf) == NULL) { |
if (append(&this, mestmp)) { |
if (append(&this, mestmp)) |
perror("temporary file"); |
err(1, "temporary file"); |
exit(1); |
makemessage(mestmp, omsgCount); |
} |
|
makemessage(mestmp); |
|
return; |
return; |
} |
} |
count = strlen(linebuf); |
count = strlen(linebuf); |
(void) fwrite(linebuf, sizeof *linebuf, count, otf); |
(void) fwrite(linebuf, sizeof(*linebuf), count, otf); |
if (ferror(otf)) { |
if (ferror(otf)) |
perror("/tmp"); |
err(1, "/tmp"); |
exit(1); |
linebuf[count - 1] = '\0'; |
} |
|
linebuf[count - 1] = 0; |
|
if (maybe && linebuf[0] == 'F' && ishead(linebuf)) { |
if (maybe && linebuf[0] == 'F' && ishead(linebuf)) { |
msgCount++; |
msgCount++; |
if (append(&this, mestmp)) { |
if (append(&this, mestmp)) |
perror("temporary file"); |
err(1, "temporary file"); |
exit(1); |
|
} |
|
this.m_flag = MUSED|MNEW; |
this.m_flag = MUSED|MNEW; |
this.m_size = 0; |
this.m_size = 0; |
this.m_lines = 0; |
this.m_lines = 0; |
|
|
/* |
/* |
* Drop the passed line onto the passed output buffer. |
* Drop the passed line onto the passed output buffer. |
* If a write error occurs, return -1, else the count of |
* If a write error occurs, return -1, else the count of |
* characters written, including the newline. |
* characters written, including the newline if requested. |
*/ |
*/ |
int |
int |
putline(obuf, linebuf) |
putline(obuf, linebuf, outlf) |
FILE *obuf; |
FILE *obuf; |
char *linebuf; |
char *linebuf; |
|
int outlf; |
{ |
{ |
register int c; |
register int c; |
|
|
c = strlen(linebuf); |
c = strlen(linebuf); |
(void) fwrite(linebuf, sizeof *linebuf, c, obuf); |
(void) fwrite(linebuf, sizeof(*linebuf), c, obuf); |
(void) putc('\n', obuf); |
if (outlf) { |
|
(void) putc('\n', obuf); |
|
c++; |
|
} |
if (ferror(obuf)) |
if (ferror(obuf)) |
return (-1); |
return(-1); |
return (c + 1); |
return(c); |
} |
} |
|
|
/* |
/* |
|
|
|
|
clearerr(ibuf); |
clearerr(ibuf); |
if (fgets(linebuf, linesize, ibuf) == NULL) |
if (fgets(linebuf, linesize, ibuf) == NULL) |
return -1; |
return(-1); |
|
|
n = strlen(linebuf); |
n = strlen(linebuf); |
if (n > 0 && linebuf[n - 1] == '\n') |
if (n > 0 && linebuf[n - 1] == '\n') |
linebuf[--n] = '\0'; |
linebuf[--n] = '\0'; |
return n; |
return(n); |
} |
} |
|
|
/* |
/* |
|
|
|
|
fflush(otf); |
fflush(otf); |
if (fseek(itf, (long)positionof(mp->m_block, mp->m_offset), 0) < 0) { |
if (fseek(itf, (long)positionof(mp->m_block, mp->m_offset), 0) < 0) { |
perror("fseek"); |
warn("fseek"); |
panic("temporary file seek"); |
panic("temporary file seek"); |
} |
} |
return (itf); |
return(itf); |
} |
} |
|
|
/* |
/* |
|
|
* a dynamically allocated message structure. |
* a dynamically allocated message structure. |
*/ |
*/ |
void |
void |
makemessage(f) |
makemessage(f, omsgCount) |
FILE *f; |
FILE *f; |
|
int omsgCount; |
{ |
{ |
register size = (msgCount + 1) * sizeof (struct message); |
register size = (msgCount + 1) * sizeof(struct message); |
|
|
if (message != 0) |
if (omsgCount) { |
free((char *) message); |
message = (struct message *)realloc(message, (unsigned) size); |
if ((message = (struct message *) malloc((unsigned) size)) == 0) |
if (message == 0) |
panic("Insufficient memory for %d messages", msgCount); |
panic("Insufficient memory for %d messages\n", msgCount); |
dot = message; |
} else { |
size -= sizeof (struct message); |
if (message != 0) |
|
free((char *) message); |
|
if ((message = (struct message *) malloc((unsigned) size)) == 0) |
|
panic("Insufficient memory for %d messages", msgCount); |
|
dot = message; |
|
} |
|
size -= (omsgCount + 1) * sizeof(struct message); |
fflush(f); |
fflush(f); |
(void) lseek(fileno(f), (off_t)sizeof *message, 0); |
(void) lseek(fileno(f), (off_t)sizeof(*message), 0); |
if (read(fileno(f), (char *) message, size) != size) |
if (read(fileno(f), (void *) &message[omsgCount], size) != size) |
panic("Message temporary file corrupted"); |
panic("Message temporary file corrupted"); |
message[msgCount].m_size = 0; |
message[msgCount].m_size = 0; |
message[msgCount].m_lines = 0; |
message[msgCount].m_lines = 0; |
Fclose(f); |
(void)Fclose(f); |
} |
} |
|
|
/* |
/* |
|
|
struct message *mp; |
struct message *mp; |
FILE *f; |
FILE *f; |
{ |
{ |
return fwrite((char *) mp, sizeof *mp, 1, f) != 1; |
return(fwrite((char *) mp, sizeof(*mp), 1, f) != 1); |
} |
} |
|
|
/* |
/* |
|
|
struct stat sbuf; |
struct stat sbuf; |
|
|
if (fstat(fileno(iob), &sbuf) < 0) |
if (fstat(fileno(iob), &sbuf) < 0) |
return 0; |
return(0); |
return sbuf.st_size; |
return(sbuf.st_size); |
} |
} |
|
|
/* |
/* |
|
|
*/ |
*/ |
switch (*name) { |
switch (*name) { |
case '%': |
case '%': |
findmail(name[1] ? name + 1 : myname, xname, sizeof xname); |
findmail(name[1] ? name + 1 : myname, xname, sizeof(xname)); |
return savestr(xname); |
return(savestr(xname)); |
case '#': |
case '#': |
if (name[1] != 0) |
if (name[1] != 0) |
break; |
break; |
if (prevfile[0] == 0) { |
if (prevfile[0] == 0) { |
printf("No previous file\n"); |
puts("No previous file"); |
return NOSTR; |
return(NOSTR); |
} |
} |
return savestr(prevfile); |
return(savestr(prevfile)); |
case '&': |
case '&': |
if (name[1] == 0 && (name = value("MBOX")) == NOSTR) |
if (name[1] == 0 && (name = value("MBOX")) == NOSTR) |
name = "~/mbox"; |
name = "~/mbox"; |
/* fall through */ |
/* fall through */ |
} |
} |
if (name[0] == '+' && getfold(cmdbuf, sizeof cmdbuf) >= 0) { |
if (name[0] == '+' && getfold(cmdbuf, sizeof(cmdbuf)) >= 0) { |
snprintf(xname, sizeof xname, "%s/%s", cmdbuf, name + 1); |
snprintf(xname, sizeof(xname), "%s/%s", cmdbuf, name + 1); |
name = savestr(xname); |
name = savestr(xname); |
} |
} |
/* catch the most common shell meta character */ |
/* catch the most common shell meta character */ |
if (name[0] == '~' && (name[1] == '/' || name[1] == '\0')) { |
if (name[0] == '~' && (name[1] == '/' || name[1] == '\0')) { |
snprintf(xname, sizeof xname, "%s%s", homedir, name + 1); |
snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1); |
name = savestr(xname); |
name = savestr(xname); |
} |
} |
if (!anyof(name, "~{[*?$`'\"\\")) |
if (!anyof(name, "~{[*?$`'\"\\")) |
return name; |
return(name); |
if (pipe(pivec) < 0) { |
if (pipe(pivec) < 0) { |
perror("pipe"); |
warn("pipe"); |
return name; |
return(name); |
} |
} |
snprintf(cmdbuf, sizeof cmdbuf, "echo %s", name); |
snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name); |
if ((shell = value("SHELL")) == NOSTR) |
if ((shell = value("SHELL")) == NOSTR) |
shell = _PATH_CSHELL; |
shell = _PATH_CSHELL; |
pid = start_command(shell, 0, -1, pivec[1], "-c", cmdbuf, NOSTR); |
pid = start_command(shell, 0, -1, pivec[1], "-c", cmdbuf, NOSTR); |
if (pid < 0) { |
if (pid < 0) { |
close(pivec[0]); |
(void)close(pivec[0]); |
close(pivec[1]); |
(void)close(pivec[1]); |
return NOSTR; |
return(NOSTR); |
} |
} |
close(pivec[1]); |
(void)close(pivec[1]); |
l = read(pivec[0], xname, BUFSIZ); |
l = read(pivec[0], xname, PATHSIZE); |
close(pivec[0]); |
(void)close(pivec[0]); |
if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) { |
if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) { |
fprintf(stderr, "\"%s\": Expansion failed.\n", name); |
fprintf(stderr, "\"%s\": Expansion failed.\n", name); |
return NOSTR; |
return(NOSTR); |
} |
} |
if (l < 0) { |
if (l < 0) { |
perror("read"); |
warn("read"); |
return NOSTR; |
return(NOSTR); |
} |
} |
if (l == 0) { |
if (l == 0) { |
fprintf(stderr, "\"%s\": No match.\n", name); |
fprintf(stderr, "\"%s\": No match.\n", name); |
return NOSTR; |
return(NOSTR); |
} |
} |
if (l == BUFSIZ) { |
if (l == PATHSIZE) { |
fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name); |
fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name); |
return NOSTR; |
return(NOSTR); |
} |
} |
xname[l] = 0; |
xname[l] = '\0'; |
for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) |
for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) |
; |
; |
cp[1] = '\0'; |
cp[1] = '\0'; |
if (strchr(xname, ' ') && stat(xname, &sbuf) < 0) { |
if (strchr(xname, ' ') && stat(xname, &sbuf) < 0) { |
fprintf(stderr, "\"%s\": Ambiguous.\n", name); |
fprintf(stderr, "\"%s\": Ambiguous.\n", name); |
return NOSTR; |
return(NOSTR); |
} |
} |
return savestr(xname); |
return(savestr(xname)); |
} |
} |
|
|
/* |
/* |
|
|
char *folder; |
char *folder; |
|
|
if ((folder = value("folder")) == NOSTR) |
if ((folder = value("folder")) == NOSTR) |
return (-1); |
return(-1); |
if (*folder == '/') { |
if (*folder == '/') { |
strncpy(name, folder, namelen-1); |
strncpy(name, folder, namelen-1); |
name[namelen-1] = '\0'; |
name[namelen-1] = '\0'; |
} else |
} else |
snprintf(name, namelen, "%s/%s", homedir, folder); |
snprintf(name, namelen, "%s/%s", homedir, folder); |
return (0); |
return(0); |
} |
} |
|
|
/* |
/* |
|
|
else if (*cp != '/') { |
else if (*cp != '/') { |
char buf[PATHSIZE]; |
char buf[PATHSIZE]; |
|
|
(void) snprintf(buf, sizeof buf, "~/%s", cp); |
(void) snprintf(buf, sizeof(buf), "~/%s", cp); |
cp = expand(buf); |
cp = expand(buf); |
} |
} |
return cp; |
return(cp); |
} |
} |