Annotation of researchv10no/cmd/nupas/smtp/qlib.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.