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

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