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

unix.superglobalmegacorp.com

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