help on a ring problem.

Hi I am studying unix programming. However, I have difficulties to do one problem on a book(practical unix programming). There is no solutions provided in the book! I need to modify the following program to make it a bidirectinal ring so that the inormation can flow in either direction between neighbors on the ring.  

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
/*
 * Sample C program for generating a unidirectional ring of processes.
 * Invoke this program with a command-line argument indicating the
 * number of processes on the ring.  Communication is done via pipes
 * that connect the standard output of a process to the standard input
 * of its successor on the ring.  After the ring is created, each
 * process identifies itself with its process ID and the process ID
 * of its parent.  Each process then exits.
 */
 
void main(int argc,  char *argv[ ])
{
   int   i;             /* number of this process (starting with 1)   */
   int   childpid;      /* indicates process should spawn another     */
   int   nprocs;        /* total number of processes in ring          */
   int   fd[2];         /* file descriptors returned by pipe          */
   int   error;         /* return value from dup2 call                */
   int       status;
    /* check command line for a valid number of processes to generate */
   if ( (argc != 2) || ((nprocs = atoi (argv[1])) <= 0) ) {
       fprintf (stderr, "Usage: %s nprocs\n", argv[0]);
       exit(1);
   }
                        /* connect std input to std output via a pipe */
   if (pipe (fd) == -1) {
      perror("Could not create pipe");
      exit(1);
   }
   if ((dup2(fd[0], STDIN_FILENO) == -1) ||
       (dup2(fd[1], STDOUT_FILENO) == -1)) {
      perror("Could not dup pipes");
      exit(1);
   }
   if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
      perror("Could not close extra descriptors");
      exit(1);
   }
        /* create the remaining processes with their connecting pipes */
   for (i = 1; i < nprocs;  i++) {
      if (pipe (fd) == -1) {
         fprintf(stderr,"Could not create pipe %d: %s\n",
            i, strerror(errno));
         exit(1);
      }  
      if ((childpid = fork()) == -1) {
         fprintf(stderr, "Could not create child %d: %s\n",
            i, strerror(errno));
         exit(1);
      }  
      if (childpid > 0)        /* for parent process, reassign stdout */
          error = dup2(fd[1], STDOUT_FILENO);
      else
          error = dup2(fd[0], STDIN_FILENO);
      if (error == -1) {
         fprintf(stderr, "Could not dup pipes for iteration %d: %s\n",
                 i, strerror(errno));
         exit(1);
      }  
      if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
         fprintf(stderr, "Could not close extra descriptors %d: %s\n",
                i, strerror(errno));
         exit(1);
      }
      if (childpid)
         break;
   }

   wait(&status);
                                  /* say hello to the world */
   fprintf(stderr,"This is process %d with ID %d and parent id %d\n",
      i, (int)getpid(), (int)getppid());
   exit (0);
}     /* end of main program here */

pete_hostAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mrauschCommented:
If you are running this on a SVR4, you automatically have a
bidirectional ring as far as you don't use the stdio routines
to access the pipe. That is, if you access the file descriptors
directly with write() and read(), it is perfectly valid for your
ring to write to fd 0 ("stdin") and read from fd 1 ("stdout").

If you want to use the stdio routines, you could add something
like this (not tested though)

[...]
      int   error;         /* return value from dup2 call                */
      int   status;
+      FILE *STDINREV, *STDOUTREV; /* FILE descriptors to write to the previous
+                                     or read from the next process in the ring */
[...]
      if (childpid)
             break;
       }
    }
+
+    /* now create new FILE descriptors for the reverse direction in the ring */
+    if ( (STDOUTREV = fdopen(STDIN_FILENO, "w")) == NULL ||
+         (STDINREV = fdopen(STDOUT_FILENO, "r")) == NULL ) {
+            perror("Could not open descriptor for reverse direction");
+            exit(1);
+    }
+
   wait(&status);
[...]

to your code and use e.g. fprintf(STDOUTREV,"whatever\n") to
write to the previous process.
This is not portable though, for example Linux doesn't know this
new semantic of pipe().

To implement it in a portable way, you just have to open up a
second pipe for the reverse direction, and in case you want to
use STDIO on this as well, use the fdopen() method to get FILE*
descriptors for these pipes as well. One thing is different though, you might run into problems if you want fixed fd's for
the reverse direction (say, fd 3 and 4). To be on the safe side,
you should access the new pipes via variables containing the fd.

Do you need code for this or do you want to try yourself?

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
pete_hostAuthor Commented:
Hi mrausch,
thank you for your help on this problem. Actually, i still have a little bit confused about this problem. Can you show me the code for this problem? I am running linux for this problem.


0
seedyCommented:
Home assignment?!  pete_host, why don't you post what you have coded so far?
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

pete_hostAuthor Commented:
here is the code i have, but i don't know why it is not working right?

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>


void main(int argc, char *argv[])
{
      
      int  i;
      int childpid;
      int nprocs;
      int fd[2];
      int error;
      int p1[2];
      int p2[2];
      int p3[2];
      int p4[2];
      int start=1;


      if ((argc !=2)|| ((nprocs = atoi(argv[1]))<=0)) {
      fprintf (stderr, "Usage: %s processes\n", argv[0]);
      exit (1);

      }
      if (pipe (p1) == -1) {
          perror("Could not create pipe1");
          exit(1);
      }
      if (pipe (p2) == -1) {
          perror("Could not create pipe2");
          exit(1);
      }
      if (pipe (p3) == -1) {
          perror("Could not create pipe3");
          exit(1);
      }
      if (pipe (p4) == -1) {
          perror("Could not create pipe4");
          exit(1);
      }
      if ((childpid= fork()) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
      if (childpid){
            if ((dup2(p2[0], p1[1]) == -1) ||
                (dup2(p3[0], p2[0]) == -1)||
                (dup2(p4[1], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }

            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
                }
      else{
            if ((dup2(p1[1], p1[0]) == -1) ||
                (dup2(p2[0], p1[1]) == -1)||
                (dup2(p3[1], p2[0]) == -1)||
                (dup2(p4[0], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }
            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
          }

      for (i=1; i<nprocs; i++) {
            if (i==1) { break;};

      if (childpid){
            if ((dup2(p2[0], p1[0]) == -1) ||
                (dup2(p2[1], p1[1]) == -1)||
                (dup2(p3[0], p2[0]) == -1)||
                (dup2(p4[1], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }
            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
            break;}
      else {
            if ((dup2(p3[1], p2[0]) == -1) ||
                (dup2(p4[0], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }
            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
            
            if (pipe(p3) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
            if (pipe(p4) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
            if ((childpid= fork()) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
      }
   }
   fprintf(stderr, "process #i:%d process ID: %ld parent ID: %ld \n",
    i, (int) getpid(), (int) getppid());
      exit(0);
}

0
pete_hostAuthor Commented:
Adjusted points to 250
0
pete_hostAuthor Commented:
anybody help me on this? I need to hand in the hw tomorrow!
0
seedyCommented:
Please see the question "Token Ring(Bidirectional)" under C Language topic area, at:
http://www.experts-exchange.com/topics/comp/lang/c/Q.10050266

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.