2 #define _MINIX_SYSTEM 1
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>
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>
29 #include <sys/socket.h>
30 #include <configfile.h>
32 #include <machine/archtypes.h>
33 #include <minix/timers.h>
38 static int class_recurs
; /* Nesting level of class statements */
39 #define MAX_CLASS_RECURS 100 /* Max nesting level for classes */
43 static void do_service(config_t
*cpe
, config_t
*config
, struct rs_config
*);
45 static void do_class(config_t
*cpe
, config_t
*config
, struct rs_config
*rs_config
)
49 if (class_recurs
> MAX_CLASS_RECURS
)
52 "do_class: nesting level too high for class '%s' at %s:%d",
53 cpe
->word
, cpe
->file
, cpe
->line
);
58 for (; cpe
; cpe
= cpe
->next
)
60 if (cpe
->flags
& CFG_SUBLIST
)
62 fatal("do_class: unexpected sublist at %s:%d",
63 cpe
->file
, cpe
->line
);
65 if (cpe
->flags
& CFG_STRING
)
67 fatal("do_uid: unexpected string at %s:%d",
68 cpe
->file
, cpe
->line
);
71 /* Find entry for the class */
72 for (cp
= config
; cp
; cp
= cp
->next
)
74 if (!(cp
->flags
& CFG_SUBLIST
))
76 fatal("do_class: expected list at %s:%d",
80 if ((cp1
->flags
& CFG_STRING
) ||
81 (cp1
->flags
& CFG_SUBLIST
))
83 fatal("do_class: expected word at %s:%d",
84 cp1
->file
, cp1
->line
);
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
);
93 if ((cp1
->flags
& CFG_STRING
) ||
94 (cp1
->flags
& CFG_SUBLIST
))
96 fatal("do_class: expected word at %s:%d",
97 cp1
->file
, cp1
->line
);
100 /* At this place we expect the name of the service */
101 if (strcmp(cp1
->word
, cpe
->word
) == 0)
107 "do_class: no entry found for class '%s' at %s:%d",
108 cpe
->word
, cpe
->file
, cpe
->line
);
110 do_service(cp1
->next
, config
, rs_config
);
116 static void do_uid(config_t
*cpe
, struct rs_start
*rs_start
)
123 if (cpe
->next
!= NULL
)
125 fatal("do_uid: just one uid/login expected at %s:%d",
126 cpe
->file
, cpe
->line
);
129 if (cpe
->flags
& CFG_SUBLIST
)
131 fatal("do_uid: unexpected sublist at %s:%d",
132 cpe
->file
, cpe
->line
);
134 if (cpe
->flags
& CFG_STRING
)
136 fatal("do_uid: unexpected string at %s:%d",
137 cpe
->file
, cpe
->line
);
139 pw
= getpwnam(cpe
->word
);
144 if (!strncmp(cpe
->word
, KW_SELF
, strlen(KW_SELF
)+1))
146 uid
= getuid(); /* Real uid */
149 uid
= strtol(cpe
->word
, &check
, 0);
150 if (check
[0] != '\0')
152 fatal("do_uid: bad uid/login '%s' at %s:%d",
153 cpe
->word
, cpe
->file
, cpe
->line
);
158 rs_start
->rss_uid
= uid
;
161 static void do_sigmgr(config_t
*cpe
, struct rs_start
*rs_start
)
163 endpoint_t sigmgr_ep
;
166 /* Process a signal manager value */
167 if (cpe
->next
!= NULL
)
169 fatal("do_sigmgr: just one sigmgr value expected at %s:%d",
170 cpe
->file
, cpe
->line
);
174 if (cpe
->flags
& CFG_SUBLIST
)
176 fatal("do_sigmgr: unexpected sublist at %s:%d",
177 cpe
->file
, cpe
->line
);
179 if (cpe
->flags
& CFG_STRING
)
181 fatal("do_sigmgr: unexpected string at %s:%d",
182 cpe
->file
, cpe
->line
);
185 if(!strcmp(cpe
->word
, "SELF")) {
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
);
195 rs_start
->rss_sigmgr
= sigmgr_ep
;
198 static void do_type(config_t
*cpe
, struct rs_config
*rs_config
)
200 if (cpe
->next
!= NULL
)
202 fatal("do_type: just one type value expected at %s:%d",
203 cpe
->file
, cpe
->line
);
207 if (cpe
->flags
& CFG_SUBLIST
)
209 fatal("do_type: unexpected sublist at %s:%d",
210 cpe
->file
, cpe
->line
);
212 if ((cpe
->flags
& CFG_STRING
))
214 fatal("do_type: unexpected string at %s:%d",
215 cpe
->file
, cpe
->line
);
219 fatal("do_type: another type at %s:%d",
220 cpe
->file
, cpe
->line
);
222 if(!strcmp(cpe
->word
, KW_NET
))
223 rs_config
->type
= KW_NET
;
225 fatal("do_type: odd type at %s:%d",
226 cpe
->file
, cpe
->line
);
229 static void do_descr(config_t
*cpe
, struct rs_config
*rs_config
)
231 if (cpe
->next
!= NULL
)
233 fatal("do_descr: just one description expected at %s:%d",
234 cpe
->file
, cpe
->line
);
238 if (cpe
->flags
& CFG_SUBLIST
)
240 fatal("do_descr: unexpected sublist at %s:%d",
241 cpe
->file
, cpe
->line
);
243 if (!(cpe
->flags
& CFG_STRING
))
245 fatal("do_descr: expected string at %s:%d",
246 cpe
->file
, cpe
->line
);
250 fatal("do_descr: another descr at %s:%d",
251 cpe
->file
, cpe
->line
);
252 rs_config
->descr
= cpe
->word
;
255 static void do_scheduler(config_t
*cpe
, struct rs_start
*rs_start
)
257 endpoint_t scheduler_ep
;
260 /* Process a scheduler value */
261 if (cpe
->next
!= NULL
)
263 fatal("do_scheduler: just one scheduler value expected at %s:%d",
264 cpe
->file
, cpe
->line
);
268 if (cpe
->flags
& CFG_SUBLIST
)
270 fatal("do_scheduler: unexpected sublist at %s:%d",
271 cpe
->file
, cpe
->line
);
273 if (cpe
->flags
& CFG_STRING
)
275 fatal("do_scheduler: unexpected string at %s:%d",
276 cpe
->file
, cpe
->line
);
279 if(!strcmp(cpe
->word
, "KERNEL")) {
280 scheduler_ep
= KERNEL
;
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
);
289 rs_start
->rss_scheduler
= scheduler_ep
;
292 static void do_priority(config_t
*cpe
, struct rs_start
*rs_start
)
297 /* Process a priority value */
298 if (cpe
->next
!= NULL
)
300 fatal("do_priority: just one priority value expected at %s:%d",
301 cpe
->file
, cpe
->line
);
305 if (cpe
->flags
& CFG_SUBLIST
)
307 fatal("do_priority: unexpected sublist at %s:%d",
308 cpe
->file
, cpe
->line
);
310 if (cpe
->flags
& CFG_STRING
)
312 fatal("do_priority: unexpected string at %s:%d",
313 cpe
->file
, cpe
->line
);
315 priority_val
= strtol(cpe
->word
, &check
, 0);
316 if (check
[0] != '\0')
318 fatal("do_priority: bad priority value '%s' at %s:%d",
319 cpe
->word
, cpe
->file
, cpe
->line
);
322 if (priority_val
< 0 || priority_val
>= NR_SCHED_QUEUES
)
324 fatal("do_priority: priority %d out of range at %s:%d",
325 priority_val
, cpe
->file
, cpe
->line
);
327 rs_start
->rss_priority
= priority_val
;
330 static void do_quantum(config_t
*cpe
, struct rs_start
*rs_start
)
335 /* Process a quantum value */
336 if (cpe
->next
!= NULL
)
338 fatal("do_quantum: just one quantum value expected at %s:%d",
339 cpe
->file
, cpe
->line
);
343 if (cpe
->flags
& CFG_SUBLIST
)
345 fatal("do_quantum: unexpected sublist at %s:%d",
346 cpe
->file
, cpe
->line
);
348 if (cpe
->flags
& CFG_STRING
)
350 fatal("do_quantum: unexpected string at %s:%d",
351 cpe
->file
, cpe
->line
);
353 quantum_val
= strtol(cpe
->word
, &check
, 0);
354 if (check
[0] != '\0')
356 fatal("do_quantum: bad quantum value '%s' at %s:%d",
357 cpe
->word
, cpe
->file
, cpe
->line
);
360 if (quantum_val
<= 0)
362 fatal("do_quantum: quantum %d out of range at %s:%d",
363 quantum_val
, cpe
->file
, cpe
->line
);
365 rs_start
->rss_quantum
= quantum_val
;
368 static void do_cpu(config_t
*cpe
, struct rs_start
*rs_start
)
373 /* Process a quantum value */
374 if (cpe
->next
!= NULL
)
376 fatal("do_cpu: just one value expected at %s:%d",
377 cpe
->file
, cpe
->line
);
381 if (cpe
->flags
& CFG_SUBLIST
)
383 fatal("do_cpu: unexpected sublist at %s:%d",
384 cpe
->file
, cpe
->line
);
386 if (cpe
->flags
& CFG_STRING
)
388 fatal("do_cpu: unexpected string at %s:%d",
389 cpe
->file
, cpe
->line
);
391 cpu
= strtol(cpe
->word
, &check
, 0);
392 if (check
[0] != '\0')
394 fatal("do_cpu: bad value '%s' at %s:%d",
395 cpe
->word
, cpe
->file
, cpe
->line
);
400 fatal("do_cpu: %d out of range at %s:%d",
401 cpu
, cpe
->file
, cpe
->line
);
403 rs_start
->rss_cpu
= cpu
;
406 static void do_irq(config_t
*cpe
, struct rs_start
*rs_start
)
412 /* Process a list of IRQs */
414 for (; cpe
; cpe
= cpe
->next
)
416 if (cpe
->flags
& CFG_SUBLIST
)
418 fatal("do_irq: unexpected sublist at %s:%d",
419 cpe
->file
, cpe
->line
);
421 if (cpe
->flags
& CFG_STRING
)
423 fatal("do_irq: unexpected string at %s:%d",
424 cpe
->file
, cpe
->line
);
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",
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",
442 rs_start
->rss_nr_irq
= RSS_IO_ALL
;
446 /* Set single IRQs as specified in the configuration. */
447 irq
= strtoul(cpe
->word
, &check
, 0);
448 if (check
[0] != '\0')
450 fatal("do_irq: bad irq '%s' at %s:%d",
451 cpe
->word
, cpe
->file
, cpe
->line
);
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
++;
461 static void do_io(config_t
*cpe
, struct rs_start
*rs_start
)
467 /* Process a list of I/O ranges */
469 for (; cpe
; cpe
= cpe
->next
)
471 if (cpe
->flags
& CFG_SUBLIST
)
473 fatal("do_io: unexpected sublist at %s:%d",
474 cpe
->file
, cpe
->line
);
476 if (cpe
->flags
& CFG_STRING
)
478 fatal("do_io: unexpected string at %s:%d",
479 cpe
->file
, cpe
->line
);
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",
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",
497 rs_start
->rss_nr_io
= RSS_IO_ALL
;
501 /* Set single ranges as specified in the configuration. */
502 base
= strtoul(cpe
->word
, &check
, 0x10);
506 len
= strtoul(check
+1, &check
, 0x10);
508 if (check
[0] != '\0')
510 fatal("do_io: bad I/O range '%s' at %s:%d",
511 cpe
->word
, cpe
->file
, cpe
->line
);
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
++;
523 static void do_pci_device(config_t
*cpe
, struct rs_start
*rs_start
)
525 u16_t vid
, did
, sub_vid
, sub_did
;
526 char *check
, *check2
;
528 /* Process a list of PCI device IDs */
529 for (; cpe
; cpe
= cpe
->next
)
531 if (cpe
->flags
& CFG_SUBLIST
)
533 fatal("do_pci_device: unexpected sublist at %s:%d",
534 cpe
->file
, cpe
->line
);
536 if (cpe
->flags
& CFG_STRING
)
538 fatal("do_pci_device: unexpected string at %s:%d",
539 cpe
->file
, cpe
->line
);
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
);
546 did
= strtoul(check
+1, &check
, 0x10);
547 if (check
[0] == '/') {
548 sub_vid
= strtoul(check
+1, &check
, 0x10);
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
);
555 } else if (check
[0] != '\0') {
556 fatal("do_pci_device: bad ID '%s' at %s:%d",
557 cpe
->word
, cpe
->file
, cpe
->line
);
559 sub_vid
= NO_SUB_VID
;
560 sub_did
= NO_SUB_DID
;
562 if (rs_start
->rss_nr_pci_id
>= RS_NR_PCI_DEVICE
)
564 fatal("do_pci_device: too many device IDs (max %d)",
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
++;
575 static void do_pci_class(config_t
*cpe
, struct rs_start
*rs_start
)
577 u8_t baseclass
, subclass
, interface
;
578 u32_t class_id
, mask
;
581 /* Process a list of PCI device class IDs */
582 for (; cpe
; cpe
= cpe
->next
)
584 if (cpe
->flags
& CFG_SUBLIST
)
586 fatal("do_pci_device: unexpected sublist at %s:%d",
587 cpe
->file
, cpe
->line
);
589 if (cpe
->flags
& CFG_STRING
)
591 fatal("do_pci_device: unexpected string at %s:%d",
592 cpe
->file
, cpe
->line
);
595 baseclass
= strtoul(cpe
->word
, &check
, 0x10);
601 subclass
= strtoul(check
+1, &check
, 0x10);
605 interface
= strtoul(check
+1, &check
, 0x10);
610 if (check
[0] != '\0')
612 fatal("do_pci_class: bad class ID '%s' at %s:%d",
613 cpe
->word
, cpe
->file
, cpe
->line
);
615 class_id
= (baseclass
<< 16) | (subclass
<< 8) | interface
;
616 if (rs_start
->rss_nr_pci_class
>= RS_NR_PCI_CLASS
)
618 fatal("do_pci_class: too many class IDs (max %d)",
621 rs_start
->rss_pci_class
[rs_start
->rss_nr_pci_class
].pciclass
=
623 rs_start
->rss_pci_class
[rs_start
->rss_nr_pci_class
].mask
= mask
;
624 rs_start
->rss_nr_pci_class
++;
628 static void do_pci(config_t
*cpe
, struct rs_start
*rs_start
)
631 return; /* Empty PCI statement */
633 if (cpe
->flags
& CFG_SUBLIST
)
635 fatal("do_pci: unexpected sublist at %s:%d",
636 cpe
->file
, cpe
->line
);
638 if (cpe
->flags
& CFG_STRING
)
640 fatal("do_pci: unexpected string at %s:%d",
641 cpe
->file
, cpe
->line
);
644 if (strcmp(cpe
->word
, KW_DEVICE
) == 0)
646 do_pci_device(cpe
->next
, rs_start
);
649 if (strcmp(cpe
->word
, KW_CLASS
) == 0)
651 do_pci_class(cpe
->next
, rs_start
);
654 fatal("do_pci: unexpected word '%s' at %s:%d",
655 cpe
->word
, cpe
->file
, cpe
->line
);
658 static void do_ipc(config_t
*cpe
, struct rs_start
*rs_start
)
662 char *word_all
= RSS_IPC_ALL
;
663 char *word_all_sys
= RSS_IPC_ALL_SYS
;
664 size_t listsize
, wordlen
;
669 list
= malloc(listsize
);
671 fatal("do_ipc: unable to malloc %d bytes", listsize
);
674 /* Process a list of process names that are allowed to be
678 for (; cpe
; cpe
= cpe
->next
)
680 if (cpe
->flags
& CFG_SUBLIST
)
682 fatal("do_ipc: unexpected sublist at %s:%d",
683 cpe
->file
, cpe
->line
);
685 if (cpe
->flags
& CFG_STRING
)
687 fatal("do_ipc: unexpected string at %s:%d",
688 cpe
->file
, cpe
->line
);
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",
698 word
= !strcmp(word
, KW_ALL
) ? word_all
: word_all_sys
;
701 wordlen
= strlen(word
);
703 listsize
+= 1 + wordlen
;
704 list
= realloc(list
, listsize
);
707 fatal("do_ipc: unable to realloc %d bytes",
715 printf("do_ipc: got list '%s'\n", list
);
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
);
733 { "EXEC_NEWMEM", VM_EXEC_NEWMEM
},
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
},
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
},
760 static void do_vm(config_t
*cpe
, struct rs_start
*rs_start
)
765 for (; cpe
; cpe
= cpe
->next
)
767 if (cpe
->flags
& CFG_SUBLIST
)
769 fatal("do_vm: unexpected sublist at %s:%d",
770 cpe
->file
, cpe
->line
);
772 if (cpe
->flags
& CFG_STRING
)
774 fatal("do_vm: unexpected string at %s:%d",
775 cpe
->file
, cpe
->line
);
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",
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",
793 rs_start
->rss_flags
&= ~RSS_VM_BASIC_CALLS
;
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",
803 for (i
= 0; i
< NR_VM_CALLS
; i
++)
804 SET_BIT(rs_start
->rss_vm
, i
);
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
))
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
);
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
},
852 static void do_system(config_t
*cpe
, struct rs_start
*rs_start
)
856 /* Process a list of 'system' calls that are allowed */
858 for (; cpe
; cpe
= cpe
->next
)
860 if (cpe
->flags
& CFG_SUBLIST
)
862 fatal("do_system: unexpected sublist at %s:%d",
863 cpe
->file
, cpe
->line
);
865 if (cpe
->flags
& CFG_STRING
)
867 fatal("do_system: unexpected string at %s:%d",
868 cpe
->file
, cpe
->line
);
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",
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",
886 rs_start
->rss_flags
&= ~RSS_SYS_BASIC_CALLS
;
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",
896 for (i
= 0; i
< NR_SYS_CALLS
; i
++)
897 SET_BIT(rs_start
->rss_system
, i
);
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
))
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
);
909 SET_BIT(rs_start
->rss_system
,
910 system_tab
[i
].call_nr
- KERNEL_CALL
);
916 static void do_control(config_t
*cpe
, struct rs_start
*rs_start
)
920 /* Process a list of 'control' labels. */
921 for (; cpe
; cpe
= cpe
->next
)
923 if (cpe
->flags
& CFG_SUBLIST
)
925 fatal("do_control: unexpected sublist at %s:%d",
926 cpe
->file
, cpe
->line
);
928 if (cpe
->flags
& CFG_STRING
)
930 fatal("do_control: unexpected string at %s:%d",
931 cpe
->file
, cpe
->line
);
933 if (nr_control
>= RS_NR_CONTROL
)
936 "do_control: RS_NR_CONTROL is too small (%d needed)",
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
;
946 static const struct {
950 /* PF_UNSPEC should not be in this table. */
951 { "LOCAL", PF_LOCAL
},
953 { "IMPLINK", PF_IMPLINK
},
955 { "CHAOS", PF_CHAOS
},
959 { "DATAKIT", PF_DATAKIT
},
960 { "CCITT", PF_CCITT
},
962 { "DECnet", PF_DECnet
},
965 { "HYLINK", PF_HYLINK
},
966 { "APPLETALK", PF_APPLETALK
},
967 { "OROUTE", PF_OROUTE
},
974 { "INET6", PF_INET6
},
980 { "BLUETOOTH", PF_BLUETOOTH
},
981 /* There is no PF_IEEE80211. */
983 { "ROUTE", PF_ROUTE
},
987 * Process a list of 'domain' protocol families for socket drivers.
990 do_domain(config_t
* cpe
, struct rs_start
* rs_start
)
993 int nr_domain
, domain
;
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
);
1000 if (cpe
->flags
& CFG_STRING
) {
1001 fatal("do_domain: unexpected string at %s:%d",
1002 cpe
->file
, cpe
->line
);
1004 if (nr_domain
>= __arraycount(rs_start
->rss_domain
)) {
1005 fatal("do_domain: NR_DOMAIN is too small (%d needed)",
1009 for (i
= 0; i
< __arraycount(domain_tab
); i
++)
1010 if (!strcmp(domain_tab
[i
].name
, (char *)cpe
->word
))
1012 if (i
< __arraycount(domain_tab
))
1013 domain
= domain_tab
[i
].domain
;
1015 domain
= atoi((char *)cpe
->word
);
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
);
1022 rs_start
->rss_domain
[nr_domain
] = domain
;
1023 rs_start
->rss_nr_domain
= ++nr_domain
;
1027 static void do_service(config_t
*cpe
, config_t
*config
, struct rs_config
*rs_config
)
1029 struct rs_start
*rs_start
= &rs_config
->rs_start
;
1032 /* At this point we expect one sublist that contains the varios
1033 * resource allocations
1035 if (!(cpe
->flags
& CFG_SUBLIST
))
1037 fatal("do_service: expected list at %s:%d",
1038 cpe
->file
, cpe
->line
);
1040 if (cpe
->next
!= NULL
)
1043 fatal("do_service: expected end of list at %s:%d",
1044 cpe
->file
, cpe
->line
);
1048 /* Process the list */
1049 for (cp
= cpe
; cp
; cp
= cp
->next
)
1051 if (!(cp
->flags
& CFG_SUBLIST
))
1053 fatal("do_service: expected list at %s:%d",
1054 cp
->file
, cp
->line
);
1057 if ((cpe
->flags
& CFG_STRING
) || (cpe
->flags
& CFG_SUBLIST
))
1059 fatal("do_service: expected word at %s:%d",
1060 cpe
->file
, cpe
->line
);
1063 if (strcmp(cpe
->word
, KW_CLASS
) == 0)
1065 do_class(cpe
->next
, config
, rs_config
);
1068 if (strcmp(cpe
->word
, KW_UID
) == 0)
1070 do_uid(cpe
->next
, rs_start
);
1073 if (strcmp(cpe
->word
, KW_SIGMGR
) == 0)
1075 do_sigmgr(cpe
->next
, rs_start
);
1078 if (strcmp(cpe
->word
, KW_TYPE
) == 0)
1080 do_type(cpe
->next
, rs_config
);
1083 if (strcmp(cpe
->word
, KW_DESCR
) == 0)
1085 do_descr(cpe
->next
, rs_config
);
1088 if (strcmp(cpe
->word
, KW_SCHEDULER
) == 0)
1090 do_scheduler(cpe
->next
, rs_start
);
1093 if (strcmp(cpe
->word
, KW_PRIORITY
) == 0)
1095 do_priority(cpe
->next
, rs_start
);
1098 if (strcmp(cpe
->word
, KW_QUANTUM
) == 0)
1100 do_quantum(cpe
->next
, rs_start
);
1103 if (strcmp(cpe
->word
, KW_CPU
) == 0)
1105 do_cpu(cpe
->next
, rs_start
);
1108 if (strcmp(cpe
->word
, KW_IRQ
) == 0)
1110 do_irq(cpe
->next
, rs_start
);
1113 if (strcmp(cpe
->word
, KW_IO
) == 0)
1115 do_io(cpe
->next
, rs_start
);
1118 if (strcmp(cpe
->word
, KW_PCI
) == 0)
1120 do_pci(cpe
->next
, rs_start
);
1123 if (strcmp(cpe
->word
, KW_SYSTEM
) == 0)
1125 do_system(cpe
->next
, rs_start
);
1128 if (strcmp(cpe
->word
, KW_IPC
) == 0)
1130 do_ipc(cpe
->next
, rs_start
);
1133 if (strcmp(cpe
->word
, KW_VM
) == 0)
1135 do_vm(cpe
->next
, rs_start
);
1138 if (strcmp(cpe
->word
, KW_CONTROL
) == 0)
1140 do_control(cpe
->next
, rs_start
);
1143 if (strcmp(cpe
->word
, KW_DOMAIN
) == 0)
1145 do_domain(cpe
->next
, rs_start
);
1151 static const char *do_config(const char *label
, char *filename
, struct rs_config
*rs_config
)
1153 config_t
*config
, *cp
, *cpe
;
1155 struct rs_start
*rs_start
= &rs_config
->rs_start
;
1157 if(!(config
= config_read(filename
, 0, NULL
)))
1158 return NULL
; /* config file read failed. */
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
;
1172 /* Find an entry for our service */
1173 for (cp
= config
; cp
; cp
= cp
->next
)
1175 if (!(cp
->flags
& CFG_SUBLIST
))
1177 fatal("do_config: expected list at %s:%d",
1178 cp
->file
, cp
->line
);
1181 if ((cpe
->flags
& CFG_STRING
) || (cpe
->flags
& CFG_SUBLIST
))
1183 fatal("do_config: expected word at %s:%d",
1184 cpe
->file
, cpe
->line
);
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
);
1193 if ((cpe
->flags
& CFG_STRING
) || (cpe
->flags
& CFG_SUBLIST
))
1195 fatal("do_config: expected word at %s:%d",
1196 cpe
->file
, cpe
->line
);
1199 /* At this place we expect the name of the service. */
1200 if (!label
|| strcmp(cpe
->word
, label
) == 0) {
1207 fprintf(stderr
, "minix-service: service '%s' not found in "
1208 "'%s'\n", label
, filename
);
1214 do_service(cpe
, config
, rs_config
);
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
);
1224 /* config file read ok. */
1228 /* returns failure */
1229 const char *parse_config(char *progname
, int custom_config
, char *req_config
,
1230 struct rs_config
*rs_config
)
1232 char *specificconfig
, *specific_pkg_config
;
1235 /* Config file specified? */
1237 return do_config(progname
, req_config
, rs_config
);
1239 /* No specific config file. */
1240 if(asprintf(&specificconfig
, "%s/%s", _PATH_SYSTEM_CONF_DIR
,
1242 errx(1, "no memory");
1245 if(asprintf(&specific_pkg_config
, "%s/%s", _PATH_SYSTEM_CONF_PKG_DIR
,
1247 errx(1, "no memory");
1250 /* Try specific config filename first, in base system
1251 * and package locations, * and only if it fails, the global
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
;