LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-27-2002, 02:43 PM   #1
hopeless
LQ Newbie
 
Registered: Aug 2002
Posts: 3

Rep: Reputation: 0
Red face writing a shell


Hi
I have to write a shell for a computer science prac. I have no clue what to do. Please could someone help. I especially need help with implementing the command execution facility by parsing the command line.
I also need help with implementing the path search capability.
I need help by tomorrow.
Please help!!
 
Old 08-27-2002, 02:55 PM   #2
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981
that's not really going to happen is it? a few people have asked this before, have a search. you won't find much useful information though, seeing as it's a pretty vast thing to ask for.
 
Old 08-27-2002, 04:32 PM   #3
lackluster
Member
 
Registered: Apr 2002
Location: D.C - USA
Distribution: slackware-current
Posts: 488

Rep: Reputation: 30
I found the Bash code pretty helpful. I wish I could give you a link to it but I don't have it. If you want the tarball, I think I have that.
 
Old 08-30-2002, 08:22 AM   #4
no2nt
Member
 
Registered: Aug 2001
Location: South Carolina, USA
Distribution: Redhat 8.0/Custom
Posts: 96

Rep: Reputation: 16
This is a derivative from a previous post I made. Shows command line
parsing (with "" support) and process forking (background procs not
implemented).

Code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

typedef enum bool {false, true} bool;

/* prototype declarations */
int parseArguments(const char *, char *, int *, int *);
    
int main( int argc, char *argv[] )
{
    char cmdStr[256], *user, hostname[256], pwd[256];
    int backgroundJobs = 0;

    memset(hostname, 0x00, sizeof(hostname));
    memset(pwd, 0x00, sizeof(pwd));

    gethostname(hostname, sizeof(hostname));
    user = (char *)getenv("USER");

    if( user == NULL )
    {
	strcpy(user, "unknown");
    }

    while(1)
    {
	char *progArgsArray[256], arg[256], *placeholder;
	int index = 0, sz, ret, i=0;
	
	getcwd(pwd, sizeof(pwd));
	printf("<%s@%s %s> ", user, hostname, pwd);
	memset(cmdStr, 0x00, sizeof(cmdStr));
	
	/*
	 * use fgets instead of gets. don't wanna be exploitable!
	 * 
	 * remember that fgets traps everything typed into the command
	 * line, event the carriage return!
	 */
	fgets(cmdStr, sizeof(cmdStr), stdin);

	/*
	 * take command line and split it into parts.
	 * executable is put in execCmd.
	 * args are put in dynamic arg array.
	 */
	if( cmdStr[strlen(cmdStr)-1] == '\n' )
	{
	    cmdStr[strlen(cmdStr)-1] = 0x00; // remove that carriage return
	}

	i = 0;
	sz = sizeof(arg);
	ret = parseArguments(cmdStr, arg, &sz, &index);
	placeholder = (char *)calloc(1, strlen(arg)+1);
	strcpy(placeholder, arg);
	progArgsArray[i] = placeholder;
	i++;

	/*
	 * this is bad coding. fix it.
	 */
	while( ret == 0 )
	{
	    sz = sizeof(arg);
	    ret = parseArguments(cmdStr, arg, &sz, &index);
	    if( ret == 0 )
	    {
		placeholder = NULL;
		placeholder = (char *)calloc(1, strlen(arg)+1);
		strcpy(placeholder, arg);
		progArgsArray[i] = placeholder;
		i++;
	    }
	}

	progArgsArray[i] = NULL;

	if( strcmp("quit", progArgsArray[0]) == 0 )
	{
	    if( backgroundJobs > 0 )
	    {
		printf("background jobs still running\n");
	    }
	    else
	    {
		// exit the shell
		break;
	    }
	}
	else if( strcmp("cd", progArgsArray[0]) == 0 )
	{
	    if( chdir(progArgsArray[1]) == -1 )
	    {
		printf("operation not permitted\n");
	    }
	}
	else if( strlen(progArgsArray[0]) > 0 )
	{
	    pid_t cpid;

	    /* 
	     * fork and attempt to execute the command
	     */
	    cpid = fork();

	    switch(cpid)
	    {
		case -1: // oops
		{
		    printf("Unable to claim system resources.\n");
		    break;
		}
		case 0: // i am child process
		{
		    // call execvp to start the user's command
		    if( execvp(progArgsArray[0], progArgsArray) == -1 )
		    {
			switch(errno)
			{
			    case EACCES:
			    {
				printf("access is denied: %s\n", progArgsArray[0]);
				break;
			    }
			    case EPERM:
			    {
				printf("operation not permitted: %s\n", progArgsArray[0]);
				break;
			    }
			    case ENOEXEC:
			    {
				printf("ENOEXEC\n");
				break;
			    }
			    case ENOENT:
			    {
				printf("command not found: %s\n", progArgsArray[0]);
				break;
			    }
			    default:
			    {
				printf("Error code: %d\n", errno);
			    }
			}
		    }

		    _exit(0);
		    break;
		}
		default: // i am parent process
		{
		    int status;

		    /*
		    if( cmdStr[strlen(cmdStr)] != '&' )
		    {
		    */
			waitpid(cpid, &status, 0);
		    /*
		    }
		    else
		    {
			printf("process id: %d\n", cpid);
		    }
		    */

		    /*
		     * this'll show exit status
		     
		    if( WIFEXITED(status) ) 
		    {
			printf("%d [%d] exited\n", WEXITSTATUS(status), cpid);
		    }
		    */
		    
		    // this'll have to be rewritten when fg/bg are implemented
		    for( i = 0; progArgsArray[i] != NULL; i++ )
		    {
			free(progArgsArray[i]);
			progArgsArray[i] = NULL;
		    }
		    break;
		}
	    }
	}

    }

    return 0;
}


