]> git.sur5r.net Git - openldap/blob - contrib/whois++/command.c
Merge from LAMBERT branch
[openldap] / contrib / whois++ / command.c
1 #if !defined(lint)
2 static char copyright[] = "Copyright 1992 The University of Adelaide";
3 #endif
4
5 /*
6  *                      C O M M A N D
7  *
8  * Author:      Mark R. Prior
9  *              Communications and Systems Branch
10  *              Information Technology Division
11  *              The University of Adelaide
12  * E-mail:      mrp@itd.adelaide.edu.au
13  * Date:        October 1992
14  * Version:     1.8
15  * Description:
16  *              Interpret the command sent by the client
17  *
18  * Redistribution and use in source and binary forms are permitted
19  * provided that the above copyright notice and this paragraph are
20  * duplicated in all such forms and that any documentation,
21  * advertising materials, and other materials related to such
22  * distribution and use acknowledge that the software was developed
23  * by the University of Adelaide. The name of the University may not
24  * be used to endorse or promote products derived from this software
25  * without specific prior written permission.
26  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
27  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
28  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  */
30
31 #include "whois++.h"
32
33 extern char     *index(), *rindex();
34
35 #define isspecial(c)    ( (c) == ',' || (c) == ';' || (c) == ':' || (c) == '=' )
36
37 static  char    **component = NULL;
38 static  int     numberOfComponents;
39 static  int     components = 10;
40
41 static int getToken( token )
42 char    *token;
43
44 {
45         static char     *buffer = NULL;
46         static int      idx;
47         char            ch;
48         fd_set          readfds;
49         struct timeval  timeout;
50         int             i, status, tablesize;
51
52         if ( buffer == NULL ) {
53 #ifdef FD_SETSIZE
54                 /*
55                  * It is invalid to use a set size in excess of the type
56                  * scope, as defined for the fd_set in sys/types.h.  This
57                  * is true for any OS.
58                  */
59                 tablesize = FD_SETSIZE;
60 #else   /* !FD_SETSIZE*/
61                 tablesize = getdtablesize();
62 #endif  /* !FD_SETSIZE*/
63                 timeout.tv_sec = 60;
64                 timeout.tv_usec = 0;
65                 FD_ZERO( &readfds );
66                 FD_SET( fileno( stdin ), &readfds );
67
68                 if ( (status = select( tablesize, &readfds, 0, 0, &timeout )) <= 0 ) {
69                         if ( status < 0 )
70                                 printFormatted( lineLength, TRUE, stdout,
71                                         "select: %s", strerror( errno ) );
72                         else
73                                 printFormatted( lineLength, TRUE, stdout,
74                                         "Connection timed out waiting for input." );
75                         exit( 1 );
76                 }
77 /**/            /*
78                  * We really should determine how many characters are
79                  * waiting for us and then malloc that amount rather than
80                  * just guessing!
81                  */
82                 if ( ( buffer = (char *)malloc(BUFSIZ) ) == NULL
83                         || fgets( buffer, BUFSIZ, stdin ) == NULL ) {
84                         *token = '\0';
85                         return EOF;
86                 }
87                 idx = 0;
88                 i = strlen( buffer );
89                 while ( i-- > 0 && ( buffer[i] == '\r' || buffer[i] == '\n' ) )
90                         buffer[i] = '\0';
91                 if ( log )
92                         syslog( LOG_INFO, "Whois++ Query: %s", buffer );
93         }
94         while ( buffer[idx] != '\0' && isspace( buffer[idx] ) )
95                 idx++;
96         token[0] = buffer[idx++];
97         token[1] = '\0';
98         switch ( token[0] ) {
99         case '\0':
100                 strcpy( token, "<end of line>" );
101                 free( buffer );
102                 buffer = NULL;
103                 return EOF;
104
105         case '^':
106                 return TEMPLATE;
107
108         case '!':
109                 return HANDLE;
110
111         case '.':
112                 return ATTRIBUTE;
113
114         case '#':
115                 return VALUE;
116
117         case '*':
118                 return SEARCH_ALL;
119
120         case '?':
121                 return HELP;
122
123         case ':':
124                 return COLON;
125
126         case ';':
127                 return SEMICOLON;
128
129         case ',':
130                 return COMMA;
131
132         case '=':
133                 return EQUALS;
134
135         case '"':
136                 i = 0;
137                 do {
138                         ch = buffer[idx++];
139                         if ( ch == '\\' && buffer[idx] != '\0' )
140                                 token[i++] = buffer[idx++];
141                         else
142                                 token[i++] = ch;
143                 } while ( ch != '\0' && ch != '"' );
144                 if ( ch == '\0' ) {
145                         printFormatted( lineLength, TRUE, stdout,
146                                 "Trailing \" missing" );
147                         idx--;
148                 }
149                 token[--i] = '\0';
150                 return SEARCH;
151
152         default:
153                 i = 1;
154                 do {
155                         ch = buffer[idx++];
156                         if ( ch == '\\' && buffer[idx] != '\0' )
157                                 token[i++] = buffer[idx++];
158                         else
159                                 token[i++] = ch;
160                 } while ( ch != '\0' && !isspace( ch ) && !isspecial( ch ) );
161                 token[--i] = '\0';
162                 idx--;
163 /**/            /*
164                  * The following is a brute force lookup, once the names
165                  * have settled down this should change to a hash table,
166                  * or something similar.
167                  */
168                 if ( EQ( token, "help" ) )
169                         return HELP;
170                 else if ( EQ( token, "list" ) )
171                         return LIST;
172                 else if ( EQ( token, "show" ) )
173                         return SHOW;
174                 else if ( EQ( token, "constraints" ) )
175                         return CONSTRAINTS;
176                 else if ( EQ( token, "describe" ) )
177                         return DESCRIBE;
178                 else if ( EQ( token, "version" ) )
179                         return VERSION;
180                 else if ( EQ( token, "template" ) )
181                         return TEMPLATE;
182                 else if ( EQ( token, "handle" ) )
183                         return HANDLE;
184                 else if ( EQ( token, "attribute" ) )
185                         return ATTRIBUTE;
186                 else if ( EQ( token, "value" ) )
187                         return VALUE;
188                 else if ( EQ( token, "full" ) )
189                         return FULL;
190                 else if ( EQ( token, "abridged" ) )
191                         return ABRIDGED;
192                 else if ( EQ( token, "summary" ) )
193                         return SUMMARY;
194                 else if ( EQ( token, "format" ) )
195                         return FORMAT;
196                 else if ( EQ( token, "hold" ) )
197                         return HOLD;
198                 else if ( EQ( token, "maxhits" ) )
199                         return MAXHITS;
200                 else if ( EQ( token, "match" ) )
201                         return MATCH;
202                 else if ( EQ( token, "linelength" ) )
203                         return LINE_LENGTH;
204                 else if ( EQ( token, "command" ) )
205                         return COMMAND;
206                 else if ( EQ( token, "trace" ) )
207                         return TRACE;
208                 else
209                         return SEARCH;
210         }
211 }
212
213 static int term( token, value, attribute, specifier, soundex )
214 int     token;
215 char    *value, *attribute;
216 int     *specifier, *soundex;
217 {
218         char    buffer[BUFSIZ], temp[BUFSIZ];
219         int     iterations;
220
221         *soundex = FALSE;
222         switch ( token ) {
223         case ATTRIBUTE: /* . */
224         case VALUE:     /* # */
225         case HANDLE:    /* ! */
226         case TEMPLATE:  /* ^ */
227         case SEARCH_ALL:/* * */
228                 *specifier = token;
229                 if ( strlen( value ) > 1 ) {
230                         /* fullname used, so expect an equals sign */
231                         if ( getToken( buffer ) != EQUALS ) {
232                                 printFormatted( lineLength, TRUE, stdout,
233                                         "\"=\" expected" );
234                                 return ERROR;
235                         } else
236                                 token = getToken( value );
237                 } else 
238                         token = getToken( value );
239                 if ( token != COMMA && token != SEMICOLON && token != EQUALS
240                         && token != COLON && token != EOF ) {
241                         token = getToken( buffer );
242                         break;
243                 }
244
245         case COMMA:
246         case SEMICOLON:
247         case EQUALS:
248         case COLON:
249         case EOF:
250                 printFormatted( lineLength, TRUE, stdout,
251                         "Expected search string but got \"%s\"", buffer );
252                 return ERROR;
253
254         default:
255                 *specifier = SEARCH_ALL;
256                 if ( ( token = getToken( buffer ) ) == EQUALS ) {
257                         strcpy( attribute, value );
258                         token = getToken( value );
259                         if ( token == COMMA || token == SEMICOLON
260                                 || token == COLON || token == EOF ) {
261                                 printFormatted( lineLength, TRUE, stdout,
262                                         "Syntax error, string expected." );
263                                 return ERROR;
264                         }
265                         token = getToken( buffer );
266                 }
267         }
268
269         while ( token != COMMA && token != SEMICOLON && token != COLON
270                 && token != EOF ) {
271                 if ( *value != '\0' )
272                         strcat( value, " " );
273                 strcat( value, buffer );
274                 token = getToken( buffer );
275         }
276         iterations = 2;
277         while ( token == COMMA ) {
278                 token = getToken( buffer );
279                 switch ( token ) {
280                 case MATCH:
281                         iterations = 0;
282                         if ( ( token = getToken( buffer ) ) != EQUALS ) {
283                                 printFormatted( lineLength, TRUE, stdout,
284                                         "\"=\" expected" );
285                         } else
286                                 token = getToken( buffer );
287                         if ( EQ( buffer, "exact" ) )
288                                 *soundex = FALSE;
289                         else if ( EQ( buffer, "fuzzy" ) )
290                                 *soundex = TRUE;
291                         else
292                                 printFormatted( lineLength, TRUE, stdout,
293                                         "Unrecognised search type" );
294                         token = getToken( buffer );
295                         break;
296
297                 default:
298                         if ( iterations == 0 ) {
299                                 /* obviously an unrecognised constraint */
300                                 printFormatted( lineLength, TRUE, stdout,
301                                         "Constraint \"%s\" not supported",
302                                         buffer );
303                                 while ( ( token = getToken( buffer ) ) != EOF
304                                         && token != COMMA && token != COLON
305                                         && token != SEMICOLON )
306                                         ;
307                         } else {
308                                 strcpy( temp, buffer );
309                                 token = getToken( buffer );
310                                 if ( token == EQUALS ) {
311                                         iterations = 0;
312                                         printFormatted( lineLength, TRUE, stdout,
313                                                 "Constraint \"%s\" not supported",
314                                                 buffer );
315                                 }
316                                 while ( token != EOF && token != SEMICOLON
317                                         && token != COLON && token != COMMA ) {
318                                         if ( iterations > 0 ) {
319                                                 strcat( temp, " " );
320                                                 strcat( temp, buffer );
321                                         }
322                                         token = getToken( buffer );
323                                 }
324                                 if ( iterations > 0 ) {
325                                         printFormatted( lineLength, TRUE, stdout,
326                                                 "Assuming \"%s\" part of query and not an unrecognised constraint.", temp );
327                                         strcat( value, "," );
328                                         strcat( value, temp );
329                                 }
330                         }
331                         break;
332
333                 }
334                 iterations--;
335         }
336         if ( *value == '\0' ) {
337                 printFormatted( lineLength, TRUE, stdout,
338                         "Value not specified" );
339                 return ERROR;
340         }
341         if ( *specifier == NULL )
342                 *specifier = SEARCH_ALL;
343         return token;
344 }
345
346 static  int processTerm( specifier, soundex, buffer, attribute, value )
347 int     specifier, soundex;
348 char    *buffer, *attribute, *value;
349
350 {
351         char    *s, *t;
352         char    query[BUFSIZ];
353         char    **reallocResult;
354
355         switch ( specifier ) {
356         case SEARCH_ALL:
357                 if ( numberOfComponents+3 >= components ) {
358                         components += 10;
359                         reallocResult = (char **)realloc(component, sizeof(char **)*components);
360                         if ( reallocResult == NULL ) {
361                                 printFormatted( lineLength, TRUE, stdout,
362                                         "Realloc failed" );
363                                 return ERROR;
364                         } else
365                                 component = reallocResult;
366                 }
367                 if ( attribute != NULL && *attribute != '\0' ) {
368                         /* The user obviously knows what they are doing */
369                         sprintf( query, "(%s%s%s)", attribute,
370                                 (soundex)?"~=":"=", buffer );
371                 } else {
372                         if ( ( s = index( buffer, ',' ) ) != NULL ) {
373                                 *s++ = '\0';
374                                 while ( *s && isspace( *s ) )
375                                         s++;
376                                 sprintf( query, "(sn%s%s)",
377                                         (soundex)?"~=":"=", buffer );
378                                 component[numberOfComponents++] = strdup( query );
379                                 /* let's just make sure there is no title */
380                                 if ( ( t = rindex( s, ',' ) ) != NULL ) {
381                                         *t++ = '\0';
382                                         while ( *t && isspace( *t ) )
383                                                 t++;
384                                         sprintf( query, "(personalTitle%s%s)",
385                                                 (soundex)?"~=":"=", t );
386                                         component[numberOfComponents++] = strdup( query );
387                                 }
388                                 sprintf( query, "%s %s", s, buffer );
389                                 strcpy( buffer, query );
390                         } else if ( strncasecmp( buffer, "first ", 6 ) == 0 ) {
391                                 sprintf( query, "%s *", &buffer[6] );
392                                 strcpy( buffer, query );
393                         }
394                         if ( ( s = index( buffer, '@' ) ) != NULL ) {
395                                 *s++ = '\0';
396                                 if ( *buffer == '\0' ) /* no username */
397                                         sprintf( query, "(mail=*@%s)", s );
398                                 else if ( *s == '\0' ) /* no host */
399                                         sprintf( query, "(|(mail=%s@*)(userid=%s))",
400                                                 buffer, buffer );
401                                 else
402                                         sprintf( query, "(mail=%s@%s)",
403                                                 buffer, s );
404                                 if ( soundex )
405                                         printFormatted( lineLength, TRUE, stdout,
406                                                 "Fuzzy matching not supported on e-mail address queries" );
407                         } else if ( index( buffer, ' ' ) == NULL ) {
408                                 sprintf( query,
409                                         "(|(sn%s%s)(userid%s%s)(l%s%s)(ou%s%s)\
410 (&(cn%s%s)(!(objectClass=person))))",
411                                         (soundex)?"~=":"=", buffer,
412                                         (soundex)?"~=":"=", buffer,
413                                         (soundex)?"~=":"=", buffer,
414                                         (soundex)?"~=":"=", buffer,
415                                         (soundex)?"~=":"=", buffer );
416                         } else {
417 #if defined(UOFA)
418                                 sprintf( query, "(|(l%s%s)(ou%s%s)(preferredName%s%s)",
419                                         (soundex)?"~=":"=", buffer,
420                                         (soundex)?"~=":"=", buffer,
421                                         (soundex)?"~=":"=", buffer );
422 #else
423                                 sprintf( query, "(|(l%s%s)(ou%s%s)",
424                                         (soundex)?"~=":"=", buffer,
425                                         (soundex)?"~=":"=", buffer );
426 #endif
427                                 /*
428                                  * If LDAP and/or Quipu didn't strip spaces
429                                  * then this would be different but as it does
430                                  * this is easy :-) but it also means we might
431                                  * get false hits.
432                                  */
433                                 if ( soundex ) {
434                                         strcat( query, "(cn~=" );
435                                         strcat( query, buffer );
436                                 } else {
437                                         strcat( query, "(cn=*" );
438                                         strcat( query, strtok( buffer, " " ) );
439                                         while ( ( s = strtok( NULL, " " ) ) != NULL ) {
440                                                 strcat( query, " * " );
441                                                 strcat( query, s );
442                                         }
443                                 }
444                                 strcat( query, "))" );
445                         }
446                 }
447                 component[numberOfComponents++] = strdup( query );
448                 break;
449
450         case ATTRIBUTE:
451                 if ( numberOfComponents+1 >= components ) {
452                         components += 10;
453                         reallocResult = (char **)realloc(component, sizeof(char **)*components);
454                         if ( reallocResult == NULL ) {
455                                 printFormatted( lineLength, TRUE, stdout,
456                                         "Realloc failed" );
457                                 return ERROR;
458                         } else
459                                 component = reallocResult;
460                 }
461                 if ( *value != '\0' ) {
462                         sprintf( query, "(%s%s%s)", buffer,
463                                 (soundex)?"~=":"=", value );
464                         component[numberOfComponents++] = strdup( query );
465                         *value = '\0';
466                 } else {
467                         if ( *attribute != '\0' ) {
468                                 sprintf( query, "(%s%s*)", attribute,
469                                         (soundex)?"~=":"=" );
470                                 component[numberOfComponents++] = strdup( query );
471                         }
472                         strcpy( attribute, buffer );
473                 }
474                 break;
475
476         case TEMPLATE:
477                 if ( numberOfComponents+1 >= components ) {
478                         components += 10;
479                         reallocResult = (char **)realloc(component, sizeof(char **)*components);
480                         if ( reallocResult == NULL ) {
481                                 printFormatted( lineLength, TRUE, stdout,
482                                         "Realloc failed" );
483                                 return ERROR;
484                         } else
485                                 component = reallocResult;
486                 }
487                 sprintf( query, "(objectClass%s%s)",
488                         (soundex)?"~=":"=", templateToObjectClass( buffer ) );
489                 component[numberOfComponents++] = strdup( query );
490                 break;
491
492         case VALUE:
493                 if ( *attribute != '\0' ) {
494                         if ( numberOfComponents+1 >= components ) {
495                                 components += 10;
496                                 reallocResult = (char **)realloc(component, sizeof(char **)*components);
497                                 if ( reallocResult == NULL ) {
498                                         printFormatted( lineLength, TRUE, stdout,
499                                                 "Realloc failed" );
500                                         return ERROR;
501                                 } else
502                                         component = reallocResult;
503                         }
504                         sprintf( query, "(%s%s%s)", attribute,
505                                 (soundex)?"~=":"=", buffer );
506                         component[numberOfComponents++] = strdup( query );
507                         *attribute = '\0';
508                 } else {
509                         if ( *value != '\0' )
510                                 printFormatted( lineLength, TRUE, stdout,
511                                         "Ignoring old value (%s)", value );
512                         strcpy( value, buffer );
513                 }
514                 break;
515
516         case HANDLE:
517                 if ( numberOfComponents+1 >= components ) {
518                         components += 10;
519                         reallocResult = (char **)realloc(component, sizeof(char **)*components);
520                         if ( reallocResult == NULL ) {
521                                 printFormatted( lineLength, TRUE, stdout,
522                                         "Realloc failed" );
523                                 return ERROR;
524                         } else
525                                 component = reallocResult;
526                 }
527                 component[numberOfComponents++] = strdup( buffer );
528                 return READ;
529
530         }
531         return SEARCH;
532 }
533
534 int     parseCommand( query )
535 char    *query;
536 {
537         /*
538          * This procedure reads the string sent by the user and breaks it
539          * down into command to execute.
540          */
541         char    buffer[BUFSIZ], attribute[BUFSIZ], objectClass[BUFSIZ],
542                 value[BUFSIZ];
543         char    **reallocResult;
544         int     command, specificName, length, token, i, j, specifier, soundex;
545         int     trace = FALSE;
546
547         switch ( command = getToken( buffer ) ) {
548         case COMMAND:
549         case CONSTRAINTS:
550         case DESCRIBE:
551         case VERSION:
552                 /* <command> */
553                 token = getToken( buffer );
554                 break;
555
556         case HELP:
557         case LIST:
558                 /* <command> [ <string> ] */
559                 if ( ( token = getToken( buffer ) ) != EOF && token != COLON ) {
560                         strcpy( query, buffer );
561                         token = getToken( buffer );
562                 } else
563                         *query = '\0';
564                 break;
565
566         case SHOW:
567                 /* "show" <string> */
568                 if ( ( token = getToken( buffer ) ) != EOF && token != COLON ) {
569                         strcpy( query, buffer );
570                         token = getToken( buffer );
571                 } else {
572                         printFormatted( lineLength, TRUE, stdout,
573                                 "Show must have a parameter" );
574                         return ERROR;
575                 }
576                 break;
577
578         default:
579                 /* <term> [ ";" <term> ] */
580                 *attribute = '\0';
581                 *value = '\0';
582                 soundex = FALSE;
583                 numberOfComponents = 0;
584                 if ( ( component = (char **)malloc(sizeof(char **)*components) ) == NULL ) {
585                         printFormatted( lineLength, TRUE, stdout,
586                                 "Malloc failed" );
587                         return ERROR;
588                 }
589                 if ( ( token = term( command, buffer, attribute, &specifier,
590                         &soundex ) ) != ERROR )
591                         command = processTerm( specifier, soundex, buffer,
592                                 attribute, value );
593                 else
594                         return ERROR;
595                 if ( token == SEMICOLON ) {
596                         if ( command == READ ) {
597                                 printFormatted( lineLength, TRUE, stdout,
598                                         "Multiple components on a Handle query not supported." );
599                                 return ERROR;
600                         }
601                         do {
602                                 soundex = FALSE;
603                                 token = getToken( buffer );
604                                 token = term( token, buffer, attribute,
605                                         &specifier, &soundex );
606                                 command = processTerm( specifier, soundex,
607                                         buffer, attribute, value );
608                                 if ( command == READ ) {
609                                         printFormatted( lineLength, TRUE, stdout,
610                                                 "Multiple components on a Handle query not supported." );
611                                         return ERROR;
612                                 } else if ( command == ERROR )
613                                         return ERROR;
614                         } while ( token == SEMICOLON );
615                 }
616                 /*
617                  * Need to tidy up outstanding single value or attribute terms
618                  */
619                 if ( *attribute != '\0' ) {
620                         if ( numberOfComponents+1 >= components ) {
621                                 components += 10;
622                                 reallocResult = (char **)realloc(component, sizeof(char **)*components);
623                                 if ( reallocResult == NULL ) {
624                                         printFormatted( lineLength, TRUE, stdout,
625                                                 "Realloc failed" );
626                                         return ERROR;
627                                 } else
628                                         component = reallocResult;
629                         }
630                         sprintf( query, "(%s%s*)", attribute,
631                                 (soundex)?"~=":"=" );
632                         component[numberOfComponents++] = strdup( query );
633                 }
634                 if ( *value != '\0' )
635                         if ( processTerm( SEARCH_ALL, soundex, value, NULL, NULL ) == ERROR )
636                                 return ERROR;
637                 if ( numberOfComponents == 0 ) {
638                         printFormatted( lineLength, TRUE, stdout,
639                                 "NULL query." );
640                         return ERROR;
641                 } else if ( numberOfComponents == 1 )
642                         strcpy( query, component[0] );
643                 else {
644                         strcpy( query, "(&" );
645                         for ( i = 0; i < numberOfComponents; i++ )
646                                 strcat( query, component[i] );
647                         strcat( query, ")" );
648                 }
649                 free( component );
650                 break;
651
652         }
653         if ( token == COLON ) { /* global constraints */
654                 do {
655                         token = getToken( buffer );
656                         switch ( token ) {
657                         case FORMAT:
658                                 if ( ( token = getToken( buffer ) ) != EQUALS ) {
659                                         printFormatted( lineLength, TRUE, stdout, "\"=\" expected" );
660                                 } else
661                                         token = getToken( buffer );
662                                 switch ( token ) {
663                                 case FULL:
664                                 case ABRIDGED:
665                                 case HANDLE:
666                                 case SUMMARY:
667                                         if ( outputFormat != NULL )
668                                                 printFormatted( lineLength, TRUE, stdout, "Only one response format can be specified." );
669                                         else
670                                                 outputFormat = token;
671                                         break;
672
673                                 default:
674                                         printFormatted( lineLength, TRUE, stdout, "Unrecognised format specifier" );
675                                 }
676                                 token = getToken( buffer );
677                                 break;
678
679                         case HOLD:
680                                 holdConnection = TRUE;
681                                 token = getToken( buffer );
682                                 break;
683
684                         case MAXHITS:
685                                 if ( ( token = getToken( buffer ) ) != EQUALS ) {
686                                         printFormatted( lineLength, TRUE, stdout, "\"=\" expected" );
687                                 } else
688                                         token = getToken( buffer );
689                                 if ( (maxHits = atoi( buffer )) < 1 
690                                         || maxHits > maximumSize ) {
691                                         printFormatted( lineLength, TRUE, stdout, "Invalid maxhits value, defaulting to %s", maximumSize );
692                                         maxHits = maximumSize;
693                                 }
694                                 token = getToken( buffer );
695                                 break;
696
697                         case LANGUAGE:
698                                 if ( ( token = getToken( buffer ) ) != EQUALS ) {
699                                         printFormatted( lineLength, TRUE, stdout, "\"=\" expected" );
700                                 } else
701                                         token = getToken( buffer );
702 /**/                            /* need to save this value and lookup locale */
703                                 printFormatted( lineLength, TRUE, stdout,
704                                         "Language not currently implemented" );
705                                 token = getToken( buffer );
706                                 break;
707
708                         case LINE_LENGTH:
709                                 if ( ( token = getToken( buffer ) ) != EQUALS ) {
710                                         printFormatted( lineLength, TRUE, stdout, "\"=\" expected" );
711                                 } else
712                                         token = getToken( buffer );
713                                 lineLength = atoi( buffer );
714                                 if ( lineLength < MIN_LINE_LENGTH
715                                         || lineLength > MAX_LINE_LENGTH ) {
716                                         printFormatted( lineLength, TRUE, stdout, "Invalid line length, using default %d", DEFAULT_LINE_LENGTH );
717                                         lineLength = DEFAULT_LINE_LENGTH;
718                                 }
719                                 token = getToken( buffer );
720                                 break;
721
722                         case TRACE:
723                                 trace = TRUE;
724                                 token = getToken( buffer );
725                                 break;
726
727                         default:
728                                 printFormatted( lineLength, TRUE, stdout, "Unrecognised global constraint \"%s\"", buffer );
729                                 while ( ( token = getToken( buffer ) ) != EOF
730                                         && token != COMMA )
731                                         ;
732                                 break;
733
734                         }
735                 } while ( token == COMMA );
736         }
737         if ( token != EOF ) {
738                 printFormatted( lineLength, TRUE, stdout,
739                         "Data following \"%s\" ignored.", buffer );
740                 while ( ( token = getToken( buffer ) ) != EOF )
741                         ;
742         }
743         if ( trace && ( command == READ || command == SEARCH ) )
744                 switch (command) {
745                 case READ:
746                         printFormatted( lineLength, TRUE, stdout,
747                                 "Attempting to read \"%s\"", query );
748                         break;
749
750                 case SEARCH:
751                         printFormatted( lineLength, TRUE, stdout,
752                                 "Searching using LDAP query %s", query );
753                         break;
754
755                 }
756         return command;
757 }