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

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;
1.1.1.4 ! misho     109:   unsigned             gPPTPtunlimit = 100;
1.1       misho     110: #endif
                    111: #ifdef PHYSTYPE_L2TP
                    112:   int                  gL2TPto = 10;
                    113: #if ((__FreeBSD_version > 603100 && __FreeBSD_version < 700000) || __FreeBSD_version >= 700055)
1.1.1.4 ! misho     114:   unsigned             gL2TPtunlimit = 100;
1.1       misho     115: #else
1.1.1.4 ! misho     116:   unsigned             gL2TPtunlimit = 10;
1.1       misho     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;
1.1.1.4 ! misho     177:     const struct phystype *pt;
1.1       misho     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: 
1.1.1.4 ! misho     328:     (void)type;
1.1       misho     329:     /* Read startup configuration section */
1.1.1.3   misho     330:     err = ReadFile(gConfigFile, STARTUP_CONF, DoCommand, c);
1.1       misho     331: 
                    332:     /* Read configuration as specified on the command line, or default */
1.1.1.3   misho     333:     if (!gPeerSystem) {
                    334:        if (err != -2)
                    335:            ReadFile(gConfigFile, DEFAULT_CONF, DoCommand, c);
                    336:     } else {
                    337:        if (err == -2 || ReadFile(gConfigFile, gPeerSystem, DoCommand, c) < 0) {
1.1       misho     338:            Log(LG_ERR, ("can't read configuration for \"%s\"", gPeerSystem));
                    339:            DoExit(EX_CONFIG);
                    340:        }
                    341:     }
                    342:     CheckOneShot();
                    343:     if (c->cs)
                    344:        c->cs->prompt(c->cs);
                    345: }
                    346: 
                    347: /*
                    348:  * CloseIfaces()
                    349:  */
                    350: 
                    351: static void
                    352: CloseIfaces(void)
                    353: {
                    354:     Bund       b;
                    355:     int                k;
                    356: 
                    357:     /* Shut down all interfaces we grabbed */
                    358:     for (k = 0; k < gNumBundles; k++) {
                    359:        if (((b = gBundles[k]) != NULL) && (!b->tmpl)) {
                    360:            IfaceClose(b);
                    361:            BundNcpsClose(b);
                    362:        }
                    363:     }
                    364: }
                    365: 
                    366: /*
                    367:  * DoExit()
                    368:  *
                    369:  * Cleanup and exit
                    370:  */
                    371: 
                    372: void
                    373: DoExit(int code)
                    374: {
                    375:     Bund       b;
                    376:     Rep                r;
                    377:     Link       l;
1.1.1.4 ! misho     378:     const struct phystype *pt;
1.1       misho     379:     int                k;
                    380: 
                    381:     gShutdownInProgress=1;
                    382:     /* Weak attempt to record what happened */
                    383:     if (code == EX_ERRDEAD)
                    384:        Log(LG_ERR, ("fatal error, exiting"));
                    385: 
                    386:     /* Shutdown stuff */
                    387:     if (code != EX_TERMINATE)  /* kludge to avoid double shutdown */
                    388:        CloseIfaces();
                    389: 
                    390:     NgFuncShutdownGlobal();
                    391: 
                    392:     /* Blow away all netgraph nodes */
                    393:     for (k = 0; k < gNumBundles; k++) {
                    394:        if ((b = gBundles[k]) != NULL)
                    395:            BundShutdown(b);
                    396:     }
                    397: 
                    398:     for (k = 0; k < gNumReps; k++) {
                    399:        if ((r = gReps[k]) != NULL)
                    400:            RepShutdown(r);
                    401:     }
                    402: 
                    403:     for (k = 0; k < gNumLinks; k++) {
                    404:        if ((l = gLinks[k]) != NULL)
                    405:            LinkShutdown(l);
                    406:     }
                    407: 
                    408:     /* Shutdown device types. */
                    409:     for (k = 0; (pt = gPhysTypes[k]); k++) {
                    410:        if (pt->tshutdown)
                    411:            (pt->tshutdown)();
                    412:     }
                    413: 
                    414:     EcpsShutdown();
                    415:     CcpsShutdown();
                    416:     LinksShutdown();
                    417: 
                    418:     /* Remove our PID file and exit */
                    419:     ConsoleShutdown(&gConsole);
                    420:     Log(LG_ALWAYS, ("process %d terminated", gPid));
                    421:     LogClose();
                    422:     (void) unlink(gPidFile);
                    423:     exit(code == EX_TERMINATE ? EX_NORMAL : code);
                    424: }
                    425: 
                    426: /*
                    427:  * SendSignal()
                    428:  *
                    429:  * Send a signal through the signaling pipe
                    430:  * don't add printf's here or any function
                    431:  * wich isn't re-entrant
                    432:  */
                    433: 
                    434: void
                    435: SendSignal(int sig)
                    436: {
                    437:     if (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT)
                    438:        FatalSignal(sig);
                    439:     write(gSignalPipe[1], &sig, 1);
                    440: }
                    441: 
                    442: /*
                    443:  * SignalHandler()
                    444:  *
                    445:  * dispatch signal
                    446:  */
                    447: static void
                    448: SignalHandler(int type, void *arg)
                    449: {
                    450:     u_char     sig;
                    451: 
1.1.1.4 ! misho     452:     (void)type;
        !           453:     (void)arg;
1.1       misho     454:     read(gSignalPipe[0], &sig, sizeof(sig));
                    455: 
                    456:     switch(sig) {
                    457:        case SIGUSR1:
                    458:        case SIGUSR2:
                    459:            OpenCloseSignal(sig);
                    460:            break;
                    461: 
                    462:        default:
                    463:            FatalSignal(sig);
                    464:     }
                    465: }
                    466: 
                    467: /*
                    468:  * FatalSignal()
                    469:  *
                    470:  * Gracefully exit on receipt of a fatal signal
                    471:  */
                    472: 
                    473: static void
                    474: FatalSignal(int sig)
                    475: {
                    476:     Bund       b;
                    477:     static struct pppTimer     gDeathTimer;
                    478:     int                                k;
                    479:     int                                upLinkCount;
1.1.1.3   misho     480: #ifdef USE_BACKTRACE
                    481:     void                       *buffer[100];
                    482:     char                       **strings;
                    483:     int                                n;
                    484: #endif
1.1       misho     485: 
                    486:     /* If a SIGTERM or SIGINT, gracefully shutdown; otherwise shutdown now */
                    487:     Log(LG_ERR, ("caught fatal signal %s", sys_signame[sig]));
                    488:     gShutdownInProgress=1;
1.1.1.3   misho     489: #ifdef USE_BACKTRACE
                    490:     if (sig != SIGTERM && sig != SIGINT) {
                    491:         n = backtrace(buffer, 100);
                    492:         strings = backtrace_symbols(buffer, n);
                    493:         if (strings == NULL) {
                    494:             Log(LG_ERR, ("No backtrace symbols found"));
                    495:         } else {
                    496:             for (k = 0; k < n; k++) {
                    497:                 Log(LG_ERR, ("%s", strings[k]));
                    498:             }
                    499:             free(strings);
                    500:         }
                    501:     }
                    502: #endif
1.1       misho     503:     for (k = 0; k < gNumBundles; k++) {
                    504:        if ((b = gBundles[k])) {
                    505:            if (sig != SIGTERM && sig != SIGINT)
                    506:                RecordLinkUpDownReason(b, NULL, 0, STR_FATAL_SHUTDOWN, NULL);
                    507:            else
                    508:                RecordLinkUpDownReason(b, NULL, 0, STR_ADMIN_SHUTDOWN, NULL);
                    509:        }
                    510:     }
                    511:     upLinkCount = 0;
                    512:     for (k = 0; k < gNumLinks; k++) {
                    513:        if (gLinks[k] && (gLinks[k]->state!=PHYS_STATE_DOWN))
                    514:            upLinkCount++;
                    515:     }
                    516: 
                    517:     /* We are going down. No more signals. */
                    518:     signal(SIGINT, SIG_IGN);
                    519:     signal(SIGTERM, SIG_IGN);
                    520:     signal(SIGUSR1, SIG_IGN);
                    521:     signal(SIGUSR2, SIG_IGN);
                    522: 
                    523:     if (sig != SIGTERM && sig != SIGINT)
                    524:        DoExit(EX_ERRDEAD);
                    525: 
                    526:     CloseIfaces();
                    527:     TimerInit(&gDeathTimer, "DeathTimer",
                    528:        TERMINATE_DEATH_WAIT * (upLinkCount/100+1), (void (*)(void *)) DoExit, (void *) EX_TERMINATE);
                    529:     TimerStart(&gDeathTimer);
                    530: }
                    531: 
                    532: /*
                    533:  * OpenCloseSignal()
                    534:  */
                    535: 
                    536: static void
                    537: OpenCloseSignal(int sig)
                    538: {
                    539:     int                k;
                    540:     Link       l;
                    541: 
                    542:     for (k = 0;
                    543:        k < gNumLinks && (gLinks[k] == NULL || gLinks[k]->tmpl);
                    544:        k++);
                    545:     if (k == gNumLinks) {
                    546:        Log(LG_ALWAYS, ("rec'd signal %s, no link defined, ignored", sys_signame[sig]));
                    547:        return;
                    548:     }
                    549: 
                    550:     l = gLinks[k];
                    551: 
                    552:     /* Open/Close Link */
                    553:     if (l && l->type) {
                    554:        if (sig == SIGUSR1) {
                    555:            Log(LG_ALWAYS, ("[%s] rec'd signal %s, opening",
                    556:                l->name, sys_signame[sig]));
                    557:            RecordLinkUpDownReason(NULL, l, 1, STR_MANUALLY, NULL);
                    558:            LinkOpen(l);
                    559:        } else {
                    560:            Log(LG_ALWAYS, ("[%s] rec'd signal %s, closing",
                    561:                l->name, sys_signame[sig]));
                    562:            RecordLinkUpDownReason(NULL, l, 0, STR_MANUALLY, NULL);
                    563:            LinkClose(l);
                    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>