void qmsgunlink(ino_t n, time_t rightnow) { const char *bigbrother=getenv("ARCHIVEDIR"); if (bigbrother && *bigbrother) { struct tm *tmptr=localtime(&rightnow); /* Archive this message */ if (tmptr) { const char *dname=qmsgsdatname(n); const char *tname=strrchr(dname, '/'); char *p=courier_malloc(strlen(bigbrother)+ strlen(tname)+40); sprintf(p, "%s/%04d.%02d.%02d%s", bigbrother, tmptr->tm_year + 1900, tmptr->tm_mon+1, tmptr->tm_mday, tname); if (bigbrother_create_rename(dname, p) == 0) { dname=qmsgsctlname(n); strcpy(strrchr(p, '/'), strrchr(dname, '/')); if (rename(dname, p) == 0) { free(p); return; } } clog_msg_start_err(); clog_msg_str("Unable to move "); clog_msg_str(dname); clog_msg_str(" to "); clog_msg_str(p); clog_msg_send(); clog_msg_prerrno(); free(p); } } unlink(qmsgsdatname(n)); unlink(qmsgsctlname(n)); }
static void fax(struct moduledel *p) { struct ctlfile ctf; unsigned nreceipients=p->nreceipients; const char *host=p->host; const char *receipient; unsigned nrecipient=(unsigned)atol(p->receipients[0]); int pipefd[2]; pid_t child_proc; int faxopts; int n_cover_pages; FILE *fp; struct faxconv_err_args err_args; struct sort_file_list *page_list, *pp; #if HAVE_SETPGRP #if SETPGRP_VOID setpgrp(); #else setpgrp(0, 0); #endif #else #if HAVE_SETPGID setpgid(0, 0); #endif #endif if (comgetfaxopts(host, &faxopts)) { clog_msg_start_err(); clog_msg_str("courierfax: FATAL: invalid host"); clog_msg_send(); exit(1); } putenv(faxopts & FAX_LOWRES ? "FAXRES=lo":"FAXRES=hi"); if (nreceipients != 1) { clog_msg_start_err(); clog_msg_str("courierfax: FATAL: # receipients must be 1"); clog_msg_send(); exit(1); } receipient=p->receipients[1]; nrecipient=(unsigned)atol(p->receipients[0]); if (ctlfile_openi(p->inum, &ctf, 0)) clog_msg_errno(); /* Convert message to fax format, use a child process */ signal(SIGTERM, faxabort); if (pipe(pipefd) < 0) { clog_msg_errno(); } child_proc=fork(); if (child_proc < 0) { clog_msg_errno(); return; } if (child_proc == 0) { const char *fn; close(0); if (open("/dev/null", O_RDONLY) != 0) clog_msg_errno(); close(pipefd[0]); close(1); if (dup(pipefd[1]) != 1) { perror("dup"); exit(1); } close(2); if (dup(pipefd[1]) != 2) { fprintf(stderr, "ERROR: dup failed\n"); exit(1); } close(pipefd[1]); libmail_changeuidgid(MAILUID, MAILGID); fn=qmsgsdatname(p->inum); if (faxconvert(fn, faxopts, &n_cover_pages)) exit (1); if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "w")) == NULL || fprintf(fp, "%d\n", n_cover_pages) < 0 || fflush(fp) < 0) exit(1); fclose(fp); exit(0); } close(pipefd[1]); err_args.ctf= &ctf; err_args.nreceip=nrecipient; if (read_childerrmsg(child_proc, pipefd[0], &faxconvert_cleanup, &err_args)) { ctlfile_close(&ctf); return; } /* Hit it */ if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "r")) == NULL || fscanf(fp, "%d", &n_cover_pages) != 1) { if (fp) fclose(fp); ctlfile_append_reply(err_args.ctf, err_args.nreceip, "Internal error: cannot read number of cover pages", COMCTLFILE_DELFAIL, 0); ctlfile_close(&ctf); exit(0); } page_list=read_dir_sort_filenames(FAXTMPDIR, FAXTMPDIR "/"); if (!page_list) { clog_msg_start_err(); clog_msg_str("courierfax: INTERNAL ERROR - no pages to xmit."); clog_msg_send(); exit(1); } /* Keep trying until the modem line is unlocked */ do { if (pipe(pipefd) < 0) { clog_msg_errno(); } child_proc=fork(); if (child_proc < 0) { clog_msg_errno(); return; } if (child_proc == 0) { unsigned page_cnt=0; char **argvec; close(pipefd[0]); close(0); if (open("/dev/null", O_RDONLY) != 0) { perror("/dev/null"); exit(1); } close(1); if (dup(pipefd[1]) != 1) { perror("dup"); exit(1); } close(2); if (dup(pipefd[1]) != 2) { fprintf(stderr, "ERROR: dup failed\n"); exit(1); } close(pipefd[1]); for (pp=page_list; pp; pp=pp->next) ++page_cnt; #if 0 while (page_list) { unlink(page_list->filename); page_list=page_list->next; } exit(0); #endif argvec=(char **)courier_malloc(sizeof(char *)* (page_cnt+10)); argvec[0]=SENDFAX; argvec[1]="-v"; argvec[2]="-r"; page_cnt=3; if (faxopts & FAX_LOWRES) argvec[page_cnt++]="-n"; argvec[page_cnt++]=(char *)receipient; while (page_list) { argvec[page_cnt++]=page_list->filename; page_list=page_list->next; } argvec[page_cnt]=0; execv(SENDFAX, argvec); perror(SENDFAX); exit(1); } close(pipefd[1]); err_args.ctf= &ctf; err_args.nreceip=nrecipient; err_args.file_list=page_list; err_args.is_locked=0; err_args.n_cover_pages=n_cover_pages; if (read_childerrmsg(child_proc, pipefd[0], &faxsend_cleanup, &err_args) == 0) { size_t npages=0; char fmtbuf[NUMBUFSIZE]; char fmtbuf1[NUMBUFSIZE]; char fmtbuf2[NUMBUFSIZE+100]; for (pp=page_list; pp; pp=pp->next) ++npages; libmail_str_size_t(npages, fmtbuf); libmail_str_size_t(n_cover_pages, fmtbuf1); sprintf(fmtbuf2, "%s pages - including %s cover page(s)" " - sent by fax.", fmtbuf, fmtbuf1); ctlfile_append_reply(&ctf, (unsigned) nrecipient, fmtbuf2, COMCTLFILE_DELSUCCESS, " l"); break; } } while (err_args.is_locked); ctlfile_close(&ctf); rmdir_contents(FAXTMPDIR); }
int main(int argc, char **argv) { struct moduledel *p; clog_open_syslog("courierlocal"); if (chdir(courier_home=getenv("COURIER_HOME"))) clog_msg_errno(); if (atol(getenv("MAXRCPT")) > 1) { clog_msg_start_err(); clog_msg_str("Invalid configuration in config, set MAXRCPT=1"); clog_msg_send(); exit(1); } module_init(0); module_delivery_timeout(config_readtime("localtimeout", 15*60)); while ((p=module_getdel()) != NULL) { unsigned delid=atol(p->delid); unsigned rcptnum; struct ctlfile ctf; int pipe1[2], pipe2[2]; pid_t pid; int datfd; struct stat stat_buf; pid=module_fork(delid, 0); if (pid < 0) { clog_msg_prerrno(); module_completed(delid, delid); continue; } if (pid) continue; #if HAVE_SETPGRP #if SETPGRP_VOID setpgrp(); #else setpgrp(0, 0); #endif #endif if (p->nreceipients != 1) { clog_msg_start_err(); clog_msg_str("Invalid message from courierd."); clog_msg_send(); _exit(0); } rcptnum=atol(p->receipients[0]); if (ctlfile_openi(p->inum, &ctf, 0)) { clog_msg_errno(); _exit(0); } if (pipe(pipe1) < 0 || pipe(pipe2) < 0 || (pid=fork()) < 0) { clog_msg_prerrno(); ctlfile_append_reply(&ctf, rcptnum, "Can't run courierdeliver.", COMCTLFILE_DELDEFERRED, 0); ctlfile_close(&ctf); _exit(0); return (0); } if ((datfd=open(qmsgsdatname(p->inum), O_RDONLY)) < 0) { clog_msg_prerrno(); ctlfile_append_reply(&ctf, rcptnum, "Unable to read message file.", COMCTLFILE_DELDEFERRED, 0); ctlfile_close(&ctf); _exit(0); return (0); } if (pid == 0) { const char *host, *homedir, *maildir, *quota; char *buf, *s; char *username, *ext; uid_t u; gid_t g; close(pipe1[0]); close(pipe2[0]); dup2(pipe2[1], 2); close(pipe2[1]); dup2(pipe1[1], 1); close(pipe1[1]); close(0); if (dup(datfd) != 0) { clog_msg_start_err(); clog_msg_str("Unable to read message file."); clog_msg_send(); _exit(EX_TEMPFAIL); } close(ctf.fd); close(datfd); /* Contents of host: */ /* acct!ext!uid!gid!homedir!maildir!quota */ host=p->host; buf=strdup(host); if (!buf) { clog_msg_prerrno(); _exit(EX_TEMPFAIL); } s=strchr(buf, '!'); username=buf; if (s) *s++=0; ext=s; if (s) s=strchr(s, '!'); if (s) *s++=0; u=0; while (s && *s != '!') { if (isdigit((int)(unsigned char)*s)) u=u*10 + (*s - '0'); ++s; } if (s) *s++=0; g=0; while (s && *s != '!') { if (isdigit((int)(unsigned char)*s)) g=g*10 + (*s - '0'); ++s; } if (s) *s++=0; homedir=s; if (s) s=strchr(s, '!'); if (s) *s++=0; maildir=s; if (s) s=strchr(s, '!'); if (s) *s++=0; quota=s; if (!s) { clog_msg_start_err(); clog_msg_str("Invalid local recipient address."); clog_msg_send(); _exit(EX_TEMPFAIL); } if (chdir(homedir)) { clog_msg_str(homedir); clog_msg_str(": "); clog_msg_prerrno(); _exit(EX_TEMPFAIL); } libmail_changeuidgid(u, g); execl( MODULEDIR "/local/courierdeliver", "courierdeliver", username, homedir, ext, ctf.receipients[rcptnum], verp_getsender(&ctf, ctf.receipients[rcptnum]), quota, maildir, (const char *)0); clog_msg_start_err(); clog_msg_prerrno(); clog_msg_send(); _exit(EX_TEMPFAIL); } close(pipe1[1]); close(pipe2[1]); libmail_changeuidgid(MAILUID, MAILGID); if (fstat(datfd, &stat_buf) == 0) ctf.msgsize=stat_buf.st_size; close(datfd); wait_delivery(pid, &ctf, rcptnum, pipe2[0], pipe1[0], p->host, p->receipients[1]); ctlfile_close(&ctf); _exit(0); } return (0); }
static void wait_delivery(pid_t pid, struct ctlfile *ctf, unsigned rcptnum, int msgpipe, int fwdpipe, const char *user, const char *ext) { fd_set fds; int maxfd= msgpipe > fwdpipe ? msgpipe:fwdpipe; char buf[BUFSIZ]; int waitstat; char *sender=verp_getsender(ctf, ctf->receipients[rcptnum]); const char *oreceipient; char *oreceipients=0; if ( ctf->oreceipients[rcptnum] == 0 || ctf->oreceipients[rcptnum][0]) { oreceipient=ctf->oreceipients[rcptnum]; } else { oreceipient=oreceipients=dsnencodeorigaddr( ctf->receipients[rcptnum]); } ++maxfd; msglen=0; fwdlen=0; while (msgpipe >= 0 && fwdpipe >= 0) { int l; FD_ZERO(&fds); if (msgpipe >= 0) FD_SET(msgpipe, &fds); if (fwdpipe >= 0) FD_SET(fwdpipe, &fds); if (select(maxfd, &fds, 0, 0, 0) < 0) { clog_msg_prerrno(); continue; } if (msgpipe >= 0 && FD_ISSET(msgpipe, &fds)) { if ( (l=read(msgpipe, buf, sizeof(buf))) <= 0) { close(msgpipe); msgpipe=-1; } else savemsg(buf, l); } if (fwdpipe >= 0 && FD_ISSET(fwdpipe, &fds)) { if ( (l=read(fwdpipe, buf, sizeof(buf))) <= 0) { close(fwdpipe); fwdpipe=-1; } else fwdmsg(buf, l, sender, ctf->receipients[rcptnum], oreceipient); } } free(sender); while ( wait(&waitstat) != pid) ; if (msglen) { char *p, *q; msgbuf[msglen]=0; for (p=msgbuf; *p; ) { for (q=p; *q; ) { if (*q == '\n') { *q++=0; break; } q++; } ctlfile_append_info(ctf, rcptnum, p); p=q; } } if (submit_started && !submit_err) { FILE *f=fopen(qmsgsdatname(ctf->n), "r"); if (!f) submit_err=1; else { int c; fprintf(submit_to, "\nDelivered-To: %s\n", ctf->receipients[rcptnum]); while ((c=getc(f)) != EOF) putc(c, submit_to); if (ferror(f) || fflush(submit_to) || fclose(submit_to)) { submit_cancel(); submit_err=1; } else if (submit_readrcprinterr()) { submit_wait(); submit_err=1; } else if (submit_wait()) submit_err=1; } } if (WIFEXITED(waitstat)) switch (WEXITSTATUS(waitstat)) { case 0: case 99: if (submit_err) { ctlfile_append_reply(ctf, rcptnum, errbuf, COMCTLFILE_DELFAIL, 0); } else { ctlfile_append_reply(ctf, rcptnum, "Message delivered.", COMCTLFILE_DELSUCCESS, " l"); } if (oreceipients) free (oreceipients); return; case EX_SOFTWARE: ctlfile_append_reply(ctf, rcptnum, "", COMCTLFILE_DELFAIL_NOTRACK, 0); if (oreceipients) free (oreceipients); return; case 64: case 65: case 67: case 68: case 69: case 76: case 77: case 78: case 100: case 112: break; default: ctlfile_append_reply(ctf, rcptnum, "", COMCTLFILE_DELDEFERRED, 0); if (oreceipients) free (oreceipients); return; } ctlfile_append_reply(ctf, rcptnum, "", COMCTLFILE_DELFAIL, 0); if (oreceipients) free (oreceipients); }
int msgq::queuescan3(std::string subdir, std::string name, const char *isnewmsg) { struct ctlfile ctlinfo; ino_t inum; time_t deltime, delsendtime; const char *p=name.c_str(); struct stat stat_buf; ++p; inum=strtoino(p); while (isdigit(*p)) p++; ++p; deltime=strtotime(p); name= subdir + '/' + name; if (ctlfile_openfn(name.c_str(), &ctlinfo, 0, 1)) { if (errno) { clog_msg_start_err(); clog_msg_str("Cannot read "); clog_msg_str(name.c_str()); clog_msg_send(); clog_msg_prerrno(); } return (0); } delsendtime=deltime; if (flushtime && ctlinfo.mtime < flushtime && flushtime < deltime) delsendtime=flushtime; if (!queuefree) { msgq *p; // // msgq array is full. See if we can remove the last message from the // pending queue. p=queuetail; if (p && p->nextsenddel > delsendtime) { #if 0 clog_msg_start_info(); clog_msg_str("Removing "); clog_msg_uint(p->msgnum); clog_msg_str(" to make room for this message."); clog_msg_send(); #endif p->removewq(); p->removeq(); } } msgq *newq=queuefree; if (!newq) { ctlfile_close(&ctlinfo); if (queuefill && nextqueuefill == 0) { nextqueuefill=current_time + queuefill; } return (1); } const char *cn=qmsgsctlname(inum); if ( stat(cn, &stat_buf) == -1 ) { unlink(name.c_str()); unlink(qmsgsdatname(inum)); unlink(cn); ctlfile_close(&ctlinfo); return (0); } #if 0 clog_msg_start_info(); clog_msg_str("Adding "); clog_msg_uint(inum); clog_msg_str(" to queue."); clog_msg_send(); #endif queuefree=newq->next; ++queuedelivering; ino_t hashbucket=inum % queuehashfirst.size(); if (queuehashfirst[hashbucket]) queuehashfirst[hashbucket]->prevhash=newq; else queuehashlast[hashbucket]=newq; newq->nexthash=queuehashfirst[hashbucket]; newq->prevhash=0; queuehashfirst[hashbucket]=newq; newq->nksize= (unsigned long)stat_buf.st_size; ctlinfo.starttime=stat_buf.st_mtime; int k=ctlfile_searchfirst(&ctlinfo, COMCTLFILE_MSGID); newq->msgid= k < 0 ? "": ctlinfo.lines[k]+1; newq->msgnum=inum; newq->nextdel=deltime; newq->nextsenddel=delsendtime; newq->rcptinfo_list.resize(0); newq->rcptcount=0; newq->cancelled=ctlinfo.cancelled; if (isnewmsg) { int auth; clog_msg_start_info(); clog_msg_str("newmsg,id="); logmsgid(newq); auth=ctlfile_searchfirst(&ctlinfo, COMCTLFILE_AUTHNAME); if (auth >= 0) { clog_msg_str(", auth="); clog_msg_str(ctlinfo.lines[auth]+1); } int m=ctlfile_searchfirst(&ctlinfo, COMCTLFILE_FROMMTA); if (m >= 0) { clog_msg_str(": "); clog_msg_str(ctlinfo.lines[m]+1); } clog_msg_send(); } unsigned i, j; std::string host, addr; k=ctlfile_searchfirst(&ctlinfo, COMCTLFILE_SENDER); struct rfc822t *sendert=rw_rewrite_tokenize(k < 0 ? "":ctlinfo.lines[k]+1); std::string errmsg; for (i=0; i<ctlinfo.nreceipients; i++) { for (j=0; ctlinfo.lines[j]; j++) { switch (ctlinfo.lines[j][0]) { case COMCTLFILE_DELSUCCESS: case COMCTLFILE_DELFAIL: if ((unsigned)atoi(ctlinfo.lines[j]+1) == i) break; // This one has been delivered default: continue; } break; } if (ctlinfo.lines[j]) continue; drvinfo *module=getdelinfo(sendert->tokens, ctlinfo.receipients[i], host, addr, errmsg); if (!module) { ctlfile_append_reply(&ctlinfo, i, errmsg.c_str(), SMTPREPLY_TYPE(errmsg.c_str()), 0); continue; } /* Check if it's time to move the message to a backup relay */ if (backup_relay_driver && ctlfile_searchfirst(&ctlinfo, COMCTLFILE_WARNINGSENT) >= 0 && strcmp(module->module->name, backup_relay_driver->module->name) == 0) { // module=backup_relay_driver; host=backup_relay; } /* Group all recipients for the same driver and host together */ for (j=0; j<newq->rcptcount; j++) if (strcmp(module->module->name, newq->rcptinfo_list[j].delmodule-> module->name) == 0 && newq->rcptinfo_list[j].delhost == host && newq->rcptinfo_list[j].addresses.size() < module->maxrcpt ) break; if (j == newq->rcptcount) { #if 0 clog_msg_start_info(); clog_msg_str("id="); logmsgid(newq); clog_msg_str(",new rcpt list - module="); clog_msg_str(module->module->name); clog_msg_str(", host="); clog_msg_str(host); clog_msg_send(); #endif newq->rcptinfo_list.resize(++newq->rcptcount); struct rw_info_rewrite rwir; struct rw_info rwi; rwir.buf=0; rwir.errmsg=0; rw_info_init(&rwi, sendert->tokens, rw_err_func); rwi.sender=0; rwi.mode=RW_OUTPUT|RW_ENVSENDER; rwi.udata= (void *)&rwir; rw_rewrite_module(module->module, &rwi, rw_rewrite_chksyn_print); char *address=((struct rw_info_rewrite *)rwi.udata)->buf; char *errmsg= ((struct rw_info_rewrite *)rwi.udata)->errmsg; if (!address) { ctlfile_append_reply(&ctlinfo, i, errmsg, SMTPREPLY_TYPE(errmsg), 0); newq->rcptinfo_list.resize(--newq->rcptcount); free(errmsg); continue; } if (errmsg) free(errmsg); newq->rcptinfo_list[j].init(newq, module, host, address); free(address); } #if 0 clog_msg_start_info(); clog_msg_str("id="); logmsgid(newq); clog_msg_str(",module="); clog_msg_str(module->module->name); clog_msg_str(", host="); clog_msg_str(host); clog_msg_str(", addr=<"); clog_msg_str(addr); clog_msg_str(">"); clog_msg_send(); #endif newq->rcptinfo_list[j].addresses.push_back(addr); newq->rcptinfo_list[j].addressesidx.push_back(i); } rfc822t_free(sendert); ctlfile_close(&ctlinfo); if (newq->nextsenddel <= current_time || /* ** If there are no more recipients, we want to call done() via ** start_message. HOWEVER, if DSN injection FAILED, we want to respect ** the rescheduled delivery attempt time. We can detect that if isnewmsg == 0 */ (newq->rcptinfo_list.size() == 0 && isnewmsg)) { newq->start_message(); return (0); } msgq *qp, *qprev; for (qprev=queuetail, qp=0; qprev; qp=qprev, qprev=qp->prev) if (qprev->nextsenddel < newq->nextsenddel) break; newq->next=qp; newq->prev=qprev; if (qprev) qprev->next=newq; else queuehead=newq; if (qp) qp->prev=newq; else queuetail=newq; ++queuewaiting; return (0); }
int msgq::tmpscan() { int found=0; time(¤t_time); DIR *tmpdir=opendir(TMPDIR); if (!tmpdir) clog_msg_errno(); struct dirent *de; std::string subdir; std::string ctlfile, datfile, newctlfile, newdatfile; struct stat stat_buf; std::string qdir, qname; while ((de=readdir(tmpdir)) != 0) { const char *p; for (p=de->d_name; *p; p++) if (!isdigit((int)(unsigned char)*p)) break; if (*p) continue; // Subdirs must be named all digits subdir=TMPDIR "/"; subdir += de->d_name; DIR *subde=opendir(subdir.c_str()); while ((de=readdir(subde)) != 0 && found < 100) { if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; ctlfile=subdir; ctlfile += '/'; ctlfile += de->d_name; int i=-1; if (stat(ctlfile.c_str(), &stat_buf)) continue; size_t j=ctlfile.size(); while (j) { if (ctlfile[--j] == '/') break; if (ctlfile[j] == '.') { i=j; break; } } ino_t inum=stat_buf.st_ino; // Cleanup timeout. Should always be sufficiently longer than // the submit timeout set in submit.C via alarm_timeout. if (stat_buf.st_mtime < current_time - 48 * 60 * 60) { if (de->d_name[0] == 'D') { datfile=subdir + "/C" + (de->d_name+1); if (stat(datfile.c_str(), &stat_buf) == 0) continue; // Wait until the C file is // purged // Be carefull with Cnnnn.x files, because // Cnnnn.1 is used to hold submission of all // of them. A race condition can leave // Cnnnn.1 in a submittable state, so if it // is removed, other copies of this message // can become submittable, during a very small // window. } else if (de->d_name[0] == 'C' && i >= 0) { // This race condition is handled simply // by not removing Cxxxxx.n if Cxxxxx.n+1 // exists. char nbuf[NUMBUFSIZE]; datfile=ctlfile.substr(0, i); size_t n=atoi( ctlfile.c_str()+i+1); ++n; datfile += '.'; datfile += libmail_str_size_t(n, nbuf); if (stat(datfile.c_str(), &stat_buf) == 0) continue; // Wait until the C.1 file is // purged unlink(ctlfile.c_str()); ctlfile=subdir + "/D" + (de->d_name+1); /* FALLTHRU */ } unlink(ctlfile.c_str()); continue; } if (de->d_name[0] != 'C') continue; if (i >= 0) { datfile=ctlfile.substr(0, i); datfile += ".1"; if (ctlfile == datfile || stat(datfile.c_str(), &stat_buf) == 0) continue; } datfile=subdir + "/D" + (de->d_name+1); newdatfile=qmsgsdatname(inum); newctlfile=qmsgsctlname(inum); struct ctlfile ctf; if ((access(datfile.c_str(), 0) == 0 && access(newdatfile.c_str(), 0) == 0) || access(newctlfile.c_str(), 0) == 0 || ctlfile_openfn(ctlfile.c_str(), &ctf, 0, 0)) { clog_msg_start_err(); clog_msg_str("QUEUE FILE CORRUPTION: inode "); clog_msg_uint(inum); clog_msg_send(); utime(ctlfile.c_str(), 0); // Keep it around continue; } time_t nextattempt=current_time+delaytime; if ((i=ctlfile_searchfirst(&ctf, COMCTLFILE_SUBMITDELAY)) >= 0) nextattempt=current_time+ atoi(ctf.lines[i]+1); qname=qmsgqname(inum, nextattempt); ctlfile_nextattempt(&ctf, nextattempt); if (link(ctlfile.c_str(), qname.c_str())) { mkdir(qmsgqdir(current_time),0755); if (link(ctlfile.c_str(), qname.c_str()) && errno != EEXIST) clog_msg_errno(); } if (rename(datfile.c_str(), newdatfile.c_str())) { mkdir(qmsgsdir(inum), 0755); // We may need to create this dir rename(datfile.c_str(), newdatfile.c_str()); } if (rename(ctlfile.c_str(), newctlfile.c_str())) clog_msg_errno(); for (i=qname.size(); i; ) { if (qname[--i] == '/') break; } qdir=qname.substr(0, i); qname=qname.substr(i+1); ++found; ctlfile_close(&ctf); queuescan3(qdir, qname, de->d_name); } closedir(subde); if (stat(subdir.c_str(), &stat_buf) == 0 && stat_buf.st_mtime < current_time - 2 * 60 * 60) rmdir(subdir.c_str()); // Just give it a try } closedir(tmpdir); return (found); }