Annotation of researchv10no/cmd/nupas/smtp/qlib.c, revision 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.