]> git.sur5r.net Git - openldap/blob - clients/rcpt500/main.c
b29920ff4003a7724d8a427d30d6e814158ef938
[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 "portable.h"
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14
15 #include <ac/syslog.h>
16 #include <ac/string.h>
17
18
19 #include "ldapconfig.h"
20 #include "rcpt500.h"
21
22 int dosyslog = 0;
23 #ifdef LDAP_CONNECTIONLESS
24 int do_cldap = 0;
25 #endif /* LDAP_CONNECTIONLESS */
26
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 LDAP_CONNECTIONLESS
82             do_cldap = 1;
83 #else /* LDAP_CONNECTIONLESS */
84             fprintf( stderr,
85                         "Compile with -DLDAP_CONNECTIONLESS for -U support\n" );
86 #endif /* LDAP_CONNECTIONLESS */
87             break;      
88         case 'b':
89             searchbase = optarg;
90             break;
91         case 'h':
92             ldaphost = optarg;
93             break;
94         case 'p':
95             ldapport = atoi( optarg );
96             break;
97         case 'z':
98             sizelimit = atoi( optarg );
99             break;
100         case 'u':
101             dapuser = optarg;
102             break;
103         case 'f':
104             filterfile = optarg;
105             break;
106         case 't':
107             templatefile = optarg;
108             break;
109         case 'c':
110             rdncount = atoi( optarg );
111             break;
112         default:
113             ++errflg;
114         }
115     }
116     if ( errflg || optind < argc ) {
117         fprintf( stderr, usage, prog );
118         exit( 1 );
119     }
120
121     if ( dosyslog ) {
122         /*
123          * if syslogging requested, initialize
124          */
125 #ifdef LOG_DAEMON
126         openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON );
127 #else
128         openlog( prog, OPENLOG_OPTIONS );
129 #endif
130     }
131
132     if ( read_msg( stdin, &msg ) < 0 ) {
133         if ( dosyslog ) {
134             syslog( LOG_INFO, "unparseable message ignored" );
135         }
136         exit( 0 );      /* so as not to give sendmail an error */
137     }
138
139     if ( dosyslog ) {
140         syslog( LOG_INFO, "processing command \"%s %s\" from %s",
141                 ( msg.msg_command < 0 ) ? "Unknown" :
142                 cmds[ msg.msg_command ].cmd_text,
143                 ( msg.msg_arg == NULL ) ? "" : msg.msg_arg, msg.msg_replyto );
144     }
145
146     if ( msg.msg_command < 0 ) {
147         msg.msg_command = 0;    /* unknown command == help command */
148     }
149
150 /*
151     sprintf( reply, "Your request was interpreted as: %s %s\n\n",
152             cmds[ msg.msg_command ].cmd_text, msg.msg_arg );
153 */
154
155     (*cmds[ msg.msg_command ].cmd_handler)( &msg, reply );
156
157     if ( send_reply( &msg, reply ) < 0 ) {
158         if ( dosyslog ) {
159             syslog( LOG_INFO, "reply failed: %m" );
160         }
161         exit( 0 );      /* so as not to give sendmail an error */
162     }
163
164     if ( dosyslog ) {
165         syslog( LOG_INFO, "reply OK" );
166     }
167
168     exit( 0 );
169 }
170
171
172 int
173 read_msg( fp, msgp )
174     FILE                *fp;
175     struct msginfo      *msgp;
176 {
177     char        buf[ MAXSIZE ], *line;
178     int         command = -1;
179
180     msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL;
181
182     line = NULL;
183     while( 1 ) {
184         if ( line == NULL ) {
185             if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) {
186                 break;
187             }
188             buf[ strlen( buf ) - 1 ] = '\0';    /* remove trailing newline */
189         }
190
191         if ( *buf == '\0' ) {   /* start of message body */
192             break;
193         }
194         if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) {
195             if ( msgp->msg_replyto != NULL ) {
196                 free( msgp->msg_replyto );
197             }
198              msgp->msg_replyto = read_hdr( fp, 9, buf, MAXSIZE, &line );
199         } else if ( strncasecmp( buf, "From:", 5 ) == 0 &&
200                     msgp->msg_replyto == NULL ) {
201              msgp->msg_replyto = read_hdr( fp, 5, buf, MAXSIZE, &line );
202         } else if ( strncasecmp( buf, "Date:", 5 ) == 0 ) {
203              msgp->msg_date = read_hdr( fp, 5, buf, MAXSIZE, &line );
204         } else if ( strncasecmp( buf, "Message-ID:", 5 ) == 0 ) {
205              msgp->msg_messageid = read_hdr( fp, 11, buf, MAXSIZE, &line );
206         } else if ( strncasecmp( buf, "Subject:", 8 ) == 0 ) {
207              if (( msgp->msg_subject =
208                     read_hdr( fp, 8, buf, MAXSIZE, &line )) != NULL ) {
209                 command = find_command( msgp->msg_subject, &msgp->msg_arg );
210             }
211         } else {
212             line = NULL;        /* discard current line */
213         }
214     }
215
216     while ( command < 0 && line != NULL ) {
217         /*
218          * read the body of the message, looking for commands
219          */
220         if (( line = fgets( buf, MAXSIZE, fp )) != NULL ) {
221             buf[ strlen( buf ) - 1 ] = '\0';    /* remove trailing newline */
222             command = find_command( buf, &msgp->msg_arg );
223         }
224     }
225
226     if ( msgp->msg_replyto == NULL ) {
227         return( -1 );
228     }
229
230     msgp->msg_command = command;
231     return( 0 );
232 }
233
234
235 char *
236 read_hdr( fp, offset, buf, MAXSIZEe, linep )
237     FILE        *fp;
238     int         offset;
239     char        *buf;
240     int         MAXSIZEe;
241     char        **linep;
242 {
243     char        *hdr;
244
245     for ( hdr = buf + offset; isspace( *hdr ); ++hdr ) {
246         ;
247     }
248     if (( hdr = strdup( hdr )) == NULL ) {
249         if ( dosyslog ) {
250             syslog( LOG_ERR, "strdup: %m" );
251         }
252         exit( 1 );
253     }
254
255     while ( 1 ) {
256         *linep = fgets( buf, MAXSIZE, fp );
257         buf[ strlen( buf ) - 1 ] = '\0';        /* remove trailing newline */
258         if ( *linep == NULL || !isspace( **linep )) {
259             break;
260         }
261         if (( hdr = realloc( hdr, strlen( hdr ) +
262                     strlen( *linep ) + 3 )) == NULL) {
263             if ( dosyslog ) {
264                 syslog( LOG_ERR, "realloc: %m" );
265             }
266             exit( 1 );
267         }
268         strcat( hdr, "\n" );
269         strcat( hdr, *linep );
270     }
271
272     return( hdr );
273 }
274
275
276 int
277 send_reply( msgp, body )
278     struct msginfo      *msgp;
279     char                *body;
280 {
281     char        buf[ MAXSIZE ];
282     FILE        *cmdpipe;
283     int         rc;
284     
285     if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) {
286         if ( dosyslog ) {
287             syslog( LOG_ERR, "popen pipemailcmd failed: %m" );
288         }
289         return( -1 );
290     }
291
292     /*
293      * send the headers
294      */
295
296     sprintf( buf, "From: %s\n", RCPT500_FROM );
297     rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
298
299     if ( rc == 1 ) {
300         if ( msgp->msg_subject != NULL ) {
301             sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject );
302         } else {
303             sprintf( buf, "Subject: query response\n" );
304         }
305         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
306     }
307
308     if ( rc == 1 && msgp->msg_date != NULL ) {
309         /*
310          * add "In-reply-to:" header
311          */
312         if ( msgp->msg_messageid == NULL ) {
313             sprintf( buf, "In-reply-to: Your message of \"%s\"\n",
314                     msgp->msg_date );
315         } else {
316             sprintf( buf,
317                     "In-reply-to: Your message of \"%s\"\n             %s\n",
318                     msgp->msg_date, msgp->msg_messageid );
319         }
320         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
321     }
322
323     if ( rc == 1 ) {
324         sprintf( buf, "To: %s\n", msgp->msg_replyto );
325         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
326     }
327
328     /*
329      * send the header/body separator (blank line)
330      */
331     if ( rc == 1 ) {
332         rc = fwrite( "\n", 1, 1, cmdpipe );
333     }
334
335     /*
336      * send the body
337      */
338     if ( rc == 1 ) {
339         rc = fwrite( body, strlen( body ), 1, cmdpipe );
340     }
341
342     if ( rc != 1 && dosyslog ) {
343         syslog( LOG_ERR, "write to binmail failed: %m" );
344     }
345
346     if ( pclose( cmdpipe ) < 0 ) {
347         if ( dosyslog ) {
348             syslog( LOG_ERR, "pclose binmail failed: %m" );
349         }
350         return( -1 );
351     }
352
353     return( rc == 1 ? 0 : -1 );
354 }
355
356
357 int
358 find_command( text, argp )
359     char        *text;
360     char        **argp;
361 {
362     int         i;
363     char        *s, *p;
364     static char argbuf[ MAXSIZE ];
365
366     p = text;
367     for ( s = argbuf; *p != '\0'; ++p ) {
368         *s++ = tolower( *p );
369     }
370     *s = '\0';
371
372     for ( i = 0; cmds[ i ].cmd_text != NULL; ++i ) {
373         if (( s = strstr( argbuf, cmds[ i ].cmd_text )) != NULL
374                     && isspace( *(s + strlen( cmds[ i ].cmd_text )))) {
375             strcpy( argbuf, text + (s - argbuf) + strlen( cmds[ i ].cmd_text ));
376             *argp = argbuf;
377             while ( isspace( **argp )) {
378                 ++(*argp);
379             }
380             return( i );
381         }
382     }
383
384     return( -1 );
385 }