Annotation of embedaddon/mpd/src/main.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * main.c
                      3:  *
                      4:  * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
                      5:  * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
                      6:  * See ``COPYRIGHT.iij''
                      7:  * 
                      8:  * Rewritten by Archie Cobbs <archie@freebsd.org>
                      9:  * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
                     10:  * See ``COPYRIGHT.whistle''
                     11:  */
                     12: 
                     13: #include "ppp.h"
                     14: #include "mp.h"
                     15: #include "iface.h"
                     16: #include "command.h"
                     17: #include "console.h"
                     18: #ifndef NOWEB
                     19: #include "web.h"
                     20: #endif
                     21: #include "radsrv.h"
                     22: #include "ngfunc.h"
                     23: #include "util.h"
                     24: #include "ippool.h"
                     25: #ifdef CCP_MPPC
                     26: #include "ccp_mppc.h"
                     27: #endif
                     28: 
1.1.1.3 ! misho      29: #ifdef USE_BACKTRACE
        !            30: #include <execinfo.h>
        !            31: #endif
1.1       misho      32: #include <netgraph.h>
                     33: 
                     34: /*
                     35:  * DEFINITIONS
                     36:  */
                     37: 
                     38:   /* Implied system name when none specified on the command line */
                     39:   #define DEFAULT_CONF "default"
                     40:   #define STARTUP_CONF "startup"
                     41: 
                     42:   #define MAX_ARGS     50
                     43: 
                     44:   struct option {
                     45:     short      n_args; 
                     46:     char       sflag;
                     47:     const char *lflag;
                     48:     const char *usage;
                     49:     const char *desc;
                     50:   };
                     51:   typedef struct option        *Option;
                     52: 
1.1.1.3 ! misho      53:   static const char            *UsageStr = "[options] [configuration]";
1.1       misho      54:   static struct option         OptList[] = {
                     55:     { 0, 'b',  "background",   "",
                     56:                                "Run as a background daemon"    },
                     57:     { 1, 'd',  "directory",    "config-dir",
                     58:                                "Set config file directory"     },
                     59:     { 0, 'k',  "kill",         "",
                     60:                                "Kill running mpd process before start" },
                     61:     { 1, 'f',  "file",         "config-file",
                     62:                                "Set configuration file"        },
                     63:     { 0, 'o',  "one-shot",     "",
                     64:                                "Terminate daemon after last link shutdown"     },
                     65:     { 1, 'p',  "pidfile",      "filename",
                     66:                                "Set PID filename"              },
                     67: #ifdef SYSLOG_FACILITY
                     68:     { 1, 's',  "syslog-ident", "ident",
                     69:                                "Identifier to use for syslog"  },
                     70: #endif
1.1.1.2   misho      71: #ifdef USE_PAM
                     72:     { 1, 'm',  "pam-service",  "service",
                     73:                                "PAM service name"      },
                     74: #endif
1.1       misho      75:     { 0, 'v',  "version",      "",
                     76:                                "Show version information"      },
                     77:     { 0, 'h',  "help",         "",
                     78:                                "Show usage information"        },
                     79:   };
                     80: 
                     81:   #define OPTLIST_SIZE         (sizeof(OptList) / sizeof(*OptList))
                     82: 
                     83:   /* How long to wait for graceful shutdown when we recieve a SIGTERM */
                     84:   #define TERMINATE_DEATH_WAIT (2 * SECONDS)
                     85: 
                     86: /*
                     87:  * GLOBAL VARIABLES
                     88:  */
                     89: 
                     90:   Rep                  *gReps;
                     91:   Link                 *gLinks;
                     92:   Bund                 *gBundles;
                     93:   int                  gNumReps;
                     94:   int                  gNumLinks;
                     95:   int                  gNumBundles;
                     96:   struct console       gConsole;
                     97: #ifndef NOWEB
                     98:   struct web           gWeb;
                     99: #endif
                    100:   struct radsrv                gRadsrv;
                    101:   int                  gBackground = FALSE;
                    102:   int                  gShutdownInProgress = FALSE;
                    103:   int                  gOverload = 0;
                    104:   pid_t                gPid;
                    105:   int                  gRouteSeq = 0;
                    106: 
                    107: #ifdef PHYSTYPE_PPTP
                    108:   int                  gPPTPto = 10;
                    109:   int                  gPPTPtunlimit = 100;
                    110: #endif
                    111: #ifdef PHYSTYPE_L2TP
                    112:   int                  gL2TPto = 10;
                    113: #if ((__FreeBSD_version > 603100 && __FreeBSD_version < 700000) || __FreeBSD_version >= 700055)
                    114:   int                  gL2TPtunlimit = 100;
                    115: #else
                    116:   int                  gL2TPtunlimit = 10;
                    117: #endif
                    118: #endif
                    119:   int                  gChildren = 0;          /* Current number of children links */
                    120:   int                  gMaxChildren = 10000;   /* Maximal number of children links */
                    121: 
                    122: #ifdef USE_NG_BPF
                    123:   struct acl           *acl_filters[ACL_FILTERS]; /* mpd's global internal bpf filters */
                    124: #endif
                    125: 
1.1.1.2   misho     126: #ifdef USE_PAM
                    127:   char                 gPamService[32];
                    128: #endif
                    129: 
1.1       misho     130:   struct globalconf    gGlobalConf;
                    131: 
                    132:   pthread_mutex_t      gGiantMutex;
                    133: 
                    134:   const char           *gConfigFile = CONF_FILE;
                    135:   const char           *gConfDirectory = PATH_CONF_DIR;
                    136: 
                    137:   const char           *gVersion = MPD_VERSION;
                    138: 
                    139: /*
                    140:  * INTERNAL FUNCTIONS
                    141:  */
                    142: 
                    143:   static void          Usage(int ex) __dead2;
                    144:   static void          OptParse(int ac, char *av[]);
                    145:   static int           OptApply(Option opt, int ac, char *av[]);
                    146:   static Option                OptDecode(char *arg, int longform);
                    147: 
                    148:   static void          ConfigRead(int type, void *arg);
                    149:   static void          OpenCloseSignal(int sig);
                    150:   static void          FatalSignal(int sig);
                    151:   static void          SignalHandler(int type, void *arg);
                    152:   static void          CloseIfaces(void);
                    153: 
                    154: 
                    155: /*
                    156:  * INTERNAL VARIABLES
                    157:  */
                    158: 
                    159:   static int           gKillProc = FALSE;
                    160:   static const char    *gPidFile = PID_FILE;
                    161:   static const char    *gPeerSystem = NULL;
                    162:   static EventRef      gSignalEvent;
                    163:   static EventRef      gConfigReadEvent;
                    164:   static int           gSignalPipe[2];
                    165:   static struct context gCtx;
                    166: 
                    167: /*
                    168:  * main()
                    169:  */
                    170: 
                    171: int
                    172: main(int ac, char *av[])
                    173: {
                    174:     int                        ret, k;
                    175:     char               *args[MAX_ARGS];
                    176:     Context            c;
                    177:     PhysType           pt;
                    178: 
1.1.1.3 ! misho     179:     gPid = getpid();
1.1       misho     180: 
                    181:     /* enable libpdel typed_mem */
                    182:     typed_mem_enable();
                    183: 
                    184:     /* init global-config */
                    185:     memset(&gGlobalConf, 0, sizeof(gGlobalConf));
                    186: 
                    187:     /* Read and parse command line */
                    188:     if (ac > MAX_ARGS)
                    189:        ac = MAX_ARGS;
                    190:     memcpy(args, av, ac * sizeof(*av));        /* Copy to preserve "ps" output */
                    191:     OptParse(ac - 1, args + 1);
                    192: 
                    193:     /* init console-stuff */
                    194:     ConsoleInit(&gConsole);
                    195: 
                    196:     memset(&gCtx, 0, sizeof(gCtx));
                    197:     gCtx.priv = 2;
                    198:     if (gBackground) {
                    199:        c = &gCtx;
                    200:     } else {
                    201:         c = StdConsoleConnect(&gConsole);
                    202:        if (c == NULL)
                    203:            c = &gCtx;
                    204:     }
                    205: 
                    206: #ifndef NOWEB
                    207:     /* init web-stuff */
                    208:     WebInit(&gWeb);
                    209: #endif
                    210: 
                    211: #ifdef RAD_COA_REQUEST
                    212:     /* init RADIUS server */
                    213:     RadsrvInit(&gRadsrv);
                    214: #endif
                    215: 
1.1.1.2   misho     216: #ifdef USE_PAM
                    217:     if (!*gPamService)
                    218:        strcpy(gPamService, "mpd");
                    219: #endif
                    220: 
                    221: 
1.1       misho     222:     /* Set up libnetgraph logging */
                    223:     NgSetErrLog(NgFuncErr, NgFuncErrx);
                    224: 
                    225:     /* Background mode? */
                    226:     if (gBackground) {
                    227:        if (daemon(TRUE, FALSE) < 0)
                    228:            err(1, "daemon");
                    229:        gPid=getpid();
                    230:        (void) chdir(gConfDirectory);
                    231:     }
                    232: 
                    233:     /* Open log file */
                    234:     if (LogOpen())
                    235:        exit(EX_ERRDEAD);
                    236: 
                    237:     /* Randomize */
                    238:     srandomdev();
                    239: 
                    240:     /* Welcome */
                    241:     Greetings();
                    242: 
                    243:     /* Check PID file */
                    244:     if (PIDCheck(gPidFile, gKillProc) < 0)
                    245:        exit(EX_UNAVAILABLE);
                    246: 
                    247:     /* Do some initialization */
                    248:     MpSetDiscrim();
                    249:     IPPoolInit();
                    250: #ifdef CCP_MPPC
                    251:     MppcTestCap();
                    252: #endif
                    253:     if ((LinksInit() != 0) || (CcpsInit() != 0) || (EcpsInit() != 0))
                    254:        exit(EX_UNAVAILABLE);
                    255:     
                    256:     /* Init device types. */
                    257:     for (k = 0; (pt = gPhysTypes[k]); k++) {
                    258:        if (pt->tinit && (pt->tinit)()) {
                    259:            Log(LG_ERR, ("Device type '%s' initialization error.\n", pt->name));
                    260:            exit(EX_UNAVAILABLE);
                    261:        }
                    262:     }
                    263: 
                    264:     ret = pthread_mutex_init (&gGiantMutex, NULL);
                    265:     if (ret != 0) {
                    266:        Log(LG_ERR, ("Could not create giant mutex %d", ret));
                    267:        exit(EX_UNAVAILABLE);
                    268:     }
                    269: 
                    270:     /* Create signaling pipe */
1.1.1.3 ! misho     271:     if (pipe(gSignalPipe) < 0) {
        !           272:        Perror("Could not create signal pipe");
1.1       misho     273:        exit(EX_UNAVAILABLE);
                    274:     }
                    275:     if (EventRegister(&gSignalEvent, EVENT_READ, gSignalPipe[0], 
                    276:       EVENT_RECURRING, SignalHandler, NULL) != 0)
                    277:        exit(EX_UNAVAILABLE);
                    278: 
                    279:     /* Register for some common fatal signals so we can exit cleanly */
                    280:     signal(SIGINT, SendSignal);
                    281:     signal(SIGTERM, SendSignal);
                    282:     signal(SIGHUP, SendSignal);
                    283: 
                    284:     /* Catastrophic signals */
                    285:     signal(SIGSEGV, SendSignal);
                    286:     signal(SIGBUS, SendSignal);
                    287:     signal(SIGABRT, SendSignal);
                    288: 
                    289:     /* Other signals make us do things */
                    290:     signal(SIGUSR1, SendSignal);
                    291:     signal(SIGUSR2, SendSignal);
                    292: 
                    293:     /* Signals we ignore */
                    294:     signal(SIGPIPE, SIG_IGN);
                    295: 
                    296:     EventRegister(&gConfigReadEvent, EVENT_TIMEOUT,
                    297:        0, 0, ConfigRead, c);
                    298: 
                    299:     pthread_exit(NULL);
                    300: 
                    301:     assert(0);
                    302:     return(1); /* Never reached, but needed to silence compiler warning */
                    303: }
                    304: 
                    305: /*
                    306:  * Greetings()
                    307:  */
                    308: 
                    309: void
                    310: Greetings(void)
                    311: {
                    312:     Log(LG_ALWAYS, ("Multi-link PPP daemon for FreeBSD"));
                    313:     Log(LG_ALWAYS, (" "));
                    314:     Log(LG_ALWAYS, ("process %lu started, version %s", (u_long) gPid, gVersion));
                    315: }
                    316: 
                    317: /*
                    318:  * ConfigRead()
                    319:  *
                    320:  * handler of initial configuration reading event
                    321:  */
                    322: static void
                    323: ConfigRead(int type, void *arg)
                    324: {
                    325:     Context    c = (Context)arg;
1.1.1.3 ! misho     326:     int                err;
1.1       misho     327: 
                    328:     /* Read startup configuration section */
1.1.1.3 ! misho     329:     err = ReadFile(gConfigFile, STARTUP_CONF, DoCommand, c);
1.1       misho     330: 
                    331:     /* Read configuration as specified on the command line, or default */
1.1.1.3 ! misho     332:     if (!gPeerSystem) {
        !           333:        if (err != -2)
        !           334:            ReadFile(gConfigFile, DEFAULT_CONF, DoCommand, c);
        !           335:     } else {
        !           336:        if (err == -2 || ReadFile(gConfigFile, gPeerSystem, DoCommand, c) < 0) {
1.1       misho     337:            Log(LG_ERR, ("can't read configuration for \"%s\"", gPeerSystem));
                    338:            DoExit(EX_CONFIG);
                    339:        }
                    340:     }
                    341:     CheckOneShot();
                    342:     if (c->cs)
                    343:        c->cs->prompt(c->cs);
                    344: }
                    345: 
                    346: /*
                    347:  * CloseIfaces()
                    348:  */
                    349: 
                    350: static void
                    351: CloseIfaces(void)
                    352: {
                    353:     Bund       b;
                    354:     int                k;
                    355: 
                    356:     /* Shut down all interfaces we grabbed */
                    357:     for (k = 0; k < gNumBundles; k++) {
                    358:        if (((b = gBundles[k]) != NULL) && (!b->tmpl)) {
                    359:            IfaceClose(b);
                    360:            BundNcpsClose(b);
                    361:        }
                    362:     }
                    363: }
                    364: 
                    365: /*
                    366:  * DoExit()
                    367:  *
                    368:  * Cleanup and exit
                    369:  */
                    370: 
                    371: void
                    372: DoExit(int code)
                    373: {
                    374:     Bund       b;
                    375:     Rep                r;
                    376:     Link       l;
                    377:     PhysType   pt;
                    378:     int                k;
                    379: 
                    380:     gShutdownInProgress=1;
                    381:     /* Weak attempt to record what happened */
                    382:     if (code == EX_ERRDEAD)
                    383:        Log(LG_ERR, ("fatal error, exiting"));
                    384: 
                    385:     /* Shutdown stuff */
                    386:     if (code != EX_TERMINATE)  /* kludge to avoid double shutdown */
                    387:        CloseIfaces();
                    388: 
                    389:     NgFuncShutdownGlobal();
                    390: 
                    391:     /* Blow away all netgraph nodes */
                    392:     for (k = 0; k < gNumBundles; k++) {
                    393:        if ((b = gBundles[k]) != NULL)
                    394:            BundShutdown(b);
                    395:     }
                    396: 
                    397:     for (k = 0; k < gNumReps; k++) {
                    398:        if ((r = gReps[k]) != NULL)
                    399:            RepShutdown(r);
                    400:     }
                    401: 
                    402:     for (k = 0; k < gNumLinks; k++) {
                    403:        if ((l = gLinks[k]) != NULL)
                    404:            LinkShutdown(l);
                    405:     }
                    406: 
                    407:     /* Shutdown device types. */
                    408:     for (k = 0; (pt = gPhysTypes[k]); k++) {
                    409:        if (pt->tshutdown)
                    410:            (pt->tshutdown)();
                    411:     }
                    412: 
                    413:     EcpsShutdown();
                    414:     CcpsShutdown();
                    415:     LinksShutdown();
                    416: 
                    417:     /* Remove our PID file and exit */
                    418:     ConsoleShutdown(&gConsole);
                    419:     Log(LG_ALWAYS, ("process %d terminated", gPid));
                    420:     LogClose();
                    421:     (void) unlink(gPidFile);
                    422:     exit(code == EX_TERMINATE ? EX_NORMAL : code);
                    423: }
                    424: 
                    425: /*
                    426:  * SendSignal()
                    427:  *
                    428:  * Send a signal through the signaling pipe
                    429:  * don't add printf's here or any function
                    430:  * wich isn't re-entrant
                    431:  */
                    432: 
                    433: void
                    434: SendSignal(int sig)
                    435: {
                    436:     if (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT)
                    437:        FatalSignal(sig);
                    438:     write(gSignalPipe[1], &sig, 1);
                    439: }
                    440: 
                    441: /*
                    442:  * SignalHandler()
                    443:  *
                    444:  * dispatch signal
                    445:  */
                    446: static void
                    447: SignalHandler(int type, void *arg)
                    448: {
                    449:     u_char     sig;
                    450: 
                    451:     read(gSignalPipe[0], &sig, sizeof(sig));
                    452: 
                    453:     switch(sig) {
                    454:        case SIGUSR1:
                    455:        case SIGUSR2:
                    456:            OpenCloseSignal(sig);
                    457:            break;
                    458: 
                    459:        default:
                    460:            FatalSignal(sig);
                    461:     }
                    462: }
                    463: 
                    464: /*
                    465:  * FatalSignal()
                    466:  *
                    467:  * Gracefully exit on receipt of a fatal signal
                    468:  */
                    469: 
                    470: static void
                    471: FatalSignal(int sig)
                    472: {
                    473:     Bund       b;
                    474:     static struct pppTimer     gDeathTimer;
                    475:     int                                k;
                    476:     int                                upLinkCount;
1.1.1.3 ! misho     477: #ifdef USE_BACKTRACE
        !           478:     void                       *buffer[100];
        !           479:     char                       **strings;
        !           480:     int                                n;
        !           481: #endif
1.1       misho     482: 
                    483:     /* If a SIGTERM or SIGINT, gracefully shutdown; otherwise shutdown now */
                    484:     Log(LG_ERR, ("caught fatal signal %s", sys_signame[sig]));
                    485:     gShutdownInProgress=1;
1.1.1.3 ! misho     486: #ifdef USE_BACKTRACE
        !           487:     if (sig != SIGTERM && sig != SIGINT) {
        !           488:         n = backtrace(buffer, 100);
        !           489:         strings = backtrace_symbols(buffer, n);
        !           490:         if (strings == NULL) {
        !           491:             Log(LG_ERR, ("No backtrace symbols found"));
        !           492:         } else {
        !           493:             for (k = 0; k < n; k++) {
        !           494:                 Log(LG_ERR, ("%s", strings[k]));
        !           495:             }
        !           496:             free(strings);
        !           497:         }
        !           498:     }
        !           499: #endif
1.1       misho     500:     for (k = 0; k < gNumBundles; k++) {
                    501:        if ((b = gBundles[k])) {
                    502:            if (sig != SIGTERM && sig != SIGINT)
                    503:                RecordLinkUpDownReason(b, NULL, 0, STR_FATAL_SHUTDOWN, NULL);
                    504:            else
                    505:                RecordLinkUpDownReason(b, NULL, 0, STR_ADMIN_SHUTDOWN, NULL);
                    506:        }
                    507:     }
                    508:     upLinkCount = 0;
                    509:     for (k = 0; k < gNumLinks; k++) {
                    510:        if (gLinks[k] && (gLinks[k]->state!=PHYS_STATE_DOWN))
                    511:            upLinkCount++;
                    512:     }
                    513: 
                    514:     /* We are going down. No more signals. */
                    515:     signal(SIGINT, SIG_IGN);
                    516:     signal(SIGTERM, SIG_IGN);
                    517:     signal(SIGUSR1, SIG_IGN);
                    518:     signal(SIGUSR2, SIG_IGN);
                    519: 
                    520:     if (sig != SIGTERM && sig != SIGINT)
                    521:        DoExit(EX_ERRDEAD);
                    522: 
                    523:     CloseIfaces();
                    524:     TimerInit(&gDeathTimer, "DeathTimer",
                    525:        TERMINATE_DEATH_WAIT * (upLinkCount/100+1), (void (*)(void *)) DoExit, (void *) EX_TERMINATE);
                    526:     TimerStart(&gDeathTimer);
                    527: }
                    528: 
                    529: /*
                    530:  * OpenCloseSignal()
                    531:  */
                    532: 
                    533: static void
                    534: OpenCloseSignal(int sig)
                    535: {
                    536:     int                k;
                    537:     Link       l;
                    538: 
                    539:     for (k = 0;
                    540:        k < gNumLinks && (gLinks[k] == NULL || gLinks[k]->tmpl);
                    541:        k++);
                    542:     if (k == gNumLinks) {
                    543:        Log(LG_ALWAYS, ("rec'd signal %s, no link defined, ignored", sys_signame[sig]));
                    544:        return;
                    545:     }
                    546: 
                    547:     l = gLinks[k];
                    548: 
                    549:     /* Open/Close Link */
                    550:     if (l && l->type) {
                    551:        if (sig == SIGUSR1) {
                    552:            Log(LG_ALWAYS, ("[%s] rec'd signal %s, opening",
                    553:                l->name, sys_signame[sig]));
                    554:            RecordLinkUpDownReason(NULL, l, 1, STR_MANUALLY, NULL);
                    555:            LinkOpen(l);
                    556:        } else {
                    557:            Log(LG_ALWAYS, ("[%s] rec'd signal %s, closing",
                    558:                l->name, sys_signame[sig]));
                    559:            RecordLinkUpDownReason(NULL, l, 0, STR_MANUALLY, NULL);
                    560:            LinkClose(l);
                    561:        }
                    562:     } else
                    563:        Log(LG_ALWAYS, ("rec'd signal %s, ignored", sys_signame[sig]));
                    564: }
                    565: 
                    566: void
                    567: CheckOneShot(void)
                    568: {
                    569:     int        i;
                    570:     if (!Enabled(&gGlobalConf.options, GLOBAL_CONF_ONESHOT))
                    571:        return;
                    572:     for (i = 0; i < gNumLinks; i++) {
                    573:        if (gLinks[i] && !gLinks[i]->tmpl)
                    574:            return;
                    575:     }
                    576:     Log(LG_ALWAYS, ("One-shot mode enabled and no links found. Terminating daemon."));
                    577:     SendSignal(SIGTERM);
                    578: }
                    579: 
                    580: /*
                    581:  * OptParse()
                    582:  */
                    583: 
                    584: static void
                    585: OptParse(int ac, char *av[])
                    586: {
                    587:     int        used, consumed;
                    588: 
                    589:     /* Get option flags */
                    590:     for ( ; ac > 0 && **av == '-'; ac--, av++) {
                    591:        if (*++(*av) == '-') {  /* Long form */
                    592:            if (*++(*av) == 0) {        /* "--" forces end of options */
                    593:                ac--; av++;
                    594:                break;
                    595:            } else {
                    596:                used = OptApply(OptDecode(*av, TRUE), ac - 1, av + 1);
                    597:                ac -= used; av += used;
                    598:            }
                    599:        } else {                        /* Short form */
                    600:            for (used = 0; **av; (*av)++, used += consumed) {
                    601:                consumed = OptApply(OptDecode(*av, FALSE), ac - 1, av + 1);
                    602:                if (used && consumed)
                    603:                    Usage(EX_USAGE);
                    604:            }
                    605:            ac -= used; av += used;
                    606:        }
                    607:     }
                    608: 
                    609:     /* Get system names */
                    610:     switch (ac) {
                    611:        case 0:
                    612:            break;
                    613:        case 1:
                    614:            gPeerSystem = *av;
                    615:            break;
                    616:        default:
                    617:            Usage(EX_USAGE);
                    618:     }
                    619: }
                    620: 
                    621: /*
                    622:  * OptApply()
                    623:  */
                    624: 
                    625: static int
                    626: OptApply(Option opt, int ac, char *av[])
                    627: {
                    628: #ifdef SYSLOG_FACILITY
                    629:     memset(gSysLogIdent, 0, sizeof(gSysLogIdent));
                    630: #endif
1.1.1.2   misho     631: #ifdef USE_PAM
                    632:     memset(gPamService, 0, sizeof(gPamService));
                    633: #endif
1.1       misho     634: 
                    635:     if (opt == NULL)
                    636:        Usage(EX_USAGE);
                    637:     if (ac < opt->n_args)
                    638:        Usage(EX_USAGE);
                    639:     switch (opt->sflag) {
                    640:        case 'b':
                    641:            gBackground = TRUE;
                    642:            return(0);
                    643:        case 'd':
                    644:            gConfDirectory = *av;
                    645:            return(1);
                    646:        case 'f':
                    647:            gConfigFile = *av;
                    648:            return(1);
                    649:        case 'o':
                    650:            Enable(&gGlobalConf.options, GLOBAL_CONF_ONESHOT);
                    651:            return(0);
                    652:        case 'p':
                    653:            gPidFile = *av;
                    654:            return(1);
                    655:        case 'k':
                    656:            gKillProc = TRUE;
                    657:            return(0);
                    658: #ifdef SYSLOG_FACILITY
                    659:        case 's':
                    660:            strlcpy(gSysLogIdent, *av, sizeof(gSysLogIdent));
                    661:            return(1);
                    662: #endif
1.1.1.2   misho     663: #ifdef USE_PAM
                    664:        case 'm':
                    665:            strlcpy(gPamService, *av, sizeof(gPamService));
                    666:            return(1);
                    667: #endif
1.1       misho     668:        case 'v':
                    669:            fprintf(stderr, "Version %s\n", gVersion);
                    670:            exit(EX_NORMAL);
                    671:        case 'h':
                    672:            Usage(EX_NORMAL);
                    673:        default:
                    674:            assert(0);
                    675:     }
                    676:     return(0);
                    677: }
                    678: 
                    679: /*
                    680:  * OptDecode()
                    681:  */
                    682: 
                    683: static Option
                    684: OptDecode(char *arg, int longform)
                    685: {
                    686:     Option     opt;
                    687:     size_t     k;
                    688: 
                    689:     for (k = 0; k < OPTLIST_SIZE; k++) {
                    690:        opt = OptList + k;
                    691:        if (longform ?
                    692:            !strcmp(arg, opt->lflag) : (*arg == opt->sflag))
                    693:         return(opt);
                    694:     }
                    695:     return(NULL);
                    696: }
                    697: 
                    698: /*
                    699:  * Usage()
                    700:  */
                    701: 
                    702: static void
                    703: Usage(int ex)
                    704: {
                    705:     Option             opt;
                    706:     char               buf[100];
                    707:     size_t             k;
                    708: 
                    709:     fprintf(stderr, "Usage: mpd5 %s\n", UsageStr);
                    710:     fprintf(stderr, "Options:\n");
                    711:     for (k = 0; k < OPTLIST_SIZE; k++) {
                    712:        opt = OptList + k;
                    713:        snprintf(buf, sizeof(buf), "  -%c, --%-s %s",
                    714:            opt->sflag, opt->lflag, opt->usage);
1.1.1.3 ! misho     715:        fprintf(stderr, "%-35s%s\n", buf, opt->desc);
1.1       misho     716:     }
                    717:     exit(ex);
                    718: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>