]> git.sur5r.net Git - openldap/blob - clients/rcpt500/main.c
Remove unused variables
[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
14 #include <ac/ctype.h>
15 #include <ac/signal.h>
16 #include <ac/string.h>
17 #include <ac/syslog.h>
18 #include <ac/unistd.h>
19
20 #include "ldapconfig.h"
21 #include "rcpt500.h"
22
23 int dosyslog = 0;
24 #ifdef LDAP_CONNECTIONLESS
25 int do_cldap = 0;
26 #endif /* LDAP_CONNECTIONLESS */
27
28 int derefaliases = 1;
29 int sizelimit = RCPT500_SIZELIMIT;
30 int rdncount = RCPT500_RDNCOUNT;
31 int ldapport = 0;
32 char *ldaphost = NULL;
33 char *searchbase = NULL;
34 char *dapuser = NULL;
35 char *filterfile = FILTERFILE;
36 char *templatefile = TEMPLATEFILE;
37 static char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
38
39
40 /*
41  * functions
42  */
43 static int  read_msg(FILE *fp, struct msginfo *msgp);
44 static char *read_hdr(FILE *fp, int off, char *buf, int MAXSIZEe, char **ln_p);
45 static int  send_reply(struct msginfo *msgp, char *body);
46 static int  find_command(char *text, char **argp);
47
48 /*
49  * main is invoked by sendmail via the alias file
50  * the entire incoming message gets piped to our standard input
51  */
52 int
53 main( int argc, 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
59     *reply = '\0';
60
61     if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
62         prog = strdup( argv[ 0 ] );
63     } else {
64         prog = strdup( prog + 1 );
65     }
66
67     errflg = 0;
68     while (( c = getopt( argc, argv, "alUh:b:s:z:f:t:p:c:" )) != EOF ) {
69         switch( c ) {
70         case 'a':
71             derefaliases = 0;
72             break;
73         case 'l':
74             dosyslog = 1;
75             break;
76         case 'U':
77 #ifdef LDAP_CONNECTIONLESS
78             do_cldap = 1;
79 #else /* LDAP_CONNECTIONLESS */
80             fprintf( stderr,
81                         "Compile with -DLDAP_CONNECTIONLESS for -U support\n" );
82 #endif /* LDAP_CONNECTIONLESS */
83             break;      
84         case 'b':
85             searchbase = optarg;
86             break;
87         case 'h':
88             ldaphost = optarg;
89             break;
90         case 'p':
91             ldapport = atoi( optarg );
92             break;
93         case 'z':
94             sizelimit = atoi( optarg );
95             break;
96         case 'u':
97             dapuser = optarg;
98             break;
99         case 'f':
100             filterfile = optarg;
101             break;
102         case 't':
103             templatefile = optarg;
104             break;
105         case 'c':
106             rdncount = atoi( optarg );
107             break;
108         default:
109             ++errflg;
110         }
111     }
112     if ( errflg || optind < argc ) {
113         fprintf( stderr, usage, prog );
114         exit( 1 );
115     }
116
117 #ifdef SIGPIPE
118         (void) SIGNAL( SIGPIPE, SIG_IGN );
119 #endif
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 static int
173 read_msg( FILE *fp, struct msginfo *msgp )
174 {
175     char        buf[ MAXSIZE ], *line;
176     int         command = -1;
177
178     msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL;
179
180     line = NULL;
181     while( 1 ) {
182         if ( line == NULL ) {
183             if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) {
184                 break;
185             }
186             buf[ strlen( buf ) - 1 ] = '\0';    /* remove trailing newline */
187         }
188
189         if ( *buf == '\0' ) {   /* start of message body */
190             break;
191         }
192         if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) {
193             if ( msgp->msg_replyto != NULL ) {
194                 free( msgp->msg_replyto );
195             }
196              msgp->msg_replyto = read_hdr( fp, 9, buf, MAXSIZE, &line );
197         } else if ( strncasecmp( buf, "From:", 5 ) == 0 &&
198                     msgp->msg_replyto == NULL ) {
199              msgp->msg_replyto = read_hdr( fp, 5, buf, MAXSIZE, &line );
200         } else if ( strncasecmp( buf, "Date:", 5 ) == 0 ) {
201              msgp->msg_date = read_hdr( fp, 5, buf, MAXSIZE, &line );
202         } else if ( strncasecmp( buf, "Message-ID:", 5 ) == 0 ) {
203              msgp->msg_messageid = read_hdr( fp, 11, buf, MAXSIZE, &line );
204         } else if ( strncasecmp( buf, "Subject:", 8 ) == 0 ) {
205              if (( msgp->msg_subject =
206                     read_hdr( fp, 8, buf, MAXSIZE, &line )) != NULL ) {
207                 command = find_command( msgp->msg_subject, &msgp->msg_arg );
208             }
209         } else {
210             line = NULL;        /* discard current line */
211         }
212     }
213
214     while ( command < 0 && line != NULL ) {
215         /*
216          * read the body of the message, looking for commands
217          */
218         if (( line = fgets( buf, MAXSIZE, fp )) != NULL ) {
219             buf[ strlen( buf ) - 1 ] = '\0';    /* remove trailing newline */
220             command = find_command( buf, &msgp->msg_arg );
221         }
222     }
223
224     if ( msgp->msg_replyto == NULL ) {
225         return( -1 );
226     }
227
228     msgp->msg_command = command;
229     return( 0 );
230 }
231
232
233 static char *
234 read_hdr( FILE *fp, int offset, char *buf, int MAXSIZEe, char **linep )
235 {
236     char        *hdr;
237
238     for ( hdr = buf + offset; isspace( (unsigned char) *hdr ); ++hdr ) {
239         ;
240     }
241     if (( hdr = strdup( hdr )) == NULL ) {
242         if ( dosyslog ) {
243             syslog( LOG_ERR, "strdup: %m" );
244         }
245         exit( 1 );
246     }
247
248     while ( 1 ) {
249         *linep = fgets( buf, MAXSIZE, fp );
250         buf[ strlen( buf ) - 1 ] = '\0';        /* remove trailing newline */
251         if ( *linep == NULL || !isspace( (unsigned char) **linep )) {
252             break;
253         }
254         if (( hdr = realloc( hdr, strlen( hdr ) +
255                     strlen( *linep ) + 3 )) == NULL) {
256             if ( dosyslog ) {
257                 syslog( LOG_ERR, "realloc: %m" );
258             }
259             exit( 1 );
260         }
261         strcat( hdr, "\n" );
262         strcat( hdr, *linep );
263     }
264
265     return( hdr );
266 }
267
268
269 static int
270 send_reply( struct msginfo *msgp, char *body )
271 {
272     char        buf[ MAXSIZE ];
273     FILE        *cmdpipe;
274     int         rc;
275     
276     if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) {
277         if ( dosyslog ) {
278             syslog( LOG_ERR, "popen pipemailcmd failed: %m" );
279         }
280         return( -1 );
281     }
282
283     /*
284      * send the headers
285      */
286
287     sprintf( buf, "From: %s\n", RCPT500_FROM );
288     rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
289
290     if ( rc == 1 ) {
291         if ( msgp->msg_subject != NULL ) {
292             sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject );
293         } else {
294             sprintf( buf, "Subject: query response\n" );
295         }
296         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
297     }
298
299     if ( rc == 1 && msgp->msg_date != NULL ) {
300         /*
301          * add "In-reply-to:" header
302          */
303         if ( msgp->msg_messageid == NULL ) {
304             sprintf( buf, "In-reply-to: Your message of \"%s\"\n",
305                     msgp->msg_date );
306         } else {
307             sprintf( buf,
308                     "In-reply-to: Your message of \"%s\"\n             %s\n",
309                     msgp->msg_date, msgp->msg_messageid );
310         }
311         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
312     }
313
314     if ( rc == 1 ) {
315         sprintf( buf, "To: %s\n", msgp->msg_replyto );
316         rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
317     }
318
319     /*
320      * send the header/body separator (blank line)
321      */
322     if ( rc == 1 ) {
323         rc = fwrite( "\n", 1, 1, cmdpipe );
324     }
325
326     /*
327      * send the body
328      */
329     if ( rc == 1 ) {
330         rc = fwrite( body, strlen( body ), 1, cmdpipe );
331     }
332
333     if ( rc != 1 && dosyslog ) {
334         syslog( LOG_ERR, "write to binmail failed: %m" );
335     }
336
337     if ( pclose( cmdpipe ) < 0 ) {
338         if ( dosyslog ) {
339             syslog( LOG_ERR, "pclose binmail failed: %m" );
340         }
341         return( -1 );
342     }
343
344     return( rc == 1 ? 0 : -1 );
345 }
346
347
348 static int
349 find_command( char *text, char **argp )
350 {
351     int         i;
352     char        *s, *p;
353     static char argbuf[ MAXSIZE ];
354
355     p = text;
356     for ( s = argbuf; *p != '\0'; ++p ) {
357         *s++ = TOLOWER( (unsigned char) *p );
358     }
359     *s = '\0';
360
361     for ( i = 0; cmds[ i ].cmd_text != NULL; ++i ) {
362         if (( s = strstr( argbuf, cmds[ i ].cmd_text )) != NULL
363             && isspace( (unsigned char) s[ strlen( cmds[ i ].cmd_text ) ] )) {
364             strcpy( argbuf, text + (s - argbuf) + strlen( cmds[ i ].cmd_text ));
365             *argp = argbuf;
366             while ( isspace( (unsigned char) **argp )) {
367                 ++(*argp);
368             }
369             return( i );
370         }
371     }
372
373     return( -1 );
374 }