Attached is my updated patch for spamc which will take two environment 
variables (default is EXT and HOST) and create a username from them.  It 
should be compatible with the existing spamc/d, as if the -u type doesn't 
match any of the special tags, it interprets the argument as the username.

Changes from the original patch for spamc from SA1.5:
- environment variables are configurable
- arbitrary user may be specified
- documentation is includedj

I'm not a wiz at the pod format (ferinstance I could not get a space between 
the text for the -u parameter and the start of the -U parameter) but the 
documentation isn't _ugly_.  :-)

Hope someone finds this useful.  Should be faster than wrapping it in a Perl 
script anyway.

Regards,
Andrew
diff -ur Mail-SpamAssassin-2.0/spamd/spamc.c new-Mail-SpamAssassin-2.0/spamd/spamc.c
--- Mail-SpamAssassin-2.0/spamd/spamc.c	Tue Jan 15 20:22:46 2002
+++ new-Mail-SpamAssassin-2.0/spamd/spamc.c	Wed Jan 23 21:01:38 2002
@@ -59,6 +59,16 @@
 
 const int ESC_PASSTHROUGHRAW = EX__MAX+666;
 
+/*
+ * vpopmail-specific user definitions by
+ * Andrew Kohlsmith <[EMAIL PROTECTED]>
+ */
+#define USER_GETUID    0
+#define USER_NOSUFFIX  1
+#define USER_NODOMAIN  2
+#define USER_RECIP     4
+#define USER_SPECIFIED 8
+
 /* set EXPANSION_ALLOWANCE to something more than might be
    added to a message in X-headers and the report template */
 const int EXPANSION_ALLOWANCE = 16384;
@@ -72,14 +82,21 @@
 
 void print_usage(void)
 {
-  printf("Usage: spamc [-d host] [-p port] [-c] [-f] [-h]\n");
+  printf("Usage: spamc [-d host] [-p port] [-u usertype | username] [-f] [-h] [-U envuser] [-H envhost]\n");
   printf("-c: check only - print score/threshold and exit code set to 0 if message is not spam, 1 if spam\n");
   printf("-d host: specify host to connect to  [default: localhost]\n");
   printf("-f: fallback safely - in case of comms error, dump original message unchanges instead of setting exitcode\n");
   printf("-h: print this help message\n");
   printf("-p port: specify port for connection [default: 783]\n");
   printf("-s size: specify max message size, any bigger and it will be returned w/out processing [default: 250k]\n");
-  printf("-u username: specify the username for spamd to process this message under\n");
+  printf("             from_getuid = from process owner, default\n");
+  printf("             long_recip = full mail recipient (user-suffix@host)\n");
+  printf("             short_recip = user@host (strip any -suffix suffixes)\n");
+  printf("             long_user = just user (discard host, keep suffixes)\n");
+  printf("             short_user = short user (discard host and suffixes)\n");
+  printf("             anything else is interpreted as the actual username\n");
+  printf("-U envuser: environment variable containing recipient username [default: EXT]\n");
+  printf("-H envhost: environment variable containing recipient hostname [default: HOST]\n");
 }
 
 
@@ -493,11 +510,11 @@
   return exstatus;	/* return the last failure code */
 }
 
