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:
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);
}
}
/* 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.
*/
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
/* 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];
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();
}
}
}
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.