Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "common.h"

typedef struct Qfile Qfile;
struct Qfile
{
        Qfile   *next;
        char    *name;
        char    *tname;
} *files;

char *user;
int isnone;

int     copy(Qfile*);

void
usage(void)
{
        fprint(2, "usage: qer [-f file] [-q dir] q-root description reply-to arg-list\n");
        exits("usage");
}

void
error(char *f, char *a)
{
        char err[Errlen+1];
        char buf[256];

        rerrstr(err, sizeof(err));
        snprint(buf, sizeof(buf),  f, a);
        fprint(2, "qer: %s: %s\n", buf, err);
        exits(buf);
}

void
main(int argc, char**argv)
{
        Dir     *dir;
        String  *f, *c;
        int     fd;
        char    file[1024];
        char    buf[1024];
        long    n;
        char    *cp, *qdir;
        int     i;
        Qfile   *q, **l;

        l = &files;
        qdir = 0;

        ARGBEGIN {
        case 'f':
                q = malloc(sizeof(Qfile));
                q->name = ARGF();
                q->next = *l;
                *l = q;
                break;
        case 'q':
                qdir = ARGF();
                if(qdir == 0)
                        usage();
                break;
        default:
                usage();
        } ARGEND;

        if(argc < 3)
                usage();
        user = getuser();
        isnone = (qdir != 0) || (strcmp(user, "none") == 0);

        if(qdir == 0) {
                qdir = user;
                if(qdir == 0)
                        error("unknown user", 0);
        }
        snprint(file, sizeof(file), "%s/%s", argv[0], qdir);

        /*
         *  data file name
         */
        f = s_copy(file);
        s_append(f, "/D.XXXXXX");
        mktemp(s_to_c(f));
        cp = utfrrune(s_to_c(f), '/');
        cp++;

        /*
         *  create directory and data file.  once the data file
         *  exists, runq won't remove the directory
         */
        fd = -1;
        for(i = 0; i < 10; i++){
                int perm;

                dir = dirstat(file);
                if(dir == nil){
                        perm = isnone?0777:0775;
                        if(sysmkdir(file, perm) < 0)
                                continue;
                } else {
                        if((dir->qid.type&QTDIR)==0)
                                error("not a directory %s", file);
                }
                perm = isnone?0664:0660;
                fd = create(s_to_c(f), OWRITE, perm);
                if(fd >= 0)
                        break;
                sleep(250);
        }
        if(fd < 0)
                error("creating data file %s", s_to_c(f));

        /*
         *  copy over associated files
         */
        if(files){
                *cp = 'F';
                for(q = files; q; q = q->next){
                        q->tname = strdup(s_to_c(f));
                        if(copy(q) < 0)
                                error("copying %s to queue", q->name);
                        (*cp)++;
                }
        }

        /*
         *  copy in the data file
         */
        i = 0;
        while((n = read(0, buf, sizeof(buf)-1)) > 0){
                if(i++ == 0 && strncmp(buf, "From", 4) != 0){
                        buf[n] = 0;
                        syslog(0, "smtp", "qer usys data starts with %-40.40s\n", buf);
                }
                if(write(fd, buf, n) != n)
                        error("writing data file %s", s_to_c(f));
        }
/*      if(n < 0)
                error("reading input"); */
        close(fd);

        /*
         *  create control file
         */
        *cp = 'C';
        fd = syscreatelocked(s_to_c(f), OWRITE, 0664);
        if(fd < 0)
                error("creating control file %s", s_to_c(f));
        c = s_new();
        for(i = 1; i < argc; i++){
                s_append(c, argv[i]);
                s_append(c, " ");
        }
        for(q = files; q; q = q->next){
                s_append(c, q->tname);
                s_append(c, " ");
        }
        s_append(c, "\n");
        if(write(fd, s_to_c(c), strlen(s_to_c(c))) < 0) {
                sysunlockfile(fd);
                error("writing control file %s", s_to_c(f));
        }
        sysunlockfile(fd);
        exits(0);
}

int
copy(Qfile *q)
{
        int from, to, n;
        char buf[4096];

        from = open(q->name, OREAD);
        if(from < 0)
                return -1;
        to = create(q->tname, OWRITE, 0660);
        if(to < 0){
                close(from);
                return -1;
        }
        for(;;){
                n = read(from, buf, sizeof(buf));
                if(n <= 0)
                        break;
                n = write(to, buf, n);
                if(n < 0)
                        break;
        }
        close(to);
        close(from);
        return n;
}