Back to index

radiance  4R0+20100331
Functions | Variables
netproc.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include "rtmisc.h"
#include "selcall.h"
#include "netproc.h"
#include "paths.h"

Go to the source code of this file.

Functions

static int readerrs (int fd)
static void wait4end (void)
static int finishjob (PSERVER *ps, int pn, int status)
PSERVERaddpserver (char *host, char *dir, char *usr, int np)
void delpserver (PSERVER *ps)
PSERVERfindjob (register int *pnp)
int startjob (register PSERVER *ps, char *command, pscompfunc *compf)
int wait4job (PSERVER *ps, int pid)

Variables

static const char RCSid [] = "$Id: netproc.c,v 2.17 2010/03/15 21:31:50 greg Exp $"
PSERVERpslist = NULL
static NETPROCpindex [FD_SETSIZE]
static char ourhost [64]
static char ourdir [PATH_MAX]
static char ouruser [32]
static char * ourshell
static fd_set errdesc
static int maxfd
char * remsh

Function Documentation

PSERVER* addpserver ( char *  host,
char *  dir,
char *  usr,
int  np 
)

Definition at line 41 of file netproc.c.

{
       register PSERVER     *ps;
                                   /* allocate the struct */
       if (np < 1)
              return(NULL);
       ps = (PSERVER *)malloc(sizeof(PSERVER)+(np-1)*sizeof(NETPROC));
       if (ps == NULL)
              return(NULL);
       if (!ourhost[0]) {          /* initialize */
              char   dirtmp[PATH_MAX];
              register char *cp;
              register int  len;

              strcpy(ourhost, myhostname());
              getcwd(dirtmp, sizeof(dirtmp));
              if ((cp = getenv("HOME")) != NULL) {
                     if (!strcmp(cp, dirtmp))
                            ourdir[0] = '\0';
                     else if (!strncmp(cp, dirtmp, len=strlen(cp)) &&
                                   dirtmp[len] == '/')
                            strcpy(ourdir, dirtmp+len+1);
                     else
                            strcpy(ourdir, dirtmp);
              } else
                     strcpy(ourdir, dirtmp);
              if ((cp = getenv("USER")) != NULL)
                     strcpy(ouruser, cp);
              if ((ourshell = getenv("SHELL")) == NULL)
                     ourshell = "/bin/sh";
              FD_ZERO(&errdesc);
              maxfd = -1;
       }
                                   /* assign host, directory, user */
       if (host == NULL || !strcmp(host, ourhost) ||
                     !strcmp(host, LHOSTNAME))
              ps->hostname[0] = '\0';
       else
              strcpy(ps->hostname, host);
       if (dir == NULL)
              strcpy(ps->directory, ourdir);
       else
              strcpy(ps->directory, dir);
       if (usr == NULL || !strcmp(usr, ouruser))
              ps->username[0] = '\0';
       else
              strcpy(ps->username, usr);
                                   /* clear process slots */
       ps->nprocs = np;
       while (np--) {
              ps->proc[np].com = NULL;
              ps->proc[np].pid = -1;
              ps->proc[np].efd = -1;
              ps->proc[np].errs = NULL;
              ps->proc[np].elen = 0;
              ps->proc[np].cf = NULL;
       }
                                   /* insert in our list */
       ps->next = pslist;
       pslist = ps;
                                   /* check for signs of life */
       if (!pserverOK(ps)) {
              delpserver(ps);                    /* failure -- abort */
              return(NULL);
       }
       return(ps);
}

Here is the caller graph for this function:

void delpserver ( PSERVER ps)

Definition at line 116 of file netproc.c.

{
       PSERVER       pstart;
       register PSERVER     *psp;
       register int  i;
                                   /* find server in our list */
       pstart.next = pslist;
       for (psp = &pstart; ps != psp->next; psp = psp->next)
              if (psp->next == NULL)
                     return;                     /* not in our list! */
                                   /* kill any running jobs */
       for (i = 0; i < ps->nprocs; i++)
              if (ps->proc[i].com != NULL) {
                     kill(SIGTERM, ps->proc[i].pid);
                     wait4job(ps, ps->proc[i].pid);
              }
                                   /* remove server from list */
       psp->next = ps->next;
       pslist = pstart.next;
       free((void *)ps);           /* free associated memory */
}

