⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edparams.c

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	edparams 1.17 - Modify boot parameters		Author: Kees J. Bot
 *								20 May 1992
 */

#define nil 0
#define _POSIX_SOURCE	1
#define _MINIX		1
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <termios.h>

/* The Minix boot block must start with these bytes: */
char boot_magic[] = { 0x31, 0xC0, 0x8E, 0xD8, 0xFA, 0x8E, 0xD0, 0xBC };

#define SECTOR_SIZE	512

#define PARAMSEC	1	/* Sector containing boot parameters. */

#define ESC		1234	/* Escape key (interrupt). */

int device;			/* Device to edit parameters. */
char *devname;			/* Name of device. */

struct termios termbuf;
int istty= 1;

void report(char *label)
/* edparams: label: No such file or directory */
{
	fprintf(stderr, "edparams: %s: %s\n", label, strerror(errno));
}

void fatal(char *label)
{
	report(label);
	exit(1);
}

void *alloc(void *m, size_t n)
{
	m= m == nil ? malloc(n) : realloc(m, n);
	if (m == nil) fatal("");
	return m;
}

char null[]= "";	/* This kludge saves lots of memory. */

void sfree(char *s)
/* Free a non-null string. */
{
	if (s != nil && s != null) free(s);
}

char *copystr(char *s)
/* Copy a non-null string using malloc. */
{
	char *c;

	if (*s == 0) return null;
	c= alloc(nil, (strlen(s) + 1) * sizeof(char));
	strcpy(c, s);
	return c;
}

int getch(void)
{
	char c;

	switch (read(0, &c, 1)) {
	case -1:
		if (errno != EINTR) fatal("");
		return(ESC);
	case 0:
		if (istty) putchar('\n');
		exit(0);
	default:
		return c & 0xFF;
	}
}

/* Sticky attributes. */
#define E_SPECIAL	0x01	/* These are known to the program. */
#define E_DEV		0x02	/* The value is a device name. */
#define E_RESERVED	0x04	/* May not be set by user, e.g. 'boot' */
#define E_STICKY	0x07	/* Don't go once set. */
/* Volatile attributes. */
#define E_VAR		0x08	/* Variable */
#define E_FUNCTION	0x10	/* Function definition. */

typedef struct environment {
	struct environment *next;
	char	flags;
	char	*name;
	char	*arg;
	char	*value;
	char	*defval;	/* Safehouse for default values. */
} environment;

environment *env;		/* Lists the environment. */

#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))
#define arraylimit(a)	((a) + arraysize(a))

char *readline(void)
/* Read a line including a newline with echoing. */
{
	char *line;
	size_t i, z;
	int c;

	i= 0;
	z= 20;
	line= alloc(nil, z * sizeof(char));

	do {
		c= getch();

		if (c < ' ' && c != '\n') {
			printf("\7Don't use control characters!\n");
			while ((c= getch()) != '\n') {}
			i= 0;
		} else {
			line[i++]= c;
			if (i == z) {
				z*= 2;
				line= alloc(line, z * sizeof(char));
			}
		}
	} while (c != '\n');
	line[i]= 0;
	return line;
}

int sugar(char *tok)
/* Recognize special tokens. */
{
	return strchr("=(){};\n", tok[0]) != nil;
}

char *onetoken(char **aline, int arg)
/* Returns a string with one token for tokenize.  Arg is true when reading
 * between ( and ).
 */
{
	char *line= *aline;
	size_t n;
	char *tok;

	/* Skip spaces and runs of newlines. */
	while (*line == ' ' || (*line == '\n' && line[1] == '\n')) line++;

	*aline= line;

	/* Don't do odd junk (nor the terminating 0!). */
	if ((unsigned) *line < ' ' && *line != '\n') return nil;

	if (arg) {
		/* Function argument, anything goes except ). */
		int depth= 0;

		while ((unsigned) *line >= ' ') {
			if (*line == '(') depth++;
			if (*line == ')' && --depth < 0) break;
			line++;
		}
		while (line > *aline && line[-1] == ' ') line--;
	} else
	if (sugar(line)) {
		/* Single character token. */
		line++;
	} else {
		/* Multicharacter token. */
		do line++; while ((unsigned) *line > ' ' && !sugar(line));
	}
	n= line - *aline;
	tok= alloc(nil, (n + 1) * sizeof(char));
	memcpy(tok, *aline, n);
	tok[n]= 0;
	if (tok[0] == '\n') tok[0]= ';';	/* ';' same as '\n' */

	*aline= line;
	return tok;
}

/* Typed commands form strings of tokens. */

typedef struct token {
	struct token	*next;	/* Next in a command chain. */
	char		*token;
} token;

token **tokenize(token **acmds, char *line, int *fundef)
/* Takes a line apart to form tokens.  The tokens are inserted into a command
 * chain at *acmds.  Tokenize returns a reference to where another line could
 * be added.  The fundef variable holds the state tokenize is in when decoding
 * a multiline function definition.  It is nonzero when more must be read.
 * Tokenize looks at spaces as token separators, and recognizes only
 * ';', '=', '(', ')' '{', '}', and '\n' as single character tokens.
 */
{
	int fd= *fundef;
	char *tok;
	token *newcmd;
	static char funsugar[]= { '(', 0, ')', '{', '}' };

	while ((tok= onetoken(&line, fd == 1)) != nil) {
		if (fd == 1) {
			fd++;	/* Function argument. */
		} else
		if (funsugar[fd] == tok[0]) {
			/* Recognize next token as part of a function def. */
			fd= tok[0] == '}' ? 0 : fd + 1;
		} else
		if (fd != 0) {
			if (tok[0] == ';' && fd == 3) {
				/* Kill separator between ')' and '{'. */
				free(tok);
				continue;
			}
			/* Syntax error unless between '{' and '}'. */
			if (fd != 4) fd= 0;
		}
		newcmd= alloc(nil, sizeof(*newcmd));
		newcmd->token= tok;
		newcmd->next= *acmds;
		*acmds= newcmd;
		acmds= &newcmd->next;
	}
	*fundef= fd;
	return acmds;
}

token *cmds;		/* String of commands to execute. */
int err;		/* Set on an error. */

char *poptoken(void)
/* Pop one token off the command chain. */
{
	token *cmd= cmds;
	char *tok= cmd->token;

	cmds= cmd->next;
	free(cmd);

	return tok;
}

void voidtoken(void)
/* Remove one token from the command chain. */
{
	free(poptoken());
}

int trapsig;

void trap(int sig)
{
	trapsig= sig;
	signal(sig, trap);
	alarm(1);
}

void interrupt(void)
/* Clean up after an ESC has been typed. */
{
	printf("[ESC]\n");
	trapsig= 0;
	err= 1;
}

int is_default(environment *e)
{
	return (e->flags & E_SPECIAL) && e->defval == nil;
}

environment **searchenv(char *name)
{
	environment **aenv= &env;

	while (*aenv != nil && strcmp((*aenv)->name, name) != 0) {
		aenv= &(*aenv)->next;
	}

	return aenv;
}

#define b_getenv(name)	(*searchenv(name))
/* Return the environment *structure* belonging to name, or nil if not found. */

char *b_value(char *name)
/* The value of a variable. */
{
	environment *e= b_getenv(name);

	return e == nil || !(e->flags & E_VAR) ? nil : e->value;
}

char *b_body(char *name)
/* The value of a function. */
{
	environment *e= b_getenv(name);

	return e == nil || !(e->flags & E_FUNCTION) ? nil : e->value;
}

int b_setenv(int flags, char *name, char *arg, char *value)
/* Change the value of an environment variable.  Returns the flags of the
 * variable if you are not allowed to change it, 0 otherwise.
 */
{
	environment **aenv, *e;

	if (*(aenv= searchenv(name)) == nil) {
		e= alloc(nil, sizeof(*e));
		e->name= copystr(name);
		e->flags= flags;
		e->defval= nil;
		e->next= nil;
		*aenv= e;
	} else {
		e= *aenv;

		/* Don't touch reserved names and don't change special
		 * variables to functions or vv.
		 */
		if (e->flags & E_RESERVED || (e->flags & E_SPECIAL
			&& (e->flags & E_FUNCTION) != (flags & E_FUNCTION)
		)) return e->flags;

		e->flags= (e->flags & E_STICKY) | flags;
		if (is_default(e)) {
			e->defval= e->value;
		} else {
			sfree(e->value);
		}
		sfree(e->arg);
	}
	e->arg= copystr(arg);
	e->value= copystr(value);
	return 0;
}

int b_setvar(int flags, char *name, char *value)
/* Set variable or simple function. */
{
	return b_setenv(flags, name, null, value);
}

