]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_options.c
Remove bdb env on exit
[netatalk.git] / etc / afpd / afp_options.c
1 /*
2  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
3  * Copyright (c) 1990,1993 Regents of The University of Michigan.
4  * All Rights Reserved.  See COPYRIGHT.
5  *
6  * modified from main.c. this handles afp options.
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif /* HAVE_CONFIG_H */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <unistd.h>
18 #include <sys/param.h>
19 #include <sys/socket.h>
20 #include <atalk/logger.h>
21
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24
25 #ifdef HAVE_NETDB_H
26 #include <netdb.h>
27 #endif /* HAVE_NETDB_H */
28
29 #ifdef ADMIN_GRP
30 #include <grp.h>
31 #include <sys/types.h>
32 #endif /* ADMIN_GRP */
33
34 #include <atalk/paths.h>
35 #include <atalk/util.h>
36 #include <atalk/compat.h>
37 #include <atalk/globals.h>
38 #include <atalk/fce_api.h>
39
40 #include "status.h"
41 #include "auth.h"
42 #include "dircache.h"
43
44 #ifndef MIN
45 #define MIN(a, b)  ((a) < (b) ? (a) : (b))
46 #endif /* MIN */
47
48 /* FIXME CNID */
49 const char *Cnid_srv = "localhost";
50 const char *Cnid_port = "4700";
51
52 #define OPTIONS "dn:f:s:uc:g:P:ptDS:TL:F:U:hIvVm:"
53 #define LENGTH 512
54
55 /* return an option. this uses an internal array, so it's necessary
56  * to duplicate it if you want to hold it for long. this is probably
57  * non-optimal. */
58 static char *getoption(char *buf, const char *option)
59 {
60     static char string[LENGTH + 1];
61     char *end;
62     int len;
63
64     if (option && (buf = strstr(buf, option)))
65         buf = strpbrk(buf, " \t");
66
67     while (buf && isspace(*buf))
68         buf++;
69
70     if (!buf)
71         return NULL;
72
73     /* search for any quoted stuff */
74     if (*buf == '"' && (end = strchr(buf + 1, '"'))) {
75         buf++;
76         len = MIN(end - buf, LENGTH);
77     } else if ((end = strpbrk(buf, " \t\n"))) /* option or eoln */
78         len = MIN(end - buf, LENGTH);
79     else
80         len = MIN(strlen(buf), LENGTH);
81
82     strncpy(string, buf, len);
83     string[len] = '\0';
84     return string;
85 }
86
87 /* get rid of any allocated afp_option buffers. */
88 void afp_options_free(struct afp_options *opt,
89                       const struct afp_options *save)
90 {
91     if (opt->defaultvol.name && (opt->defaultvol.name != save->defaultvol.name))
92         free(opt->defaultvol.name);
93     if (opt->defaultvol.full_name && (opt->defaultvol.full_name != save->defaultvol.full_name))
94         free(opt->defaultvol.full_name);
95
96     if (opt->systemvol.name && (opt->systemvol.name != save->systemvol.name))
97         free(opt->systemvol.name);
98     if (opt->systemvol.full_name && (opt->systemvol.full_name != save->systemvol.full_name))
99         free(opt->systemvol.full_name);
100
101     if (opt->uservol.name && (opt->uservol.name != save->uservol.name))
102         free(opt->uservol.name);
103     if (opt->uservol.full_name && (opt->uservol.full_name != save->uservol.full_name))
104         free(opt->uservol.full_name);
105
106     if (opt->loginmesg && (opt->loginmesg != save->loginmesg))
107         free(opt->loginmesg);
108     if (opt->guest && (opt->guest != save->guest))
109         free(opt->guest);
110     if (opt->server && (opt->server != save->server))
111         free(opt->server);
112     if (opt->ipaddr && (opt->ipaddr != save->ipaddr))
113         free(opt->ipaddr);
114     if (opt->port && (opt->port != save->port))
115         free(opt->port);
116     if (opt->fqdn && (opt->fqdn != save->fqdn))
117         free(opt->fqdn);
118     if (opt->uampath && (opt->uampath != save->uampath))
119         free(opt->uampath);
120     if (opt->uamlist && (opt->uamlist != save->uamlist))
121         free(opt->uamlist);
122     if (opt->passwdfile && (opt->passwdfile != save->passwdfile))
123         free(opt->passwdfile);
124     if (opt->signatureopt && (opt->signatureopt != save->signatureopt))
125         free(opt->signatureopt);
126     if (opt->k5service && (opt->k5service != save->k5service))
127         free(opt->k5service);
128     if (opt->k5realm && (opt->k5realm != save->k5realm))
129         free(opt->k5realm);
130     if (opt->k5keytab && (opt->k5keytab != save->k5keytab))
131         free(opt->k5keytab);
132     if (opt->unixcodepage && (opt->unixcodepage != save->unixcodepage))
133         free(opt->unixcodepage);
134     if (opt->maccodepage && (opt->maccodepage != save->maccodepage))
135         free(opt->maccodepage);
136
137     if (opt->ntdomain && (opt->ntdomain != save->ntdomain))
138         free(opt->ntdomain);
139     if (opt->ntseparator && (opt->ntseparator != save->ntseparator))
140         free(opt->ntseparator);
141     if (opt->logconfig && (opt->logconfig != save->logconfig))
142         free(opt->logconfig);
143         if (opt->mimicmodel && (opt->mimicmodel != save->mimicmodel))
144         free(opt->mimicmodel);
145         if (opt->adminauthuser && (opt->adminauthuser != save->adminauthuser))
146         free(opt->adminauthuser);
147 }
148
149 /* initialize options */
150 void afp_options_init(struct afp_options *options)
151 {
152     memset(options, 0, sizeof(struct afp_options));
153     options->connections = 20;
154     options->pidfile = _PATH_AFPDLOCK;
155     options->defaultvol.name = _PATH_AFPDDEFVOL;
156     options->systemvol.name = _PATH_AFPDSYSVOL;
157     options->configfile = _PATH_AFPDCONF;
158     options->sigconffile = _PATH_AFPDSIGCONF;
159     options->uuidconf = _PATH_AFPDUUIDCONF;
160     options->uampath = _PATH_AFPDUAMPATH;
161     options->uamlist = "uams_dhx.so,uams_dhx2.so";
162     options->guest = "nobody";
163     options->loginmesg = "";
164     options->transports = AFPTRANS_TCP; /*  TCP only */
165     options->passwdfile = _PATH_AFPDPWFILE;
166     options->tickleval = 30;
167     options->timeout = 4;       /* 4 tickles = 2 minutes */
168     options->sleep = 10 * 60 * 2; /* 10 h in 30 seconds tick */
169     options->disconnected = 10 * 60 * 2; /* 10 h in 30 seconds tick */
170     options->server_notif = 1;
171     options->authprintdir = NULL;
172     options->signatureopt = "auto";
173     options->umask = 0;
174 #ifdef ADMIN_GRP
175     options->admingid = 0;
176 #endif /* ADMIN_GRP */
177     options->k5service = NULL;
178     options->k5realm = NULL;
179     options->k5keytab = NULL;
180     options->unixcharset = CH_UNIX;
181     options->unixcodepage = "LOCALE";
182     options->maccharset = CH_MAC;
183     options->maccodepage = "MAC_ROMAN";
184     options->volnamelen = 80; /* spec: 255, 10.1: 73, 10.4/10.5: 80 */
185     options->ntdomain = NULL;
186     options->ntseparator = NULL;
187 #ifdef USE_SRVLOC
188     /* don't advertize slp by default */
189     options->flags |= OPTION_NOSLP;
190 #endif
191     options->dircachesize = DEFAULT_MAX_DIRCACHE_SIZE;
192     options->flags |= OPTION_ACL2MACCESS;
193     options->flags |= OPTION_UUID;
194     options->tcp_sndbuf = 0;    /* 0 means don't change OS default */
195     options->tcp_rcvbuf = 0;    /* 0 means don't change OS default */
196     options->dsireadbuf = 12;
197         options->mimicmodel = NULL;
198     options->fce_fmodwait = 60; /* put fmod events 60 seconds on hold */
199     options->adminauthuser = NULL;
200 }
201
202 /* parse an afpd.conf line. i'm doing it this way because it's
203  * easy. it is, however, massively hokey. sample afpd.conf:
204  * server:AFPServer@zone -loginmesg "blah blah blah" -nodsi 
205  * "private machine"@zone2 -noguest -port 11012
206  * server2 -nocleartxt -nodsi
207  *
208  * NOTE: this ignores unknown options 
209  */
210 int afp_options_parseline(char *buf, struct afp_options *options)
211 {
212     char *c, *opt;
213
214     /* handle server */
215     if (*buf != '-' && (c = getoption(buf, NULL)) && (opt = strdup(c)))
216         options->server = opt;
217
218     /* parse toggles */
219     if (strstr(buf, " -nodebug"))
220         options->flags &= ~OPTION_DEBUG;
221 #ifdef USE_SRVLOC
222     if (strstr(buf, " -slp"))
223         options->flags &= ~OPTION_NOSLP;
224 #endif
225 #ifdef USE_ZEROCONF
226     if (strstr(buf, " -nozeroconf"))
227         options->flags |= OPTION_NOZEROCONF;
228 #endif
229     if (strstr(buf, " -nouservolfirst"))
230         options->flags &= ~OPTION_USERVOLFIRST;
231     if (strstr(buf, " -uservolfirst"))
232         options->flags |= OPTION_USERVOLFIRST;
233     if (strstr(buf, " -nouservol"))
234         options->flags |= OPTION_NOUSERVOL;
235     if (strstr(buf, " -uservol"))
236         options->flags &= ~OPTION_NOUSERVOL;
237     if (strstr(buf, " -proxy"))
238         options->flags |= OPTION_PROXY;
239     if (strstr(buf, " -noicon"))
240         options->flags &= ~OPTION_CUSTOMICON;
241     if (strstr(buf, " -icon"))
242         options->flags |= OPTION_CUSTOMICON;
243     if (strstr(buf, " -advertise_ssh"))
244         options->flags |= OPTION_ANNOUNCESSH;
245     if (strstr(buf, " -noacl2maccess"))
246         options->flags &= ~OPTION_ACL2MACCESS;
247     if (strstr(buf, " -keepsessions")) {
248         default_options.flags |= OPTION_KEEPSESSIONS;
249         options->flags |= OPTION_KEEPSESSIONS;
250     }
251
252     /* passwd bits */
253     if (strstr(buf, " -nosavepassword"))
254         options->passwdbits |= PASSWD_NOSAVE;
255     if (strstr(buf, " -savepassword"))
256         options->passwdbits &= ~PASSWD_NOSAVE;
257     if (strstr(buf, " -nosetpassword"))
258         options->passwdbits &= ~PASSWD_SET;
259     if (strstr(buf, " -setpassword"))
260         options->passwdbits |= PASSWD_SET;
261
262     /* transports */
263     if (strstr(buf, " -transall"))
264         options->transports = AFPTRANS_ALL;
265     if (strstr(buf, " -notransall"))
266         options->transports = AFPTRANS_NONE;
267     if (strstr(buf, " -tcp"))
268         options->transports |= AFPTRANS_TCP;
269     if (strstr(buf, " -notcp"))
270         options->transports &= ~AFPTRANS_TCP;
271     if (strstr(buf, " -ddp"))
272         options->transports |= AFPTRANS_DDP;
273     if (strstr(buf, " -noddp"))
274         options->transports &= ~AFPTRANS_DDP;
275     if (strstr(buf, "-client_polling"))
276         options->server_notif = 0;
277
278     /* figure out options w/ values. currently, this will ignore the setting
279      * if memory is lacking. */
280
281     if ((c = getoption(buf, "-hostname"))) {
282         int len = strlen (c);
283         if (len <= MAXHOSTNAMELEN) {
284             memcpy(options->hostname, c, len);
285             options->hostname[len] = 0;
286         }
287         else
288             LOG(log_info, logtype_afpd, "WARNING: hostname %s is too long (%d)",c,len);
289     }
290
291     if ((c = getoption(buf, "-defaultvol")) && (opt = strdup(c)))
292         options->defaultvol.name = opt;
293     if ((c = getoption(buf, "-systemvol")) && (opt = strdup(c)))
294         options->systemvol.name = opt;
295     if ((c = getoption(buf, "-loginmesg")) && (opt = strdup(c))) {
296         int i = 0, j = 0;
297         while (c[i]) {
298             if (c[i] != '\\') {
299                 opt[j++] = c[i];
300             } else {
301                 i++;
302                 if (c[i] == 'n')
303                     opt[j++] = '\n';
304             }
305             i++;
306         }
307         opt[j] = 0;
308         options->loginmesg = opt;
309         
310     }
311     if ((c = getoption(buf, "-guestname")) && (opt = strdup(c)))
312         options->guest = opt;
313     if ((c = getoption(buf, "-passwdfile")) && (opt = strdup(c)))
314         options->passwdfile = opt;
315     if ((c = getoption(buf, "-passwdminlen")))
316         options->passwdminlen = MIN(1, atoi(c));
317     if ((c = getoption(buf, "-loginmaxfail")))
318         options->loginmaxfail = atoi(c);
319     if ((c = getoption(buf, "-tickleval"))) {
320         options->tickleval = atoi(c);
321         if (options->tickleval <= 0) {
322             options->tickleval = 30;
323         }
324     }
325     if ((c = getoption(buf, "-timeout"))) {
326         options->timeout = atoi(c);
327         if (options->timeout <= 0) {
328             options->timeout = 4;
329         }
330     }
331
332     if ((c = getoption(buf, "-sleep"))) {
333         options->disconnected = options->sleep = atoi(c) * 120;
334         if (options->sleep <= 4) {
335             options->disconnected = options->sleep = 4;
336         }
337     }
338
339     if ((c = getoption(buf, "-dsireadbuf"))) {
340         options->dsireadbuf = atoi(c);
341         if (options->dsireadbuf < 6)
342             options->dsireadbuf = 6;
343     }
344
345     if ((c = getoption(buf, "-server_quantum")))
346         options->server_quantum = strtoul(c, NULL, 0);
347
348     if ((c = getoption(buf, "-volnamelen"))) {
349         options->volnamelen = atoi(c);
350         if (options->volnamelen < 8) {
351             options->volnamelen = 8; /* max mangled volname "???#FFFF" */
352         }
353         if (options->volnamelen > 255) {
354             options->volnamelen = 255; /* AFP3 spec */
355         }
356     }
357
358     /* -[no]setuplog <logtype> <loglevel> [<filename>]*/
359     c = buf;
360     /* Now THIS is hokey! Multiple occurrences are not supported by our current code, */
361     /* so I have to loop myself. */
362     while (NULL != (c = strstr(c, "-setuplog"))) {
363         char *optstr;
364         if ((optstr = getoption(c, "-setuplog"))) {
365             /* hokey2: options->logconfig must be converted to store an array of logstrings */
366             if (options->logconfig)
367                 free(options->logconfig);
368             options->logconfig = strdup(optstr);
369             setuplog(optstr);
370             c += sizeof("-setuplog");
371         }
372     }
373
374     if ((c = getoption(buf, "-unsetuplog")))
375       unsetuplog(c);
376
377 #ifdef ADMIN_GRP
378     if ((c = getoption(buf, "-admingroup"))) {
379         struct group *gr = getgrnam(c);
380         if (gr != NULL) {
381             options->admingid = gr->gr_gid;
382         }
383     }
384 #endif /* ADMIN_GRP */
385
386     if ((c = getoption(buf, "-k5service")) && (opt = strdup(c)))
387         options->k5service = opt;
388     if ((c = getoption(buf, "-k5realm")) && (opt = strdup(c)))
389         options->k5realm = opt;
390     if ((c = getoption(buf, "-k5keytab"))) {
391         if ( NULL == (options->k5keytab = (char *) malloc(sizeof(char)*(strlen(c)+14)) )) {
392                 LOG(log_error, logtype_afpd, "malloc failed");
393                 exit(-1);
394         }
395         snprintf(options->k5keytab, strlen(c)+14, "KRB5_KTNAME=%s", c);
396         putenv(options->k5keytab);
397         /* setenv( "KRB5_KTNAME", c, 1 ); */
398     }
399     if ((c = getoption(buf, "-authprintdir")) && (opt = strdup(c)))
400         options->authprintdir = opt;
401     if ((c = getoption(buf, "-uampath")) && (opt = strdup(c)))
402         options->uampath = opt;
403     if ((c = getoption(buf, "-uamlist")) && (opt = strdup(c)))
404         options->uamlist = opt;
405
406     if ((c = getoption(buf, "-ipaddr"))) {
407 #if 0
408         struct in_addr inaddr;
409         if (inet_aton(c, &inaddr) && (opt = strdup(c))) {
410             if (!gethostbyaddr((const char *) &inaddr, sizeof(inaddr), AF_INET))
411                 LOG(log_info, logtype_afpd, "WARNING: can't find %s", opt);
412             options->ipaddr = opt;
413         }
414         else {
415             LOG(log_error, logtype_afpd, "Error parsing -ipaddr, is %s in numbers-and-dots notation?", c);
416         }
417 #endif
418         options->ipaddr = strdup(c);
419     }
420
421     /* FIXME CNID Cnid_srv is a server attribute */
422     if ((c = getoption(buf, "-cnidserver"))) {
423         char *p = strrchr(c, ':');
424         if (p)
425             *p = 0;
426         Cnid_srv = strdup(c);
427         if (p)
428             Cnid_port = strdup(p + 1);
429         LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", Cnid_srv, Cnid_port);
430     }
431
432     if ((c = getoption(buf, "-port")))
433         options->port = strdup(c);
434 #ifndef NO_DDP
435     if ((c = getoption(buf, "-ddpaddr")))
436         atalk_aton(c, &options->ddpaddr);
437 #endif
438     if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
439         options->signatureopt = opt;
440
441     /* do a little checking for the domain name. */
442     if ((c = getoption(buf, "-fqdn"))) {
443         char *p = strchr(c, ':');
444         if (p)
445             *p = '\0';
446         if (gethostbyname(c)) {
447             if (p)
448                 *p = ':';
449             if ((opt = strdup(c)))
450                 options->fqdn = opt;
451         }
452         else {
453             LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
454         }
455     }
456
457     if ((c = getoption(buf, "-unixcodepage"))) {
458         if ((charset_t)-1  == ( options->unixcharset = add_charset(c)) ) {
459             options->unixcharset = CH_UNIX;
460             LOG(log_warning, logtype_afpd, "setting Unix codepage to '%s' failed", c);
461         }
462         else {
463             if ((opt = strdup(c)))
464                 options->unixcodepage = opt;
465         }
466     }
467         
468     if ((c = getoption(buf, "-maccodepage"))) {
469         if ((charset_t)-1 == ( options->maccharset = add_charset(c)) ) {
470             options->maccharset = CH_MAC;
471             LOG(log_warning, logtype_afpd, "setting Mac codepage to '%s' failed", c);
472         }
473         else {
474             if ((opt = strdup(c)))
475                 options->maccodepage = opt;
476         }
477     }
478     
479     if ((c = strstr(buf, "-closevol"))) {
480         options->closevol= 1;
481     }
482
483     if ((c = getoption(buf, "-ntdomain")) && (opt = strdup(c)))
484        options->ntdomain = opt;
485
486     if ((c = getoption(buf, "-ntseparator")) && (opt = strdup(c)))
487        options->ntseparator = opt;
488
489     if ((c = getoption(buf, "-dircachesize")))
490         options->dircachesize = atoi(c);
491      
492     if ((c = getoption(buf, "-tcpsndbuf")))
493         options->tcp_sndbuf = atoi(c);
494
495     if ((c = getoption(buf, "-tcprcvbuf")))
496         options->tcp_rcvbuf = atoi(c);
497
498         if ((c = getoption(buf, "-fcelistener"))) {
499                 LOG(log_note, logtype_afpd, "Adding fce listener \"%s\"", c);
500                 fce_add_udp_socket(c);
501         }
502         if ((c = getoption(buf, "-fcecoalesce"))) {
503                 LOG(log_note, logtype_afpd, "Fce coalesce: %s", c);
504                 fce_set_coalesce(c);
505         }
506         if ((c = getoption(buf, "-fceevents"))) {
507                 LOG(log_note, logtype_afpd, "Fce events: %s", c);
508                 fce_set_events(c);
509         }
510
511     if ((c = getoption(buf, "-fceholdfmod")))
512         options->fce_fmodwait = atoi(c);
513
514     if ((c = getoption(buf, "-mimicmodel")) && (opt = strdup(c)))
515        options->mimicmodel = opt;
516
517     if ((c = getoption(buf, "-adminauthuser")) && (opt = strdup(c)))
518        options->adminauthuser = opt;
519
520     return 1;
521 }
522
523 /*
524  * Show version information about afpd.
525  * Used by "afp -v".
526  */
527 static void show_version( void )
528 {
529         int num, i;
530
531         printf( "afpd %s - Apple Filing Protocol (AFP) daemon of Netatalk\n\n", VERSION );
532
533         puts( "This program is free software; you can redistribute it and/or modify it under" );
534         puts( "the terms of the GNU General Public License as published by the Free Software" );
535         puts( "Foundation; either version 2 of the License, or (at your option) any later" );
536         puts( "version. Please see the file COPYING for further information and details.\n" );
537
538         puts( "afpd has been compiled with support for these features:\n" );
539
540         num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
541         printf( "          AFP versions:\t" );
542         for ( i = 0; i < num; i++ ) {
543                 printf( "%d.%d ", afp_versions[ i ].av_number/10, afp_versions[ i ].av_number%10);
544         }
545         puts( "" );
546
547         printf( "DDP(AppleTalk) Support:\t" );
548 #ifdef NO_DDP
549         puts( "No" );
550 #else
551         puts( "Yes" );
552 #endif
553
554         printf( "         CNID backends:\t" );
555 #ifdef CNID_BACKEND_CDB
556         printf( "cdb ");
557 #endif
558 #ifdef CNID_BACKEND_DB3
559         printf( "db3 " );
560 #endif
561 #ifdef CNID_BACKEND_DBD
562 #ifdef CNID_BACKEND_DBD_TXN
563         printf( "dbd-txn " );
564 #else
565         printf( "dbd " );
566 #endif
567 #endif
568 #ifdef CNID_BACKEND_HASH
569         printf( "hash " );
570 #endif
571 #ifdef CNID_BACKEND_LAST
572         printf( "last " );
573 #endif
574 #ifdef CNID_BACKEND_MTAB
575         printf( "mtab " );
576 #endif
577 #ifdef CNID_BACKEND_TDB
578         printf( "tdb " );
579 #endif
580         puts( "" );
581 }
582
583 /*
584  * Show extended version information about afpd and Netatalk.
585  * Used by "afp -V".
586  */
587 static void show_version_extended(void )
588 {
589         show_version( );
590
591         printf( "           SLP support:\t" );
592 #ifdef USE_SRVLOC
593         puts( "Yes" );
594 #else
595         puts( "No" );
596 #endif
597
598         printf( "      Zeroconf support:\t" );
599 #ifdef USE_ZEROCONF
600         puts( "Yes" );
601 #else
602         puts( "No" );
603 #endif
604
605         printf( "  TCP wrappers support:\t" );
606 #ifdef TCPWRAP
607         puts( "Yes" );
608 #else
609         puts( "No" );
610 #endif
611
612         printf( "         Quota support:\t" );
613 #ifndef NO_QUOTA_SUPPORT
614         puts( "Yes" );
615 #else
616         puts( "No" );
617 #endif
618
619         printf( "   Admin group support:\t" );
620 #ifdef ADMIN_GRP
621         puts( "Yes" );
622 #else
623         puts( "No" );
624 #endif
625
626         printf( "    Valid shell checks:\t" );
627 #ifndef DISABLE_SHELLCHECK
628         puts( "Yes" );
629 #else
630         puts( "No" );
631 #endif
632
633         printf( "      cracklib support:\t" );
634 #ifdef USE_CRACKLIB
635         puts( "Yes" );
636 #else
637         puts( "No" );
638 #endif
639
640         printf( "        Dropbox kludge:\t" );
641 #ifdef DROPKLUDGE
642         puts( "Yes" );
643 #else
644         puts( "No" );
645 #endif
646
647         printf( "  Force volume uid/gid:\t" );
648 #ifdef FORCE_UIDGID
649         puts( "Yes" );
650 #else
651         puts( "No" );
652 #endif
653
654         printf( "            EA support:\t" );
655         puts( EA_MODULES );
656
657         printf( "           ACL support:\t" );
658 #ifdef HAVE_ACLS
659         puts( "Yes" );
660 #else
661         puts( "No" );
662 #endif
663
664         printf( "          LDAP support:\t" );
665 #ifdef HAVE_LDAP
666         puts( "Yes" );
667 #else
668         puts( "No" );
669 #endif
670 }
671
672 /*
673  * Display compiled-in default paths
674  */
675 static void show_paths( void )
676 {
677         printf( "             afpd.conf:\t%s\n", _PATH_AFPDCONF );
678         printf( "   AppleVolumes.system:\t%s\n", _PATH_AFPDSYSVOL );
679         printf( "  AppleVolumes.default:\t%s\n", _PATH_AFPDDEFVOL );
680         printf( "    afp_signature.conf:\t%s\n", _PATH_AFPDSIGCONF );
681         printf( "      afp_voluuid.conf:\t%s\n", _PATH_AFPDUUIDCONF );
682 #ifdef HAVE_LDAP
683         printf( "         afp_ldap.conf:\t%s\n", _PATH_ACL_LDAPCONF );
684 #else
685         printf( "         afp_ldap.conf:\tnot supported\n");
686 #endif
687         printf( "       UAM search path:\t%s\n", _PATH_AFPDUAMPATH );
688         printf( "  Server messages path:\t%s\n", SERVERTEXT);
689         printf( "              lockfile:\t%s\n", _PATH_AFPDLOCK);
690 }
691
692 /*
693  * Display usage information about afpd.
694  */
695 static void show_usage( char *name )
696 {
697         fprintf( stderr, "Usage:\t%s [-duptDTI] [-f defaultvolumes] [-s systemvolumes] [-n nbpname]\n", name );
698         fprintf( stderr, "\t     [-c maxconnections] [-g guest] [-P pidfile] [-S port] [-L message]\n" );
699         fprintf( stderr, "\t     [-F configfile] [-U uams] [-m umask]\n" );
700         fprintf( stderr, "\t%s -h|-v|-V\n", name );
701 }
702
703 int afp_options_parse(int ac, char **av, struct afp_options *options)
704 {
705     extern char *optarg;
706     extern int optind;
707
708     char *p;
709     char *tmp;  /* Used for error checking the result of strtol */
710     int c, err = 0;
711
712     if (gethostname(options->hostname, sizeof(options->hostname )) < 0 ) {
713         perror( "gethostname" );
714         return 0;
715     }
716     if (NULL != ( p = strchr(options->hostname, '.' )) ) {
717         *p = '\0';
718     }
719
720 #ifdef ultrix
721     if (NULL == ( p = strrchr( av[ 0 ], '/' )) ) {
722         p = av[ 0 ];
723     } else {
724         p++;
725     }
726     openlog( p, LOG_PID ); /* ultrix only */
727 #endif /* ultrix */
728
729     while (EOF != ( c = getopt( ac, av, OPTIONS )) ) {
730         switch ( c ) {
731         case 'd' :
732             options->flags |= OPTION_DEBUG;
733             break;
734         case 'n' :
735             options->server = optarg;
736             break;
737         case 'f' :
738             options->defaultvol.name = optarg;
739             break;
740         case 's' :
741             options->systemvol.name = optarg;
742             break;
743         case 'u' :
744             options->flags |= OPTION_USERVOLFIRST;
745             break;
746         case 'c' :
747             options->connections = atoi( optarg );
748             break;
749         case 'g' :
750             options->guest = optarg;
751             break;
752
753         case 'P' :
754             options->pidfile = optarg;
755             break;
756
757         case 'p':
758             options->passwdbits |= PASSWD_NOSAVE;
759             break;
760         case 't':
761             options->passwdbits |= PASSWD_SET;
762             break;
763
764         case 'D':
765             options->transports &= ~AFPTRANS_DDP;
766             break;
767         case 'S':
768             options->port = optarg;
769             break;
770         case 'T':
771             options->transports &= ~AFPTRANS_TCP;
772             break;
773         case 'L':
774             options->loginmesg = optarg;
775             break;
776         case 'F':
777             options->configfile = optarg;
778             break;
779         case 'U':
780             options->uamlist = optarg;
781             break;
782         case 'v':       /* version */
783             show_version( ); puts( "" );
784             show_paths( ); puts( "" );
785             exit( 0 );
786             break;
787         case 'V':       /* extended version */
788             show_version_extended( ); puts( "" );
789             show_paths( ); puts( "" );
790             exit( 0 );
791             break;
792         case 'h':       /* usage */
793             show_usage( p );
794             exit( 0 );
795             break;
796         case 'I':
797             options->flags |= OPTION_CUSTOMICON;
798             break;
799         case 'm':
800             options->umask = strtoul(optarg, &tmp, 8);
801             if ((options->umask > 0777)) {
802                 fprintf(stderr, "%s: out of range umask setting provided\n", p);
803                 err++;
804             }
805             if (tmp[0] != '\0') {
806                 fprintf(stderr, "%s: invalid characters in umask setting provided\n", p);
807                 err++;
808             }
809             break;
810         default :
811             err++;
812         }
813     }
814     if ( err || optind != ac ) {
815         show_usage( p );
816         exit( 2 );
817     }
818
819     return 1;
820 }