1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 10585 Dhanaraj * Common Development and Distribution License (the "License"). 6 10585 Dhanaraj * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 10585 Dhanaraj * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 0 stevel /* All Rights Reserved */ 28 0 stevel 29 0 stevel 30 0 stevel /* 31 0 stevel * autopush(1) is the command interface to the STREAMS autopush 32 0 stevel * mechanism. The autopush command can be used to configure autopush 33 0 stevel * information about a STREAMS driver, remove autopush information, 34 0 stevel * and report on current configuration information. Its use is as 35 0 stevel * follows: 36 0 stevel * 37 0 stevel * autopush -f file 38 0 stevel * autopush -r -M major -m minor 39 0 stevel * autopush -g -M major -m minor 40 0 stevel * 41 0 stevel * The -f option allows autopush information to be set from a file. The 42 0 stevel * format of the file is as follows: 43 0 stevel * 44 0 stevel * # Comment lines begin with a # in column one. 45 0 stevel * # The fields are separated by white space and are: 46 0 stevel * # major minor lastminor module1 module2 ... module8 47 0 stevel * 48 0 stevel * "lastminor" is used to configure ranges of minor devices, from "minor" 49 0 stevel * to "lastminor" inclusive. It should be set to zero when not in use. 50 0 stevel * The -r option allows autopush information to be removed for the given 51 0 stevel * major/minor pair. The -g option allows the configuration information 52 0 stevel * to be printed. The format of printing is the same as for the file. 53 0 stevel */ 54 0 stevel 55 0 stevel /* 56 0 stevel * Use autopush version 1; keep before #include <sys/sad.h>. 57 0 stevel * See <sys/sad.h> for details. 58 0 stevel */ 59 0 stevel #define AP_VERSION 1 60 0 stevel 61 0 stevel #include <sys/types.h> 62 0 stevel #include <sys/conf.h> 63 0 stevel #include <sys/modctl.h> 64 0 stevel #include <sys/sad.h> 65 0 stevel #include <stdio.h> 66 0 stevel #include <fcntl.h> 67 0 stevel #include <errno.h> 68 0 stevel #include <ctype.h> 69 0 stevel #include <stdlib.h> 70 0 stevel #include <unistd.h> 71 0 stevel #include <string.h> 72 0 stevel #include <locale.h> 73 0 stevel #include <sys/stat.h> 74 10585 Dhanaraj #include <zone.h> 75 0 stevel 76 0 stevel #define OPTIONS "M:f:gm:r" /* command line options for getopt(3C) */ 77 0 stevel #define COMMENT '#' 78 0 stevel #define MINUS '-' 79 0 stevel #define SLASH '/' 80 0 stevel 81 0 stevel /* 82 0 stevel * Output format. 83 0 stevel */ 84 0 stevel #define OHEADER " Major Minor Lastminor\tModules\n" 85 0 stevel #define OFORMAT1_ONE "%10ld %10ld - \t" 86 0 stevel #define OFORMAT1_RANGE "%10ld %10ld %10ld\t" 87 0 stevel #define OFORMAT1_ALL "%10ld ALL - \t" 88 0 stevel 89 0 stevel #define AP_ANCHOR "[anchor]" 90 0 stevel 91 0 stevel #define Openerr gettext("%s: ERROR: Could not open %s: ") 92 0 stevel #define Digiterr gettext("%s: ERROR: argument to %s option must be " \ 93 0 stevel "numeric\n") 94 0 stevel #define Badline gettext("%s: WARNING: File %s: bad input line %d " \ 95 0 stevel "ignored\n") 96 0 stevel 97 0 stevel static void usage(); 98 0 stevel static int rem_info(), get_info(), set_info(); 99 0 stevel static int is_white_space(), parse_line(); 100 0 stevel 101 0 stevel static char *Cmdp; /* command name */ 102 0 stevel 103 0 stevel /* 104 0 stevel * main(): 105 0 stevel * process command line arguments. 106 0 stevel */ 107 0 stevel int 108 0 stevel main(int argc, char *argv[]) 109 0 stevel { 110 0 stevel int c; /* character read by getopt(3C) */ 111 0 stevel char *filenamep; /* name of configuration file */ 112 0 stevel major_t major; /* major device number */ 113 0 stevel minor_t minor; /* minor device number */ 114 0 stevel char *cp; 115 0 stevel int exitcode; 116 0 stevel ushort_t minflag = 0; /* -m option used */ 117 0 stevel ushort_t majflag = 0; /* -M option used */ 118 0 stevel ushort_t fflag = 0; /* -f option used */ 119 0 stevel ushort_t rflag = 0; /* -r option used */ 120 0 stevel ushort_t gflag = 0; /* -g option used */ 121 0 stevel ushort_t errflag = 0; /* options usage error */ 122 0 stevel 123 0 stevel (void) setlocale(LC_ALL, ""); 124 0 stevel #if !defined(TEXT_DOMAIN) 125 0 stevel #define TEXT_DOMAIN "SYS_TEST" 126 0 stevel #endif 127 0 stevel (void) textdomain(TEXT_DOMAIN); 128 0 stevel 129 0 stevel /* 130 0 stevel * Get command name. 131 0 stevel */ 132 0 stevel Cmdp = argv[0]; 133 0 stevel for (filenamep = argv[0]; *filenamep; filenamep++) 134 0 stevel if (*filenamep == SLASH) 135 0 stevel Cmdp = filenamep + 1; 136 0 stevel 137 0 stevel /* 138 0 stevel * Get options. 139 0 stevel */ 140 0 stevel while (!errflag && ((c = getopt(argc, argv, OPTIONS)) != -1)) { 141 0 stevel switch (c) { 142 0 stevel case 'M': 143 0 stevel if (fflag|majflag) 144 0 stevel errflag++; 145 0 stevel else { 146 0 stevel majflag++; 147 0 stevel for (cp = optarg; *cp; cp++) 148 0 stevel if (!isdigit(*cp)) { 149 0 stevel (void) fprintf(stderr, 150 0 stevel Digiterr, Cmdp, "-M"); 151 0 stevel exit(1); 152 0 stevel } 153 0 stevel major = (major_t)atol(optarg); 154 0 stevel } 155 0 stevel break; 156 0 stevel 157 0 stevel case 'm': 158 0 stevel if (fflag|minflag) 159 0 stevel errflag++; 160 0 stevel else { 161 0 stevel minflag++; 162 0 stevel for (cp = optarg; *cp; cp++) 163 0 stevel if (!isdigit(*cp)) { 164 0 stevel (void) fprintf(stderr, 165 0 stevel Digiterr, Cmdp, "-m"); 166 0 stevel exit(1); 167 0 stevel } 168 0 stevel minor = (minor_t)atol(optarg); 169 0 stevel } 170 0 stevel break; 171 0 stevel 172 0 stevel case 'f': 173 0 stevel if (fflag|gflag|rflag|majflag|minflag) 174 0 stevel errflag++; 175 0 stevel else { 176 0 stevel fflag++; 177 0 stevel filenamep = optarg; 178 0 stevel } 179 0 stevel break; 180 0 stevel 181 0 stevel case 'r': 182 0 stevel if (fflag|gflag|rflag) 183 0 stevel errflag++; 184 0 stevel else 185 0 stevel rflag++; 186 0 stevel break; 187 0 stevel 188 0 stevel case 'g': 189 0 stevel if (fflag|gflag|rflag) 190 0 stevel errflag++; 191 0 stevel else 192 0 stevel gflag++; 193 0 stevel break; 194 0 stevel 195 0 stevel default: 196 0 stevel errflag++; 197 0 stevel break; 198 0 stevel } /* switch */ 199 0 stevel if (errflag) { 200 0 stevel usage(); 201 0 stevel exit(1); 202 0 stevel } 203 0 stevel } /* while */ 204 0 stevel if (((gflag || rflag) && (!majflag || !minflag)) || (optind != argc)) { 205 0 stevel usage(); 206 0 stevel exit(1); 207 0 stevel } 208 10585 Dhanaraj 209 10585 Dhanaraj if (getzoneid() != GLOBAL_ZONEID) { 210 10585 Dhanaraj (void) fprintf(stderr, gettext("autopush " 211 10585 Dhanaraj "can only be run from the global zone.\n")); 212 10585 Dhanaraj exit(1); 213 10585 Dhanaraj } 214 10585 Dhanaraj 215 0 stevel if (fflag) 216 0 stevel exitcode = set_info(filenamep); 217 0 stevel else if (rflag) 218 0 stevel exitcode = rem_info(major, minor); 219 0 stevel else if (gflag) 220 0 stevel exitcode = get_info(major, minor); 221 0 stevel else { 222 0 stevel usage(); 223 0 stevel exit(1); 224 0 stevel } 225 0 stevel 226 0 stevel return (exitcode); 227 0 stevel } 228 0 stevel 229 0 stevel /* 230 0 stevel * usage(): 231 0 stevel * print out usage statement. 232 0 stevel */ 233 0 stevel static void 234 0 stevel usage() 235 0 stevel { 236 0 stevel (void) fprintf(stderr, gettext("%s: USAGE:\n\t%s -f filename\n" 237 0 stevel "\t%s -r -M major -m minor\n" 238 0 stevel "\t%s -g -M major -m minor\n"), Cmdp, Cmdp, Cmdp, Cmdp); 239 0 stevel } 240 0 stevel 241 0 stevel /* 242 0 stevel * set_info(): 243 0 stevel * set autopush configuration information. 244 0 stevel * namep: autopush configuration filename 245 0 stevel */ 246 0 stevel static int 247 0 stevel set_info(char *namep) 248 0 stevel { 249 0 stevel int line; /* line number of file */ 250 0 stevel FILE *fp; /* file pointer of config file */ 251 0 stevel char buf[256]; /* input buffer */ 252 0 stevel struct strapush push; /* configuration information */ 253 0 stevel int sadfd; /* file descriptor to SAD driver */ 254 0 stevel int retcode = 0; /* return code */ 255 0 stevel int parsecode; /* return value from parse function */ 256 0 stevel 257 0 stevel if ((sadfd = open(ADMINDEV, O_RDWR)) < 0) { 258 0 stevel (void) fprintf(stderr, Openerr, Cmdp, ADMINDEV); 259 0 stevel perror(""); 260 0 stevel return (1); 261 0 stevel } 262 0 stevel if ((fp = fopen(namep, "r")) == NULL) { 263 0 stevel (void) fprintf(stderr, Openerr, Cmdp, namep); 264 0 stevel perror(""); 265 0 stevel return (1); 266 0 stevel } 267 0 stevel line = 0; 268 0 stevel while (fgets(buf, sizeof (buf), fp) != NULL) { 269 0 stevel line++; 270 0 stevel if ((buf[0] == COMMENT) || is_white_space(buf)) 271 0 stevel continue; 272 0 stevel (void) memset(&push, 0, sizeof (struct strapush)); 273 0 stevel 274 0 stevel parsecode = parse_line(buf, line, namep, &push); 275 0 stevel if (parsecode != 0) { 276 0 stevel retcode = parsecode; 277 0 stevel continue; 278 0 stevel } 279 0 stevel 280 0 stevel if (push.sap_minor == (minor_t)-1) 281 0 stevel push.sap_cmd = SAP_ALL; 282 0 stevel else if (push.sap_lastminor == 0) 283 0 stevel push.sap_cmd = SAP_ONE; 284 0 stevel else 285 0 stevel push.sap_cmd = SAP_RANGE; 286 0 stevel 287 0 stevel if (ioctl(sadfd, SAD_SAP, &push) < 0) { 288 0 stevel int error = errno; 289 0 stevel 290 0 stevel retcode = 1; 291 0 stevel (void) fprintf(stderr, 292 0 stevel gettext("%s: ERROR: File %s: could not configure " 293 0 stevel "autopush for line %d\n"), Cmdp, namep, line); 294 0 stevel switch (error) { 295 0 stevel case EPERM: 296 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 297 0 stevel "You don't have permission to set autopush " 298 0 stevel "information\n"), Cmdp); 299 0 stevel break; 300 0 stevel 301 0 stevel case EINVAL: 302 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 303 0 stevel "Invalid major device number or invalid " 304 0 stevel "module name or too many modules\n"), Cmdp); 305 0 stevel break; 306 0 stevel 307 0 stevel case ENOSTR: 308 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 309 0 stevel "Major device is not a STREAMS " 310 0 stevel "driver\n"), Cmdp); 311 0 stevel break; 312 0 stevel 313 0 stevel case EEXIST: 314 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 315 0 stevel "Major/minor already configured\n"), Cmdp); 316 0 stevel break; 317 0 stevel 318 0 stevel case ENOSR: 319 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: Ran " 320 0 stevel "out of autopush structures\n"), Cmdp); 321 0 stevel break; 322 0 stevel 323 0 stevel case ERANGE: 324 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 325 0 stevel "lastminor must be greater than minor\n"), 326 0 stevel Cmdp); 327 0 stevel break; 328 0 stevel 329 0 stevel default: 330 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: "), 331 0 stevel Cmdp); 332 0 stevel (void) fprintf(stderr, "%s\n", strerror(error)); 333 0 stevel break; 334 0 stevel } /* switch */ 335 0 stevel } /* if */ 336 0 stevel } /* while */ 337 0 stevel return (retcode); 338 0 stevel } 339 0 stevel 340 0 stevel /* 341 0 stevel * rem_info(): 342 0 stevel * remove autopush configuration information. 343 0 stevel */ 344 0 stevel static int 345 0 stevel rem_info(major_t maj, minor_t min) 346 0 stevel { 347 0 stevel struct strapush push; /* configuration information */ 348 0 stevel int sadfd; /* file descriptor to SAD driver */ 349 0 stevel int retcode = 0; /* return code */ 350 0 stevel 351 0 stevel if ((sadfd = open(ADMINDEV, O_RDWR)) < 0) { 352 0 stevel (void) fprintf(stderr, Openerr, Cmdp, ADMINDEV); 353 0 stevel perror(""); 354 0 stevel return (1); 355 0 stevel } 356 0 stevel push.sap_cmd = SAP_CLEAR; 357 0 stevel push.sap_minor = min; 358 0 stevel push.sap_major = maj; 359 0 stevel 360 0 stevel if (ioctl(sadfd, SAD_SAP, &push) < 0) { 361 0 stevel int error = errno; 362 0 stevel 363 0 stevel retcode = 1; 364 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: Could not remove " 365 0 stevel "autopush information\n"), Cmdp); 366 0 stevel switch (error) { 367 0 stevel case EPERM: 368 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: You don't " 369 0 stevel "have permission to remove autopush " 370 0 stevel "information\n"), Cmdp); 371 0 stevel break; 372 0 stevel 373 0 stevel case EINVAL: 374 0 stevel if ((min != 0) && (ioctl(sadfd, SAD_GAP, &push) == 0) && 375 0 stevel (push.sap_cmd == SAP_ALL)) 376 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 377 0 stevel "When removing an entry for ALL minors, " 378 0 stevel "minor must be set to 0\n"), Cmdp); 379 0 stevel else 380 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 381 0 stevel "Invalid major device number\n"), Cmdp); 382 0 stevel break; 383 0 stevel 384 0 stevel case ENODEV: 385 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: Major/minor " 386 0 stevel "not configured for autopush\n"), Cmdp); 387 0 stevel break; 388 0 stevel 389 0 stevel case ERANGE: 390 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: minor must " 391 0 stevel "be set to begining of range when clearing\n"), 392 0 stevel Cmdp); 393 0 stevel break; 394 0 stevel 395 0 stevel default: 396 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: "), Cmdp); 397 0 stevel (void) fprintf(stderr, "%s\n", strerror(error)); 398 0 stevel break; 399 0 stevel } /* switch */ 400 0 stevel } 401 0 stevel return (retcode); 402 0 stevel } 403 0 stevel 404 0 stevel /* 405 0 stevel * get_info(): 406 0 stevel * get autopush configuration information. 407 0 stevel */ 408 0 stevel static int 409 0 stevel get_info(major_t maj, minor_t min) 410 0 stevel { 411 0 stevel struct strapush push; /* configuration information */ 412 0 stevel int i; /* counter */ 413 0 stevel int sadfd; /* file descriptor to SAD driver */ 414 0 stevel 415 0 stevel if ((sadfd = open(USERDEV, O_RDWR)) < 0) { 416 0 stevel (void) fprintf(stderr, Openerr, Cmdp, USERDEV); 417 0 stevel perror(""); 418 0 stevel return (1); 419 0 stevel } 420 0 stevel push.sap_major = maj; 421 0 stevel push.sap_minor = min; 422 0 stevel 423 0 stevel if (ioctl(sadfd, SAD_GAP, &push) < 0) { 424 0 stevel int error = errno; 425 0 stevel 426 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: Could not get " 427 0 stevel "autopush information\n"), Cmdp); 428 0 stevel switch (error) { 429 0 stevel case EINVAL: 430 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: Invalid " 431 0 stevel "major device number\n"), Cmdp); 432 0 stevel break; 433 0 stevel 434 0 stevel case ENOSTR: 435 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: Major " 436 0 stevel "device is not a STREAMS driver\n"), Cmdp); 437 0 stevel break; 438 0 stevel 439 0 stevel case ENODEV: 440 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: Major/minor " 441 0 stevel "not configured for autopush\n"), Cmdp); 442 0 stevel break; 443 0 stevel 444 0 stevel default: 445 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: "), Cmdp); 446 0 stevel (void) fprintf(stderr, "%s\n", strerror(error)); 447 0 stevel break; 448 0 stevel } /* switch */ 449 0 stevel return (1); 450 0 stevel } 451 0 stevel (void) printf(OHEADER); 452 0 stevel switch (push.sap_cmd) { 453 0 stevel case SAP_ONE: 454 0 stevel (void) printf(OFORMAT1_ONE, push.sap_major, push.sap_minor); 455 0 stevel break; 456 0 stevel 457 0 stevel case SAP_RANGE: 458 0 stevel (void) printf(OFORMAT1_RANGE, push.sap_major, push.sap_minor, 459 0 stevel push.sap_lastminor); 460 0 stevel break; 461 0 stevel 462 0 stevel case SAP_ALL: 463 0 stevel (void) printf(OFORMAT1_ALL, push.sap_major); 464 0 stevel break; 465 0 stevel 466 0 stevel default: 467 0 stevel (void) fprintf(stderr, 468 0 stevel gettext("%s: ERROR: Unknown configuration type\n"), Cmdp); 469 0 stevel return (1); 470 0 stevel } 471 0 stevel 472 0 stevel for (i = 0; i < push.sap_npush; i++) { 473 0 stevel 474 0 stevel (void) printf("%s", push.sap_list[i]); 475 0 stevel 476 0 stevel if (push.sap_anchor == (i + 1)) 477 0 stevel (void) printf(" %s", AP_ANCHOR); 478 0 stevel 479 0 stevel if (i < push.sap_npush - 1) 480 0 stevel (void) printf(" "); 481 0 stevel 482 0 stevel } 483 0 stevel 484 0 stevel (void) printf("\n"); 485 0 stevel return (0); 486 0 stevel } 487 0 stevel 488 0 stevel /* 489 0 stevel * is_white_space(): 490 0 stevel * Return 1 if buffer is all white space. 491 0 stevel * Return 0 otherwise. 492 0 stevel */ 493 0 stevel static int 494 0 stevel is_white_space(char *bufp) 495 0 stevel { 496 0 stevel while (*bufp) { 497 0 stevel if (!isspace(*bufp)) 498 0 stevel return (0); 499 0 stevel bufp++; 500 0 stevel } 501 0 stevel return (1); 502 0 stevel } 503 0 stevel 504 0 stevel /* 505 0 stevel * parse_line(): 506 0 stevel * Parse input line from file and report any errors found. Fill 507 0 stevel * strapush structure along the way. Returns 1 if the line has 508 0 stevel * errors and 0 if the line is well-formed. Another hidden 509 0 stevel * dependency on MAXAPUSH. `linep' is the input buffer, `lineno' 510 0 stevel * is the current line number, and `namep' is the filename. 511 0 stevel */ 512 0 stevel static int 513 0 stevel parse_line(char *linep, int lineno, char *namep, struct strapush *pushp) 514 0 stevel { 515 0 stevel char *wp; /* word pointer */ 516 0 stevel char *cp; /* character pointer */ 517 0 stevel int midx; /* module index */ 518 0 stevel int npush; /* number of modules to push */ 519 0 stevel char c; 520 0 stevel major_t major_num; 521 0 stevel 522 0 stevel pushp->sap_anchor = 0; /* by default, no anchor */ 523 0 stevel 524 0 stevel /* 525 0 stevel * Find the major device number. 526 0 stevel */ 527 0 stevel for (wp = linep; isspace(*wp); wp++) 528 0 stevel ; 529 0 stevel for (cp = wp; !isspace(*cp); cp++) 530 0 stevel ; 531 0 stevel if (!isspace(*cp)) { 532 0 stevel (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 533 0 stevel return (1); 534 0 stevel } 535 0 stevel c = *cp; 536 0 stevel *cp = '\0'; 537 0 stevel if (modctl(MODGETMAJBIND, wp, strlen(wp) + 1, &major_num) != 0) { 538 0 stevel (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 539 0 stevel return (1); 540 0 stevel } 541 0 stevel *cp = c; 542 0 stevel pushp->sap_major = major_num; 543 0 stevel 544 0 stevel /* 545 0 stevel * Find the minor device number. Must handle negative values here. 546 0 stevel */ 547 0 stevel for (wp = cp; isspace(*wp); wp++) 548 0 stevel ; 549 0 stevel for (cp = wp; (isdigit(*cp) || (*cp == MINUS)); cp++) 550 0 stevel ; 551 0 stevel if (!isspace(*cp)) { 552 0 stevel (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 553 0 stevel return (1); 554 0 stevel } 555 0 stevel pushp->sap_minor = (minor_t)atol(wp); 556 0 stevel 557 0 stevel /* 558 0 stevel * Find the lastminor. 559 0 stevel */ 560 0 stevel for (wp = cp; isspace(*wp); wp++) 561 0 stevel ; 562 0 stevel for (cp = wp; isdigit(*cp); cp++) 563 0 stevel ; 564 0 stevel if (!isspace(*cp)) { 565 0 stevel (void) fprintf(stderr, Badline, Cmdp, namep, lineno); 566 0 stevel return (1); 567 0 stevel } 568 0 stevel pushp->sap_lastminor = (minor_t)atol(wp); 569 0 stevel 570 0 stevel /* 571 0 stevel * Read the list of module names. 572 0 stevel */ 573 0 stevel npush = 0; 574 0 stevel while ((npush < MAXAPUSH) && (*cp)) { 575 0 stevel 576 0 stevel while (isspace(*cp)) 577 0 stevel cp++; 578 0 stevel 579 0 stevel if (strncasecmp(cp, AP_ANCHOR, sizeof (AP_ANCHOR) - 1) == 0) { 580 0 stevel if (pushp->sap_anchor != 0) { 581 0 stevel (void) fprintf(stderr, 582 0 stevel gettext("%s: ERROR: File %s: more than " 583 0 stevel "one anchor in line, line %d ignored\n"), 584 0 stevel Cmdp, namep, lineno); 585 0 stevel return (1); 586 0 stevel } 587 0 stevel if (npush == 0) 588 0 stevel (void) fprintf(stderr, 589 0 stevel gettext("%s: WARNING: File %s: anchor at " 590 0 stevel "beginning of stream on line %d ignored\n"), 591 0 stevel Cmdp, namep, lineno); 592 0 stevel pushp->sap_anchor = npush; 593 0 stevel cp += sizeof (AP_ANCHOR) - 1; 594 0 stevel continue; 595 0 stevel } 596 0 stevel 597 0 stevel for (midx = 0; !isspace(*cp) && *cp; midx++) { 598 0 stevel if (midx == FMNAMESZ) { 599 0 stevel (void) fprintf(stderr, gettext("%s: ERROR: " 600 0 stevel "File %s: module name too long, line %d " 601 0 stevel "ignored\n"), Cmdp, namep, lineno); 602 0 stevel return (1); 603 0 stevel } 604 0 stevel pushp->sap_list[npush][midx] = *cp++; 605 0 stevel } 606 0 stevel 607 0 stevel if (midx > 0) { 608 0 stevel pushp->sap_list[npush][midx] = '\0'; 609 0 stevel npush++; 610 0 stevel } 611 0 stevel } 612 0 stevel pushp->sap_npush = npush; 613 0 stevel 614 0 stevel /* 615 0 stevel * We have everything we want from the line. 616 0 stevel * Now make sure there is no extra garbage on the line. 617 0 stevel */ 618 0 stevel while (isspace(*cp)) 619 0 stevel cp++; 620 0 stevel if (*cp) { 621 0 stevel (void) fprintf(stderr, 622 0 stevel gettext("%s: ERROR: File %s: too many modules, line %d " 623 0 stevel "ignored\n"), Cmdp, namep, lineno); 624 0 stevel return (1); 625 0 stevel } 626 0 stevel return (0); 627 0 stevel } 628