|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <ctype.h> ! 3: #include "string.h" ! 4: #include "smtp.h" ! 5: #include "mail.h" ! 6: #include <sys/stat.h> ! 7: ! 8: char spoolsubdir[1026]; ! 9: extern char *UPASROOT; ! 10: ! 11: /* ! 12: * copy the directory component of `file' into lf. return ! 13: * a pointer to the base name of `file' ! 14: */ ! 15: static char * ! 16: copydir(lf, file) ! 17: string *lf; ! 18: char *file; ! 19: { ! 20: char *base; ! 21: ! 22: base = strrchr(file, '/'); ! 23: if (base){ ! 24: *base = 0; ! 25: s_append(lf, file); ! 26: s_append(lf, "/"); ! 27: *base++ = '/'; ! 28: } else ! 29: base = file; ! 30: return base; ! 31: } ! 32: ! 33: /* ! 34: * convert the control file name into a file name of the ! 35: * type specified. ! 36: */ ! 37: char * ! 38: fileoftype(type, ctl) ! 39: char type; ! 40: char *ctl; ! 41: { ! 42: static string *x; ! 43: char *cp; ! 44: ! 45: x = s_reset(x); ! 46: s_append(x, ctl); ! 47: cp = strrchr(s_to_c(x), '/'); ! 48: if(cp) ! 49: cp++; ! 50: else ! 51: cp = s_to_c(x); ! 52: *cp = type; ! 53: return s_to_c(x); ! 54: } ! 55: ! 56: /* ! 57: * creates a file with a unique name ! 58: * based on `template'. Any trailing string of x's in the ! 59: * template are converted to pppppsssssvv, where ppppp is the ! 60: * process id, sssss is the last 16 bits of the time, vv is enough ! 61: * to make the name unique. If there aren't enough x's to fit all ! 62: * of pppppsssssvv, only as much as will fit (starting right to left) ! 63: * will be substituted for the x's. ! 64: * ! 65: * returns an open fd or -1 if the file couldn't be created. ! 66: * the new name is put into template. ! 67: */ ! 68: mkdatafile(template) ! 69: char *template; ! 70: { ! 71: struct stat s; ! 72: int i, len, pid, fd; ! 73: long seed; ! 74: char hash[14]; ! 75: char *xp; ! 76: ! 77: /* ! 78: * find the number of x's ! 79: */ ! 80: if((len = strlen(template))==0) ! 81: return -1; ! 82: for(xp = template+len-1; xp>=template; xp--) ! 83: if(*xp!='x') ! 84: break; ! 85: xp++; ! 86: len = len-(xp-template); ! 87: ! 88: /* ! 89: * make sure it's <= 12 ! 90: */ ! 91: if(len>12) ! 92: len = 12; ! 93: pid = getpid(); ! 94: seed = (time((long *)0)%100000)*100; ! 95: ! 96: /* ! 97: * try 100 different file names ! 98: */ ! 99: for(i=0; i<100; i++){ ! 100: sprintf(hash, "%05d%07d", pid, seed+i); ! 101: strncpy(xp, hash+(12-len), len); ! 102: if(stat(template, &s)>=0) ! 103: continue; ! 104: if((fd = creat(template, 0660))<0) ! 105: return -1; ! 106: return fd; ! 107: } ! 108: return -1; ! 109: } ! 110: ! 111: /* ! 112: * creates a control file to go with the data file. ! 113: * the control file name is the same as the data file ! 114: * with the first character replaced by 'C'. ! 115: */ ! 116: int ! 117: mkctlfile(letter, dataname, contents) ! 118: char letter; ! 119: char *dataname; ! 120: char *contents; ! 121: { ! 122: int fd; ! 123: static string *cf; ! 124: static string *tf; ! 125: ! 126: /* ! 127: * make the file names ! 128: */ ! 129: cf = s_reset(cf); ! 130: s_append(cf, fileoftype(letter, dataname)); ! 131: tf = s_reset(tf); ! 132: s_append(tf, fileoftype('T', dataname)); ! 133: ! 134: /* ! 135: * create the control file with a temporary (non-control) name ! 136: */ ! 137: fd = creat(s_to_c(tf), 0660); ! 138: if (fd<0) ! 139: return -1; ! 140: if(write(fd, contents, strlen(contents))!=strlen(contents)){ ! 141: close(fd); ! 142: unlink(s_to_c(tf)); ! 143: return -1; ! 144: } ! 145: if(close(fd)<0){ ! 146: unlink(s_to_c(tf)); ! 147: return -1; ! 148: } ! 149: ! 150: /* ! 151: * change it's name so that it looks like a control file ! 152: */ ! 153: if(link(s_to_c(tf), s_to_c(cf))<0){ ! 154: unlink(s_to_c(tf)); ! 155: return -1; ! 156: } ! 157: unlink(s_to_c(tf)); ! 158: return 0; ! 159: } ! 160: ! 161: /* ! 162: * Fill name with the lock name for file. The lockname is ! 163: * dir/L.xxx where dir is the directory containing the file ! 164: * being locked and xxx is the first 12 characters of that file's ! 165: * name. ! 166: */ ! 167: static ! 168: setlname(lf, file) ! 169: string *lf; ! 170: char *file; ! 171: { ! 172: char *base; ! 173: ! 174: /* ! 175: * copy over directory portion ! 176: */ ! 177: base = copydir(lf, file); ! 178: ! 179: /* ! 180: * copy in the rest ! 181: */ ! 182: s_append(lf, "L."); ! 183: s_append(lf, base); ! 184: ! 185: /* ! 186: * make sure we didn't get too long ! 187: */ ! 188: base = strrchr(s_to_c(lf), '/'); ! 189: if(base) ! 190: base++; ! 191: else ! 192: base = s_to_c(lf); ! 193: if(strlen(base)>14) ! 194: base[14] = 0; ! 195: } ! 196: ! 197: /* ! 198: * Return true if file has been locked by us or another program using the same ! 199: * lock name scheme. ! 200: * ! 201: * Remove the lock file if the locking process has gone away. ! 202: */ ! 203: int ! 204: islocked(file) ! 205: char *file; ! 206: { ! 207: struct stat stbuf; ! 208: static string *ln; ! 209: int pid; ! 210: FILE *fp; ! 211: ! 212: ln = s_reset(ln); ! 213: if(setlname(ln, file)<0) ! 214: return 1; ! 215: if(stat(s_to_c(ln), &stbuf)==0) { ! 216: fp = fopen(s_to_c(ln), "r"); ! 217: if (fp == 0 || fscanf(fp, "%d", &pid)!=1) { ! 218: /* ! 219: * either we made the lock wrong ! 220: * or it just went away (race) ! 221: */ ! 222: fprintf(stderr, "can't read pid: breaking lock %s\n", ! 223: s_to_c(ln)); ! 224: if(fp) ! 225: fclose(fp); ! 226: unlink(s_to_c(ln)); ! 227: return 0; ! 228: } ! 229: if(fp) ! 230: fclose(fp); ! 231: if (kill(pid, 0) == 0) ! 232: return 1; ! 233: ! 234: /* ! 235: * locker has gone away ! 236: */ ! 237: fprintf(stderr, "breaking stale lock %s\n", s_to_c(ln)); ! 238: unlink(s_to_c(ln)); ! 239: } ! 240: return 0; ! 241: } ! 242: ! 243: /* ! 244: * lock a file being processed. see setlname (above) for the name of the lock. ! 245: * the lock file is in the same directory. ! 246: * ! 247: * returns 0 if the lock was granted, -1 otherwise. this is a none ! 248: * blocking routine. ! 249: */ ! 250: lock(file) ! 251: char *file; ! 252: { ! 253: int fd; ! 254: char *sp; ! 255: char pidbuf[20]; ! 256: static string *tn; ! 257: static string *ln; ! 258: ! 259: /* ! 260: * create a temporary file (in same directory) ! 261: */ ! 262: tn = s_reset(tn); ! 263: copydir(tn, file); ! 264: s_append(tn, "T.xxxxxxxxxxxx"); ! 265: fd = mkdatafile(s_to_c(tn)); ! 266: if(fd<0) ! 267: return -1; ! 268: sprintf(pidbuf, "%d lock", getpid()); ! 269: write(fd, pidbuf, strlen(pidbuf)); ! 270: close(fd); ! 271: ! 272: /* ! 273: * Make a link to it with the lock file name. This will fail only ! 274: * if it already exists. ! 275: */ ! 276: ln = s_reset(ln); ! 277: setlname(ln, file); ! 278: while(link(s_to_c(tn), s_to_c(ln)) < 0) { ! 279: /* ! 280: * might be a stale lock ! 281: */ ! 282: if(islocked(file)){ ! 283: unlink(s_to_c(tn)); ! 284: return -1; ! 285: } ! 286: } ! 287: unlink(s_to_c(tn)); ! 288: return 0; ! 289: } ! 290: ! 291: /* ! 292: * unlock a file ! 293: */ ! 294: unlock(file) ! 295: char *file; ! 296: { ! 297: static string *ln; ! 298: ! 299: ln = s_reset(ln); ! 300: setlname(ln, file); ! 301: unlink(s_to_c(ln)); ! 302: } ! 303: ! 304: /* ! 305: * make a spool directory and cd into it. the spool directory is in ! 306: * /usr/spool/smtpq and it's name is the 2 most significant elements of ! 307: * the domain name, `target'. ! 308: */ ! 309: #define WEIRD "weird.domain" ! 310: gotodir(target) ! 311: char *target; ! 312: { ! 313: register char *bp, *lp, *last; ! 314: char t[256]; ! 315: int elems; ! 316: ! 317: if(chdir(SMTPQROOT)<0){ ! 318: mkdir(SMTPQROOT, 0775); ! 319: if(chdir(SMTPQROOT)<0) { ! 320: Syslog(LOG_WARNING, "Could not create %s", SMTPQROOT); ! 321: return -1; ! 322: } ! 323: } ! 324: ! 325: for (bp=target, lp=t; *bp; bp++, lp++) { ! 326: if (*bp == '/') ! 327: *lp = '.'; ! 328: else if (isupper(*bp)) ! 329: *lp = tolower(*bp); ! 330: else ! 331: *lp = *bp; ! 332: } ! 333: *lp = '\0'; ! 334: ! 335: if (strncmp(t, "dk!", 3) == 0) ! 336: bp = t + 3; ! 337: else if (strncmp(t, "tcp!", 4) == 0) ! 338: bp = t + 4; ! 339: else ! 340: bp = t; ! 341: ! 342: if ((lp=strchr(bp, '!')) != NULL) /*ignore trailing service*/ ! 343: *lp-- = '\0'; ! 344: else ! 345: lp = bp + strlen(bp); ! 346: last = lp; ! 347: ! 348: for(elems=0; lp>bp && last-(--lp)<MAXPATHLEN; ){ ! 349: if(*lp=='.') ! 350: if(++elems==6){ ! 351: lp++; ! 352: break; ! 353: } ! 354: } ! 355: bp = lp; ! 356: while ((*bp != '\0') && (*bp == '.')) ! 357: bp++; ! 358: ! 359: if (*bp == '\0') ! 360: strcpy(spoolsubdir, WEIRD); ! 361: else ! 362: strcpy(spoolsubdir, bp); ! 363: ! 364: if(chdir(spoolsubdir)<0){ ! 365: mkdir(spoolsubdir, 0775); ! 366: if(chdir(spoolsubdir)<0) { ! 367: Syslog(LOG_WARNING, "Could not chdir to %s", spoolsubdir); ! 368: return -1; ! 369: } ! 370: } ! 371: ! 372: return 0; ! 373: } ! 374: ! 375: /* ! 376: * start the scheduler ! 377: */ ! 378: smtpsched(av0, target) ! 379: char *av0; ! 380: char *target; ! 381: { ! 382: int status; ! 383: static string *cmd; ! 384: ! 385: switch(fork()){ ! 386: case -1: ! 387: break; ! 388: case 0: ! 389: /* ! 390: * exec the sched process ! 391: */ ! 392: cmd = s_reset(cmd); ! 393: s_append(cmd, UPASROOT); ! 394: s_append(cmd, "/smtpsched"); ! 395: execl(s_to_c(cmd), av0, target, 0); ! 396: exit(1); ! 397: default: ! 398: /* ! 399: * wait for any sub processes to finish ! 400: */ ! 401: while(wait(&status)>=0) ! 402: ; ! 403: break; ! 404: } ! 405: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.