⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdelivermail.c

📁 相当优秀的 UNIX 进程管理工具
💻 C
📖 第 1 页 / 共 3 页
字号:
 */int deliver_mail(char *address, char *quota){ time_t tm; off_t file_count; long unsigned pid; long unsigned inject_pid = 0; int child; int write_fd; FILE *fs; char tmp_file[256];    /* This is a comment, ignore it */    if ( *address == '#' ) return(0);    /* check if the email is looping to this user */    if ( is_looping( address ) == 1 ) {        printf("message is looping %s\n", address );        return(-3);    }    #ifdef MAKE_SEEKABLE    /* at this point we know the message size - if its 0 drop out silently */    if (message_size==0)        return(0);#endif    /* This is an command */    if ( *address == '|' ) {         /* run the command */         run_command(address);        return(0);      }    /* Starts with '.' or '/', then it's an mbox or maildir delivery */    else if ((*address == '.') || (*address == '/')) {        /* check for mbox delivery and exit accordingly */        if (address[strlen(address)-1] != '/') {            printf ("can't handle mbox delivery for %s", address);            vexit(111);        }        /* if the user has a quota set */        if ( strncmp(quota, "NOQUOTA", 2) != 0 ) {            /* If the user is over their quota, return it back             * to the sender.             */            if (user_over_maildirquota(address,format_maildirquota(quota))==1) {                /* check for over quota message in domain */                sprintf(tmp_file, "%s/.over-quota.msg",TheDomainDir);                if ( (fs=fopen(tmp_file, "r")) == NULL ) {                    /* if no domain over quota then check in vpopmail dir */                    sprintf(tmp_file, "%s/domains/.over-quota.msg",VPOPMAILDIR);                    fs=fopen(tmp_file, "r");                }                if ( fs == NULL ) {                    printf("user is over quota\n");                } else {                    while( fgets( tmp_file, 256, fs ) != NULL ) {                        fputs(tmp_file, stdout);                    }                    fclose(fs);                }                deliver_quota_warning(address, format_maildirquota(quota));                return(-1);            }            if (QUOTA_WARN_PERCENT >= 0 &&                vmaildir_readquota(address, format_maildirquota(quota))                    >= QUOTA_WARN_PERCENT) {                deliver_quota_warning(address, format_maildirquota(quota));            }        }#ifdef DOMAIN_QUOTAS	/* bk: check domain quota */        if (domain_over_maildirquota(address)==1)        {            /* check for over quota message in domain */            sprintf(tmp_file, "%s/.over-quota.msg",TheDomainDir);            if ( (fs=fopen(tmp_file, "r")) == NULL ) {                /* if no domain over quota then check in vpopmail dir */                sprintf(tmp_file, "%s/domains/.over-quota.msg",VPOPMAILDIR);                fs=fopen(tmp_file, "r");            }            if ( fs == NULL ) {                printf("domain is over quota\n");            } else {                while( fgets( tmp_file, 256, fs ) != NULL ) {                    fputs(tmp_file, stdout);                }                fclose(fs);            }            deliver_quota_warning(address, format_maildirquota(quota));            return(-1);        }#endif        /* Format the email file name */        gethostname(hostname,sizeof(hostname));        pid=getpid();        time (&tm);        snprintf(local_file, 156, "%stmp/%lu.%lu.%s,S=%lu",            address,(long unsigned)tm,(long unsigned)pid,            hostname, (long unsigned)message_size);        snprintf(local_file_new, 156, "%snew/%lu.%lu.%s,S=%lu",            address,(long unsigned)tm,(long unsigned)pid,hostname,         (long unsigned)message_size);        /* open the new email file */        if ((write_fd=open(local_file,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR))== -1) {            printf("can not open new email file errno=%d file=%s\n",                 errno, local_file);            return(-2);        }         /* Set the Delivered-To: header */        if ( strcmp( address, bounce) == 0 ) {            snprintf(DeliveredTo, sizeof(DeliveredTo),                 "%sDelivered-To: %s@%s\n", getenv("RPLINE"),                  TheUser, TheDomain);        } else {                    snprintf(DeliveredTo, sizeof(DeliveredTo),                 "%sDelivered-To: %s\n", getenv("RPLINE"),                 maildir_to_email(address));        }    /* must be an email address */    } else {      char *dtline;      char *atpos;      int dtlen;      inject_pid = qmail_inject_open(address);      write_fd = fdm;      /* use the DTLINE variable, but skip past the dash in        * domain-user@domain        */      if ( (dtline = getenv("DTLINE")) != NULL ) {        dtlen = strlen(dtline);        /* make sure dtline is at least as long as "Delivered-To: " */        if (dtlen < 15) {          dtline = NULL;        } else {          dtline += 14;  /* skip "Delivered-To: " */          dtlen -= 14;          atpos = strchr (dtline, '@');          /* ex: dtline = "x-y-z.com-fred@x-y-z.com\n"           * dtlen = 25, atpos = dtline+14           * add 25 - 14 - 1 = 10 bytes to dtline,           * now points to "fred@x-y-z.com\n".           */          if (atpos != NULL) {            dtline += (dtlen - (atpos - dtline) - 1);          }        }      }      if (dtline == NULL) {        if (*address=='&') ++address;  /* will this case ever happen? */        snprintf(DeliveredTo, sizeof(DeliveredTo),           "%sDelivered-To: %s\n", getenv("RPLINE"), address);      } else {        snprintf(DeliveredTo, sizeof(DeliveredTo),           "%sDelivered-To: %s", getenv("RPLINE"), dtline);      }    }#ifdef MAKE_SEEKABLE    if (!Seekable(0))        MakeSeekable(stdin);#endif    if ( lseek(0, 0L, SEEK_SET) < 0 ) {        printf("lseek errno=%d\n", errno);        return(-2);    }    /* write the Return-Path: and Delivered-To: headers */    if (write(write_fd,DeliveredTo,strlen(DeliveredTo))!=               strlen(DeliveredTo)) {        close(write_fd);        /* Check if the user is over quota */        if ( errno == EDQUOT ) {            return(-1);        } else {            printf("failed to write delivered to line errno=%d\n",errno);           return(-2);        }    }    /* read it in chunks and write it to the new file */    while((file_count=read(0,msgbuf,MSG_BUF_SIZE))>0) {        if ( write(write_fd,msgbuf,file_count) == -1 ) {            close(write_fd);            /* if the write fails and we are writing to a Maildir             * then unlink the file             */            if ( unlink(local_file) != 0 ) {                printf("unlink failed %s errno = %d\n", local_file, errno);                return(-2);            }            /* Check if the user is over quota */            if ( errno == EDQUOT ) {                return(-1);            } else {                printf("write failed errno = %d\n", errno);                return(-2);            }        }    }    if ( inject_pid != 0 ) {        close(write_fd);        waitpid(inject_pid,&child,0);        return(wait_exitcode(child));    }    /* if we are writing to a Maildir, move it     * into the new directory     */    /* sync the data to disk and close the file */    errno = 0;    if ( #ifdef FILE_SYNC#ifdef HAVE_FDATASYNC        fdatasync(write_fd) == 0 &&#else        fsync(write_fd) == 0 &&#endif#endif        close(write_fd) == 0 ) {        /* if this succeeds link the file to the new directory */        if ( link( local_file, local_file_new ) == 0 ) {            if ( unlink(local_file) != 0 ) {                printf("unlink failed %s errno = %d\n", local_file, errno);            }        } else {            /* coda fs has problems with link, check for that error */            if ( errno==EXDEV ) {                /* try to rename the file instead */                if (rename(local_file, local_file_new)!=0) {                    /* even rename failed, time to give up */                    printf("rename failed %s %s errno = %d\n",                         local_file, local_file_new, errno);                    /* shouldn't we unlink the file here? */                    return(-2);                /* rename worked, so we are okay now */                } else {                    errno = 0;                }            /* link failed and we are not on coda */            } else {                printf("link REALLY failed %s %s errno = %d\n",                     local_file, local_file_new, errno);                unlink(local_file);                return(-2);            }        }    }    /* return success */    return(0);}/* Check if the vpopmail user has a .qmail file in thier directory * and foward to each email address, Maildir or program  *  that is found there in that file * * Return: 1 if we found and delivered email *       : 0 if not found *       : -1 if no user .qmail file  * */int check_forward_deliver(char *dir){ static char qmail_line[500]; char tmpbuf[500]; FILE *fs; int i; int return_value = 0; int deliver_err;       chdir(dir);    /* format the file name */    if ( (fs = fopen(".qmail","r")) == NULL ) {        /* no file, so just return */        return(-1);    }    /* format a simple loop checker name */    snprintf(tmpbuf, 500, "%s@%s", TheUser, TheDomain);    /* read the file, line by line */    while ( fgets(qmail_line, 500, fs ) != NULL ) {        if (*qmail_line == '#') continue;        /* remove the trailing new line */        for(i=0;qmail_line[i]!=0;++i) {            if (qmail_line[i] == '\n') qmail_line[i] = 0;        }        /* simple loop check, if they are sending it to themselves         * then skip this line         */        if ( strcmp( qmail_line, tmpbuf) == 0 ) continue;        /* check for &user@example.com as well */        if ((*qmail_line == '&') && (strcmp (qmail_line + 1, tmpbuf) == 0))            continue;        deliver_err = deliver_mail(qmail_line, "NOQUOTA");        if (deliver_err == -2) {            printf("system error\n");            vexit(111);        } else if (deliver_err == -3) {            printf("mail is looping\n");            vexit(111);        }        return_value = 1;    }    /* close the file */    fclose(fs);    /* return if we found one or not */    return(return_value);}void sig_catch(sig,f)int sig;void (*f)();{#ifdef HAVE_SIGACTION  struct sigaction sa;  sa.sa_handler = f;  sa.sa_flags = 0;  sigemptyset(&sa.sa_mask);  sigaction(sig,&sa,(struct sigaction *) 0);#else  signal(sig,f); /* won't work under System V, even nowadays---dorks */#endif}/* open a pipe to a command  * return the pid or -1 if error */void run_command(char *prog){ int child; char *(args[4]); int wstat; while (*prog==' ') ++prog; while (*prog=='|') ++prog;#ifdef MAKE_SEEKABLE    if (!Seekable(0))        MakeSeekable(stdin);#endif    if ( lseek(0, 0L, SEEK_SET) < 0 ) {        printf("lseek errno=%d\n", errno);        return;    } switch(child = fork())  {   case -1:     printf("unable to fork\n");      exit(0);   case 0:     args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;     sig_catch(SIGPIPE,SIG_DFL);     execv(*args,args);     printf("Unable to run /bin/sh: ");     exit(-1);  }  wait(&wstat);  waitpid(wstat,&child,0);  switch(wait_exitcode(wstat))   {    case 64: case 65: case 70: case 76: case 77: case 78: case 100: case 112: _exit(100);    case 99: _exit(99);    case 0: break;    default: _exit(111);   }}/* Check for a looping message * This is done by checking for a matching line * in the email headers for Delivered-To: which * we put in each email *  * Return 1 if looping * Return 0 if not looping * Return -1 on error  */int is_looping( char *address ) { int i; int found; char *dtline;    /* if we don't know the message size then get it */    if ( message_size == 0 ) {        /* read the message to get the size */        message_size = get_message_size();    }    if (*address=='&') ++address;    /* check the DTLINE */    dtline = getenv("DTLINE");    if ( dtline != NULL && is_loop_match(dtline, address) == 1 ) {      return(1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -