Improve the process for GNU tools
[minix3.git] / minix / commands / service / parse.c
blobdfae9e3c37c7e5411f121d38fe2d2982603a0271
2 #define _MINIX_SYSTEM 1
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>
31 #include <machine/archtypes.h>
32 #include <minix/timers.h>
34 #include "config.h"
35 #include "proto.h"
37 static int class_recurs; /* Nesting level of class statements */
38 #define MAX_CLASS_RECURS 100 /* Max nesting level for classes */
40 #include "parse.h"
42 static void do_service(config_t *cpe, config_t *config, struct rs_config *);
44 static void do_class(config_t *cpe, config_t *config, struct rs_config *rs_config)
46 config_t *cp, *cp1;
48 if (class_recurs > MAX_CLASS_RECURS)
50 fatal(
51 "do_class: nesting level too high for class '%s' at %s:%d",
52 cpe->word, cpe->file, cpe->line);
54 class_recurs++;
56 /* Process classes */
57 for (; cpe; cpe= cpe->next)
59 if (cpe->flags & CFG_SUBLIST)
61 fatal("do_class: unexpected sublist at %s:%d",
62 cpe->file, cpe->line);
64 if (cpe->flags & CFG_STRING)
66 fatal("do_uid: unexpected string at %s:%d",
67 cpe->file, cpe->line);
70 /* Find entry for the class */
71 for (cp= config; cp; cp= cp->next)
73 if (!(cp->flags & CFG_SUBLIST))
75 fatal("do_class: expected list at %s:%d",
76 cp->file, cp->line);
78 cp1= cp->list;
79 if ((cp1->flags & CFG_STRING) ||
80 (cp1->flags & CFG_SUBLIST))
82 fatal("do_class: expected word at %s:%d",
83 cp1->file, cp1->line);
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);
91 cp1= cp1->next;
92 if ((cp1->flags & CFG_STRING) ||
93 (cp1->flags & CFG_SUBLIST))
95 fatal("do_class: expected word at %s:%d",
96 cp1->file, cp1->line);
99 /* At this place we expect the name of the service */
100 if (strcmp(cp1->word, cpe->word) == 0)
101 break;
103 if (cp == NULL)
105 fatal(
106 "do_class: no entry found for class '%s' at %s:%d",
107 cpe->word, cpe->file, cpe->line);
109 do_service(cp1->next, config, rs_config);
112 class_recurs--;
115 static void do_uid(config_t *cpe, struct rs_start *rs_start)
117 uid_t uid;
118 struct passwd *pw;
119 char *check;
121 /* Process a uid */
122 if (cpe->next != NULL)
124 fatal("do_uid: just one uid/login expected at %s:%d",
125 cpe->file, cpe->line);
128 if (cpe->flags & CFG_SUBLIST)
130 fatal("do_uid: unexpected sublist at %s:%d",
131 cpe->file, cpe->line);
133 if (cpe->flags & CFG_STRING)
135 fatal("do_uid: unexpected string at %s:%d",
136 cpe->file, cpe->line);
138 pw= getpwnam(cpe->word);
139 if (pw != NULL)
140 uid= pw->pw_uid;
141 else
143 if (!strncmp(cpe->word, KW_SELF, strlen(KW_SELF)+1))
145 uid= getuid(); /* Real uid */
147 else {
148 uid= strtol(cpe->word, &check, 0);
149 if (check[0] != '\0')
151 fatal("do_uid: bad uid/login '%s' at %s:%d",
152 cpe->word, cpe->file, cpe->line);
157 rs_start->rss_uid= uid;
160 static void do_sigmgr(config_t *cpe, struct rs_start *rs_start)
162 endpoint_t sigmgr_ep;
163 int r;
165 /* Process a signal manager value */
166 if (cpe->next != NULL)
168 fatal("do_sigmgr: just one sigmgr value expected at %s:%d",
169 cpe->file, cpe->line);
173 if (cpe->flags & CFG_SUBLIST)
175 fatal("do_sigmgr: unexpected sublist at %s:%d",
176 cpe->file, cpe->line);
178 if (cpe->flags & CFG_STRING)
180 fatal("do_sigmgr: unexpected string at %s:%d",
181 cpe->file, cpe->line);
184 if(!strcmp(cpe->word, "SELF")) {
185 sigmgr_ep = SELF;
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);
194 rs_start->rss_sigmgr= sigmgr_ep;
197 static void do_type(config_t *cpe, struct rs_config *rs_config)
199 if (cpe->next != NULL)
201 fatal("do_type: just one type value expected at %s:%d",
202 cpe->file, cpe->line);
206 if (cpe->flags & CFG_SUBLIST)
208 fatal("do_type: unexpected sublist at %s:%d",
209 cpe->file, cpe->line);
211 if ((cpe->flags & CFG_STRING))
213 fatal("do_type: unexpected string at %s:%d",
214 cpe->file, cpe->line);
217 if(rs_config->type)
218 fatal("do_type: another type at %s:%d",
219 cpe->file, cpe->line);
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);
228 static void do_descr(config_t *cpe, struct rs_config *rs_config)
230 if (cpe->next != NULL)
232 fatal("do_descr: just one description expected at %s:%d",
233 cpe->file, cpe->line);
237 if (cpe->flags & CFG_SUBLIST)
239 fatal("do_descr: unexpected sublist at %s:%d",
240 cpe->file, cpe->line);
242 if (!(cpe->flags & CFG_STRING))
244 fatal("do_descr: expected string at %s:%d",
245 cpe->file, cpe->line);
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;
254 static void do_scheduler(config_t *cpe, struct rs_start *rs_start)
256 endpoint_t scheduler_ep;
257 int r;
259 /* Process a scheduler value */
260 if (cpe->next != NULL)
262 fatal("do_scheduler: just one scheduler value expected at %s:%d",
263 cpe->file, cpe->line);
267 if (cpe->flags & CFG_SUBLIST)
269 fatal("do_scheduler: unexpected sublist at %s:%d",
270 cpe->file, cpe->line);
272 if (cpe->flags & CFG_STRING)
274 fatal("do_scheduler: unexpected string at %s:%d",
275 cpe->file, cpe->line);
278 if(!strcmp(cpe->word, "KERNEL")) {
279 scheduler_ep = KERNEL;
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);
288 rs_start->rss_scheduler= scheduler_ep;
291 static void do_priority(config_t *cpe, struct rs_start *rs_start)
293 int priority_val;
294 char *check;
296 /* Process a priority value */
297 if (cpe->next != NULL)
299 fatal("do_priority: just one priority value expected at %s:%d",
300 cpe->file, cpe->line);
304 if (cpe->flags & CFG_SUBLIST)
306 fatal("do_priority: unexpected sublist at %s:%d",
307 cpe->file, cpe->line);
309 if (cpe->flags & CFG_STRING)
311 fatal("do_priority: unexpected string at %s:%d",
312 cpe->file, cpe->line);
314 priority_val= strtol(cpe->word, &check, 0);
315 if (check[0] != '\0')
317 fatal("do_priority: bad priority value '%s' at %s:%d",
318 cpe->word, cpe->file, cpe->line);
321 if (priority_val < 0 || priority_val >= NR_SCHED_QUEUES)
323 fatal("do_priority: priority %d out of range at %s:%d",
324 priority_val, cpe->file, cpe->line);
326 rs_start->rss_priority= priority_val;
329 static void do_quantum(config_t *cpe, struct rs_start *rs_start)
331 int quantum_val;
332 char *check;
334 /* Process a quantum value */
335 if (cpe->next != NULL)
337 fatal("do_quantum: just one quantum value expected at %s:%d",
338 cpe->file, cpe->line);
342 if (cpe->flags & CFG_SUBLIST)
344 fatal("do_quantum: unexpected sublist at %s:%d",
345 cpe->file, cpe->line);
347 if (cpe->flags & CFG_STRING)
349 fatal("do_quantum: unexpected string at %s:%d",
350 cpe->file, cpe->line);
352 quantum_val= strtol(cpe->word, &check, 0);
353 if (check[0] != '\0')
355 fatal("do_quantum: bad quantum value '%s' at %s:%d",
356 cpe->word, cpe->file, cpe->line);
359 if (quantum_val <= 0)
361 fatal("do_quantum: quantum %d out of range at %s:%d",
362 quantum_val, cpe->file, cpe->line);
364 rs_start->rss_quantum= quantum_val;
367 static void do_cpu(config_t *cpe, struct rs_start *rs_start)
369 int cpu;
370 char *check;
372 /* Process a quantum value */
373 if (cpe->next != NULL)
375 fatal("do_cpu: just one value expected at %s:%d",
376 cpe->file, cpe->line);
380 if (cpe->flags & CFG_SUBLIST)
382 fatal("do_cpu: unexpected sublist at %s:%d",
383 cpe->file, cpe->line);
385 if (cpe->flags & CFG_STRING)
387 fatal("do_cpu: unexpected string at %s:%d",
388 cpe->file, cpe->line);
390 cpu= strtol(cpe->word, &check, 0);
391 if (check[0] != '\0')
393 fatal("do_cpu: bad value '%s' at %s:%d",
394 cpe->word, cpe->file, cpe->line);
397 if (cpu < 0)
399 fatal("do_cpu: %d out of range at %s:%d",
400 cpu, cpe->file, cpe->line);
402 rs_start->rss_cpu= cpu;
405 static void do_irq(config_t *cpe, struct rs_start *rs_start)
407 int irq;
408 int first;
409 char *check;
411 /* Process a list of IRQs */
412 first = TRUE;
413 for (; cpe; cpe= cpe->next)
415 if (cpe->flags & CFG_SUBLIST)
417 fatal("do_irq: unexpected sublist at %s:%d",
418 cpe->file, cpe->line);
420 if (cpe->flags & CFG_STRING)
422 fatal("do_irq: unexpected string at %s:%d",
423 cpe->file, cpe->line);
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);
432 break;
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);
441 rs_start->rss_nr_irq = RSS_IO_ALL;
442 break;
445 /* Set single IRQs as specified in the configuration. */
446 irq= strtoul(cpe->word, &check, 0);
447 if (check[0] != '\0')
449 fatal("do_irq: bad irq '%s' at %s:%d",
450 cpe->word, cpe->file, cpe->line);
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;
460 static void do_io(config_t *cpe, struct rs_start *rs_start)
462 unsigned base, len;
463 int first;
464 char *check;
466 /* Process a list of I/O ranges */
467 first = TRUE;
468 for (; cpe; cpe= cpe->next)
470 if (cpe->flags & CFG_SUBLIST)
472 fatal("do_io: unexpected sublist at %s:%d",
473 cpe->file, cpe->line);
475 if (cpe->flags & CFG_STRING)
477 fatal("do_io: unexpected string at %s:%d",
478 cpe->file, cpe->line);
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);
487 break;
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);
496 rs_start->rss_nr_io = RSS_IO_ALL;
497 break;
500 /* Set single ranges as specified in the configuration. */
501 base= strtoul(cpe->word, &check, 0x10);
502 len= 1;
503 if (check[0] == ':')
505 len= strtoul(check+1, &check, 0x10);
507 if (check[0] != '\0')
509 fatal("do_io: bad I/O range '%s' at %s:%d",
510 cpe->word, cpe->file, cpe->line);
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;
522 static void do_pci_device(config_t *cpe, struct rs_start *rs_start)
524 u16_t vid, did, sub_vid, sub_did;
525 char *check, *check2;
527 /* Process a list of PCI device IDs */
528 for (; cpe; cpe= cpe->next)
530 if (cpe->flags & CFG_SUBLIST)
532 fatal("do_pci_device: unexpected sublist at %s:%d",
533 cpe->file, cpe->line);
535 if (cpe->flags & CFG_STRING)
537 fatal("do_pci_device: unexpected string at %s:%d",
538 cpe->file, cpe->line);
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);
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);
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;
561 if (rs_start->rss_nr_pci_id >= RS_NR_PCI_DEVICE)
563 fatal("do_pci_device: too many device IDs (max %d)",
564 RS_NR_PCI_DEVICE);
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++;
574 static void do_pci_class(config_t *cpe, struct rs_start *rs_start)
576 u8_t baseclass, subclass, interface;
577 u32_t class_id, mask;
578 char *check;
580 /* Process a list of PCI device class IDs */
581 for (; cpe; cpe= cpe->next)
583 if (cpe->flags & CFG_SUBLIST)
585 fatal("do_pci_device: unexpected sublist at %s:%d",
586 cpe->file, cpe->line);
588 if (cpe->flags & CFG_STRING)
590 fatal("do_pci_device: unexpected string at %s:%d",
591 cpe->file, cpe->line);
594 baseclass= strtoul(cpe->word, &check, 0x10);
595 subclass= 0;
596 interface= 0;
597 mask= 0xff0000;
598 if (check[0] == '/')
600 subclass= strtoul(check+1, &check, 0x10);
601 mask= 0xffff00;
602 if (check[0] == '/')
604 interface= strtoul(check+1, &check, 0x10);
605 mask= 0xffffff;
609 if (check[0] != '\0')
611 fatal("do_pci_class: bad class ID '%s' at %s:%d",
612 cpe->word, cpe->file, cpe->line);
614 class_id= (baseclass << 16) | (subclass << 8) | interface;
615 if (rs_start->rss_nr_pci_class >= RS_NR_PCI_CLASS)
617 fatal("do_pci_class: too many class IDs (max %d)",
618 RS_NR_PCI_CLASS);
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++;
627 static void do_pci(config_t *cpe, struct rs_start *rs_start)
629 if (cpe == NULL)
630 return; /* Empty PCI statement */
632 if (cpe->flags & CFG_SUBLIST)
634 fatal("do_pci: unexpected sublist at %s:%d",
635 cpe->file, cpe->line);
637 if (cpe->flags & CFG_STRING)
639 fatal("do_pci: unexpected string at %s:%d",
640 cpe->file, cpe->line);
643 if (strcmp(cpe->word, KW_DEVICE) == 0)
645 do_pci_device(cpe->next, rs_start);
646 return;
648 if (strcmp(cpe->word, KW_CLASS) == 0)
650 do_pci_class(cpe->next, rs_start);
651 return;
653 fatal("do_pci: unexpected word '%s' at %s:%d",
654 cpe->word, cpe->file, cpe->line);
657 static void do_ipc(config_t *cpe, struct rs_start *rs_start)
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;
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';
673 /* Process a list of process names that are allowed to be
674 * contacted
676 first = TRUE;
677 for (; cpe; cpe= cpe->next)
679 if (cpe->flags & CFG_SUBLIST)
681 fatal("do_ipc: unexpected sublist at %s:%d",
682 cpe->file, cpe->line);
684 if (cpe->flags & CFG_STRING)
686 fatal("do_ipc: unexpected string at %s:%d",
687 cpe->file, cpe->line);
689 word = cpe->word;
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);
697 word = !strcmp(word, KW_ALL) ? word_all : word_all_sys;
700 wordlen= strlen(word);
702 listsize += 1 + wordlen;
703 list= realloc(list, listsize);
704 if (list == NULL)
706 fatal("do_ipc: unable to realloc %d bytes",
707 listsize);
709 strcat(list, " ");
710 strcat(list, word);
711 first = FALSE;
713 #if 0
714 printf("do_ipc: got list '%s'\n", list);
715 #endif
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);
724 struct
726 char *label;
727 int call_nr;
728 } vm_table[] =
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 },
759 static void do_vm(config_t *cpe, struct rs_start *rs_start)
761 int i, first;
763 first = TRUE;
764 for (; cpe; cpe = cpe->next)
766 if (cpe->flags & CFG_SUBLIST)
768 fatal("do_vm: unexpected sublist at %s:%d",
769 cpe->file, cpe->line);
771 if (cpe->flags & CFG_STRING)
773 fatal("do_vm: unexpected string at %s:%d",
774 cpe->file, cpe->line);
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);
783 break;
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);
792 rs_start->rss_flags &= ~RSS_VM_BASIC_CALLS;
793 break;
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);
802 for (i = 0; i < NR_VM_CALLS; i++)
803 SET_BIT(rs_start->rss_vm, i);
804 break;
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);
819 first = FALSE;
823 struct
825 char *label;
826 int call_nr;
827 } system_tab[]=
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 }
851 static void do_system(config_t *cpe, struct rs_start *rs_start)
853 int i, first;
855 /* Process a list of 'system' calls that are allowed */
856 first = TRUE;
857 for (; cpe; cpe= cpe->next)
859 if (cpe->flags & CFG_SUBLIST)
861 fatal("do_system: unexpected sublist at %s:%d",
862 cpe->file, cpe->line);
864 if (cpe->flags & CFG_STRING)
866 fatal("do_system: unexpected string at %s:%d",
867 cpe->file, cpe->line);
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);
876 break;
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);
885 rs_start->rss_flags &= ~RSS_SYS_BASIC_CALLS;
886 break;
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);
895 for (i = 0; i < NR_SYS_CALLS; i++)
896 SET_BIT(rs_start->rss_system, i);
897 break;
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);
911 first = FALSE;
915 static void do_control(config_t *cpe, struct rs_start *rs_start)
917 int nr_control = 0;
919 /* Process a list of 'control' labels. */
920 for (; cpe; cpe= cpe->next)
922 if (cpe->flags & CFG_SUBLIST)
924 fatal("do_control: unexpected sublist at %s:%d",
925 cpe->file, cpe->line);
927 if (cpe->flags & CFG_STRING)
929 fatal("do_control: unexpected string at %s:%d",
930 cpe->file, cpe->line);
932 if (nr_control >= RS_NR_CONTROL)
934 fatal(
935 "do_control: RS_NR_CONTROL is too small (%d needed)",
936 nr_control+1);
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;
945 static void do_service(config_t *cpe, config_t *config, struct rs_config *rs_config)
947 struct rs_start *rs_start = &rs_config->rs_start;
948 config_t *cp;
950 /* At this point we expect one sublist that contains the varios
951 * resource allocations
953 if (!(cpe->flags & CFG_SUBLIST))
955 fatal("do_service: expected list at %s:%d",
956 cpe->file, cpe->line);
958 if (cpe->next != NULL)
960 cpe= cpe->next;
961 fatal("do_service: expected end of list at %s:%d",
962 cpe->file, cpe->line);
964 cpe= cpe->list;
966 /* Process the list */
967 for (cp= cpe; cp; cp= cp->next)
969 if (!(cp->flags & CFG_SUBLIST))
971 fatal("do_service: expected list at %s:%d",
972 cp->file, cp->line);
974 cpe= cp->list;
975 if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST))
977 fatal("do_service: expected word at %s:%d",
978 cpe->file, cpe->line);
981 if (strcmp(cpe->word, KW_CLASS) == 0)
983 do_class(cpe->next, config, rs_config);
984 continue;
986 if (strcmp(cpe->word, KW_UID) == 0)
988 do_uid(cpe->next, rs_start);
989 continue;
991 if (strcmp(cpe->word, KW_SIGMGR) == 0)
993 do_sigmgr(cpe->next, rs_start);
994 continue;
996 if (strcmp(cpe->word, KW_TYPE) == 0)
998 do_type(cpe->next, rs_config);
999 continue;
1001 if (strcmp(cpe->word, KW_DESCR) == 0)
1003 do_descr(cpe->next, rs_config);
1004 continue;
1006 if (strcmp(cpe->word, KW_SCHEDULER) == 0)
1008 do_scheduler(cpe->next, rs_start);
1009 continue;
1011 if (strcmp(cpe->word, KW_PRIORITY) == 0)
1013 do_priority(cpe->next, rs_start);
1014 continue;
1016 if (strcmp(cpe->word, KW_QUANTUM) == 0)
1018 do_quantum(cpe->next, rs_start);
1019 continue;
1021 if (strcmp(cpe->word, KW_CPU) == 0)
1023 do_cpu(cpe->next, rs_start);
1024 continue;
1026 if (strcmp(cpe->word, KW_IRQ) == 0)
1028 do_irq(cpe->next, rs_start);
1029 continue;
1031 if (strcmp(cpe->word, KW_IO) == 0)
1033 do_io(cpe->next, rs_start);
1034 continue;
1036 if (strcmp(cpe->word, KW_PCI) == 0)
1038 do_pci(cpe->next, rs_start);
1039 continue;
1041 if (strcmp(cpe->word, KW_SYSTEM) == 0)
1043 do_system(cpe->next, rs_start);
1044 continue;
1046 if (strcmp(cpe->word, KW_IPC) == 0)
1048 do_ipc(cpe->next, rs_start);
1049 continue;
1051 if (strcmp(cpe->word, KW_VM) == 0)
1053 do_vm(cpe->next, rs_start);
1054 continue;
1056 if (strcmp(cpe->word, KW_CONTROL) == 0)
1058 do_control(cpe->next, rs_start);
1059 continue;
1064 static const char *do_config(const char *label, char *filename, struct rs_config *rs_config)
1066 config_t *config, *cp, *cpe;
1067 struct passwd *pw;
1068 struct rs_start *rs_start = &rs_config->rs_start;
1070 if(!(config= config_read(filename, 0, NULL)))
1071 return NULL; /* config file read failed. */
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;
1085 /* Find an entry for our service */
1086 for (cp= config; cp; cp= cp->next)
1088 if (!(cp->flags & CFG_SUBLIST))
1090 fatal("do_config: expected list at %s:%d",
1091 cp->file, cp->line);
1093 cpe= cp->list;
1094 if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST))
1096 fatal("do_config: expected word at %s:%d",
1097 cpe->file, cpe->line);
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);
1105 cpe= cpe->next;
1106 if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST))
1108 fatal("do_config: expected word at %s:%d",
1109 cpe->file, cpe->line);
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;
1118 if (cp == NULL)
1120 fprintf(stderr, "service: service '%s' not found in '%s'\n",
1121 label, filename);
1122 exit(1);
1125 cpe= cpe->next;
1127 do_service(cpe, config, rs_config);
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);
1137 /* config file read ok. */
1138 return label;
1141 /* returns failure */
1142 const char *parse_config(char *progname, int custom_config, char *req_config,
1143 struct rs_config *rs_config)
1145 char *specificconfig, *specific_pkg_config;
1146 const char *l;
1148 /* Config file specified? */
1149 if(custom_config)
1150 return do_config(progname, req_config, rs_config);
1152 /* No specific config file. */
1153 if(asprintf(&specificconfig, "%s/%s", _PATH_SYSTEM_CONF_DIR,
1154 progname) < 0) {
1155 errx(1, "no memory");
1158 if(asprintf(&specific_pkg_config, "%s/%s", _PATH_SYSTEM_CONF_PKG_DIR,
1159 progname) < 0) {
1160 errx(1, "no memory");
1163 /* Try specific config filename first, in base system
1164 * and package locations, * and only if it fails, the global
1165 * system one.
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;
1171 return NULL;