1*7dd7cddfSDavid 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 11*7dd7cddfSDavid du Colombier char *user; 12*7dd7cddfSDavid du Colombier int isnone; 13*7dd7cddfSDavid du Colombier 14219b2ee8SDavid du Colombier int copy(Qfile*); 15219b2ee8SDavid du Colombier 163e12c5d1SDavid du Colombier void 173e12c5d1SDavid du Colombier usage(void) 183e12c5d1SDavid du Colombier { 19*7dd7cddfSDavid 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 243e12c5d1SDavid du Colombier error(char *f, char *a) 253e12c5d1SDavid du Colombier { 263e12c5d1SDavid du Colombier char err[ERRLEN+1]; 273e12c5d1SDavid du Colombier char buf[256]; 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier errstr(err); 30*7dd7cddfSDavid 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 36219b2ee8SDavid du Colombier main(int argc, char**argv) 373e12c5d1SDavid du Colombier { 383e12c5d1SDavid 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; 44*7dd7cddfSDavid du Colombier char *cp, *qdir; 453e12c5d1SDavid du Colombier int i; 46219b2ee8SDavid du Colombier Qfile *q, **l; 473e12c5d1SDavid du Colombier 48219b2ee8SDavid du Colombier l = &files; 49*7dd7cddfSDavid 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; 58*7dd7cddfSDavid du Colombier case 'q': 59*7dd7cddfSDavid du Colombier qdir = ARGF(); 60*7dd7cddfSDavid du Colombier if(qdir == 0) 61*7dd7cddfSDavid du Colombier usage(); 62*7dd7cddfSDavid 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(); 69*7dd7cddfSDavid du Colombier user = getuser(); 70*7dd7cddfSDavid du Colombier isnone = (qdir != 0) || (strcmp(user, "none") == 0); 713e12c5d1SDavid du Colombier 72*7dd7cddfSDavid du Colombier if(qdir == 0) { 73*7dd7cddfSDavid du Colombier qdir = user; 74*7dd7cddfSDavid du Colombier if(qdir == 0) 75*7dd7cddfSDavid du Colombier error("unknown user", 0); 763e12c5d1SDavid du Colombier } 77*7dd7cddfSDavid du Colombier snprint(file, sizeof(file), "%s/%s", argv[0], qdir); 783e12c5d1SDavid du Colombier 793e12c5d1SDavid du Colombier /* 80*7dd7cddfSDavid 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)); 85*7dd7cddfSDavid du Colombier cp = utfrrune(s_to_c(f), '/'); 86*7dd7cddfSDavid du Colombier cp++; 87*7dd7cddfSDavid du Colombier 88*7dd7cddfSDavid du Colombier /* 89*7dd7cddfSDavid du Colombier * create directory and data file. once the data file 90*7dd7cddfSDavid du Colombier * exists, runq won't remove the directory 91*7dd7cddfSDavid du Colombier */ 92*7dd7cddfSDavid du Colombier fd = -1; 93*7dd7cddfSDavid du Colombier for(i = 0; i < 10; i++){ 94*7dd7cddfSDavid du Colombier int perm; 95*7dd7cddfSDavid du Colombier 96*7dd7cddfSDavid du Colombier if(dirstat(file, &dir) < 0){ 97*7dd7cddfSDavid du Colombier perm = isnone?0777:0775; 98*7dd7cddfSDavid du Colombier if(sysmkdir(file, perm) < 0) 99*7dd7cddfSDavid du Colombier continue; 100*7dd7cddfSDavid du Colombier } else { 101*7dd7cddfSDavid du Colombier if((dir.qid.path&CHDIR)==0) 102*7dd7cddfSDavid du Colombier error("not a directory %s", file); 103*7dd7cddfSDavid du Colombier } 104*7dd7cddfSDavid du Colombier perm = isnone?0664:0660; 105*7dd7cddfSDavid du Colombier fd = create(s_to_c(f), OWRITE, perm); 106*7dd7cddfSDavid du Colombier if(fd >= 0) 107*7dd7cddfSDavid du Colombier break; 108*7dd7cddfSDavid du Colombier sleep(250); 109*7dd7cddfSDavid du Colombier } 110*7dd7cddfSDavid du Colombier if(fd < 0) 111*7dd7cddfSDavid du Colombier error("creating data file %s", s_to_c(f)); 112219b2ee8SDavid du Colombier 113219b2ee8SDavid du Colombier /* 114219b2ee8SDavid du Colombier * copy over associated files 115219b2ee8SDavid du Colombier */ 116219b2ee8SDavid du Colombier if(files){ 117219b2ee8SDavid du Colombier *cp = 'F'; 118219b2ee8SDavid du Colombier for(q = files; q; q = q->next){ 119219b2ee8SDavid du Colombier q->tname = strdup(s_to_c(f)); 120219b2ee8SDavid du Colombier if(copy(q) < 0) 121219b2ee8SDavid du Colombier error("copying %s to queue", q->name); 122219b2ee8SDavid du Colombier (*cp)++; 123219b2ee8SDavid du Colombier } 124219b2ee8SDavid du Colombier } 125219b2ee8SDavid du Colombier 126219b2ee8SDavid du Colombier /* 127219b2ee8SDavid du Colombier * copy in the data file 128219b2ee8SDavid du Colombier */ 129*7dd7cddfSDavid du Colombier i = 0; 130*7dd7cddfSDavid du Colombier while((n = read(0, buf, sizeof(buf)-1)) > 0){ 131*7dd7cddfSDavid du Colombier if(i++ == 0 && strncmp(buf, "From", 4) != 0){ 132*7dd7cddfSDavid du Colombier buf[n] = 0; 133*7dd7cddfSDavid du Colombier syslog(0, "smtp", "qer usys data starts with %-40.40s\n", buf); 134*7dd7cddfSDavid du Colombier } 1353e12c5d1SDavid du Colombier if(write(fd, buf, n) != n) 1363e12c5d1SDavid du Colombier error("writing data file %s", s_to_c(f)); 137*7dd7cddfSDavid du Colombier } 1383e12c5d1SDavid du Colombier /* if(n < 0) 1393e12c5d1SDavid du Colombier error("reading input"); */ 1403e12c5d1SDavid du Colombier close(fd); 1413e12c5d1SDavid du Colombier 1423e12c5d1SDavid du Colombier /* 1433e12c5d1SDavid du Colombier * create control file 1443e12c5d1SDavid du Colombier */ 1453e12c5d1SDavid du Colombier *cp = 'C'; 146*7dd7cddfSDavid du Colombier fd = syscreatelocked(s_to_c(f), OWRITE, 0664); 1473e12c5d1SDavid du Colombier if(fd < 0) 1483e12c5d1SDavid du Colombier error("creating control file %s", s_to_c(f)); 1493e12c5d1SDavid du Colombier c = s_new(); 150219b2ee8SDavid du Colombier for(i = 1; i < argc; i++){ 151219b2ee8SDavid du Colombier s_append(c, argv[i]); 152219b2ee8SDavid du Colombier s_append(c, " "); 153219b2ee8SDavid du Colombier } 154219b2ee8SDavid du Colombier for(q = files; q; q = q->next){ 155219b2ee8SDavid du Colombier s_append(c, q->tname); 1563e12c5d1SDavid du Colombier s_append(c, " "); 1573e12c5d1SDavid du Colombier } 1583e12c5d1SDavid du Colombier s_append(c, "\n"); 159*7dd7cddfSDavid du Colombier if(write(fd, s_to_c(c), strlen(s_to_c(c))) < 0) { 160*7dd7cddfSDavid du Colombier sysunlockfile(fd); 1613e12c5d1SDavid du Colombier error("writing control file %s", s_to_c(f)); 162*7dd7cddfSDavid du Colombier } 163*7dd7cddfSDavid du Colombier sysunlockfile(fd); 1643e12c5d1SDavid du Colombier exits(0); 1653e12c5d1SDavid du Colombier } 166219b2ee8SDavid du Colombier 167219b2ee8SDavid du Colombier int 168219b2ee8SDavid du Colombier copy(Qfile *q) 169219b2ee8SDavid du Colombier { 170219b2ee8SDavid du Colombier int from, to, n; 171219b2ee8SDavid du Colombier char buf[4096]; 172219b2ee8SDavid du Colombier 173219b2ee8SDavid du Colombier from = open(q->name, OREAD); 174219b2ee8SDavid du Colombier if(from < 0) 175219b2ee8SDavid du Colombier return -1; 176219b2ee8SDavid du Colombier to = create(q->tname, OWRITE, 0660); 177219b2ee8SDavid du Colombier if(to < 0){ 178219b2ee8SDavid du Colombier close(from); 179219b2ee8SDavid du Colombier return -1; 180219b2ee8SDavid du Colombier } 181219b2ee8SDavid du Colombier for(;;){ 182219b2ee8SDavid du Colombier n = read(from, buf, sizeof(buf)); 183219b2ee8SDavid du Colombier if(n <= 0) 184219b2ee8SDavid du Colombier break; 185219b2ee8SDavid du Colombier n = write(to, buf, n); 186219b2ee8SDavid du Colombier if(n < 0) 187219b2ee8SDavid du Colombier break; 188219b2ee8SDavid du Colombier } 189219b2ee8SDavid du Colombier close(to); 190219b2ee8SDavid du Colombier close(from); 191219b2ee8SDavid du Colombier return n; 192219b2ee8SDavid du Colombier } 193