root/usr/src/cmd/mailx/cmd4.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/*        All Rights Reserved   */


/*
 * University Copyright- Copyright (c) 1982, 1986, 1988
 * The Regents of the University of California
 * All Rights Reserved
 *
 * University Acknowledgment- Portions of this document are derived from
 * software developed by the University of California, Berkeley, and its
 * contributors.
 */

#include "rcv.h"
#include <locale.h>

/*
 * mailx -- a modified version of a University of California at Berkeley
 *      mail program
 *
 * More commands..
 */

static char *stripquotes(char *str);

/*
 * pipe messages to cmd.
 */

int
dopipe(char str[])
{
        int *ip, mesg;
        struct message *mp;
        char *cp, *cmd;
        int f, *msgvec, nowait=0;
        void (*sigint)(int), (*sigpipe)(int);
        long lc, cc, t;
        pid_t pid;
        int page, s, pivec[2];
        char *Shell;
        FILE *pio = NULL;
        extern jmp_buf pipestop;
        extern void brokpipe(int);

        msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
        if ((cmd = stripquotes(snarf(str, &f, 0))) == NOSTR) {
                if (f == -1) {
                        printf(gettext("pipe command error\n"));
                        return(1);
                }
                if ( (cmd = value("cmd")) == NOSTR) {
                        printf(gettext("\"cmd\" not set, ignored.\n"));
                        return(1);
                }
        }
        if (!f) {
                *msgvec = first(0, MMNORM);
                if (*msgvec == 0) {
                        printf(gettext("No messages to pipe.\n"));
                        return(1);
                }
                msgvec[1] = 0;
        }
        if (f && getmsglist(str, msgvec, 0) < 0)
                return(1);
        if (*(cp=cmd+strlen(cmd)-1)=='&') {
                *cp=0;
                nowait++;
        }
        printf(gettext("Pipe to: \"%s\"\n"), cmd);
        flush();

        if (setjmp(pipestop))
                goto err;
                                        /*  setup pipe */
        if (pipe(pivec) < 0) {
                perror("pipe");
                return(0);
        }

        if ((pid = vfork()) == 0) {
                close(pivec[1]);        /* child */
                close(0);
                dup(pivec[0]);
                close(pivec[0]);
                if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
                        Shell = SHELL;
                execlp(Shell, Shell, "-c", cmd, 0);
                perror(Shell);
                _exit(1);
        }
        if (pid == (pid_t)-1) {         /* error */
                perror("fork");
                close(pivec[0]);
                close(pivec[1]);
                return(0);
        }

        close(pivec[0]);                /* parent */
        pio=fdopen(pivec[1],"w");
        sigint = sigset(SIGINT, SIG_IGN);
        sigpipe = sigset(SIGPIPE, brokpipe);

                                        /* send all messages to cmd */
        page = (value("page")!=NOSTR);
        lc = cc = 0;
        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                mesg = *ip;
                touch(mesg);
                mp = &message[mesg-1];
                dot = mp;
                if ((t = msend(mp, pio,
                    (value("alwaysignore") != NOSTR ||
                     value("pipeignore") != NOSTR)
                     ? M_IGNORE : 0, fputs)) < 0) {
                        perror(cmd);
                        sigset(SIGPIPE, sigpipe);
                        sigset(SIGINT, sigint);
                        fclose(pio);
                        return(1);
                }
                lc += t;
                cc += mp->m_size;
                if (page) putc('\f', pio);
        }

        fflush(pio);
        if (ferror(pio))
              perror(cmd);
        fclose(pio);
        pio = NULL;

                                        /* wait */
        if (!nowait) {
                while (wait(&s) != pid);
                s &= 0377;
                if (s != 0)
                        goto err;
        }

        printf("\"%s\" %ld/%ld\n", cmd, lc, cc);
        sigset(SIGPIPE, sigpipe);
        sigset(SIGINT, sigint);
        return(0);

err:
        printf(gettext("Pipe to \"%s\" failed\n"), cmd);
        if (pio)
                fclose(pio);
        sigset(SIGPIPE, sigpipe);
        sigset(SIGINT, sigint);
        return(0);
}

/*
 * Load the named message from the named file.
 */
int
loadmsg(char str[])
{
        char *file;
        int f, *msgvec;
        int c, lastc = '\n';
        int blank;
        int lines;
        long ms;
        FILE *ibuf;
        struct message *mp;
        off_t size;

        msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
        if ((file = snarf(str, &f, 1)) == NOSTR)
                return(1);
        if (f==-1)
                return(1);
        if (!f) {
                *msgvec = first(0, MMNORM);
                if (*msgvec == 0) {
                        printf(gettext("No message to load into.\n"));
                        return(1);
                }
                msgvec[1] = 0;
        }
        if (f && getmsglist(str, msgvec, 0) < 0)
                return(1);
        if (msgvec[1] != 0) {
                printf(gettext("Can only load into a single message.\n"));
                return(1);
        }
        if ((file = expand(file)) == NOSTR)
                return(1);
        printf("\"%s\" ", file);
        fflush(stdout);
        if ((ibuf = fopen(file, "r")) == NULL) {
                perror("");
                return(1);
        }
        mp = &message[*msgvec-1];
        dot = mp;
        mp->m_flag |= MODIFY;
        mp->m_flag &= ~MSAVED;          /* should probably turn off more */
        fseek(otf, (long) 0, 2);
        size = fsize(otf);
        mp->m_offset = size;
        ms = 0L;
        lines = 0;
        while ((c = getc(ibuf)) != EOF) {
                if (c == '\n') {
                        lines++;
                        blank = lastc == '\n';
                }
                lastc = c;
                putc(c, otf);
                if (ferror(otf))
                        break;
                ms++;
        }
        if (!blank) {
                putc('\n', otf);
                ms++;
                lines++;
        }
        mp->m_size = ms;
        mp->m_lines = lines;
        if (fferror(otf))
                perror("/tmp");
        fclose(ibuf);
        setclen(mp);
        printf(gettext("[Loaded] %d/%ld\n"), lines, ms);
        return(0);
}

/*
 * Display the named field.
 */
int
field(char str[])
{
        int *ip;
        struct message *mp;
        char *cp, *fld;
        int f, *msgvec;

        msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
        if ((fld = stripquotes(snarf(str, &f, 0))) == NOSTR) {
                if (f == -1)
                        printf(gettext("Bad field\n"));
                else
                        printf(gettext("No field specified\n"));
                return(1);
        }
        if (!f) {
                *msgvec = first(0, MMNORM);
                if (*msgvec == 0) {
                        printf(gettext("No messages to display.\n"));
                        return(1);
                }
                msgvec[1] = 0;
        }
        if (f && getmsglist(str, msgvec, 0) < 0)
                return(1);

        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                mp = &message[*ip - 1];
                dot = mp;
                if ((cp = hfield(fld, mp, addone)) != NULL)
                        printf("%s\n", cp);
        }
        return(0);
}

/*
 *  Remove the quotes from around the string passed in (if any).  Return
 *  the beginning of the result.
 */

static char *
stripquotes(char *str)
{
        int lastch;
        if (str == NOSTR) {
                return(NOSTR);
        }
        lastch = strlen(str)-1;
        if (any(*str, "\"'") && str[lastch] == *str) {
                str[lastch] = '\0';
                ++str;
        }
        return(str);
}