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 1992-2003 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 void 129 main() 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 145 static void 146 dotape() 147 { 148 DIR *dirp; 149 struct dirent *dep; /* directory entry pointer */ 150 int i, j, n; 151 char *nm; /* name/device of special device */ 152 char linkvalue[2048]; /* symlink value */ 153 struct stat stat; /* determine if it's a symlink */ 154 int sz; /* size of symlink value */ 155 char *cp; /* pointer into string */ 156 int ntape; /* max array size */ 157 158 ntape = DFLT_NTAPE; 159 160 /* 161 * look for rst* and nrst* 162 */ 163 164 if ((dirp = opendir("/dev")) == NULL) { 165 perror(gettext("open /dev failure")); 166 exit(1); 167 } 168 169 i = 0; 170 while (dep = readdir(dirp)) { 171 /* ignore if neither rst* nor nrst* */ 172 if (strncmp(dep->d_name, "rst", SIZE_OF_RST) && 173 strncmp(dep->d_name, "nrst", SIZE_OF_NRST)) 174 continue; 175 176 /* if array full, then expand it */ 177 if (i == ntape) { 178 /* will exit(1) if insufficient memory */ 179 ntape = expandmem(i, (void **)&tape, 180 sizeof (struct tape)); 181 } 182 183 /* save name (/dev + / + d_name + \0) */ 184 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 185 if (nm == NULL) 186 no_memory(); 187 (void) strcpy(nm, "/dev/"); 188 (void) strcat(nm, dep->d_name); 189 tape[i].name = nm; 190 191 /* ignore if not symbolic link (note i not incremented) */ 192 if (lstat(tape[i].name, &stat) < 0) { 193 perror("stat(2) failed "); 194 exit(1); 195 } 196 if ((stat.st_mode & S_IFMT) != S_IFLNK) 197 continue; 198 199 /* get name from symbolic link */ 200 if ((sz = readlink(tape[i].name, linkvalue, 201 sizeof (linkvalue))) < 0) 202 continue; 203 nm = (char *)malloc(sz + 1); 204 if (nm == NULL) 205 no_memory(); 206 (void) strncpy(nm, linkvalue, sz); 207 nm[sz] = '\0'; 208 tape[i].device = nm; 209 210 /* get device number */ 211 cp = strrchr(tape[i].device, '/'); 212 cp++; /* advance to device # */ 213 (void) sscanf(cp, "%d", &tape[i].number); 214 215 i++; 216 } 217 218 (void) closedir(dirp); 219 220 /* 221 * scan /dev/rmt and add entry to table 222 */ 223 224 if ((dirp = opendir("/dev/rmt")) == NULL) { 225 perror(gettext("open /dev failure")); 226 exit(1); 227 } 228 229 while (dep = readdir(dirp)) { 230 /* skip . .. etc... */ 231 if (strncmp(dep->d_name, ".", 1) == NULL) 232 continue; 233 234 /* if array full, then expand it */ 235 if (i == ntape) { 236 /* will exit(1) if insufficient memory */ 237 ntape = expandmem(i, (void **)&tape, 238 sizeof (struct tape)); 239 } 240 241 /* save name (/dev/rmt + / + d_name + \0) */ 242 nm = (char *)malloc(SIZE_OF_RMT + 1 + strlen(dep->d_name) + 1); 243 if (nm == NULL) 244 no_memory(); 245 (void) strcpy(nm, "/dev/rmt/"); 246 (void) strcat(nm, dep->d_name); 247 tape[i].name = nm; 248 249 /* save device name (rmt/ + d_name + \0) */ 250 nm = (char *)malloc(SIZE_OF_TMP + strlen(dep->d_name) + 1); 251 if (nm == NULL) 252 no_memory(); 253 (void) strcpy(nm, "rmt/"); 254 (void) strcat(nm, dep->d_name); 255 tape[i].device = nm; 256 257 (void) sscanf(dep->d_name, "%d", &tape[i].number); 258 259 i++; 260 } 261 n = i; 262 263 (void) closedir(dirp); 264 265 /* remove duplicate entries */ 266 for (i = 0; i < n - 1; i++) { 267 for (j = i + 1; j < n; j++) { 268 if (strcmp(tape[i].device, tape[j].device)) 269 continue; 270 tape[j].number = -1; 271 } 272 } 273 274 /* print out device_allocate entries for tape devices */ 275 for (i = 0; i < 8; i++) { 276 for (j = 0; j < n; j++) { 277 if (tape[j].number == i) { 278 (void) printf( 279 "st%d;st;reserved;reserved;%s;", 280 i, DEFAULT_DEV_ALLOC_AUTH); 281 (void) printf("%s%s\n", SECLIB, "/st_clean"); 282 break; 283 } 284 } 285 } 286 } 287 288 static void 289 doaudio() 290 { 291 DIR *dirp; 292 struct dirent *dep; /* directory entry pointer */ 293 int i, j, n; 294 char *nm; /* name/device of special device */ 295 char linkvalue[2048]; /* symlink value */ 296 struct stat stat; /* determine if it's a symlink */ 297 int sz; /* size of symlink value */ 298 char *cp; /* pointer into string */ 299 int naudio; /* max array size */ 300 301 naudio = DFLT_NAUDIO; 302 303 if ((dirp = opendir("/dev")) == NULL) { 304 perror(gettext("open /dev failure")); 305 exit(1); 306 } 307 308 i = 0; 309 while (dep = readdir(dirp)) { 310 if (strcmp(dep->d_name, "audio") && 311 strcmp(dep->d_name, "audioctl")) 312 continue; 313 314 /* if array full, then expand it */ 315 if (i == naudio) { 316 /* will exit(1) if insufficient memory */ 317 naudio = expandmem(i, (void **)&audio, 318 sizeof (struct audio)); 319 } 320 321 /* save name (/dev + 1 + d_name + \0) */ 322 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 323 if (nm == NULL) 324 no_memory(); 325 (void) strcpy(nm, "/dev/"); 326 (void) strcat(nm, dep->d_name); 327 audio[i].name = nm; 328 329 /* ignore if not symbolic link (note i not incremented) */ 330 if (lstat(audio[i].name, &stat) < 0) { 331 perror(gettext("stat(2) failed ")); 332 exit(1); 333 } 334 if ((stat.st_mode & S_IFMT) != S_IFLNK) 335 continue; 336 337 /* get name from symbolic link */ 338 if ((sz = readlink(audio[i].name, linkvalue, 339 sizeof (linkvalue))) < 0) 340 continue; 341 nm = (char *)malloc(sz + 1); 342 if (nm == NULL) 343 no_memory(); 344 (void) strncpy(nm, linkvalue, sz); 345 nm[sz] = '\0'; 346 audio[i].device = nm; 347 348 cp = strrchr(audio[i].device, '/'); 349 cp++; /* advance to device # */ 350 (void) sscanf(cp, "%d", &audio[i].number); 351 352 i++; 353 } 354 355 (void) closedir(dirp); 356 357 if ((dirp = opendir("/dev/sound")) == NULL) { 358 goto skip; 359 } 360 361 while (dep = readdir(dirp)) { 362 /* skip . .. etc... */ 363 if (strncmp(dep->d_name, ".", 1) == NULL) 364 continue; 365 366 /* if array full, then expand it */ 367 if (i == naudio) { 368 /* will exit(1) if insufficient memory */ 369 naudio = expandmem(i, (void **)&audio, 370 sizeof (struct audio)); 371 } 372 373 /* save name (/dev/sound + / + d_name + \0) */ 374 nm = (char *)malloc(SIZE_OF_SOUND + 1 + 375 strlen(dep->d_name) + 1); 376 if (nm == NULL) 377 no_memory(); 378 (void) strcpy(nm, "/dev/sound/"); 379 (void) strcat(nm, dep->d_name); 380 audio[i].name = nm; 381 382 nm = (char *)malloc(SIZE_OF_SOUND + 1 + 383 strlen(dep->d_name) + 1); 384 if (nm == NULL) 385 no_memory(); 386 (void) strcpy(nm, "/dev/sound/"); 387 (void) strcat(nm, dep->d_name); 388 audio[i].device = nm; 389 390 (void) sscanf(dep->d_name, "%d", &audio[i].number); 391 392 i++; 393 } 394 395 (void) closedir(dirp); 396 397 skip: 398 n = i; 399 400 /* remove duplicate entries */ 401 for (i = 0; i < n - 1; i++) { 402 for (j = i + 1; j < n; j++) { 403 if (strcmp(audio[i].device, audio[j].device)) 404 continue; 405 audio[j].number = -1; 406 } 407 } 408 409 /* print out device_allocate entries for tape devices */ 410 for (i = 0; i < 8; i++) { 411 for (j = 0; j < n; j++) { 412 if (audio[j].number == i) { 413 (void) printf("audio;audio;"); 414 (void) printf("reserved;reserved;%s;", 415 DEFAULT_DEV_ALLOC_AUTH); 416 (void) printf("%s%s\n", SECLIB, "/audio_clean"); 417 break; 418 } 419 } 420 } 421 } 422 423 static void 424 dofloppy() 425 { 426 DIR *dirp; 427 struct dirent *dep; /* directory entry pointer */ 428 int i, j, n; 429 char *nm; /* name/device of special device */ 430 char linkvalue[2048]; /* symlink value */ 431 struct stat stat; /* determine if it's a symlink */ 432 int sz; /* size of symlink value */ 433 char *cp; /* pointer into string */ 434 int nfp; /* max array size */ 435 436 nfp = DFLT_NFP; 437 438 /* 439 * look for fd* and rfd* 440 */ 441 442 if ((dirp = opendir("/dev")) == NULL) { 443 perror(gettext("open /dev failure")); 444 exit(1); 445 } 446 447 i = 0; 448 while (dep = readdir(dirp)) { 449 /* ignore if neither rst* nor nrst* */ 450 if (strncmp(dep->d_name, "fd0", SIZE_OF_FD0) && 451 strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0) && 452 strncmp(dep->d_name, "fd1", SIZE_OF_FD0) && 453 strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0)) 454 continue; 455 456 /* if array full, then expand it */ 457 if (i == nfp) { 458 /* will exit(1) if insufficient memory */ 459 nfp = expandmem(i, (void **)&fp, sizeof (struct fp)); 460 } 461 462 /* save name (/dev + 1 + d_name + \0) */ 463 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 464 if (nm == NULL) 465 no_memory(); 466 (void) strcpy(nm, "/dev/"); 467 (void) strcat(nm, dep->d_name); 468 fp[i].name = nm; 469 470 /* ignore if not symbolic link (note i not incremented) */ 471 if (lstat(fp[i].name, &stat) < 0) { 472 perror(gettext("stat(2) failed ")); 473 exit(1); 474 } 475 if ((stat.st_mode&S_IFMT) != S_IFLNK) 476 continue; 477 478 /* get name from symbolic link */ 479 if ((sz = readlink(fp[i].name, linkvalue, 480 sizeof (linkvalue))) < 0) 481 continue; 482 nm = (char *)malloc(sz+1); 483 if (nm == NULL) 484 no_memory(); 485 (void) strncpy(nm, linkvalue, sz); 486 nm[sz] = '\0'; 487 fp[i].device = nm; 488 489 /* get device number */ 490 cp = strchr(fp[i].name, 'd'); 491 cp++; /* advance to device # */ 492 cp = strchr(cp, 'd'); 493 cp++; /* advance to device # */ 494 (void) sscanf(cp, "%d", &fp[i].number); 495 496 i++; 497 } 498 499 (void) closedir(dirp); 500 501 n = i; 502 503 /* print out device_allocate entries for tape devices */ 504 for (i = 0; i < 8; i++) { 505 for (j = 0; j < n; j++) { 506 if (fp[j].number == i) { 507 (void) printf("fd%d;fd;reserved;reserved;%s;", 508 i, DEFAULT_DEV_ALLOC_AUTH); 509 (void) printf("/etc/security/lib/fd_clean\n"); 510 break; 511 } 512 } 513 } 514 } 515 516 static void 517 docd() 518 { 519 DIR *dirp; 520 struct dirent *dep; /* directory entry pointer */ 521 int i, j, n; 522 char *nm; /* name/device of special device */ 523 char linkvalue[2048]; /* symlink value */ 524 struct stat stat; /* determine if it's a symlink */ 525 int sz; /* size of symlink value */ 526 char *cp; /* pointer into string */ 527 int id; /* disk id */ 528 int ctrl; /* disk controller */ 529 int ncd; /* max array size */ 530 531 ncd = DFLT_NCD; 532 533 /* 534 * look for sr* and rsr* 535 */ 536 537 if ((dirp = opendir("/dev")) == NULL) { 538 perror(gettext("open /dev failure")); 539 exit(1); 540 } 541 542 i = 0; 543 while (dep = readdir(dirp)) { 544 /* ignore if neither sr* nor rsr* */ 545 if (strncmp(dep->d_name, "sr", SIZE_OF_SR) && 546 strncmp(dep->d_name, "rsr", SIZE_OF_RSR)) 547 continue; 548 549 /* if array full, then expand it */ 550 if (i == ncd) { 551 /* will exit(1) if insufficient memory */ 552 ncd = expandmem(i, (void **)&cd, sizeof (struct cd)); 553 } 554 555 /* save name (/dev + / + d_name + \0) */ 556 nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1); 557 if (nm == NULL) 558 no_memory(); 559 (void) strcpy(nm, "/dev/"); 560 (void) strcat(nm, dep->d_name); 561 cd[i].name = nm; 562 563 /* save id # */ 564 if (dep->d_name[0] == 'r') 565 (void) sscanf(dep->d_name, "rsr%d", &cd[i].id); 566 else 567 (void) sscanf(dep->d_name, "sr%d", &cd[i].id); 568 569 /* ignore if not symbolic link (note i not incremented) */ 570 if (lstat(cd[i].name, &stat) < 0) { 571 perror(gettext("stat(2) failed ")); 572 exit(1); 573 } 574 if ((stat.st_mode & S_IFMT) != S_IFLNK) 575 continue; 576 577 /* get name from symbolic link */ 578 if ((sz = readlink(cd[i].name, linkvalue, sizeof (linkvalue))) < 579 0) 580 continue; 581 nm = (char *)malloc(sz + 1); 582 if (nm == NULL) 583 no_memory(); 584 (void) strncpy(nm, linkvalue, sz); 585 nm[sz] = '\0'; 586 cd[i].device = nm; 587 588 cp = strrchr(cd[i].device, '/'); 589 cp++; /* advance to device # */ 590 (void) sscanf(cp, "c%dt%d", &cd[i].controller, &cd[i].number); 591 592 i++; 593 } 594 n = i; 595 596 (void) closedir(dirp); 597 598 /* 599 * scan /dev/dsk for cd devices 600 */ 601 602 if ((dirp = opendir("/dev/dsk")) == NULL) { 603 perror("gettext(open /dev/dsk failure)"); 604 exit(1); 605 } 606 607 while (dep = readdir(dirp)) { 608 /* skip . .. etc... */ 609 if (strncmp(dep->d_name, ".", 1) == NULL) 610 continue; 611 612 /* get device # (disk #) */ 613 if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0) 614 continue; 615 616 /* see if this is one of the cd special devices */ 617 for (j = 0; j < n; j++) { 618 if (cd[j].number == id && cd[j].controller == ctrl) 619 goto found; 620 } 621 continue; 622 623 /* add new entry to table (/dev/dsk + / + d_name + \0) */ 624 found: 625 /* if array full, then expand it */ 626 if (i == ncd) { 627 /* will exit(1) if insufficient memory */ 628 ncd = expandmem(i, (void **)&cd, sizeof (struct cd)); 629 } 630 631 nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1); 632 if (nm == NULL) 633 no_memory(); 634 (void) strcpy(nm, "/dev/dsk/"); 635 (void) strcat(nm, dep->d_name); 636 cd[i].name = nm; 637 638 cd[i].id = cd[j].id; 639 640 cd[i].device = ""; 641 642 cd[i].number = id; 643 644 i++; 645 } 646 647 (void) closedir(dirp); 648 649 /* 650 * scan /dev/rdsk for cd devices 651 */ 652 653 if ((dirp = opendir("/dev/rdsk")) == NULL) { 654 perror(gettext("open /dev/dsk failure")); 655 exit(1); 656 } 657 658 while (dep = readdir(dirp)) { 659 /* skip . .. etc... */ 660 if (strncmp(dep->d_name, ".", 1) == NULL) 661 continue; 662 663 /* get device # (disk #) */ 664 if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) != 2) 665 continue; 666 667 /* see if this is one of the cd special devices */ 668 for (j = 0; j < n; j++) { 669 if (cd[j].number == id && cd[j].controller == ctrl) 670 goto found1; 671 } 672 continue; 673 674 /* add new entry to table (/dev/rdsk + / + d_name + \0) */ 675 found1: 676 /* if array full, then expand it */ 677 if (i == ncd) { 678 /* will exit(1) if insufficient memory */ 679 ncd = expandmem(i, (void **)&cd, sizeof (struct cd)); 680 } 681 682 nm = (char *)malloc(SIZE_OF_RDSK + 1 + strlen(dep->d_name) + 1); 683 if (nm == NULL) 684 no_memory(); 685 (void) strcpy(nm, "/dev/rdsk/"); 686 (void) strcat(nm, dep->d_name); 687 cd[i].name = nm; 688 689 cd[i].id = cd[j].id; 690 691 cd[i].device = ""; 692 693 cd[i].number = id; 694 695 cd[i].controller = ctrl; 696 697 i++; 698 } 699 700 (void) closedir(dirp); 701 702 n = i; 703 704 /* print out device_maps entries for tape devices */ 705 for (i = 0; i < 8; i++) { 706 for (j = 0; j < n; j++) { 707 if (cd[j].id == i) { 708 (void) printf( 709 "sr%d;sr;reserved;reserved;%s;", 710 i, DEFAULT_DEV_ALLOC_AUTH); 711 (void) printf("%s%s\n", SECLIB, "/sr_clean"); 712 break; 713 } 714 } 715 } 716 } 717 718 /* set default array sizes */ 719 static void 720 initmem() 721 { 722 tape = (struct tape *)calloc(DFLT_NTAPE, sizeof (struct tape)); 723 audio = (struct audio *)calloc(DFLT_NAUDIO, sizeof (struct audio)); 724 cd = (struct cd *)calloc(DFLT_NCD, sizeof (struct cd)); 725 fp = (struct fp *)calloc(DFLT_NFP, sizeof (struct fp)); 726 727 if (tape == NULL || audio == NULL || cd == NULL || fp == NULL) 728 no_memory(); 729 } 730 731 /* note n will be # elments in array (and could be 0) */ 732 static int 733 expandmem(int n, void **array, int size) 734 { 735 void *old = *array; 736 void *new; 737 738 /* get new array space (n + DELTA) */ 739 new = (void *)calloc(n + DELTA, size); 740 741 if (new == NULL) { 742 perror("memory allocation failed"); 743 exit(1); 744 } 745 746 /* copy old array into new space */ 747 bcopy(old, new, n * size); 748 749 /* now release old arrary */ 750 free(old); 751 752 *array = new; 753 754 return (n + DELTA); 755 } 756 757 static void 758 no_memory(void) 759 { 760 (void) fprintf(stderr, "%s: %s\n", "mkdevalloc", 761 gettext("out of memory")); 762 exit(1); 763 /* NOT REACHED */ 764 } 765