Annotation of embedaddon/sudo/compat/getopt_long.c, revision 1.1
1.1 ! misho 1: /* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */
! 2: /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
! 3: /* $FreeBSD: head/lib/libc/stdlib/getopt_long.c 236936 2012-06-11 22:25:20Z delphij $ */
! 4:
! 5: /*
! 6: * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
! 7: *
! 8: * Permission to use, copy, modify, and distribute this software for any
! 9: * purpose with or without fee is hereby granted, provided that the above
! 10: * copyright notice and this permission notice appear in all copies.
! 11: *
! 12: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 13: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 14: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 15: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 16: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 17: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 18: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 19: *
! 20: * Sponsored in part by the Defense Advanced Research Projects
! 21: * Agency (DARPA) and Air Force Research Laboratory, Air Force
! 22: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
! 23: */
! 24: /*-
! 25: * Copyright (c) 2000 The NetBSD Foundation, Inc.
! 26: * All rights reserved.
! 27: *
! 28: * This code is derived from software contributed to The NetBSD Foundation
! 29: * by Dieter Baron and Thomas Klausner.
! 30: *
! 31: * Redistribution and use in source and binary forms, with or without
! 32: * modification, are permitted provided that the following conditions
! 33: * are met:
! 34: * 1. Redistributions of source code must retain the above copyright
! 35: * notice, this list of conditions and the following disclaimer.
! 36: * 2. Redistributions in binary form must reproduce the above copyright
! 37: * notice, this list of conditions and the following disclaimer in the
! 38: * documentation and/or other materials provided with the distribution.
! 39: *
! 40: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 41: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 42: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 43: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 44: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 45: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 46: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 47: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 48: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 49: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 50: * POSSIBILITY OF SUCH DAMAGE.
! 51: */
! 52:
! 53: #include <config.h>
! 54:
! 55: #include <stdio.h>
! 56: #ifdef STDC_HEADERS
! 57: # include <stdlib.h>
! 58: # include <stddef.h>
! 59: #else
! 60: # ifdef HAVE_STDLIB_H
! 61: # include <stdlib.h>
! 62: # endif
! 63: #endif /* STDC_HEADERS */
! 64: #ifdef HAVE_STRING_H
! 65: # include <string.h>
! 66: #endif /* HAVE_STRING_H */
! 67: #ifdef HAVE_STRINGS_H
! 68: # include <strings.h>
! 69: #endif /* HAVE_STRINGS_H */
! 70:
! 71: #define SUDO_ERROR_WRAP 0
! 72:
! 73: #include "missing.h"
! 74: #include "fatal.h"
! 75: #include "compat/getopt.h"
! 76:
! 77: #define GNU_COMPATIBLE /* Be more compatible with GNU getopt. */
! 78:
! 79: #ifdef REPLACE_GETOPT
! 80: int opterr = 1; /* if error message should be printed */
! 81: int optind = 1; /* index into parent argv vector */
! 82: int optopt = '?'; /* character checked for validity */
! 83: char *optarg; /* argument associated with option */
! 84: #else
! 85: extern int opterr; /* if error message should be printed */
! 86: extern int optind; /* index into parent argv vector */
! 87: extern int optopt; /* character checked for validity */
! 88: extern char *optarg; /* argument associated with option */
! 89: #endif
! 90: #if !defined(REPLACE_GETOPT) && !defined(HAVE_OPTRESET)
! 91: int optreset; /* reset getopt */
! 92: #endif
! 93:
! 94: #define PRINT_ERROR ((opterr) && (*options != ':'))
! 95:
! 96: #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
! 97: #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
! 98: #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
! 99:
! 100: /* return values */
! 101: #define BADCH (int)'?'
! 102: #define BADARG ((*options == ':') ? (int)':' : (int)'?')
! 103: #define INORDER (int)1
! 104:
! 105: #define EMSG ""
! 106:
! 107: #ifdef GNU_COMPATIBLE
! 108: #define NO_PREFIX (-1)
! 109: #define D_PREFIX 0
! 110: #define DD_PREFIX 1
! 111: #define W_PREFIX 2
! 112: #endif
! 113:
! 114: static int getopt_internal(int, char * const *, const char *,
! 115: const struct option *, int *, int);
! 116: static int parse_long_options(char * const *, const char *,
! 117: const struct option *, int *, int, int);
! 118: static int gcd(int, int);
! 119: static void permute_args(int, int, int, char * const *);
! 120:
! 121: static char *place = EMSG; /* option letter processing */
! 122:
! 123: /* XXX: set optreset to 1 rather than these two */
! 124: static int nonopt_start = -1; /* first non option argument (for permute) */
! 125: static int nonopt_end = -1; /* first option after non options (for permute) */
! 126:
! 127: /* Error messages */
! 128: static const char recargchar[] = "option requires an argument -- %c";
! 129: static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
! 130: #ifdef GNU_COMPATIBLE
! 131: static int dash_prefix = NO_PREFIX;
! 132: static const char gnuoptchar[] = "invalid option -- %c";
! 133:
! 134: static const char recargstring[] = "option `%s%s' requires an argument";
! 135: static const char ambig[] = "option `%s%.*s' is ambiguous";
! 136: static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
! 137: static const char illoptstring[] = "unrecognized option `%s%s'";
! 138: #else
! 139: static const char recargstring[] = "option requires an argument -- %s";
! 140: static const char ambig[] = "ambiguous option -- %.*s";
! 141: static const char noarg[] = "option doesn't take an argument -- %.*s";
! 142: static const char illoptstring[] = "unknown option -- %s";
! 143: #endif
! 144:
! 145: /*
! 146: * Compute the greatest common divisor of a and b.
! 147: */
! 148: static int
! 149: gcd(int a, int b)
! 150: {
! 151: int c;
! 152:
! 153: c = a % b;
! 154: while (c != 0) {
! 155: a = b;
! 156: b = c;
! 157: c = a % b;
! 158: }
! 159:
! 160: return (b);
! 161: }
! 162:
! 163: /*
! 164: * Exchange the block from nonopt_start to nonopt_end with the block
! 165: * from nonopt_end to opt_end (keeping the same order of arguments
! 166: * in each block).
! 167: */
! 168: static void
! 169: permute_args(int panonopt_start, int panonopt_end, int opt_end,
! 170: char * const *nargv)
! 171: {
! 172: int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
! 173: char *swap;
! 174:
! 175: /*
! 176: * compute lengths of blocks and number and size of cycles
! 177: */
! 178: nnonopts = panonopt_end - panonopt_start;
! 179: nopts = opt_end - panonopt_end;
! 180: ncycle = gcd(nnonopts, nopts);
! 181: cyclelen = (opt_end - panonopt_start) / ncycle;
! 182:
! 183: for (i = 0; i < ncycle; i++) {
! 184: cstart = panonopt_end+i;
! 185: pos = cstart;
! 186: for (j = 0; j < cyclelen; j++) {
! 187: if (pos >= panonopt_end)
! 188: pos -= nnonopts;
! 189: else
! 190: pos += nopts;
! 191: swap = nargv[pos];
! 192: /* LINTED const cast */
! 193: ((char **) nargv)[pos] = nargv[cstart];
! 194: /* LINTED const cast */
! 195: ((char **)nargv)[cstart] = swap;
! 196: }
! 197: }
! 198: }
! 199:
! 200: /*
! 201: * parse_long_options --
! 202: * Parse long options in argc/argv argument vector.
! 203: * Returns -1 if short_too is set and the option does not match long_options.
! 204: */
! 205: static int
! 206: parse_long_options(char * const *nargv, const char *options,
! 207: const struct option *long_options, int *idx, int short_too, int flags)
! 208: {
! 209: char *current_argv, *has_equal;
! 210: #ifdef GNU_COMPATIBLE
! 211: char *current_dash;
! 212: #endif
! 213: size_t current_argv_len;
! 214: int i, match, exact_match, second_partial_match;
! 215:
! 216: current_argv = place;
! 217: #ifdef GNU_COMPATIBLE
! 218: switch (dash_prefix) {
! 219: case D_PREFIX:
! 220: current_dash = "-";
! 221: break;
! 222: case DD_PREFIX:
! 223: current_dash = "--";
! 224: break;
! 225: case W_PREFIX:
! 226: current_dash = "-W ";
! 227: break;
! 228: default:
! 229: current_dash = "";
! 230: break;
! 231: }
! 232: #endif
! 233: match = -1;
! 234: exact_match = 0;
! 235: second_partial_match = 0;
! 236:
! 237: optind++;
! 238:
! 239: if ((has_equal = strchr(current_argv, '=')) != NULL) {
! 240: /* argument found (--option=arg) */
! 241: current_argv_len = has_equal - current_argv;
! 242: has_equal++;
! 243: } else
! 244: current_argv_len = strlen(current_argv);
! 245:
! 246: for (i = 0; long_options[i].name; i++) {
! 247: /* find matching long option */
! 248: if (strncmp(current_argv, long_options[i].name,
! 249: current_argv_len))
! 250: continue;
! 251:
! 252: if (strlen(long_options[i].name) == current_argv_len) {
! 253: /* exact match */
! 254: match = i;
! 255: exact_match = 1;
! 256: break;
! 257: }
! 258: /*
! 259: * If this is a known short option, don't allow
! 260: * a partial match of a single character.
! 261: */
! 262: if (short_too && current_argv_len == 1)
! 263: continue;
! 264:
! 265: if (match == -1) /* first partial match */
! 266: match = i;
! 267: else if ((flags & FLAG_LONGONLY) ||
! 268: long_options[i].has_arg !=
! 269: long_options[match].has_arg ||
! 270: long_options[i].flag != long_options[match].flag ||
! 271: long_options[i].val != long_options[match].val)
! 272: second_partial_match = 1;
! 273: }
! 274: if (!exact_match && second_partial_match) {
! 275: /* ambiguous abbreviation */
! 276: if (PRINT_ERROR)
! 277: warningx(ambig,
! 278: #ifdef GNU_COMPATIBLE
! 279: current_dash,
! 280: #endif
! 281: (int)current_argv_len,
! 282: current_argv);
! 283: optopt = 0;
! 284: return (BADCH);
! 285: }
! 286: if (match != -1) { /* option found */
! 287: if (long_options[match].has_arg == no_argument
! 288: && has_equal) {
! 289: if (PRINT_ERROR)
! 290: warningx(noarg,
! 291: #ifdef GNU_COMPATIBLE
! 292: current_dash,
! 293: #endif
! 294: (int)current_argv_len,
! 295: current_argv);
! 296: /*
! 297: * XXX: GNU sets optopt to val regardless of flag
! 298: */
! 299: if (long_options[match].flag == NULL)
! 300: optopt = long_options[match].val;
! 301: else
! 302: optopt = 0;
! 303: #ifdef GNU_COMPATIBLE
! 304: return (BADCH);
! 305: #else
! 306: return (BADARG);
! 307: #endif
! 308: }
! 309: if (long_options[match].has_arg == required_argument ||
! 310: long_options[match].has_arg == optional_argument) {
! 311: if (has_equal)
! 312: optarg = has_equal;
! 313: else if (long_options[match].has_arg ==
! 314: required_argument) {
! 315: /*
! 316: * optional argument doesn't use next nargv
! 317: */
! 318: optarg = nargv[optind++];
! 319: }
! 320: }
! 321: if ((long_options[match].has_arg == required_argument)
! 322: && (optarg == NULL)) {
! 323: /*
! 324: * Missing argument; leading ':' indicates no error
! 325: * should be generated.
! 326: */
! 327: if (PRINT_ERROR)
! 328: warningx(recargstring,
! 329: #ifdef GNU_COMPATIBLE
! 330: current_dash,
! 331: #endif
! 332: current_argv);
! 333: /*
! 334: * XXX: GNU sets optopt to val regardless of flag
! 335: */
! 336: if (long_options[match].flag == NULL)
! 337: optopt = long_options[match].val;
! 338: else
! 339: optopt = 0;
! 340: --optind;
! 341: return (BADARG);
! 342: }
! 343: } else { /* unknown option */
! 344: if (short_too) {
! 345: --optind;
! 346: return (-1);
! 347: }
! 348: if (PRINT_ERROR)
! 349: warningx(illoptstring,
! 350: #ifdef GNU_COMPATIBLE
! 351: current_dash,
! 352: #endif
! 353: current_argv);
! 354: optopt = 0;
! 355: return (BADCH);
! 356: }
! 357: if (idx)
! 358: *idx = match;
! 359: if (long_options[match].flag) {
! 360: *long_options[match].flag = long_options[match].val;
! 361: return (0);
! 362: } else
! 363: return (long_options[match].val);
! 364: }
! 365:
! 366: /*
! 367: * getopt_internal --
! 368: * Parse argc/argv argument vector. Called by user level routines.
! 369: */
! 370: static int
! 371: getopt_internal(int nargc, char * const *nargv, const char *options,
! 372: const struct option *long_options, int *idx, int flags)
! 373: {
! 374: char *oli; /* option letter list index */
! 375: int optchar, short_too;
! 376: int posixly_correct; /* no static, can be changed on the fly */
! 377:
! 378: if (options == NULL)
! 379: return (-1);
! 380:
! 381: /*
! 382: * Disable GNU extensions if POSIXLY_CORRECT is set or options
! 383: * string begins with a '+'.
! 384: */
! 385: posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
! 386: #ifdef GNU_COMPATIBLE
! 387: if (*options == '-')
! 388: flags |= FLAG_ALLARGS;
! 389: else if (posixly_correct || *options == '+')
! 390: flags &= ~FLAG_PERMUTE;
! 391: #else
! 392: if (posixly_correct || *options == '+')
! 393: flags &= ~FLAG_PERMUTE;
! 394: else if (*options == '-')
! 395: flags |= FLAG_ALLARGS;
! 396: #endif
! 397: if (*options == '+' || *options == '-')
! 398: options++;
! 399:
! 400: /*
! 401: * XXX Some GNU programs (like cvs) set optind to 0 instead of
! 402: * XXX using optreset. Work around this braindamage.
! 403: */
! 404: if (optind == 0)
! 405: optind = optreset = 1;
! 406:
! 407: optarg = NULL;
! 408: if (optreset)
! 409: nonopt_start = nonopt_end = -1;
! 410: start:
! 411: if (optreset || !*place) { /* update scanning pointer */
! 412: optreset = 0;
! 413: if (optind >= nargc) { /* end of argument vector */
! 414: place = EMSG;
! 415: if (nonopt_end != -1) {
! 416: /* do permutation, if we have to */
! 417: permute_args(nonopt_start, nonopt_end,
! 418: optind, nargv);
! 419: optind -= nonopt_end - nonopt_start;
! 420: }
! 421: else if (nonopt_start != -1) {
! 422: /*
! 423: * If we skipped non-options, set optind
! 424: * to the first of them.
! 425: */
! 426: optind = nonopt_start;
! 427: }
! 428: nonopt_start = nonopt_end = -1;
! 429: return (-1);
! 430: }
! 431: if (*(place = nargv[optind]) != '-' ||
! 432: #ifdef GNU_COMPATIBLE
! 433: place[1] == '\0') {
! 434: #else
! 435: (place[1] == '\0' && strchr(options, '-') == NULL)) {
! 436: #endif
! 437: place = EMSG; /* found non-option */
! 438: if (flags & FLAG_ALLARGS) {
! 439: /*
! 440: * GNU extension:
! 441: * return non-option as argument to option 1
! 442: */
! 443: optarg = nargv[optind++];
! 444: return (INORDER);
! 445: }
! 446: if (!(flags & FLAG_PERMUTE)) {
! 447: /*
! 448: * If no permutation wanted, stop parsing
! 449: * at first non-option.
! 450: */
! 451: return (-1);
! 452: }
! 453: /* do permutation */
! 454: if (nonopt_start == -1)
! 455: nonopt_start = optind;
! 456: else if (nonopt_end != -1) {
! 457: permute_args(nonopt_start, nonopt_end,
! 458: optind, nargv);
! 459: nonopt_start = optind -
! 460: (nonopt_end - nonopt_start);
! 461: nonopt_end = -1;
! 462: }
! 463: optind++;
! 464: /* process next argument */
! 465: goto start;
! 466: }
! 467: if (nonopt_start != -1 && nonopt_end == -1)
! 468: nonopt_end = optind;
! 469:
! 470: /*
! 471: * If we have "-" do nothing, if "--" we are done.
! 472: */
! 473: if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
! 474: optind++;
! 475: place = EMSG;
! 476: /*
! 477: * We found an option (--), so if we skipped
! 478: * non-options, we have to permute.
! 479: */
! 480: if (nonopt_end != -1) {
! 481: permute_args(nonopt_start, nonopt_end,
! 482: optind, nargv);
! 483: optind -= nonopt_end - nonopt_start;
! 484: }
! 485: nonopt_start = nonopt_end = -1;
! 486: return (-1);
! 487: }
! 488: }
! 489:
! 490: /*
! 491: * Check long options if:
! 492: * 1) we were passed some
! 493: * 2) the arg is not just "-"
! 494: * 3) either the arg starts with -- we are getopt_long_only()
! 495: */
! 496: if (long_options != NULL && place != nargv[optind] &&
! 497: (*place == '-' || (flags & FLAG_LONGONLY))) {
! 498: short_too = 0;
! 499: #ifdef GNU_COMPATIBLE
! 500: dash_prefix = D_PREFIX;
! 501: #endif
! 502: if (*place == '-') {
! 503: place++; /* --foo long option */
! 504: #ifdef GNU_COMPATIBLE
! 505: dash_prefix = DD_PREFIX;
! 506: #endif
! 507: } else if (*place != ':' && strchr(options, *place) != NULL)
! 508: short_too = 1; /* could be short option too */
! 509:
! 510: optchar = parse_long_options(nargv, options, long_options,
! 511: idx, short_too, flags);
! 512: if (optchar != -1) {
! 513: place = EMSG;
! 514: return (optchar);
! 515: }
! 516: }
! 517:
! 518: if ((optchar = (int)*place++) == (int)':' ||
! 519: (optchar == (int)'-' && *place != '\0') ||
! 520: (oli = strchr(options, optchar)) == NULL) {
! 521: /*
! 522: * If the user specified "-" and '-' isn't listed in
! 523: * options, return -1 (non-option) as per POSIX.
! 524: * Otherwise, it is an unknown option character (or ':').
! 525: */
! 526: if (optchar == (int)'-' && *place == '\0')
! 527: return (-1);
! 528: if (!*place)
! 529: ++optind;
! 530: #ifdef GNU_COMPATIBLE
! 531: if (PRINT_ERROR)
! 532: warningx(posixly_correct ? illoptchar : gnuoptchar,
! 533: optchar);
! 534: #else
! 535: if (PRINT_ERROR)
! 536: warningx(illoptchar, optchar);
! 537: #endif
! 538: optopt = optchar;
! 539: return (BADCH);
! 540: }
! 541: if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
! 542: /* -W long-option */
! 543: if (*place) /* no space */
! 544: /* NOTHING */;
! 545: else if (++optind >= nargc) { /* no arg */
! 546: place = EMSG;
! 547: if (PRINT_ERROR)
! 548: warningx(recargchar, optchar);
! 549: optopt = optchar;
! 550: return (BADARG);
! 551: } else /* white space */
! 552: place = nargv[optind];
! 553: #ifdef GNU_COMPATIBLE
! 554: dash_prefix = W_PREFIX;
! 555: #endif
! 556: optchar = parse_long_options(nargv, options, long_options,
! 557: idx, 0, flags);
! 558: place = EMSG;
! 559: return (optchar);
! 560: }
! 561: if (*++oli != ':') { /* doesn't take argument */
! 562: if (!*place)
! 563: ++optind;
! 564: } else { /* takes (optional) argument */
! 565: optarg = NULL;
! 566: if (*place) /* no white space */
! 567: optarg = place;
! 568: else if (oli[1] != ':') { /* arg not optional */
! 569: if (++optind >= nargc) { /* no arg */
! 570: place = EMSG;
! 571: if (PRINT_ERROR)
! 572: warningx(recargchar, optchar);
! 573: optopt = optchar;
! 574: return (BADARG);
! 575: } else
! 576: optarg = nargv[optind];
! 577: }
! 578: place = EMSG;
! 579: ++optind;
! 580: }
! 581: /* dump back option letter */
! 582: return (optchar);
! 583: }
! 584:
! 585: #ifdef REPLACE_GETOPT
! 586: /*
! 587: * getopt --
! 588: * Parse argc/argv argument vector.
! 589: */
! 590: int
! 591: getopt(int nargc, char * const *nargv, const char *options)
! 592: {
! 593:
! 594: /*
! 595: * We don't pass FLAG_PERMUTE to getopt_internal() since
! 596: * the BSD getopt(3) (unlike GNU) has never done this.
! 597: *
! 598: * Furthermore, since many privileged programs call getopt()
! 599: * before dropping privileges it makes sense to keep things
! 600: * as simple (and bug-free) as possible.
! 601: */
! 602: return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
! 603: }
! 604: #endif /* REPLACE_GETOPT */
! 605:
! 606: /*
! 607: * getopt_long --
! 608: * Parse argc/argv argument vector.
! 609: */
! 610: int
! 611: getopt_long(int nargc, char * const *nargv, const char *options,
! 612: const struct option *long_options, int *idx)
! 613: {
! 614:
! 615: return (getopt_internal(nargc, nargv, options, long_options, idx,
! 616: FLAG_PERMUTE));
! 617: }
! 618:
! 619: /*
! 620: * getopt_long_only --
! 621: * Parse argc/argv argument vector.
! 622: */
! 623: int
! 624: getopt_long_only(int nargc, char * const *nargv, const char *options,
! 625: const struct option *long_options, int *idx)
! 626: {
! 627:
! 628: return (getopt_internal(nargc, nargv, options, long_options, idx,
! 629: FLAG_PERMUTE|FLAG_LONGONLY));
! 630: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>