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

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

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