This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
91e152a5c10710441963639693028136227188c1
[perl5.git] / cpan / CPANPLUS / lib / CPANPLUS / Config.pm
1 package CPANPLUS::Config;
2
3 use strict;
4 use warnings;
5
6 use base 'Object::Accessor';
7
8 use base 'CPANPLUS::Internals::Utils';
9
10 use Config;
11 use File::Spec;
12 use Module::Load;
13 use CPANPLUS;
14 use CPANPLUS::Error;
15 use CPANPLUS::Internals::Constants;
16
17 use File::Basename              qw[dirname];
18 use IPC::Cmd                    qw[can_run];
19 use Locale::Maketext::Simple    Class => 'CPANPLUS', Style => 'gettext';
20 use Module::Load::Conditional   qw[check_install];
21
22
23 =pod
24
25 =head1 NAME
26
27 CPANPLUS::Config
28
29 =head1 SYNOPSIS
30
31     ### conf object via CPANPLUS::Backend;
32     $cb   = CPANPLUS::Backend->new;
33     $conf = $cb->configure_object;
34     
35     ### or as a standalone object
36     $conf = CPANPLUS::Configure->new;
37
38     ### values in 'conf' section
39     $verbose = $conf->get_conf( 'verbose' );    
40     $conf->set_conf( verbose => 1 );
41
42     ### values in 'program' section
43     $editor = $conf->get_program( 'editor' );
44     $conf->set_program( editor => '/bin/vi' );
45
46 =head1 DESCRIPTION
47
48 This module contains defaults and heuristics for configuration 
49 information for CPANPLUS. To change any of these values, please
50 see the documentation in C<CPANPLUS::Configure>.
51
52 Below you'll find a list of configuration types and keys, and
53 their meaning.
54
55 =head1 CONFIGURATION
56
57 =cut
58
59 ### BAH! you can't have POD interleaved with a hash
60 ### declaration.. so declare every entry separately :(
61 my $Conf = {
62     '_fetch' => {
63         'blacklist' => [ 'ftp' ],
64     },
65     
66     ### _source, _build and _mirror are supposed to be static
67     ### no changes should be needed unless pause/cpan changes
68     '_source' => {
69         'hosts'             => 'MIRRORED.BY',
70         'auth'              => '01mailrc.txt.gz',
71         'stored'            => 'sourcefiles',
72         'dslip'             => '03modlist.data.gz',
73         'update'            => '86400',
74         'mod'               => '02packages.details.txt.gz',
75         'custom_index'      => 'packages.txt',
76     },
77     '_build' => {
78         'plugins'           => 'plugins',
79         'moddir'            => 'build',
80         'startdir'          => '',
81         'distdir'           => 'dist',
82         'autobundle'        => 'autobundle',
83         'autobundle_prefix' => 'Snapshot',
84         'autdir'            => 'authors',
85         'install_log_dir'   => 'install-logs',
86         'custom_sources'    => 'custom-sources',
87         'sanity_check'      => 1,
88     },
89     '_mirror' => {
90         'base'              => 'authors/id/',
91         'auth'              => 'authors/01mailrc.txt.gz',
92         'dslip'             => 'modules/03modlist.data.gz',
93         'mod'               => 'modules/02packages.details.txt.gz'
94     },
95 };
96
97 =head2 Section 'conf'
98
99 =over 4
100
101 =item hosts
102
103 An array ref containing hosts entries to be queried for packages.
104
105 An example entry would like this:
106
107     {   'scheme' => 'ftp',
108         'path' => '/pub/CPAN/',
109         'host' => 'ftp.cpan.org'
110     },
111
112 =cut
113
114     ### default host list
115     $Conf->{'conf'}->{'hosts'} = [
116             {
117                 'scheme' => 'ftp',
118                 'path' => '/pub/CPAN/',
119                 'host' => 'ftp.cpan.org'
120             },
121             {
122                 'scheme' => 'http',
123                 'path' => '/',
124                 'host' => 'www.cpan.org'
125             },
126             {
127                 'scheme' => 'ftp',
128                 'path' => '/',
129                 'host' => 'cpan.hexten.net'
130             },
131             {
132                 'scheme' => 'ftp',
133                 'path' => '/CPAN/',
134                 'host' => 'cpan.cpantesters.org'
135             },
136             {
137                 'scheme' => 'ftp',
138                 'path' => '/pub/languages/perl/CPAN/',
139                 'host' => 'ftp.funet.fi'
140             }
141         ];
142         
143 =item allow_build_interactivity
144
145 Boolean flag to indicate whether 'perl Makefile.PL' and similar
146 are run interactively or not. Defaults to 'true'.
147
148 =cut
149
150         $Conf->{'conf'}->{'allow_build_interactivity'} = 1;
151
152 =item base
153
154 The directory CPANPLUS keeps all its build and state information in.
155 Defaults to ~/.cpanplus.
156
157 =cut
158
159        $Conf->{'conf'}->{'base'} = File::Spec->catdir(
160                                         __PACKAGE__->_home_dir, DOT_CPANPLUS );
161
162 =item buildflags
163
164 Any flags to be passed to 'perl Build.PL'. See C<perldoc Module::Build>
165 for details. Defaults to an empty string.
166
167 =cut
168
169         $Conf->{'conf'}->{'buildflags'} = '';
170
171 =item cpantest
172
173 Boolean flag to indicate whether or not to mail test results of module
174 installations to C<http://testers.cpan.org>. Defaults to 'false'.
175
176 =cut
177
178         $Conf->{'conf'}->{'cpantest'} = 0;
179
180 =item cpantest_mx
181
182 String holding an explicit mailserver to use when sending out emails
183 for C<http://testers.cpan.org>. An empty string will use your system
184 settings. Defaults to an empty string.
185
186 =cut
187
188         $Conf->{'conf'}->{'cpantest_mx'} = '';
189
190 =item debug
191
192 Boolean flag to enable or disable extensive debuggging information.
193 Defaults to 'false'.
194
195 =cut
196
197         $Conf->{'conf'}->{'debug'} = 0;
198
199 =item dist_type
200
201 Default distribution type to use when building packages. See C<cpan2dist>
202 or C<CPANPLUS::Dist> for details. An empty string will not use any 
203 package building software. Defaults to an empty string.
204
205 =cut
206
207         $Conf->{'conf'}->{'dist_type'} = '';
208
209 =item email
210
211 Email address to use for anonymous ftp access and as C<from> address
212 when sending emails. Defaults to an C<example.com> address.
213
214 =cut
215
216         $Conf->{'conf'}->{'email'} = DEFAULT_EMAIL;
217         
218 =item enable_custom_sources
219
220 Boolean flag indicating whether custom sources should be enabled or
221 not. See the C<CUSTOM MODULE SOURCES> in C<CPANPLUS::Backend> for
222 details on how to use them.
223
224 Defaults to C<true>
225
226 =cut
227
228         ### this addresses #32248 which requests a possibility to
229         ### turn off custom sources
230         $Conf->{'conf'}->{'enable_custom_sources'} = 1;
231
232 =item extractdir
233
234 String containing the directory where fetched archives should be 
235 extracted. An empty string will use a directory under your C<base>
236 directory. Defaults to an empty string.
237
238 =cut
239
240         $Conf->{'conf'}->{'extractdir'} = '';
241
242 =item fetchdir
243
244 String containing the directory where fetched archives should be 
245 stored. An empty string will use a directory under your C<base>
246 directory. Defaults to an empty string.
247
248 =cut
249
250         $Conf->{'conf'}->{'fetchdir'} = '';
251
252 =item flush
253
254 Boolean indicating whether build failures, cache dirs etc should
255 be flushed after every operation or not. Defaults to 'true'.
256
257 =cut
258
259         $Conf->{'conf'}->{'flush'} = 1;
260
261 =item force
262
263 Boolean indicating whether files should be forcefully overwritten
264 if they exist, modules should be installed when they fail tests,
265 etc. Defaults to 'false'.
266
267 =cut
268
269         $Conf->{'conf'}->{'force'} = 0;
270
271 =item lib
272
273 An array ref holding directories to be added to C<@INC> when CPANPLUS
274 starts up. Defaults to an empty array reference.
275
276 =cut
277
278         $Conf->{'conf'}->{'lib'} = [];
279
280 =item makeflags
281
282 A string holding flags that will be passed to the C<make> program
283 when invoked. Defaults to an empty string.
284
285 =cut
286
287         $Conf->{'conf'}->{'makeflags'} = '';
288
289 =item makemakerflags
290
291 A string holding flags that will be passed to C<perl Makefile.PL>
292 when invoked. Defaults to an empty string.
293
294 =cut
295
296         $Conf->{'conf'}->{'makemakerflags'} = '';
297
298 =item md5
299
300 A boolean indicating whether or not md5 checks should be done when
301 an archive is fetched. Defaults to 'true' if you have C<Digest::MD5>
302 installed, 'false' otherwise.
303
304 =cut
305
306         $Conf->{'conf'}->{'md5'} = ( 
307                             check_install( module => 'Digest::MD5' ) ? 1 : 0 );
308
309 =item no_update
310
311 A boolean indicating whether or not C<CPANPLUS>' source files should be
312 updated or not. Defaults to 'false'.
313
314 =cut
315
316         $Conf->{'conf'}->{'no_update'} = 0;
317
318 =item passive
319
320 A boolean indicating whether or not to use passive ftp connections.
321 Defaults to 'true'.
322
323 =cut
324
325         $Conf->{'conf'}->{'passive'} = 1;
326
327 =item prefer_bin
328
329 A boolean indicating whether or not to prefer command line programs 
330 over perl modules. Defaults to 'false' unless you do not have 
331 C<Compress::Zlib> installed (as that would mean we could not extract
332 C<.tar.gz> files)
333
334 =cut
335         ### if we dont have c::zlib, we'll need to use /bin/tar or we
336         ### can not extract any files. Good time to change the default
337         $Conf->{'conf'}->{'prefer_bin'} = 
338                                 (eval {require Compress::Zlib; 1} ? 0 : 1 );
339
340 =item prefer_makefile
341
342 A boolean indicating whether or not prefer a C<Makefile.PL> over a 
343 C<Build.PL> file if both are present. Defaults to 'true', unless
344 the perl version is at least 5.10.1 or appropriate versions of L<Module::Build>
345 and L<CPANPLUS::Dist::Build> are available.
346
347 =cut
348
349         $Conf->{'conf'}->{'prefer_makefile'} = 
350             ( $] >= 5.010001 or 
351               ( check_install( module => 'Module::Build', version => '0.32' ) and
352                 check_install( module => INSTALLER_BUILD, version => '0.24' ) )
353               ? 0 : 1 );
354
355 =item prereqs
356
357 A digit indicating what to do when a package you are installing has a
358 prerequisite. Options are:
359
360     0   Do not install
361     1   Install
362     2   Ask
363     3   Ignore  (dangerous, install will probably fail!)
364
365 The default is to ask.
366
367 =cut
368
369         $Conf->{'conf'}->{'prereqs'} = PREREQ_ASK;
370
371 =item shell
372
373 A string holding the shell class you wish to start up when starting
374 C<CPANPLUS> in interactive mode.
375
376 Defaults to C<CPANPLUS::Shell::Default>, the default CPANPLUS shell.
377
378 =cut
379
380         $Conf->{'conf'}->{'shell'} = 'CPANPLUS::Shell::Default';
381
382 =item show_startup_tip
383
384 A boolean indicating whether or not to show start up tips in the 
385 interactive shell. Defaults to 'true'.
386
387 =cut
388
389         $Conf->{'conf'}->{'show_startup_tip'} = 1;
390
391 =item signature
392
393 A boolean indicating whether or not check signatures if packages are
394 signed. Defaults to 'true' if you have C<gpg> or C<Crypt::OpenPGP> 
395 installed, 'false' otherwise.
396
397 =cut
398
399         $Conf->{'conf'}->{'signature'} = do {
400             check_install( module => 'Module::Signature', version => '0.06' )
401             and ( can_run('gpg') || 
402                   check_install(module => 'Crypt::OpenPGP')
403             );
404         } ? 1 : 0;
405
406 =item skiptest
407
408 A boolean indicating whether or not to skip tests when installing modules.
409 Defaults to 'false'.
410
411 =cut
412
413         $Conf->{'conf'}->{'skiptest'} = 0;
414
415 =item storable
416
417 A boolean indicating whether or not to use C<Storable> to write compiled
418 source file information to disk. This makes for faster startup and look
419 up times, but takes extra diskspace. Defaults to 'true' if you have 
420 C<Storable> installed and 'false' if you don't.
421
422 =cut
423
424        $Conf->{'conf'}->{'storable'} = 
425                         ( check_install( module => 'Storable' ) ? 1 : 0 );
426
427 =item timeout
428
429 Digit indicating the time before a fetch request times out (in seconds).
430 Defaults to 300.
431
432 =cut
433
434         $Conf->{'conf'}->{'timeout'} = 300;
435
436 =item verbose
437
438 A boolean indicating whether or not C<CPANPLUS> runs in verbose mode.
439 Defaults to 'true' if you have the environment variable 
440 C<PERL5_CPANPLUS_VERBOSE> set to true, 'false' otherwise.
441
442 It is recommended you run with verbose enabled, but it is disabled
443 for historical reasons.
444
445 =cut
446
447         $Conf->{'conf'}->{'verbose'} = $ENV{PERL5_CPANPLUS_VERBOSE} || 0;
448
449 =item write_install_log
450
451 A boolean indicating whether or not to write install logs after installing
452 a module using the interactive shell. Defaults to 'true'.
453
454
455 =cut
456
457         $Conf->{'conf'}->{'write_install_logs'} = 1;
458
459 =item source_engine
460
461 Class to use as the source engine, which is generally a subclass of
462 C<CPANPLUS::Internals::Source>. Default to C<CPANPLUS::Internals::Source::Memory>.
463
464 =cut
465
466         $Conf->{'conf'}->{'source_engine'} = DEFAULT_SOURCE_ENGINE; 
467
468 =item cpantest_reporter_args
469
470 A hashref of key => value pairs that are passed to the constructor
471 of C<Test::Reporter>. If you'd want to enable TLS for example, you'd
472 set it to:
473
474   { transport       => 'Net::SMTP::TLS',
475     transport_args  => [ User => 'Joe', Password => '123' ],
476   }  
477
478 =cut
479
480         $Conf->{'conf'}->{'cpantest_reporter_args'} = {};
481
482 =back
483     
484 =head2 Section 'program'
485
486 =cut
487
488     ### Paths get stripped of whitespace on win32 in the constructor
489     ### sudo gets emptied if there's no need for it in the constructor
490
491 =over 4
492
493 =item editor
494
495 A string holding the path to your editor of choice. Defaults to your
496 $ENV{EDITOR}, $ENV{VISUAL}, 'vi' or 'pico' programs, in that order.
497
498 =cut
499
500         $Conf->{'program'}->{'editor'} = do {
501             $ENV{'EDITOR'}  || $ENV{'VISUAL'} ||
502             can_run('vi')   || can_run('pico')
503         };
504
505 =item make
506
507 A string holding the path to your C<make> binary. Looks for the C<make>
508 program used to build perl or failing that, a C<make> in your path.
509
510 =cut
511
512         $Conf->{'program'}->{'make'} = 
513             can_run($Config{'make'}) || can_run('make');
514
515 =item pager
516
517 A string holding the path to your pager of choice. Defaults to your
518 $ENV{PAGER}, 'less' or 'more' programs, in that order.
519
520 =cut
521
522         $Conf->{'program'}->{'pager'} = 
523             $ENV{'PAGER'} || can_run('less') || can_run('more');
524
525         ### no one uses this feature anyway, and it's only working for EU::MM
526         ### and not for module::build
527         #'perl'      => '',
528
529 =item shell
530
531 A string holding the path to your login shell of choice. Defaults to your
532 $ENV{SHELL} setting, or $ENV{COMSPEC} on Windows.
533
534 =cut
535
536         $Conf->{'program'}->{'shell'} = $^O eq 'MSWin32' 
537                                         ? $ENV{COMSPEC} 
538                                         : $ENV{SHELL};
539
540 =item sudo
541
542 A string holding the path to your C<sudo> binary if your install path
543 requires super user permissions. Looks for C<sudo> in your path, or 
544 remains empty if you do not require super user permissions to install.
545
546 =cut
547
548         $Conf->{'program'}->{'sudo'} = do {
549             ### let's assume you dont need sudo,
550             ### unless one of the below criteria tells us otherwise
551             my $sudo = undef;
552             
553             ### you're a normal user, you might need sudo
554             if( $> ) {
555     
556                 ### check for all install dirs!
557                 ### you have write permissions to the installdir,
558                 ### you don't need sudo
559                 if( -w $Config{'installsitelib'} && -w $Config{'installsitebin'} ) {                    
560                     
561                     ### installsiteman3dir is a 5.8'ism.. don't check
562                     ### it on 5.6.x...            
563                     if( defined $Config{'installsiteman3dir'} ) {
564                         $sudo = -w $Config{'installsiteman3dir'} 
565                             ? undef
566                             : can_run('sudo');
567                     } else {
568                         $sudo = undef;
569                     }
570
571                 ### you have PERL_MM_OPT set to some alternate
572                 ### install place. You probably have write permissions
573                 ### to that
574                 } elsif ( $ENV{'PERL_MM_OPT'} and 
575                           $ENV{'PERL_MM_OPT'} =~ /INSTALL|LIB|PREFIX/
576                 ) {
577                     $sudo = undef;
578
579                 ### you probably don't have write permissions
580                 } else {                
581                     $sudo = can_run('sudo');
582                 }
583             }  
584             
585             ### and return the value
586             $sudo;
587         };
588
589 =item perlwrapper
590
591 A string holding the path to the C<cpanp-run-perl> utility bundled
592 with CPANPLUS, which is used to enable autoflushing in spawned processes.
593
594 =cut
595
596         ### perlwrapper that allows us to turn on autoflushing                        
597         $Conf->{'program'}->{'perlwrapper'} = sub { 
598             my $name = 'cpanp-run-perl';
599
600             my @bins = do{
601                 require Config;
602                 my $ver  = $Config::Config{version};
603                 
604                 ### if we are running with 'versiononly' enabled,
605                 ### all binaries will have the perlversion appended
606                 ### ie, cpanp will become cpanp5.9.5
607                 ### so prefer the versioned binary in that case
608                 $Config::Config{versiononly}
609                         ? ($name.$ver, $name)
610                         : ($name, $name.$ver);
611             };
612
613             ### patch from Steve Hay Fri 29 Jun 2007 14:26:02 GMT+02:00
614             ### Msg-Id: <4684FA5A.7030506@uk.radan.com>
615             ### look for files with a ".bat" extension as well on Win32
616             @bins = map { $_, "$_.bat" } @bins if $^O eq 'MSWin32';
617
618             my $path;
619             BIN: for my $bin (@bins) {
620                 
621                 ### parallel to your cpanp/cpanp-boxed
622                 my $maybe = File::Spec->rel2abs(
623                                 File::Spec->catfile( dirname($0), $bin )
624                             );        
625                 $path = $maybe and last BIN if -f $maybe;
626         
627                 ### parallel to your CPANPLUS.pm:
628                 ### $INC{cpanplus}/../bin/cpanp-run-perl
629                 $maybe = File::Spec->rel2abs(
630                             File::Spec->catfile( 
631                                 dirname($INC{'CPANPLUS.pm'}),
632                                 '..',   # lib dir
633                                 'bin',  # bin dir
634                                 $bin,   # script
635                             )
636                          );
637                 $path = $maybe and last BIN if -f $maybe;
638                          
639                 ### you installed CPANPLUS in a custom prefix,
640                 ### so go parallel to /that/. PREFIX=/tmp/cp
641                 ### would put cpanp-run-perl in /tmp/cp/bin and
642                 ### CPANPLUS.pm in
643                 ### /tmp/cp/lib/perl5/site_perl/5.8.8
644                 $maybe = File::Spec->rel2abs(
645                             File::Spec->catfile( 
646                                 dirname( $INC{'CPANPLUS.pm'} ),
647                                 '..', '..', '..', '..', # 4x updir
648                                 'bin',                  # bin dir
649                                 $bin,                   # script
650                             )
651                          );
652                 $path = $maybe and last BIN if -f $maybe;
653
654                 ### in your path -- take this one last, the
655                 ### previous two assume extracted tarballs
656                 ### or user installs
657                 ### note that we don't use 'can_run' as it's
658                 ### not an executable, just a wrapper...
659                 ### prefer anything that's found in the path paralel to your $^X
660                 for my $dir (File::Spec->rel2abs( dirname($^X) ),
661                              split(/\Q$Config::Config{path_sep}\E/, $ENV{PATH}),
662                              File::Spec->curdir, 
663                 ) {             
664
665                     ### On VMS the path could be in UNIX format, and we
666                     ### currently need it to be in VMS format
667                     $dir = VMS::Filespec::vmspath($dir) if ON_VMS;
668
669                     $maybe = File::Spec->catfile( $dir, $bin );
670                     $path = $maybe and last BIN if -f $maybe;
671                 }
672             }          
673                 
674             ### we should have a $path by now ideally, if so return it
675             return $path if defined $path;
676             
677             ### if not, warn about it and give sensible default.
678             ### XXX try to be a no-op instead then.. 
679             ### cross your fingers...
680             ### pass '-P' to perl: "run program through C 
681             ### preprocessor before compilation"
682             ### XXX using -P actually changes the way some Makefile.PLs
683             ### are executed, so don't do that... --kane
684             error(loc(
685                 "Could not find the '%1' binary in your path".
686                 "--this may be a problem.\n".
687                 "Please locate this program and set ".
688                 "your '%2' config entry to its path.\n".
689                 "From the default shell, you can do this by typing:\n\n".
690                 "  %3\n".
691                 "  %4\n",
692                 $name, 'perlwrapper', 
693                 's program perlwrapper FULL_PATH_TO_CPANP_RUN_PERL',
694                 's save'
695              ));                                        
696              return '';
697         }->();
698         
699 =back
700
701 =cut
702
703 sub new {
704     my $class   = shift;
705     my $obj     = $class->SUPER::new;
706
707     $obj->mk_accessors( keys %$Conf );
708
709     for my $acc ( keys %$Conf ) {
710         my $subobj = Object::Accessor->new;
711         $subobj->mk_accessors( keys %{$Conf->{$acc}} );
712
713         ### read in all the settings from the sub accessors;
714         for my $subacc ( $subobj->ls_accessors ) {
715             $subobj->$subacc( $Conf->{$acc}->{$subacc} );
716         }
717
718         ### now store it in the parent object
719         $obj->$acc( $subobj );
720     }
721     
722     $obj->_clean_up_paths;
723     
724     ### shut up IPC::Cmd warning about not findin IPC::Run on win32
725     $IPC::Cmd::WARN = 0;
726     
727     return $obj;
728 }
729
730 sub _clean_up_paths {
731     my $self = shift;
732
733     ### clean up paths if we are on win32
734     if( $^O eq 'MSWin32' ) {
735         for my $pgm ( $self->program->ls_accessors ) {
736             my $path = $self->program->$pgm;
737
738             ### paths with whitespace needs to be shortened
739             ### for shell outs.
740             if ($path and $path =~ /\s+/) {
741                 my($prog, $args);
742
743                 ### patch from Steve Hay, 13nd of June 2007
744                 ### msg-id: <467012A4.6060705@uk.radan.com>
745                 ### windows directories are not allowed to end with 
746                 ### a space, so any occurrence of '\w\s+/\w+' means
747                 ### we're dealing with arguments, not directory
748                 ### names.
749                 if ($path =~ /^(.*?)(\s+\/.*$)/) {
750                     ($prog, $args) = ($1, $2);
751                 
752                 ### otherwise, there are no arguments
753                 } else {
754                     ($prog, $args) = ($path, '');
755                 }
756                 
757                 $prog = Win32::GetShortPathName( $prog );
758                 $self->program->$pgm( $prog . $args );
759             }
760         }
761     }
762
763     return 1;
764 }
765
766 1;
767
768 =pod
769
770 =head1 BUG REPORTS
771
772 Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
773
774 =head1 AUTHOR
775
776 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
777
778 =head1 COPYRIGHT
779
780 The CPAN++ interface (of which this module is a part of) is copyright (c) 
781 2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
782
783 This library is free software; you may redistribute and/or modify it 
784 under the same terms as Perl itself.
785
786 =head1 SEE ALSO
787
788 L<CPANPLUS::Backend>, L<CPANPLUS::Configure::Setup>, L<CPANPLUS::Configure>
789
790 =cut
791
792 # Local variables:
793 # c-indentation-style: bsd
794 # c-basic-offset: 4
795 # indent-tabs-mode: nil
796 # End:
797 # vim: expandtab shiftwidth=4: