]> git.sur5r.net Git - openldap/blob - clients/rcpt500/main.c
3e65ac233b6467731c569e486c1a6d2f8c901098
[openldap] / clients / rcpt500 / main.c
1 /*
2  * main.c: for rcpt500 (X.500 email query responder)
3  *
4  * 16 June 1992 by Mark C Smith
5  * Copyright (c) 1992 The Regents of The University of Michigan
6  * All Rights Reserved
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <syslog.h>
12 #include <string.h>
13 #include <ctype.h>
14
15 #include "portable.h"
16 #include "ldapconfig.h"
17 #include "rcpt500.h"
18
19 #ifdef ultrix
20 extern char *strdup();
21 #endif
22
23 int dosyslog = 0;
24 #ifdef CLDAP
25 int do_cldap = 0;
26 #endif /* CLDAP */
27 int derefaliases = 1;
28 int sizelimit = RCPT500_SIZELIMIT;
29 int rdncount = RCPT500_RDNCOUNT;
30 int ldapport = 0;
31 char *ldaphost = LDAPHOST;
32 char *searchbase = RCPT500_BASE;
33 char *dapuser = RCPT500_BINDDN;
34 char *filterfile = FILTERFILE;
35 char *templatefile = TEMPLATEFILE;
36 char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
37
38
39
40 /*
41  * functions
42  */
43 int     read_msg();
44 char    *read_hdr();
45 int     send_reply();
46
47 /*
48  * main is invoked by sendmail via the alias file
49  * the entire incoming message gets piped to our standard input
50  */
51 main( argc, argv )
52     int         argc;
53     char        **argv;
54 {
55     char                *prog, *usage = "%s [-l] [-U] [-h ldaphost] [-p ldapport] [-b searchbase] [-a] [-z sizelimit] [-u dapuser] [-f filterfile] [-t templatefile] [-c rdncount]\n";
56     struct msginfo      msg;
57     int                 c, errflg;
58     char                *replytext;
59
60     extern int          optind;
61     extern char         *optarg;
62
63     *reply = '\0';
64
65     if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
66         prog = strdup( argv[ 0 ] );
67     } else {
68         prog = strdup( prog + 1 );
69     }
70
71     errflg = 0;
72     while (( c = getopt( argc, argv, "alUh:b:s:z:f:t:p:c:" )) != EOF ) {
73         switch( c ) {
74         case 'a':
75             derefaliases = 0;
76             break;
77         case 'l':
78             dosyslog = 1;
79             break;
80         case 'U':
81 #ifdef CLDAP
82             do_cldap = 1;
83 #else /* CLDAP */
84             fprintf( stderr, "Compile with -DCLDAP for -U support\n" );
85 #endif /* CLDAP */
86             break;      
87         case 'b':
88             searchbase = optarg;
89             break;
90         case 'h':
91             ldaphost = optarg;
92             break;
93         case 'p':
94             ldapport = atoi( optarg );
95             break;
96         case 'z':
97             sizelimit = atoi( optarg );
98             break;
99         case 'u':
100             dapuser = optarg;
101             break;
102         case 'f':
103             filterfile = optarg;
104             break;
105         case 't':
106             templatefile = optarg;
107             break;
108         case 'c':
109             rdncount = atoi( optarg );
110             break;
111         default:
112             ++errflg;
113         }
114     }
115     if ( errflg || optind < argc ) {
116         fprintf( stderr, usage, prog );
117         exit( 1 );
118     }
119
120     if ( dosyslog ) {
121         /*
122          * if syslogging requested, initialize
123          */
124 #ifdef LOG_DAEMON
125         openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON );
126 #else
127         openlog( prog, OPENLOG_OPTIONS );
128 #endif
129     }
130
131     if ( read_msg( stdin, &msg ) < 0 ) {
132         if ( dosyslog ) {
133             syslog( LOG_INFO, "unparseable message ignored" );
134         }
135         exit( 0 );      /* so as not to give sendmail an error */
136     }
137
138     if ( dosyslog ) {
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 );
143     }
144
145     if ( msg.msg_command < 0 ) {
146         msg.msg_command = 0;    /* unknown command == help command */
147     }
148
149 /*
150     sprintf( reply, "Your request was interpreted as: %s %s\n\n",
151             cmds[ msg.msg_command ].cmd_text, msg.msg_arg );
152 */
153
154     (*cmds[ msg.msg_command ].cmd_handler)( &msg, reply );
155
156     if ( send_reply( &msg, reply ) < 0 ) {
157         if ( dosyslog ) {
158             syslog( LOG_INFO, "reply failed: %m" );
159         }
160         exit( 0 );      /* so as not to give sendmail an error */
161     }
162
163     if ( dosyslog ) {
164         syslog( LOG_INFO, "reply OK" );
165     }
166
167     exit( 0 );
168 }
169
170
171 int
172 read_msg( fp, msgp )
173     FILE                *fp;
174     struct msginfo      *msgp;
175 {
176     char        buf[ MAXSIZE ], *line;
177     int         command = -1;
178
179     msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL;
180
181     line = NULL;
182     while( 1 ) {
183         if ( line == NULL ) {
184             if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) {
185                 break;
186             }
187             buf[ strlen( buf ) - 1 ] = '\0';    /* remove trailing newline */
188         }
189
190         if ( *buf == '\0' ) {   /* start of message body */
191             break;
192         }
193         if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) {
194             if ( msgp->msg_replyto != NULL ) {
195                 free( msgp->msg_replyto );
196             }
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 );
209             }
210         } else {
211             line = NULL;        /* discard current line */
212         }
213     }
214
215     while ( command < 0 && line != NULL ) {
216         /*
217          * read the body of the message, looking for commands
218          */
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 );
222         }
223     }
224
225     if ( msgp->msg_replyto == NULL ) {
226         return( -1 );
227     }
228
229     msgp->msg_command = command;
230     return( 0 );
231 }
232
233
234 char *
235 read_hdr( fp, offset, buf, MAXSIZEe, linep )
236     FILE        *fp;
237     int         offset;
238     char        *buf;
239     int         MAXSIZEe;
240     char        **linep;
241 {
242     char        *hdr;
243
244     for ( hdr = buf + offset; isspace( *hdr ); ++hdr ) {
245         ;
246     }
247     if (( hdr = strdup( hdr )) == NULL ) {
248         if ( dosyslog ) {
249             syslog( LOG_ERR, "strdup: %m" );
250         }
251         exit( 1 );
252     }
253
254     while ( 1 ) {
255         *linep = fgets( buf, MAXSIZE, fp );
256         buf[ strlen( buf ) - 1 ] = '\0';        /* remove trailing newline */
257         if ( *linep == NULL || !isspace( **linep )) {
258             break;
259         }
260         if (( hdr = realloc( hdr, strlen( hdr ) +
261                     strlen( *linep ) + 3 )) == NULL) {
262             if ( dosyslog ) {
263                 syslog( LOG_ERR, "realloc: %m" );
264             }
265             exit( 1 );
266         }
267         strcat( hdr, "\n" );
268         strcat( hdr, *linep );
269     }
270
271     return( hdr );
272 }
273
274
275 int
276 send_reply( msgp, body )
277     struct msginfo      *msgp;
278     char                *body;
279 {
280     char        buf[ MAXSIZE ];
281     FILE        *cmdpipe;
282     int         rc;
283     
284     if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) {
285         if ( dosyslog ) {
286             syslog( LOG_ERR, "popen pipemailcmd failed: %m" );
287         }
288         return( -1 );
289     }
290
291     /*
292      * send the headers
293      */
294
295     sprintf( buf, "From: %s\n", RCPT500_FROM );
296     rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
297
298     if ( rc == 1 ) {
299         if ( msgp->msg_subject != NULL ) {
300             sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject );
301         } else {
302             sprintf( buf, "Subject: query response\n" );
303         }
304         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
305     }
306
307     if ( rc == 1 && msgp->msg_date != NULL ) {
308         /*
309          * add "In-reply-to:" header
310          */
311         if ( msgp->msg_messageid == NULL ) {
312             sprintf( buf, "In-reply-to: Your message of \"%s\"\n",
313                     msgp->msg_date );
314         } else {
315             sprintf( buf,
316                     "In-reply-to: Your message of \"%s\"\n             %s\n",
317                     msgp->msg_date, msgp->msg_messageid );
318         }
319         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
320     }
321
322     if ( rc == 1 ) {
323         sprintf( buf, "To: %s\n", msgp->msg_replyto );
324         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
325     }
326
327     /*
328      * send the header/body separator (blank line)
329      */
330     if ( rc == 1 ) {
331         rc = fwrite( "\n", 1, 1, cmdpipe );
332     }
333
334     /*
335      * send the body
336      */
337     if ( rc == 1 ) {
338         rc = fwrite( body, strlen( body ), 1, cmdpipe );
339     }
340
341     if ( rc != 1 && dosyslog ) {
342         syslog( LOG_ERR, "write to binmail failed: %m" );
343     }
344
345     if ( pclose( cmdpipe ) < 0 ) {
346         if ( dosyslog ) {
347             syslog( LOG_ERR, "pclose binmail failed: %m" );
348         }
349         return( -1 );
350     }
351
352     return( rc == 1 ? 0 : -1 );
353 }
354
355
356 int
357 find_command( text, argp )
358     char        *text;
359     char        **argp;
360 {
361     int         i;
362     char        *s, *p;
363     static char argbuf[ MAXSIZE ];
364
365     p = text;
366     for ( s = argbuf; *p != '\0'; ++p ) {
367         *s++ = tolower( *p );
368     }
369     *s = '\0';
370
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 ));
375             *argp = argbuf;
376             while ( isspace( **argp )) {
377                 ++(*argp);
378             }
379             return( i );
380         }
381     }
382
383     return( -1 );
384 }