void b_unset(char *name)
/* Remove a variable from the environment.  A special variable is reset to
 * its default value.
 */
{
	environment **aenv, *e;

	if ((e= *(aenv= searchenv(name))) == nil) return;

	if (e->flags & E_SPECIAL) {
		if (e->defval != nil) {
			sfree(e->arg);
			e->arg= null;
			sfree(e->value);
			e->value= e->defval;
			e->defval= nil;
		}
	} else {
		sfree(e->name);
		sfree(e->arg);
		sfree(e->value);
		*aenv= e->next;
		free(e);
	}
}

#define between(a, c, z)	((unsigned) ((c) - (a)) <= ((z) - (a)))

long a2l(char *a)
/* Cheap atol(). */
{
	int sign= 1;
	long n= 0;

	if (*a == '-') { sign= -1; a++; }

	while (between('0', *a, '9')) n= n * 10 + (*a++ - '0');

	return sign * n;
}

char *ul2a(u32_t n)
/* Transform a long number to ascii digits. */
{
	static char num[3 * sizeof(n)];
	char *a= arraylimit(num) - 1;

	do *--a = (n % 10) + '0'; while ((n/= 10) > 0);
	return a;
}

char *u2a(U16_t n)
/* Transform a short number to ascii digits. */
{
	return ul2a(n);
}

void get_parameters(void)
{
	char params[SECTOR_SIZE + 1];
	token **acmds;
	int fundef= 0;

	/* Variables that Minix needs: */
	b_setvar(E_SPECIAL|E_VAR|E_DEV, "rootdev", "ram");
	b_setvar(E_SPECIAL|E_VAR|E_DEV, "ramimagedev", "bootdev");
	b_setvar(E_SPECIAL|E_VAR, "ramsize", "0");
	b_setvar(E_SPECIAL|E_VAR, "processor", "?");
	b_setvar(E_SPECIAL|E_VAR, "bus", "?");
	b_setvar(E_SPECIAL|E_VAR, "memsize", "?");
	b_setvar(E_SPECIAL|E_VAR, "emssize", "?");
	b_setvar(E_SPECIAL|E_VAR, "video", "?");
	b_setvar(E_SPECIAL|E_VAR, "chrome", "?");

	/* Variables boot needs: */
	b_setvar(E_SPECIAL|E_VAR, "image", "minix");
	b_setvar(E_SPECIAL|E_FUNCTION, "main", "menu");

	/* Default menu function: */
	b_setenv(E_RESERVED|E_FUNCTION, "\1", "=,Start Minix", "boot");

	/* Reserved names: */
	b_setvar(E_RESERVED|E_VAR, "bootdev", null);
	b_setvar(E_RESERVED, "boot", null);
	b_setvar(E_RESERVED, "menu", null);
	b_setvar(E_RESERVED, "set", null);
	b_setvar(E_RESERVED, "unset", null);
	b_setvar(E_RESERVED, "save", null);
	b_setvar(E_RESERVED, "ls", null);
	b_setvar(E_RESERVED, "echo", null);
	b_setvar(E_RESERVED, "trap", null);
	b_setvar(E_RESERVED, "help", null);
	b_setvar(E_RESERVED, "exit", null);

	memset(params, 0, sizeof(params));

	/* Tokenize bootparams sector. */
	if (lseek(device, PARAMSEC * SECTOR_SIZE, SEEK_SET) < 0
				|| read(device, params, SECTOR_SIZE) < 0)
		fatal(devname);
	else {
		acmds= tokenize(&cmds, params, &fundef);

		/* Syntax check */
		(void) tokenize(acmds, ":;", &fundef);
	}
}

char *addptr;

void addparm(char *n)
{
	while (*n != 0 && *addptr != 0) *addptr++ = *n++;
}

void save_parameters(void)
/* Save nondefault environment variables to the bootparams sector. */
{
	environment *e;
	char params[SECTOR_SIZE + 1];

	/* Default filling: */
	memset(params, '\n', SECTOR_SIZE);

	/* Don't touch the 0! */
	params[SECTOR_SIZE]= 0;
	addptr= params;

	for (e= env; e != nil; e= e->next) {
		if (e->flags & E_RESERVED || is_default(e)) continue;

		addparm(e->name);
		if (e->flags & E_FUNCTION) {
			addparm("(");
			addparm(e->arg);
			addparm("){");
		} else {
			addparm((e->flags & (E_DEV|E_SPECIAL)) != E_DEV
							? "=" : "=d ");
		}
		addparm(e->value);
		if (e->flags & E_FUNCTION) addparm("}");
		if (*addptr == 0) {
			printf("The environment is too big\n");
			return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -