Messages in this thread Patch in this message |  | | From | (David Hinds) | Subject | Patch for 2.1.20 to try: "kernel environment" | Date | 5 Jan 1997 18:26:34 GMT |
| |
Here's an update to the kernel environment patch I posted the other day, that fixes a memory leak. Also I was told the original patch didn't go cleanly against 2.1.20. It's possible I posted a patch against 2.1.16 by mistake... in any case, this one is definitely for 2.1.20. I've also put the patch on hyper.stanford.edu in /pub/pcmcia/patches/kenv-2.1.20 just in case.
-- Dave Hinds
--- linux/init/main.c.orig Thu Jan 2 22:32:15 1997 +++ linux/init/main.c Sun Jan 5 10:29:47 1997 @@ -6,6 +6,7 @@ * GK 2/5/95 - Changed to support mounting root fs via NFS * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 + * Rewrite of boot parameter parsing - Dave Hinds, Dec '96 */ #define __KERNEL_SYSCALLS__ @@ -29,6 +30,7 @@ #include <linux/mm.h> #include <linux/major.h> #include <linux/blk.h> +#include <linux/malloc.h> #ifdef CONFIG_ROOT_NFS #include <linux/nfs_fs.h> #endif @@ -205,7 +207,6 @@ * Boot command-line arguments */ #define MAX_INIT_ARGS 8 -#define MAX_INIT_ENVS 8 extern void time_init(void); @@ -235,11 +236,65 @@ extern void dquot_init(void); static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; -static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; +char ** envp_init; static char * argv_rc[] = { "/bin/sh", NULL }; static char * envp_rc[] = { "HOME=/", "TERM=linux", NULL }; +char *getkenv(const char *name) +{ + char **s, *t; + int i; + for (s = envp_init; (t = *s); s++) { + for (i = 0; (t[i] != '=') && name[i]; i++) + if (t[i] != name[i]) break; + if ((t[i] == '=') && (name[i] == '\0')) + return t+i+1; + } + return NULL; +} + +int putkenv(const char *str) +{ + char **e, *s, *t; + int i, j; + unsigned long flags; + + if (strchr(str, '=') == NULL) + return -1; + /* See if the tag is already in the environment */ + for (i = 0; (t = envp_init[i]); i++) { + for (j = 0; (t[j] != '=') && (str[j] != '='); j++) + if (t[j] != str[j]) break; + if ((t[j] == '=') && (str[j] == '=')) + break; + } + if (!t) { + /* Extend the environment table if necessary */ + e = kmalloc((i+2) * sizeof(char *), GFP_KERNEL); + if (e == NULL) + return -1; + memcpy(e, envp_init, (i+1) * sizeof(char *)); + save_flags(flags); + cli(); + if ((unsigned long)envp_init > memory_start) + kfree(envp_init); + envp_init = e; + restore_flags(flags); + e[i+1] = NULL; + } + /* Copy the string to a safe place and add to table */ + s = kmalloc(strlen(str)+1, GFP_KERNEL); + if (s == NULL) + return -1; + strcpy(s, str); + envp_init[i] = s; + /* If the old string was kmalloc()ed, then free it */ + if (t && ((unsigned long)t > memory_start)) + kfree(t); + return 0; +} + char *get_options(char *str, int *ints) { char *cur = str; @@ -500,27 +555,25 @@ #endif -static int checksetup(char *line) +static void checksetup(char *line) { - int i = 0; + int i; int ints[11]; #ifdef CONFIG_BLK_DEV_IDE /* ide driver needs the basic string, rather than pre-processed values */ if (!strncmp(line,"ide",3) || (!strncmp(line,"hd",2) && line[2] != '=')) { ide_setup(line); - return 1; + return; } #endif - while (bootsetups[i].str) { + for (i = 0; bootsetups[i].str; i++) { int n = strlen(bootsetups[i].str); if (!strncmp(line,bootsetups[i].str,n)) { bootsetups[i].setup_func(get_options(line+n,ints), ints); - return 1; + return; } - i++; } - return 0; } /* this should be approx 2 Bo*oMips to start (note initial shift), and will @@ -636,88 +689,79 @@ * as appropriate. Any cmd-line option is taken to be an environment * variable if it contains the character '='. * - * - * This routine also checks for options meant for the kernel. - * These options are not given to init - they are for internal kernel use only. + * Options can be enclosed in quotation marks, and the backslash can + * be used to escape spaces and quotation marks. */ -static void parse_options(char *line) +static unsigned long parse_options(char *line, unsigned long memory_start) { - char *next; - int args, envs; + char *last, *next, *s; + int quot = 0, args, envs; - if (!*line) - return; - args = 0; - envs = 1; /* TERM is set to 'linux' by default */ - next = line; - while ((line = next) != NULL) { - if ((next = strchr(line,' ')) != NULL) - *next++ = 0; - /* - * check for kernel options first.. - */ - if (!strncmp(line,"root=",5)) { - parse_root_dev(line+5); - continue; - } -#ifdef CONFIG_ROOT_NFS - if (!strncmp(line, "nfsroot=", 8)) { - int n; - line += 8; - ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); - if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) { - strncpy(nfs_root_name, line, sizeof(nfs_root_name)); - nfs_root_name[sizeof(nfs_root_name)-1] = '\0'; + envp_init = (char **) memory_start; + envp_init[0] = "HOME=/"; + envp_init[1] = "TERM=linux"; + envs = 2; + args = 1; + for (;;) { + while (*line == ' ') line++; + if (*line == '\0') break; + /* Interpret quotes, backslashes */ + for (last = next = line; *next != '\0'; next++) { + if (*next == '"') { + quot = !quot; continue; } - n = strlen(line) + strlen(NFS_ROOT); - if (n >= sizeof(nfs_root_name)) - line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0'; - sprintf(nfs_root_name, NFS_ROOT, line); - continue; - } - if (!strncmp(line, "nfsaddrs=", 9)) { - line += 9; - strncpy(nfs_root_addrs, line, sizeof(nfs_root_addrs)); - nfs_root_addrs[sizeof(nfs_root_addrs)-1] = '\0'; - continue; + if (!quot && (*next == ' ')) + break; + if (*next == '\\') + next++; + *(last++) = *next; } -#endif - if (!strcmp(line,"ro")) { + if (*next != '\0') next++; + *last = '\0'; + if (strcmp(line, "ro") == 0) root_mountflags |= MS_RDONLY; - continue; - } - if (!strcmp(line,"rw")) { + else if (strcmp(line, "rw") == 0) root_mountflags &= ~MS_RDONLY; - continue; - } - if (!strcmp(line,"debug")) { + else if (strcmp(line, "debug") == 0) console_loglevel = 10; - continue; - } - if (!strncmp(line,"init=",5)) { - line += 5; - execute_command = line; - continue; - } - if (checksetup(line)) - continue; - /* - * Then check if it's an environment variable or - * an option. - */ - if (strchr(line,'=')) { - if (envs >= MAX_INIT_ENVS) - break; - envp_init[++envs] = line; + else if (strchr(line,'=')) { + envp_init[envs++] = line; + checksetup(line); } else { - if (args >= MAX_INIT_ARGS) + if (args > MAX_INIT_ARGS) break; - argv_init[++args] = line; + argv_init[args++] = line; + } + line = next; + } + argv_init[args] = NULL; + envp_init[envs] = NULL; + + if ((s = getkenv("root")) != NULL) + parse_root_dev(s); +#ifdef CONFIG_ROOT_NFS + if ((s = getkenv("nfsroot")) != NULL) { + int n; + ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); + if (s[0] == '/' || s[0] == ',' || (s[0] >= '0' && s[0] <= '9')) { + strncpy(nfs_root_name, s, sizeof(nfs_root_name)); + nfs_root_name[sizeof(nfs_root_name)-1] = '\0'; + } else { + n = strlen(s) + strlen(NFS_ROOT); + if (n >= sizeof(nfs_root_name)) + s[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0'; + sprintf(nfs_root_name, NFS_ROOT, s); } } - argv_init[args+1] = NULL; - envp_init[envs+1] = NULL; + if ((s = getkenv("nfsaddrs")) != NULL) { + strncpy(nfs_root_addrs, line, sizeof(nfs_root_addrs)); + nfs_root_addrs[sizeof(nfs_root_addrs)-1] = '\0'; + } +#endif + execute_command = getkenv("init"); + + return (memory_start + (envs+1) * sizeof(char *)); } @@ -843,7 +887,7 @@ init_IRQ(); sched_init(); time_init(); - parse_options(command_line); + memory_start = parse_options(command_line, memory_start); #ifdef CONFIG_MODULES init_modules(); #endif --- linux/kernel/ksyms.c.orig Wed Jan 1 22:09:13 1997 +++ linux/kernel/ksyms.c Fri Jan 3 23:55:34 1997 @@ -70,7 +70,6 @@ #include <linux/smp.h> #endif -extern char *get_options(char *str, int *ints); extern void set_device_ro(int dev,int flag); extern struct file_operations * get_blkfops(unsigned int); extern void blkdev_release(struct inode * inode); @@ -93,6 +92,8 @@ #ifdef CONFIG_KERNELD EXPORT_SYMBOL(kerneld_send); #endif +EXPORT_SYMBOL(getkenv); +EXPORT_SYMBOL(putkenv); EXPORT_SYMBOL(get_options); #ifdef CONFIG_PCI --- linux/include/linux/kernel.h.orig Sun Dec 1 01:06:55 1996 +++ linux/include/linux/kernel.h Fri Jan 3 23:54:36 1997 @@ -62,6 +62,10 @@ #define pr_info(fmt,arg...) \ printk(KERN_INFO fmt,##arg) +extern char *get_options(char *str, int *ints); +extern char *getkenv(const char *name); +extern int putkenv(const char *str); + /* * "suser()" checks against the effective user id, while "fsuser()" * is used for file permission checking and checks against the fsuid.. --- linux/include/linux/proc_fs.h.orig Wed Jan 1 22:08:27 1997 +++ linux/include/linux/proc_fs.h Fri Jan 3 23:56:23 1997 @@ -46,7 +46,8 @@ PROC_MD, PROC_RTC, PROC_LOCKS, - PROC_ZORRO + PROC_ZORRO, + PROC_KENV }; enum pid_directory_inos { --- linux/fs/proc/array.c.orig Wed Jan 1 22:08:20 1997 +++ linux/fs/proc/array.c Fri Jan 3 23:54:36 1997 @@ -322,6 +322,16 @@ return sprintf(buffer, "%s\n", saved_command_line); } +static int get_kenv(char * buffer) +{ + extern char **envp_init; + char **p; + int len = 0; + for (p = envp_init; *p; p++) + len += sprintf(buffer+len, "%s\n", *p); + return len; +} + static struct task_struct ** get_task(pid_t pid) { struct task_struct ** p; @@ -1081,6 +1091,9 @@ #endif case PROC_CMDLINE: return get_cmdline(page); + + case PROC_KENV: + return get_kenv(page); case PROC_MTAB: return get_filesystem_info( page ); --- linux/fs/proc/root.c.orig Wed Jan 1 22:08:21 1997 +++ linux/fs/proc/root.c Fri Jan 3 23:54:36 1997 @@ -496,6 +496,10 @@ PROC_CMDLINE, 7, "cmdline", S_IFREG | S_IRUGO, 1, 0, 0, }; +static struct proc_dir_entry proc_root_kenv = { + PROC_KENV, 6, "kenv", + S_IFREG | S_IRUGO, 1, 0, 0, +}; #ifdef CONFIG_RTC static struct proc_dir_entry proc_root_rtc = { PROC_RTC, 3, "rtc", @@ -562,6 +566,7 @@ proc_register(&proc_root, &proc_root_dma); proc_register(&proc_root, &proc_root_ioports); proc_register(&proc_root, &proc_root_cmdline); + proc_register(&proc_root, &proc_root_kenv); #ifdef CONFIG_RTC proc_register(&proc_root, &proc_root_rtc); #endif
|  |