qer.c (3179B)
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[Errlen+1]; 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\n", 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 }