Blob


1 #include "common.h"
3 typedef struct Qfile Qfile;
4 struct Qfile
5 {
6 Qfile *next;
7 char *name;
8 char *tname;
9 } *files;
11 char *user;
12 int isnone;
14 int copy(Qfile*);
16 void
17 usage(void)
18 {
19 fprint(2, "usage: qer [-f file] [-q dir] q-root description reply-to arg-list\n");
20 exits("usage");
21 }
23 void
24 error(char *f, char *a)
25 {
26 char err[Errlen+1];
27 char buf[256];
29 rerrstr(err, sizeof(err));
30 snprint(buf, sizeof(buf), f, a);
31 fprint(2, "qer: %s: %s\n", buf, err);
32 exits(buf);
33 }
35 void
36 main(int argc, char**argv)
37 {
38 Dir *dir;
39 String *f, *c;
40 int fd;
41 char file[1024];
42 char buf[1024];
43 long n;
44 char *cp, *qdir;
45 int i;
46 Qfile *q, **l;
48 l = &files;
49 qdir = 0;
51 ARGBEGIN {
52 case 'f':
53 q = malloc(sizeof(Qfile));
54 q->name = ARGF();
55 q->next = *l;
56 *l = q;
57 break;
58 case 'q':
59 qdir = ARGF();
60 if(qdir == 0)
61 usage();
62 break;
63 default:
64 usage();
65 } ARGEND;
67 if(argc < 3)
68 usage();
69 user = getuser();
70 isnone = (qdir != 0) || (strcmp(user, "none") == 0);
72 if(qdir == 0) {
73 qdir = user;
74 if(qdir == 0)
75 error("unknown user", 0);
76 }
77 snprint(file, sizeof(file), "%s/%s", argv[0], qdir);
79 /*
80 * data file name
81 */
82 f = s_copy(file);
83 s_append(f, "/D.XXXXXX");
84 mktemp(s_to_c(f));
85 cp = utfrrune(s_to_c(f), '/');
86 cp++;
88 /*
89 * create directory and data file. once the data file
90 * exists, runq won't remove the directory
91 */
92 fd = -1;
93 for(i = 0; i < 10; i++){
94 int perm;
96 dir = dirstat(file);
97 if(dir == nil){
98 perm = isnone?0777:0775;
99 if(sysmkdir(file, perm) < 0)
100 continue;
101 } else {
102 if((dir->qid.type&QTDIR)==0)
103 error("not a directory %s", file);
105 perm = isnone?0664:0660;
106 fd = create(s_to_c(f), OWRITE, perm);
107 if(fd >= 0)
108 break;
109 sleep(250);
111 if(fd < 0)
112 error("creating data file %s", s_to_c(f));
114 /*
115 * copy over associated files
116 */
117 if(files){
118 *cp = 'F';
119 for(q = files; q; q = q->next){
120 q->tname = strdup(s_to_c(f));
121 if(copy(q) < 0)
122 error("copying %s to queue", q->name);
123 (*cp)++;
127 /*
128 * copy in the data file
129 */
130 i = 0;
131 while((n = read(0, buf, sizeof(buf)-1)) > 0){
132 if(i++ == 0 && strncmp(buf, "From", 4) != 0){
133 buf[n] = 0;
134 syslog(0, "smtp", "qer usys data starts with %-40.40s\n", buf);
136 if(write(fd, buf, n) != n)
137 error("writing data file %s", s_to_c(f));
139 /* if(n < 0)
140 error("reading input"); */
141 close(fd);
143 /*
144 * create control file
145 */
146 *cp = 'C';
147 fd = syscreatelocked(s_to_c(f), OWRITE, 0664);
148 if(fd < 0)
149 error("creating control file %s", s_to_c(f));
150 c = s_new();
151 for(i = 1; i < argc; i++){
152 s_append(c, argv[i]);
153 s_append(c, " ");
155 for(q = files; q; q = q->next){
156 s_append(c, q->tname);
157 s_append(c, " ");
159 s_append(c, "\n");
160 if(write(fd, s_to_c(c), strlen(s_to_c(c))) < 0) {
161 sysunlockfile(fd);
162 error("writing control file %s", s_to_c(f));
164 sysunlockfile(fd);
165 exits(0);
168 int
169 copy(Qfile *q)
171 int from, to, n;
172 char buf[4096];
174 from = open(q->name, OREAD);
175 if(from < 0)
176 return -1;
177 to = create(q->tname, OWRITE, 0660);
178 if(to < 0){
179 close(from);
180 return -1;
182 for(;;){
183 n = read(from, buf, sizeof(buf));
184 if(n <= 0)
185 break;
186 n = write(to, buf, n);
187 if(n < 0)
188 break;
190 close(to);
191 close(from);
192 return n;