#define _MINIX_SYSTEM 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "proto.h" static int class_recurs; /* Nesting level of class statements */ #define MAX_CLASS_RECURS 100 /* Max nesting level for classes */ #include "parse.h" static void do_service(config_t *cpe, config_t *config, struct rs_config *); static void do_class(config_t *cpe, config_t *config, struct rs_config *rs_config) { config_t *cp, *cp1; if (class_recurs > MAX_CLASS_RECURS) { fatal( "do_class: nesting level too high for class '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } class_recurs++; /* Process classes */ for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_class: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_uid: unexpected string at %s:%d", cpe->file, cpe->line); } /* Find entry for the class */ for (cp= config; cp; cp= cp->next) { if (!(cp->flags & CFG_SUBLIST)) { fatal("do_class: expected list at %s:%d", cp->file, cp->line); } cp1= cp->list; if ((cp1->flags & CFG_STRING) || (cp1->flags & CFG_SUBLIST)) { fatal("do_class: expected word at %s:%d", cp1->file, cp1->line); } /* At this place we expect the word KW_SERVICE */ if (strcmp(cp1->word, KW_SERVICE) != 0) fatal("do_class: exected word '%S' at %s:%d", KW_SERVICE, cp1->file, cp1->line); cp1= cp1->next; if ((cp1->flags & CFG_STRING) || (cp1->flags & CFG_SUBLIST)) { fatal("do_class: expected word at %s:%d", cp1->file, cp1->line); } /* At this place we expect the name of the service */ if (strcmp(cp1->word, cpe->word) == 0) break; } if (cp == NULL) { fatal( "do_class: no entry found for class '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } do_service(cp1->next, config, rs_config); } class_recurs--; } static void do_uid(config_t *cpe, struct rs_start *rs_start) { uid_t uid; struct passwd *pw; char *check; /* Process a uid */ if (cpe->next != NULL) { fatal("do_uid: just one uid/login expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_uid: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_uid: unexpected string at %s:%d", cpe->file, cpe->line); } pw= getpwnam(cpe->word); if (pw != NULL) uid= pw->pw_uid; else { if (!strncmp(cpe->word, KW_SELF, strlen(KW_SELF)+1)) { uid= getuid(); /* Real uid */ } else { uid= strtol(cpe->word, &check, 0); if (check[0] != '\0') { fatal("do_uid: bad uid/login '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } } } rs_start->rss_uid= uid; } static void do_sigmgr(config_t *cpe, struct rs_start *rs_start) { endpoint_t sigmgr_ep; int r; /* Process a signal manager value */ if (cpe->next != NULL) { fatal("do_sigmgr: just one sigmgr value expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_sigmgr: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_sigmgr: unexpected string at %s:%d", cpe->file, cpe->line); } if(!strcmp(cpe->word, "SELF")) { sigmgr_ep = SELF; } else { if((r = minix_rs_lookup(cpe->word, &sigmgr_ep))) { fatal("do_sigmgr: unknown sigmgr %s at %s:%d", cpe->word, cpe->file, cpe->line); } } rs_start->rss_sigmgr= sigmgr_ep; } static void do_type(config_t *cpe, struct rs_config *rs_config) { if (cpe->next != NULL) { fatal("do_type: just one type value expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_type: unexpected sublist at %s:%d", cpe->file, cpe->line); } if ((cpe->flags & CFG_STRING)) { fatal("do_type: unexpected string at %s:%d", cpe->file, cpe->line); } if(rs_config->type) fatal("do_type: another type at %s:%d", cpe->file, cpe->line); if(!strcmp(cpe->word, KW_NET)) rs_config->type = KW_NET; else fatal("do_type: odd type at %s:%d", cpe->file, cpe->line); } static void do_descr(config_t *cpe, struct rs_config *rs_config) { if (cpe->next != NULL) { fatal("do_descr: just one description expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_descr: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (!(cpe->flags & CFG_STRING)) { fatal("do_descr: expected string at %s:%d", cpe->file, cpe->line); } if(rs_config->descr) fatal("do_descr: another descr at %s:%d", cpe->file, cpe->line); rs_config->descr = cpe->word; } static void do_scheduler(config_t *cpe, struct rs_start *rs_start) { endpoint_t scheduler_ep; int r; /* Process a scheduler value */ if (cpe->next != NULL) { fatal("do_scheduler: just one scheduler value expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_scheduler: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_scheduler: unexpected string at %s:%d", cpe->file, cpe->line); } if(!strcmp(cpe->word, "KERNEL")) { scheduler_ep = KERNEL; } else { if((r = minix_rs_lookup(cpe->word, &scheduler_ep))) { fatal("do_scheduler: unknown scheduler %s at %s:%d", cpe->word, cpe->file, cpe->line); } } rs_start->rss_scheduler= scheduler_ep; } static void do_priority(config_t *cpe, struct rs_start *rs_start) { int priority_val; char *check; /* Process a priority value */ if (cpe->next != NULL) { fatal("do_priority: just one priority value expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_priority: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_priority: unexpected string at %s:%d", cpe->file, cpe->line); } priority_val= strtol(cpe->word, &check, 0); if (check[0] != '\0') { fatal("do_priority: bad priority value '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } if (priority_val < 0 || priority_val >= NR_SCHED_QUEUES) { fatal("do_priority: priority %d out of range at %s:%d", priority_val, cpe->file, cpe->line); } rs_start->rss_priority= priority_val; } static void do_quantum(config_t *cpe, struct rs_start *rs_start) { int quantum_val; char *check; /* Process a quantum value */ if (cpe->next != NULL) { fatal("do_quantum: just one quantum value expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_quantum: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_quantum: unexpected string at %s:%d", cpe->file, cpe->line); } quantum_val= strtol(cpe->word, &check, 0); if (check[0] != '\0') { fatal("do_quantum: bad quantum value '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } if (quantum_val <= 0) { fatal("do_quantum: quantum %d out of range at %s:%d", quantum_val, cpe->file, cpe->line); } rs_start->rss_quantum= quantum_val; } static void do_cpu(config_t *cpe, struct rs_start *rs_start) { int cpu; char *check; /* Process a quantum value */ if (cpe->next != NULL) { fatal("do_cpu: just one value expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { fatal("do_cpu: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_cpu: unexpected string at %s:%d", cpe->file, cpe->line); } cpu= strtol(cpe->word, &check, 0); if (check[0] != '\0') { fatal("do_cpu: bad value '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } if (cpu < 0) { fatal("do_cpu: %d out of range at %s:%d", cpu, cpe->file, cpe->line); } rs_start->rss_cpu= cpu; } static void do_irq(config_t *cpe, struct rs_start *rs_start) { int irq; int first; char *check; /* Process a list of IRQs */ first = TRUE; for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_irq: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_irq: unexpected string at %s:%d", cpe->file, cpe->line); } /* No IRQ allowed? (default) */ if(!strcmp(cpe->word, KW_NONE)) { if(!first || cpe->next) { fatal("do_irq: %s keyword not allowed in list", KW_NONE); } break; } /* All IRQs are allowed? */ if(!strcmp(cpe->word, KW_ALL)) { if(!first || cpe->next) { fatal("do_irq: %s keyword not allowed in list", KW_ALL); } rs_start->rss_nr_irq = RSS_IO_ALL; break; } /* Set single IRQs as specified in the configuration. */ irq= strtoul(cpe->word, &check, 0); if (check[0] != '\0') { fatal("do_irq: bad irq '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } if (rs_start->rss_nr_irq >= RSS_NR_IRQ) fatal("do_irq: too many IRQs (max %d)", RSS_NR_IRQ); rs_start->rss_irq[rs_start->rss_nr_irq]= irq; rs_start->rss_nr_irq++; first = FALSE; } } static void do_io(config_t *cpe, struct rs_start *rs_start) { unsigned base, len; int first; char *check; /* Process a list of I/O ranges */ first = TRUE; for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_io: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_io: unexpected string at %s:%d", cpe->file, cpe->line); } /* No range allowed? (default) */ if(!strcmp(cpe->word, KW_NONE)) { if(!first || cpe->next) { fatal("do_io: %s keyword not allowed in list", KW_NONE); } break; } /* All ranges are allowed? */ if(!strcmp(cpe->word, KW_ALL)) { if(!first || cpe->next) { fatal("do_io: %s keyword not allowed in list", KW_ALL); } rs_start->rss_nr_io = RSS_IO_ALL; break; } /* Set single ranges as specified in the configuration. */ base= strtoul(cpe->word, &check, 0x10); len= 1; if (check[0] == ':') { len= strtoul(check+1, &check, 0x10); } if (check[0] != '\0') { fatal("do_io: bad I/O range '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } if (rs_start->rss_nr_io >= RSS_NR_IO) fatal("do_io: too many I/O ranges (max %d)", RSS_NR_IO); rs_start->rss_io[rs_start->rss_nr_io].base= base; rs_start->rss_io[rs_start->rss_nr_io].len= len; rs_start->rss_nr_io++; first = FALSE; } } static void do_pci_device(config_t *cpe, struct rs_start *rs_start) { u16_t vid, did, sub_vid, sub_did; char *check, *check2; /* Process a list of PCI device IDs */ for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_pci_device: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_pci_device: unexpected string at %s:%d", cpe->file, cpe->line); } vid= strtoul(cpe->word, &check, 0x10); if (check[0] != ':' && /* LEGACY: */ check[0] != '/') { fatal("do_pci_device: bad ID '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } did= strtoul(check+1, &check, 0x10); if (check[0] == '/') { sub_vid= strtoul(check+1, &check, 0x10); if (check[0] == ':') sub_did= strtoul(check+1, &check2, 0x10); if (check[0] != ':' || check2[0] != '\0') { fatal("do_pci_device: bad ID '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } } else if (check[0] != '\0') { fatal("do_pci_device: bad ID '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } else { sub_vid = NO_SUB_VID; sub_did = NO_SUB_DID; } if (rs_start->rss_nr_pci_id >= RS_NR_PCI_DEVICE) { fatal("do_pci_device: too many device IDs (max %d)", RS_NR_PCI_DEVICE); } rs_start->rss_pci_id[rs_start->rss_nr_pci_id].vid= vid; rs_start->rss_pci_id[rs_start->rss_nr_pci_id].did= did; rs_start->rss_pci_id[rs_start->rss_nr_pci_id].sub_vid= sub_vid; rs_start->rss_pci_id[rs_start->rss_nr_pci_id].sub_did= sub_did; rs_start->rss_nr_pci_id++; } } static void do_pci_class(config_t *cpe, struct rs_start *rs_start) { u8_t baseclass, subclass, interface; u32_t class_id, mask; char *check; /* Process a list of PCI device class IDs */ for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_pci_device: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_pci_device: unexpected string at %s:%d", cpe->file, cpe->line); } baseclass= strtoul(cpe->word, &check, 0x10); subclass= 0; interface= 0; mask= 0xff0000; if (check[0] == '/') { subclass= strtoul(check+1, &check, 0x10); mask= 0xffff00; if (check[0] == '/') { interface= strtoul(check+1, &check, 0x10); mask= 0xffffff; } } if (check[0] != '\0') { fatal("do_pci_class: bad class ID '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } class_id= (baseclass << 16) | (subclass << 8) | interface; if (rs_start->rss_nr_pci_class >= RS_NR_PCI_CLASS) { fatal("do_pci_class: too many class IDs (max %d)", RS_NR_PCI_CLASS); } rs_start->rss_pci_class[rs_start->rss_nr_pci_class].pciclass= class_id; rs_start->rss_pci_class[rs_start->rss_nr_pci_class].mask= mask; rs_start->rss_nr_pci_class++; } } static void do_pci(config_t *cpe, struct rs_start *rs_start) { if (cpe == NULL) return; /* Empty PCI statement */ if (cpe->flags & CFG_SUBLIST) { fatal("do_pci: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_pci: unexpected string at %s:%d", cpe->file, cpe->line); } if (strcmp(cpe->word, KW_DEVICE) == 0) { do_pci_device(cpe->next, rs_start); return; } if (strcmp(cpe->word, KW_CLASS) == 0) { do_pci_class(cpe->next, rs_start); return; } fatal("do_pci: unexpected word '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } static void do_ipc(config_t *cpe, struct rs_start *rs_start) { char *list; const char *word; char *word_all = RSS_IPC_ALL; char *word_all_sys = RSS_IPC_ALL_SYS; size_t listsize, wordlen; int first; list= NULL; listsize= 1; list= malloc(listsize); if (list == NULL) fatal("do_ipc: unable to malloc %d bytes", listsize); list[0]= '\0'; /* Process a list of process names that are allowed to be * contacted */ first = TRUE; for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_ipc: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_ipc: unexpected string at %s:%d", cpe->file, cpe->line); } word = cpe->word; /* All (system) ipc targets are allowed? */ if(!strcmp(word, KW_ALL) || !strcmp(word, KW_ALL_SYS)) { if(!first || cpe->next) { fatal("do_ipc: %s keyword not allowed in list", word); } word = !strcmp(word, KW_ALL) ? word_all : word_all_sys; } wordlen= strlen(word); listsize += 1 + wordlen; list= realloc(list, listsize); if (list == NULL) { fatal("do_ipc: unable to realloc %d bytes", listsize); } strcat(list, " "); strcat(list, word); first = FALSE; } #if 0 printf("do_ipc: got list '%s'\n", list); #endif if (rs_start->rss_ipc) fatal("do_ipc: req_ipc is set"); rs_start->rss_ipc = list+1; rs_start->rss_ipclen= strlen(rs_start->rss_ipc); } struct { char *label; int call_nr; } vm_table[] = { { "EXIT", VM_EXIT }, { "FORK", VM_FORK }, { "EXEC_NEWMEM", VM_EXEC_NEWMEM }, { "PUSH_SIG", 0 }, { "WILLEXIT", VM_WILLEXIT }, { "ADDDMA", VM_ADDDMA }, { "DELDMA", VM_DELDMA }, { "GETDMA", VM_GETDMA }, { "REMAP", VM_REMAP }, { "REMAP_RO", VM_REMAP_RO }, { "SHM_UNMAP", VM_SHM_UNMAP }, { "GETPHYS", VM_GETPHYS }, { "GETREF", VM_GETREF }, { "RS_SET_PRIV", VM_RS_SET_PRIV }, { "QUERY_EXIT", VM_QUERY_EXIT }, { "WATCH_EXIT", VM_WATCH_EXIT }, { "NOTIFY_SIG", VM_NOTIFY_SIG }, { "INFO", VM_INFO }, { "RS_UPDATE", VM_RS_UPDATE }, { "RS_MEMCTL", VM_RS_MEMCTL }, { "PROCCTL", VM_PROCCTL }, { "MAPCACHEPAGE", VM_MAPCACHEPAGE }, { "SETCACHEPAGE", VM_SETCACHEPAGE }, { "FORGETCACHEPAGE", VM_FORGETCACHEPAGE }, { "CLEARCACHE", VM_CLEARCACHE }, { "VFS_MMAP", VM_VFS_MMAP }, { "VFS_REPLY", VM_VFS_REPLY }, { "GETRUSAGE", VM_GETRUSAGE }, { "RS_PREPARE", VM_RS_PREPARE }, { NULL, 0 }, }; static void do_vm(config_t *cpe, struct rs_start *rs_start) { int i, first; first = TRUE; for (; cpe; cpe = cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_vm: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_vm: unexpected string at %s:%d", cpe->file, cpe->line); } /* Only basic calls allowed? (default). */ if(!strcmp(cpe->word, KW_BASIC)) { if(!first || cpe->next) { fatal("do_vm: %s keyword not allowed in list", KW_NONE); } break; } /* No calls allowed? */ if(!strcmp(cpe->word, KW_NONE)) { if(!first || cpe->next) { fatal("do_vm: %s keyword not allowed in list", KW_NONE); } rs_start->rss_flags &= ~RSS_VM_BASIC_CALLS; break; } /* All calls are allowed? */ if(!strcmp(cpe->word, KW_ALL)) { if(!first || cpe->next) { fatal("do_vm: %s keyword not allowed in list", KW_ALL); } for (i = 0; i < NR_VM_CALLS; i++) SET_BIT(rs_start->rss_vm, i); break; } /* Set single calls as specified in the configuration. */ for (i = 0; vm_table[i].label != NULL; i++) if (!strcmp(cpe->word, vm_table[i].label)) break; if (vm_table[i].label == NULL) { warning("do_vm: ignoring unknown call '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } else if(vm_table[i].call_nr) { SET_BIT(rs_start->rss_vm, vm_table[i].call_nr - VM_RQ_BASE); } first = FALSE; } } struct { char *label; int call_nr; } system_tab[]= { { "PRIVCTL", SYS_PRIVCTL }, { "TRACE", SYS_TRACE }, { "KILL", SYS_KILL }, { "UMAP", SYS_UMAP }, { "VIRCOPY", SYS_VIRCOPY }, { "PHYSCOPY", SYS_PHYSCOPY }, { "UMAP_REMOTE", SYS_UMAP_REMOTE }, { "VUMAP", SYS_VUMAP }, { "IRQCTL", SYS_IRQCTL }, { "INT86", SYS_INT86 }, { "DEVIO", SYS_DEVIO }, { "SDEVIO", SYS_SDEVIO }, { "VDEVIO", SYS_VDEVIO }, { "ABORT", SYS_ABORT }, { "IOPENABLE", SYS_IOPENABLE }, { "READBIOS", SYS_READBIOS }, { "STIME", SYS_STIME }, { "VMCTL", SYS_VMCTL }, { "MEMSET", SYS_MEMSET }, { "PADCONF", SYS_PADCONF }, { NULL, 0 } }; static void do_system(config_t *cpe, struct rs_start *rs_start) { int i, first; /* Process a list of 'system' calls that are allowed */ first = TRUE; for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_system: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_system: unexpected string at %s:%d", cpe->file, cpe->line); } /* Only basic calls allowed? (default). */ if(!strcmp(cpe->word, KW_BASIC)) { if(!first || cpe->next) { fatal("do_system: %s keyword not allowed in list", KW_NONE); } break; } /* No calls allowed? */ if(!strcmp(cpe->word, KW_NONE)) { if(!first || cpe->next) { fatal("do_system: %s keyword not allowed in list", KW_NONE); } rs_start->rss_flags &= ~RSS_SYS_BASIC_CALLS; break; } /* All calls are allowed? */ if(!strcmp(cpe->word, KW_ALL)) { if(!first || cpe->next) { fatal("do_system: %s keyword not allowed in list", KW_ALL); } for (i = 0; i < NR_SYS_CALLS; i++) SET_BIT(rs_start->rss_system, i); break; } /* Set single calls as specified in the configuration. */ for (i = 0; system_tab[i].label != NULL; i++) if (!strcmp(cpe->word, system_tab[i].label)) break; if (system_tab[i].label == NULL) { warning("do_system: ignoring unknown call '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } else { SET_BIT(rs_start->rss_system, system_tab[i].call_nr - KERNEL_CALL); } first = FALSE; } } static void do_control(config_t *cpe, struct rs_start *rs_start) { int nr_control = 0; /* Process a list of 'control' labels. */ for (; cpe; cpe= cpe->next) { if (cpe->flags & CFG_SUBLIST) { fatal("do_control: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { fatal("do_control: unexpected string at %s:%d", cpe->file, cpe->line); } if (nr_control >= RS_NR_CONTROL) { fatal( "do_control: RS_NR_CONTROL is too small (%d needed)", nr_control+1); } rs_start->rss_control[nr_control].l_addr = (char*) cpe->word; rs_start->rss_control[nr_control].l_len = strlen(cpe->word); rs_start->rss_nr_control = ++nr_control; } } static void do_service(config_t *cpe, config_t *config, struct rs_config *rs_config) { struct rs_start *rs_start = &rs_config->rs_start; config_t *cp; /* At this point we expect one sublist that contains the varios * resource allocations */ if (!(cpe->flags & CFG_SUBLIST)) { fatal("do_service: expected list at %s:%d", cpe->file, cpe->line); } if (cpe->next != NULL) { cpe= cpe->next; fatal("do_service: expected end of list at %s:%d", cpe->file, cpe->line); } cpe= cpe->list; /* Process the list */ for (cp= cpe; cp; cp= cp->next) { if (!(cp->flags & CFG_SUBLIST)) { fatal("do_service: expected list at %s:%d", cp->file, cp->line); } cpe= cp->list; if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) { fatal("do_service: expected word at %s:%d", cpe->file, cpe->line); } if (strcmp(cpe->word, KW_CLASS) == 0) { do_class(cpe->next, config, rs_config); continue; } if (strcmp(cpe->word, KW_UID) == 0) { do_uid(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_SIGMGR) == 0) { do_sigmgr(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_TYPE) == 0) { do_type(cpe->next, rs_config); continue; } if (strcmp(cpe->word, KW_DESCR) == 0) { do_descr(cpe->next, rs_config); continue; } if (strcmp(cpe->word, KW_SCHEDULER) == 0) { do_scheduler(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_PRIORITY) == 0) { do_priority(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_QUANTUM) == 0) { do_quantum(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_CPU) == 0) { do_cpu(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_IRQ) == 0) { do_irq(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_IO) == 0) { do_io(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_PCI) == 0) { do_pci(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_SYSTEM) == 0) { do_system(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_IPC) == 0) { do_ipc(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_VM) == 0) { do_vm(cpe->next, rs_start); continue; } if (strcmp(cpe->word, KW_CONTROL) == 0) { do_control(cpe->next, rs_start); continue; } } } static const char *do_config(const char *label, char *filename, struct rs_config *rs_config) { config_t *config, *cp, *cpe; struct passwd *pw; struct rs_start *rs_start = &rs_config->rs_start; if(!(config= config_read(filename, 0, NULL))) return NULL; /* config file read failed. */ /* Set clean rs_start defaults. */ memset(rs_config, 0, sizeof(*rs_config)); if(!(pw= getpwnam(SERVICE_LOGIN))) fatal("no passwd file entry for '%s'", SERVICE_LOGIN); rs_start->rss_uid= pw->pw_uid; rs_start->rss_sigmgr= DSRV_SM; rs_start->rss_scheduler= DSRV_SCH; rs_start->rss_priority= DSRV_Q; rs_start->rss_quantum= DSRV_QT; rs_start->rss_cpu = DSRV_CPU; rs_start->rss_flags = RSS_VM_BASIC_CALLS | RSS_SYS_BASIC_CALLS; /* Find an entry for our service */ for (cp= config; cp; cp= cp->next) { if (!(cp->flags & CFG_SUBLIST)) { fatal("do_config: expected list at %s:%d", cp->file, cp->line); } cpe= cp->list; if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) { fatal("do_config: expected word at %s:%d", cpe->file, cpe->line); } /* At this place we expect the word KW_SERVICE */ if (strcmp(cpe->word, KW_SERVICE) != 0) fatal("do_config: exected word '%S' at %s:%d", KW_SERVICE, cpe->file, cpe->line); cpe= cpe->next; if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST)) { fatal("do_config: expected word at %s:%d", cpe->file, cpe->line); } /* At this place we expect the name of the service. */ if (!label || strcmp(cpe->word, label) == 0) { label = cpe->word; break; } } if (cp == NULL) { fprintf(stderr, "service: service '%s' not found in '%s'\n", label, filename); exit(1); } cpe= cpe->next; do_service(cpe, config, rs_config); { char *default_ipc = RSS_IPC_ALL_SYS; if(!rs_start->rss_ipc) { rs_start->rss_ipc= default_ipc; rs_start->rss_ipclen= strlen(default_ipc); } } /* config file read ok. */ return label; } /* returns failure */ const char *parse_config(char *progname, int custom_config, char *req_config, struct rs_config *rs_config) { char *specificconfig, *specific_pkg_config; const char *l; /* Config file specified? */ if(custom_config) return do_config(progname, req_config, rs_config); /* No specific config file. */ if(asprintf(&specificconfig, "%s/%s", _PATH_SYSTEM_CONF_DIR, progname) < 0) { errx(1, "no memory"); } if(asprintf(&specific_pkg_config, "%s/%s", _PATH_SYSTEM_CONF_PKG_DIR, progname) < 0) { errx(1, "no memory"); } /* Try specific config filename first, in base system * and package locations, * and only if it fails, the global * system one. */ if((l=do_config(progname, specific_pkg_config, rs_config))) return l; if((l=do_config(progname, specificconfig, rs_config))) return l; if((l=do_config(progname, req_config, rs_config))) return l; return NULL; }