commit 91f17a2007af56e7a849bc5ea5f6f2d06c9f5185
parent e399db13cacb63f1a2c362e2548b6a4afd16e9f9
Author: Jesus Galan Lopez (yiyus) <yiyu.jgl@gmail.com>
Date: Fri, 24 Sep 2010 01:15:13 +0200
new option parsing
Diffstat:
5 files changed, 205 insertions(+), 237 deletions(-)
diff --git a/src/9vx/a/lib.h b/src/9vx/a/lib.h
@@ -22,6 +22,7 @@ extern char* cleanname(char*);
extern ulong getcallerpc(void*);
extern int getfields(char*, char**, int, int, char*);
+extern int gettokens(char *, char **, int , char *);
extern int tokenize(char*, char**, int);
extern int dec64(uchar*, int, char*, int);
diff --git a/src/9vx/conf.c b/src/9vx/conf.c
@@ -12,36 +12,55 @@
#include "etherif.h"
#include "vether.h"
-/*
- * read configuration file
- */
-int
-readini(char *fn)
+char filebuf[BOOTARGSLEN];
+
+void
+setinioptions()
{
- int blankline, incomment, inspace, n, fd;
- static int nfields = 0;
- static char *buf = inibuf;
- char *cp, *p, *q;
+ static int i;
+ char *name, *value;
- if(strcmp(fn, "-") == 0)
- fd = fileno(stdin);
- else if((fd = open(fn, OREAD)) < 0)
- return -1;
+ for(; i < MAXCONF; i++){
+ if(!inifield[i])
+ break;
+ name = inifield[i];
+ if(*name == '*')
+ name++;
+ value = strchr(inifield[i], '=');
+ if(value == 0)
+ continue;
+ *value++ = 0;
+ if(strcmp(name, "cpulimit") == 0)
+ cpulimit = atoi(value);
+ else if(strcmp(name, "memsize") == 0)
+ memsize = atoi(value);
+ else if(strcmp(name, "canopenfiles") == 0)
+ canopen = value;
+ else if(strcmp(name, "ether") == 0)
+ //addether(name, value);
+ value = value;
+ else if(strcmp(name, "initarg") == 0)
+ initarg = value;
+ else if(strcmp(name, "localroot") == 0)
+ localroot = value;
+ else if(strcmp(name, "user") == 0)
+ username = value;
+ *(--value) = '=';
+ }
+}
- cp = buf;
- *buf = 0;
- while((n = read(fd, buf, BOOTARGSLEN-1)) > 0)
- if(n<0)
- return -1;
- else
- buf += n;
- close(fd);
- *buf = 0;
+void
+addini(char *buf)
+{
+ static int n = 0;
+ int blankline, incomment, inspace, inquote;
+ char *p, *q;
/*
* Strip out '\r', change '\t' -> ' '.
* Change runs of spaces into single spaces.
* Strip out trailing spaces, blank lines.
+ * The text between single quotes is not touched.
*
* We do this before we make the copy so that if we
* need to change the copy, it is already fairly clean.
@@ -49,10 +68,18 @@ readini(char *fn)
* padded with lots of trailing spaces, as is the case
* for those created during a distribution install.
*/
- p = cp;
+ p = buf;
blankline = 1;
- incomment = inspace = 0;
- for(q = cp; *q; q++){
+ incomment = inquote =inspace = 0;
+ for(q = buf; *q; q++){
+ if(inquote){
+ if(*q == '\'')
+ inquote = 0;
+ *p++ = *q;
+ continue;
+ }
+ if(!incomment && *q == '\'')
+ inquote = 1;
if(*q == '\r')
continue;
if(*q == '\t')
@@ -81,99 +108,103 @@ readini(char *fn)
if(!incomment)
*p++ = *q;
}
- if(p > cp && p[-1] != '\n')
+ if(p > buf && p[-1] != '\n')
*p++ = '\n';
*p++ = 0;
- nfields += gettokens(cp, &iniline[nfields], MAXCONF-nfields, "\n");
-
- return 0;
+ n += gettokens(buf, &inifield[n], MAXCONF-n, "\n");
+ setinioptions();
}
-void
-inifields(void (*fp)(char*, char*))
+int
+addinifile(char *file)
{
- int i;
- char *cp;
- char *cq;
+ static char *fb = filebuf;
+ char *buf;
+ int n, fd;
- for(i = 0; i < MAXCONF; i++){
- if(!iniline[i])
- break;
- cp = strchr(iniline[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(*cp == '\''){
- cp++;
- if((cq = strrchr(cp, '\'')) > 0)
- *cq = 0;
- }
- if(cp - iniline[i] >= NAMELEN+1)
- *(iniline[i]+NAMELEN-1) = 0;
- (fp)(iniline[i], cp);
- *(cp-1) = '=';
- }
+ if(strcmp(file, "-") == 0)
+ fd = fileno(stdin);
+ else if((fd = open(file, OREAD)) < 0)
+ return -1;
+
+ buf = fb;
+ *buf = 0;
+ while((n = read(fd, buf, BOOTARGSLEN-1)) > 0)
+ if(n<0)
+ return -1;
+ else
+ buf += n;
+ close(fd);
+ *buf = 0;
+ addini(fb);
+ fb = buf;
+ return n;
}
-void
-iniopt(char *name, char *value)
-{
- char *cp, *vedev;
- int vetap;
-
- if(*name == '*')
- name++;
- if(strcmp(name, "nofork") == 0)
- nofork = 1;
- else if(strcmp(name, "nogui") == 0){
- nogui = 1;
- usetty = 1;
+char*
+fullpath(char *root) {
+ char cwd[1024];
+
+ if(root[0] != '/'){
+ if(getcwd(cwd, sizeof cwd) == nil)
+ panic("getcwd: %r");
+ root = cleanname(smprint("%s/%s", cwd, root));
}
- else if(strcmp(name, "initrc") == 0)
- initrc = 1;
- else if(strcmp(name, "usetty") == 0)
- usetty = 1;
- else if(strcmp(name, "cpulimit") == 0)
- cpulimit = atoi(value);
- else if(strcmp(name, "memsize") == 0)
- memmb = atoi(value);
- else if(strcmp(name, "netdev") == 0){
- if(strncmp(value, "tap", 3) == 0) {
- vetap = 1;
- value += 4;
- }
- vedev = value;
- cp = vedev;
- if((value = strchr(vedev, ' ')) != 0){
- cp = strchr(value+1, '=');
- *value=0;
- *cp=0;
- }
- addve(*vedev == 0 ? nil : vedev, vetap);
- if(cp != vedev){
- iniopt(value+1, cp+1);
- *value=' ';
- *cp='=';
- }
+ return root;
+}
+
+/* poor man's quotestrdup to avoid needing quote.c */
+char*
+quoted(char *in) {
+ char *out, *p;
+ int i, n;
+
+ n = 0;
+ for(i = 0; i < strlen(in); i++)
+ if(in[i] == '\'')
+ n++;
+ out = malloc(strlen(in) + n + 2);
+ p = out;
+ if(*in != '\'')
+ *p++ = '\'';
+ for(i = 0; i < strlen(in); i++){
+ if(in[i] == '\'')
+ *p++ = in[i];
+ *p++ = in[i];
}
- else if(strcmp(name, "macaddr") == 0)
- setmac(value);
- else if(strcmp(name, "localroot") == 0 && !localroot)
- localroot = value;
- else if(strcmp(name, "allowed") == 0 && !allowed)
- allowed = value;
- else if(strcmp(name, "user") == 0 && !username)
- username = value;
- else if(strcmp(name, "initcmd") == 0 && !initcmd)
- initcmd = value;
+ *p++ = '\'';
+ *p = 0;
+ return out;
}
void
-inienv(char *name, char *value)
+setinienv()
{
- if(*name != '*')
+ int i;
+ char *name, *value;
+
+ for(i = 0; i < MAXCONF; i++){
+ if(!inifield[i])
+ break;
+ name = inifield[i];
+ value = strchr(inifield[i], '=');
+ if(*name == '*' || value == 0 || value[0] == 0)
+ continue;
+ *value++ = 0;
ksetenv(name, value, 0);
+ }
+ if(initarg){
+ if(*initarg != '\'')
+ initarg = quoted(initarg);
+ value = smprint("/386/init -t %s", initarg);
+ ksetenv("init", value, 0);
+ }
+ if(localroot){
+ value = smprint("local!#Z%s", fullpath(localroot));
+ ksetenv("nobootprompt", value, 0);
+ }
+ ksetenv("user", username, 0);
}
/*
@@ -184,30 +215,16 @@ printconfig(char *argv0){
int i;
print(argv0);
- if(inifile)
- print(" -p %s", inifile);
- if(nofork | nogui | initrc | usetty)
- print(" -%s%s%s%s", nofork ? "f " : "", nogui ? "g" : "",
- initrc ? "i " : "", usetty ? "t " : "");
- if(cpulimit != 0)
- print(" -l %d", cpulimit);
- if(memmb != 0)
- print(" -m %d", memmb);
- for(i=0; i<nve; i++){
- print(" -n %s", ve[i].tap ? "tap ": "");
- if(ve[i].dev != nil)
- print(" %s", ve[i].dev);
- if(ve[i].mac != nil)
- print(" -a %s", ve[i].mac);
+ if(usetty)
+ print(" -%c", nogui ? 'g' : 't');
+ for(i = 0; i < MAXCONF; i++){
+ if(!inifield[i])
+ break;
+ print("\t%s\n", inifield[i]);
}
- if(allowed && strcmp(allowed, "/") != 0)
- print(" -z %s", allowed);
+ if(initarg)
+ print("\tinit=/386/init -t %s\n", initarg);
if(localroot)
- print(" -r %s", localroot);
- print(" -u %s", username);
- if(initcmd)
- print(" -e %s", initcmd);
- for(i = 0; i < bootargc; i++)
- print(" %s", bootargv[i]);
- print("\n");
-}
-\ No newline at end of file
+ print("\tnobootprompt=#Z%s\n", localroot);
+ print("\tuser=%s\n", username);
+}
diff --git a/src/9vx/conf.h b/src/9vx/conf.h
@@ -2,24 +2,20 @@
#define BOOTARGSLEN (3584-0x200-BOOTLINELEN)
#define MAXCONF 100
-char inibuf[BOOTARGSLEN];
-char *iniline[MAXCONF];
-int cpulimit; /* max cpu usage */
-int initrc; /* run rc instead of init */
-int nofork; /* do not fork at init */
-int nogui; /* do not start the gui */
-int usetty; /* use tty for input/output */
-int memmb; /* memory size in mb */
+char *inifield[MAXCONF];
+int nofork;
+int nogui;
+int usetty;
+int cpulimit;
+int memsize;
int bootargc;
char** bootargv;
-char* initcmd;
-char* inifile;
+char* canopen;
+char* initarg;
char* localroot;
-char* allowed;
char* username;
-int readini(char *fn);
-void inifields(void (*fp)(char*, char*));
-void iniopt(char*, char*);
-void inienv(char*, char*);
+int addinifile(char*);
+void addini(char*);
void printconfig(char*);
+void setinienv();
diff --git a/src/9vx/devfs-posix.c b/src/9vx/devfs-posix.c
@@ -33,7 +33,7 @@ enum
FsChar = 'Z',
};
-extern char *allowed;
+extern char *canopen;
extern Path *addelem(Path*, char*, Chan*);
static char *uidtoname(int);
static char *gidtoname(int);
@@ -357,7 +357,7 @@ fsopen(Chan *c, int mode)
print("fsopen %s %#x\n", ufd->path->s, mode);
/* protect files whose path does not begin with allowed */
- if(strncmp(ufd->path->s, allowed, strlen(allowed)) != 0)
+ if(strncmp(ufd->path->s, canopen, strlen(canopen)) != 0)
error(Eperm);
if(mode & ~(OTRUNC|ORCLOSE|3))
diff --git a/src/9vx/main.c b/src/9vx/main.c
@@ -50,11 +50,7 @@ int abortonfault;
int nocpuload;
char* argv0;
char* conffile = "9vx";
-char* defaultroot = "local!/boot/rootfs.bz2";
-char* defaultinit = "\
-/386/bin/bind -a /386/bin /bin; \
-/386/bin/bind -a /rc/bin /bin; \
-/386/bin/rc -i";
+char* defaultboot = "local!/boot/rootfs.bz2";
Conf conf;
static Mach mach0;
@@ -69,13 +65,12 @@ static void siginit(void);
static void machkeyinit(void);
static char* getuser(void);
-static char* nobootprompt(char*);
void
usage(void)
{
// TODO(yy): add debug and other options by ron
- fprint(2, "usage: 9vx [-p file.ini] [-fgit] [-l cpulimit] [-m memsize] [-n [tap] netdev] [-a macaddr] [-z allowed] [-r root] [-u user] [-e initcmd] [bootargs]\n");
+ fprint(2, "usage: 9vx [-gt] [-f inifile | inifields ... ] [-i initarg] [-r localroot] [-u user]\n");
exit(1);
}
@@ -88,7 +83,7 @@ int
main(int argc, char **argv)
{
int vetap;
- char *vedev;
+ char *file;
/* Minimal set up to make print work. */
#ifndef TLS
@@ -99,14 +94,13 @@ main(int argc, char **argv)
quotefmtinstall();
cpulimit = 0;
- inifile = nil;
- memset(iniline, 0, MAXCONF);
- memmb = 0;
+ memset(inifield, 0, MAXCONF);
+ memsize = 256;
+ canopen = "/";
nogui = 0;
nofork = 0;
nve = 0;
usetty = 0;
- allowed = "/";
ARGBEGIN{
/* debugging options */
case '1':
@@ -118,6 +112,9 @@ main(int argc, char **argv)
case 'B':
abortonfault++;
break;
+ case 'F':
+ nofork = 1;
+ break;
case 'K':
tracekdev++;
break;
@@ -141,70 +138,56 @@ main(int argc, char **argv)
break;
/* real options */
- case 'a':
- setmac(EARGF(usage()));
- break;
- case 'e':
- initcmd = EARGF(usage());
- break;
- case 'f':
- nofork = 1;
- break;
case 'g':
nogui = 1;
usetty = 1;
break;
- case 'i':
- initrc = 1;
- break;
- case 'l':
- cpulimit = atoi(EARGF(usage()));
+ case 't':
+ usetty = 1;
break;
- case 'm':
- memmb = atoi(EARGF(usage()));
+ default:
+ goto iniargs;
+ }ARGEND
+
+iniargs:
+ while(argc > 0 && argv[0][0] != '-'){
+ addini(strdup(argv[0]));
+ argc--; argv++;
+ }
+ /*
+ * ARGBEGIN will do: argv++; argc--;
+ * but argv[0] is not argv0 now
+ */
+ argc++; argv--;
+ ARGBEGIN{
+ case 'f':
+ file = EARGF(usage());
+ if(addinifile(file) < 0)
+ panic("error reading config file %s", file);
break;
- case 'n':
- vetap = 0;
- vedev = ARGF();
- if(vedev != nil && strcmp(vedev, "tap") == 0){
- vetap = 1;
- vedev = ARGF();
+ case 'i':
+ /*
+ * Pass additional flag after -i is to init
+ * This is convenient for -ic and -im
+ */
+ if(_args[0] != 0){
+ initarg = smprint("-%c", _args[0]);
+ _args++;
}
- if(vedev == nil)
- usage();
- addve(vedev, vetap);
- break;
- case 'p':
- inifile = EARGF(usage());
+ else
+ initarg = EARGF(usage());
break;
case 'r':
localroot = EARGF(usage());
break;
- case 't':
- usetty = 1;
- break;
case 'u':
username = EARGF(usage());
break;
- case 'z':
- allowed = EARGF(usage());
- break;
default:
usage();
}ARGEND
-
- if(inifile != nil && readini(inifile) != 0)
- panic("error reading config file %s", inifile);
-
- bootargc = argc;
- bootargv = argv;
- /*
- * bootargs have preference over -r
- */
- if(bootargc > 0)
- localroot = nil;
-
- inifields(&iniopt);
+ if(argc > 0)
+ goto iniargs;
if(username == nil && (username = getuser()) == nil)
username = "tor";
@@ -212,7 +195,7 @@ main(int argc, char **argv)
if(eve == nil)
panic("strdup eve");
- mmusize(memmb);
+ mmusize(memsize);
mach0init();
mmuinit();
confinit();
@@ -276,18 +259,6 @@ main(int argc, char **argv)
return 0; // Not reached
}
-char*
-nobootprompt(char *root) {
- char cwd[1024];
-
- if(root[0] != '/'){
- if(getcwd(cwd, sizeof cwd) == nil)
- panic("getcwd: %r");
- root = cleanname(smprint("%s/%s", cwd, root));
- }
- return smprint("local!#Z%s", root);
-}
-
static char*
getuser(void)
{
@@ -457,7 +428,7 @@ bootargs(void *base)
for(i = 0; i < bootargc && ac < 32; i++)
av[ac++] = pusharg(bootargv[i]);
if(i == 0)
- av[ac++] = pusharg(defaultroot);
+ av[ac++] = pusharg(defaultboot);
/* 4 byte word align stack */
sp = (uchar*)((uintptr)sp & ~3);
@@ -527,26 +498,10 @@ init0(void)
ksetenv("cputype", "386", 0);
ksetenv("rootdir", "/root", 0);
ksetenv("service", "terminal", 0);
- ksetenv("user", username, 0);
ksetenv("sysname", "vx32", 0);
- inifields(&inienv);
-
- if(initrc != 0){
- if(localroot == nil && inifile == nil && bootargc == 0){
- ksetenv("nobootprompt", defaultroot, 0);
- ksetenv("initcmd", defaultinit, 0);
- ksetenv("init", "/386/bin/rc -c 'eval $initcmd", 0);
- }
- else
- ksetenv("init", "/386/init -tm", 0);
- }
- else if(initcmd){
- ksetenv("initcmd", initcmd, 0);
- ksetenv("init", "/386/init -t '. /rc/bin/termrc; home=/usr/$user;\
- test -d $home && cd; rc -c $initcmd; reboot'", 0);
- }
- if(localroot)
- ksetenv("nobootprompt", nobootprompt(localroot), 0);
+ ksetenv("init", "/386/init -t", 0);
+ ksetenv("user", username, 0);
+ setinienv();
poperror();