Problems for writing a small UNIX shell

Problems for writing a small UNIX shell

Post by Yin Tan Cu » Sun, 29 Mar 1998 04:00:00



I'm trying to write a small unix shell in order to learn about UNIX
process management. And so far I encountered the following problem:

my shell(msh) will recognize foreground process and background process
(when there is a '&' at the end of command). when I execute a program
at background ( eg:  xterm& ). It will start without problem. and as
long as I don't exit from this program or kill this program, there is
no problem, I can still execute other commands from my shell. But if I
stop the background program or kill it, then all the command I type at
my shell will act like if there is a '&' at the end. eg:
(after i execute 'xterm&' then exit from it or terminate it:

msh$ ls
msh$ Makefile   others     shell.c     shell_3.c
cmd        pid.c      shell.c~   ssh

<enter> again, it will back to command prompt.

below is my source for executing background program, I have a function

        int isBgProc(int argc, char *argv[]);

which will check if there is a '&' at the end of the user command, if so
it will set a flag and call the function below.

/***************************************************************/

void run_background_job(int argc, char *argv[])
{
  pid_t pid;
  int status;

  if ((pid = fork()) < 0)
    perror("fork");
  else if (pid == 0)   /* child */
   {
     if( execvp(argv[0], argv) == -1)
         perror(argv[0]);   /* if execvp returns error occured */
   }

  else  /* parent */
    waitpid(pid, &status, WNOHANG);

Quote:}

/**************************************************************/

and in main(), I have these two lines to catch signals and they are in a
while(1) loop :

        signal(SIGQUIT, SIG_DFL);
        signal(SIGKILL, SIG_DFL);

I checked the function isBgProc() with gdb and there is nothing wrong
with it. everytime it returns correct value.

Can anyone tell me why is my program act like above ?

Please reply by email to this address :


Thank you very much !!

 
 
 

Problems for writing a small UNIX shell

Post by Jeremy Nels » Fri, 03 Apr 1998 04:00:00



Quote:>[about a simple shell and job control]

Just to make sure the basis are there, you are remembering that your shell
needs to do two things (for interactive use)

        1) setsid() to put the shell in a new session
                -- this may not be required on all systems --
        2) setpgid(0, getpid()) to put the shell in its own process group
        2) Open up /dev/tty and that is now your controlling terminal
                -- this is refered to as 'ctty' below --
        4) tcsetpgrp(ctty, getpgrp());  to make the shell the foreground
           process.

Every command you run from your shell should be in its own process group.
The general algorithm you might find helpful is:

1) User enters command
2) You fork() off new process
3) In child process, setpgid(getpid(), getpid());
   a) If command is to run in background, then thats it
        -- If you want the ability to 'fg' background groups, then you
           will have to keep a record of the child process somewhere in
           the shell, so you can do (b) below later to bring it to the
           foreground.
   b) If command is to run in foreground, then you need to:
                tcsetpgrp(ctty, getpgrp());
      where 'ctty' is the file descriptor to the shell's controlling
      terminal.
4) Exec the program to run.
5) In parent process, if child is in background, waitpid() for it.
   When its done, tcsetpgrp(ctty, getpid()) to give the terminal
   back to the shell.  If the sub-process is in the background, continue
   on your way.

The reason you were having the problems you were having is because your
child process is running *in the same process group* as the shell.
This is definitely a no-no, as then when the kernel sends a signal to
the foreground process group, your shell will get it as well.

I am not by any means a "master" of job control, so i may very well have
a few details incorrect.  You will want to refer to your man pages for
the full semantics, and i cannot highly enough recommend "Advanced
Programming In the Unix Environment" by W. Richard Stevens, found in any
big book store (borders, barnes&noble).  If anyone wants to correct my
examples, please feel free to do so, as i always relish the opportunity
to learn more from others..

Jeremy

 
 
 

Problems for writing a small UNIX shell

Post by Andrew Giert » Fri, 03 Apr 1998 04:00:00


 Jeremy> Just to make sure the basis are there, you are remembering
 Jeremy> that your shell needs to do two things (for interactive use)

 Jeremy>     1) setsid() to put the shell in a new session
 Jeremy>             -- this may not be required on all systems --

It's not required on any system. No shell should try and establish
a session; that's already been done for you (by getty, telnetd, xterm
or whatever) before the shell is invoked.

If you in fact did perform this step, all the following ones would fail
anyway.

 Jeremy>     2) setpgid(0, getpid()) to put the shell in its own
 Jeremy> process group

Correct (setpgid(0,0) works too)

 Jeremy>     2) Open up /dev/tty and that is now your controlling terminal
 Jeremy>             -- this is refered to as 'ctty' below --

No. You should already have the terminal open on stdin/out/err anyway, and
if not, don't try to second-guess the user.

 Jeremy>     4) tcsetpgrp(ctty, getpgrp()); to make the shell the
 Jeremy> foreground process.

--
Andrew.

comp.unix.programmer FAQ: see <URL: http://www.erlenstar.demon.co.uk/unix/>
                           or <URL: http://www.whitefang.com/unix/>

 
 
 

1. Small Shell for small scripts

I have a ton of small Bourne Shell scripts that I like to run in the
background while I work, but each of them uses a shell--which is a waste
of memory, even when some of that memory is shared between them.

Part of the problem is that instead of sh or csh, bash or tcsh are
called.  They are substantially larger due to all the extra features they
contain.

One possible solution is to reprogram everything in PERL, which uses one
instance of its interpreter no matter how many perl scripts are running
(I think), and should thus be very memory efficient.

I am looking for a way to NOT reprogram all my myriad little programs,
however.  The best possible way I can think of is to use a very small
Bourne shell.

Are there any small shells for Linux out there that would fit this bill?  

Are there any better ways than the two I listed to do what I want done?

Thanks,
-Patrick

--

Blake Online Project:           http://virtual.park.uga.edu/~wblake
Kyudo Makiwara:                 http://www.negia.net/~pdarden

        ...the bud of her lips opened and closed smoothly,
           like a beautiful little circle of leeches.
                --Kawabata Yasunari _Snow Country_

2. NAT and Win95 payload source addresses.

3. Unix Pgmrs: Is this a C problem or a unix shell problem?

4. Problems with xrn - from Newbie

5. Small problem in AIX write command

6. ISDN problem

7. Need help writing UNIX shell program

8. Superfluous videomode reload during VT switch

9. Help in writing a unix shell script!

10. writing a shell script on unix sun workstation

11. Writing a range of lines, in UNIX shell or perl

12. writing a UNIX shell

13. UNIX Free shell accounts Bots allowed Cuentas shell bajo unix gratis permiten bots