# Changes:
#
+# Get system config
+. /etc/rc.conf
+
LOCALRC=/usr/etc/rc.local
INETCONF=/etc/inet.conf
RCNET=/etc/rc.net
HOSTS=/etc/hosts
HOSTNAME=/etc/hostname.file
USRKBFILE=/.usrkb
+LSPCI=/tmp/lspci.$$
+DEVICES=/tmp/devices.$$
step1=""
step2=""
shift 2
while [ $# -gt 0 ]
do
- lspci | grep > /dev/null "^$1" && card_avail=1
+ cat $LSPCI | grep > /dev/null "^$1" && card_avail=1
shift
done
if [ $card_avail -gt 0 ]
printf "%2d. %s %s\n" "$card_number" "$card_mark" "$card_name"
}
+first_pcicard=4
+
cards()
{
card 0 "No Ethernet card (no networking)"
- card 1 "Intel Pro/100" "8086:103D" "8086:1064" "8086:1229" "8086:2449" \
- "8086:1031" "8086:1032"
- card 2 "3Com 501 or 3Com 509 based card"
- card 3 "Realtek 8139 based card (also emulated by KVM)" \
- "10EC:8139" "02AC:1012" "1065:8139" "1113:1211" "1186:1300" \
- "1186:1340" "11DB:1234" "1259:A117" "1259:A11E" "126C:1211" \
- "13D1:AB06" "1432:9130" "14EA:AB06" "14EA:AB07" "1500:1360" \
- "1743:8139" "4033:1360"
- card 4 "Realtek 8169 based card" \
- "10EC:8129" "10EC:8167" "10EC:8169" "1186:4300" "1259:C107" \
- "1385:8169" "16EC:0116" "1737:1032" "10EC:8168"
- card 5 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029"
- card 6 "NE2000, 3com 503 or WD based card (also emulated by Bochs)"
- card 7 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000"
- card 8 "Intel PRO/1000 Gigabit" \
- "8086:100E" "8086:107C" "8086:10CD" "8086:10D3" "8086:10DE"
-
- card 9 "Attansic/Atheros L2 FastEthernet" "1969:2048"
- card 10 "DEC Tulip 21140A in VirtualPC" "1011:0009"
- card 11 "Different Ethernet card (no networking)"
+ card 1 "3Com 501 or 3Com 509 based card"
+ card 2 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029"
+ card 3 "NE2000, 3com 503 or WD based card (also emulated by Bochs)"
+ n=$first_pcicard
+ for pcicard in $pci_list
+ do var=\$pci_descr$pcicard; descr="`eval echo $var`"
+ var=\$pci_pcilist$pcicard; pcilist="`eval echo $var`"
+ card $n "$descr" $pcilist
+ n="`expr $n + 1`"
+ done
+
+ card $first_after_pci "Different Ethernet card (no networking)"
}
warn()
echo -e "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b ! $1"
}
+config_pci_cards() {
+ rm -f $DEVICES
+
+ n=0
+
+ # Collect configs from network devices
+ for dir in $SYSTEM_CONF_DIRS
+ do for f in $dir/$SYSTEM_CONF_SUBDIR/*
+ do if [ -f $f ]
+ then printconfig $f | grep 'type net.*pci device'
+ fi
+ done
+ done >$DEVICES
+ while read devline
+ do pcilist="`echo $devline | sed 's/.*pci device //' | sed 's/,.*//'`"
+ descr="`echo $devline | sed 's/.*,descr //' | sed 's/,.*//'`"
+ label="`echo $devline | sed 's/.*service //' | sed 's/,.*//'`"
+ pci_list="$pci_list $n"
+ eval "pci_pcilist$n=\"$pcilist\""
+ eval "pci_descr$n=\"$descr\""
+ eval "pci_label$n=\"$label\""
+ n="`expr $n + 1`"
+ done <$DEVICES
+
+ first_after_pci=`expr $first_pcicard + $n`
+
+ rm -f $DEVICES
+}
+
do_step1()
{
eth_default=0
drv_params()
{
+ # If this is a known pci device, we only have to set
+ # the driver.
+ if [ $1 -ge $first_pcicard -a $1 -lt $first_after_pci ]
+ then pcicard="`expr $1 - $first_pcicard`"
+ var=\$pci_label$pcicard; driver="`eval echo $var`"
+ return
+ fi
+
+ # Other possibilities.
case "$1" in
0) driver=psip0; ;;
- 1) driver=fxp; ;;
- 2) driver=dpeth; driverargs="#dpeth_arg='DPETH0=port:irq:memory'";
+ 1) driver=dpeth; driverargs="#dpeth_arg='DPETH0=port:irq:memory'";
test "$v" = 1 && echo ""
test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
;;
- 4) driver=rtl8169; ;;
- 3) driver=rtl8139; ;;
- 5) driver=dp8390; driverargs="dp8390_arg='DPETH0=pci'"; ;;
- 6) driver=dp8390; driverargs="dp8390_arg='DPETH0=240:9'";
+ 2) driver=dp8390; driverargs="dp8390_arg='DPETH0=pci'"; ;;
+ 3) driver=dp8390; driverargs="dp8390_arg='DPETH0=240:9'";
test "$v" = 1 && echo ""
test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
test "$v" = 1 && echo " chose option 4, the defaults for emulation by Bochs have been set."
;;
- 7) driver="lance"; ;;
- 8) driver="e1000"; ;;
- 9) driver="atl2"; ;;
- 10) driver="dec21140A"; ;;
- 11) driver="psip0"; ;;
+ $first_after_pci) driver="psip0"; ;;
*) warn "choose a number"
esac
}
fi
}
+# Find pci cards we know about
+config_pci_cards
+
# Parse options
while getopts ":qe:p:aH:i:n:g:d:s:hc" arg; do
case "$arg" in
esac
done
+# Run lspci once to a temp file
+lspci >$LSPCI || exit
+
# Verify parameter count
if [ "$dhcp" != "yes" ] ; then
if [ $manual_opts -gt 0 ] ; then
fi
echo "$driverargs" > $LOCALRC
+# Remove temporary lspci output
+rm -f $LSPCI
+
if [ -n "$manual" ]
then
# Backup config file if it exists and we're not running from CD
# Makefile for service
-PROG= service
+PROGS= service printconfig
+SRCS.service=service.c parse.c util.c
+SRCS.printconfig=print.c parse.c util.c
BINDIR= /bin
-MAN=
+MAN.service=
+MAN.printconfig=
CPPFLAGS+= -I${MINIXSRCDIR}
--- /dev/null
+
+struct rs_config {
+ struct rs_start rs_start; /* RS parameters */
+ const char *descr; /* human-readable description, if specified */
+ char *type; /* service type, if specified */
+};
+
--- /dev/null
+
+#include <stdarg.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <err.h>
+#include <unistd.h>
+#include <limits.h>
+#include <lib.h>
+#include <minix/config.h>
+#include <minix/com.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/rs.h>
+#include <minix/syslib.h>
+#include <minix/bitmap.h>
+#include <paths.h>
+#include <minix/sef.h>
+#include <minix/dmap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <configfile.h>
+
+#include <machine/archtypes.h>
+#include <timers.h>
+#include "kernel/proc.h"
+
+#include "config.h"
+#include "proto.h"
+
+PRIVATE int class_recurs; /* Nesting level of class statements */
+#define MAX_CLASS_RECURS 100 /* Max nesting level for classes */
+
+#include "parse.h"
+
+#define SERVICE_LOGIN "service" /* passwd file entry for services */
+
+FORWARD void do_service(config_t *cpe, config_t *config, struct rs_config *);
+
+PRIVATE 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--;
+}
+
+PRIVATE 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
+ {
+ 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;
+}
+
+PRIVATE 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;
+}
+
+PRIVATE 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);
+}
+
+PRIVATE 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;
+}
+
+PRIVATE 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;
+}
+
+PRIVATE 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;
+}
+
+PRIVATE 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;
+}
+
+PRIVATE 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;
+}
+
+PRIVATE 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;
+ }
+}
+
+PRIVATE 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;
+ }
+}
+
+PRIVATE void do_pci_device(config_t *cpe, struct rs_start *rs_start)
+{
+ u16_t vid, 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] == '/')
+ 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);
+ }
+ 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_nr_pci_id++;
+ }
+}
+
+PRIVATE 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++;
+ }
+}
+
+PRIVATE 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);
+}
+
+PRIVATE 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 },
+ { "BRK", VM_BRK },
+ { "EXEC_NEWMEM", VM_EXEC_NEWMEM },
+ { "PUSH_SIG", VM_PUSH_SIG },
+ { "WILLEXIT", VM_WILLEXIT },
+ { "ADDDMA", VM_ADDDMA },
+ { "DELDMA", VM_DELDMA },
+ { "GETDMA", VM_GETDMA },
+ { "REMAP", VM_REMAP },
+ { "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 },
+ { NULL, 0 },
+};
+
+PRIVATE 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)
+ fatal("do_vm: unknown call '%s' at %s:%d",
+ cpe->word, cpe->file, cpe->line);
+ 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 },
+ { "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 },
+ { NULL, 0 }
+};
+
+PRIVATE 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)
+ fatal("do_system: unknown call '%s' at %s:%d",
+ cpe->word, cpe->file, cpe->line);
+ SET_BIT(rs_start->rss_system, system_tab[i].call_nr - KERNEL_CALL);
+ first = FALSE;
+ }
+}
+
+PRIVATE 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;
+ }
+}
+
+PRIVATE 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;
+ }
+ }
+}
+
+PRIVATE 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 */
+PUBLIC 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;
+}
+
--- /dev/null
+#define KW_SERVICE "service"
+#define KW_UID "uid"
+#define KW_SIGMGR "sigmgr"
+#define KW_SCHEDULER "scheduler"
+#define KW_PRIORITY "priority"
+#define KW_QUANTUM "quantum"
+#define KW_CPU "cpu"
+#define KW_IRQ "irq"
+#define KW_IO "io"
+#define KW_PCI "pci"
+#define KW_DEVICE "device"
+#define KW_CLASS "class"
+#define KW_SYSTEM "system"
+#define KW_IPC "ipc"
+#define KW_VM "vm"
+#define KW_CONTROL "control"
+#define KW_ALL "ALL"
+#define KW_ALL_SYS "ALL_SYS"
+#define KW_NONE "NONE"
+#define KW_BASIC "BASIC"
+#define KW_TYPE "type" /* set service type */
+#define KW_NET "net" /* ethernet driver type */
+#define KW_DESCR "descr" /* human-readable string */
--- /dev/null
+
+#include <stdarg.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <limits.h>
+#include <lib.h>
+#include <minix/config.h>
+#include <minix/com.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/rs.h>
+#include <minix/syslib.h>
+#include <minix/bitmap.h>
+#include <paths.h>
+#include <minix/sef.h>
+#include <minix/dmap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <configfile.h>
+
+#include <machine/archtypes.h>
+#include <timers.h>
+#include <err.h>
+
+#include "config.h"
+#include "proto.h"
+#include "parse.h"
+
+#define MAXDEPTH 10
+
+static struct {
+ const char *field, *str;
+} configstack[MAXDEPTH];
+
+int depth = 0;
+
+void printstack(void)
+{
+ int i;
+ for(i = 0; i < depth; i++)
+ printf("%s %s,", configstack[i].field,
+ configstack[i].str);
+}
+
+void print(const char *field, const char *str)
+{
+ printstack();
+ printf("%s %s\n", field, str);
+}
+
+void push(const char *field, const char *str)
+{
+ assert(depth < MAXDEPTH);
+ configstack[depth].field = field;
+ configstack[depth].str = str;
+ depth++;
+ printstack();
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct rs_config config;
+ const char *label;
+ int id;
+
+ if(argc != 2) {
+ fprintf(stderr, "usage: %s <config>\n", argv[0]);
+ return 1;
+ }
+
+ memset(&config, 0, sizeof(config));
+ if(!(label = parse_config(NULL, 1, argv[1], &config)))
+ errx(1, "parse_config failed");
+
+ push(KW_SERVICE, label);
+ if(config.type) push(KW_TYPE, config.type);
+
+ if(config.descr) push(KW_DESCR, config.descr);
+ if(config.rs_start.rss_nr_pci_id > 0) {
+ printstack();
+ printf("%s %s ", KW_PCI, KW_DEVICE);
+ for(id = 0; id < config.rs_start.rss_nr_pci_id; id++) {
+ printf("%04X:%04X ",
+ config.rs_start.rss_pci_id[id].vid,
+ config.rs_start.rss_pci_id[id].did);
+ }
+ printf("\n");
+ }
+}
+
--- /dev/null
+void fatal(char *fmt, ...);
+const char *parse_config(char *progname, int custom, char *configname,
+ struct rs_config *config);
#include <machine/archtypes.h>
#include <timers.h>
+#include <err.h>
#include "kernel/proc.h"
+#include "config.h"
+#include "proto.h"
/* This array defines all known requests. */
PRIVATE char *known_requests[] = {
#define ARG_DEVMANID "-devid" /* the id of the devman device this
driver should be able to access */
-#define SERVICE_LOGIN "service" /* passwd file entry for services */
-
-#define MAX_CLASS_RECURS 100 /* Max nesting level for classes */
-
/* The function parse_arguments() verifies and parses the command line
* parameters passed to this utility. Request parameters that are needed
* are stored globally in the following variables:
PRIVATE int req_dev_style = STYLE_NDEV;
PRIVATE long req_period = 0;
PRIVATE char *req_script = NULL;
-PRIVATE char *req_ipc = NULL;
PRIVATE char *req_config = PATH_CONFIG;
PRIVATE int custom_config_file = 0;
-PRIVATE int class_recurs; /* Nesting level of class statements */
PRIVATE int req_lu_state = DEFAULT_LU_STATE;
PRIVATE int req_lu_maxtime = DEFAULT_LU_MAXTIME;
/* Buffer to build "/command arg1 arg2 ..." string to pass to RS server. */
PRIVATE char command[4096];
-/* Arguments for RS to start a new service */
-PRIVATE struct rs_start rs_start;
-
/* An error occurred. Report the problem, print the usage, and exit.
*/
PRIVATE void print_usage(char *app_name, char *problem)
/* Parse and verify correctness of arguments. Report problem and exit if an
* error is found. Store needed parameters in global variables.
*/
-PRIVATE int parse_arguments(int argc, char **argv)
+PRIVATE int parse_arguments(int argc, char **argv, u32_t *rss_flags)
{
struct stat stat_buf;
char *hz, *buff;
req_nr = RS_RQ_BASE + req_type;
}
- rs_start.rss_flags = RSS_SYS_BASIC_CALLS | RSS_VM_BASIC_CALLS;
+ *rss_flags = 0;
if (req_nr == RS_UP || req_nr == RS_UPDATE || req_nr == RS_EDIT) {
u32_t system_hz;
if (c_flag)
- rs_start.rss_flags |= RSS_COPY;
+ *rss_flags |= RSS_COPY;
if(r_flag)
- rs_start.rss_flags |= RSS_REUSE;
+ *rss_flags |= RSS_REUSE;
if(n_flag)
- rs_start.rss_flags |= RSS_NOBLOCK;
+ *rss_flags |= RSS_NOBLOCK;
if(p_flag)
- rs_start.rss_flags |= RSS_REPLICA;
+ *rss_flags |= RSS_REPLICA;
req_path = argv[optind+ARG_PATH];
if(req_nr == RS_UPDATE && !strcmp(req_path, SELF_BINARY)) {
/* Self update needs no real path or configuration file. */
req_config = NULL;
req_path = req_path_self;
- rs_start.rss_flags |= RSS_SELF_LU;
+ *rss_flags |= RSS_SELF_LU;
}
if (do_run)
}
/* Verify the name of the binary of the system service. */
- if(!(rs_start.rss_flags & RSS_SELF_LU)) {
+ if(!(*rss_flags & RSS_SELF_LU)) {
if (req_path[0] != '/') {
print_usage(argv[ARG_NAME], "binary should be absolute path");
exit(EINVAL);
/* no extra arguments required */
}
- label_required = (rs_start.rss_flags & RSS_SELF_LU) || (req_nr == RS_EDIT);
+ label_required = (*rss_flags & RSS_SELF_LU) || (req_nr == RS_EDIT);
if(label_required && !req_label) {
print_usage(argv[ARG_NAME], "label option mandatory for target action");
exit(EINVAL);
return(req_nr);
}
-PRIVATE void fatal(char *fmt, ...)
-{
- va_list ap;
-
- fprintf(stderr, "fatal error: ");
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-
- exit(1);
-}
-
-#define KW_SERVICE "service"
-#define KW_UID "uid"
-#define KW_SIGMGR "sigmgr"
-#define KW_SCHEDULER "scheduler"
-#define KW_PRIORITY "priority"
-#define KW_QUANTUM "quantum"
-#define KW_CPU "cpu"
-#define KW_IRQ "irq"
-#define KW_IO "io"
-#define KW_PCI "pci"
-#define KW_DEVICE "device"
-#define KW_CLASS "class"
-#define KW_SYSTEM "system"
-#define KW_IPC "ipc"
-#define KW_VM "vm"
-#define KW_CONTROL "control"
-#define KW_ALL "ALL"
-#define KW_ALL_SYS "ALL_SYS"
-#define KW_NONE "NONE"
-#define KW_BASIC "BASIC"
-
-FORWARD void do_service(config_t *cpe, config_t *config);
-
-PRIVATE void do_class(config_t *cpe, config_t *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);
- }
-
- class_recurs--;
-}
-
-PRIVATE void do_uid(config_t *cpe)
-{
- 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
- {
- 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;
-}
-
-PRIVATE void do_sigmgr(config_t *cpe)
-{
- 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 {
- r = minix_rs_lookup(cpe->word, &sigmgr_ep);
- if(r != OK) {
- fatal("do_sigmgr: unknown sigmgr %s at %s:%d",
- cpe->word, cpe->file, cpe->line);
- }
- }
-
- rs_start.rss_sigmgr= sigmgr_ep;
-}
-
-PRIVATE void do_scheduler(config_t *cpe)
-{
- 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 {
- r = minix_rs_lookup(cpe->word, &scheduler_ep);
- if(r != OK) {
- fatal("do_scheduler: unknown scheduler %s at %s:%d",
- cpe->word, cpe->file, cpe->line);
- }
- }
-
- rs_start.rss_scheduler= scheduler_ep;
-}
-
-PRIVATE void do_priority(config_t *cpe)
-{
- 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;
-}
-
-PRIVATE void do_quantum(config_t *cpe)
-{
- 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;
-}
-
-PRIVATE void do_cpu(config_t *cpe)
-{
- 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;
-}
-
-PRIVATE void do_irq(config_t *cpe)
-{
- 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;
- }
-}
-
-PRIVATE void do_io(config_t *cpe)
-{
- 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;
- }
-}
-
-PRIVATE void do_pci_device(config_t *cpe)
-{
- u16_t vid, 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] == '/')
- 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);
- }
- 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_nr_pci_id++;
- }
-}
-
-PRIVATE void do_pci_class(config_t *cpe)
-{
- 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++;
- }
-}
-
-PRIVATE void do_pci(config_t *cpe)
-{
- 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);
- return;
- }
- if (strcmp(cpe->word, KW_CLASS) == 0)
- {
- do_pci_class(cpe->next);
- return;
- }
- fatal("do_pci: unexpected word '%s' at %s:%d",
- cpe->word, cpe->file, cpe->line);
-}
-
-PRIVATE void do_ipc(config_t *cpe)
-{
- char *list, *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 (req_ipc)
- fatal("do_ipc: req_ipc is set");
- req_ipc= list;
-}
-
-struct
-{
- char *label;
- int call_nr;
-} vm_table[] =
-{
- { "EXIT", VM_EXIT },
- { "FORK", VM_FORK },
- { "BRK", VM_BRK },
- { "EXEC_NEWMEM", VM_EXEC_NEWMEM },
- { "PUSH_SIG", VM_PUSH_SIG },
- { "WILLEXIT", VM_WILLEXIT },
- { "ADDDMA", VM_ADDDMA },
- { "DELDMA", VM_DELDMA },
- { "GETDMA", VM_GETDMA },
- { "REMAP", VM_REMAP },
- { "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 },
- { NULL, 0 },
-};
-
-PRIVATE void do_vm(config_t *cpe)
-{
- 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)
- fatal("do_vm: unknown call '%s' at %s:%d",
- cpe->word, cpe->file, cpe->line);
- 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 },
- { "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 },
- { NULL, 0 }
-};
-
-PRIVATE void do_system(config_t *cpe)
-{
- 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)
- fatal("do_system: unknown call '%s' at %s:%d",
- cpe->word, cpe->file, cpe->line);
- SET_BIT(rs_start.rss_system, system_tab[i].call_nr - KERNEL_CALL);
- first = FALSE;
- }
-}
-
-PRIVATE void do_control(config_t *cpe)
-{
- 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;
- }
-}
-
-PRIVATE void do_service(config_t *cpe, config_t *config)
-{
- 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);
- continue;
- }
- if (strcmp(cpe->word, KW_UID) == 0)
- {
- do_uid(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_SIGMGR) == 0)
- {
- do_sigmgr(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_SCHEDULER) == 0)
- {
- do_scheduler(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_PRIORITY) == 0)
- {
- do_priority(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_QUANTUM) == 0)
- {
- do_quantum(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_CPU) == 0)
- {
- do_cpu(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_IRQ) == 0)
- {
- do_irq(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_IO) == 0)
- {
- do_io(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_PCI) == 0)
- {
- do_pci(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_SYSTEM) == 0)
- {
- do_system(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_IPC) == 0)
- {
- do_ipc(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_VM) == 0)
- {
- do_vm(cpe->next);
- continue;
- }
- if (strcmp(cpe->word, KW_CONTROL) == 0)
- {
- do_control(cpe->next);
- continue;
- }
- }
-}
-
-PRIVATE int do_config(char *label, char *filename)
-{
- config_t *config, *cp, *cpe;
-
- config= config_read(filename, 0, NULL);
- if (config == NULL)
- {
- /* config file read failed. */
- return 1;
- }
-
- /* 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 (strcmp(cpe->word, label) == 0)
- 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);
-
- /* config file read ok. */
- return 0;
-}
-
/* Main program.
*/
PUBLIC int main(int argc, char **argv)
int result = EXIT_SUCCESS;
int request;
char *progname = NULL;
- struct passwd *pw;
+ /* Arguments for RS to start a new service */
+ struct rs_config config;
+ u32_t rss_flags = 0;
/* Verify and parse the command line arguments. All arguments are checked
* here. If an error occurs, the problem is reported and exit(2) is called.
* all needed parameters to perform the request are extracted and stored
* global variables.
*/
- request = parse_arguments(argc, argv);
+ request = parse_arguments(argc, argv, &rss_flags);
/* Arguments seem fine. Try to perform the request. Only valid requests
* should end up here. The default is used for not yet supported requests.
command[strlen(req_path)] = ' ';
strcpy(command+strlen(req_path)+1, req_args);
- rs_start.rss_cmd= command;
- rs_start.rss_cmdlen= strlen(command);
- rs_start.rss_major= req_major;
- rs_start.rss_dev_style= req_dev_style;
- rs_start.rss_period= req_period;
- rs_start.rss_script= req_script;
- rs_start.devman_id= devman_id;
- if(req_label) {
- rs_start.rss_label.l_addr = req_label;
- rs_start.rss_label.l_len = strlen(req_label);
- } else {
- rs_start.rss_label.l_addr = progname;
- rs_start.rss_label.l_len = strlen(progname);
- }
- if (req_script)
- rs_start.rss_scriptlen= strlen(req_script);
- else
- rs_start.rss_scriptlen= 0;
-
- pw= getpwnam(SERVICE_LOGIN);
- if (pw == NULL)
- 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;
-
if (req_config) {
- int config_fail = 0;
assert(progname);
- if(custom_config_file) {
- config_fail = do_config(progname, req_config);
- } else {
- char *specificconfig;
- if(asprintf(&specificconfig, "%s/%s", _PATH_SYSTEM_CONF_DIR,
- progname) < 0) {
- errx(1, "no memory");
- }
-
- /* Try specific config filename first,
- * and only if it fails, the global system one.
- */
- config_fail =
- do_config(progname, specificconfig) &&
- do_config(progname, req_config);
- }
-
- if(config_fail) {
- fprintf(stderr, "config_read failed for %s\n", progname);
- exit(1);
- }
+ memset(&config, 0, sizeof(config));
+ if(!parse_config(progname, custom_config_file, req_config, &config))
+ errx(1, "couldn't parse config");
}
- assert(rs_start.rss_priority < NR_SCHED_QUEUES);
- assert(rs_start.rss_quantum > 0);
-
- if (req_ipc)
- {
- rs_start.rss_ipc= req_ipc+1; /* Skip initial space */
- rs_start.rss_ipclen= strlen(rs_start.rss_ipc);
+ /* Set specifics */
+ config.rs_start.rss_cmd= command;
+ config.rs_start.rss_cmdlen= strlen(command);
+ config.rs_start.rss_major= req_major;
+ config.rs_start.rss_dev_style= req_dev_style;
+ config.rs_start.rss_period= req_period;
+ config.rs_start.rss_script= req_script;
+ config.rs_start.devman_id= devman_id;
+ config.rs_start.rss_flags |= rss_flags;
+ if(req_label) {
+ config.rs_start.rss_label.l_addr = req_label;
+ config.rs_start.rss_label.l_len = strlen(req_label);
+ } else {
+ config.rs_start.rss_label.l_addr = progname;
+ config.rs_start.rss_label.l_len = strlen(progname);
}
+ if (req_script)
+ config.rs_start.rss_scriptlen= strlen(req_script);
else
- {
- char *default_ipc = RSS_IPC_ALL_SYS;
- rs_start.rss_ipc= default_ipc;
- rs_start.rss_ipclen= strlen(default_ipc);
- }
+ config.rs_start.rss_scriptlen= 0;
+
+ assert(config.rs_start.rss_priority < NR_SCHED_QUEUES);
+ assert(config.rs_start.rss_quantum > 0);
- m.RS_CMD_ADDR = (char *) &rs_start;
+ m.RS_CMD_ADDR = (char *) &config.rs_start;
break;
case RS_DOWN:
case RS_REFRESH:
--- /dev/null
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void fatal(char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "fatal error: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+
+ exit(1);
+}
_PROTOTYPE(char *itoa, (int _n));
#ifndef __NBSD_LIBC
_PROTOTYPE(char *getpass, (const char *_prompt));
+#ifdef __ACK__
_PROTOTYPE(void swab, (char *_from, char *_to, int _count));
+#endif
#endif /* !_NBSD_LIBC */
/* Miscellaneous MINIX. */
PROG= atl2
SRCS= atl2.c
+FILES=$(PROG).conf
+FILESNAME=$(PROG)
+FILESDIR= /etc/system.conf.d
+
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
--- /dev/null
+service atl2
+{
+ type net;
+ descr "Attansic/Atheros L2 FastEthernet";
+ system
+ UMAP # 14
+ IRQCTL # 19
+ ;
+ pci device 1969/2048;
+ ipc
+ SYSTEM pm rs tty ds vm
+ pci inet lwip
+ ;
+};
+
PROG= dec21140A
SRCS= dec21140A.c
+FILES=$(PROG).conf
+FILESNAME=$(PROG)
+FILESDIR= /etc/system.conf.d
+
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
--- /dev/null
+
+service dec21140A
+{
+ type net;
+ descr "DEC Tulip 21140A in VirtualPC";
+ system
+ UMAP # 14
+ IRQCTL # 19
+ DEVIO # 21
+ ;
+ pci device 1011/0009;
+ ipc
+ SYSTEM pm rs log tty ds vm
+ pci inet lwip
+ ;
+};
+
PROG= e1000
SRCS= e1000.c
+FILES=$(PROG).conf
+FILESNAME=$(PROG)
+FILESDIR= /etc/system.conf.d
+
DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -lnetdriver -lsys -ltimers
--- /dev/null
+service e1000
+{
+ type net;
+ descr "Intel PRO/1000 Gigabit";
+ system
+ UMAP # 14
+ IRQCTL # 19
+ DEVIO # 21
+ ;
+ pci device 8086/100e;
+ pci device 8086/107c;
+ pci device 8086/10cd;
+ pci device 8086/10d3;
+ pci device 8086/10de;
+ pci device 8086/105e;
+ ipc
+ SYSTEM pm rs log tty ds vm
+ pci inet lwip ;
+};
+
PROG= fxp
SRCS= fxp.c mii.c
+FILES=$(PROG).conf
+FILESNAME=$(PROG)
+FILESDIR= /etc/system.conf.d
+
DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -lnetdriver -lsys -ltimers
--- /dev/null
+
+service fxp
+{
+ type net;
+ descr "Intel PRO/100";
+ system
+ UMAP # 14
+ IRQCTL # 19
+ DEVIO # 21
+ ;
+ pci device 8086/1031;
+ pci device 8086/1032;
+ pci device 8086/103d;
+ pci device 8086/1064;
+ pci device 8086/1229;
+ pci device 8086/2449;
+ ipc
+ SYSTEM pm rs log tty ds vm
+ pci inet lwip amddev
+ ;
+};
+
PROG= lance
SRCS= lance.c
+FILES=$(PROG).conf
+FILESNAME=$(PROG)
+FILESDIR= /etc/system.conf.d
+
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
LDADD+= -lnetdriver -lsys
--- /dev/null
+
+service lance
+{
+ type net;
+ descr "AMD LANCE (also emulated by VMWare and VirtualBox)";
+ system
+ UMAP # 14
+ IRQCTL # 19
+ DEVIO # 21
+ ;
+ pci device 1022/2000;
+ uid 0;
+};
+
PROG= rtl8139
SRCS= rtl8139.c liveupdate.c
+FILES=$(PROG).conf
+FILESNAME=$(PROG)
+FILESDIR= /etc/system.conf.d
+
DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -lnetdriver -lsys -ltimers
--- /dev/null
+service rtl8139
+{
+ type net;
+ descr "Realtek 8139 based card";
+ system
+ UMAP # 14
+ IRQCTL # 19
+ DEVIO # 21
+ ;
+ pci device 10ec/8139;
+ pci device 02ac/1012;
+ pci device 1065/8139;
+ pci device 1113/1211;
+ pci device 1186/1300;
+ pci device 1186/1340;
+ pci device 11db/1234;
+ pci device 1259/a117;
+ pci device 1259/a11e;
+ pci device 126c/1211;
+ pci device 13d1/ab06;
+ pci device 1432/9130;
+ pci device 14ea/ab06;
+ pci device 14ea/ab07;
+ pci device 1500/1360;
+ pci device 1743/8139;
+ pci device 4033/1360;
+ ipc
+ SYSTEM pm rs log tty ds vm
+ pci inet lwip amddev
+ ;
+};
+
PROG= rtl8169
SRCS= rtl8169.c
+FILES=$(PROG).conf
+FILESNAME=$(PROG)
+FILESDIR= /etc/system.conf.d
+
DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS}
LDADD+= -lnetdriver -lsys -ltimers
--- /dev/null
+
+service rtl8169
+{
+ type net;
+ descr "Realtek 8169 based card";
+ system
+ UMAP # 14
+ IRQCTL # 19
+ DEVIO # 21
+ ;
+ pci device 10ec/8129;
+ pci device 10ec/8167;
+ pci device 10ec/8169;
+ pci device 10ec/8168;
+ pci device 1186/4300;
+ pci device 1259/c107;
+ pci device 1385/8169;
+ pci device 16ec/0116;
+ pci device 1737/1032;
+ ipc
+ SYSTEM pm rs log tty ds vm
+ pci inet lwip amddev
+ ;
+};
+
ETC=/etc/
USR=/usr/
USRETC=/usr/etc/
+DEFAULTS=/etc/defaults
FILES1=group hostname.file inet.conf motd.install mtab profile \
protocols rc services termcap ttytab utmp rc.cd binary_sizes \
binary_sizes.big binary_sizes.xxl syslog.conf rc.daemons.dist \
PWFILES=master.passwd
FILES3=daily dhcptags.conf rc
+DEFAULTFILES=minix.rc.conf
USRFILES=Makefile
TOOL_PWD_MKDB= pwd_mkdb
@echo "Making hierarchy.."
sh mtree.sh mtree/minix.tree
@for f in $(FILES3); do if [ -f $(USRETC)/$$f ]; then :; else cp usr/$$f $(USRETC); chmod 755 $(USRETC)/$$f; fi; done
+ for f in $(DEFAULTFILES); do cp $$f $(DEFAULTS); chmod 644 $(DEFAULTS)/$$f; done
@echo "Making devices.."
p=`pwd` && cd /dev && sh $$p/../commands/MAKEDEV/MAKEDEV.sh null
p=`pwd` && cd /dev && sh $$p/../commands/MAKEDEV/MAKEDEV.sh std 2>/dev/null
--- /dev/null
+# Minix-specific rc.conf default values
+
+# Where to find servers/drivers binaries
+PKG_SERVICE_DIR=/usr/pkg/minixservices
+SERVICES_DIRS="/usr/sbin $PKG_SERVICE_DIR"
+
+# Where to find system.conf files and system.conf.d directories
+# for servers/drivers
+SYSTEM_CONF_SUBDIR=system.conf.d
+PKG_SYSTEM_CONF_DIR=/usr/pkg/etc
+SYSTEM_CONF_DIRS="/etc $PKG_SYSTEM_CONF_DIR"
755 root operator /dev
/dev/mouse -> /dev/kbdaux
755 root operator /etc
+755 root operator /etc/defaults
755 root operator /etc/system.conf.d
755 root operator /boot
755 root operator /boot/image
. /etc/defaults/rc.conf
fi
+if [ -r /etc/defaults/minix.rc.conf ]; then
+ . /etc/defaults/minix.rc.conf
+fi
+
# If this is not set to YES, the system will drop into single-user mode.
# (Doesn't matter for Minix.)
rc_configured=NO
uid 0;
};
-service lance
-{
- system
- UMAP # 14
- IRQCTL # 19
- DEVIO # 21
- ;
- pci device 1022/2000;
- uid 0;
-};
-
-service rtl8139
-{
- system
- UMAP # 14
- IRQCTL # 19
- DEVIO # 21
- ;
- pci device 10ec/8139;
- pci device 02ac/1012;
- pci device 1065/8139;
- pci device 1113/1211;
- pci device 1186/1300;
- pci device 1186/1340;
- pci device 11db/1234;
- pci device 1259/a117;
- pci device 1259/a11e;
- pci device 126c/1211;
- pci device 13d1/ab06;
- pci device 1432/9130;
- pci device 14ea/ab06;
- pci device 14ea/ab07;
- pci device 1500/1360;
- pci device 1743/8139;
- pci device 4033/1360;
- ipc
- SYSTEM pm rs log tty ds vm
- pci inet lwip amddev
- ;
-};
-
-service fxp
-{
- system
- UMAP # 14
- IRQCTL # 19
- DEVIO # 21
- ;
- pci device 8086/1031;
- pci device 8086/1032;
- pci device 8086/103d;
- pci device 8086/1064;
- pci device 8086/1229;
- pci device 8086/2449;
- ipc
- SYSTEM pm rs log tty ds vm
- pci inet lwip amddev
- ;
-};
-
service inet
{
uid 0;
uid 0;
};
-service rtl8169
-{
- system
- UMAP # 14
- IRQCTL # 19
- DEVIO # 21
- ;
- pci device 10ec/8129;
- pci device 10ec/8167;
- pci device 10ec/8169;
- pci device 10ec/8168;
- pci device 1186/4300;
- pci device 1259/c107;
- pci device 1385/8169;
- pci device 16ec/0116;
- pci device 1737/1032;
- ipc
- SYSTEM pm rs log tty ds vm
- pci inet lwip amddev
- ;
-};
-
service filter
{
ipc
;
};
-service e1000
-{
- system
- UMAP # 14
- IRQCTL # 19
- DEVIO # 21
- ;
- pci device 8086/100e;
- pci device 8086/107c;
- pci device 8086/10cd;
- pci device 8086/10d3;
- pci device 8086/10de;
- pci device 8086/105e;
- ipc
- SYSTEM pm rs log tty ds vm
- pci inet lwip ;
-};
-
-service atl2
-{
- system
- UMAP # 14
- IRQCTL # 19
- ;
- pci device 1969/2048;
- ipc
- SYSTEM pm rs tty ds vm
- pci inet lwip
- ;
-};
-
-service dec21140A
-{
- system
- UMAP # 14
- IRQCTL # 19
- DEVIO # 21
- ;
- pci device 1011/0009;
- ipc
- SYSTEM pm rs log tty ds vm
- pci inet lwip
- ;
-};
-
service hello
{
system
RANDOM_FILE=/usr/adm/random.dat
LOCAL_FILE=/usr/etc/rc.local
+# Get $SERVICES_DIRS
+. /etc/rc.conf
+
+# Directories to find services in
+if [ ! "$SERVICES_DIRS" ]
+then SERVICES_DIRS=/usr/sbin
+fi
+
case "$#:$1" in
1:start|1:stop|1:down)
action=$1
if disabled $service; then return; fi
# Service is not disabled. Try to bring it up.
- echo -n " $service"
- service $opt up /usr/sbin/$service "$@"
+ found=""
+ for dir in $SERVICES_DIRS
+ do bin=$dir/$service
+ if [ -x $bin -a -z "$found" ]
+ then service $opt up $bin "$@"
+ echo -n " $service"
+ found=yes
+ fi
+ done
+ if [ -z "$found" ]
+ then echo " ($service not found in $SERVICES_DIRS)"
+ fi
}
get_eth_labels() {
#define _PATH_SERVICE "/bin/service"
#define _PATH_SYSTEM_CONF "/etc/system.conf"
#define _PATH_SYSTEM_CONF_DIR "/etc/system.conf.d"
+#define _PATH_SYSTEM_CONF_PKG_DIR "/usr/pkg/etc/system.conf.d"
/* Provide trailing slash, since mostly used for building pathnames. */
#define _PATH_DEV "/dev/"
#define _PATH_SYSTEM_CONF "/etc/system.conf"
#define _PATH_SYSTEM_CONF_DIR "/etc/system.conf.d"
+#define _PATH_SYSTEM_CONF_PKG_DIR "/usr/pkg/etc/system.conf.d"
#define _PATH_DHCPCONF "/etc/dhcp.conf"
#define _PATH_DHCPPID "/usr/run/dhcpd.pid"