Blame | Last modification | View Log | RSS feed
/*
* esh - the 'extensible' shell.
*
* Developed by Godmar Back for CS 3214 Fall 2009
* Virginia Tech.
*
* $Id: esh.h,v 1.4 2011/03/29 15:46:28 cs3214 Exp $
*/
#include <stdbool.h>
#include <obstack.h>
#include <stdlib.h>
#include <termios.h>
#include "list.h"
/* Forward declarations. */
struct esh_command;
struct esh_pipeline;
struct esh_command_line;
/*
* A esh_shell object allows plugins to access services and information.
* The shell object should support the following operations.
*/
struct esh_shell {
/* Return the list of current jobs */
struct list/* <esh_pipeline> */ * (* get_jobs) (void);
/* Return job corresponding to jid */
struct esh_pipeline * (* get_job_from_jid)(int jid);
/* Return job corresponding to pgrp */
struct esh_pipeline * (* get_job_from_pgrp)(pid_t pgrp);
/* Return process corresponding to pid */
struct esh_command * (* get_cmd_from_pid)(pid_t pid);
/* Build a prompt. Memory must be malloc'd */
char * (* build_prompt) (void);
/* Read an input line */
char * (* readline) (const char *prompt);
/* Parse command line */
struct esh_command_line * (* parse_command_line) (char *);
};
/*
* Modules must define a esh_plugin instance named 'esh_module.'
* Each of the following members is optional.
* esh will call its 'init' functions upon successful load.
*
* For binary compatibility, do not change the order of these fields.
*/
struct esh_plugin {
struct list_elem elem; /* Link element */
/* an integer number denoting the relative rank of the plugin
* Plugins are notified of events in increasing rank. */
int rank;
/* Initialize plugin and pass shell object */
bool (* init)(struct esh_shell *);
/* The return value of the following three functions indicates
* whether the plugin wants processing to stop.
* true - indicates processing should stop.
* false - indicates processing should continue.
*/
/* The command line the user entered.
* A plugin may change it. */
bool (* process_raw_cmdline)(char **);
/* A given pipeline of commands
* A plugin may change it. */
bool (* process_pipeline)(struct esh_pipeline *);
/* If the command is a built-in provided by a plugin, execute the
* command and return true. */
bool (* process_builtin)(struct esh_command *);
/* Manufacture part of a prompt. Memory must be allocated via malloc().
* If no plugin implements this, the shell will provide a default prompt. */
char * (* make_prompt)(void);
/* The process or processes that are part of a new pipeline
* have been forked.
* The jid and pgid fields of the pipeline and the pid fields
* of all commands in the pipeline are set.
* SIGCHLD is blocked.
*/
void (* pipeline_forked)(struct esh_pipeline *);
/* Notify the plugin about a child's status change.
* 'waitstatus' is the value returned by waitpid(2)
*
* May be called from SIGCHLD handler.
* The status of the associated pipeline has not yet been
* updated.
* */
bool (* command_status_change)(struct esh_command *, int waitstatus);
/* Add additional fields here if needed. */
};
/* A command line may contain multiple pipelines. */
struct esh_command_line {
struct list/* <esh_pipeline> */ pipes; /* List of pipelines */
/* Add additional fields here if needed. */
};
enum job_status {
FOREGROUND, /* job is running in foreground. Only one job can be
in the foreground state. */
BACKGROUND, /* job is running in background */
STOPPED, /* job is stopped via SIGSTOP */
NEEDSTERMINAL, /* job is stopped because it was a background job
and requires exclusive terminal access */
COMPLETED,
TERMINATED,
};
/* A pipeline is a list of one or more commands.
* For the purposes of job control, a pipeline forms one job.
*/
struct esh_pipeline {
struct list/* <esh_command> */ commands; /* List of commands */
char *iored_input; /* If non-NULL, first command should read from
file 'iored_input' */
char *iored_output; /* If non-NULL, last command should write to
file 'iored_output' */
bool append_to_output; /* True if user typed >> to append */
bool bg_job; /* True if user entered & */
struct list_elem elem; /* Link element. */
int jid; /* Job id. */
pid_t pgrp; /* Process group. */
enum job_status status; /* Job status. */
struct termios saved_tty_state; /* The state of the terminal when this job was
stopped after having been in foreground */
/* Add additional fields here if needed. */
char cmd_string[256]; /* Command string */
};
/* A command is part of a pipeline. */
struct esh_command {
char **argv; /* NULL terminated array of pointers to words
making up this command. */
char *iored_input; /* If non-NULL, command should read from
file 'iored_input' */
char *iored_output; /* If non-NULL, command should write to
file 'iored_output' */
bool append_to_output; /* True if user typed >> to append */
struct list_elem elem; /* Link element to link commands in pipeline. */
pid_t pid; /* Process id. */
struct esh_pipeline * pipeline;
/* The pipeline of which this job is a part. */
/* Add additional fields here if needed. */
};
/** ----------------------------------------------------------- */
/* Create new command structure and initialize it */
struct esh_command * esh_command_create(char ** argv,
char *iored_input,
char *iored_output,
bool append_to_output);
/* Create a new pipeline containing only one command */
struct esh_pipeline * esh_pipeline_create(struct esh_command *cmd);
/* Complete a pipe's setup by copying I/O redirection information
* from first and last command */
void esh_pipeline_finish(struct esh_pipeline *pipe);
/* Create an empty command line */
struct esh_command_line * esh_command_line_create_empty(void);
/* Create a command line with a single pipeline */
struct esh_command_line * esh_command_line_create(struct esh_pipeline *pipe);
/* Deallocation functions */
void esh_command_line_free(struct esh_command_line *);
void esh_pipeline_free(struct esh_pipeline *);
void esh_command_free(struct esh_command *);
/* Print functions */
void esh_command_print(struct esh_command *cmd);
void esh_pipeline_print(struct esh_pipeline *pipe);
void esh_command_line_print(struct esh_command_line *line);
/* Parse a command line. Implemented in esh-grammar.y */
struct esh_command_line * esh_parse_command_line(char * line);
/* Load plugins from directory dir */
void esh_plugin_load_from_directory(char *dirname);
/* Initialize loaded plugins */
void esh_plugin_initialize(struct esh_shell *shell);
/* List of loaded plugins */
extern struct list esh_plugin_list;