Building Operating System using c++

Hey folks..new guy here.. So heres teh deal.. got a school project to design an OS using c++ and create functionality like pipe "|", redirect ">", and run in background "&".. So, the user screen looks like this:
___________________________________________
The shell commands..
ls
cat
..so on....
q
quit
umount u
wrdisk sus
Start with ! to invoke a Unix shell cmd
sh33%
___________________________________________
//if you type in

ls | cat it should act like the linux command, but inside the c++ program..We're supposed to use these system functions --> dup2, creat, pipe, fork, pthread_create, system, printf
here is the file of most use (there is a lot of stuff missing due to the fact I have a limit on my message..but you can kind of see the processing:

#include "fs33types.hpp"
#include <iostream>
#include <sstream>

using namespace std;

extern MountEntry *mtab;
extern VNIN cwdVNIN;
FileVolume * fv; // Suspicious!
Directory * wd; // Suspicious!

void doSpawnChild()
{
// Set up a pipe so the child can report errors.
int fds[2];
if(pipe(fds) == -1)
{
throw "cannot create pipe";
}

// Set close-on-exec on write end of pipe.
int flags = fcntl(fds[1], F_GETFD);
if(flags == -1)
{
throw "cannot get fcntl flags";
}
flags |= FD_CLOEXEC;
if(fcntl(fds[1], F_SETFD, flags) == -1)
{
throw "cannot set close-on-exec";
}

// If the parent uses signal handlers, block signal delivery here.

pid_t pid = fork();
switch(pid)
{
case -1:
{
throw "cannot fork";
}
case 0:
{
// Child

// If the parent uses Ice::Application or IceUtil::CtrlCHandler,
// and the child requires the default behavior for SIGHUP, SIGINT,
// and SIGTERM, reset these signals to the default behavior here.

// Close all open file descriptors.
int maxFd = static_cast<int>(sysconf(_SC_OPEN_MAX));
for(int fd = 0; fd < maxFd; ++fd)
{
if(fd != fds[1]) // Don't close write end of pipe.
{
close(fd);
}
}

char *argCmd[] = { "ls", 0 };

execv(argCmd[0], argCmd);

const char msg[] = "exec failed";
write(fds[1], msg, sizeof(msg) - 1);
_exit(1);
}
default:
{
// Parent

// Close the write end of the pipe.
close(fds[1]);

// Wait for child to write error message or exec successfully.
stringstream err (stringstream::in | stringstream::out);
char c;
while(read(fds[0], &c, 1) > 0)
{
err << c;
}
close(fds[0]);
string msg;
if(!err.eof())
{
msg= err.str();
}

// If the parent uses signal handlers,
// restore signal delivery here.

if(!msg.empty())
{
cout<<"error throwing now.."<<endl;
throw msg;
}
}
}

}



/* The following describes one entry in our table of commands. For
* each cmmdName (a null terminated string), we specify the arguments
* it requires by a sequence of letters. The letter s stands for
* "that argument should be a string", the letter u stands for "that
* argument should be an unsigned int." The data member (func) is a
* pointer to the function in our code that implements that command.
* globalsNeeded identifies whether we need a volume ("v"), a simdisk
* ("d"), or a mount table ("m"). See invokeCmd() below for exact
* details of how all these flags are interpreted.
*/

class CmdTable {
public:
char *cmdName;
char *argsRequired;
char *globalsNeeded; // need d==simDisk, v==cfv, m=mtab
void (*func) (Arg * a);
} cmdTable[] = {
{"cd", "s", "v", doChDir},
{"cp", "ss", "v", doCopy},
{"echo", "ssss", "", doEcho},
{"inode", "u", "v", doInode},
{"ls", "", "v", doLsLong},
{"lslong", "", "v", doLsLong},
{"mkdir", "s", "v", doMkDir},
{"mkdisk", "s", "", doMakeDisk},
{"mkfs", "s", "", doMakeFV},
{"mount", "us","", doMountUS},
{"mount", "", "", doMountDF},
{"mv", "ss", "v", doMv},
{"rddisk", "su", "", doReadDisk},
{"rmdir", "s", "v", doRm},
{"rm", "s", "v", doRm},
{"pwd", "", "v", doPwd},
{"q", "", "", doQuit},
{"quit", "", "", doQuit},
{"umount", "u", "m", doUmount},
{"wrdisk", "sus", "", doWriteDisk}
};

uint ncmds = sizeof(cmdTable) / sizeof(CmdTable);

void usage()
{
printf("The shell has only the following cmds:\n");
for (uint i = 0; i < ncmds; i++)
printf("\t%s\t%s\n", cmdTable[i].cmdName, cmdTable[i].argsRequired);
printf("Start with ! to invoke a Unix shell cmd\n");
}

/* pre:: k >= 0, arg[] are set already;; post:: Check that args are
* ok, and the needed simDisk or cfv exists before invoking the
* appropriate action. */

void invokeCmd(int k, Arg *arg)
{
uint ok = 1;
if (cmdTable[k].globalsNeeded[0] == 'v' && cwdVNIN == 0) {
ok = 0;
printf("Cmd %s needs the cfv to be != 0.\n", cmdTable[k].cmdName);
}
else if (cmdTable[k].globalsNeeded[0] == 'm' && mtab == 0) {
ok = 0;
printf("Cmd %s needs the mtab to be != 0.\n", cmdTable[k].cmdName);
}

char *req = cmdTable[k].argsRequired;
uint na = strlen(req);
for (uint i = 0; i < na; i++) {
if (req[i] == 's' && (arg[i].s == 0 || arg[i].s[0] == 0)) {
ok = 0;
printf("arg #%d must be a non-empty string.\n", i);
}
if ((req[i] == 'u') && (arg[i].s == 0 || !isDigit(arg[i].s[0]))) {
ok = 0;
printf("arg #%d (%s) must be a number.\n", i, arg[i].s);
}
}
if (ok)
(*cmdTable[k].func) (arg);
}

/* pre:: buf[] is the command line as typed by the user, nMax + 1 ==
* sizeof(types);; post:: Parse the line, and set types[], arg[].s and
* arg[].u fields.
*/

void setArgsGiven(char *buf, Arg *arg, char *types, uint nMax)
{
for (uint i = 0; i < nMax; i++) {
arg[i].s = 0;
types[i] = 0;
}
types[nMax] = 0;

strtok(buf, " \t\n"); // terminates the cmd name with a \0

for (uint i = 0; i < nMax;) {
char *q = strtok(0, " \t");
if (q == 0 || *q == 0) break;
arg[i].s = q;
arg[i].u = toNum(q);
types[i] = isDigit(*q)? 'u' : 's';
nArgs = ++i;
}
}

/* pre:: name pts to the command token, argtypes[] is a string of
* 's'/'u' indicating the types of arguments the user gave;; post::
* Find the row number of the (possibly overloaded) cmd given in
* name[]. Return this number if found; return -1 otherwise. */

int findCmd(char *name, char *argtypes)
{
for (uint i = 0; i < ncmds; i++) {
if (strcmp(name, cmdTable[i].cmdName) == 0
&& strcmp(argtypes, cmdTable[i].argsRequired) == 0) {
return i;
}
}
return -1;
}

void ourgets(char *buf) {
fgets(buf, 1024, stdin);
char * p = index(buf, '\n');
if (p) *p = 0;
}

void remWhite(char str[])//removes white space
{
int i, len;
len = strlen(str);
i = 0;
while(i < len)
{
if (isspace(str[i]))
{
memmove(&str[i],&str[i+1], strlen(&str[i+1])+1);
len--;
}
else
i++;
}

}


int main()
{
char buf[1024]; // better not type longer than 1023 chars
char secBuf[1024];
char redBuf[1024];


bool procDetect=false;
bool pipeDetect=false;
bool redirectDetect=false;

usage();
for (;;) {

*buf = 0; // <--main input ---clear old buffers
*secBuf = 0;
*redBuf=0;

procDetect=false; //clear anddetect
pipeDetect=false;
redirectDetect=false;

printf("%s", "sh33% "); // prompt
ourgets(buf);
printf("cmd [%s]\n", buf); // just print out what we got as-is

printf("cmd [%s]\n", buf); // just print out what we got minus &
printf("cmd2 [%s]\n", secBuf); // print pipe target
printf("cmd [%s]\n", redBuf); // print redirect target
if (buf[0] == 0)
continue;
if (buf[0] == '#')
continue; // this is a comment line, do nothing
if (buf[0] == '!') // begins with !, execute it as
system(buf + 1); // a normal shell cmd
else {
setArgsGiven(buf, arg, types, nArgsMax);
int k = findCmd(buf, types);
if (k >= 0)
{
doSpawnChild();
invokeCmd(k, arg);
}
else
usage();
}
}
}
You forgot to include your question...
Hi I want to make a radio streamer,
which basically do the following things,
1)establish connection over HTTP with shoutcast and fetch main page
2)Parse main page to get links to MP3
3)asked user to select a channel based on title
4)fetch playlist file and establish connection to one of the URL
5)When it suceeds,radio streamer start receiving a MP3 packets over TCP
6)Convert MP3 packets to PCM
7)Stream PCM packets using RTP to clients.

Any suggestions on how to start
Topic archived. No new replies allowed.