Пример #1
0
/*
 * Incorporate any new mail that has arrived since we first
 * started reading mail.
 */
int
incfile(void)
{
	off_t newsize;
	int omsgCount = msgCount;
	FILE *ibuf;

	ibuf = Fopen(mailname, "r");
	if (ibuf == NULL)
		return (-1);
	holdsigs();
	newsize = fsize(ibuf);
	if (newsize == 0)
		return (-1);		/* mail box is now empty??? */
	if (newsize < mailsize)
		return (-1);		/* mail box has shrunk??? */
	if (newsize == mailsize)
		return (0);		/* no new mail */
	setptr(ibuf, mailsize);
	setmsize(msgCount);
	mailsize = ftello(ibuf);
	(void)Fclose(ibuf);
	relsesigs();
	return (msgCount - omsgCount);
}
Пример #2
0
/*
 * Wait for a specific child to die.
 */
int
wait_command(int pid)
{
	register struct child*	cp = findchild(pid);
	int			status = -1;

	holdsigs();
	while (waitpid(pid, &status, 0) == -1 && errno == EINTR);
	relsesigs();
	delchild(cp);
	return status;
}
Пример #3
0
int
fileclose(FILE* fp)
{
	int		r;
	struct file*	p;
	struct file**	pp;

	if (fp == 0 || fp == stdin)
		return 0;
	if (fp == stdout || fp == stderr)
		return fflush(fp);
	r = 0;
	for (pp = &state.files;; pp = &p->link) {
		if (!(p = *pp)) {
			fclose(fp);
			return 0;
		}
		if (p->fp == fp) {
			r = p->pid;
			*pp = p->link;
			free(p);
			break;
		}
	}
	if (r) {
		holdsigs();
		fclose(fp);
		signal(SIGPIPE, SIG_IGN);
		r = wait_command(r);
		signal(SIGPIPE, SIG_DFL);
		relsesigs();
	}
	else
		r = fclose(fp);
	return r;
}
Пример #4
0
/*
 * 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[STSIZ], *id;
	int tmpfd = -1;

	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) {
		nstrcpy(tempname, STSIZ, "/tmp/mboxXXXXXX");
		if ((tmpfd = mkstemp(tempname)) == -1) {
			perror(tempname);
			fclose(ibuf);
			relsesigs();
			longjmp(srbuf, 1);
		}
		if ((obuf = fdopen(tmpfd, "w")) == NULL) {
			perror(tempname);
			fclose(ibuf);
			removefile(tempname);
			relsesigs();
			(void) close(tmpfd);
			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);
		}
	}
	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);
	trunc(obuf);
	fclose(obuf);
	flush();

done:
	relsesigs();
	return (1);
}
Пример #5
0
/*
 * Terminate an editing session by attempting to write out the user's
 * file from the temporary.  Save any new stuff appended to the file.
 */
static void
edstop(void)
{
    int gotcha, c;
    struct message *mp;
    FILE *obuf, *ibuf, *readstat;
    struct stat statb;
    char tempname[PATHSIZE];

    if (readonly)
        return;
    holdsigs();
    if (Tflag != NULL) {
        if ((readstat = Fopen(Tflag, "w")) == NULL)
            Tflag = NULL;
    }
    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 != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
            char *id;

            if ((id = hfield("article-id", mp)) != NULL)
                fprintf(readstat, "%s\n", id);
        }
    }
    if (Tflag != NULL)
        Fclose(readstat);
    if (!gotcha || Tflag != NULL)
        goto done;
    ibuf = NULL;
    if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
        int fd;

        snprintf(tempname, sizeof(tempname), "%s/mbox.XXXXXXXXXX",
                 tmpdir);
        if ((fd = mkstemp(tempname)) == -1 ||
                (obuf = Fdopen(fd, "w")) == NULL) {
            warn("%s", tempname);
            relsesigs();
            reset(0);
        }
        if ((ibuf = Fopen(mailname, "r")) == NULL) {
            warn("%s", mailname);
            Fclose(obuf);
            rm(tempname);
            relsesigs();
            reset(0);
        }
        fseeko(ibuf, mailsize, SEEK_SET);
        while ((c = getc(ibuf)) != EOF)
            putc(c, obuf);
        Fclose(ibuf);
        Fclose(obuf);
        if ((ibuf = Fopen(tempname, "r")) == NULL) {
            warn("%s", tempname);
            rm(tempname);
            relsesigs();
            reset(0);
        }
        rm(tempname);
    }
    printf("\"%s\" ", mailname);
    fflush(stdout);
    if ((obuf = Fopen(mailname, "r+")) == NULL) {
        warn("%s", mailname);
        relsesigs();
        reset(0);
    }
    trunc(obuf);
    c = 0;
    for (mp = &message[0]; mp < &message[msgCount]; mp++) {
        if ((mp->m_flag & MDELETED) != 0)
            continue;
        c++;
        if (sendmessage(mp, obuf, NULL, NULL) < 0) {
            warnx("%s", mailname);
            relsesigs();
            reset(0);
        }
    }
    gotcha = (c == 0 && ibuf == NULL);
    if (ibuf != NULL) {
        while ((c = getc(ibuf)) != EOF)
            putc(c, obuf);
        Fclose(ibuf);
    }
    fflush(obuf);
    if (ferror(obuf)) {
        warn("%s", mailname);
        relsesigs();
        reset(0);
    }
    Fclose(obuf);
    if (gotcha) {
        rm(mailname);
        printf("removed\n");
    } else
        printf("complete\n");
    fflush(stdout);