/*
 * This function returns the next available "word" from <src> into <dest> starting
 * at <idx>. Words surrounded by "" are considered a word (spaces may exist).
 * Returns:
 *  0 = successful
 *  1 = no more words
 *  2 = destination buffer too small
 *  3 = unterminated single/double quote
 *
 * Example:
 * char src[] = "ls -al";
 * char dst[256];
 * int dst_sz = sizeof(dst);
 * int index = 0, ret;
 * 
 * ret = parseArguments(src, dst, &dst_sz, &index);
 *
 * //dst == "ls"
 * //dst_sz == 2;
 * //index == 3;
 * //ret == 0;
 * 
 * // call it again. remember index is now equal to 3.
 * ret = parseArguments(src, dst, &dst_sz, &index);
 *
 * //dst == "-al"
 * //dst_sz == 3;
 * //index == 6;
 * //ret == 1;
 * 
 */
int parseArguments(const char *src, char *dest, int *dest_sz, int *idx)
{
    int src_len, dest_idx = 0;
    bool inQuotes = false;
    int ret = 1;

    memset(dest, 0x00, *dest_sz);
    src_len = strlen(src);

    while( *idx < src_len )
    {
	if( src[*idx] == ' ' )
	{
	    //printf("      : space\n");
	    if( inQuotes )
	    {
		dest[dest_idx++] = src[*idx];
	    }
	    else if( strlen(dest) > 0 )
	    {
		// we are finished, we have at least one character
		ret = 0;
		break;
	    }
	}
	else if( src[*idx] == '"' )
	{
	    //printf("      : double quote\n");
	    inQuotes = !inQuotes;
	    // are we starting or fininshing a word?
	}
	else
	{
	    //printf("      : normal char \n");

	    if( dest_idx < *dest_sz )
	    {
		dest[dest_idx++] = src[*idx];
	    }
	    else
	    {
		// dest buffer too small!!
		ret = 2;
		break;
	    }
	}
	*idx += 1;
    }

    if( *idx >= src_len && strlen(dest) > 0 )
    {
	ret = 0;
    }

    if( inQuotes )
    {
	ret = 3;
    }
    
    return ret;
}
I guess the next step is to set the tty into raw mode for tabline
completion. background procs would be nice. command line
substitution (*, variables, etc) also.

as for the parent post.... don't tell me you waited until the day before
your project was due to rip off someone else's code? i hope i'm wrong.
 
