All pastes #1554500 Raw Edit

richard

public text v1 · immutable
#1554500 ·published 2009-09-05 01:58 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 PROMPT_LAST_CHAR '>'#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);	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++;}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;	memset(info,0,sizeof(execution_info));	while(index<arg_count) {		argument *arg=args+index;		if(arg->len) {			if(arg->len==1) {				if(arg->buf[0]==';') {					++index;// 					if(info->args[curr])						break;// 					else// 						continue;				} else if(arg->buf[0]=='&') {					info->background=1;					++index;					break;				}			}			info->args[curr++]=arg->buf;			info->count++;			index++;		} else break;	}	return index;}__attribute__((unused)) static void dump_execinfo(execution_info* info) {	printf("Command: %s\n",		   execinfo.background?"Run in background":"Run in forground");	for(int i=0;i<execinfo.count;++i)		printf("Arg[%d]:%s\n",i,execinfo.args[i]);}void run_program(execution_info* info) {	int program_fd=-1;	if(!info->args[0]) return; // if it was a null command.	if(info->args[0][0]=='/')		program_fd =sys_open(info->args[0]+1,0);	else		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_execve(program_fd,info->args);// 			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) {					char **argg=info->args;					while(*argg){						print(*argg++);						putch(' ');					}					printf(" returned %d\n",curr_line,retval);				}			}			break;	}}int main(void) {	print("!rsh version 2. (C) Richard Whitty 2009\n");	for(;;) {		print(PROMPT);		flush();		line_len=fgets(stdin,curr_line,BUF_LEN);		if(line_len==-1) {			printf("\nLine too long!\n");			continue;		}// 		printf("Got line: '%s' len: %d\n",curr_line,line_len);		if(line_len==0)			continue;		if(strncmp(curr_line,"exit",5)==0) return 0;		split_args();		int x=0;		while(x<arg_count) {			x=set_exec(x,&execinfo);// 			 dump_execinfo(&execinfo);			run_program(&execinfo);		}	}	return 0;}