-void read_args(int argc, char **argv, char **hostname, int *port, int *max_size, char **username)
+void read_args(int argc, char **argv, char **hostname, int *port, int *max_size, char **username, int *usertype, char **envuser, char **envhost)
 {
   int opt;
 
-  while(-1 != (opt = getopt(argc,argv,"cd:fhp:s:u:")))
+  while(-1 != (opt = getopt(argc,argv,"cd:fhp:s:u:U:H:")))
   {
     switch(opt)
     {
@@ -523,14 +540,39 @@
       }
     case 'u':
       {
-	*username = optarg;
-	break;
+      *username = (int)NULL;
+
+      if(strcmp(optarg, "long_recip") == 0)
+        *usertype = USER_RECIP;
+      else if(strcmp(optarg, "short_recip") == 0)
+        *usertype = USER_RECIP | USER_NOSUFFIX;
+      else if(strcmp(optarg, "long_user") == 0)
+        *usertype = USER_RECIP | USER_NODOMAIN;
+      else if(strcmp(optarg, "short_user") == 0)
+        *usertype = USER_RECIP | USER_NODOMAIN | USER_NOSUFFIX;
+      else if(strcmp(optarg, "from_getuid") == 0)
+        *usertype = USER_GETUID;
+      else			/* nothing matches, must be the actual username */
+        {
+        *username = optarg;
+        *usertype = USER_SPECIFIED;
+        }
+        
+      break;
       }
     case 's':
       {
 	*max_size = atoi(optarg);
 	break;
       }
+    case 'U': {
+        *envuser = optarg;
+        break;
+    }
+    case 'H': {
+        *envhost = optarg;
+        break;
+    }
     case '?': {
       syslog (LOG_ERR, "invalid usage");
       /* NOTE: falls through to usage case below... */
@@ -548,24 +590,62 @@
 {
   int port = 783;
   int max_size = 250*1024;
+  int usertype = USER_GETUID;
   char *hostname = "127.0.0.1";
-  char *username = NULL;
+  char *username, *userhost, *p;
+  char *envuser = "EXT";
+  char *envhost = "HOST";
+  char recip[250];
   struct passwd *curr_user;
 
   openlog ("spamc", LOG_CONS|LOG_PID, LOG_MAIL);
   signal (SIGPIPE, SIG_IGN);
 
-  read_args(argc,argv,&hostname,&port,&max_size,&username);
+  read_args(argc,argv,&hostname,&port,&max_size,&username,&usertype,&envuser,&envhost);
 
-  if(NULL == username)
-  {
+  if(usertype == USER_GETUID)
+    {
     curr_user = getpwuid(getuid());
     if (curr_user == NULL) {
       perror ("getpwuid failed");
       return EX_OSERR;
-    }
+      }
+
     username = curr_user->pw_name;
-  }
+    }
+  else if (usertype != USER_SPECIFIED)
+    {
+
+/*
+ * 23 Jan 2001 ABK
+ * Instead of using the username from pw_name,
+ * create it from the user the email is being delivered to.
+ *
+ * vpopmail uses EXT and HOST for the user and domain that the
+ * message will be going to.
+ */
+
+    username = getenv(envuser);
+    userhost = getenv(envhost);
+    if(username != NULL)
+      {
+      strncpy(recip, username, 124);
+      if(usertype & USER_NOSUFFIX)
+        {
+        p = strchr(recip, '-');
+        if(p)
+          *p = 0x00;
+        }
+      if(! (usertype & USER_NODOMAIN))
+        {
+        strcat(recip, "@");
+        strncat(recip, userhost, 124);
+        }
+      username = recip;
+      }
+    }
+
+  fprintf(stderr, "user type is %i, user name is %s\n", usertype, username);
 
   return process_message(hostname,port,username,max_size);
 }
Only in new-Mail-SpamAssassin-2.0/spamd: spamc.c.orig
diff -ur Mail-SpamAssassin-2.0/spamd/spamc.pod new-Mail-SpamAssassin-2.0/spamd/spamc.pod
--- Mail-SpamAssassin-2.0/spamd/spamc.pod	Tue Jan 15 20:22:46 2002
+++ new-Mail-SpamAssassin-2.0/spamd/spamc.pod	Wed Jan 23 21:17:37 2002
@@ -7,7 +7,7 @@
 
 =over
 
-=item spamc [-c] [-d host] [-f] [-h] [-p port] [-s max_size] [-u username]
+=item spamc [-c] [-d host] [-f] [-h] [-p port] [-s max_size] [-u usertype | username]
 
 =back
 
@@ -48,9 +48,53 @@
 
 Set the maximum message size which will be sent to spamd -- any bigger than this threshold and the message will be returned unprocessed.  Note that the default size is 250k, so if spamc gets handed a message bigger than this, it won't be passed to spamd.  The size is specified in bytes, and if you send it a negative number, things are quite likely to break very hard.
 
-=item B<-u> I<username>
+=item B<-u> I<usertype | username>
 
-This argument has been semi-obsoleted.  To have spamd use per-user-config files, run spamc as the user whose config files spamd should load.  If you're running spamc as some other user though (eg. root, mail, nobody, cyrus, etc.) then you can still use this flag.
+Allows spamc to use per-user configuration files.  The default is to use the user that is running spamc, but the following options alter this:
+
+=over
+
+=item B<from_getuid> 	get the username from process owner (this is the default mode of operation)
+
+=item B<long_recip>	full mail recipient (user-suffix@host)
+
+=item B<short_recip>	user@host (strip any -suffix suffixes)
+
+=item B<long_user>		just user (discard host, keep suffixes)
+
+=item B<short_user>	short user (discard host and suffixes)
+
+=back
+
+Anything else is interpreted as the actual username.
+
+By default, the environment variables EXT and HOST are used as the recipient's name and host, respectively.  Refer to the -U and -H options if you want to use different environment variables.
+Some examples (using the recipient [EMAIL PROTECTED]):
+
+=over
+
+=item B<-u from_getuid>		username is whatever spamc's process owner is (usually 'nobody' or 'root')
+
+=item B<-u long_recip>		username is '[EMAIL PROTECTED]'
+
+=item B<-u short_recip>		username is '[EMAIL PROTECTED]'
+
+=item B<-u log_user>		username is 'myuser-extension'
+
+=item B<-u short_user>		username is 'myuser'
+
+=item B<-u mickey.mouse>	username is 'mickey.mouse' 
+
+
+=back
+
+=item B<-U> I<envuser>
+
+Use the environment variable 'envuser' for the recipient's username.  The default is EXT.
+
+=item B<-H> I<envhost>
+
+Use the environment variable 'envhost' for the recipient's host.  The default is HOST.
 
 =back
 

Reply via email to