1 /*
2  * conf.c
3  *
4  * All rights reserved. Copyright (C) 1998 by NARITA Tomio.
5  * $Id: conf.c,v 1.16 2004/01/05 07:23:29 nrt Exp $
6  */
7 /*
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include <import.h>
28 #include <itable.h>
29 #include <unimap.h>
30 #include <find.h>
31 #include <display.h>
32 #include <guess.h>
33 #include <console.h>
34 #include <file.h>
35 #include <kana.h>
36 #include <decode.h>
37 #include <command.h>
38 #include <conv.h>
39 #include <uty.h>
40 #include <version.h>
41 #ifdef HAVE_SETLOCALE
42 #include <locale.h>
43 #include <guesslocale.h>
44 #endif
45 #include <begin.h>
46 #include <conf.h>
47 
48 #define DEFAULT_INPUT_CODING_SYSTEM	AUTOSELECT
49 
50 #ifdef UNIX
51 #define DEFAULT_OUTPUT_CODING_SYSTEM	EUC_JAPAN	/* ja specific */
52 #define DEFAULT_KEYBOARD_CODING_SYSTEM	EUC_JAPAN
53 #define DEFAULT_PATHNAME_CODING_SYSTEM	EUC_JAPAN
54 #define DEFAULT_DEFAULT_CODING_SYSTEM	EUC_JAPAN
55 
56 #define LV_CONF		".lv"
57 #endif /* UNIX */
58 
59 #ifdef MSDOS
60 #define DEFAULT_OUTPUT_CODING_SYSTEM	SHIFT_JIS
61 #define DEFAULT_KEYBOARD_CODING_SYSTEM	SHIFT_JIS
62 #define DEFAULT_PATHNAME_CODING_SYSTEM	SHIFT_JIS
63 #define DEFAULT_DEFAULT_CODING_SYSTEM	EUC_JAPAN
64 
65 #define LV_CONF 	"_lv"
66 #endif /* MSDOS */
67 
68 #define BUF_SIZE 	128
69 
70 #define LV_HELP		"lv.hlp"
71 /*#define LV_HELP_PATH	"/usr/local/lib/lv/"*/ /* now defined through make */
72 
73 private byte *lvHelpFile[ 2 ];
74 
ConfInitArgs(conf_t * conf)75 private void ConfInitArgs( conf_t *conf )
76 {
77 #ifdef HAVE_SETLOCALE
78   byte localeCodingSystem;
79   char dummy[6];
80   char *nl;
81   int use_locale = 1;
82 
83   nl = setlocale( LC_CTYPE, "" );
84   if (NULL == nl || !strcmp("C", nl))
85     use_locale = 0;
86   else
87     localeCodingSystem = LocaleCodingSystem(dummy);
88 #endif
89 
90   conf->file	= NULL;
91   conf->st	= NULL;
92   conf->width	= -1;
93   conf->height	= -1;
94   conf->options	= TRUE;
95   conf->inputCodingSystem	= DEFAULT_INPUT_CODING_SYSTEM;
96 #ifdef HAVE_SETLOCALE
97   if (use_locale) {
98     conf->keyboardCodingSystem	= localeCodingSystem;
99     conf->outputCodingSystem	= localeCodingSystem;
100     conf->pathnameCodingSystem	= localeCodingSystem;
101     conf->defaultCodingSystem	= localeCodingSystem;
102   } else
103 #endif
104   {
105     conf->keyboardCodingSystem	= DEFAULT_KEYBOARD_CODING_SYSTEM;
106     conf->outputCodingSystem	= DEFAULT_OUTPUT_CODING_SYSTEM;
107     conf->pathnameCodingSystem	= DEFAULT_PATHNAME_CODING_SYSTEM;
108     conf->defaultCodingSystem	= DEFAULT_DEFAULT_CODING_SYSTEM;
109   }
110   conf->keyCodingSystemVirgin	= TRUE;
111 
112 #ifndef MSDOS /* IF NOT DEFINED */
113   unicode_width_threshold = 0x3000;	/* itable_t.h */
114   unimap_iso8859 = FALSE;		/* unimap.h */
115 #endif /* MSDOS */
116 
117   casefold_search	= TRUE;		/* find.h */
118   regexp_search		= TRUE;		/* find.h */
119   carefully_divide	= TRUE;		/* display.h */
120   adjust_charset	= TRUE;		/* guess.h */
121   no_scroll		= TRUE;		/* console.h */
122 
123   allow_unify		= FALSE;	/* itable_t.h */
124   allow_ansi_esc	= FALSE;	/* console.h */
125   line_number		= FALSE;	/* conv.h */
126   grep_inverted		= FALSE;	/* conv.h */
127   kana_conv		= FALSE;	/* kana.h */
128   smooth_paging		= FALSE;	/* display.h */
129   hz_detection		= FALSE;	/* decode.h */
130 
131   ConsoleResetAnsiSequence();
132 }
133 
UnknownOption(byte * s,byte * location)134 private void UnknownOption( byte *s, byte *location )
135 {
136   fprintf( stderr, "lv: unknown option %s in %s\n", s, location );
137   exit( -1 );
138 }
139 
SetCodingSystem(byte * s,byte * codingSystem,byte * location)140 private void SetCodingSystem( byte *s, byte *codingSystem, byte *location )
141 {
142   switch( *( s + 1 ) ){
143   case 'e':
144     /*
145      * extended unix code
146      */
147     switch( *( s + 2 ) ){
148     case 'c': *codingSystem = EUC_CHINA;	break;
149     case 'j': *codingSystem = EUC_JAPAN;	break;
150     case 'k': *codingSystem = EUC_KOREA;	break;
151     case 't': *codingSystem = EUC_TAIWAN;	break;
152     default:
153       *codingSystem = EUC_JAPAN;
154     }
155     break;
156   case 'l':
157     /*
158      * iso-8859
159      */
160     switch( *( s + 2 ) ){
161     case '1': *codingSystem = ISO_8859_1;	break;
162     case '2': *codingSystem = ISO_8859_2;	break;
163     case '3': *codingSystem = ISO_8859_3;	break;
164     case '4': *codingSystem = ISO_8859_4;	break;
165     case '5': *codingSystem = ISO_8859_5;	break;
166     case '6': *codingSystem = ISO_8859_6;	break;
167     case '7': *codingSystem = ISO_8859_7;	break;
168     case '8': *codingSystem = ISO_8859_8;	break;
169     case '9': *codingSystem = ISO_8859_9;	break;
170     case '0': *codingSystem = ISO_8859_10;	break;
171     case 'b': *codingSystem = ISO_8859_11;	break;
172     case 'd': *codingSystem = ISO_8859_13;	break;
173     case 'e': *codingSystem = ISO_8859_14;	break;
174     case 'f': *codingSystem = ISO_8859_15;	break;
175     case 'g': *codingSystem = ISO_8859_16;	break;
176     default:
177       *codingSystem = ISO_8859_1;
178     }
179     break;
180   case 'c': *codingSystem = ISO_2022_CN;	break;
181   case 'j': *codingSystem = ISO_2022_JP;	break;
182   case 'k': *codingSystem = ISO_2022_KR;	break;
183   case 'm':
184   case 's': *codingSystem = SHIFT_JIS;		break;
185   case 'b': *codingSystem = BIG_FIVE;		break;
186   case 'h':
187   case 'z':
188     hz_detection = TRUE;
189     *codingSystem = HZ_GB;			break;
190 #ifndef MSDOS /* IF NOT DEFINED */
191   case 'u':
192     switch( *( s + 2 ) ){
193     case '7': *codingSystem = UTF_7;		break;
194     case '8': *codingSystem = UTF_8;		break;
195     default:
196       *codingSystem = UTF_8;
197     }
198     break;
199 #endif /* MSDOS */
200   case 'r': *codingSystem = RAW;		break;
201   default:
202     UnknownOption( s, location );
203   }
204 }
205 
SetAnsiSequence(byte * s,byte * location)206 private void SetAnsiSequence( byte *s, byte *location )
207 {
208   switch( *( s + 1 ) ){
209   case 's': ansi_standout = TokenAlloc( s + 2 ); 	break;
210   case 'r': ansi_reverse = TokenAlloc( s + 2 );		break;
211   case 'b': ansi_blink = TokenAlloc( s + 2 );		break;
212   case 'u': ansi_underline = TokenAlloc( s + 2 );	break;
213   case 'h': ansi_hilight = TokenAlloc( s + 2 );		break;
214   default:
215     UnknownOption( s, location );
216   }
217 }
218 
ConfArg(conf_t * conf,byte ** argv,byte * location)219 private void ConfArg( conf_t *conf, byte **argv, byte *location )
220 {
221   byte *s, quotationChar;
222 #ifdef HAVE_SETLOCALE
223   char dummy[6];
224 #endif
225 
226   if( TRUE == conf->options && '-' == **argv ){
227     s = *argv + 1;
228     if( 0x00 == *s )
229       conf->options = FALSE;
230     while( *s ){
231       switch( *s ){
232       case 'A':
233 	SetCodingSystem( s, &conf->inputCodingSystem, location );
234 	conf->keyboardCodingSystem = conf->outputCodingSystem =
235 	  conf->pathnameCodingSystem = conf->defaultCodingSystem =
236 	    conf->inputCodingSystem;
237 	break;
238       case 'I':
239 	if( 'a' == *( s + 1 ) )
240 	  conf->inputCodingSystem = AUTOSELECT;
241 	else
242 	  SetCodingSystem( s, &conf->inputCodingSystem, location );
243 	break;
244       case 'O':
245 #ifdef HAVE_SETLOCALE
246 	if( 'a' == *( s + 1 ) )
247 	  conf->outputCodingSystem = LocaleCodingSystem(dummy);
248 	else
249 	  SetCodingSystem( s, &conf->outputCodingSystem, location );
250 #else
251 	SetCodingSystem( s, &conf->outputCodingSystem, location );
252 #endif
253 	break;
254       case 'K':
255 	SetCodingSystem( s, &conf->keyboardCodingSystem, location );
256 	conf->keyCodingSystemVirgin = FALSE;
257 	break;
258       case 'P':
259 	SetCodingSystem( s, &conf->pathnameCodingSystem, location );
260 	break;
261       case 'D':
262 	SetCodingSystem( s, &conf->defaultCodingSystem, location );
263 	break;
264       case 'S': SetAnsiSequence( s, location ); break;
265       case 'W': conf->width = atoi( s + 1 ); break;
266       case 'H': conf->height = atoi( s + 1 ); break;
267       case 'E':
268 	if( '\'' == *( s + 1 ) ||  '"' == *( s + 1 ) ){
269 	  quotationChar = *( s + 1 );
270 	  editor_program = TokenAlloc( s + 1 );
271 	  s += 2;
272 	  while( 0x00 != *s && quotationChar != *s )
273 	    s++;
274 	} else {
275 	  editor_program = Malloc( strlen( s + 1 ) + 1 );
276 	  strcpy( editor_program, s + 1 );
277 	}
278 	break;
279 #ifndef MSDOS /* IF NOT DEFINED */
280       case 'T': unicode_width_threshold = (ic_t)atoi( s + 1 ); break;
281       case 'm': unimap_iso8859 = TRUE; s++; continue;
282 #endif /* MSDOS */
283       case 'a': adjust_charset = TRUE; s++; continue;
284       case 'c': allow_ansi_esc = TRUE; s++; continue;
285       case 'd': casefold_search = TRUE; s++; continue;
286       case 'i': casefold_search = TRUE; s++; continue;
287       case 'f': regexp_search = FALSE; s++; continue;
288       case 'g': grep_mode = TRUE; s++; continue;
289       case 'k': kana_conv = TRUE; s++; continue;
290       case 'l': carefully_divide = FALSE; s++; continue;
291       case 'n': line_number = TRUE; s++; continue;
292       case 'q': no_scroll = FALSE; s++; continue;
293       case 's': smooth_paging = TRUE; s++; continue;
294       case 'u': allow_unify = TRUE; s++; continue;
295       case 'v': grep_inverted = TRUE; s++; continue;
296       case 'z': hz_detection = TRUE; s++; continue;
297       case '+': ConfInitArgs( conf ); s++; continue;
298       case 'h': conf->file = lvHelpFile; break;
299       case 'V': Banner(); exit( 0 );
300       case SP:
301       case HT:
302 	break;
303       default:
304 	UnknownOption( s, location );
305       }
306       do {
307 	s++;
308 	if( '-' == *s || '+' == *s ){
309 	  s++;
310 	  break;
311 	}
312       } while( *s );
313     }
314   } else if( TRUE == conf->options && '+' == **argv ){
315     s = *argv + 1;
316     while( *s ){
317       switch( *s ){
318 #ifndef MSDOS /* IF NOT DEFINED */
319       case 'm': unimap_iso8859 = FALSE; s++; continue;
320 #endif /* MSDOS */
321       case 'a': adjust_charset = FALSE; s++; continue;
322       case 'c': allow_ansi_esc = FALSE; s++; continue;
323       case 'd': casefold_search = FALSE; s++; continue;
324       case 'i': casefold_search = FALSE; s++; continue;
325       case 'f': regexp_search = TRUE; s++; continue;
326       case 'g': grep_mode = FALSE; s++; continue;
327       case 'k': kana_conv = FALSE; s++; continue;
328       case 'l': carefully_divide = TRUE; s++; continue;
329       case 'n': line_number = FALSE; s++; continue;
330       case 'q': no_scroll = TRUE; s++; continue;
331       case 's': smooth_paging = FALSE; s++; continue;
332       case 'u': allow_unify = FALSE; s++; continue;
333       case 'v': grep_inverted = FALSE; s++; continue;
334       case 'z': hz_detection = FALSE; s++; continue;
335       case SP:
336       case HT:
337 	break;
338       default:
339 	UnknownOption( s, location );
340       }
341       do {
342 	s++;
343 	if( '-' == *s || '+' == *s ){
344 	  s++;
345 	  break;
346 	}
347       } while( *s );
348     }
349   } else {
350     if( TRUE == grep_mode && NULL == conf->pattern )
351       conf->pattern = *argv;
352     else if( NULL == conf->file )
353       conf->file = argv;
354   }
355 }
356 
ConfFile(conf_t * conf,byte * file)357 private void ConfFile( conf_t *conf, byte *file )
358 {
359   FILE *fp;
360   int i;
361   byte *argv[ 1 ], buf[ BUF_SIZE ];
362 
363   if( NULL == (fp = fopen( file, "r" )) )
364     return;
365 
366   while( NULL != fgets( buf, BUF_SIZE, fp ) ){
367     if( '#' == *buf )
368       continue;
369     for( i = strlen( buf ) - 1 ; i >= 0 ; i-- ){
370       if( buf[ i ] < SP )
371 	buf[ i ] = 0x00;
372       else
373 	break;
374     }
375     *argv = buf;
376     ConfArg( conf, argv, file );
377   }
378 
379   fclose( fp );
380 }
381 
Conf(conf_t * conf,byte ** argv)382 public void Conf( conf_t *conf, byte **argv )
383 {
384   byte *ptr, buf[ BUF_SIZE ];
385 
386   ConfInitArgs( conf );
387 
388   if( NULL != (ptr = getenv( "HOME" )) ){
389     strcpy( buf, ptr );
390     strcat( buf, "/" LV_CONF );
391     ConfFile( conf, buf );
392   }
393 
394 #ifdef MSDOS
395   ConfFile( conf, LV_CONF );
396 #endif
397 
398   if( NULL != (*argv = getenv( "LV" )) )
399     ConfArg( conf, argv, "environment" );
400 
401   conf->file = NULL;
402   conf->pattern = NULL;
403 
404   while( *++argv )
405     ConfArg( conf, argv, "argument" );
406 }
407 
ConfInit(byte ** argv)408 public void ConfInit( byte **argv )
409 {
410 #define helpFile	(*lvHelpFile)
411   lvHelpFile[ 1 ] = NULL;
412 
413 #ifdef MSDOS
414   {
415     int i;
416 
417     helpFile = Malloc( strlen( argv[ 0 ] ) + strlen( LV_HELP ) + 1 );
418     strcpy( helpFile, argv[ 0 ] );
419     for( i = strlen( helpFile ) - 1 ; i >= 0 ; i-- ){
420       if( '/' == helpFile[ i ] || '\\' == helpFile[ i ] ){
421 	i++;
422 	break;
423       }
424     }
425     if( i < 0 ) i = 0;
426     helpFile[ i ] = NULL;
427     strcat( helpFile, LV_HELP );
428   }
429 #else
430   helpFile = Malloc( strlen( LV_HELP_PATH "/" LV_HELP ) + 1 );
431   strcpy( helpFile, LV_HELP_PATH "/" LV_HELP );
432 #endif /* MSDOS */
433 }
434 
ConfFilename(conf_t * conf)435 public byte *ConfFilename( conf_t *conf )
436 {
437   byte *env;
438 
439   if( NULL == conf->file ){
440     if( NULL != (env = getenv( "MAN_PN" )) )
441       return env;
442     else
443       return (byte *)"(stdin)";
444   } else {
445     return *( conf->file );
446   }
447 }
448