Logo Search packages:      
Sourcecode: ksh version File versions

cslocal.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*           Copyright (c) 1990-2007 AT&T Knowledge Ventures            *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                      by AT&T Knowledge Ventures                      *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                                                                      *
***********************************************************************/
#pragma prototyped
/*
 * Glenn Fowler
 * AT&T Research
 *
 * open|initiate /dev/fdp/local/<service>/user
 * coded for bootstrap
 */

#include "cslib.h"

#include <wait.h>

#define DEVLOCAL  "/dev/fdp/local/"

#ifdef SIGCHLD

static int  children;

static void
child(int sig)
{
      NoP(sig);
      children++;
}

#endif

static int
initiate(Cs_t* state, const char* svc, char* cmd)
{
      pid_t pid;
      pid_t n;
      char* av[3];

#ifdef SIGCHLD
      Handler_t   fun;

      children = 0;
      if ((fun = signal(SIGCHLD, child)) == SIG_DFL) signal(SIGCHLD, fun);
      else if (children) children++;
#endif
      pathcanon(cmd, 0);
      av[0] = cmd;
      av[1] = (char*)svc;
      av[2] = 0;
      if ((pid = spawnveg(av[0], av, environ, 0)) == -1)
      {
            messagef((state->id, NiL, -1, "local: %s: cannot initiate %s", svc, cmd));
            return -1;
      }
      while ((n = waitpid(pid, NiL, 0)) == -1 && errno == EINTR);
#ifdef SIGCHLD
      if (fun != SIG_DFL)
      {
            signal(SIGCHLD, fun);
            if (fun != SIG_IGN)
                  while (--children > 0)
                        (*fun)(SIGCHLD);
      }
#endif

      /*
       * yuk: looks like we have to give fdp services time
       *    to start up -- a few seconds shouldn't hurt
       */

      sleep(2);
      return n;
}

int
cslocal(register Cs_t* state, const char* path)
{
      register char*    s;
      register char*    p;
      register char*    t;
      register char*    v;
      struct stat st;
      char        cmd[PATH_MAX / 8];
      char        exe[PATH_MAX + 1];
      char        tmp[PATH_MAX + 1];
#if CS_LIB_STREAM || CS_LIB_V10 || CS_LIB_SOCKET_UN
      int         fd;
      int         n;
#endif

      messagef((state->id, NiL, -8, "local(%s) call", path));

      /*
       * validate the path
       */

      p = (char*)path;
      if (strncmp(p, DEVLOCAL, sizeof(DEVLOCAL) - 1))
      {
            messagef((state->id, NiL, -1, "local: %s: %s* expected", path, DEVLOCAL));
            goto sorry;
      }
      p += sizeof(DEVLOCAL) - 1;
      for (t = p; *t && *t != '/'; t++);
      if (!streq(t + 1, "user"))
      {
            messagef((state->id, NiL, -1, "local: %s: %s*/user expected", path, DEVLOCAL));
            goto sorry;
      }

      /*
       * locate the service
       */

      s = cmd;
      for (v = p; p <= t; *s++ = *p++);
      t = s - 1;
      for (p = v; p <= t; *s++ = *p++);
      for (p = CS_SVC_SUFFIX; *s++ = *p++;);
      p = pathbin();
      for (;;)
      {
            p = pathcat(exe, p, ':', "../lib/cs/fdp", cmd);
            if (!eaccess(exe, X_OK) && !stat(exe, &st)) break;
            if (!p)
            {
                  messagef((state->id, NiL, -1, "local: %s: %s: cannot locate service on ../lib/cs/fdp", path, cmd));
                  goto sorry;
            }
      }
      *t = 0;
      sfsprintf(tmp, sizeof(tmp), "%s/fdp/%s/%s/%d-%d-/%c%s", csvar(state, CS_VAR_LOCAL, 0), csname(state, 0), cmd, st.st_uid, geteuid(), CS_MNT_STREAM, CS_MNT_TAIL);

#if CS_LIB_STREAM || CS_LIB_V10

      for (n = 0; (fd = open(tmp, O_RDWR)) < 0; n++)
            if (n || errno == EACCES)
            {
                  messagef((state->id, NiL, -1, "local: %s: %s: cannot open service", path, tmp));
                  return -1;
            }
            else if (initiate(state, path, exe) < 0)
            {
                  messagef((state->id, NiL, -1, "local: %s: %s: cannot initiate service %s", path, tmp, exe));
                  return -1;
            }
      messagef((state->id, NiL, -8, "local(%s) fd=%d server=%s stream=%s", path, fd, exe, tmp));
      return fd;

#else

#if CS_LIB_SOCKET_UN

      {
            int               namlen;
            struct sockaddr_un      nam;

            nam.sun_family = AF_UNIX;
            strcpy(nam.sun_path, tmp);
            namlen = sizeof(nam.sun_family) + strlen(tmp);
            n = 0;
            fd = -1;
            for (;;)
            {
                  if (fd < 0 && (fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
                  {
                        messagef((state->id, NiL, -1, "local: %s: AF_UNIX socket error", path));
                        return -1;
                  }
                  if (!connect(fd, (struct sockaddr*)&nam, namlen))
                  {
#if CS_LIB_SOCKET_RIGHTS
                        if (read(fd, cmd, 1) != 1)
                              messagef((state->id, NiL, -1, "local: %s: connect ack read error", path));
                        else if (cssend(state, fd, NiL, 0))
                              messagef((state->id, NiL, -1, "local: %s: connect authentication send error", path));
                        else
#endif
                        return fd;
#if CS_LIB_SOCKET_RIGHTS
                        close(fd);
                        fd = -1;
#endif
                  }
                  else messagef((state->id, NiL, -1, "local: %s: connect error", path));
                  if (errno != EACCES) errno = ENOENT;
                  if (n || errno == EACCES || initiate(state, path, exe) < 0)
                  {
                        if (fd >= 0) close(fd);
                        return -1;
                  }
                  n = 1;
                  messagef((state->id, NiL, -1, "local: %s: connect retry", path));
            }
      }

#endif

#endif

 sorry:
      errno = ENOENT;
      return -1;
}

int
_cs_local(const char* path)
{
      return cslocal(&cs, path);
}

Generated by  Doxygen 1.6.0   Back to index