Here is the caller graph for this function:

PSERVER* findjob ( register int *  pnp)

Definition at line 142 of file netproc.c.

{
       register PSERVER     *ps;
       register int  i;

       for (ps = pslist; ps != NULL; ps = ps->next)
              for (i = 0; i < ps->nprocs; i++)
                     if (ps->proc[i].pid == *pnp) {
                            *pnp = i;
                            return(ps);
                     }
       return(NULL);        /* not found */
}

Here is the caller graph for this function:

static int finishjob ( PSERVER ps,
int  pn,
int  status 
) [static]

Definition at line 299 of file netproc.c.

{
       register NETPROC     *pp;

       pp = ps->proc + pn;
       if (pp->cf != NULL)                /* client cleanup */
              status = (*pp->cf)(ps, pn, status);
       close(pp->efd);                           /* close error stream */
       pindex[pp->efd] = NULL;
       FD_CLR(pp->efd, &errdesc);
       free((void *)pp->errs);
       pp->com = NULL;                           /* clear settings */
       pp->pid = -1;
       pp->efd = -1;
       pp->errs = NULL;
       pp->elen = 0;
       pp->cf = NULL;
       return(status);
}

Here is the caller graph for this function:

static int readerrs ( int  fd) [static]

Definition at line 244 of file netproc.c.

{
       char   errbuf[BUFSIZ];
       int    nr;
       register NETPROC     *pp;
                            /* look up associated process */
       if ((pp = pindex[fd]) == NULL)
              abort();             /* serious consistency error */
       nr = read(fd, errbuf, BUFSIZ-1);
       if (nr < 0) {
              perror("read error");
              exit(1);
       }
       if (nr == 0)         /* stream closed (process finished) */
              return(0);
       errbuf[nr] = '\0';   /* add to error buffer */
       if (pp->elen == 0)
              pp->errs = (char *)malloc(nr+1);
       else
              pp->errs = (char *)realloc((void *)pp->errs, pp->elen+nr+1);
       if (pp->errs == NULL) {
              perror("malloc failed");
              exit(1);
       }
       strcpy(pp->errs+pp->elen, errbuf);
       pp->elen += nr;
       return(nr);
}

Here is the caller graph for this function:

int startjob ( register PSERVER ps,
char *  command,
pscompfunc compf 
)

Definition at line 160 of file netproc.c.

{
       char   udirt[PATH_MAX];
       char   *av[16];
       int    pfd[2], pid;
       register int  i;

       if (ps == NULL) {           /* find a server */
              for (ps = pslist; ps != NULL; ps = ps->next)
                     if ((i = startjob(ps, command, compf)) != -1)
                            return(i);           /* got one */
              return(-1);   /* no slots anywhere */
       }
       for (i = 0; i < ps->nprocs; i++)
              if (ps->proc[i].com == NULL)
                     break;
       if (i >= ps->nprocs)
              return(-1);          /* out of process slots */
                                   /* open pipe */
       if (pipe(pfd) < 0) {
              perror("cannot open pipe");
              exit(1);
       }
                                   /* start child process */
       if ((pid = fork()) == 0) {
              close(pfd[0]);                     /* connect stderr to pipe */
              if (pfd[1] != 2) {
                     dup2(pfd[1], 2);
                     close(pfd[1]);
              }
              if (ps->hostname[0]) {             /* rsh command */
                     av[i=0] = remsh;
                     av[++i] = ps->hostname;
                     av[++i] = "-n";                    /* no stdin */
                     if (ps->username[0]) {             /* different user */
                            av[++i] = "-l";
                            av[++i] = ps->username;
                            if (ps->directory[0] != '/') {
                                   av[++i] = "cd";
                                   udirt[0] = '~';
                                   strcpy(udirt+1, ouruser);
                                   av[++i] = udirt;
                                   av[++i] = ";";
                            }
                     }
                     if (ps->directory[0]) {            /* change directory */
                            av[++i] = "cd";
                            av[++i] = ps->directory;
                            av[++i] = ";";
                     }
                     av[++i] = command;
                     av[++i] = NULL;
              } else {                    /* shell command */
                     av[0] = ourshell;
                     av[1] = "-c";
                     av[2] = command;
                     av[3] = NULL;
              }
              execv(av[0], av);
              _exit(1);
       }
       if (pid == -1) {
              perror("fork failed");
              exit(1);
       }
       ps->proc[i].com = command;  /* assign process slot */
       ps->proc[i].cf = compf;
       ps->proc[i].pid = pid;
       close(pfd[1]);                     /* get piped stderr file descriptor */
       ps->proc[i].efd = pfd[0];
       fcntl(pfd[0], F_SETFD, FD_CLOEXEC);       /* set close on exec flag */
       pindex[pfd[0]] = ps->proc + i;     /* assign error fd index */
       FD_SET(pfd[0], &errdesc);   /* add to select call parameter */
       if (pfd[0] > maxfd)
              maxfd = pfd[0];
       return(pid);                /* return to parent process */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void wait4end ( void  ) [static]

Definition at line 277 of file netproc.c.

{
       fd_set readfds, excepfds;
       register int  i;
                            /* find end of descriptor set */
       for ( ; maxfd >= 0; maxfd--)
              if (FD_ISSET(maxfd, &errdesc))
                     break;
       if (maxfd < 0)
              return;              /* nothing to read */
       readfds = excepfds = errdesc;
       while (select(maxfd+1, &readfds, NULL, &excepfds, NULL) > 0)
              for (i = 0; i <= maxfd; i++)              /* get pending i/o */
                     if (FD_ISSET(i, &readfds) || FD_ISSET(i, &excepfds))
                            if (readerrs(i) == 0)
                                   return;              /* finished process */
       perror("select call failed");
       exit(1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int wait4job ( PSERVER ps,
int  pid 
)

Definition at line 325 of file netproc.c.

{
       int    status, psn, psn2;
       PSERVER       *ps2;

       if (pid == -1) {                   /* wait for first job */
              if (ps != NULL) {
                     for (psn = ps->nprocs; psn--; )
                            if (ps->proc[psn].com != NULL)
                                   break;
                     if (psn < 0)
                            return(-1);   /* no processes this server */
              }
              do {
                     wait4end();          /* wait for something to end */
                     if ((psn2 = wait(&status)) == -1)
                            return(-1);   /* none left */
                     ps2 = findjob(&psn2);
                     if (ps2 != NULL)     /* clean up job if ours */
                            status = finishjob(ps2, psn2, status);
              } while (ps2 == NULL || (ps != NULL && ps2 != ps));
              return(status);                    /* return job status */
       }
       psn = pid;                         /* else find specific job */
       ps2 = findjob(&psn);               /* find process slot */
       if (ps2 == NULL || (ps != NULL && ps2 != ps))
              return(-1);          /* inconsistent target */
       ps = ps2;
       do {
              wait4end();                 /* wait for something to end */
              if ((psn2 = wait(&status)) == -1)
                     return(-1);          /* none left */
              ps2 = findjob(&psn2);
              if (ps2 != NULL)            /* clean up job if ours */
                     status = finishjob(ps2, psn2, status);
       } while (ps2 != ps || psn2 != psn);
       return(status);                           /* return job status */
}

Here is the caller graph for this function:


Variable Documentation

fd_set errdesc [static]

Definition at line 30 of file netproc.c.

int maxfd [static]

Definition at line 31 of file netproc.c.

char ourdir[PATH_MAX] [static]

Definition at line 26 of file netproc.c.

char ourhost[64] [static]

Definition at line 25 of file netproc.c.

char* ourshell [static]

Definition at line 28 of file netproc.c.

char ouruser[32] [static]

Definition at line 27 of file netproc.c.

Definition at line 23 of file netproc.c.

PSERVER* pslist = NULL

Definition at line 21 of file netproc.c.

const char RCSid[] = "$Id: netproc.c,v 2.17 2010/03/15 21:31:50 greg Exp $" [static]

Definition at line 2 of file netproc.c.

char* remsh

Definition at line 112 of file ranimate.c.