All pastes #1530737 Raw Edit

richard

public text v1 · immutable
#1530737 ·published 2009-08-15 18:50 UTC
rendered paste body
#include "api.h"#include "lib.h"// this one is going to be supporting multiple command lines etc.#define ALWAYS_REPORT_EXIT_CODE 0#define PROMPT "+>"#define BUF_LEN 256#define ARG_LEN 80#define ARG_MAX 20char curr_line[BUF_LEN];int line_len;typedef struct {	int len;	char buf[ARG_LEN];} argument;void append_arg(argument*arg,char c) {	arg->buf[arg->len++]=c;}void reset_arg(argument*arg) {	memset(arg,0,sizeof(arg));}argument args[ARG_MAX];int arg_count=0;void split_args() {	argument *curr_arg=args;	reset_arg(curr_arg);	curr_arg->len=0;	arg_count=0;	char *curr=curr_line;	char *end=curr_line+line_len;	while(curr!=end) {		switch(*curr) {			case 0: break;			case ';': case '&': // command seperators				if(curr_arg->len) {					curr_arg++;					reset_arg(curr_arg);					arg_count++;				}				append_arg(curr_arg,*curr);				++curr_arg;				reset_arg(curr_arg);				arg_count++;				break;			case ' ':				if(curr_arg->len) {					curr_arg++;					reset_arg(curr_arg);					arg_count++;				}				break;			default:				append_arg(curr_arg,*curr);				break;		}		++curr;	}	if(curr_arg->len)		arg_count++;}int read_line() {	for(int i=0;i<BUF_LEN;++i) {		char c = getch();		switch(c) {			case 0: // null byte, probably a keyboard key we've not mapped yet.				--i;				continue;			case 8: // backspace.				i-=2;				continue;			case '\n':				c=0;			default:				curr_line[i]=c;				break;		}		if(c==0) {			return line_len=i;		}	}	return -1;}typedef struct {	int background;	int count;	char* args[ARG_MAX];} execution_info;execution_info execinfo;int set_exec(int index,execution_info* info) {	int curr=0;	info->background=0;	info->count=0;	for(int i=0;i<ARG_MAX;++i) {		info->args[i]=0;	}	while(index<ARG_MAX) {		argument *arg=args+index;		if(arg->len) {			if(arg->len==1) {				if(arg->buf[0]==';') {					++index;					break;				} else if(arg->buf[0]=='&') {					info->background=1;					++index;					break;				}			}			info->args[curr++]=arg->buf;			info->count++;			index++;		} else break;	}	return index;}void run_program(execution_info* info) {	int program_fd =sys_open(info->args[0],0);	if(program_fd==-1) {		printf("No such program: %s - errno=%d\n",curr_line,errno);		return;	}	int retval=0;	int childpid=sys_fork();	switch(childpid) {		case -1: printf("Error forking: %d\n",childpid);				break;		case 0:			sys_exec(program_fd);			print("Could not execute program\n");			sys_exit(1);			// doesn't return...		default:			sys_close(program_fd);			if(info->background) {				printf("Running %d in background.\n",childpid);			}else{				sys_wait(&retval);				if(retval || ALWAYS_REPORT_EXIT_CODE)				printf("%s returned %d\n",curr_line,retval);			}			break;	}}int main(void) {	print("!rsh version 2. (C) Richard Whitty 2009\n");	for(;;) {		print(PROMPT);		flush();		int len=read_line();		if(len==-1) {			printf("\nLine too long!\n");			continue;		}		if(len==0)			continue;		if(strncmp(curr_line,"exit",5)==0) return 0;		split_args();// 		printf("Got %d args\n",arg_count);// 		for(int i=0;i<arg_count;++i) {// 			printf("args[%d]=%s\n",i,args[i].buf);// 		}// 		int com=0;		int x=0;		while(x<arg_count) {			x=set_exec(x,&execinfo);		//for(int x=set_exec(0,&execinfo);x<arg_count;x=set_exec(x,&execinfo)) {// 			printf("Command %d: %s\n",com++,execinfo.background?"Run in background":"Run in forground");// 			printf("x=%d - args=%d\n",x,arg_count);// 			for(int i=0;i<execinfo.count;++i) {// 				printf("Arg[%d]:%s\n",i,execinfo.args[i]);// 			}			run_program(&execinfo);		}	}	return 0;}