]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/upas/q/qer.c
upas/fs: fix more locking bugs, remove debugging clutter, remove planb mbox code
[plan9front.git] / sys / src / cmd / upas / q / qer.c
1 #include "common.h"
2
3 typedef struct Qfile Qfile;
4 struct Qfile
5 {
6         Qfile   *next;
7         char    *name;
8         char    *tname;
9 } *files;
10
11 char *user;
12 int isnone;
13
14 int     copy(Qfile*);
15
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 }
22
23 void
24 error(char *f, char *a)
25 {
26         char err[ERRMAX];
27         char buf[256];
28
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 }
34
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;
47
48         l = &files;
49         qdir = 0;
50
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;
66
67         if(argc < 3)
68                 usage();
69         user = getuser();
70         isnone = (qdir != 0) || (strcmp(user, "none") == 0);
71
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);
78
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++;
87
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;
95
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);
104                 }
105                 perm = isnone?0664:0660;
106                 fd = create(s_to_c(f), OWRITE, perm);
107                 if(fd >= 0)
108                         break;
109                 sleep(250);
110         }
111         if(fd < 0)
112                 error("creating data file %s", s_to_c(f));
113
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)++;
124                 }
125         }
126
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", buf);
135                 }
136                 if(write(fd, buf, n) != n)
137                         error("writing data file %s", s_to_c(f));
138         }
139 /*      if(n < 0)
140                 error("reading input"); */
141         close(fd);
142
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, " ");
154         }
155         for(q = files; q; q = q->next){
156                 s_append(c, q->tname);
157                 s_append(c, " ");
158         }
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));
163         }
164         sysunlockfile(fd);
165         exits(0);
166 }
167
168 int
169 copy(Qfile *q)
170 {
171         int from, to, n;
172         char buf[4096];
173
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;
181         }
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;
189         }
190         close(to);
191         close(from);
192         return n;
193 }