1 2 #define _MINIX_SYSTEM 1 3 4 #include <stdarg.h> 5 #include <assert.h> 6 #include <stdlib.h> 7 #include <stdio.h> 8 #include <string.h> 9 #include <errno.h> 10 #include <pwd.h> 11 #include <err.h> 12 #include <unistd.h> 13 #include <limits.h> 14 #include <lib.h> 15 #include <minix/config.h> 16 #include <minix/com.h> 17 #include <minix/const.h> 18 #include <minix/type.h> 19 #include <minix/ipc.h> 20 #include <minix/rs.h> 21 #include <minix/syslib.h> 22 #include <minix/bitmap.h> 23 #include <minix/paths.h> 24 #include <minix/sef.h> 25 #include <minix/dmap.h> 26 #include <minix/priv.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/socket.h> 30 #include <configfile.h> 31 32 #include <machine/archtypes.h> 33 #include <minix/timers.h> 34 35 #include "config.h" 36 #include "proto.h" 37 38 static int class_recurs; /* Nesting level of class statements */ 39 #define MAX_CLASS_RECURS 100 /* Max nesting level for classes */ 40 41 #include "parse.h" 42 43 static void do_service(config_t *cpe, config_t *config, struct rs_config *); 44 45 static void do_class(config_t *cpe, config_t *config, struct rs_config *rs_config) 46 { 47 config_t *cp, *cp1; 48 49 if (class_recurs > MAX_CLASS_RECURS) 50 { 51 fatal( 52 "do_class: nesting level too high for class '%s' at %s:%d", 53 cpe->word, cpe->file, cpe->line); 54 } 55 class_recurs++; 56 57 /* Process classes */ 58 for (; cpe; cpe= cpe->next) 59 { 60 if (cpe->flags & CFG_SUBLIST) 61 { 62 fatal("do_class: unexpected sublist at %s:%d", 63 cpe->file, cpe->line); 64 } 65 if (cpe->flags & CFG_STRING) 66 { 67 fatal("do_uid: unexpected string at %s:%d", 68 cpe->file, cpe->line); 69 } 70 71 /* Find entry for the class */ 72 for (cp= config; cp; cp= cp->next) 73 { 74 if (!(cp->flags & CFG_SUBLIST)) 75 { 76 fatal("do_class: expected list at %s:%d", 77 cp->file, cp->line); 78 } 79 cp1= cp->list; 80 if ((cp1->flags & CFG_STRING) || 81 (cp1->flags & CFG_SUBLIST)) 82 { 83 fatal("do_class: expected word at %s:%d", 84 cp1->file, cp1->line); 85 } 86 87 /* At this place we expect the word KW_SERVICE */ 88 if (strcmp(cp1->word, KW_SERVICE) != 0) 89 fatal("do_class: exected word '%S' at %s:%d", 90 KW_SERVICE, cp1->file, cp1->line); 91 92 cp1= cp1->next; 93 if ((cp1->flags & CFG_STRING) || 94 (cp1->flags & CFG_SUBLIST)) 95 { 96 fatal("do_class: expected word at %s:%d", 97 cp1->file, cp1->line); 98 } 99 100 /* At this place we expect the name of the service */ 101 if (strcmp(cp1->word, cpe->word) == 0) 102 break; 103 } 104 if (cp == NULL) 105 { 106 fatal( 107 "do_class: no entry found for class '%s' at %s:%d", 108 cpe->word, cpe->file, cpe->line); 109 } 110 do_service(cp1->next, config, rs_config); 111 } 112 113 class_recurs--; 114 } 115 116 static void do_uid(config_t *cpe, struct rs_start *rs_start) 117 { 118 uid_t uid; 119 struct passwd *pw; 120 char *check; 121 122 /* Process a uid */ 123 if (cpe->next != NULL) 124 { 125 fatal("do_uid: just one uid/login expected at %s:%d", 126 cpe->file, cpe->line); 127 } 128 129 if (cpe->flags & CFG_SUBLIST) 130 { 131 fatal("do_uid: unexpected sublist at %s:%d", 132 cpe->file, cpe->line); 133 } 134 if (cpe->flags & CFG_STRING) 135 { 136 fatal("do_uid: unexpected string at %s:%d", 137 cpe->file, cpe->line); 138 } 139 pw= getpwnam(cpe->word); 140 if (pw != NULL) 141 uid= pw->pw_uid; 142 else 143 { 144 if (!strncmp(cpe->word, KW_SELF, strlen(KW_SELF)+1)) 145 { 146 uid= getuid(); /* Real uid */ 147 } 148 else { 149 uid= strtol(cpe->word, &check, 0); 150 if (check[0] != '\0') 151 { 152 fatal("do_uid: bad uid/login '%s' at %s:%d", 153 cpe->word, cpe->file, cpe->line); 154 } 155 } 156 } 157 158 rs_start->rss_uid= uid; 159 } 160 161 static void do_sigmgr(config_t *cpe, struct rs_start *rs_start) 162 { 163 endpoint_t sigmgr_ep; 164 int r; 165 166 /* Process a signal manager value */ 167 if (cpe->next != NULL) 168 { 169 fatal("do_sigmgr: just one sigmgr value expected at %s:%d", 170 cpe->file, cpe->line); 171 } 172 173 174 if (cpe->flags & CFG_SUBLIST) 175 { 176 fatal("do_sigmgr: unexpected sublist at %s:%d", 177 cpe->file, cpe->line); 178 } 179 if (cpe->flags & CFG_STRING) 180 { 181 fatal("do_sigmgr: unexpected string at %s:%d", 182 cpe->file, cpe->line); 183 } 184 185 if(!strcmp(cpe->word, "SELF")) { 186 sigmgr_ep = SELF; 187 } 188 else { 189 if((r = minix_rs_lookup(cpe->word, &sigmgr_ep))) { 190 fatal("do_sigmgr: unknown sigmgr %s at %s:%d", 191 cpe->word, cpe->file, cpe->line); 192 } 193 } 194 195 rs_start->rss_sigmgr= sigmgr_ep; 196 } 197 198 static void do_type(config_t *cpe, struct rs_config *rs_config) 199 { 200 if (cpe->next != NULL) 201 { 202 fatal("do_type: just one type value expected at %s:%d", 203 cpe->file, cpe->line); 204 } 205 206 207 if (cpe->flags & CFG_SUBLIST) 208 { 209 fatal("do_type: unexpected sublist at %s:%d", 210 cpe->file, cpe->line); 211 } 212 if ((cpe->flags & CFG_STRING)) 213 { 214 fatal("do_type: unexpected string at %s:%d", 215 cpe->file, cpe->line); 216 } 217 218 if(rs_config->type) 219 fatal("do_type: another type at %s:%d", 220 cpe->file, cpe->line); 221 222 if(!strcmp(cpe->word, KW_NET)) 223 rs_config->type = KW_NET; 224 else 225 fatal("do_type: odd type at %s:%d", 226 cpe->file, cpe->line); 227 } 228 229 static void do_descr(config_t *cpe, struct rs_config *rs_config) 230 { 231 if (cpe->next != NULL) 232 { 233 fatal("do_descr: just one description expected at %s:%d", 234 cpe->file, cpe->line); 235 } 236 237 238 if (cpe->flags & CFG_SUBLIST) 239 { 240 fatal("do_descr: unexpected sublist at %s:%d", 241 cpe->file, cpe->line); 242 } 243 if (!(cpe->flags & CFG_STRING)) 244 { 245 fatal("do_descr: expected string at %s:%d", 246 cpe->file, cpe->line); 247 } 248 249 if(rs_config->descr) 250 fatal("do_descr: another descr at %s:%d", 251 cpe->file, cpe->line); 252 rs_config->descr = cpe->word; 253 } 254 255 static void do_scheduler(config_t *cpe, struct rs_start *rs_start) 256 { 257 endpoint_t scheduler_ep; 258 int r; 259 260 /* Process a scheduler value */ 261 if (cpe->next != NULL) 262 { 263 fatal("do_scheduler: just one scheduler value expected at %s:%d", 264 cpe->file, cpe->line); 265 } 266 267 268 if (cpe->flags & CFG_SUBLIST) 269 { 270 fatal("do_scheduler: unexpected sublist at %s:%d", 271 cpe->file, cpe->line); 272 } 273 if (cpe->flags & CFG_STRING) 274 { 275 fatal("do_scheduler: unexpected string at %s:%d", 276 cpe->file, cpe->line); 277 } 278 279 if(!strcmp(cpe->word, "KERNEL")) { 280 scheduler_ep = KERNEL; 281 } 282 else { 283 if((r = minix_rs_lookup(cpe->word, &scheduler_ep))) { 284 fatal("do_scheduler: unknown scheduler %s at %s:%d", 285 cpe->word, cpe->file, cpe->line); 286 } 287 } 288 289 rs_start->rss_scheduler= scheduler_ep; 290 } 291 292 static void do_priority(config_t *cpe, struct rs_start *rs_start) 293 { 294 int priority_val; 295 char *check; 296 297 /* Process a priority value */ 298 if (cpe->next != NULL) 299 { 300 fatal("do_priority: just one priority value expected at %s:%d", 301 cpe->file, cpe->line); 302 } 303 304 305 if (cpe->flags & CFG_SUBLIST) 306 { 307 fatal("do_priority: unexpected sublist at %s:%d", 308 cpe->file, cpe->line); 309 } 310 if (cpe->flags & CFG_STRING) 311 { 312 fatal("do_priority: unexpected string at %s:%d", 313 cpe->file, cpe->line); 314 } 315 priority_val= strtol(cpe->word, &check, 0); 316 if (check[0] != '\0') 317 { 318 fatal("do_priority: bad priority value '%s' at %s:%d", 319 cpe->word, cpe->file, cpe->line); 320 } 321 322 if (priority_val < 0 || priority_val >= NR_SCHED_QUEUES) 323 { 324 fatal("do_priority: priority %d out of range at %s:%d", 325 priority_val, cpe->file, cpe->line); 326 } 327 rs_start->rss_priority= priority_val; 328 } 329 330 static void do_quantum(config_t *cpe, struct rs_start *rs_start) 331 { 332 int quantum_val; 333 char *check; 334 335 /* Process a quantum value */ 336 if (cpe->next != NULL) 337 { 338 fatal("do_quantum: just one quantum value expected at %s:%d", 339 cpe->file, cpe->line); 340 } 341 342 343 if (cpe->flags & CFG_SUBLIST) 344 { 345 fatal("do_quantum: unexpected sublist at %s:%d", 346 cpe->file, cpe->line); 347 } 348 if (cpe->flags & CFG_STRING) 349 { 350 fatal("do_quantum: unexpected string at %s:%d", 351 cpe->file, cpe->line); 352 } 353 quantum_val= strtol(cpe->word, &check, 0); 354 if (check[0] != '\0') 355 { 356 fatal("do_quantum: bad quantum value '%s' at %s:%d", 357 cpe->word, cpe->file, cpe->line); 358 } 359 360 if (quantum_val <= 0) 361 { 362 fatal("do_quantum: quantum %d out of range at %s:%d", 363 quantum_val, cpe->file, cpe->line); 364 } 365 rs_start->rss_quantum= quantum_val; 366 } 367 368 static void do_cpu(config_t *cpe, struct rs_start *rs_start) 369 { 370 int cpu; 371 char *check; 372 373 /* Process a quantum value */ 374 if (cpe->next != NULL) 375 { 376 fatal("do_cpu: just one value expected at %s:%d", 377 cpe->file, cpe->line); 378 } 379 380 381 if (cpe->flags & CFG_SUBLIST) 382 { 383 fatal("do_cpu: unexpected sublist at %s:%d", 384 cpe->file, cpe->line); 385 } 386 if (cpe->flags & CFG_STRING) 387 { 388 fatal("do_cpu: unexpected string at %s:%d", 389 cpe->file, cpe->line); 390 } 391 cpu= strtol(cpe->word, &check, 0); 392 if (check[0] != '\0') 393 { 394 fatal("do_cpu: bad value '%s' at %s:%d", 395 cpe->word, cpe->file, cpe->line); 396 } 397 398 if (cpu < 0) 399 { 400 fatal("do_cpu: %d out of range at %s:%d", 401 cpu, cpe->file, cpe->line); 402 } 403 rs_start->rss_cpu= cpu; 404 } 405 406 static void do_irq(config_t *cpe, struct rs_start *rs_start) 407 { 408 int irq; 409 int first; 410 char *check; 411 412 /* Process a list of IRQs */ 413 first = TRUE; 414 for (; cpe; cpe= cpe->next) 415 { 416 if (cpe->flags & CFG_SUBLIST) 417 { 418 fatal("do_irq: unexpected sublist at %s:%d", 419 cpe->file, cpe->line); 420 } 421 if (cpe->flags & CFG_STRING) 422 { 423 fatal("do_irq: unexpected string at %s:%d", 424 cpe->file, cpe->line); 425 } 426 427 /* No IRQ allowed? (default) */ 428 if(!strcmp(cpe->word, KW_NONE)) { 429 if(!first || cpe->next) { 430 fatal("do_irq: %s keyword not allowed in list", 431 KW_NONE); 432 } 433 break; 434 } 435 436 /* All IRQs are allowed? */ 437 if(!strcmp(cpe->word, KW_ALL)) { 438 if(!first || cpe->next) { 439 fatal("do_irq: %s keyword not allowed in list", 440 KW_ALL); 441 } 442 rs_start->rss_nr_irq = RSS_IO_ALL; 443 break; 444 } 445 446 /* Set single IRQs as specified in the configuration. */ 447 irq= strtoul(cpe->word, &check, 0); 448 if (check[0] != '\0') 449 { 450 fatal("do_irq: bad irq '%s' at %s:%d", 451 cpe->word, cpe->file, cpe->line); 452 } 453 if (rs_start->rss_nr_irq >= RSS_NR_IRQ) 454 fatal("do_irq: too many IRQs (max %d)", RSS_NR_IRQ); 455 rs_start->rss_irq[rs_start->rss_nr_irq]= irq; 456 rs_start->rss_nr_irq++; 457 first = FALSE; 458 } 459 } 460 461 static void do_io(config_t *cpe, struct rs_start *rs_start) 462 { 463 unsigned base, len; 464 int first; 465 char *check; 466 467 /* Process a list of I/O ranges */ 468 first = TRUE; 469 for (; cpe; cpe= cpe->next) 470 { 471 if (cpe->flags & CFG_SUBLIST) 472 { 473 fatal("do_io: unexpected sublist at %s:%d", 474 cpe->file, cpe->line); 475 } 476 if (cpe->flags & CFG_STRING) 477 { 478 fatal("do_io: unexpected string at %s:%d", 479 cpe->file, cpe->line); 480 } 481 482 /* No range allowed? (default) */ 483 if(!strcmp(cpe->word, KW_NONE)) { 484 if(!first || cpe->next) { 485 fatal("do_io: %s keyword not allowed in list", 486 KW_NONE); 487 } 488 break; 489 } 490 491 /* All ranges are allowed? */ 492 if(!strcmp(cpe->word, KW_ALL)) { 493 if(!first || cpe->next) { 494 fatal("do_io: %s keyword not allowed in list", 495 KW_ALL); 496 } 497 rs_start->rss_nr_io = RSS_IO_ALL; 498 break; 499 } 500 501 /* Set single ranges as specified in the configuration. */ 502 base= strtoul(cpe->word, &check, 0x10); 503 len= 1; 504 if (check[0] == ':') 505 { 506 len= strtoul(check+1, &check, 0x10); 507 } 508 if (check[0] != '\0') 509 { 510 fatal("do_io: bad I/O range '%s' at %s:%d", 511 cpe->word, cpe->file, cpe->line); 512 } 513 514 if (rs_start->rss_nr_io >= RSS_NR_IO) 515 fatal("do_io: too many I/O ranges (max %d)", RSS_NR_IO); 516 rs_start->rss_io[rs_start->rss_nr_io].base= base; 517 rs_start->rss_io[rs_start->rss_nr_io].len= len; 518 rs_start->rss_nr_io++; 519 first = FALSE; 520 } 521 } 522 523 static void do_pci_device(config_t *cpe, struct rs_start *rs_start) 524 { 525 u16_t vid, did, sub_vid, sub_did; 526 char *check, *check2; 527 528 /* Process a list of PCI device IDs */ 529 for (; cpe; cpe= cpe->next) 530 { 531 if (cpe->flags & CFG_SUBLIST) 532 { 533 fatal("do_pci_device: unexpected sublist at %s:%d", 534 cpe->file, cpe->line); 535 } 536 if (cpe->flags & CFG_STRING) 537 { 538 fatal("do_pci_device: unexpected string at %s:%d", 539 cpe->file, cpe->line); 540 } 541 vid= strtoul(cpe->word, &check, 0x10); 542 if (check[0] != ':' && /* LEGACY: */ check[0] != '/') { 543 fatal("do_pci_device: bad ID '%s' at %s:%d", 544 cpe->word, cpe->file, cpe->line); 545 } 546 did= strtoul(check+1, &check, 0x10); 547 if (check[0] == '/') { 548 sub_vid= strtoul(check+1, &check, 0x10); 549 if (check[0] == ':') 550 sub_did= strtoul(check+1, &check2, 0x10); 551 if (check[0] != ':' || check2[0] != '\0') { 552 fatal("do_pci_device: bad ID '%s' at %s:%d", 553 cpe->word, cpe->file, cpe->line); 554 } 555 } else if (check[0] != '\0') { 556 fatal("do_pci_device: bad ID '%s' at %s:%d", 557 cpe->word, cpe->file, cpe->line); 558 } else { 559 sub_vid = NO_SUB_VID; 560 sub_did = NO_SUB_DID; 561 } 562 if (rs_start->rss_nr_pci_id >= RS_NR_PCI_DEVICE) 563 { 564 fatal("do_pci_device: too many device IDs (max %d)", 565 RS_NR_PCI_DEVICE); 566 } 567 rs_start->rss_pci_id[rs_start->rss_nr_pci_id].vid= vid; 568 rs_start->rss_pci_id[rs_start->rss_nr_pci_id].did= did; 569 rs_start->rss_pci_id[rs_start->rss_nr_pci_id].sub_vid= sub_vid; 570 rs_start->rss_pci_id[rs_start->rss_nr_pci_id].sub_did= sub_did; 571 rs_start->rss_nr_pci_id++; 572 } 573 } 574 575 static void do_pci_class(config_t *cpe, struct rs_start *rs_start) 576 { 577 u8_t baseclass, subclass, interface; 578 u32_t class_id, mask; 579 char *check; 580 581 /* Process a list of PCI device class IDs */ 582 for (; cpe; cpe= cpe->next) 583 { 584 if (cpe->flags & CFG_SUBLIST) 585 { 586 fatal("do_pci_device: unexpected sublist at %s:%d", 587 cpe->file, cpe->line); 588 } 589 if (cpe->flags & CFG_STRING) 590 { 591 fatal("do_pci_device: unexpected string at %s:%d", 592 cpe->file, cpe->line); 593 } 594 595 baseclass= strtoul(cpe->word, &check, 0x10); 596 subclass= 0; 597 interface= 0; 598 mask= 0xff0000; 599 if (check[0] == '/') 600 { 601 subclass= strtoul(check+1, &check, 0x10); 602 mask= 0xffff00; 603 if (check[0] == '/') 604 { 605 interface= strtoul(check+1, &check, 0x10); 606 mask= 0xffffff; 607 } 608 } 609 610 if (check[0] != '\0') 611 { 612 fatal("do_pci_class: bad class ID '%s' at %s:%d", 613 cpe->word, cpe->file, cpe->line); 614 } 615 class_id= (baseclass << 16) | (subclass << 8) | interface; 616 if (rs_start->rss_nr_pci_class >= RS_NR_PCI_CLASS) 617 { 618 fatal("do_pci_class: too many class IDs (max %d)", 619 RS_NR_PCI_CLASS); 620 } 621 rs_start->rss_pci_class[rs_start->rss_nr_pci_class].pciclass= 622 class_id; 623 rs_start->rss_pci_class[rs_start->rss_nr_pci_class].mask= mask; 624 rs_start->rss_nr_pci_class++; 625 } 626 } 627 628 static void do_pci(config_t *cpe, struct rs_start *rs_start) 629 { 630 if (cpe == NULL) 631 return; /* Empty PCI statement */ 632 633 if (cpe->flags & CFG_SUBLIST) 634 { 635 fatal("do_pci: unexpected sublist at %s:%d", 636 cpe->file, cpe->line); 637 } 638 if (cpe->flags & CFG_STRING) 639 { 640 fatal("do_pci: unexpected string at %s:%d", 641 cpe->file, cpe->line); 642 } 643 644 if (strcmp(cpe->word, KW_DEVICE) == 0) 645 { 646 do_pci_device(cpe->next, rs_start); 647 return; 648 } 649 if (strcmp(cpe->word, KW_CLASS) == 0) 650 { 651 do_pci_class(cpe->next, rs_start); 652 return; 653 } 654 fatal("do_pci: unexpected word '%s' at %s:%d", 655 cpe->word, cpe->file, cpe->line); 656 } 657 658 static void do_ipc(config_t *cpe, struct rs_start *rs_start) 659 { 660 char *list; 661 const char *word; 662 char *word_all = RSS_IPC_ALL; 663 char *word_all_sys = RSS_IPC_ALL_SYS; 664 size_t listsize, wordlen; 665 int first; 666 667 list= NULL; 668 listsize= 1; 669 list= malloc(listsize); 670 if (list == NULL) 671 fatal("do_ipc: unable to malloc %d bytes", listsize); 672 list[0]= '\0'; 673 674 /* Process a list of process names that are allowed to be 675 * contacted 676 */ 677 first = TRUE; 678 for (; cpe; cpe= cpe->next) 679 { 680 if (cpe->flags & CFG_SUBLIST) 681 { 682 fatal("do_ipc: unexpected sublist at %s:%d", 683 cpe->file, cpe->line); 684 } 685 if (cpe->flags & CFG_STRING) 686 { 687 fatal("do_ipc: unexpected string at %s:%d", 688 cpe->file, cpe->line); 689 } 690 word = cpe->word; 691 692 /* All (system) ipc targets are allowed? */ 693 if(!strcmp(word, KW_ALL) || !strcmp(word, KW_ALL_SYS)) { 694 if(!first || cpe->next) { 695 fatal("do_ipc: %s keyword not allowed in list", 696 word); 697 } 698 word = !strcmp(word, KW_ALL) ? word_all : word_all_sys; 699 } 700 701 wordlen= strlen(word); 702 703 listsize += 1 + wordlen; 704 list= realloc(list, listsize); 705 if (list == NULL) 706 { 707 fatal("do_ipc: unable to realloc %d bytes", 708 listsize); 709 } 710 strcat(list, " "); 711 strcat(list, word); 712 first = FALSE; 713 } 714 #if 0 715 printf("do_ipc: got list '%s'\n", list); 716 #endif 717 718 if (rs_start->rss_ipc) 719 fatal("do_ipc: req_ipc is set"); 720 rs_start->rss_ipc = list+1; 721 rs_start->rss_ipclen= strlen(rs_start->rss_ipc); 722 } 723 724 725 struct 726 { 727 char *label; 728 int call_nr; 729 } vm_table[] = 730 { 731 { "EXIT", VM_EXIT }, 732 { "FORK", VM_FORK }, 733 { "EXEC_NEWMEM", VM_EXEC_NEWMEM }, 734 { "PUSH_SIG", 0 }, 735 { "WILLEXIT", VM_WILLEXIT }, 736 { "ADDDMA", VM_ADDDMA }, 737 { "DELDMA", VM_DELDMA }, 738 { "GETDMA", VM_GETDMA }, 739 { "REMAP", VM_REMAP }, 740 { "REMAP_RO", VM_REMAP_RO }, 741 { "SHM_UNMAP", VM_SHM_UNMAP }, 742 { "GETPHYS", VM_GETPHYS }, 743 { "GETREF", VM_GETREF }, 744 { "RS_SET_PRIV", VM_RS_SET_PRIV }, 745 { "INFO", VM_INFO }, 746 { "RS_UPDATE", VM_RS_UPDATE }, 747 { "RS_MEMCTL", VM_RS_MEMCTL }, 748 { "PROCCTL", VM_PROCCTL }, 749 { "MAPCACHEPAGE", VM_MAPCACHEPAGE }, 750 { "SETCACHEPAGE", VM_SETCACHEPAGE }, 751 { "FORGETCACHEPAGE", VM_FORGETCACHEPAGE }, 752 { "CLEARCACHE", VM_CLEARCACHE }, 753 { "VFS_MMAP", VM_VFS_MMAP }, 754 { "VFS_REPLY", VM_VFS_REPLY }, 755 { "GETRUSAGE", VM_GETRUSAGE }, 756 { "RS_PREPARE", VM_RS_PREPARE }, 757 { NULL, 0 }, 758 }; 759 760 static void do_vm(config_t *cpe, struct rs_start *rs_start) 761 { 762 int i, first; 763 764 first = TRUE; 765 for (; cpe; cpe = cpe->next) 766 { 767 if (cpe->flags & CFG_SUBLIST) 768 { 769 fatal("do_vm: unexpected sublist at %s:%d", 770 cpe->file, cpe->line); 771 } 772 if (cpe->flags & CFG_STRING) 773 { 774 fatal("do_vm: unexpected string at %s:%d", 775 cpe->file, cpe->line); 776 } 777 778 /* Only basic calls allowed? (default). */ 779 if(!strcmp(cpe->word, KW_BASIC)) { 780 if(!first || cpe->next) { 781 fatal("do_vm: %s keyword not allowed in list", 782 KW_NONE); 783 } 784 break; 785 } 786 787 /* No calls allowed? */ 788 if(!strcmp(cpe->word, KW_NONE)) { 789 if(!first || cpe->next) { 790 fatal("do_vm: %s keyword not allowed in list", 791 KW_NONE); 792 } 793 rs_start->rss_flags &= ~RSS_VM_BASIC_CALLS; 794 break; 795 } 796 797 /* All calls are allowed? */ 798 if(!strcmp(cpe->word, KW_ALL)) { 799 if(!first || cpe->next) { 800 fatal("do_vm: %s keyword not allowed in list", 801 KW_ALL); 802 } 803 for (i = 0; i < NR_VM_CALLS; i++) 804 SET_BIT(rs_start->rss_vm, i); 805 break; 806 } 807 808 /* Set single calls as specified in the configuration. */ 809 for (i = 0; vm_table[i].label != NULL; i++) 810 if (!strcmp(cpe->word, vm_table[i].label)) 811 break; 812 if (vm_table[i].label == NULL) { 813 warning("do_vm: ignoring unknown call '%s' at %s:%d", 814 cpe->word, cpe->file, cpe->line); 815 } else if(vm_table[i].call_nr) { 816 SET_BIT(rs_start->rss_vm, 817 vm_table[i].call_nr - VM_RQ_BASE); 818 } 819 820 first = FALSE; 821 } 822 } 823 824 struct 825 { 826 char *label; 827 int call_nr; 828 } system_tab[]= 829 { 830 { "PRIVCTL", SYS_PRIVCTL }, 831 { "TRACE", SYS_TRACE }, 832 { "KILL", SYS_KILL }, 833 { "UMAP", SYS_UMAP }, 834 { "VIRCOPY", SYS_VIRCOPY }, 835 { "PHYSCOPY", SYS_PHYSCOPY }, 836 { "UMAP_REMOTE", SYS_UMAP_REMOTE }, 837 { "VUMAP", SYS_VUMAP }, 838 { "IRQCTL", SYS_IRQCTL }, 839 { "DEVIO", SYS_DEVIO }, 840 { "SDEVIO", SYS_SDEVIO }, 841 { "VDEVIO", SYS_VDEVIO }, 842 { "ABORT", SYS_ABORT }, 843 { "IOPENABLE", SYS_IOPENABLE }, 844 { "READBIOS", SYS_READBIOS }, 845 { "STIME", SYS_STIME }, 846 { "VMCTL", SYS_VMCTL }, 847 { "MEMSET", SYS_MEMSET }, 848 { "PADCONF", SYS_PADCONF }, 849 { NULL, 0 } 850 }; 851 852 static void do_system(config_t *cpe, struct rs_start *rs_start) 853 { 854 int i, first; 855 856 /* Process a list of 'system' calls that are allowed */ 857 first = TRUE; 858 for (; cpe; cpe= cpe->next) 859 { 860 if (cpe->flags & CFG_SUBLIST) 861 { 862 fatal("do_system: unexpected sublist at %s:%d", 863 cpe->file, cpe->line); 864 } 865 if (cpe->flags & CFG_STRING) 866 { 867 fatal("do_system: unexpected string at %s:%d", 868 cpe->file, cpe->line); 869 } 870 871 /* Only basic calls allowed? (default). */ 872 if(!strcmp(cpe->word, KW_BASIC)) { 873 if(!first || cpe->next) { 874 fatal("do_system: %s keyword not allowed in list", 875 KW_NONE); 876 } 877 break; 878 } 879 880 /* No calls allowed? */ 881 if(!strcmp(cpe->word, KW_NONE)) { 882 if(!first || cpe->next) { 883 fatal("do_system: %s keyword not allowed in list", 884 KW_NONE); 885 } 886 rs_start->rss_flags &= ~RSS_SYS_BASIC_CALLS; 887 break; 888 } 889 890 /* All calls are allowed? */ 891 if(!strcmp(cpe->word, KW_ALL)) { 892 if(!first || cpe->next) { 893 fatal("do_system: %s keyword not allowed in list", 894 KW_ALL); 895 } 896 for (i = 0; i < NR_SYS_CALLS; i++) 897 SET_BIT(rs_start->rss_system, i); 898 break; 899 } 900 901 /* Set single calls as specified in the configuration. */ 902 for (i = 0; system_tab[i].label != NULL; i++) 903 if (!strcmp(cpe->word, system_tab[i].label)) 904 break; 905 if (system_tab[i].label == NULL) { 906 warning("do_system: ignoring unknown call '%s' at %s:%d", 907 cpe->word, cpe->file, cpe->line); 908 } else { 909 SET_BIT(rs_start->rss_system, 910 system_tab[i].call_nr - KERNEL_CALL); 911 } 912 first = FALSE; 913 } 914 } 915 916 static void do_control(config_t *cpe, struct rs_start *rs_start) 917 { 918 int nr_control = 0; 919 920 /* Process a list of 'control' labels. */ 921 for (; cpe; cpe= cpe->next) 922 { 923 if (cpe->flags & CFG_SUBLIST) 924 { 925 fatal("do_control: unexpected sublist at %s:%d", 926 cpe->file, cpe->line); 927 } 928 if (cpe->flags & CFG_STRING) 929 { 930 fatal("do_control: unexpected string at %s:%d", 931 cpe->file, cpe->line); 932 } 933 if (nr_control >= RS_NR_CONTROL) 934 { 935 fatal( 936 "do_control: RS_NR_CONTROL is too small (%d needed)", 937 nr_control+1); 938 } 939 940 rs_start->rss_control[nr_control].l_addr = (char*) cpe->word; 941 rs_start->rss_control[nr_control].l_len = strlen(cpe->word); 942 rs_start->rss_nr_control = ++nr_control; 943 } 944 } 945 946 static const struct { 947 const char *name; 948 int domain; 949 } domain_tab[] = { 950 /* PF_UNSPEC should not be in this table. */ 951 { "LOCAL", PF_LOCAL }, 952 { "INET", PF_INET }, 953 { "IMPLINK", PF_IMPLINK }, 954 { "PUP", PF_PUP }, 955 { "CHAOS", PF_CHAOS }, 956 { "NS", PF_NS }, 957 { "ISO", PF_ISO }, 958 { "ECMA", PF_ECMA }, 959 { "DATAKIT", PF_DATAKIT }, 960 { "CCITT", PF_CCITT }, 961 { "SNA", PF_SNA }, 962 { "DECnet", PF_DECnet }, 963 { "DLI", PF_DLI }, 964 { "LAT", PF_LAT }, 965 { "HYLINK", PF_HYLINK }, 966 { "APPLETALK", PF_APPLETALK }, 967 { "OROUTE", PF_OROUTE }, 968 { "LINK", PF_LINK }, 969 { "XTP", PF_XTP }, 970 { "COIP", PF_COIP }, 971 { "CNT", PF_CNT }, 972 { "RTIP", PF_RTIP }, 973 { "IPX", PF_IPX }, 974 { "INET6", PF_INET6 }, 975 { "PIP", PF_PIP }, 976 { "ISDN", PF_ISDN }, 977 { "NATM", PF_NATM }, 978 { "ARP", PF_ARP }, 979 { "KEY", PF_KEY }, 980 { "BLUETOOTH", PF_BLUETOOTH }, 981 /* There is no PF_IEEE80211. */ 982 { "MPLS", PF_MPLS }, 983 { "ROUTE", PF_ROUTE }, 984 }; 985 986 /* 987 * Process a list of 'domain' protocol families for socket drivers. 988 */ 989 static void 990 do_domain(config_t * cpe, struct rs_start * rs_start) 991 { 992 unsigned int i; 993 int nr_domain, domain; 994 995 for (nr_domain = 0; cpe != NULL; cpe = cpe->next) { 996 if (cpe->flags & CFG_SUBLIST) { 997 fatal("do_domain: unexpected sublist at %s:%d", 998 cpe->file, cpe->line); 999 } 1000 if (cpe->flags & CFG_STRING) { 1001 fatal("do_domain: unexpected string at %s:%d", 1002 cpe->file, cpe->line); 1003 } 1004 if (nr_domain >= __arraycount(rs_start->rss_domain)) { 1005 fatal("do_domain: NR_DOMAIN is too small (%d needed)", 1006 nr_domain + 1); 1007 } 1008 1009 for (i = 0; i < __arraycount(domain_tab); i++) 1010 if (!strcmp(domain_tab[i].name, (char *)cpe->word)) 1011 break; 1012 if (i < __arraycount(domain_tab)) 1013 domain = domain_tab[i].domain; 1014 else 1015 domain = atoi((char *)cpe->word); 1016 1017 if (domain <= 0 || domain >= PF_MAX) { 1018 fatal("do_domain: unknown domain %s at %s:%d", 1019 (char *)cpe->word, cpe->file, cpe->line); 1020 } 1021 1022 rs_start->rss_domain[nr_domain] = domain; 1023 rs_start->rss_nr_domain = ++nr_domain; 1024 } 1025 } 1026 1027 static void do_service(config_t *cpe, config_t *config, struct rs_config *rs_config) 1028 { 1029 struct rs_start *rs_start = &rs_config->rs_start; 1030 config_t *cp; 1031 1032 /* At this point we expect one sublist that contains the varios 1033 * resource allocations 1034 */ 1035 if (!(cpe->flags & CFG_SUBLIST)) 1036 { 1037 fatal("do_service: expected list at %s:%d", 1038 cpe->file, cpe->line); 1039 } 1040 if (cpe->next != NULL) 1041 { 1042 cpe= cpe->next; 1043 fatal("do_service: expected end of list at %s:%d", 1044 cpe->file, cpe->line); 1045 } 1046 cpe= cpe->list; 1047 1048 /* Process the list */ 1049 for (cp= cpe; cp; cp= cp->next) 1050 { 1051 if (!(cp->flags & CFG_SUBLIST)) 1052 { 1053 fatal("do_service: expected list at %s:%d", 1054 cp->file, cp->line); 1055 } 1056 cpe= cp->list; 1057 if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) 1058 { 1059 fatal("do_service: expected word at %s:%d", 1060 cpe->file, cpe->line); 1061 } 1062 1063 if (strcmp(cpe->word, KW_CLASS) == 0) 1064 { 1065 do_class(cpe->next, config, rs_config); 1066 continue; 1067 } 1068 if (strcmp(cpe->word, KW_UID) == 0) 1069 { 1070 do_uid(cpe->next, rs_start); 1071 continue; 1072 } 1073 if (strcmp(cpe->word, KW_SIGMGR) == 0) 1074 { 1075 do_sigmgr(cpe->next, rs_start); 1076 continue; 1077 } 1078 if (strcmp(cpe->word, KW_TYPE) == 0) 1079 { 1080 do_type(cpe->next, rs_config); 1081 continue; 1082 } 1083 if (strcmp(cpe->word, KW_DESCR) == 0) 1084 { 1085 do_descr(cpe->next, rs_config); 1086 continue; 1087 } 1088 if (strcmp(cpe->word, KW_SCHEDULER) == 0) 1089 { 1090 do_scheduler(cpe->next, rs_start); 1091 continue; 1092 } 1093 if (strcmp(cpe->word, KW_PRIORITY) == 0) 1094 { 1095 do_priority(cpe->next, rs_start); 1096 continue; 1097 } 1098 if (strcmp(cpe->word, KW_QUANTUM) == 0) 1099 { 1100 do_quantum(cpe->next, rs_start); 1101 continue; 1102 } 1103 if (strcmp(cpe->word, KW_CPU) == 0) 1104 { 1105 do_cpu(cpe->next, rs_start); 1106 continue; 1107 } 1108 if (strcmp(cpe->word, KW_IRQ) == 0) 1109 { 1110 do_irq(cpe->next, rs_start); 1111 continue; 1112 } 1113 if (strcmp(cpe->word, KW_IO) == 0) 1114 { 1115 do_io(cpe->next, rs_start); 1116 continue; 1117 } 1118 if (strcmp(cpe->word, KW_PCI) == 0) 1119 { 1120 do_pci(cpe->next, rs_start); 1121 continue; 1122 } 1123 if (strcmp(cpe->word, KW_SYSTEM) == 0) 1124 { 1125 do_system(cpe->next, rs_start); 1126 continue; 1127 } 1128 if (strcmp(cpe->word, KW_IPC) == 0) 1129 { 1130 do_ipc(cpe->next, rs_start); 1131 continue; 1132 } 1133 if (strcmp(cpe->word, KW_VM) == 0) 1134 { 1135 do_vm(cpe->next, rs_start); 1136 continue; 1137 } 1138 if (strcmp(cpe->word, KW_CONTROL) == 0) 1139 { 1140 do_control(cpe->next, rs_start); 1141 continue; 1142 } 1143 if (strcmp(cpe->word, KW_DOMAIN) == 0) 1144 { 1145 do_domain(cpe->next, rs_start); 1146 continue; 1147 } 1148 } 1149 } 1150 1151 static const char *do_config(const char *label, char *filename, struct rs_config *rs_config) 1152 { 1153 config_t *config, *cp, *cpe; 1154 struct passwd *pw; 1155 struct rs_start *rs_start = &rs_config->rs_start; 1156 1157 if(!(config= config_read(filename, 0, NULL))) 1158 return NULL; /* config file read failed. */ 1159 1160 /* Set clean rs_start defaults. */ 1161 memset(rs_config, 0, sizeof(*rs_config)); 1162 if(!(pw= getpwnam(SERVICE_LOGIN))) 1163 fatal("no passwd file entry for '%s'", SERVICE_LOGIN); 1164 rs_start->rss_uid= pw->pw_uid; 1165 rs_start->rss_sigmgr= DSRV_SM; 1166 rs_start->rss_scheduler= DSRV_SCH; 1167 rs_start->rss_priority= DSRV_Q; 1168 rs_start->rss_quantum= DSRV_QT; 1169 rs_start->rss_cpu = DSRV_CPU; 1170 rs_start->rss_flags = RSS_VM_BASIC_CALLS | RSS_SYS_BASIC_CALLS; 1171 1172 /* Find an entry for our service */ 1173 for (cp= config; cp; cp= cp->next) 1174 { 1175 if (!(cp->flags & CFG_SUBLIST)) 1176 { 1177 fatal("do_config: expected list at %s:%d", 1178 cp->file, cp->line); 1179 } 1180 cpe= cp->list; 1181 if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) 1182 { 1183 fatal("do_config: expected word at %s:%d", 1184 cpe->file, cpe->line); 1185 } 1186 1187 /* At this place we expect the word KW_SERVICE */ 1188 if (strcmp(cpe->word, KW_SERVICE) != 0) 1189 fatal("do_config: exected word '%S' at %s:%d", 1190 KW_SERVICE, cpe->file, cpe->line); 1191 1192 cpe= cpe->next; 1193 if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) 1194 { 1195 fatal("do_config: expected word at %s:%d", 1196 cpe->file, cpe->line); 1197 } 1198 1199 /* At this place we expect the name of the service. */ 1200 if (!label || strcmp(cpe->word, label) == 0) { 1201 label = cpe->word; 1202 break; 1203 } 1204 } 1205 if (cp == NULL) 1206 { 1207 fprintf(stderr, "minix-service: service '%s' not found in " 1208 "'%s'\n", label, filename); 1209 exit(1); 1210 } 1211 1212 cpe= cpe->next; 1213 1214 do_service(cpe, config, rs_config); 1215 1216 { 1217 char *default_ipc = RSS_IPC_ALL_SYS; 1218 if(!rs_start->rss_ipc) { 1219 rs_start->rss_ipc= default_ipc; 1220 rs_start->rss_ipclen= strlen(default_ipc); 1221 } 1222 } 1223 1224 /* config file read ok. */ 1225 return label; 1226 } 1227 1228 /* returns failure */ 1229 const char *parse_config(char *progname, int custom_config, char *req_config, 1230 struct rs_config *rs_config) 1231 { 1232 char *specificconfig, *specific_pkg_config; 1233 const char *l; 1234 1235 /* Config file specified? */ 1236 if(custom_config) 1237 return do_config(progname, req_config, rs_config); 1238 1239 /* No specific config file. */ 1240 if(asprintf(&specificconfig, "%s/%s", _PATH_SYSTEM_CONF_DIR, 1241 progname) < 0) { 1242 errx(1, "no memory"); 1243 } 1244 1245 if(asprintf(&specific_pkg_config, "%s/%s", _PATH_SYSTEM_CONF_PKG_DIR, 1246 progname) < 0) { 1247 errx(1, "no memory"); 1248 } 1249 1250 /* Try specific config filename first, in base system 1251 * and package locations, * and only if it fails, the global 1252 * system one. 1253 */ 1254 if((l=do_config(progname, specific_pkg_config, rs_config))) return l; 1255 if((l=do_config(progname, specificconfig, rs_config))) return l; 1256 if((l=do_config(progname, req_config, rs_config))) return l; 1257 1258 return NULL; 1259 } 1260 1261