17dd7cddfSDavid du Colombier #include "common.h"
23e12c5d1SDavid du Colombier
3219b2ee8SDavid du Colombier typedef struct Qfile Qfile;
4219b2ee8SDavid du Colombier struct Qfile
5219b2ee8SDavid du Colombier {
6219b2ee8SDavid du Colombier Qfile *next;
7219b2ee8SDavid du Colombier char *name;
8219b2ee8SDavid du Colombier char *tname;
9219b2ee8SDavid du Colombier } *files;
10219b2ee8SDavid du Colombier
117dd7cddfSDavid du Colombier char *user;
127dd7cddfSDavid du Colombier int isnone;
137dd7cddfSDavid du Colombier
14219b2ee8SDavid du Colombier int copy(Qfile*);
15219b2ee8SDavid du Colombier
163e12c5d1SDavid du Colombier void
usage(void)173e12c5d1SDavid du Colombier usage(void)
183e12c5d1SDavid du Colombier {
197dd7cddfSDavid du Colombier fprint(2, "usage: qer [-f file] [-q dir] q-root description reply-to arg-list\n");
203e12c5d1SDavid du Colombier exits("usage");
213e12c5d1SDavid du Colombier }
223e12c5d1SDavid du Colombier
233e12c5d1SDavid du Colombier void
error(char * f,char * a)243e12c5d1SDavid du Colombier error(char *f, char *a)
253e12c5d1SDavid du Colombier {
26*9a747e4fSDavid du Colombier char err[Errlen+1];
273e12c5d1SDavid du Colombier char buf[256];
283e12c5d1SDavid du Colombier
29*9a747e4fSDavid du Colombier rerrstr(err, sizeof(err));
307dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), f, a);
313e12c5d1SDavid du Colombier fprint(2, "qer: %s: %s\n", buf, err);
323e12c5d1SDavid du Colombier exits(buf);
333e12c5d1SDavid du Colombier }
343e12c5d1SDavid du Colombier
353e12c5d1SDavid du Colombier void
main(int argc,char ** argv)36219b2ee8SDavid du Colombier main(int argc, char**argv)
373e12c5d1SDavid du Colombier {
38*9a747e4fSDavid du Colombier Dir *dir;
393e12c5d1SDavid du Colombier String *f, *c;
403e12c5d1SDavid du Colombier int fd;
413e12c5d1SDavid du Colombier char file[1024];
423e12c5d1SDavid du Colombier char buf[1024];
433e12c5d1SDavid du Colombier long n;
447dd7cddfSDavid du Colombier char *cp, *qdir;
453e12c5d1SDavid du Colombier int i;
46219b2ee8SDavid du Colombier Qfile *q, **l;
473e12c5d1SDavid du Colombier
48219b2ee8SDavid du Colombier l = &files;
497dd7cddfSDavid du Colombier qdir = 0;
50219b2ee8SDavid du Colombier
51219b2ee8SDavid du Colombier ARGBEGIN {
52219b2ee8SDavid du Colombier case 'f':
53219b2ee8SDavid du Colombier q = malloc(sizeof(Qfile));
54219b2ee8SDavid du Colombier q->name = ARGF();
55219b2ee8SDavid du Colombier q->next = *l;
56219b2ee8SDavid du Colombier *l = q;
57219b2ee8SDavid du Colombier break;
587dd7cddfSDavid du Colombier case 'q':
597dd7cddfSDavid du Colombier qdir = ARGF();
607dd7cddfSDavid du Colombier if(qdir == 0)
617dd7cddfSDavid du Colombier usage();
627dd7cddfSDavid du Colombier break;
63219b2ee8SDavid du Colombier default:
64219b2ee8SDavid du Colombier usage();
65219b2ee8SDavid du Colombier } ARGEND;
66219b2ee8SDavid du Colombier
67219b2ee8SDavid du Colombier if(argc < 3)
683e12c5d1SDavid du Colombier usage();
697dd7cddfSDavid du Colombier user = getuser();
707dd7cddfSDavid du Colombier isnone = (qdir != 0) || (strcmp(user, "none") == 0);
713e12c5d1SDavid du Colombier
727dd7cddfSDavid du Colombier if(qdir == 0) {
737dd7cddfSDavid du Colombier qdir = user;
747dd7cddfSDavid du Colombier if(qdir == 0)
757dd7cddfSDavid du Colombier error("unknown user", 0);
763e12c5d1SDavid du Colombier }
777dd7cddfSDavid du Colombier snprint(file, sizeof(file), "%s/%s", argv[0], qdir);
783e12c5d1SDavid du Colombier
793e12c5d1SDavid du Colombier /*
807dd7cddfSDavid du Colombier * data file name
813e12c5d1SDavid du Colombier */
823e12c5d1SDavid du Colombier f = s_copy(file);
833e12c5d1SDavid du Colombier s_append(f, "/D.XXXXXX");
843e12c5d1SDavid du Colombier mktemp(s_to_c(f));
857dd7cddfSDavid du Colombier cp = utfrrune(s_to_c(f), '/');
867dd7cddfSDavid du Colombier cp++;
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier /*
897dd7cddfSDavid du Colombier * create directory and data file. once the data file
907dd7cddfSDavid du Colombier * exists, runq won't remove the directory
917dd7cddfSDavid du Colombier */
927dd7cddfSDavid du Colombier fd = -1;
937dd7cddfSDavid du Colombier for(i = 0; i < 10; i++){
947dd7cddfSDavid du Colombier int perm;
957dd7cddfSDavid du Colombier
96*9a747e4fSDavid du Colombier dir = dirstat(file);
97*9a747e4fSDavid du Colombier if(dir == nil){
987dd7cddfSDavid du Colombier perm = isnone?0777:0775;
997dd7cddfSDavid du Colombier if(sysmkdir(file, perm) < 0)
1007dd7cddfSDavid du Colombier continue;
1017dd7cddfSDavid du Colombier } else {
102*9a747e4fSDavid du Colombier if((dir->qid.type&QTDIR)==0)
1037dd7cddfSDavid du Colombier error("not a directory %s", file);
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier perm = isnone?0664:0660;
1067dd7cddfSDavid du Colombier fd = create(s_to_c(f), OWRITE, perm);
1077dd7cddfSDavid du Colombier if(fd >= 0)
1087dd7cddfSDavid du Colombier break;
1097dd7cddfSDavid du Colombier sleep(250);
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier if(fd < 0)
1127dd7cddfSDavid du Colombier error("creating data file %s", s_to_c(f));
113219b2ee8SDavid du Colombier
114219b2ee8SDavid du Colombier /*
115219b2ee8SDavid du Colombier * copy over associated files
116219b2ee8SDavid du Colombier */
117219b2ee8SDavid du Colombier if(files){
118219b2ee8SDavid du Colombier *cp = 'F';
119219b2ee8SDavid du Colombier for(q = files; q; q = q->next){
120219b2ee8SDavid du Colombier q->tname = strdup(s_to_c(f));
121219b2ee8SDavid du Colombier if(copy(q) < 0)
122219b2ee8SDavid du Colombier error("copying %s to queue", q->name);
123219b2ee8SDavid du Colombier (*cp)++;
124219b2ee8SDavid du Colombier }
125219b2ee8SDavid du Colombier }
126219b2ee8SDavid du Colombier
127219b2ee8SDavid du Colombier /*
128219b2ee8SDavid du Colombier * copy in the data file
129219b2ee8SDavid du Colombier */
1307dd7cddfSDavid du Colombier i = 0;
1317dd7cddfSDavid du Colombier while((n = read(0, buf, sizeof(buf)-1)) > 0){
1327dd7cddfSDavid du Colombier if(i++ == 0 && strncmp(buf, "From", 4) != 0){
1337dd7cddfSDavid du Colombier buf[n] = 0;
1347dd7cddfSDavid du Colombier syslog(0, "smtp", "qer usys data starts with %-40.40s\n", buf);
1357dd7cddfSDavid du Colombier }
1363e12c5d1SDavid du Colombier if(write(fd, buf, n) != n)
1373e12c5d1SDavid du Colombier error("writing data file %s", s_to_c(f));
1387dd7cddfSDavid du Colombier }
1393e12c5d1SDavid du Colombier /* if(n < 0)
1403e12c5d1SDavid du Colombier error("reading input"); */
1413e12c5d1SDavid du Colombier close(fd);
1423e12c5d1SDavid du Colombier
1433e12c5d1SDavid du Colombier /*
1443e12c5d1SDavid du Colombier * create control file
1453e12c5d1SDavid du Colombier */
1463e12c5d1SDavid du Colombier *cp = 'C';
1477dd7cddfSDavid du Colombier fd = syscreatelocked(s_to_c(f), OWRITE, 0664);
1483e12c5d1SDavid du Colombier if(fd < 0)
1493e12c5d1SDavid du Colombier error("creating control file %s", s_to_c(f));
1503e12c5d1SDavid du Colombier c = s_new();
151219b2ee8SDavid du Colombier for(i = 1; i < argc; i++){
152219b2ee8SDavid du Colombier s_append(c, argv[i]);
153219b2ee8SDavid du Colombier s_append(c, " ");
154219b2ee8SDavid du Colombier }
155219b2ee8SDavid du Colombier for(q = files; q; q = q->next){
156219b2ee8SDavid du Colombier s_append(c, q->tname);
1573e12c5d1SDavid du Colombier s_append(c, " ");
1583e12c5d1SDavid du Colombier }
1593e12c5d1SDavid du Colombier s_append(c, "\n");
1607dd7cddfSDavid du Colombier if(write(fd, s_to_c(c), strlen(s_to_c(c))) < 0) {
1617dd7cddfSDavid du Colombier sysunlockfile(fd);
1623e12c5d1SDavid du Colombier error("writing control file %s", s_to_c(f));
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier sysunlockfile(fd);
1653e12c5d1SDavid du Colombier exits(0);
1663e12c5d1SDavid du Colombier }
167219b2ee8SDavid du Colombier
168219b2ee8SDavid du Colombier int
copy(Qfile * q)169219b2ee8SDavid du Colombier copy(Qfile *q)
170219b2ee8SDavid du Colombier {
171219b2ee8SDavid du Colombier int from, to, n;
172219b2ee8SDavid du Colombier char buf[4096];
173219b2ee8SDavid du Colombier
174219b2ee8SDavid du Colombier from = open(q->name, OREAD);
175219b2ee8SDavid du Colombier if(from < 0)
176219b2ee8SDavid du Colombier return -1;
177219b2ee8SDavid du Colombier to = create(q->tname, OWRITE, 0660);
178219b2ee8SDavid du Colombier if(to < 0){
179219b2ee8SDavid du Colombier close(from);
180219b2ee8SDavid du Colombier return -1;
181219b2ee8SDavid du Colombier }
182219b2ee8SDavid du Colombier for(;;){
183219b2ee8SDavid du Colombier n = read(from, buf, sizeof(buf));
184219b2ee8SDavid du Colombier if(n <= 0)
185219b2ee8SDavid du Colombier break;
186219b2ee8SDavid du Colombier n = write(to, buf, n);
187219b2ee8SDavid du Colombier if(n < 0)
188219b2ee8SDavid du Colombier break;
189219b2ee8SDavid du Colombier }
190219b2ee8SDavid du Colombier close(to);
191219b2ee8SDavid du Colombier close(from);
192219b2ee8SDavid du Colombier return n;
193219b2ee8SDavid du Colombier }
194