Logo Search packages:      
Sourcecode: ksh version File versions  Download package

cspath.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1990-2007 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                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
 *
 * return a pointer to a pathname for an open fd
 */

#include "cslib.h"

#include <ast_dir.h>

/*
 * someone thinks FIFO and SOCK are the same (bsd, eh?)
 */

#if defined(S_IFMT) && defined(S_IFIFO)
#undef      S_ISFIFO
#define S_ISFIFO(m)     (((m)&S_IFMT)==S_IFIFO)
#endif

/*
 * scan /dev for path matching st
 */

static char*
devpath(char* path, int size, int blk, register struct stat* st)
{
      register DIR*           dirp;
      register struct dirent* entry;
      DIR*              subp = 0;
      char*             base;
      int               n;
      int               t;
      struct stat       tst;

      strcpy(path, "/dev");
      if (!(dirp = opendir(path))) return 0;
      path[4] = '/';
      base = path + 5;
      for (n = 1;;)
      {
            while (entry = readdir(dirp))
            {
#ifdef D_FILENO
                  if (n && D_FILENO(entry) != st->st_ino)
                        continue;
#endif
                  if (*entry->d_name == '.' || D_NAMLEN(entry) + (base - path) + 1 > size)
                        continue;
                  strcpy(base, entry->d_name);
                  if (stat(path, &tst))
                        continue;
                  if (!subp && S_ISDIR(tst.st_mode) && !streq(path, "/dev/fd"))
                  {
                        subp = dirp;
                        if (dirp = opendir(path))
                        {
                              base = path + strlen(path);
                              *base++ = '/';
                        }
                        else
                        {
                              dirp = subp;
                              subp = 0;
                        }
                        continue;
                  }
#ifndef D_FILENO
                  if (n && tst.st_ino != st->st_ino)
                        continue;
#endif
                  if (idevice(&tst) == idevice(st) && ((t = S_ISBLK(tst.st_mode)) || S_ISCHR(tst.st_mode)) && t == blk && (!n || tst.st_dev == st->st_dev && tst.st_ino == st->st_ino))
                  {
                        closedir(dirp);
                        if (subp) closedir(subp);
                        return path;
                  }
            }
            if (subp)
            {
                  closedir(dirp);
                  dirp = subp;
                  subp = 0;
                  base = path + 5;
            }
            else if (!n--) break;
            else rewinddir(dirp);
      }
      closedir(dirp);
      return 0;
}

/*
 * return a pointer to a pathname for an open fd
 */

char*
cspath(register Cs_t* state, register int fd, int flags)
{
      register char*          s;
      char              num[16];
      struct stat       st;
      int               typ;

#if CS_LIB_V10

      struct tcpuser          tcp;

#else

#if CS_LIB_SOCKET

      struct sockaddr_in      lcl;
      struct sockaddr_in      rmt;
      Sock_size_t       namlen = sizeof(lcl);
#ifdef SO_TYPE
      Sock_size_t       typlen = sizeof(typ);
#endif

#endif

#endif

      if (fstat(fd, &st)) return "/dev/fd/-1";
      else if (S_ISFIFO(st.st_mode)) sfsprintf(state->path, sizeof(state->path), "/dev/pipe/%u", st.st_ino);
#if CS_LIB_V10
      else if (!ioctl(fd, TCPGETADDR, &tcp))
      {
            if (tcp.raddr) sfsprintf(state->path, sizeof(state->path), "/dev/tcp/%s/%d.%d", (flags & CS_PATH_NAME) ? csname(state, tcp.raddr) : csntoa(state, tcp.raddr), ntohs(tcp.rport), ntohs(tcp.lport));
            else
            {
                  if (!tcp.laddr) tcp.laddr = csaddr(state, NiL);
                  sfsprintf(state->path, sizeof(state->path), "/dev/tcp/%s/%d", (flags & CS_PATH_NAME) ? csname(state, tcp.laddr) : csntoa(state, tcp.laddr), ntohs(tcp.lport));
            }
      }
#endif
#if CS_LIB_SOCKET
      else if (!getsockname(fd, (struct sockaddr*)&lcl, &namlen) && namlen == sizeof(lcl) && lcl.sin_family == AF_INET)
      {
            s = "tcp";
#ifdef SO_TYPE
            if (!getsockopt(fd, SOL_SOCKET, SO_TYPE, (char*)&typ, &typlen)) switch (typ)
            {
            case SOCK_DGRAM:
                  s = "udp";
                  break;
            case SOCK_STREAM:
                  break;
            default:
                  sfsprintf(s = num, sizeof(num), "%d.p", typ);
                  break;
            }
#endif
            namlen = sizeof(rmt);
            if (!getpeername(fd, (struct sockaddr*)&rmt, &namlen) && namlen == sizeof(rmt) && rmt.sin_family == AF_INET)
            {
                  if (!rmt.sin_addr.s_addr) rmt.sin_addr.s_addr = csaddr(state, NiL);
                  sfsprintf(state->path, sizeof(state->path), "/dev/%s/%s/%d.%d", s, (flags & CS_PATH_NAME) ? csname(state, (unsigned long)rmt.sin_addr.s_addr) : csntoa(state, (unsigned long)rmt.sin_addr.s_addr), ntohs((unsigned short)rmt.sin_port), ntohs((unsigned short)lcl.sin_port));
            }
            else
            {
                  if (!lcl.sin_addr.s_addr) lcl.sin_addr.s_addr = csaddr(state, NiL);
                  sfsprintf(state->path, sizeof(state->path), "/dev/%s/%s/%d", s, (flags & CS_PATH_NAME) ? csname(state, (unsigned long)lcl.sin_addr.s_addr) : csntoa(state, (unsigned long)lcl.sin_addr.s_addr), ntohs((unsigned short)lcl.sin_port));
            }
      }
#endif
      else if ((typ = S_ISBLK(st.st_mode)) || S_ISCHR(st.st_mode))
      {
            if (s = devpath(state->path, sizeof(state->path), typ, &st))
                  return s;
            sfsprintf(state->path, sizeof(state->path), "/dev/%s-%u,%u", typ ? "blk" : "chr", major(idevice(&st)), minor(idevice(&st)));
      }
      else
            sfsprintf(state->path, sizeof(state->path), "/dev/ino/%u/%u", st.st_dev, st.st_ino);
      return state->path;
}

char*
_cs_path(int fd, int flags)
{
      return cspath(&cs, fd, flags);
}

Generated by  Doxygen 1.6.0   Back to index