The contents of the file are C sources that implement a simple shell. The contents are: smsh.c: /** smsh1.c small-shell

Business, Finance, Economics, Accounting, Operations Management, Computer Science, Electrical Engineering, Mechanical Engineering, Civil Engineering, Chemical Engineering, Algebra, Precalculus, Statistics and Probabilty, Advanced Math, Physics, Chemistry, Biology, Nursing, Psychology, Certifications, Tests, Prep, and more.
Post Reply
answerhappygod
Site Admin
Posts: 899604
Joined: Mon Aug 02, 2021 8:13 am

The contents of the file are C sources that implement a simple shell. The contents are: smsh.c: /** smsh1.c small-shell

Post by answerhappygod »

The contents of the file are C sources that implement a simple
shell. The contents
are:
smsh.c:
/** smsh1.c small-shell version 1
** first really useful version after prompting shell
** this one parses the command line into strings
** uses fork, exec, wait, and ignores signals
**/
#include
#include
#include
#include
#include "smsh.h"
#define DFL_PROMPT "> "
int main()
{
char *cmdline, *prompt, **arglist;
int result;
void setup();
prompt = DFL_PROMPT ;
setup();
while ( (cmdline = next_cmd(prompt, stdin)) !=
NULL ){
if ( (arglist = splitline(cmdline)) !=
NULL ){
result = execute(arglist);
freelist(arglist);
}
free(cmdline);
}
return 0;
}
void setup()
/*
* purpose: initialize shell
* returns: nothing. calls fatal() if trouble
*/
{
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
}
void fatal(char *s1,
char *s2, int n)
{
fprintf(stderr,"Error: %s,%s\n", s1, s2);
exit(n);
}
smsh.h:
#define YES 1
#define NO 0
char *next_cmd();
char **splitline(char *);
void freelist(char **);
void *emalloc(size_t);
void *erealloc(void *,
size_t);
int execute(char **);
void fatal(char *,
char *, int );
int process();
execute.c:
/* execute.c - code used by small shell to execute commands
*/
#include
#include
#include
#include
#include
int execute(char *argv[])
/*
* purpose: run a program passing it arguments
* returns: status returned via wait, or -1 on error
* errors: -1 on fork() or wait() errors
*/
{
int pid ;
int child_info = -1;
if ( argv[0] == NULL ) /*
nothing succeeds */
return 0;
if ( (pid = fork()) == -1 )
perror("fork");
else if ( pid == 0 ){
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
execvp(argv[0], argv);
perror("cannot execute command");
exit(1);
}
else {
if ( wait(&child_info) == -1 )
perror("wait");
}
return child_info;
}
splitline.c:
/* splitline.c - commmand reading and parsing functions for
smsh
*
* char *next_cmd(char *prompt, FILE *fp) - get next command
* char **splitline(char *str); - parse a string
*/
#include
#include
#include
#include "smsh.h"
char * next_cmd(char *prompt,
FILE *fp)
/*
* purpose: read next command line from fp
* returns: dynamically allocated string holding command line
* errors: NULL at EOF (not really an error)
* calls fatal from emalloc()
* notes: allocates space in BUFSIZ chunks.
*/
{
char *buf ; /* the buffer */
int bufspace = 0; /* total size */
int pos = 0; /* current position */
int c; /* input char */
printf("%s", prompt); /* prompt user */
while( ( c = getc(fp)) != EOF ) {
/* need space? */
if( pos+1 >= bufspace ){ /* 1 for \0 */
if ( bufspace == 0 ) /* y: 1st time */
buf = emalloc(BUFSIZ);
else /* or expand */
buf = erealloc(buf,bufspace+BUFSIZ);
bufspace += BUFSIZ; /* update size */
}
/* end of command? */
if ( c == '\n' )
break;
/* no, add to buffer */
buf[pos++] = c;
}
if ( c == EOF && pos == 0 ) /* EOF and
no input */
return NULL; /* say so */
buf[pos] = '\0';
return buf;
}
/**
** splitline ( parse a line into an array of strings )
**/
#define is_delim(x) ((x)==' '||(x)=='\t')
char ** splitline(char
*line)
/*
* purpose: split a line into array of white-space separated
tokens
* returns: a NULL-terminated array of pointers to copies of the
tokens
* or NULL if line if no tokens on the line
* action: traverse the array, locate strings, make copies
* note: strtok() could work, but we may want to add quotes
later
*/
{
char *newstr();
char **args ;
int spots = 0; /* spots in table */
int bufspace = 0; /* bytes in table */
int argnum = 0; /* slots used */
char *cp = line; /* pos in string */
char *start;
int len;
if ( line == NULL ) /* handle
special case */
return NULL;
args = emalloc(BUFSIZ); /* initialize array */
bufspace = BUFSIZ;
spots = BUFSIZ/sizeof(char
*);
while( *cp != '\0' )
{
while ( is_delim(*cp) ) /* skip leading spaces
*/
cp++;
if ( *cp == '\0' ) /* quit at end-o-string
*/
break;
/* make sure the array has room (+1 for NULL) */
if ( argnum+1 >= spots ){
args = erealloc(args,bufspace+BUFSIZ);
bufspace += BUFSIZ;
spots += (BUFSIZ/sizeof(char
*));
}
/* mark start, then find end of word */
start = cp;
len = 1;
while (*++cp != '\0' &&
!(is_delim(*cp)) )
len++;
args[argnum++] = newstr(start, len);
}
args[argnum] = NULL;
return args;
}
/*
* purpose: constructor for strings
* returns: a string, never NULL
*/
char *newstr(char *s,
int l)
{
char *rv = emalloc(l+1);
rv[l] = '\0';
strncpy(rv, s, l);
return rv;
}
void
freelist(char **list)
/*
* purpose: free the list returned by splitline
* returns: nothing
* action: free all strings in list and then free the list
*/
{
char **cp = list;
while( *cp )
free(*cp++);
free(list);
}
void * emalloc(size_t n)
{
void *rv ;
if ( (rv = malloc(n)) == NULL
)
fatal("out of memory","",1);
return rv;
}
void * erealloc(void *p,
size_t n)
{
void *rv;
if ( (rv = realloc(p,n)) ==
NULL )
fatal("realloc() failed","",1);
return rv;
}
QUESTION 1:
The Contents Of The File Are C Sources That Implement A Simple Shell The Contents Are Smsh C Smsh1 C Small Shell 1
The Contents Of The File Are C Sources That Implement A Simple Shell The Contents Are Smsh C Smsh1 C Small Shell 1 (280.52 KiB) Viewed 68 times
- Part 1 - Adding the ability to pipe commands to your shell (30 marks) At the moment smsh1 doesn't support piping of commands. So, for example, if you type: ls WC at the prompt you get: ls: wc: No such file or directory ls: 1: No such file or directory Write a new program called smsh2.c that is based on smsh1.c which performs all of the shell operations of smsh1.c but also allows commands to be piped as above so that if you type: Is WC You get output like: 6 6 53 instead. You are free to add and modify files as required to accomplish this task. You must add a Makefile to your submission so that you can compile all the files for part1 by typing: make part1 and the solution for part 1 can be run by typing: ./smsh2 Note, your program must still cater for all the behaviours that were correct in the original version of smsh1. You may find the lectures on piping useful in completing this part.
Join a community of subject matter experts. Register for FREE to view solutions, replies, and use search function. Request answer by replying!
Post Reply