done:
    relsesigs();
}
Пример #6
0
/*
 * Set up editing on the given file name.
 * If the first character of name is %, we are considered to be
 * editing the file, otherwise we are reading our mail which has
 * signficance for mbox and so forth.
 *
 * If the -e option is being passed to mail, this function has a
 * tri-state return code: -1 on error, 0 on no mail, 1 if there is
 * mail.
 */
int
setfile(char *name)
{
	FILE *ibuf;
	int checkmode, i, fd;
	struct stat stb;
	char isedit = *name != '%' || getuserid(myname) != getuid();
	char *who = name[1] ? name + 1 : myname;
	char tempname[PATHSIZE];
	static int shudclob;

	checkmode = value("checkmode") != NULL;
	if ((name = expand(name)) == NULL)
		return (-1);

	if ((ibuf = Fopen(name, "r")) == NULL) {
		if (!isedit && errno == ENOENT)
			goto nomail;
		warn("%s", name);
		return (-1);
	}

	if (fstat(fileno(ibuf), &stb) < 0) {
		warn("fstat");
		(void)Fclose(ibuf);
		return (-1);
	}

	if (S_ISDIR(stb.st_mode) || !S_ISREG(stb.st_mode)) {
		(void)Fclose(ibuf);
		errno = S_ISDIR(stb.st_mode) ? EISDIR : EINVAL;
		warn("%s", name);
		return (-1);
	}

	/*
	 * Looks like all will be well.  We must now relinquish our
	 * hold on the current set of stuff.  Must hold signals
	 * while we are reading the new file, else we will ruin
	 * the message[] data structure.
	 */

	holdsigs();
	if (shudclob)
		quit();

	/*
	 * Copy the messages into /tmp
	 * and set pointers.
	 */

	readonly = 0;
	if ((i = open(name, 1)) < 0)
		readonly++;
	else
		(void)close(i);
	if (shudclob) {
		(void)fclose(itf);
		(void)fclose(otf);
	}
	shudclob = 1;
	edit = isedit;
	strlcpy(prevfile, mailname, sizeof(prevfile));
	if (name != mailname)
		strlcpy(mailname, name, sizeof(mailname));
	mailsize = fsize(ibuf);
	(void)snprintf(tempname, sizeof(tempname),
	    "%s/mail.RxXXXXXXXXXX", tmpdir);
	if ((fd = mkstemp(tempname)) == -1 || (otf = fdopen(fd, "w")) == NULL)
		err(1, "%s", tempname);
	(void)fcntl(fileno(otf), F_SETFD, 1);
	if ((itf = fopen(tempname, "r")) == NULL)
		err(1, "%s", tempname);
	(void)fcntl(fileno(itf), F_SETFD, 1);
	(void)rm(tempname);
	setptr(ibuf, 0);
	setmsize(msgCount);
	/*
	 * New mail may have arrived while we were reading
	 * the mail file, so reset mailsize to be where
	 * we really are in the file...
	 */
	mailsize = ftello(ibuf);
	(void)Fclose(ibuf);
	relsesigs();
	sawcom = 0;

	if ((checkmode || !edit) && msgCount == 0) {
nomail:
		if (!checkmode) {
			fprintf(stderr, "No mail for %s\n", who);
			return (-1);
		} else
			return (0);
	}
	return (checkmode ? 1 : 0);
}
Пример #7
0
/*
 * 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(void)
{
	int gotcha, c;
	struct message *mp;
	FILE *obuf, *ibuf;
	struct stat statb;
	char tempname[PATHSIZE];

	if (readonly)
		return(0);
	holdsigs();
	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 (!gotcha)
		goto done;
	ibuf = NULL;
	if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
		int fd;

		(void)snprintf(tempname, sizeof(tempname), "%s/mbox.XXXXXXXXXX",
		    tmpdir);
		if ((fd = mkstemp(tempname)) == -1 ||
		    (obuf = Fdopen(fd, "w")) == NULL) {
			warn("%s", tempname);
			if (fd != -1)
				close(fd);
			relsesigs();
			return(-1);
		}
		if ((ibuf = Fopen(mailname, "r")) == NULL) {
			warn("%s", mailname);
			(void)Fclose(obuf);
			(void)rm(tempname);
			relsesigs();
			return(-1);
		}
		fseek(ibuf, (long)mailsize, SEEK_SET);
		while ((c = getc(ibuf)) != EOF)
			(void)putc(c, obuf);
		(void)Fclose(ibuf);
		(void)Fclose(obuf);
		if ((ibuf = Fopen(tempname, "r")) == NULL) {
			warn("%s", tempname);
			(void)rm(tempname);
			relsesigs();
			return(-1);
		}
		(void)rm(tempname);
	}
	printf("\"%s\" ", mailname);
	fflush(stdout);
	if ((obuf = Fopen(mailname, "r+")) == NULL) {
		warn("%s", mailname);
		relsesigs();
		return(-1);
	}
	trunc(obuf);
	c = 0;
	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
		if ((mp->m_flag & MDELETED) != 0)
			continue;
		c++;
		if (sendmessage(mp, obuf, NULL, NULL) < 0) {
			warn("%s", mailname);
			relsesigs();
			return(-1);
		}
	}
	gotcha = (c == 0 && ibuf == NULL);
	if (ibuf != NULL) {
		while ((c = getc(ibuf)) != EOF)
			(void)putc(c, obuf);
		(void)Fclose(ibuf);
	}
	fflush(obuf);
	if (ferror(obuf)) {
		warn("%s", mailname);
		relsesigs();
		return(-1);
	}
	(void)Fclose(obuf);
	if (gotcha) {
		(void)rm(mailname);
		puts("removed");
	} else
		puts("complete");
	fflush(stdout);

done:
	relsesigs();
	return(0);
}