3 * main.c: for rcpt500 (X.500 email query responder)
5 * 16 June 1992 by Mark C Smith
6 * Copyright (c) 1992 The Regents of The University of Michigan
14 #include <ac/stdlib.h>
17 #include <ac/signal.h>
18 #include <ac/string.h>
19 #include <ac/syslog.h>
20 #include <ac/unistd.h>
22 #include "ldap_defaults.h"
28 int sizelimit = RCPT500_SIZELIMIT;
29 int rdncount = RCPT500_RDNCOUNT;
31 char *ldaphost = NULL;
32 char *searchbase = NULL;
34 char *filterfile = FILTERFILE;
35 char *templatefile = TEMPLATEFILE;
36 static char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
42 static int read_msg(FILE *fp, struct msginfo *msgp);
43 static char *read_hdr(FILE *fp, int off, char *buf, int MAXSIZEe, char **ln_p);
44 static int send_reply(struct msginfo *msgp, char *body);
45 static int find_command(char *text, char **argp);
48 * main is invoked by sendmail via the alias file
49 * the entire incoming message gets piped to our standard input
52 main( int argc, char **argv )
54 char *prog, *usage = "%s [-l] [-U] [-h ldaphost] [-p ldapport] [-b searchbase] [-a] [-z sizelimit] [-u dapuser] [-f filterfile] [-t templatefile] [-c rdncount]\n";
60 if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
61 prog = strdup( argv[ 0 ] );
63 prog = strdup( prog + 1 );
67 while (( c = getopt( argc, argv, "alh:b:s:z:f:t:p:c:" )) != EOF ) {
82 ldapport = atoi( optarg );
85 sizelimit = atoi( optarg );
94 templatefile = optarg;
97 rdncount = atoi( optarg );
103 if ( errflg || optind < argc ) {
104 fprintf( stderr, usage, prog );
105 exit( EXIT_FAILURE );
109 (void) SIGNAL( SIGPIPE, SIG_IGN );
114 * if syslogging requested, initialize
117 openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON );
119 openlog( prog, OPENLOG_OPTIONS );
123 if ( read_msg( stdin, &msg ) < 0 ) {
125 syslog( LOG_INFO, "unparseable message ignored" );
127 exit( 0 ); /* so as not to give sendmail an error */
131 syslog( LOG_INFO, "processing command \"%s %s\" from %s",
132 ( msg.msg_command < 0 ) ? "Unknown" :
133 rcpt_cmds[ msg.msg_command ].cmd_text,
134 ( msg.msg_arg == NULL ) ? "" : msg.msg_arg, msg.msg_replyto );
137 if ( msg.msg_command < 0 ) {
138 msg.msg_command = 0; /* unknown command == help command */
142 sprintf( reply, "Your request was interpreted as: %s %s\n\n",
143 rcpt_cmds[ msg.msg_command ].cmd_text, msg.msg_arg );
146 (*rcpt_cmds[ msg.msg_command ].cmd_handler)( &msg, reply );
148 if ( send_reply( &msg, reply ) < 0 ) {
150 syslog( LOG_INFO, "reply failed: %m" );
152 exit( 0 ); /* so as not to give sendmail an error */
156 syslog( LOG_INFO, "reply OK" );
164 read_msg( FILE *fp, struct msginfo *msgp )
166 char buf[ MAXSIZE ], *line;
169 msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL;
173 if ( line == NULL ) {
174 if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) {
177 buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
180 if ( *buf == '\0' ) { /* start of message body */
183 if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) {
184 if ( msgp->msg_replyto != NULL ) {
185 free( msgp->msg_replyto );
187 msgp->msg_replyto = read_hdr( fp, 9, buf, MAXSIZE, &line );
188 } else if ( strncasecmp( buf, "From:", 5 ) == 0 &&
189 msgp->msg_replyto == NULL ) {
190 msgp->msg_replyto = read_hdr( fp, 5, buf, MAXSIZE, &line );
191 } else if ( strncasecmp( buf, "Date:", 5 ) == 0 ) {
192 msgp->msg_date = read_hdr( fp, 5, buf, MAXSIZE, &line );
193 } else if ( strncasecmp( buf, "Message-ID:", 5 ) == 0 ) {
194 msgp->msg_messageid = read_hdr( fp, 11, buf, MAXSIZE, &line );
195 } else if ( strncasecmp( buf, "Subject:", 8 ) == 0 ) {
196 if (( msgp->msg_subject =
197 read_hdr( fp, 8, buf, MAXSIZE, &line )) != NULL ) {
198 command = find_command( msgp->msg_subject, &msgp->msg_arg );
201 line = NULL; /* discard current line */
205 while ( command < 0 && line != NULL ) {
207 * read the body of the message, looking for commands
209 if (( line = fgets( buf, MAXSIZE, fp )) != NULL ) {
210 buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
211 command = find_command( buf, &msgp->msg_arg );
215 if ( msgp->msg_replyto == NULL ) {
219 msgp->msg_command = command;
225 read_hdr( FILE *fp, int offset, char *buf, int MAXSIZEe, char **linep )
229 for ( hdr = buf + offset; isspace( (unsigned char) *hdr ); ++hdr ) {
232 if (( hdr = strdup( hdr )) == NULL ) {
234 syslog( LOG_ERR, "strdup: %m" );
236 exit( EXIT_FAILURE );
240 *linep = fgets( buf, MAXSIZE, fp );
241 buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
242 if ( *linep == NULL || !isspace( (unsigned char) **linep )) {
245 if (( hdr = realloc( hdr, strlen( hdr ) +
246 strlen( *linep ) + 3 )) == NULL) {
248 syslog( LOG_ERR, "realloc: %m" );
250 exit( EXIT_FAILURE );
253 strcat( hdr, *linep );
261 send_reply( struct msginfo *msgp, char *body )
267 if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) {
269 syslog( LOG_ERR, "popen pipemailcmd failed: %m" );
278 sprintf( buf, "From: %s\n", RCPT500_FROM );
279 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
282 if ( msgp->msg_subject != NULL ) {
283 sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject );
285 sprintf( buf, "Subject: query response\n" );
287 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
290 if ( rc == 1 && msgp->msg_date != NULL ) {
292 * add "In-reply-to:" header
294 if ( msgp->msg_messageid == NULL ) {
295 sprintf( buf, "In-reply-to: Your message of \"%s\"\n",
299 "In-reply-to: Your message of \"%s\"\n %s\n",
300 msgp->msg_date, msgp->msg_messageid );
302 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
306 sprintf( buf, "To: %s\n", msgp->msg_replyto );
307 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
311 * send the header/body separator (blank line)
314 rc = fwrite( "\n", 1, 1, cmdpipe );
321 rc = fwrite( body, strlen( body ), 1, cmdpipe );
324 if ( rc != 1 && dosyslog ) {
325 syslog( LOG_ERR, "write to binmail failed: %m" );
328 if ( pclose( cmdpipe ) < 0 ) {
330 syslog( LOG_ERR, "pclose binmail failed: %m" );
335 return( rc == 1 ? 0 : -1 );
340 find_command( char *text, char **argp )
344 static char argbuf[ MAXSIZE ];
347 for ( s = argbuf; *p != '\0'; ++p ) {
348 *s++ = TOLOWER( (unsigned char) *p );
352 for ( i = 0; rcpt_cmds[ i ].cmd_text != NULL; ++i ) {
353 if (( s = strstr( argbuf, rcpt_cmds[ i ].cmd_text )) != NULL
354 && isspace( (unsigned char) s[ strlen( rcpt_cmds[ i ].cmd_text ) ] )) {
355 strcpy( argbuf, text + (s - argbuf) + strlen( rcpt_cmds[ i ].cmd_text ));
357 while ( isspace( (unsigned char) **argp )) {