?? vpopbull.c
字號:
/* * $Id: vpopbull.c,v 1.6 2004/01/11 09:16:53 mbowe Exp $ * Copyright (C) 1999-2003 Inter7 Internet Technologies, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <time.h>#include <pwd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>#include "config.h"#include "vpopmail.h"#include "vauth.h"#define MAX_BUFF 256#define MSG_BUF_SIZE 32768#define TOKENS ":\r\n"static char EmailFile[MAX_BUFF];static char CurDir[MAX_BUFF];static char ExcludeFile[MAX_BUFF];static char Domain[MAX_BUFF];static char TmpBuf[MAX_BUFF];static char MsgBuf[MSG_BUF_SIZE];static int Verbose;static int DoNothing;#define COPY_IT 0#define HARD_LINK_IT 1#define SYMBOLIC_LINK_IT 2static int DeliveryMethod = COPY_IT;int InsertDate = 1;int EmailFileFlag = 0;int ExcludeFileFlag = 0;int process_domain(char *, FILE *, FILE *);int copy_email( FILE *, char *, char *, struct vqpasswd *);int in_exclude_list( FILE *, char *, char *);void get_options(int argc,char **argv);void usage();int main(int argc, char *argv[]){ FILE *fsi = NULL; FILE *fsx = NULL; FILE *fsassign; char *domain; char *alias; char *domain_dir = NULL; char *tmpstr; static struct stat statbuf; memset(TmpBuf,0,sizeof(TmpBuf)); memset(MsgBuf,0,sizeof(MsgBuf)); Verbose = 0; DoNothing = 0; if ( argc == 1 ) { usage(); vexit(-1); } get_options(argc,argv); getcwd(CurDir,sizeof(CurDir)); if ( EmailFileFlag == 1 ) { if ( (fsi = fopen(EmailFile, "r")) == NULL ) { fprintf(stderr, "Could not open file %s\n", EmailFile); vexit(-1); } else { /* make sure the file size is not 0 */ stat(EmailFile, &statbuf); if(statbuf.st_size == 0) { fprintf(stderr, "Error: %s is empty\n", EmailFile); vexit(-1); } /* check for existing date header */ while (fgets (TmpBuf, sizeof(TmpBuf), fsi) != NULL) { /* check for end of headers (blank line) */ if (*TmpBuf == '\n') break; if (strncasecmp ("Date: ", TmpBuf, 6) == 0) { InsertDate = 0; break; } } rewind(fsi); } } else if (! DoNothing) { /* require -f [email_file] */ fprintf(stderr, "Error: email_file not specified\n"); usage(); vexit(-1); } if ( ExcludeFileFlag == 1 ) { if ( (fsx = fopen(ExcludeFile, "r")) == NULL ) { fprintf(stderr, "Could not open file %s\n", ExcludeFile); vexit(-1); } } if (( EmailFile[0] != 0 || DoNothing == 1) && Domain[0] != 0 ) { /* Process list of domains */ domain = strtok(Domain, " "); while (domain != NULL ) { if((vget_assign(domain, domain_dir, sizeof(domain_dir), NULL, NULL)) != NULL) { process_domain(domain, fsi, fsx ); } else { fprintf(stderr, "Error: domain %s does not exist\n", domain); } domain = strtok(NULL, " "); } vexit(0); } else if ( (EmailFile[0] != 0 || DoNothing == 1) && Domain[0] == 0 ) { /* Process ALL domains */ snprintf(TmpBuf, sizeof(TmpBuf), "%s/users/assign", QMAILDIR); if ( (fsassign = fopen(TmpBuf, "r")) == NULL ) { perror("can not open assign file"); vexit(0); } while ( fgets(TmpBuf, sizeof(TmpBuf), fsassign) != NULL ) { if ( (alias=strtok(TmpBuf, TOKENS)) == NULL ) continue; if ( (domain=strtok(NULL, TOKENS)) == NULL ) continue; if ( (tmpstr=strtok(NULL, TOKENS)) == NULL ) continue; if ( (tmpstr=strtok(NULL, TOKENS)) == NULL ) continue; if ( (domain_dir=strtok(NULL, TOKENS)) == NULL ) continue; alias++; /* point past leading + */ alias[strlen(alias)-1] = '\0'; /* remove trailing - */ if (strcmp (alias, domain) != 0) { if (Verbose) { fprintf (stderr, "skipping %s (alias of %s)\n", alias, domain); } } else { chdir(domain_dir); process_domain(domain, fsi, fsx ); } } fclose(fsassign); } return(vexit(0));}int process_domain(domain, fsi, fsx ) char *domain; FILE *fsi; FILE *fsx;{ char filename[MAX_BUFF]; char hostname[MAX_BUFF]; static struct vqpasswd *pwent; time_t tm; int pid; int first = 1; gethostname(hostname,sizeof(hostname)); pid=getpid(); time (&tm); snprintf(filename, sizeof(filename), "%lu.%lu.%s",(long unsigned)tm, (long unsigned)pid,hostname); first = 1; while( (pwent = vauth_getall(domain, first, 1)) != NULL ) { first = 0; if ( !in_exclude_list( fsx, domain, pwent->pw_name) ) { if (DoNothing) { printf("%s@%s\n", pwent->pw_name, domain); } else { if(copy_email( fsi, filename, domain, pwent) != 0) { fprintf(stderr, "%s@%s: ERROR COPYING TO %s\n", pwent->pw_name, domain, pwent->pw_dir); } else if (Verbose) { printf("%s@%s\n", pwent->pw_name, domain); } } } } return(0);}int copy_email( fs_file, filename, domain, pwent) FILE *fs_file; char *filename; char *domain; struct vqpasswd *pwent;{ static char tmpbuf[MAX_BUFF]; static char tmpbuf1[MAX_BUFF]; FILE *fs; int count; struct stat mystatbuf; uid_t uid; gid_t gid; /* At this point, we know that the user exists in the auth backend. * Now we need to run some other checks before we can copy the * bulletin into their maildir... */ /* test to see if the user has been allocated a userdir yet. * Some of the auth backends (eg MySQL) allow users to be inserted * into authsystem while leaving their dir blank. The idea here is * that this information will get allocated/updated the first time * the user does an AUTH or receives a msg. */ if ( pwent->pw_dir == NULL || pwent->pw_dir[0]==0 ) { /* A dir hasnt been allocated to this user yet. * Try and allocate one now */ /* retrieve the domain's uid/gid * (required for the call to make_user_dir() */ if (vget_assign(domain, NULL, 0, &uid, &gid) == NULL) { fprintf(stderr, "Failed to vget_assign() for %s\n", domain); return (-1); } if ( make_user_dir(pwent->pw_name, domain, uid, gid) == NULL) { fprintf(stderr, "Auto creation of maildir failed for %s@%s\n", pwent->pw_name, domain); return(-1); } /* Re-read pwent, because we need to lookup the newly created * pw_dir entry */ if ((pwent=vauth_getpw(pwent->pw_name, domain)) == NULL ) { fprintf(stderr, "Failed to vauth_getpw() for %s@%s\n", pwent->pw_name, domain); return(-1); } } /* At this point, a dir must have been allocated to the user * in the auth backend. So the next thing to do is test to see * if the dir exists on the filesystem or not. If the dir doesnt * exist, then we will try and create it */ if ( stat(pwent->pw_dir, &mystatbuf ) == -1 ) { if ( vmake_maildir(domain, pwent->pw_dir )!= VA_SUCCESS ) { fprintf(stderr, "Auto creation of maildir failed for %s@%s\n", pwent->pw_name, domain); return(-1); } } snprintf(tmpbuf, sizeof(tmpbuf), "%s/Maildir/new/%s", pwent->pw_dir, filename ); if ( DeliveryMethod == COPY_IT ) { rewind(fs_file); if ( (fs = fopen(tmpbuf, "w+")) == NULL ) { return(-1); } fprintf(fs, "To: %s@%s\n", pwent->pw_name, domain); if (InsertDate) fprintf(fs, "%s", date_header()); while((count=fread(MsgBuf,sizeof(char),MSG_BUF_SIZE,fs_file)) != 0 ) { fwrite( MsgBuf, sizeof(char), count, fs ); } fclose(fs); } else if ( DeliveryMethod == HARD_LINK_IT ) { if (*EmailFile == '/') snprintf(tmpbuf1, sizeof(tmpbuf1), "%s", EmailFile); else snprintf(tmpbuf1, sizeof(tmpbuf1), "%s/%s", CurDir, EmailFile); if ( link( tmpbuf1, tmpbuf) < 0 ) { perror("link"); } } else if ( DeliveryMethod == SYMBOLIC_LINK_IT ) { if (*EmailFile == '/') snprintf(tmpbuf1, sizeof(tmpbuf1), "%s", EmailFile); else snprintf(tmpbuf1, sizeof(tmpbuf1), "%s/%s", CurDir, EmailFile); if ( symlink( tmpbuf1, tmpbuf) < 0 ) { perror("symlink"); } } else { fprintf(stderr, "no delivery method set\n"); return -1; } /* fix permissions */ chown(tmpbuf, VPOPMAILUID, VPOPMAILGID); chmod(tmpbuf, 0600); return(0);}int in_exclude_list( FILE *fsx, char *domain, char *user ){ static char tmpbuf[MAX_BUFF]; static char emailaddr[MAX_BUFF]; int i; if ( fsx == NULL ) { return(0); } rewind(fsx); snprintf(emailaddr, sizeof(emailaddr), "%s@%s", user, domain); while (fgets(tmpbuf, sizeof(tmpbuf), fsx) != NULL) { for(i=0;tmpbuf[i]!=0;++i) if (tmpbuf[i]=='\n') tmpbuf[i]=0; if ( strcmp( tmpbuf, emailaddr ) == 0 ) { return(1); } } return(0);}void get_options(int argc, char **argv){ int n = 0; int c; int errflag; extern char *optarg; extern int optind; memset(Domain, 0, sizeof(Domain)); memset(EmailFile, 0, sizeof(EmailFile)); memset(ExcludeFile, 0, sizeof(ExcludeFile)); errflag = 0; EmailFileFlag = 0; ExcludeFileFlag = 0; while( !errflag && (c=getopt(argc,argv,"Vvcshnf:e:")) != -1 ) { switch(c) { case 'v': printf("version: %s\n", VERSION); break; case 'V': Verbose = 1; break; case 's': DeliveryMethod = SYMBOLIC_LINK_IT; break; case 'c': DeliveryMethod = COPY_IT; break; case 'f': EmailFileFlag = 1; snprintf(EmailFile, sizeof(EmailFile), "%s", optarg); break; case 'e': ExcludeFileFlag = 1; snprintf(ExcludeFile, sizeof(ExcludeFile), "%s", optarg); break; case 'h': DeliveryMethod = HARD_LINK_IT; break; case 'n': DoNothing = 1; break; default: errflag = 1; break; } } if ( errflag > 0 ) { usage(); vexit(-1); } n = 0; while ( optind < argc ) { if((n=1)) strncat(Domain, " ", sizeof(Domain)-strlen(Domain)-1); strncat(Domain, argv[optind], sizeof(Domain)-strlen(Domain)-1); n = 1; ++optind; }}void usage(){ printf("usage: vpopbull [options] -f [email_file] [virtual_domain] [...]\n"); printf(" -v (print version number)\n"); printf(" -V (verbose)\n"); printf(" -f email_file (file with message contents)\n"); printf(" -e exclude_email_addr_file (list of addresses to exclude)\n"); printf(" -n (don't mail. Use with -V to list accounts)\n"); printf(" -c (default, copy file)\n"); printf(" -h (use hard links)\n"); printf(" -s (use symbolic links)\n"); }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -