sysctl.c revision 1.55
1/* $OpenBSD: sysctl.c,v 1.55 2000/12/22 22:47:04 deraadt Exp $ */ 2/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */ 3 4/* 5 * Copyright (c) 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#ifndef lint 38static char copyright[] = 39"@(#) Copyright (c) 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41#endif /* not lint */ 42 43#ifndef lint 44#if 0 45static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95"; 46#else 47static char *rcsid = "$OpenBSD: sysctl.c,v 1.55 2000/12/22 22:47:04 deraadt Exp $"; 48#endif 49#endif /* not lint */ 50 51#include <sys/param.h> 52#include <sys/gmon.h> 53#include <sys/mount.h> 54#include <sys/stat.h> 55#include <sys/sysctl.h> 56#include <sys/socket.h> 57#include <vm/vm_param.h> 58#include <machine/cpu.h> 59#include <net/route.h> 60 61#include <netinet/in.h> 62#include <netinet/in_systm.h> 63#include <netinet/ip.h> 64#include <netinet/in_pcb.h> 65#include <netinet/ip_icmp.h> 66#include <netinet/ip_ipip.h> 67#include <netinet/ip_ether.h> 68#include <netinet/ip_ah.h> 69#include <netinet/ip_esp.h> 70#include <netinet/icmp_var.h> 71#include <netinet/ip_var.h> 72#include <netinet/udp.h> 73#include <netinet/udp_var.h> 74#include <netinet/tcp.h> 75#include <netinet/tcp_timer.h> 76#include <netinet/tcp_var.h> 77#include <netinet/ip_gre.h> 78 79#ifdef INET6 80#include <netinet/ip6.h> 81#include <netinet/icmp6.h> 82#include <netinet6/ip6_var.h> 83#include <netinet6/pim6_var.h> 84#endif 85 86#ifdef UVM 87#include <uvm/uvm_swap_encrypt.h> 88#endif 89 90#include <ufs/ufs/quota.h> 91#include <ufs/ufs/inode.h> 92#include <ufs/ffs/fs.h> 93#include <ufs/ffs/ffs_extern.h> 94 95#include <nfs/rpcv2.h> 96#include <nfs/nfsproto.h> 97#include <nfs/nfs.h> 98 99#include <netipx/ipx.h> 100#include <netipx/ipx_var.h> 101#include <netipx/spx_var.h> 102#include <ddb/db_var.h> 103#include <dev/rndvar.h> 104 105#include <err.h> 106#include <errno.h> 107#include <stdio.h> 108#include <stdlib.h> 109#include <string.h> 110#include <ctype.h> 111 112#ifdef CPU_BIOS 113#include <machine/biosvar.h> 114#endif 115 116struct ctlname topname[] = CTL_NAMES; 117struct ctlname kernname[] = CTL_KERN_NAMES; 118struct ctlname vmname[] = CTL_VM_NAMES; 119struct ctlname fsname[] = CTL_FS_NAMES; 120struct ctlname netname[] = CTL_NET_NAMES; 121struct ctlname hwname[] = CTL_HW_NAMES; 122struct ctlname username[] = CTL_USER_NAMES; 123struct ctlname debugname[CTL_DEBUG_MAXID]; 124struct ctlname *vfsname; 125#ifdef CTL_MACHDEP_NAMES 126struct ctlname machdepname[] = CTL_MACHDEP_NAMES; 127#endif 128struct ctlname ddbname[] = CTL_DDB_NAMES; 129char names[BUFSIZ]; 130int lastused; 131 132struct list { 133 struct ctlname *list; 134 int size; 135}; 136struct list toplist = { topname, CTL_MAXID }; 137struct list secondlevel[] = { 138 { 0, 0 }, /* CTL_UNSPEC */ 139 { kernname, KERN_MAXID }, /* CTL_KERN */ 140 { vmname, VM_MAXID }, /* CTL_VM */ 141 { fsname, FS_MAXID }, /* CTL_FS */ 142 { netname, NET_MAXID }, /* CTL_NET */ 143 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 144 { hwname, HW_MAXID }, /* CTL_HW */ 145#ifdef CTL_MACHDEP_NAMES 146 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ 147#else 148 { 0, 0 }, /* CTL_MACHDEP */ 149#endif 150 { username, USER_MAXID }, /* CTL_USER_NAMES */ 151 { ddbname, DBCTL_MAXID }, /* CTL_DDB_NAMES */ 152 { 0, 0 }, /* CTL_VFS */ 153}; 154 155int Aflag, aflag, nflag, wflag; 156 157/* 158 * Variables requiring special processing. 159 */ 160#define CLOCK 0x00000001 161#define BOOTTIME 0x00000002 162#define CHRDEV 0x00000004 163#define BLKDEV 0x00000008 164#define RNDSTATS 0x00000010 165#define BADDYNAMIC 0x00000020 166#define BIOSGEO 0x00000040 167#define BIOSDEV 0x00000080 168#define MAJ2DEV 0x00000100 169#define UNSIGNED 0x00000200 170 171/* prototypes */ 172void debuginit __P((void)); 173void listall __P((char *, struct list *)); 174void parse __P((char *, int)); 175void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int)); 176void usage __P((void)); 177int findname __P((char *, char *, char **, struct list *)); 178int sysctl_inet __P((char *, char **, int *, int, int *)); 179#ifdef INET6 180int sysctl_inet6 __P((char *, char **, int *, int, int *)); 181#endif 182int sysctl_ipx __P((char *, char **, int *, int, int *)); 183int sysctl_fs __P((char *, char **, int *, int, int *)); 184static int sysctl_vfs __P((char *, char **, int[], int, int *)); 185static int sysctl_vfsgen __P((char *, char **, int[], int, int *)); 186int sysctl_bios __P((char *, char **, int *, int, int *)); 187int sysctl_swpenc __P((char *, char **, int *, int, int *)); 188void vfsinit __P((void)); 189 190int 191main(argc, argv) 192 int argc; 193 char *argv[]; 194{ 195 int ch, lvl1; 196 197 while ((ch = getopt(argc, argv, "Aanw")) != -1) { 198 switch (ch) { 199 200 case 'A': 201 Aflag = 1; 202 break; 203 204 case 'a': 205 aflag = 1; 206 break; 207 208 case 'n': 209 nflag = 1; 210 break; 211 212 case 'w': 213 wflag = 1; 214 break; 215 216 default: 217 usage(); 218 } 219 } 220 argc -= optind; 221 argv += optind; 222 223 if (argc == 0 && (Aflag || aflag)) { 224 debuginit(); 225 vfsinit(); 226 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 227 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 228 exit(0); 229 } 230 if (argc == 0) 231 usage(); 232 for (; *argv != NULL; ++argv) 233 parse(*argv, 1); 234 exit(0); 235} 236 237/* 238 * List all variables known to the system. 239 */ 240void 241listall(prefix, lp) 242 char *prefix; 243 struct list *lp; 244{ 245 int lvl2; 246 char *cp, name[BUFSIZ]; 247 248 if (lp->list == NULL) 249 return; 250 (void)strlcpy(name, prefix, BUFSIZ); 251 cp = &name[strlen(name)]; 252 *cp++ = '.'; 253 for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 254 if (lp->list[lvl2].ctl_name == NULL) 255 continue; 256 (void)strcpy(cp, lp->list[lvl2].ctl_name); 257 parse(name, Aflag); 258 } 259} 260 261/* 262 * Parse a name into a MIB entry. 263 * Lookup and print out the MIB entry if it exists. 264 * Set a new value if requested. 265 */ 266void 267parse(string, flags) 268 char *string; 269 int flags; 270{ 271 int indx, type, state, intval, len; 272 size_t size, newsize = 0; 273 int special = 0; 274 void *newval = 0; 275 quad_t quadval; 276 struct list *lp; 277 int mib[CTL_MAXNAME]; 278 char *cp, *bufp, buf[BUFSIZ]; 279 280 (void)strlcpy(buf, string, sizeof(buf)); 281 bufp = buf; 282 if ((cp = strchr(string, '=')) != NULL) { 283 if (!wflag) 284 errx(2, "must specify -w to set variables"); 285 *strchr(buf, '=') = '\0'; 286 *cp++ = '\0'; 287 while (isspace(*cp)) 288 cp++; 289 newval = cp; 290 newsize = strlen(cp); 291 } 292 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 293 return; 294 mib[0] = indx; 295 if (indx == CTL_VFS) 296 vfsinit(); 297 if (indx == CTL_DEBUG) 298 debuginit(); 299 lp = &secondlevel[indx]; 300 if (lp->list == 0) { 301 warnx("%s: class is not implemented", topname[indx].ctl_name); 302 return; 303 } 304 if (bufp == NULL) { 305 listall(topname[indx].ctl_name, lp); 306 return; 307 } 308 if ((indx = findname(string, "second", &bufp, lp)) == -1) 309 return; 310 mib[1] = indx; 311 type = lp->list[indx].ctl_type; 312 len = 2; 313 switch (mib[0]) { 314 315 case CTL_KERN: 316 switch (mib[1]) { 317 case KERN_PROF: 318 mib[2] = GPROF_STATE; 319 size = sizeof(state); 320 if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) { 321 if (flags == 0) 322 return; 323 if (!nflag) 324 (void)printf("%s: ", string); 325 (void)puts("kernel is not compiled for profiling"); 326 return; 327 } 328 if (!nflag) 329 (void)printf("%s = %s\n", string, 330 state == GMON_PROF_OFF ? "off" : "running"); 331 return; 332 case KERN_VNODE: 333 case KERN_FILE: 334 if (flags == 0) 335 return; 336 warnx("use pstat to view %s information", string); 337 return; 338 case KERN_PROC: 339 if (flags == 0) 340 return; 341 warnx("use ps to view %s information", string); 342 return; 343 case KERN_NTPTIME: 344 if (flags == 0) 345 return; 346 warnx("use xntpdc to view %s information", string); 347 return; 348 case KERN_CLOCKRATE: 349 special |= CLOCK; 350 break; 351 case KERN_BOOTTIME: 352 special |= BOOTTIME; 353 break; 354 case KERN_RND: 355 special |= RNDSTATS; 356 break; 357 case KERN_HOSTID: 358 case KERN_ARND: 359 special |= UNSIGNED; 360 break; 361 } 362 break; 363 364 case CTL_HW: 365 break; 366 367 case CTL_VM: 368 if (mib[1] == VM_LOADAVG) { 369 double loads[3]; 370 371 getloadavg(loads, 3); 372 if (!nflag) 373 (void)printf("%s = ", string); 374 (void)printf("%.2f %.2f %.2f\n", loads[0], 375 loads[1], loads[2]); 376 return; 377 } else if (mib[1] == VM_PSSTRINGS) { 378 struct _ps_strings _ps; 379 380 size = sizeof(_ps); 381 if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) { 382 if (flags == 0) 383 return; 384 if (!nflag) 385 (void)printf("%s: ", string); 386 (void)puts("can't find ps strings"); 387 return; 388 } 389 if (!nflag) 390 (void)printf("%s = ", string); 391 (void)printf("%p\n", _ps.val); 392 return; 393 } 394#ifdef UVM 395 else if (mib[1] == VM_SWAPENCRYPT) { 396 len = sysctl_swpenc(string, &bufp, mib, flags, &type); 397 if (len < 0) 398 return; 399 400 break; 401 } 402#endif 403 if (flags == 0) 404 return; 405 warnx("use vmstat or systat to view %s information", string); 406 return; 407 408 break; 409 410 case CTL_NET: 411 if (mib[1] == PF_INET) { 412 len = sysctl_inet(string, &bufp, mib, flags, &type); 413 if (len < 0) 414 return; 415 416 if ((mib[2] == IPPROTO_TCP && 417 mib[3] == TCPCTL_BADDYNAMIC) || 418 (mib[2] == IPPROTO_UDP && 419 mib[3] == UDPCTL_BADDYNAMIC)) { 420 421 special |= BADDYNAMIC; 422 423 if (newval != NULL) 424 parse_baddynamic(mib, len, string, 425 &newval, &newsize, flags, nflag); 426 } 427 break; 428 } 429#ifdef INET6 430 if (mib[1] == PF_INET6) { 431 len = sysctl_inet6(string, &bufp, mib, flags, &type); 432 if (len < 0) 433 return; 434 435 break; 436 } 437#endif 438 if (mib[1] == PF_IPX) { 439 len = sysctl_ipx(string, &bufp, mib, flags, &type); 440 if (len >= 0) 441 break; 442 return; 443 } 444 if (flags == 0) 445 return; 446 warnx("use netstat to view %s information", string); 447 return; 448 449 case CTL_DEBUG: 450 mib[2] = CTL_DEBUG_VALUE; 451 len = 3; 452 break; 453 454 case CTL_MACHDEP: 455#ifdef CPU_CONSDEV 456 if (mib[1] == CPU_CONSDEV) 457 special |= CHRDEV; 458#endif 459#ifdef CPU_BLK2CHR 460 if (mib[1] == CPU_BLK2CHR) { 461 if (bufp == NULL) 462 return; 463 mib[2] = makedev(atoi(bufp),0); 464 bufp = NULL; 465 len = 3; 466 special |= CHRDEV; 467 break; 468 } 469#endif 470#ifdef CPU_CHR2BLK 471 if (mib[1] == CPU_CHR2BLK) { 472 if (bufp == NULL) 473 return; 474 mib[2] = makedev(atoi(bufp),0); 475 bufp = NULL; 476 len = 3; 477 special |= BLKDEV; 478 break; 479 } 480#endif 481#ifdef CPU_BIOS 482 if (mib[1] == CPU_BIOS) { 483 len = sysctl_bios(string, &bufp, mib, flags, &type); 484 if (len < 0) 485 return; 486 if (mib[2] == BIOS_DEV) 487 special |= BIOSDEV; 488 if (mib[2] == BIOS_DISKINFO) 489 special |= BIOSGEO; 490 break; 491 } 492#endif 493 break; 494 495 case CTL_FS: 496 len = sysctl_fs(string, &bufp, mib, flags, &type); 497 if (len >= 0) 498 break; 499 return; 500 501 case CTL_VFS: 502 if (mib[1]) 503 len = sysctl_vfs(string, &bufp, mib, flags, &type); 504 else 505 len = sysctl_vfsgen(string, &bufp, mib, flags, &type); 506 if (len >= 0) { 507 if (type == CTLTYPE_STRUCT) { 508 if (flags) 509 warnx("use nfsstat to view %s information", 510 MOUNT_NFS); 511 return; 512 } else 513 break; 514 } 515 return; 516 517 case CTL_USER: 518 case CTL_DDB: 519 break; 520 521 default: 522 warnx("illegal top level value: %d", mib[0]); 523 return; 524 525 } 526 if (bufp) { 527 warnx("name %s in %s is unknown", bufp, string); 528 return; 529 } 530 if (newsize > 0) { 531 switch (type) { 532 case CTLTYPE_INT: 533 errno = 0; 534 if (special & UNSIGNED) 535 intval = strtoul(newval, &cp, 10); 536 else 537 intval = strtol(newval, &cp, 10); 538 if (*cp != '\0') { 539 warnx("%s: illegal value: %s", string, 540 (char *)newval); 541 return; 542 } 543 if (errno == ERANGE) { 544 warnx("%s: value %s out of range", string, 545 (char *)newval); 546 return; 547 } 548 newval = &intval; 549 newsize = sizeof(intval); 550 break; 551 552 case CTLTYPE_QUAD: 553 (void)sscanf(newval, "%qd", &quadval); 554 newval = &quadval; 555 newsize = sizeof(quadval); 556 break; 557 } 558 } 559 size = BUFSIZ; 560 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 561 if (flags == 0) 562 return; 563 switch (errno) { 564 case EOPNOTSUPP: 565 warnx("%s: value is not available", string); 566 return; 567 case ENOTDIR: 568 warnx("%s: specification is incomplete", string); 569 return; 570 case ENOMEM: 571 warnx("%s: type is unknown to this program", string); 572 return; 573 case ENXIO: 574 if (special & BIOSGEO) 575 return; 576 default: 577 warn("%s", string); 578 return; 579 } 580 } 581 if (special & CLOCK) { 582 struct clockinfo *clkp = (struct clockinfo *)buf; 583 584 if (!nflag) 585 (void)printf("%s = ", string); 586 (void)printf( 587 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 588 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 589 return; 590 } 591 if (special & BOOTTIME) { 592 struct timeval *btp = (struct timeval *)buf; 593 time_t boottime; 594 595 if (!nflag) { 596 boottime = btp->tv_sec; 597 (void)printf("%s = %s", string, ctime(&boottime)); 598 } else 599 (void)printf("%ld\n", btp->tv_sec); 600 return; 601 } 602 if (special & BLKDEV) { 603 dev_t dev = *(dev_t *)buf; 604 605 if (!nflag) 606 (void)printf("%s = %s\n", string, 607 devname(dev, S_IFBLK)); 608 else 609 (void)printf("0x%x\n", dev); 610 return; 611 } 612 if (special & CHRDEV) { 613 dev_t dev = *(dev_t *)buf; 614 615 if (!nflag) 616 (void)printf("%s = %s\n", string, 617 devname(dev, S_IFCHR)); 618 else 619 (void)printf("0x%x\n", dev); 620 return; 621 } 622#ifdef CPU_BIOS 623 if (special & BIOSGEO) { 624 bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf; 625 626 if (!nflag) 627 (void)printf("%s = ", string); 628 (void)printf("bootdev = 0x%x, " 629 "cylinders = %u, heads = %u, sectors = %u\n", 630 pdi->bsd_dev, pdi->bios_cylinders, pdi->bios_heads, 631 pdi->bios_sectors); 632 return; 633 } 634 if (special & BIOSDEV) { 635 int dev = *(int*)buf; 636 637 if (!nflag) 638 (void)printf("%s = ", string); 639 (void) printf("0x%02x\n", dev); 640 return; 641 } 642#endif 643 if (special & UNSIGNED) { 644 if (newsize == 0) { 645 if (!nflag) 646 (void)printf("%s = ", string); 647 (void)printf("%u\n", *(u_int *)buf); 648 } else { 649 if (!nflag) 650 (void)printf("%s: %u -> ", string, 651 *(u_int *)buf); 652 (void)printf("%u\n", *(u_int *)newval); 653 } 654 return; 655 } 656 if (special & RNDSTATS) { 657 struct rndstats *rndstats = (struct rndstats *)buf; 658 int i; 659 660 if (!nflag) 661 (void)printf("%s = ", string); 662 (void)printf( 663 "%qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu", 664 rndstats->rnd_total, 665 rndstats->rnd_used, rndstats->rnd_reads, 666 rndstats->arc4_reads, rndstats->arc4_nstirs, 667 rndstats->arc4_stirs, 668 rndstats->rnd_pad[0], 669 rndstats->rnd_pad[1], 670 rndstats->rnd_pad[2], 671 rndstats->rnd_pad[3], 672 rndstats->rnd_pad[4], 673 rndstats->rnd_waits, 674 rndstats->rnd_enqs, rndstats->rnd_deqs, 675 rndstats->rnd_drops, rndstats->rnd_drople); 676 for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]); i++) 677 (void)printf(" %qu", rndstats->rnd_ed[i]); 678 for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]); i++) 679 (void)printf(" %qu", rndstats->rnd_sc[i]); 680 for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]); i++) 681 (void)printf(" %qu", rndstats->rnd_sb[i]); 682 printf("\n"); 683 return; 684 } 685 if (special & BADDYNAMIC) { 686 in_port_t port, lastport; 687 u_int32_t *baddynamic = (u_int32_t *)buf; 688 689 if (!nflag) 690 (void)printf("%s%s", string, newsize ? ": " : " = "); 691 lastport = 0; 692 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++) 693 if (DP_ISSET(baddynamic, port)) { 694 (void)printf("%s%hd", lastport ? "," : "", 695 port); 696 lastport = port; 697 } 698 if (newsize != 0) { 699 if (!nflag) 700 fputs(" -> ", stdout); 701 baddynamic = (u_int32_t *)newval; 702 lastport = 0; 703 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; 704 port++) 705 if (DP_ISSET(baddynamic, port)) { 706 (void)printf("%s%hd", 707 lastport ? "," : "", port); 708 lastport = port; 709 } 710 } 711 (void)putchar('\n'); 712 return; 713 } 714 switch (type) { 715 case CTLTYPE_INT: 716 if (newsize == 0) { 717 if (!nflag) 718 (void)printf("%s = ", string); 719 (void)printf("%d\n", *(int *)buf); 720 } else { 721 if (!nflag) 722 (void)printf("%s: %d -> ", string, 723 *(int *)buf); 724 (void)printf("%d\n", *(int *)newval); 725 } 726 return; 727 728 case CTLTYPE_STRING: 729 if (newsize == 0) { 730 if (!nflag) 731 (void)printf("%s = ", string); 732 (void)puts(buf); 733 } else { 734 if (!nflag) 735 (void)printf("%s: %s -> ", string, buf); 736 (void)puts((char *)newval); 737 } 738 return; 739 740 case CTLTYPE_QUAD: 741 if (newsize == 0) { 742 if (!nflag) 743 (void)printf("%s = ", string); 744 (void)printf("%qd\n", *(quad_t *)buf); 745 } else { 746 if (!nflag) 747 (void)printf("%s: %qd -> ", string, 748 *(quad_t *)buf); 749 (void)printf("%qd\n", *(quad_t *)newval); 750 } 751 return; 752 753 case CTLTYPE_STRUCT: 754 warnx("%s: unknown structure returned", string); 755 return; 756 757 default: 758 case CTLTYPE_NODE: 759 warnx("%s: unknown type returned", string); 760 return; 761 } 762} 763 764void 765parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag) 766 int mib[]; 767 size_t len; 768 char *string; 769 void **newvalp; 770 size_t *newsizep; 771 int flags; 772 int nflag; 773{ 774 static u_int32_t newbaddynamic[DP_MAPSIZE]; 775 in_port_t port; 776 size_t size; 777 char action, *cp; 778 779 if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) { 780 size = sizeof(newbaddynamic); 781 if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) { 782 if (flags == 0) 783 return; 784 if (!nflag) 785 (void)printf("%s: ", string); 786 (void)puts("kernel does contain bad dynamic port tables"); 787 return; 788 } 789 790 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 791 if (*cp != '+' && *cp != '-') 792 errx(1, "cannot mix +/- with full list"); 793 action = *cp++; 794 port = atoi(cp); 795 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 796 errx(1, "invalid port, range is %d to %d", 797 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 798 if (action == '+') 799 DP_SET(newbaddynamic, port); 800 else 801 DP_CLR(newbaddynamic, port); 802 } 803 } else { 804 (void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic)); 805 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 806 port = atoi(cp); 807 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 808 errx(1, "invalid port, range is %d to %d", 809 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 810 DP_SET(newbaddynamic, port); 811 } 812 } 813 814 *newvalp = (void *)newbaddynamic; 815 *newsizep = sizeof(newbaddynamic); 816} 817 818/* 819 * Initialize the set of debugging names 820 */ 821void 822debuginit() 823{ 824 int mib[3], loc, i; 825 size_t size; 826 827 if (secondlevel[CTL_DEBUG].list != 0) 828 return; 829 secondlevel[CTL_DEBUG].list = debugname; 830 mib[0] = CTL_DEBUG; 831 mib[2] = CTL_DEBUG_NAME; 832 for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) { 833 mib[1] = i; 834 size = BUFSIZ - loc; 835 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 836 continue; 837 debugname[i].ctl_name = &names[loc]; 838 debugname[i].ctl_type = CTLTYPE_INT; 839 loc += size; 840 } 841 lastused = loc; 842} 843 844struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES; 845struct ctlname ffsname[] = FFS_NAMES; 846struct ctlname nfsname[] = FS_NFS_NAMES; 847struct list *vfsvars; 848int *vfs_typenums; 849 850/* 851 * Initialize the set of filesystem names 852 */ 853void 854vfsinit() 855{ 856 int mib[4], maxtypenum, cnt, loc, size; 857 struct vfsconf vfc; 858 size_t buflen; 859 860 if (secondlevel[CTL_VFS].list != 0) 861 return; 862 mib[0] = CTL_VFS; 863 mib[1] = VFS_GENERIC; 864 mib[2] = VFS_MAXTYPENUM; 865 buflen = 4; 866 if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0) 867 return; 868 maxtypenum++; /* + generic */ 869 if ((vfs_typenums = malloc(maxtypenum * sizeof(int))) == NULL) 870 return; 871 memset(vfs_typenums, 0, maxtypenum * sizeof(int)); 872 if ((vfsvars = malloc(maxtypenum * sizeof(*vfsvars))) == NULL) { 873 free(vfs_typenums); 874 return; 875 } 876 memset(vfsvars, 0, maxtypenum * sizeof(*vfsvars)); 877 if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == NULL) { 878 free(vfs_typenums); 879 free(vfsvars); 880 return; 881 } 882 memset(vfsname, 0, maxtypenum * sizeof(*vfsname)); 883 mib[2] = VFS_CONF; 884 buflen = sizeof vfc; 885 for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) { 886 mib[3] = cnt - 1; 887 if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) { 888 if (errno == EOPNOTSUPP) 889 continue; 890 warn("vfsinit"); 891 free(vfsname); 892 return; 893 } 894 if (!strcmp(vfc.vfc_name, MOUNT_FFS)) { 895 vfsvars[cnt].list = ffsname; 896 vfsvars[cnt].size = FFS_MAXID; 897 } 898 if (!strcmp(vfc.vfc_name, MOUNT_NFS)) { 899 vfsvars[cnt].list = nfsname; 900 vfsvars[cnt].size = NFS_MAXID; 901 } 902 vfs_typenums[cnt] = vfc.vfc_typenum; 903 strcat(&names[loc], vfc.vfc_name); 904 vfsname[cnt].ctl_name = &names[loc]; 905 vfsname[cnt].ctl_type = CTLTYPE_NODE; 906 size = strlen(vfc.vfc_name) + 1; 907 loc += size; 908 } 909 lastused = loc; 910 911 vfsname[0].ctl_name = "mounts"; 912 vfsname[0].ctl_type = CTLTYPE_NODE; 913 vfsvars[0].list = vfsname + 1; 914 vfsvars[0].size = maxtypenum - 1; 915 916 secondlevel[CTL_VFS].list = vfsname; 917 secondlevel[CTL_VFS].size = maxtypenum; 918 return; 919} 920 921int 922sysctl_vfsgen(string, bufpp, mib, flags, typep) 923 char *string; 924 char **bufpp; 925 int mib[]; 926 int flags; 927 int *typep; 928{ 929 int indx; 930 size_t size; 931 struct vfsconf vfc; 932 933 if (*bufpp == NULL) { 934 listall(string, vfsvars); 935 return (-1); 936 } 937 938 if ((indx = findname(string, "third", bufpp, vfsvars)) == -1) 939 return (-1); 940 941 mib[1] = VFS_GENERIC; 942 mib[2] = VFS_CONF; 943 mib[3] = indx; 944 size = sizeof vfc; 945 if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) { 946 if (errno != EOPNOTSUPP) 947 warn("vfs print"); 948 return -1; 949 } 950 if (flags == 0 && vfc.vfc_refcount == 0) 951 return -1; 952 if (!nflag) 953 fprintf(stdout, "%s has %d mounted instance%s\n", 954 string, vfc.vfc_refcount, 955 vfc.vfc_refcount != 1 ? "s" : ""); 956 else 957 fprintf(stdout, "%d\n", vfc.vfc_refcount); 958 959 return -1; 960} 961 962int 963sysctl_vfs(string, bufpp, mib, flags, typep) 964 char *string; 965 char **bufpp; 966 int mib[]; 967 int flags; 968 int *typep; 969{ 970 struct list *lp = &vfsvars[mib[1]]; 971 int indx; 972 973 if (lp->list == NULL) { 974 if (flags) 975 warnx("No variables defined for file system %s", string); 976 return(-1); 977 } 978 if (*bufpp == NULL) { 979 listall(string, lp); 980 return (-1); 981 } 982 if ((indx = findname(string, "third", bufpp, lp)) == -1) 983 return (-1); 984 985 mib[1] = vfs_typenums[mib[1]]; 986 mib[2] = indx; 987 *typep = lp->list[indx].ctl_type; 988 return (3); 989} 990 991struct ctlname posixname[] = CTL_FS_POSIX_NAMES; 992struct list fslist = { posixname, FS_POSIX_MAXID }; 993 994/* 995 * handle file system requests 996 */ 997int 998sysctl_fs(string, bufpp, mib, flags, typep) 999 char *string; 1000 char **bufpp; 1001 int mib[]; 1002 int flags; 1003 int *typep; 1004{ 1005 int indx; 1006 1007 if (*bufpp == NULL) { 1008 listall(string, &fslist); 1009 return(-1); 1010 } 1011 if ((indx = findname(string, "third", bufpp, &fslist)) == -1) 1012 return(-1); 1013 mib[2] = indx; 1014 *typep = fslist.list[indx].ctl_type; 1015 return(3); 1016} 1017 1018#ifdef CPU_BIOS 1019struct ctlname biosname[] = CTL_BIOS_NAMES; 1020struct list bioslist = { biosname, BIOS_MAXID }; 1021 1022/* 1023 * handle BIOS requests 1024 */ 1025int 1026sysctl_bios(string, bufpp, mib, flags, typep) 1027 char *string; 1028 char **bufpp; 1029 int mib[]; 1030 int flags; 1031 int *typep; 1032{ 1033 char *name; 1034 int indx; 1035 1036 if (*bufpp == NULL) { 1037 listall(string, &bioslist); 1038 return(-1); 1039 } 1040 if ((indx = findname(string, "third", bufpp, &bioslist)) == -1) 1041 return(-1); 1042 mib[2] = indx; 1043 if (indx == BIOS_DISKINFO) { 1044 if (*bufpp == NULL) { 1045 char name[BUFSIZ]; 1046 1047 /* scan all the bios devices */ 1048 for (indx = 0; indx < 256; indx++) { 1049 snprintf(name, sizeof(name), "%s.%u", 1050 string, indx); 1051 parse(name, 1); 1052 } 1053 return(-1); 1054 } 1055 if ((name = strsep(bufpp, ".")) == NULL) { 1056 warnx("%s: incomplete specification", string); 1057 return(-1); 1058 } 1059 mib[3] = atoi(name); 1060 *typep = CTLTYPE_STRUCT; 1061 return 4; 1062 } else { 1063 *typep = bioslist.list[indx].ctl_type; 1064 return(3); 1065 } 1066} 1067#endif 1068 1069#ifdef UVM 1070struct ctlname swpencname[] = CTL_SWPENC_NAMES; 1071struct list swpenclist = { swpencname, SWPENC_MAXID }; 1072 1073/* 1074 * handle swap encrypt requests 1075 */ 1076int 1077sysctl_swpenc(string, bufpp, mib, flags, typep) 1078 char *string; 1079 char **bufpp; 1080 int mib[]; 1081 int flags; 1082 int *typep; 1083{ 1084 char *name; 1085 int indx; 1086 1087 if (*bufpp == NULL) { 1088 listall(string, &swpenclist); 1089 return(-1); 1090 } 1091 if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1) 1092 return(-1); 1093 mib[2] = indx; 1094 *typep = swpenclist.list[indx].ctl_type; 1095 return(3); 1096} 1097#endif 1098 1099struct ctlname inetname[] = CTL_IPPROTO_NAMES; 1100struct ctlname ipname[] = IPCTL_NAMES; 1101struct ctlname icmpname[] = ICMPCTL_NAMES; 1102struct ctlname ipipname[] = IPIPCTL_NAMES; 1103struct ctlname tcpname[] = TCPCTL_NAMES; 1104struct ctlname udpname[] = UDPCTL_NAMES; 1105struct ctlname espname[] = ESPCTL_NAMES; 1106struct ctlname ahname[] = AHCTL_NAMES; 1107struct ctlname etheripname[] = ETHERIPCTL_NAMES; 1108struct ctlname grename[] = GRECTL_NAMES; 1109struct ctlname mobileipname[] = MOBILEIPCTL_NAMES; 1110struct list inetlist = { inetname, IPPROTO_MAXID }; 1111struct list inetvars[] = { 1112 { ipname, IPCTL_MAXID }, /* ip */ 1113 { icmpname, ICMPCTL_MAXID }, /* icmp */ 1114 { 0, 0 }, /* igmp */ 1115 { 0, 0 }, /* ggmp */ 1116 { ipipname, IPIPCTL_MAXID }, /* ipencap */ 1117 { 0, 0 }, 1118 { tcpname, TCPCTL_MAXID }, /* tcp */ 1119 { 0, 0 }, 1120 { 0, 0 }, /* egp */ 1121 { 0, 0 }, 1122 { 0, 0 }, 1123 { 0, 0 }, 1124 { 0, 0 }, /* pup */ 1125 { 0, 0 }, 1126 { 0, 0 }, 1127 { 0, 0 }, 1128 { 0, 0 }, 1129 { udpname, UDPCTL_MAXID }, /* udp */ 1130 { 0, 0 }, 1131 { 0, 0 }, 1132 { 0, 0 }, 1133 { 0, 0 }, 1134 { 0, 0 }, 1135 { 0, 0 }, 1136 { 0, 0 }, 1137 { 0, 0 }, 1138 { 0, 0 }, 1139 { 0, 0 }, 1140 { 0, 0 }, 1141 { 0, 0 }, 1142 { 0, 0 }, 1143 { 0, 0 }, 1144 { 0, 0 }, 1145 { 0, 0 }, 1146 { 0, 0 }, 1147 { 0, 0 }, 1148 { 0, 0 }, 1149 { 0, 0 }, 1150 { 0, 0 }, 1151 { 0, 0 }, 1152 { 0, 0 }, 1153 { 0, 0 }, 1154 { 0, 0 }, 1155 { 0, 0 }, 1156 { 0, 0 }, 1157 { 0, 0 }, 1158 { 0, 0 }, 1159 { grename, GRECTL_MAXID }, /* GRE */ 1160 { 0, 0 }, 1161 { 0, 0 }, 1162 { espname, ESPCTL_MAXID }, /* esp */ 1163 { ahname, AHCTL_MAXID }, /* ah */ 1164 { 0, 0 }, 1165 { 0, 0 }, 1166 { 0, 0 }, 1167 { mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */ 1168 { 0, 0 }, 1169 { 0, 0 }, 1170 { 0, 0 }, 1171 { 0, 0 }, 1172 { 0, 0 }, 1173 { 0, 0 }, 1174 { 0, 0 }, 1175 { 0, 0 }, 1176 { 0, 0 }, 1177 { 0, 0 }, 1178 { 0, 0 }, 1179 { 0, 0 }, 1180 { 0, 0 }, 1181 { 0, 0 }, 1182 { 0, 0 }, 1183 { 0, 0 }, 1184 { 0, 0 }, 1185 { 0, 0 }, 1186 { 0, 0 }, 1187 { 0, 0 }, 1188 { 0, 0 }, 1189 { 0, 0 }, 1190 { 0, 0 }, 1191 { 0, 0 }, 1192 { 0, 0 }, 1193 { 0, 0 }, 1194 { 0, 0 }, 1195 { 0, 0 }, 1196 { 0, 0 }, 1197 { 0, 0 }, 1198 { 0, 0 }, 1199 { 0, 0 }, 1200 { 0, 0 }, 1201 { 0, 0 }, 1202 { 0, 0 }, 1203 { 0, 0 }, 1204 { 0, 0 }, 1205 { 0, 0 }, 1206 { 0, 0 }, 1207 { 0, 0 }, 1208 { 0, 0 }, 1209 { etheripname, ETHERIPCTL_MAXID }, 1210}; 1211 1212/* 1213 * handle internet requests 1214 */ 1215int 1216sysctl_inet(string, bufpp, mib, flags, typep) 1217 char *string; 1218 char **bufpp; 1219 int mib[]; 1220 int flags; 1221 int *typep; 1222{ 1223 struct list *lp; 1224 int indx; 1225 1226 if (*bufpp == NULL) { 1227 listall(string, &inetlist); 1228 return(-1); 1229 } 1230 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 1231 return(-1); 1232 mib[2] = indx; 1233 if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL) 1234 lp = &inetvars[indx]; 1235 else if (!flags) 1236 return(-1); 1237 else { 1238 warnx("%s: no variables defined for this protocol", string); 1239 return(-1); 1240 } 1241 if (*bufpp == NULL) { 1242 listall(string, lp); 1243 return(-1); 1244 } 1245 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1246 return(-1); 1247 mib[3] = indx; 1248 *typep = lp->list[indx].ctl_type; 1249 return(4); 1250} 1251 1252#ifdef INET6 1253struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES; 1254struct ctlname ip6name[] = IPV6CTL_NAMES; 1255struct ctlname icmp6name[] = ICMPV6CTL_NAMES; 1256struct ctlname pim6name[] = PIM6CTL_NAMES; 1257struct list inet6list = { inet6name, IPV6PROTO_MAXID }; 1258struct list inet6vars[] = { 1259/*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1260 { 0, 0 }, 1261 { 0, 0 }, 1262 { 0, 0 }, 1263 { 0, 0 }, 1264 { 0, 0 }, 1265/*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1266 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1267/*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1268 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1269/*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1270 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1271/*40*/ { 0, 0 }, 1272 { ip6name, IPV6CTL_MAXID }, /* ipv6 */ 1273 { 0, 0 }, 1274 { 0, 0 }, 1275 { 0, 0 }, 1276 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1277/*50*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1278 { 0, 0 }, 1279 { 0, 0 }, 1280 { 0, 0 }, 1281 { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */ 1282 { 0, 0 }, 1283/*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1284 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1285/*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1286 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1287/*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1288 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1289/*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1290 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1291/*100*/ { 0, 0 }, 1292 { 0, 0 }, 1293 { 0, 0 }, 1294 { pim6name, PIM6CTL_MAXID }, /* pim6 */ 1295}; 1296 1297/* 1298 * handle internet6 requests 1299 */ 1300int 1301sysctl_inet6(string, bufpp, mib, flags, typep) 1302 char *string; 1303 char **bufpp; 1304 int mib[]; 1305 int flags; 1306 int *typep; 1307{ 1308 struct list *lp; 1309 int indx; 1310 1311 if (*bufpp == NULL) { 1312 listall(string, &inet6list); 1313 return(-1); 1314 } 1315 if ((indx = findname(string, "third", bufpp, &inet6list)) == -1) 1316 return(-1); 1317 mib[2] = indx; 1318 if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL) 1319 lp = &inet6vars[indx]; 1320 else if (!flags) 1321 return(-1); 1322 else { 1323 warnx("%s: no variables defined for this protocol", string); 1324 return(-1); 1325 } 1326 if (*bufpp == NULL) { 1327 listall(string, lp); 1328 return(-1); 1329 } 1330 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1331 return(-1); 1332 mib[3] = indx; 1333 *typep = lp->list[indx].ctl_type; 1334 return(4); 1335} 1336#endif 1337 1338struct ctlname ipxname[] = CTL_IPXPROTO_NAMES; 1339struct ctlname ipxpname[] = IPXCTL_NAMES; 1340struct ctlname spxpname[] = SPXCTL_NAMES; 1341struct list ipxlist = { ipxname, IPXCTL_MAXID }; 1342struct list ipxvars[] = { 1343 { ipxpname, IPXCTL_MAXID }, /* ipx */ 1344 { 0, 0 }, 1345 { 0, 0 }, 1346 { 0, 0 }, 1347 { 0, 0 }, 1348 { spxpname, SPXCTL_MAXID }, 1349}; 1350 1351/* 1352 * Handle internet requests 1353 */ 1354int 1355sysctl_ipx(string, bufpp, mib, flags, typep) 1356 char *string; 1357 char **bufpp; 1358 int mib[]; 1359 int flags; 1360 int *typep; 1361{ 1362 struct list *lp; 1363 int indx; 1364 1365 if (*bufpp == NULL) { 1366 listall(string, &ipxlist); 1367 return(-1); 1368 } 1369 if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1) 1370 return(-1); 1371 mib[2] = indx; 1372 if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL) 1373 lp = &ipxvars[indx]; 1374 else if (!flags) 1375 return(-1); 1376 else { 1377 warnx("%s: no variables defined for this protocol", string); 1378 return(-1); 1379 } 1380 if (*bufpp == NULL) { 1381 listall(string, lp); 1382 return(-1); 1383 } 1384 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1385 return(-1); 1386 mib[3] = indx; 1387 *typep = lp->list[indx].ctl_type; 1388 return(4); 1389} 1390 1391/* 1392 * Scan a list of names searching for a particular name. 1393 */ 1394int 1395findname(string, level, bufp, namelist) 1396 char *string; 1397 char *level; 1398 char **bufp; 1399 struct list *namelist; 1400{ 1401 char *name; 1402 int i; 1403 1404 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 1405 warnx("%s: incomplete specification", string); 1406 return(-1); 1407 } 1408 for (i = 0; i < namelist->size; i++) 1409 if (namelist->list[i].ctl_name != NULL && 1410 strcmp(name, namelist->list[i].ctl_name) == 0) 1411 break; 1412 if (i == namelist->size) { 1413 warnx("%s level name %s in %s is invalid", level, name, string); 1414 return(-1); 1415 } 1416 return(i); 1417} 1418 1419void 1420usage() 1421{ 1422 1423 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 1424 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 1425 "sysctl [-n] -a", "sysctl [-n] -A"); 1426 exit(1); 1427} 1428