⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 Graphviz - Graph Drawing Programs from AT&T Research and Lucent Bell Labs See doc/build.html for
💻 C
字号:
/* $Id: io.c,v 1.4 2005/11/13 01:43:56 ellson Exp $ $Revision: 1.4 $ *//* vim:set shiftwidth=4 ts=8: *//***********************************************************      This software is part of the graphviz package      **                http://www.graphviz.org/                 **                                                         **            Copyright (c) 1994-2004 AT&T Corp.           **                and is licensed under the                **            Common Public License, Version 1.0           **                      by AT&T Corp.                      **                                                         **        Information and Software Systems Research        **              AT&T Research, Florham Park NJ             ***********************************************************//* Lefteris Koutsofios - AT&T Labs Research */#include "common.h"#include "io.h"#ifdef FEATURE_CS#include "cs2l.h"#endif#include "mem.h"#include <fcntl.h>#include <signal.h>#include <sys/wait.h>#ifndef HAVE_TERMIOS_H#include <termio.h>#else#include <termios.h>#endif#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#ifdef FEATURE_VFORK#define FORK vfork#else#define FORK fork#endif#include <netdb.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endifio_t *iop;int ion;static char *shell;static char *shbname;static FILE *serverconnect (char *);static void ptyopen (char *, FILE **, FILE **, int *);static int findpty (int *);static void pipeopen (char *, FILE **, FILE **, int *);static void socketopen (char *, int, FILE **, FILE **, int *);static void sigchldhandler (int);void IOinit (void) {    struct stat statbuf;    int ioi;    if (!(shell = getenv ("SHELL")))        shell = "/bin/sh";    if (shell[0] != '/' && shell[0] != '.') {        if (!(shell = buildpath (shell, TRUE)))            shell = "/bin/sh";        else            shell = strdup (shell);    }    shbname = shell + strlen (shell) - 1;    while (shbname >= shell && *shbname != '/')        shbname--;    if (*shbname == '/')        shbname++;    ion = IOINCR;    for (ioi = FD_SETSIZE - 1; ioi >= 0; ioi--) {        if (fstat (ioi, &statbuf) == 0) {            ion = (ioi / IOINCR + 1) * IOINCR;            break;        }    }    iop = Marrayalloc ((long) ion * IOSIZE);    for (ioi = 0; ioi < ion; ioi++)        iop[ioi].inuse = FALSE;    for (ioi = 0; ioi < ion; ioi++) {        if (fstat (ioi, &statbuf) == 0) {            if ((iop[ioi].ifp = iop[ioi].ofp = fdopen (                ioi, (ioi == 0 ? "r" : "w")            ))) {                iop[ioi].inuse = TRUE;                iop[ioi].type = IO_FILE;                iop[ioi].ismonitored = FALSE;                iop[ioi].pid = -1;                iop[ioi].buf = NULL;            }        }    }    signal (SIGCHLD, sigchldhandler);    signal (SIGPIPE, SIG_IGN);}void IOterm (void) {    int ioi;    for (ioi = 3; ioi < ion; ioi++)        if (iop[ioi].inuse)            IOclose (ioi, NULL);    Marrayfree (iop), iop = NULL, ion = 0;}int IOopen (char *kind, char *name, char *mode, char *fmt) {    io_t *p;    int type;    char *path, *command;    char hname[200];    int sfd;    unsigned int slen;    int i;    struct sockaddr_in sname;    if (strcmp (kind, "file") == 0)        type = IO_FILE;    else if (strcmp (kind, "pty") == 0)        type = IO_PTY;    else if (strcmp (kind, "pipe") == 0)        type = IO_PIPE;    else if (strcmp (kind, "socket") == 0)        type = IO_SOCKET;#ifdef FEATURE_CS    else if (strcmp (kind, "cs") == 0)        type = IO_CS;#endif    else        return -1;    for (i = 0; i < ion; i++)        if (!iop[i].inuse)            break;    if (i == ion) {        iop = Marraygrow (iop, (long) (ion + IOINCR) * IOSIZE);        for (i = ion + IOINCR - 1; i >= ion; i--)            iop[i].inuse = FALSE;        i++, ion += IOINCR;    }    p = &iop[i];    p->type = type;    p->pid = -1;    switch (type) {    case IO_FILE:        if (!(p->ifp = p->ofp = fopen (name, mode))) {            if (strncmp (name, "/dev/tcp/", 9) == 0) {                if (!(p->ifp = p->ofp = serverconnect (name)))                    return -1;                break;            }            path = buildpath (name, FALSE);            if (!path || !(p->ifp = p->ofp = fopen (path, mode)))                return -1;        }        break;    case IO_PTY:        if (!fmt)            fmt = "%e";        if (            !(path = buildpath (name, TRUE)) ||            !(command = buildcommand (path, NULL, -1, -1, fmt))        )            return -1;        ptyopen (command, &p->ifp, &p->ofp, &p->pid);        if (!p->ifp || !p->ofp)            return -1;        break;    case IO_PIPE:        if (!fmt)            fmt = "%e";        if (            !(path = buildpath (name, TRUE)) ||            !(command = buildcommand (path, NULL, -1, -1, fmt))        )            return -1;        pipeopen (command, &p->ifp, &p->ofp, &p->pid);        if (!p->ifp || !p->ofp)            return -1;        break;    case IO_SOCKET:        if (!fmt)            fmt = "%e";        if ((sfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)            return -1;        sname.sin_family = AF_INET;        sname.sin_port = 0;        sname.sin_addr.s_addr = htonl (INADDR_ANY);        slen = sizeof (sname);        if (            bind (sfd, (struct sockaddr *) &sname, slen) < 0 ||            getsockname (sfd, (struct sockaddr *) &sname, &slen) < 0        )            return -1;        if (listen (sfd, 5) < 0)            return -1;        gethostname (hname, sizeof (hname));        if (!(path = buildpath (name, TRUE)) || !(command = buildcommand (            path, hname, (int) ntohs (sname.sin_port),            (int) ntohs (sname.sin_port), fmt        )))            return -1;        socketopen (command, sfd, &p->ifp, &p->ofp, &p->pid);        if (!p->ifp || !p->ofp)            return -1;        close (sfd);        break;#ifdef FEATURE_CS    case IO_CS:        if (C2Lopen (name, mode, &p->ifp, &p->ofp) == -1)            return -1;        break;#endif    }    p->inuse = TRUE;    FD_CLR (fileno (p->ifp), &inputfds);    FD_CLR (fileno (p->ofp), &inputfds);    return i;}int IOclose (int ioi, char *action) {    io_t *p;    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)        return -1;    p = &iop[ioi];    FD_CLR (fileno (p->ifp), &inputfds);    FD_CLR (fileno (p->ofp), &inputfds);    if (p->ifp != p->ofp)        fclose (p->ifp);    fclose (p->ofp);    p->inuse = FALSE;    if (action && strcmp (action, "kill") == 0 && p->pid != -1)        kill (p->pid, 15);    return 0;}int IOreadline (int ioi, char *bufp, int bufn) {    io_t *p;    int l;    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)        return -1;    p = &iop[ioi];    fseek (p->ofp, 0L, 1);    if (fgets (bufp, bufn, p->ifp) == NULL)        return -1;    l = strlen (bufp) - 1;    while (bufp[l] == '\n' || bufp[l] == '\r')        bufp[l--] = '\000';    return l + 1;}int IOread (int ioi, char *bufp, int bufn) {    io_t *p;    int l;    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)        return -1;    p = &iop[ioi];    if ((l = read (fileno (p->ifp), bufp, bufn - 1)) == -1)        return -1;    else if (l == 0)        return 0;    bufp[l] = '\000';    return l;}int IOwriteline (int ioi, char *bufp) {    io_t *p;    if (ioi < 0 || ioi >= ion || !iop[ioi].inuse)        return -1;    p = &iop[ioi];    fseek (p->ofp, 0L, 1);    if (fputs (bufp, p->ofp) == EOF || fputs ("\n", p->ofp) == EOF)        return -1;    fflush (p->ofp);    fseek (p->ofp, 0L, 1);    return 0;}static FILE *serverconnect (char *name) {    char *host, *portp, buf[1024];    int port;    struct hostent *hp;    struct sockaddr_in sin;    int cfd;    strcpy (buf, name);    host = buf + 9;    portp = strchr (host, '/');    if (*host == 0 || !portp)        return NULL;    *portp++ = 0, port = atoi (portp);    if (!(hp = gethostbyname (host)))        return NULL;    memset ((char *) &sin, 1, sizeof (sin));    memcpy ((char *) &sin.sin_addr, hp->h_addr, hp->h_length);    sin.sin_family = hp->h_addrtype;    sin.sin_port = htons (port);    if ((cfd = socket (hp->h_addrtype, SOCK_STREAM, 0)) < 0)        return NULL;    if (connect (cfd, (struct sockaddr *) &sin, sizeof (sin)) < 0)        return NULL;    return fdopen (cfd, "w+");}static void ptyopen (char *cmd, FILE **ifp, FILE **ofp, int *pidp) {    int fd[2];    if (findpty (fd) == -1) {        *ifp = NULL;        return;    }    switch ((*pidp = FORK ())) {    case -1:        panic2 (POS, "ptyopen", "cannot fork");    case 0:        close (fd[0]), close (0), dup (fd[1]);        close (1), dup (fd[1]), close (fd[1]);        execl (shell, shbname, "-c", cmd, NULL);        panic2 (POS, "ptyopen", "child cannot exec: %s\n", cmd);    default:        close (fd[1]);    }    fcntl (fd[0], F_SETFD, FD_CLOEXEC);    *ifp = fdopen (fd[0], "r"), *ofp = fdopen (fd[0], "a+");    return;}static int findpty (int *fd) {    char *majorp, *minorp;    char pty[32], tty[32];#ifndef HAVE_TERMIOS_H    struct termio tio;#else    struct termios tio;#endif    static char ptymajor[] = "pqrs";    static char ptyminor[] = "0123456789abcdefghijklmnopqrstuvwxyz";    for (majorp = ptymajor; *majorp; majorp++) {        for (minorp = ptyminor; *minorp; minorp++) {            sprintf (pty, "/dev/pty%c%c", *majorp, *minorp);            if ((fd[0] = open (pty, O_RDWR)) >= 0) {                sprintf (tty, "/dev/tty%c%c", *majorp, *minorp);                if ((fd[1] = open (tty, O_RDWR)) >= 0) {#ifndef HAVE_TERMIOS_H                    ioctl (fd[1], TCGETA, &tio);                    tio.c_lflag &= ~ECHO;                    ioctl (fd[1], TCSETA, &tio);#else                    tcgetattr (fd[1], &tio);                    tio.c_lflag &= ~ECHO;                    tcsetattr (fd[1], TCSANOW, &tio);#endif                    return 0;                }                close (fd[0]);            }        }    }    return -1;}static void pipeopen (char *cmd, FILE **ifp, FILE **ofp, int *pidp) {    int p1[2], p2[2];    char cmd2[1024];    char *s;    if (pipe (p1) == -1 || pipe (p2) == -1) {        *ifp = NULL;        return;    }    switch ((*pidp = FORK ())) {    case -1:        panic2 (POS, "pipeopen", "cannot fork");    case 0:        close (p1[0]), close (p2[1]);        for (s = cmd; *s; s++)            if (*s == '%' && *(s + 1) && *(s + 1) == 'd') {                sprintf (cmd2, cmd, p2[0], p1[1]);                execl (shell, shbname, "-c", cmd2, NULL);                panic2 (POS, "pipeopen", "child cannot exec: %s\n", cmd2);            }        close (1), dup (p1[1]), close (p1[1]);        close (0), dup (p2[0]), close (p2[0]);        execl (shell, shbname, "-c", cmd, NULL);        panic2 (POS, "pipeopen", "child cannot exec: %s\n", cmd);    default:        close (p1[1]), close (p2[0]);    }    fcntl (p1[0], F_SETFD, FD_CLOEXEC);    fcntl (p2[1], F_SETFD, FD_CLOEXEC);    *ifp = fdopen (p1[0], "r"), *ofp = fdopen (p2[1], "a");    return;}static void socketopen (char *cmd, int sfd, FILE **ifp, FILE **ofp, int *pidp) {    int fd;    switch ((*pidp = FORK ())) {    case -1:        panic2 (POS, "socketopen", "cannot fork");    case 0:        execl (shell, shbname, "-c", cmd, NULL);        panic2 (POS, "socketopen", "child cannot exec: %s\n", cmd);    default:        if ((fd = accept (sfd, NULL, NULL)) < 0) {            *ifp = NULL;            return;        }    }    fcntl (fd, F_SETFD, FD_CLOEXEC);    *ifp = fdopen (fd, "r"), *ofp = fdopen (fd, "a+");    return;}static void sigchldhandler (int data) {    while (waitpid (-1, NULL, WNOHANG) > 0)        ;    signal (SIGCHLD, sigchldhandler);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -