#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;
}
|