Remove building with NOCRYPTO option
[minix3.git] / minix / commands / minix-service / parse.c
blobed49920cb197bb0fe55b64d0d216eabb0cb8d6b9
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 <sys/socket.h>
30 #include <configfile.h>
32 #include <machine/archtypes.h>
33 #include <minix/timers.h>
35 #include "config.h"
36 #include "proto.h"
38 static int class_recurs; /* Nesting level of class statements */
39 #define MAX_CLASS_RECURS 100 /* Max nesting level for classes */
41 #include "parse.h"
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)
47 config_t *cp, *cp1;
49 if (class_recurs > MAX_CLASS_RECURS)
51 fatal(
52 "do_class: nesting level too high for class '%s' at %s:%d",
53 cpe->word, cpe->file, cpe->line);
55 class_recurs++;
57 /* Process classes */
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",
77 cp->file, cp->line);
79 cp1= cp->list;
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);
92 cp1= cp1->next;
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)
102 break;
104 if (cp == NULL)
106 fatal(
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);
113 class_recurs--;
116 static void do_uid(config_t *cpe, struct rs_start *rs_start)
118 uid_t uid;
119 struct passwd *pw;
120 char *check;
122 /* Process a uid */
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);
140 if (pw != NULL)
141 uid= pw->pw_uid;
142 else
144 if (!strncmp(cpe->word, KW_SELF, strlen(KW_SELF)+1))
146 uid= getuid(); /* Real uid */
148 else {
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;
164 int r;
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")) {
186 sigmgr_ep = SELF;
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);
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);
218 if(rs_config->type)
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;
224 else
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);
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;
255 static void do_scheduler(config_t *cpe, struct rs_start *rs_start)
257 endpoint_t scheduler_ep;
258 int r;
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;
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);
289 rs_start->rss_scheduler= scheduler_ep;
292 static void do_priority(config_t *cpe, struct rs_start *rs_start)
294 int priority_val;
295 char *check;
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)
332 int quantum_val;
333 char *check;
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)
370 int cpu;
371 char *check;
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);
398 if (cpu < 0)
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)
408 int irq;
409 int first;
410 char *check;
412 /* Process a list of IRQs */
413 first = TRUE;
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",
431 KW_NONE);
433 break;
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);
442 rs_start->rss_nr_irq = RSS_IO_ALL;
443 break;
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++;
457 first = FALSE;
461 static void do_io(config_t *cpe, struct rs_start *rs_start)
463 unsigned base, len;
464 int first;
465 char *check;
467 /* Process a list of I/O ranges */
468 first = TRUE;
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",
486 KW_NONE);
488 break;
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);
497 rs_start->rss_nr_io = RSS_IO_ALL;
498 break;
501 /* Set single ranges as specified in the configuration. */
502 base= strtoul(cpe->word, &check, 0x10);
503 len= 1;
504 if (check[0] == ':')
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++;
519 first = FALSE;
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);
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);
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;
562 if (rs_start->rss_nr_pci_id >= RS_NR_PCI_DEVICE)
564 fatal("do_pci_device: too many device IDs (max %d)",
565 RS_NR_PCI_DEVICE);
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;
579 char *check;
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);
596 subclass= 0;
597 interface= 0;
598 mask= 0xff0000;
599 if (check[0] == '/')
601 subclass= strtoul(check+1, &check, 0x10);
602 mask= 0xffff00;
603 if (check[0] == '/')
605 interface= strtoul(check+1, &check, 0x10);
606 mask= 0xffffff;
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)",
619 RS_NR_PCI_CLASS);
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++;
628 static void do_pci(config_t *cpe, struct rs_start *rs_start)
630 if (cpe == NULL)
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);
647 return;
649 if (strcmp(cpe->word, KW_CLASS) == 0)
651 do_pci_class(cpe->next, rs_start);
652 return;
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)
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;
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';
674 /* Process a list of process names that are allowed to be
675 * contacted
677 first = TRUE;
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);
690 word = cpe->word;
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);
698 word = !strcmp(word, KW_ALL) ? word_all : word_all_sys;
701 wordlen= strlen(word);
703 listsize += 1 + wordlen;
704 list= realloc(list, listsize);
705 if (list == NULL)
707 fatal("do_ipc: unable to realloc %d bytes",
708 listsize);
710 strcat(list, " ");
711 strcat(list, word);
712 first = FALSE;
714 #if 0
715 printf("do_ipc: got list '%s'\n", list);
716 #endif
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);
725 struct
727 char *label;
728 int call_nr;
729 } vm_table[] =
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 },
760 static void do_vm(config_t *cpe, struct rs_start *rs_start)
762 int i, first;
764 first = TRUE;
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",
782 KW_NONE);
784 break;
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);
793 rs_start->rss_flags &= ~RSS_VM_BASIC_CALLS;
794 break;
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);
803 for (i = 0; i < NR_VM_CALLS; i++)
804 SET_BIT(rs_start->rss_vm, i);
805 break;
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);
820 first = FALSE;
824 struct
826 char *label;
827 int call_nr;
828 } system_tab[]=
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 }
852 static void do_system(config_t *cpe, struct rs_start *rs_start)
854 int i, first;
856 /* Process a list of 'system' calls that are allowed */
857 first = TRUE;
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",
875 KW_NONE);
877 break;
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);
886 rs_start->rss_flags &= ~RSS_SYS_BASIC_CALLS;
887 break;
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);
896 for (i = 0; i < NR_SYS_CALLS; i++)
897 SET_BIT(rs_start->rss_system, i);
898 break;
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);
912 first = FALSE;
916 static void do_control(config_t *cpe, struct rs_start *rs_start)
918 int nr_control = 0;
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)
935 fatal(
936 "do_control: RS_NR_CONTROL is too small (%d needed)",
937 nr_control+1);
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 {
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 },
987 * Process a list of 'domain' protocol families for socket drivers.
989 static void
990 do_domain(config_t * cpe, struct rs_start * rs_start)
992 unsigned int i;
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)",
1006 nr_domain + 1);
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);
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;
1030 config_t *cp;
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)
1042 cpe= cpe->next;
1043 fatal("do_service: expected end of list at %s:%d",
1044 cpe->file, cpe->line);
1046 cpe= cpe->list;
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);
1056 cpe= cp->list;
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);
1066 continue;
1068 if (strcmp(cpe->word, KW_UID) == 0)
1070 do_uid(cpe->next, rs_start);
1071 continue;
1073 if (strcmp(cpe->word, KW_SIGMGR) == 0)
1075 do_sigmgr(cpe->next, rs_start);
1076 continue;
1078 if (strcmp(cpe->word, KW_TYPE) == 0)
1080 do_type(cpe->next, rs_config);
1081 continue;
1083 if (strcmp(cpe->word, KW_DESCR) == 0)
1085 do_descr(cpe->next, rs_config);
1086 continue;
1088 if (strcmp(cpe->word, KW_SCHEDULER) == 0)
1090 do_scheduler(cpe->next, rs_start);
1091 continue;
1093 if (strcmp(cpe->word, KW_PRIORITY) == 0)
1095 do_priority(cpe->next, rs_start);
1096 continue;
1098 if (strcmp(cpe->word, KW_QUANTUM) == 0)
1100 do_quantum(cpe->next, rs_start);
1101 continue;
1103 if (strcmp(cpe->word, KW_CPU) == 0)
1105 do_cpu(cpe->next, rs_start);
1106 continue;
1108 if (strcmp(cpe->word, KW_IRQ) == 0)
1110 do_irq(cpe->next, rs_start);
1111 continue;
1113 if (strcmp(cpe->word, KW_IO) == 0)
1115 do_io(cpe->next, rs_start);
1116 continue;
1118 if (strcmp(cpe->word, KW_PCI) == 0)
1120 do_pci(cpe->next, rs_start);
1121 continue;
1123 if (strcmp(cpe->word, KW_SYSTEM) == 0)
1125 do_system(cpe->next, rs_start);
1126 continue;
1128 if (strcmp(cpe->word, KW_IPC) == 0)
1130 do_ipc(cpe->next, rs_start);
1131 continue;
1133 if (strcmp(cpe->word, KW_VM) == 0)
1135 do_vm(cpe->next, rs_start);
1136 continue;
1138 if (strcmp(cpe->word, KW_CONTROL) == 0)
1140 do_control(cpe->next, rs_start);
1141 continue;
1143 if (strcmp(cpe->word, KW_DOMAIN) == 0)
1145 do_domain(cpe->next, rs_start);
1146 continue;
1151 static const char *do_config(const char *label, char *filename, struct rs_config *rs_config)
1153 config_t *config, *cp, *cpe;
1154 struct passwd *pw;
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);
1180 cpe= cp->list;
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);
1192 cpe= cpe->next;
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) {
1201 label = cpe->word;
1202 break;
1205 if (cp == NULL)
1207 fprintf(stderr, "minix-service: service '%s' not found in "
1208 "'%s'\n", label, filename);
1209 exit(1);
1212 cpe= cpe->next;
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. */
1225 return label;
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;
1233 const char *l;
1235 /* Config file specified? */
1236 if(custom_config)
1237 return do_config(progname, req_config, rs_config);
1239 /* No specific config file. */
1240 if(asprintf(&specificconfig, "%s/%s", _PATH_SYSTEM_CONF_DIR,
1241 progname) < 0) {
1242 errx(1, "no memory");
1245 if(asprintf(&specific_pkg_config, "%s/%s", _PATH_SYSTEM_CONF_PKG_DIR,
1246 progname) < 0) {
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
1252 * system one.
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;
1258 return NULL;