194 lines
3.1 KiB
C
194 lines
3.1 KiB
C
|
|
#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;
|
||
|
|
}
|