3000shell.c
v2 Sept. 15, 2019
v1 Sept. 24, 2017
based off of csimpleshell.c, Enrico Franchi2005
https:web.archive.orgweb20170223203852
http:rik0.altervista.orgsnippetscsimpleshell.html
Original under BSD license
This version is under GPLv3, copyright 2017, 2019 Anil Somayaji
You really shouldnt be incorporating parts of this in any other code,
it is meant for teaching, not production
include stdio.h
include stdlib.h
include unistd.h
include string.h
include errno.h
include systypes.h
include sysstat.h
include syswait.h
include dirent.h
include ctype.h
include fcntl.h
include signal.h
define BUFFERSIZE 116
define ARRSIZE 116
define COMMSIZE 32
const char procprefixproc;
void parseargschar buffer, char args,
sizet argssize, sizet nargs
char bufargsargssize;You need C99
char cp, wbuf;
sizet i, j;
wbufbuffer;
bufargs0buffer;
args0 buffer;
forcpbufargs; cpstrsepwbuf,nt ! NULL ;
if cp ! NULLcpbufargsargssize
break;
for ji0; bufargsi!NULL; i
if strlenbufargsi0
argsjbufargsi;
nargsj;
argsjNULL;
this is kind of like getenv
char findenvchar envvar, char notfound, char envp
const int MAXPATTERN128;
int i, p;
char c;
char patternMAXPATTERN;
char valueNULL;
p0;
while cenvvarp
patternpc;
p;
if pMAXPATTERN2
break;
patternp;
p;
patternp0;
i0;
while envpi ! NULL
if strncmppattern, envpi, p0
valueenvpip;
i;
if valueNULL
return notfound;
else
return value;
void findbinarychar name, char path, char fn, int fnsize
char n, p;
int r, statreturn;
struct stat filestatus;
if name0.name0
strncpyfn, name, fnsize;
return;
ppath;
while p ! 0
r0;
while p ! 0p ! :rfnsize1
fnrp;
r;
p;
fnr;
r;
nname;
while n ! 0rfnsize
fnrn;
n;
r;
fnr0;
statreturnstatfn, filestatus;
if statreturn0
return;
if p ! 0
p;
void setupcommfnchar pidstr, char commfn
char c;
strcpycommfn, procprefix;
ccommfnstrlencommfn;
c;
c;
strcpyc, pidstr;
ccstrlenpidstr;
strcpyc, comm;
void plist
DIR proc;
struct dirent e;
int result;
char commCOMMSIZE; seems to just need 16
char commfn512;
int fd, i, n;
procopendirprocprefix;
if procNULL
fprintfstderr, ERROR: Couldnt open proc.n;
for ereaddirproc; e ! NULL; ereaddirproc
if isdigitedname0
setupcommfnedname, commfn;
fdopencommfn, ORDONLY;
if fd1
nreadfd, comm, COMMSIZE;
closefd;
for i0; in; i
if commin
commi0;
break;
printfs: sn, edname, comm;
else
printfsn, edname;
resultclosedirproc;
if result
fprintfstderr, ERROR: Couldnt close proc.n;
void signalhandlerint thesignal
int pid, status;
if thesignalSIGHUP
fprintfstderr, Received SIGHUP.n;
return;
if thesignal ! SIGCHLD
fprintfstderr, Child handler called for signal d?!n,
thesignal;
return;
pidwaitstatus;
if pid1
nothing to wait for
return;
if WIFEXITEDstatus
fprintfstderr, nProcess d exited with status d.n,
pid, WEXITSTATUSstatus;
else
fprintfstderr, nProcess d aborted.n, pid;
void runprogramchar args, int background, char stdoutfn,
char path, char envp
pidt pid;
int fd, retstatusNULL;
char binfnBUFFERSIZE;
pidfork;
if pid
if background
fprintfstderr,
Process d running in the background.n,
pid;
else
pidwaitretstatus;
else
findbinaryargs0, path, binfn, BUFFERSIZE;
if stdoutfn ! NULL
fdcreatstdoutfn, 0666;
dup2fd, 1;
closefd;
if execvebinfn, args, envp
putsstrerrorerrno;
exit127;
void promptloopchar username, char path, char envp
char bufferBUFFERSIZE;
char argsARRSIZE;
int background;
sizet nargs;
char s;
int i, j;
char stdoutfn;
while1
printfs, username;
sfgetsbuffer, BUFFERSIZE, stdin;
if sNULL
we reached EOF
printfn;
exit0;
parseargsbuffer, args, ARRSIZE, nargs;
if nargs0 continue;
if !strcmpargs0, exit
exit0;
if !strcmpargs0, plist
plist;
continue;
background0;
if strcmpargsnargs1, 0
background1;
nargs;
argsnargsNULL;
stdoutfnNULL;
for i1; inargs; i
if argsi0
stdoutfnargsi;
stdoutfn;
printfSet stdout to sn, stdoutfn;
for ji; jnargs1; j
argsjargsj1;
nargs;
argsnargsNULL;
break;
runprogramargs, background, stdoutfn, path, envp;
int mainint argc, char argv, char envp
struct sigaction signalhandlerstruct;
char username;
char defaultusernameUNKNOWN;
char path;
char defaultpathusrbin:bin;
memset signalhandlerstruct, 0, sizeofsignalhandlerstruct;
signalhandlerstruct.sahandlersignalhandler;
signalhandlerstruct.saflagsSARESTART;
if sigactionSIGCHLD, signalhandlerstruct, NULL
fprintfstderr, Couldnt register SIGCHLD handler.n;
if sigactionSIGHUP, signalhandlerstruct, NULL
fprintfstderr, Couldnt register SIGHUP handler.n;
usernamefindenvUSER, defaultusername, envp;
pathfindenvPATH, defaultpath, envp;
promptloopusername, path, envp;
return 0;
Reviews
There are no reviews yet.