📄 vqmaillocal.c
字号:
*/ if ( (dtline = getenv("DTLINE")) != NULL ) { while (*dtline!=0 && *dtline!=':' ) ++dtline; while (*dtline!=0 && *dtline!='-' ) ++dtline; if ( *dtline != 0 ) ++dtline; for(tstr=dtline;*tstr!=0;++tstr) if (*tstr=='\n') *tstr=0; } else { if (*address=='&') ++address; dtline = address; } snprintf(DeliveredTo, AUTH_SIZE, "%sDelivered-To: %s\n", getenv("RPLINE"), dtline); } if ( lseek(0, 0L, SEEK_SET) < 0 ) { printf("lseek errno=%d\n", errno); return(errno); } /* 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(errno); } } /* 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(errno); } /* Check if the user is over quota */ if ( errno == EDQUOT ) { return(-1); } else { printf("write failed errno = %d\n", errno); return(errno); } } } if ( inject == 1 ) { close(write_fd); return(0); } /* 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); return(errno); /* rename worked, so we are okay now */ } else { errno = 0; } /* link failed and we are not on coda */ } else { printf("link failed %s %s errno = %d\n", local_file, local_file_new, errno); } } } /* 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; /* format the file name */ snprintf(tmpbuf, 500, "%s/.qmail", dir); if ( (fs = fopen(tmpbuf,"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 ) { /* 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; deliver_mail(qmail_line, "NOQUOTA"); 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; 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);}/* 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 && strstr(dtline, address) != NULL ) { return(1); } lseek(0,0L,SEEK_SET); while(fgets(loop_buf,sizeof(loop_buf),stdin)!=NULL){ /* if we find the line, return error (looping) */ if (strstr(loop_buf, "Delivered-To")!= 0 && strstr(loop_buf, address)!=0 ) { /* return the loop found */ return(1); /* check for the start of the body, we only need * to check the headers. */ } else { /* walk through the charaters in the body */ for(i=0,found=0;loop_buf[i]!=0&&found==0;++i){ switch(loop_buf[i]){ /* skip blank spaces and new lines */ case ' ': case '\n': case '\t': case '\r': break; /* found a non blank, so we are still * in the headers */ default: /* set the found non blank char flag */ found = 1; break; } } /* if the line only had blanks, then it is the * delimiting line between the headers and the * body. We don't need to check the body for * the duplicate Delivered-To: line. Hence, we * are done with our search and can return the * looping not found value */ if ( found == 0 ) { /* return not found looping message value */ return(0); } } } /* if we get here then the there is either no body * or the logic above failed and we scanned * the whole email, headers and body. */ return(0);}/* * Get the size of the email message * return the size */off_t get_message_size(){ ssize_t message_size; ssize_t bytes; if ( lseek(0, 0L,SEEK_SET) < 0 ) { printf("lseek error %d\n", errno); return(-1); } message_size = 0; while((bytes=read(0,msgbuf,MSG_BUF_SIZE))>0) { message_size += bytes; } return(message_size);}/* * Check if the user is over quota * * Do all quota recalculation needed * * Return 1 if user is over quota * Return 0 if user is not over quota */int user_over_quota(char *maildir, char *quota){ ssize_t per_user_limit; off_t cur_msg_bytes; int i; int ret_value = 0; off_t new_size; /* translate the quota to a number */ per_user_limit = atol(quota); for(i=0;quota[i]!=0;++i){ if ( quota[i] == 'k' || quota[i] == 'K' ) { per_user_limit = per_user_limit * 1000; break; } if ( quota[i] == 'm' || quota[i] == 'M' ) { per_user_limit = per_user_limit * 1000000; break; } } /* Get thier current total */ cur_msg_bytes = check_quota(maildir); /* Check if this email would bring them over quota */ if ( cur_msg_bytes + message_size > per_user_limit ) { /* recalculate thier quota since they might have * deleted email */ cur_msg_bytes = recalc_quota(maildir); if ( cur_msg_bytes + message_size > per_user_limit ) { ret_value = 1; } } /* If we are going to deliver it, then add in the size */ if ( ret_value == 0 ) { new_size = message_size + cur_msg_bytes; update_quota(new_size); } close(CurrentQuotaSizeFd); return(ret_value);}/* * check for locked account * deliver to .qmail file if any * deliver to user if no .qmail file */void checkuser() { if (vpw->pw_gid & BOUNCE_MAIL ) { printf("vdelivermail: account is locked email bounced %s@%s\n", TheUser, TheDomain); vexit(100); } /* If thier directory path is empty make them a new one */ if ( vpw->pw_dir == NULL || vpw->pw_dir[0]==0 ) { uid_t pw_uid; gid_t pw_gid; vget_assign(TheDomain,NULL,0,&pw_uid,&pw_gid); if ( make_user_dir(vpw->pw_name, TheDomain, pw_uid, pw_gid)==NULL){ printf("Auto creation of maildir failed. vpopmail (#5.9.8)\n"); vexit(100); } } /* check for a .qmail file in thier Maildir * If it exists, then deliver to the contents and exit */ if ( check_forward_deliver(vpw->pw_dir) == 1 ) { vexit(0); } snprintf(TheDir, AUTH_SIZE, "%s/Maildir/", vpw->pw_dir); if ( deliver_mail(TheDir, vpw->pw_shell) != 0 ) { vexit(100); }}/* * the vpopmail user does not exist. Follow the rest of * the directions in the .qmail-default file */void usernotfound() { int ret; /* If they want to delete email for non existant users * then just exit 0. Qmail will delete the email for us */ if ( strcmp(bounce, DELETE_ALL) == 0 ) { /* just exit 0 and qmail will delete the email from the system */ vexit(0); /* If they want to bounce the email back then * print a message and exit 100 */ } else if ( strcmp(bounce, BOUNCE_ALL) == 0 ) { printf("Sorry, no mailbox here by that name. vpopmail (#5.1.1)\n"); /* exit 100 causes the email to be bounced back */ vexit(100); } /* check if it is a path add the /Maildir/ for delivery */ if ( strstr( bounce, VPOPMAILDIR ) != 0 ) { strcat( bounce, "/Maildir/"); } ret = deliver_mail(bounce, "NOQUOTA" ); /* Send the email out, if we get a -1 then the user is over quota */ if ( ret == -1 ) { printf("user is over quota, mail bounced\n"); vexit(100); } else if ( ret == -2 ) { printf("system error\n"); vexit(100); } else if ( ret != 0 ) { printf("mail is looping\n"); vexit(100); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -