2 * main.c: for rcpt500 (X.500 email query responder)
4 * 16 June 1992 by Mark C Smith
5 * Copyright (c) 1992 The Regents of The University of Michigan
15 #include <ac/string.h>
16 #include <ac/syslog.h>
18 #include "ldapconfig.h"
22 #ifdef LDAP_CONNECTIONLESS
24 #endif /* LDAP_CONNECTIONLESS */
27 int sizelimit = RCPT500_SIZELIMIT;
28 int rdncount = RCPT500_RDNCOUNT;
30 char *ldaphost = LDAPHOST;
31 char *searchbase = RCPT500_BASE;
32 char *dapuser = RCPT500_BINDDN;
33 char *filterfile = FILTERFILE;
34 char *templatefile = TEMPLATEFILE;
35 char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
47 * main is invoked by sendmail via the alias file
48 * the entire incoming message gets piped to our standard input
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";
64 if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
65 prog = strdup( argv[ 0 ] );
67 prog = strdup( prog + 1 );
71 while (( c = getopt( argc, argv, "alUh:b:s:z:f:t:p:c:" )) != EOF ) {
80 #ifdef LDAP_CONNECTIONLESS
82 #else /* LDAP_CONNECTIONLESS */
84 "Compile with -DLDAP_CONNECTIONLESS for -U support\n" );
85 #endif /* LDAP_CONNECTIONLESS */
94 ldapport = atoi( optarg );
97 sizelimit = atoi( optarg );
106 templatefile = optarg;
109 rdncount = atoi( optarg );
115 if ( errflg || optind < argc ) {
116 fprintf( stderr, usage, prog );
122 * if syslogging requested, initialize
125 openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON );
127 openlog( prog, OPENLOG_OPTIONS );
131 if ( read_msg( stdin, &msg ) < 0 ) {
133 syslog( LOG_INFO, "unparseable message ignored" );
135 exit( 0 ); /* so as not to give sendmail an error */
139 syslog( LOG_INFO, "processing command \"%s %s\" from %s",
140 ( msg.msg_command < 0 ) ? "Unknown" :
141 cmds[ msg.msg_command ].cmd_text,
142 ( msg.msg_arg == NULL ) ? "" : msg.msg_arg, msg.msg_replyto );
145 if ( msg.msg_command < 0 ) {
146 msg.msg_command = 0; /* unknown command == help command */
150 sprintf( reply, "Your request was interpreted as: %s %s\n\n",
151 cmds[ msg.msg_command ].cmd_text, msg.msg_arg );
154 (*cmds[ msg.msg_command ].cmd_handler)( &msg, reply );
156 if ( send_reply( &msg, reply ) < 0 ) {
158 syslog( LOG_INFO, "reply failed: %m" );
160 exit( 0 ); /* so as not to give sendmail an error */
164 syslog( LOG_INFO, "reply OK" );
174 struct msginfo *msgp;
176 char buf[ MAXSIZE ], *line;
179 msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL;
183 if ( line == NULL ) {
184 if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) {
187 buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
190 if ( *buf == '\0' ) { /* start of message body */
193 if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) {
194 if ( msgp->msg_replyto != NULL ) {
195 free( msgp->msg_replyto );
197 msgp->msg_replyto = read_hdr( fp, 9, buf, MAXSIZE, &line );
198 } else if ( strncasecmp( buf, "From:", 5 ) == 0 &&
199 msgp->msg_replyto == NULL ) {
200 msgp->msg_replyto = read_hdr( fp, 5, buf, MAXSIZE, &line );
201 } else if ( strncasecmp( buf, "Date:", 5 ) == 0 ) {
202 msgp->msg_date = read_hdr( fp, 5, buf, MAXSIZE, &line );
203 } else if ( strncasecmp( buf, "Message-ID:", 5 ) == 0 ) {
204 msgp->msg_messageid = read_hdr( fp, 11, buf, MAXSIZE, &line );
205 } else if ( strncasecmp( buf, "Subject:", 8 ) == 0 ) {
206 if (( msgp->msg_subject =
207 read_hdr( fp, 8, buf, MAXSIZE, &line )) != NULL ) {
208 command = find_command( msgp->msg_subject, &msgp->msg_arg );
211 line = NULL; /* discard current line */
215 while ( command < 0 && line != NULL ) {
217 * read the body of the message, looking for commands
219 if (( line = fgets( buf, MAXSIZE, fp )) != NULL ) {
220 buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
221 command = find_command( buf, &msgp->msg_arg );
225 if ( msgp->msg_replyto == NULL ) {
229 msgp->msg_command = command;
235 read_hdr( fp, offset, buf, MAXSIZEe, linep )
244 for ( hdr = buf + offset; isspace( *hdr ); ++hdr ) {
247 if (( hdr = strdup( hdr )) == NULL ) {
249 syslog( LOG_ERR, "strdup: %m" );
255 *linep = fgets( buf, MAXSIZE, fp );
256 buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
257 if ( *linep == NULL || !isspace( **linep )) {
260 if (( hdr = realloc( hdr, strlen( hdr ) +
261 strlen( *linep ) + 3 )) == NULL) {
263 syslog( LOG_ERR, "realloc: %m" );
268 strcat( hdr, *linep );
276 send_reply( msgp, body )
277 struct msginfo *msgp;
284 if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) {
286 syslog( LOG_ERR, "popen pipemailcmd failed: %m" );
295 sprintf( buf, "From: %s\n", RCPT500_FROM );
296 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
299 if ( msgp->msg_subject != NULL ) {
300 sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject );
302 sprintf( buf, "Subject: query response\n" );
304 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
307 if ( rc == 1 && msgp->msg_date != NULL ) {
309 * add "In-reply-to:" header
311 if ( msgp->msg_messageid == NULL ) {
312 sprintf( buf, "In-reply-to: Your message of \"%s\"\n",
316 "In-reply-to: Your message of \"%s\"\n %s\n",
317 msgp->msg_date, msgp->msg_messageid );
319 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
323 sprintf( buf, "To: %s\n", msgp->msg_replyto );
324 rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
328 * send the header/body separator (blank line)
331 rc = fwrite( "\n", 1, 1, cmdpipe );
338 rc = fwrite( body, strlen( body ), 1, cmdpipe );
341 if ( rc != 1 && dosyslog ) {
342 syslog( LOG_ERR, "write to binmail failed: %m" );
345 if ( pclose( cmdpipe ) < 0 ) {
347 syslog( LOG_ERR, "pclose binmail failed: %m" );
352 return( rc == 1 ? 0 : -1 );
357 find_command( text, argp )
363 static char argbuf[ MAXSIZE ];
366 for ( s = argbuf; *p != '\0'; ++p ) {
367 *s++ = TOLOWER( *p );
371 for ( i = 0; cmds[ i ].cmd_text != NULL; ++i ) {
372 if (( s = strstr( argbuf, cmds[ i ].cmd_text )) != NULL
373 && isspace( *(s + strlen( cmds[ i ].cmd_text )))) {
374 strcpy( argbuf, text + (s - argbuf) + strlen( cmds[ i ].cmd_text ));
376 while ( isspace( **argp )) {