]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_options.c
Merge master
[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     if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
435         options->signatureopt = opt;
436
437     /* do a little checking for the domain name. */
438     if ((c = getoption(buf, "-fqdn"))) {
439         char *p = strchr(c, ':');
440         if (p)
441             *p = '\0';
442         if (gethostbyname(c)) {
443             if (p)
444                 *p = ':';
445             if ((opt = strdup(c)))
446                 options->fqdn = opt;
447         }
448         else {
449             LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
450         }
451     }
452
453     if ((c = getoption(buf, "-unixcodepage"))) {
454         if ((charset_t)-1  == ( options->unixcharset = add_charset(c)) ) {
455             options->unixcharset = CH_UNIX;
456             LOG(log_warning, logtype_afpd, "setting Unix codepage to '%s' failed", c);
457         }
458         else {
459             if ((opt = strdup(c)))
460                 options->unixcodepage = opt;
461         }
462     }
463         
464     if ((c = getoption(buf, "-maccodepage"))) {
465         if ((charset_t)-1 == ( options->maccharset = add_charset(c)) ) {
466             options->maccharset = CH_MAC;
467             LOG(log_warning, logtype_afpd, "setting Mac codepage to '%s' failed", c);
468         }
469         else {
470             if ((opt = strdup(c)))
471                 options->maccodepage = opt;
472         }
473     }
474     
475     if ((c = strstr(buf, "-closevol"))) {
476         options->closevol= 1;
477     }
478
479     if ((c = getoption(buf, "-ntdomain")) && (opt = strdup(c)))
480        options->ntdomain = opt;
481
482     if ((c = getoption(buf, "-ntseparator")) && (opt = strdup(c)))
483        options->ntseparator = opt;
484
485     if ((c = getoption(buf, "-dircachesize")))
486         options->dircachesize = atoi(c);
487      
488     if ((c = getoption(buf, "-tcpsndbuf")))
489         options->tcp_sndbuf = atoi(c);
490
491     if ((c = getoption(buf, "-tcprcvbuf")))
492         options->tcp_rcvbuf = atoi(c);
493
494         if ((c = getoption(buf, "-fcelistener"))) {
495                 LOG(log_note, logtype_afpd, "Adding fce listener \"%s\"", c);
496                 fce_add_udp_socket(c);
497         }
498         if ((c = getoption(buf, "-fcecoalesce"))) {
499                 LOG(log_note, logtype_afpd, "Fce coalesce: %s", c);
500                 fce_set_coalesce(c);
501         }
502         if ((c = getoption(buf, "-fceevents"))) {
503                 LOG(log_note, logtype_afpd, "Fce events: %s", c);
504                 fce_set_events(c);
505         }
506
507     if ((c = getoption(buf, "-fceholdfmod")))
508         options->fce_fmodwait = atoi(c);
509
510     if ((c = getoption(buf, "-mimicmodel")) && (opt = strdup(c)))
511        options->mimicmodel = opt;
512
513     if ((c = getoption(buf, "-adminauthuser")) && (opt = strdup(c)))
514        options->adminauthuser = opt;
515
516     return 1;
517 }
518
519 /*
520  * Show version information about afpd.
521  * Used by "afp -v".
522  */
523 static void show_version( void )
524 {
525         int num, i;
526
527         printf( "afpd %s - Apple Filing Protocol (AFP) daemon of Netatalk\n\n", VERSION );
528
529         puts( "This program is free software; you can redistribute it and/or modify it under" );
530         puts( "the terms of the GNU General Public License as published by the Free Software" );
531         puts( "Foundation; either version 2 of the License, or (at your option) any later" );
532         puts( "version. Please see the file COPYING for further information and details.\n" );
533
534         puts( "afpd has been compiled with support for these features:\n" );
535
536         num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
537         printf( "          AFP versions:\t" );
538         for ( i = 0; i < num; i++ ) {
539                 printf( "%d.%d ", afp_versions[ i ].av_number/10, afp_versions[ i ].av_number%10);
540         }
541         puts( "" );
542
543         printf( "         CNID backends:\t" );
544 #ifdef CNID_BACKEND_CDB
545         printf( "cdb ");
546 #endif
547 #ifdef CNID_BACKEND_DB3
548         printf( "db3 " );
549 #endif
550 #ifdef CNID_BACKEND_DBD
551 #ifdef CNID_BACKEND_DBD_TXN
552         printf( "dbd-txn " );
553 #else
554         printf( "dbd " );
555 #endif
556 #endif
557 #ifdef CNID_BACKEND_HASH
558         printf( "hash " );
559 #endif
560 #ifdef CNID_BACKEND_LAST
561         printf( "last " );
562 #endif
563 #ifdef CNID_BACKEND_MTAB
564         printf( "mtab " );
565 #endif
566 #ifdef CNID_BACKEND_TDB
567         printf( "tdb " );
568 #endif
569         puts( "" );
570 }
571
572 /*
573  * Show extended version information about afpd and Netatalk.
574  * Used by "afp -V".
575  */
576 static void show_version_extended(void )
577 {
578         show_version( );
579
580         printf( "           SLP support:\t" );
581 #ifdef USE_SRVLOC
582         puts( "Yes" );
583 #else
584         puts( "No" );
585 #endif
586
587         printf( "      Zeroconf support:\t" );
588 #ifdef USE_ZEROCONF
589         puts( "Yes" );
590 #else
591         puts( "No" );
592 #endif
593
594         printf( "  TCP wrappers support:\t" );
595 #ifdef TCPWRAP
596         puts( "Yes" );
597 #else
598         puts( "No" );
599 #endif
600
601         printf( "         Quota support:\t" );
602 #ifndef NO_QUOTA_SUPPORT
603         puts( "Yes" );
604 #else
605         puts( "No" );
606 #endif
607
608         printf( "   Admin group support:\t" );
609 #ifdef ADMIN_GRP
610         puts( "Yes" );
611 #else
612         puts( "No" );
613 #endif
614
615         printf( "    Valid shell checks:\t" );
616 #ifndef DISABLE_SHELLCHECK
617         puts( "Yes" );
618 #else
619         puts( "No" );
620 #endif
621
622         printf( "      cracklib support:\t" );
623 #ifdef USE_CRACKLIB
624         puts( "Yes" );
625 #else
626         puts( "No" );
627 #endif
628
629         printf( "           ACL support:\t" );
630 #ifdef HAVE_ACLS
631         puts( "Yes" );
632 #else
633         puts( "No" );
634 #endif
635
636         printf( "            EA support:\t" );
637         puts( EA_MODULES );
638
639         printf( "          LDAP support:\t" );
640 #ifdef HAVE_LDAP
641         puts( "Yes" );
642 #else
643         puts( "No" );
644 #endif
645 }
646
647 /*
648  * Display compiled-in default paths
649  */
650 static void show_paths( void )
651 {
652         printf( "             afpd.conf:\t%s\n", _PATH_AFPDCONF );
653         printf( "   AppleVolumes.system:\t%s\n", _PATH_AFPDSYSVOL );
654         printf( "  AppleVolumes.default:\t%s\n", _PATH_AFPDDEFVOL );
655         printf( "    afp_signature.conf:\t%s\n", _PATH_AFPDSIGCONF );
656         printf( "      afp_voluuid.conf:\t%s\n", _PATH_AFPDUUIDCONF );
657 #ifdef HAVE_LDAP
658         printf( "         afp_ldap.conf:\t%s\n", _PATH_ACL_LDAPCONF );
659 #else
660         printf( "         afp_ldap.conf:\tnot supported\n");
661 #endif
662         printf( "       UAM search path:\t%s\n", _PATH_AFPDUAMPATH );
663         printf( "  Server messages path:\t%s\n", SERVERTEXT);
664         printf( "              lockfile:\t%s\n", _PATH_AFPDLOCK);
665 }
666
667 /*
668  * Display usage information about afpd.
669  */
670 static void show_usage( char *name )
671 {
672         fprintf( stderr, "Usage:\t%s [-duptDTI] [-f defaultvolumes] [-s systemvolumes] [-n nbpname]\n", name );
673         fprintf( stderr, "\t     [-c maxconnections] [-g guest] [-P pidfile] [-S port] [-L message]\n" );
674         fprintf( stderr, "\t     [-F configfile] [-U uams] [-m umask]\n" );
675         fprintf( stderr, "\t%s -h|-v|-V\n", name );
676 }
677
678 int afp_options_parse(int ac, char **av, struct afp_options *options)
679 {
680     extern char *optarg;
681     extern int optind;
682
683     char *p;
684     char *tmp;  /* Used for error checking the result of strtol */
685     int c, err = 0;
686
687     if (gethostname(options->hostname, sizeof(options->hostname )) < 0 ) {
688         perror( "gethostname" );
689         return 0;
690     }
691     if (NULL != ( p = strchr(options->hostname, '.' )) ) {
692         *p = '\0';
693     }
694
695 #ifdef ultrix
696     if (NULL == ( p = strrchr( av[ 0 ], '/' )) ) {
697         p = av[ 0 ];
698     } else {
699         p++;
700     }
701     openlog( p, LOG_PID ); /* ultrix only */
702 #endif /* ultrix */
703
704     while (EOF != ( c = getopt( ac, av, OPTIONS )) ) {
705         switch ( c ) {
706         case 'd' :
707             options->flags |= OPTION_DEBUG;
708             break;
709         case 'n' :
710             options->server = optarg;
711             break;
712         case 'f' :
713             options->defaultvol.name = optarg;
714             break;
715         case 's' :
716             options->systemvol.name = optarg;
717             break;
718         case 'u' :
719             options->flags |= OPTION_USERVOLFIRST;
720             break;
721         case 'c' :
722             options->connections = atoi( optarg );
723             break;
724         case 'g' :
725             options->guest = optarg;
726             break;
727
728         case 'P' :
729             options->pidfile = optarg;
730             break;
731
732         case 'p':
733             options->passwdbits |= PASSWD_NOSAVE;
734             break;
735         case 't':
736             options->passwdbits |= PASSWD_SET;
737             break;
738
739         case 'D':
740             options->transports &= ~AFPTRANS_DDP;
741             break;
742         case 'S':
743             options->port = optarg;
744             break;
745         case 'T':
746             options->transports &= ~AFPTRANS_TCP;
747             break;
748         case 'L':
749             options->loginmesg = optarg;
750             break;
751         case 'F':
752             options->configfile = optarg;
753             break;
754         case 'U':
755             options->uamlist = optarg;
756             break;
757         case 'v':       /* version */
758             show_version( ); puts( "" );
759             show_paths( ); puts( "" );
760             exit( 0 );
761             break;
762         case 'V':       /* extended version */
763             show_version_extended( ); puts( "" );
764             show_paths( ); puts( "" );
765             exit( 0 );
766             break;
767         case 'h':       /* usage */
768             show_usage( p );
769             exit( 0 );
770             break;
771         case 'I':
772             options->flags |= OPTION_CUSTOMICON;
773             break;
774         case 'm':
775             options->umask = strtoul(optarg, &tmp, 8);
776             if ((options->umask > 0777)) {
777                 fprintf(stderr, "%s: out of range umask setting provided\n", p);
778                 err++;
779             }
780             if (tmp[0] != '\0') {
781                 fprintf(stderr, "%s: invalid characters in umask setting provided\n", p);
782                 err++;
783             }
784             break;
785         default :
786             err++;
787         }
788     }
789     if ( err || optind != ac ) {
790         show_usage( p );
791         exit( 2 );
792     }
793
794     return 1;
795 }