1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * scan /dev directory for mountable objects and construct device_allocate 31 * file for allocate.... 32 * 33 * devices are: 34 * tape (cartridge) 35 * /dev/rst* 36 * /dev/nrst* 37 * /dev/rmt/... 38 * audio 39 * /dev/audio 40 * /dev/audioctl 41 * /dev/sound/... 42 * floppy 43 * /dev/diskette 44 * /dev/fd* 45 * /dev/rdiskette 46 * /dev/rfd* 47 * CD 48 * /dev/sr* 49 * /dev/nsr* 50 * /dev/dsk/c?t?d0s? 51 * /dev/rdsk/c?t?d0s? 52 */ 53 54 #include <sys/types.h> /* for stat(2), etc. */ 55 #include <sys/stat.h> 56 #include <dirent.h> /* for readdir(3), etc. */ 57 #include <unistd.h> /* for readlink(2) */ 58 #include <string.h> /* for strcpy(3), etc. */ 59 #include <strings.h> /* for bcopy(3C), etc. */ 60 #include <stdio.h> /* for perror(3) */ 61 #include <stdlib.h> /* for atoi(3) */ 62 #include <locale.h> 63 #include <libintl.h> 64 #include <auth_attr.h> 65 #include <auth_list.h> 66 #include "allocate.h" /* for SECLIB */ 67 68 #ifndef TEXT_DOMAIN 69 #define TEXT_DOMAIN "SUNW_OST_OSCMD" 70 #endif 71 72 #define DELTA 5 /* array size delta when full */ 73 74 /* "/dev/rst...", "/dev/nrst...", "/dev/rmt/..." */ 75 struct tape { 76 char *name; 77 char *device; 78 int number; 79 } *tape; 80 #define DFLT_NTAPE 10 /* size of initial array */ 81 #define SIZE_OF_RST 3 /* |rmt| */ 82 #define SIZE_OF_NRST 4 /* |nrmt| */ 83 #define SIZE_OF_TMP 4 /* |/tmp| */ 84 #define SIZE_OF_RMT 8 /* |/dev/rmt| */ 85 86 /* "/dev/audio", "/dev/audioctl", "/dev/sound/..." */ 87 struct audio { 88 char *name; 89 char *device; 90 int number; 91 } *audio; 92 #define DFLT_NAUDIO 10 /* size of initial array */ 93 #define SIZE_OF_SOUND 10 /* |/dev/sound| */ 94 95 /* "/dev/sr", "/dev/nsr", "/dev/dsk/c?t?d0s?", "/dev/rdsk/c?t?d0s?" */ 96 struct cd { 97 char *name; 98 char *device; 99 int id; 100 int controller; 101 int number; 102 } *cd; 103 #define DFLT_NCD 10 /* size of initial array */ 104 #define SIZE_OF_SR 2 /* |sr| */ 105 #define SIZE_OF_RSR 3 /* |rsr| */ 106 #define SIZE_OF_DSK 8 /* |/dev/dsk| */ 107 #define SIZE_OF_RDSK 9 /* |/dev/rdsk| */ 108 109 110 /* "/dev/fd0*", "/dev/rfd0*", "/dev/fd1*", "/dev/rfd1*" */ 111 struct fp { 112 char *name; 113 char *device; 114 int number; 115 } *fp; 116 #define DFLT_NFP 10 /* size of initial array */ 117 #define SIZE_OF_FD0 3 /* |fd0| */ 118 #define SIZE_OF_RFD0 4 /* |rfd0| */ 119 120 static void dotape(); 121 static void doaudio(); 122 static void dofloppy(); 123 static void docd(); 124 static void initmem(); 125 static int expandmem(int, void **, int); 126 static void no_memory(void); 127 128 int 129 main(void) 130 { 131 (void) setlocale(LC_ALL, ""); 132 (void) textdomain(TEXT_DOMAIN); 133 134 initmem(); /* initialize memory */ 135 136 dotape(); /* do tape */ 137 138 doaudio(); /* do audio */ 139 140 dofloppy(); /* do floppy */ 141 142 docd(); /* do cd */ 143 144 return (0); 145 } 146 147 static void 148 dotape() 149 { 150 DIR *dirp; 151 struct dirent *dep; /* directory entry pointer */ 152 int i, j, n; 153 char *nm; /* name/device of special device */ 154 char linkvalue[2048]; /* symlink value */ 155 struct stat stat; /* determine if it's a symlink */ 156 int sz; /* size of symlink value */ 157 char *cp; /* pointer into string */ 158 int ntape; /* max array size */ 159 160 ntape = DFLT_NTAPE; 161 162 /* 163 * look for rst* and nrst* 164 */ 165 166 if ((dirp = opendir("/dev")) == NULL) { 167 perror(gettext("open /dev failure")); 168 exit(1); 169 } 170 171 i = 0; 172 while (dep = readdir(dirp)) { 173 /* ignore if neither rst* nor nrst* */ 174 if (strncmp(dep->d_name, "rst", SIZE_OF_RST) && 175 strncmp(dep->d_name, "nrst", SIZE_OF_NRST)) 176 continue; 177 178 /* if array full, then expand it */ 179 if (i == ntape) { 180 /* will exit(1) if insufficient memory */ 181 ntape = expandmem(i, (void **)&tape, 182 sizeof (struct tape)); 183 } 184 185 /* save name (/dev + / + d_name + \0) */ 186 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 187 if (nm == NULL) 188 no_memory(); 189 (void) strcpy(nm, "/dev/"); 190 (void) strcat(nm, dep->d_name); 191 tape[i].name = nm; 192 193 /* ignore if not symbolic link (note i not incremented) */ 194 if (lstat(tape[i].name, &stat) < 0) { 195 perror("stat(2) failed "); 196 exit(1); 197 } 198 if ((stat.st_mode & S_IFMT) != S_IFLNK) 199 continue; 200 201 /* get name from symbolic link */ 202 if ((sz = readlink(tape[i].name, linkvalue, 203 sizeof (linkvalue))) < 0) 204 continue; 205 nm = (char *)malloc(sz + 1); 206 if (nm == NULL) 207 no_memory(); 208 (void) strncpy(nm, linkvalue, sz); 209 nm[sz] = '\0'; 210 tape[i].device = nm; 211 212 /* get device number */ 213 cp = strrchr(tape[i].device, '/'); 214 cp++; /* advance to device # */ 215 (void) sscanf(cp, "%d", &tape[i].number); 216 217 i++; 218 } 219 220 (void) closedir(dirp); 221 222 /* 223 * scan /dev/rmt and add entry to table 224 */ 225 226 if ((dirp = opendir("/dev/rmt")) == NULL) { 227 perror(gettext("open /dev failure")); 228 exit(1); 229 } 230 231 while (dep = readdir(dirp)) { 232 /* skip . .. etc... */ 233 if (strncmp(dep->d_name, ".", 1) == NULL) 234 continue; 235 236 /* if array full, then expand it */ 237 if (i == ntape) { 238 /* will exit(1) if insufficient memory */ 239 ntape = expandmem(i, (void **)&tape, 240 sizeof (struct tape)); 241 } 242 243 /* save name (/dev/rmt + / + d_name + \0) */ 244 nm = (char *)malloc(SIZE_OF_RMT + 1 + strlen(dep->d_name) + 1); 245 if (nm == NULL) 246 no_memory(); 247 (void) strcpy(nm, "/dev/rmt/"); 248 (void) strcat(nm, dep->d_name); 249 tape[i].name = nm; 250 251 /* save device name (rmt/ + d_name + \0) */ 252 nm = (char *)malloc(SIZE_OF_TMP + strlen(dep->d_name) + 1); 253 if (nm == NULL) 254 no_memory(); 255 (void) strcpy(nm, "rmt/"); 256 (void) strcat(nm, dep->d_name); 257 tape[i].device = nm; 258 259 (void) sscanf(dep->d_name, "%d", &tape[i].number); 260 261 i++; 262 } 263 n = i; 264 265 (void) closedir(dirp); 266 267 /* remove duplicate entries */ 268 for (i = 0; i < n - 1; i++) { 269 for (j = i + 1; j < n; j++) { 270 if (strcmp(tape[i].device, tape[j].device)) 271 continue; 272 tape[j].number = -1; 273 } 274 } 275 276 /* print out device_allocate entries for tape devices */ 277 for (i = 0; i < 8; i++) { 278 for (j = 0; j < n; j++) { 279 if (tape[j].number == i) { 280 (void) printf( 281 "st%d;st;reserved;reserved;%s;", 282 i, DEFAULT_DEV_ALLOC_AUTH); 283 (void) printf("%s%s\n", SECLIB, "/st_clean"); 284 break; 285 } 286 } 287 } 288 } 289 290 static void 291 doaudio() 292 { 293 DIR *dirp; 294 struct dirent *dep; /* directory entry pointer */ 295 int i, j, n; 296 char *nm; /* name/device of special device */ 297 char linkvalue[2048]; /* symlink value */ 298 struct stat stat; /* determine if it's a symlink */ 299 int sz; /* size of symlink value */ 300 char *cp; /* pointer into string */ 301 int naudio; /* max array size */ 302 303 naudio = DFLT_NAUDIO; 304 305 if ((dirp = opendir("/dev")) == NULL) { 306 perror(gettext("open /dev failure")); 307 exit(1); 308 } 309 310 i = 0; 311 while (dep = readdir(dirp)) { 312 if (strcmp(dep->d_name, "audio") && 313 strcmp(dep->d_name, "audioctl")) 314 continue; 315 316 /* if array full, then expand it */ 317 if (i == naudio) { 318 /* will exit(1) if insufficient memory */ 319 naudio = expandmem(i, (void **)&audio, 320 sizeof (struct audio)); 321 } 322 323 /* save name (/dev + 1 + d_name + \0) */ 324 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 325 if (nm == NULL) 326 no_memory(); 327 (void) strcpy(nm, "/dev/"); 328 (void) strcat(nm, dep->d_name); 329 audio[i].name = nm; 330 331 /* ignore if not symbolic link (note i not incremented) */ 332 if (lstat(audio[i].name, &stat) < 0) { 333 perror(gettext("stat(2) failed ")); 334 exit(1); 335 } 336 if ((stat.st_mode & S_IFMT) != S_IFLNK) 337 continue; 338 339 /* get name from symbolic link */ 340 if ((sz = readlink(audio[i].name, linkvalue, 341 sizeof (linkvalue))) < 0) 342 continue; 343 nm = (char *)malloc(sz + 1); 344 if (nm == NULL) 345 no_memory(); 346 (void) strncpy(nm, linkvalue, sz); 347 nm[sz] = '\0'; 348 audio[i].device = nm; 349 350 cp = strrchr(audio[i].device, '/'); 351 cp++; /* advance to device # */ 352 (void) sscanf(cp, "%d", &audio[i].number); 353 354 i++; 355 } 356 357 (void) closedir(dirp); 358 359 if ((dirp = opendir("/dev/sound")) == NULL) { 360 goto skip; 361 } 362 363 while (dep = readdir(dirp)) { 364 /* skip . .. etc... */ 365 if (strncmp(dep->d_name, ".", 1) == NULL) 366 continue; 367 368 /* if array full, then expand it */ 369 if (i == naudio) { 370 /* will exit(1) if insufficient memory */ 371 naudio = expandmem(i, (void **)&audio, 372 sizeof (struct audio)); 373 } 374 375 /* save name (/dev/sound + / + d_name + \0) */ 376 nm = (char *)malloc(SIZE_OF_SOUND + 1 + 377 strlen(dep->d_name) + 1); 378 if (nm == NULL) 379 no_memory(); 380 (void) strcpy(nm, "/dev/sound/"); 381 (void) strcat(nm, dep->d_name); 382 audio[i].name = nm; 383 384 nm = (char *)malloc(SIZE_OF_SOUND + 1 + 385 strlen(dep->d_name) + 1); 386 if (nm == NULL) 387 no_memory(); 388 (void) strcpy(nm, "/dev/sound/"); 389 (void) strcat(nm, dep->d_name); 390 audio[i].device = nm; 391 392 (void) sscanf(dep->d_name, "%d", &audio[i].number); 393 394 i++; 395 } 396 397 (void) closedir(dirp); 398 399 skip: 400 n = i; 401 402 /* remove duplicate entries */ 403 for (i = 0; i < n - 1; i++) { 404 for (j = i + 1; j < n; j++) { 405 if (strcmp(audio[i].device, audio[j].device)) 406 continue; 407 audio[j].number = -1; 408 } 409 } 410 411 /* print out device_allocate entries for tape devices */ 412 for (i = 0; i < 8; i++) { 413 for (j = 0; j < n; j++) { 414 if (audio[j].number == i) { 415 (void) printf("audio;audio;"); 416 (void) printf("reserved;reserved;%s;", 417 DEFAULT_DEV_ALLOC_AUTH); 418 (void) printf("%s%s\n", SECLIB, "/audio_clean"); 419 break; 420 } 421 } 422 } 423 } 424 425 static void 426 dofloppy() 427 { 428 DIR *dirp; 429 struct dirent *dep; /* directory entry pointer */ 430 int i, j, n; 431 char *nm; /* name/device of special device */ 432 char linkvalue[2048]; /* symlink value */ 433 struct stat stat; /* determine if it's a symlink */ 434 int sz; /* size of symlink value */ 435 char *cp; /* pointer into string */ 436 int nfp; /* max array size */ 437 438 nfp = DFLT_NFP; 439 440 /* 441 * look for fd* and rfd* 442 */ 443 444 if ((dirp = opendir("/dev")) == NULL) { 445 perror(gettext("open /dev failure")); 446 exit(1); 447 } 448 449 i = 0; 450 while (dep = readdir(dirp)) { 451 /* ignore if neither rst* nor nrst* */ 452 if (strncmp(dep->d_name, "fd0", SIZE_OF_FD0) && 453 strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0) && 454 strncmp(dep->d_name, "fd1", SIZE_OF_FD0) && 455 strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0)) 456 continue; 457 458 /* if array full, then expand it */ 459 if (i == nfp) { 460 /* will exit(1) if insufficient memory */ 461 nfp = expandmem(i, (void **)&fp, sizeof (struct fp)); 462 } 463 464 /* save name (/dev + 1 + d_name + \0) */ 465 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 466 if (nm == NULL) 467 no_memory(); 468 (void) strcpy(nm, "/dev/"); 469 (void) strcat(nm, dep->d_name); 470 fp[i].name = nm; 471 472 /* ignore if not symbolic link (note i not incremented) */ 473 if (lstat(fp[i].name, &stat) < 0) { 474 perror(gettext("stat(2) failed ")); 475 exit(1); 476 } 477 if ((stat.st_mode&S_IFMT) != S_IFLNK) 478 continue; 479 480 /* get name from symbolic link */ 481 if ((sz = readlink(fp[i].name, linkvalue, 482 sizeof (linkvalue))) < 0) 483 continue; 484 nm = (char *)malloc(sz+1); 485 if (nm == NULL) 486 no_memory(); 487 (void) strncpy(nm, linkvalue, sz); 488 nm[sz] = '\0'; 489 fp[i].device = nm; 490 491 /* get device number */ 492 cp = strchr(fp[i].name, 'd'); 493 cp++; /* advance to device # */ 494 cp = strchr(cp, 'd'); 495 cp++; /* advance to device # */ 496 (void) sscanf(cp, "%d", &fp[i].number); 497 498 i++; 499 } 500 501 (void) closedir(dirp); 502 503 n = i; 504 505 /* print out device_allocate entries for tape devices */ 506 for (i = 0; i < 8; i++) { 507 for (j = 0; j < n; j++) { 508 if (fp[j].number == i) { 509 (void) printf("fd%d;fd;reserved;reserved;%s;", 510 i, DEFAULT_DEV_ALLOC_AUTH); 511 (void) printf("/etc/security/lib/fd_clean\n"); 512 break; 513 } 514 } 515 } 516 } 517 518 static void 519 docd() 520 { 521 DIR *dirp; 522 struct dirent *dep; /* directory entry pointer */ 523 int i, j, n; 524 char *nm; /* name/device of special device */ 525 char linkvalue[2048]; /* symlink value */ 526 struct stat stat; /* determine if it's a symlink */ 527 int sz; /* size of symlink value */ 528 char *cp; /* pointer into string */ 529 int id; /* disk id */ 530 int ctrl; /* disk controller */ 531 int ncd; /* max array size */ 532 533 ncd = DFLT_NCD; 534 535 /* 536 * look for sr* and rsr* 537 */ 538 539 if ((dirp = opendir("/dev")) == NULL) { 540 perror(gettext("open /dev failure")); 541 exit(1); 542 } 543 544 i = 0; 545 while (dep = readdir(dirp)) { 546 /* ignore if neither sr* nor rsr* */ 547 if (strncmp(dep->d_name, "sr", SIZE_OF_SR) && 548 strncmp(dep->d_name, "rsr", SIZE_OF_RSR)) 549 continue; 550 551 /* if array full, then expand it */ 552 if (i == ncd) { 553 /* will exit(1) if insufficient memory */ 554 ncd = expandmem(i, (void **)&cd, sizeof (struct cd)); 555 } 556 557 /* save name (/dev + / + d_name + \0) */ 558 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 559 if (nm == NULL) 560 no_memory(); 561 (void) strcpy(nm, "/dev/"); 562 (void) strcat(nm, dep->d_name); 563 cd[i].name = nm; 564 565 /* save id # */ 566 if (dep->d_name[0] == 'r') 567 (void) sscanf(dep->d_name, "rsr%d", &cd[i].id); 568 else 569 (void) sscanf(dep->d_name, "sr%d", &cd[i].id); 570 571 /* ignore if not symbolic link (note i not incremented) */ 572 if (lstat(cd[i].name, &stat) < 0) { 573 perror(gettext("stat(2) failed ")); 574 exit(1); 575 } 576 if ((stat.st_mode & S_IFMT) != S_IFLNK) 577 continue; 578 579 /* get name from symbolic link */ 580 if ((sz = readlink(cd[i].name, linkvalue, sizeof (linkvalue))) < 581 0) 582 continue; 583 nm = (char *)malloc(sz + 1); 584 if (nm == NULL) 585 no_memory(); 586 (void) strncpy(nm, linkvalue, sz); 587 nm[sz] = '\0'; 588 cd[i].device = nm; 589 590 cp = strrchr(cd[i].device, '/'); 591 cp++; /* advance to device # */ 592 (void) sscanf(cp, "c%dt%d", &cd[i].controller, &cd[i].number); 593 594 i++; 595 } 596 n = i; 597 598 (void) closedir(dirp); 599 600 /* 601 * scan /dev/dsk for cd devices 602 */ 603 604 if ((dirp = opendir("/dev/dsk")) == NULL) { 605 perror("gettext(open /dev/dsk failure)"); 606 exit(1); 607 } 608 609 while (dep = readdir(dirp)) { 610 /* skip . .. etc... */ 611 if (strncmp(dep->d_name, ".", 1) == NULL) 612 continue; 613 614 /* get device # (disk #) */ 615 if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0) 616 continue; 617 618 /* see if this is one of the cd special devices */ 619 for (j = 0; j < n; j++) { 620 if (cd[j].number == id && cd[j].controller == ctrl) 621 goto found; 622 } 623 continue; 624 625 /* add new entry to table (/dev/dsk + / + d_name + \0) */ 626 found: 627 /* if array full, then expand it */ 628 if (i == ncd) { 629 /* will exit(1) if insufficient memory */ 630 ncd = expandmem(i, (void **)&cd, sizeof (struct cd)); 631 } 632 633 nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1); 634 if (nm == NULL) 635 no_memory(); 636 (void) strcpy(nm, "/dev/dsk/"); 637 (void) strcat(nm, dep->d_name); 638 cd[i].name = nm; 639 640 cd[i].id = cd[j].id; 641 642 cd[i].device = ""; 643 644 cd[i].number = id; 645 646 i++; 647 } 648 649 (void) closedir(dirp); 650 651 /* 652 * scan /dev/rdsk for cd devices 653 */ 654 655 if ((dirp = opendir("/dev/rdsk")) == NULL) { 656 perror(gettext("open /dev/dsk failure")); 657 exit(1); 658 } 659 660 while (dep = readdir(dirp)) { 661 /* skip . .. etc... */ 662 if (strncmp(dep->d_name, ".", 1) == NULL) 663 continue; 664 665 /* get device # (disk #) */ 666 if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) != 2) 667 continue; 668 669 /* see if this is one of the cd special devices */ 670 for (j = 0; j < n; j++) { 671 if (cd[j].number == id && cd[j].controller == ctrl) 672 goto found1; 673 } 674 continue; 675 676 /* add new entry to table (/dev/rdsk + / + d_name + \0) */ 677 found1: 678 /* if array full, then expand it */ 679 if (i == ncd) { 680 /* will exit(1) if insufficient memory */ 681 ncd = expandmem(i, (void **)&cd, sizeof (struct cd)); 682 } 683 684 nm = (char *)malloc(SIZE_OF_RDSK + 1 + strlen(dep->d_name) + 1); 685 if (nm == NULL) 686 no_memory(); 687 (void) strcpy(nm, "/dev/rdsk/"); 688 (void) strcat(nm, dep->d_name); 689 cd[i].name = nm; 690 691 cd[i].id = cd[j].id; 692 693 cd[i].device = ""; 694 695 cd[i].number = id; 696 697 cd[i].controller = ctrl; 698 699 i++; 700 } 701 702 (void) closedir(dirp); 703 704 n = i; 705 706 /* print out device_maps entries for tape devices */ 707 for (i = 0; i < 8; i++) { 708 for (j = 0; j < n; j++) { 709 if (cd[j].id == i) { 710 (void) printf( 711 "sr%d;sr;reserved;reserved;%s;", 712 i, DEFAULT_DEV_ALLOC_AUTH); 713 (void) printf("%s%s\n", SECLIB, "/sr_clean"); 714 break; 715 } 716 } 717 } 718 } 719 720 /* set default array sizes */ 721 static void 722 initmem() 723 { 724 tape = (struct tape *)calloc(DFLT_NTAPE, sizeof (struct tape)); 725 audio = (struct audio *)calloc(DFLT_NAUDIO, sizeof (struct audio)); 726 cd = (struct cd *)calloc(DFLT_NCD, sizeof (struct cd)); 727 fp = (struct fp *)calloc(DFLT_NFP, sizeof (struct fp)); 728 729 if (tape == NULL || audio == NULL || cd == NULL || fp == NULL) 730 no_memory(); 731 } 732 733 /* note n will be # elments in array (and could be 0) */ 734 static int 735 expandmem(int n, void **array, int size) 736 { 737 void *old = *array; 738 void *new; 739 740 /* get new array space (n + DELTA) */ 741 new = (void *)calloc(n + DELTA, size); 742 743 if (new == NULL) { 744 perror("memory allocation failed"); 745 exit(1); 746 } 747 748 /* copy old array into new space */ 749 bcopy(old, new, n * size); 750 751 /* now release old arrary */ 752 free(old); 753 754 *array = new; 755 756 return (n + DELTA); 757 } 758 759 static void 760 no_memory(void) 761 { 762 (void) fprintf(stderr, "%s: %s\n", "mkdevalloc", 763 gettext("out of memory")); 764 exit(1); 765 /* NOT REACHED */ 766 } 767