vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

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:
Msrc/9vx/a/lib.h | 1+
Msrc/9vx/conf.c | 272++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/9vx/conf.h | 26+++++++++++---------------
Msrc/9vx/devfs-posix.c | 4++--
Msrc/9vx/main.c | 139+++++++++++++++++++++++++++----------------------------------------------------
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();