Old 09-02-2002, 04:27 AM   #5
hopeless
LQ Newbie
 
Registered: Aug 2002
Posts: 3

Original Poster
Rep: Reputation: 0
hi thanks for the code. NO I didn't wait till the last minute to do this. In the end I actually got it working, I worked with a group of friends. I handed it in on thurs
 
Old 09-02-2002, 11:40 AM   #6
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981
hopeless, do not ask about school questions here, we are NOT here to do your homework.
 
Old 09-02-2002, 11:13 PM   #7
Keen_Eager
LQ Newbie
 
Registered: Sep 2002
Location: Down Under
Distribution: 7.3
Posts: 2

Rep: Reputation: 0
Question




Hi there

I dont mean to annoy anyone but guidance here is much appreciated. I need to do a shell script for unix.

This is what I have to do;
An electric power distribution compnay charges the domestic consumers as follows;

Consumption Units Rate of Charge
0-200 60 cents per unit

201-400 $120 plus 70 cents per unit excess of 200

401-600 $260 plus 80 cents per unit excess of 400

601 and above $420 plus $1.00 per unit excess of 600


Prepare a shell script which reads in customer number and power consumed and prints on the screen the amount to be paid by the customer(Call it powercal)
Note: Unix can carry out mathematical functions on integers only. The shell variables store numbers as integers. The student has to devise a method to display the amount in terms of dollars and cents.

All this after one lesson on scripting and I have no programming background, hence my dilemma. The other modules were fine. I just dont know where to begin and put them all together. Your help and guidance is greatly appreciated.

Regards
Keen_Eager
 
Old 09-03-2002, 02:04 AM   #8
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981
well firstly this is homework, and it's not allowed, but i guess you do clearly ask for help, not a solution, so i'll let you also. secondly welcome to lq, but please start a new thread for new questions, don't tag along on old threads.

hmm, ok then with no idea of what your input is it's pretty trivial really. to do the actual work itself you would check the value used in a block test ( [ ] ) statement, i.e if it's less that 200, less than 400 etc.... and then inside each clause you would print your output

Code:
if [ amountused -lt anothervalue ] 
then
    echo blah blah blah = $(( rate * amountused ))
elif [ amountused -lt abiggervalue ]
etc...... (deliberatly vague you understand.... )

as for getting those values, read the section about "read" way down in the bash manpage (quite near the end).

naturally there are nicer and better ways to do everything, but that's really for you to learn in your own time.
 
Old 09-03-2002, 08:15 AM   #9
no2nt
Member
 
Registered: Aug 2001
Location: South Carolina, USA
Distribution: Redhat 8.0/Custom
Posts: 96

Rep: Reputation: 16
Quote:
Note: Unix can carry out mathematical functions on integers only. The shell variables store numbers as integers.
(assuming you are using bash)
I don't know who told you that but they never apparently heard of $(()).
Hence...

no2nt@grep# echo $((50.0*1.25))
62.5
no2nt@grep# export a=65.1; export b=29.1; echo $(($a + $b))
94..1999999999999989

something possibly helpful for formatting floats/doubles:

no2nt@grep# echo `printf "%.2f" $((234.234 * 9092.23))`
2129709.40

welcome to lq!

Last edited by no2nt; 09-04-2002 at 09:25 AM.
 
Old 09-04-2002, 08:28 AM   #10
Keen_Eager
LQ Newbie
 
Registered: Sep 2002
Location: Down Under
Distribution: 7.3
Posts: 2

Rep: Reputation: 0
Thank You for help, it's appreciated from a newbie like me for the only programming i have done is on a vcr. Thanks again
regards
keen_eager
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
writing a shell script tchoua Linux - General 8 02-24-2005 06:18 PM
writing my first shell script speedhead34 Linux - Newbie 4 12-20-2004 12:50 AM
writing own shell bahuguna_n Programming 9 11-25-2003 02:11 PM
Writing C++ Shell Scripts MasterKin8T Programming 5 09-29-2003 10:43 AM
Need Help in Writing a Shell Script. KptnKrill Linux - General 2 05-19-2003 05:44 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:23 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration