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