DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦8e9888ff7⟧ TextFile

    Length: 10770 (0x2a12)
    Types: TextFile
    Names: »pipe.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/others/quipu/uips/fred/pipe.c« 

TextFile

/* pipe.c - fred talks to dish */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/others/quipu/uips/fred/RCS/pipe.c,v 7.3 90/01/16 20:43:41 mrose Exp $";
#endif

/* 
 * $Header: /f/osi/others/quipu/uips/fred/RCS/pipe.c,v 7.3 90/01/16 20:43:41 mrose Exp $
 *
 *
 * $Log:	pipe.c,v $
 * Revision 7.3  90/01/16  20:43:41  mrose
 * last check-out
 * 
 * Revision 7.2  90/01/11  18:36:39  mrose
 * real-sync
 * 
 * Revision 7.1  89/12/13  20:01:51  mrose
 * errfp
 * 
 * Revision 7.0  89/11/23  22:09:03  mrose
 * Release 6.0
 * 
 */

/*
 *				  NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


#include <signal.h>
#include "fred.h"
#include "internet.h"

#include <sys/ioctl.h>
#ifndef	SYS5
#include <sys/file.h>
#else
#if	!defined(AIX) && !defined(HPUX)
#include <sys/fcntl.h>
#else
#include <fcntl.h>
#endif
#endif
#include <sys/stat.h>
#include "usr.dirent.h"
#ifdef	BSD42
#include <sys/wait.h>
#endif

/* \f

 */

int	didbind = 0;
int	dontpage = 0;

static int	dish_running = NOTOK;

static struct sockaddr_in sin;

/* \f

   DISH */

int	dish (command, silent)
char   *command;
int	silent;
{
    int	    cc,
	    isarea,
	    isuser,
	    n,
	    sd,
	    status;
    char    buffer[BUFSIZ],
	    where[BUFSIZ];
    register struct sockaddr_in *sock = &sin;
    FILE   *fp;

    if (watch) {
	fprintf (stderr, "%s\n", command);
	(void) fflush (stderr);
    }

    isarea = strncmp (command, "moveto -pwd", sizeof "moveto -pwd" - 1)
		? 0 : 1;
    isuser = !isarea && strcmp (command, "squid -user") == 0;

    if (dish_running != NOTOK && kill (dish_running, 0) == NOTOK)
	dish_running = NOTOK;

    if (dish_running == NOTOK) {
	int	vecp;
	char	dishname[BUFSIZ],
	       *vec[10];
	static int very_first_time = 1;

	if (very_first_time) {
	    (void) unsetenv ("DISHPROC");
	    (void) unsetenv ("DISHPARENT");

	    very_first_time = 0;
	}

	if (get_dish_sock (&sin, getpid ()) == NOTOK)
	    exit (1);

	(void) strcpy (dishname, _isodefile (isodebinpath, "dish"));

fork_again: ;
	switch (dish_running = vfork ()) {
	    case NOTOK:
	        adios ("fork", "unable to");
		/* NOT REACHED */

	    case OK:
		if (ifd != NOTOK)
		    (void) close (ifd);
		if (ofd != NOTOK)
		    (void) close (ofd);
		vecp = 0;
		vec[vecp++] = "dish";
		vec[vecp++] = "-pipe";
		vec[vecp++] = "-fast";
		vec[vecp] = NULL;
		(void) execv (dishname, vec);
		fprintf (stderr, "unable to exec ");
		perror (dishname);
		_exit (1);

	    default:
		for (;;) {
		    if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0))
			    == NOTOK)
			adios ("client", "unable to start");
		    if (join_tcp_server (sd, sock) != NOTOK)
			break;

		    (void) close_tcp_socket (sd);

		    sleep (5);

		    if (kill (dish_running, 0) == NOTOK)
			goto fork_again;
		}
		didbind = 0;
		(void) signal (SIGPIPE, SIG_IGN);
		break;
	}
    }
    else {
	if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0)) == NOTOK)
	    adios ("client", "unable to start");
	if (join_tcp_server (sd, sock) == NOTOK)
	    adios ("server", "unable to join");
    }

    n = send (sd, command, cc = strlen (command), 0);
    if (debug)
	fprintf (stderr, "wrote %d of %d octets to DUA\n", n, cc);

    if (n != cc)
	if (n == NOTOK) {
	    advise ("please retry", "write to DUA failed,");
	    (void) f_quit (NULLVP);
	    (void) close_tcp_socket (sd);
	    return NOTOK;
	}
	else
	    adios (NULLCP, "write to DUA truncated, sent %d of %d octets",
		   n, cc);

    status = OK;
    for (;;) {
	if ((cc = recv (sd, buffer, sizeof buffer - 1, 0)) == NOTOK) {
	    if (!interrupted)
		adios ("failed", "read from DUA");

	    (void) kill (dish_running, SIGINT);
	    interrupted = 0;
	    continue;
	}

	buffer[cc] = NULL;
	if (debug)
	    fprintf (stderr, "read %d octets from DUA: 0x%x\n", cc, buffer[0]);
	if (cc == OK) {
	    if (kill (dish_running, 0) == NOTOK)
		advise (NULLCP, "lost DUA");

	    break;
	}

	switch (buffer[0]) {
	    case '2':
	        if ((fp = errfp) == NULL)
		    fp = stdfp != stdout ? stdfp : stderr;
		status = NOTOK;
		
copy_out: ;
	        if (cc > 1 && !silent)
		    paginate (fp, buffer + 1, cc - 1);
			    
		while ((cc = recv (sd, buffer, sizeof buffer - 1, 0)) > OK)
		    if (!silent)
			paginate (fp, buffer, cc);

		if (!silent)
		    paginate (fp, NULLCP, 0);
		break;

	    case '1':
	    case '3':
		if (isarea || isuser) {
		    char   *cp,
			  **vp;

		    if (cp = index (buffer + 1, '\n'))
			*cp = NULL;
#ifdef	notdef
		    if (buffer[1] == NULL)
			break;
#endif
		    buffer[0] = '@';
		    vp = isarea ? &myarea : &mydn;

		    if (*vp)
			free (*vp);
		    *vp = strdup (buffer);
		}
		fp = stdfp;
		goto copy_out;

	    case 'e':
		if (watch) {
		    fprintf (stderr, "%s\n", buffer + 1);
		    (void) fflush (stderr);
		}
		if (system (buffer + 1))
		    (void) strcpy (where, "e");
		else
		    (void) getcwd (where, sizeof where);
		goto stuff_it;

	    case 'y':
		if (network)
		    (void) strcpy (where, "n");
		else {
		    fprintf (stderr, "%s", buffer + 1);
		    (void) fflush (stderr);
		    (void) fgets (where, sizeof where, stdin);
		}
		goto stuff_it;

	    case 'p':
		(void) sprintf (where, "Enter password for \"%s\": ",
				buffer + 1);
		(void) strcpy (where, getpassword (where));

stuff_it: ;
		n = send (sd, where, cc = strlen (where), 0);
		if (debug)
		    fprintf (stderr, "wrote %d of %d octets to DUA\n", n, cc);

		if (n != cc)
		    if (n == NOTOK) {
			advise ("please retry", "write to DUA failed,");
			(void) f_quit (NULLVP);
			(void) close_tcp_socket (sd);
			return NOTOK;
		    }
		    else
			adios (NULLCP,
			       "write to DUA truncated, sent %d of %d octets",
			       n, cc);
		continue;

	    default:
		advise (NULLCP, "unexpected opcode 0x%x -- contact a camayoc",
			buffer[0]);
		break;
	}
	break;
    }

    (void) close_tcp_socket (sd);

    return status;
}

/* \f

 */

paginate (fp, buffer, cc)
FILE   *fp;
char   *buffer;
int	cc;
{
    static int first_time = 1;
    static int doing_pager = 0;
    static int pid = NOTOK;
    static int sd = NOTOK;
    static SFP istat, qstat;

    if (cc == 0) {
#ifndef	BSD42
	int	status;
#else
	union wait status;
#endif
	int	child;

	first_time = 1;
	(void) fflush (fp);
	if (!doing_pager)
	    return;

	doing_pager = 0;

	if (dup2 (sd, fileno (fp)) == NOTOK)
	    adios ("standard output", "unable to dup2");

	clearerr (fp);
	(void) close (sd);

	while ((child = wait (&status)) != NOTOK && pid != child)
	    continue;

	(void) signal (SIGINT, istat);
	(void) signal (SIGQUIT, qstat);

	return;
    }

    if (first_time) {
	int	pd[2];

	first_time = 0;

	if (dontpage || network || *pager == NULL || !isatty (fileno (fp)))
	    goto no_pager;

	(void) fflush (fp);

	foreground ();

	if ((sd = dup (fileno (fp))) == NOTOK) {
	    advise ("dup", "unable to");
	    goto no_pager;
	}

	if (pipe (pd) == NOTOK) {
	    advise ("pipe", "unable to");
	    goto no_pager;
	}
	switch (pid = fork ()) {
	    case NOTOK:
	        advise ("fork", "unable to");
		(void) close (pd[0]);
		(void) close (pd[1]);
		goto no_pager;

	    case OK:
		(void) signal (SIGINT, SIG_DFL);
		(void) signal (SIGQUIT, SIG_DFL);

		(void) close (pd[1]);
		if (pd[0] != fileno (stdin)) {
		    (void) dup2 (pd[0], fileno (stdin));
		    (void) close (pd[0]);
		}
		if (readonly)
		    mypager (stdin);
		else {
		    execlp (pager, pager, NULLCP);
		    fprintf (stderr, "unable to exec ");
		    perror (pager);
		}
		_exit (-1);

	    default:
		(void) close (pd[0]);
		if (pd[1] != fileno (fp)) {
		    (void) dup2 (pd[1], fileno (fp));
		    (void) close (pd[1]);
		}
		break;
	}

	istat = signal (SIGINT, SIG_IGN);
	qstat = signal (SIGQUIT, SIG_IGN);

	doing_pager = 1;
    }

no_pager: ;
    if (network && !mail) {
	register char *cp,
		      *dp;

	for (dp = (cp = buffer) + cc; cp < dp; cp++) {
	    if (*cp == '\n')
		(void) fputc ('\r', fp);
	    (void) fputc (*cp, fp);
	}
    }
    else
	(void) fwrite (buffer, sizeof buffer[0], cc, fp);
}

/* \f

 */

/* if you start a fred command and then background fred, if your pager is less,
   then for some reason, less gets the terminal modes/process groups messed up.

   this code pretty much ensures that fred is running in the foreground when
   it forks less.  there is still a critical window, but it is very small...
 */

static  foreground () {
#ifdef	TIOCGPGRP
    int     pgrp,
            tpgrp;
    SFP	    tstat;

    if ((pgrp = getpgrp (0)) == NOTOK)
	return;

    tstat = signal (SIGTTIN, SIG_DFL);
    for (;;) {
	if (ioctl (fileno (stdin), TIOCGPGRP, (char *) &tpgrp) == NOTOK)
	    break;
	if (pgrp == tpgrp)
	    break;

	(void) kill (0, SIGTTIN);
    }
    (void) signal (SIGTTIN, tstat);
#endif
}

/* \f

 */

static	int	cols;
static	int	rows;
static	int	length = 0;
static	int	width = 0;


static	mypager (fp)
FILE   *fp;
{
    register char *bp;
    char    buffer[BUFSIZ];
#ifdef	TIOCGWINSZ
    struct winsize    ws;
#endif

#ifdef	TIOCGWINSZ
    if (ioctl (fileno (stdout), TIOCGWINSZ, (char *) &ws) != NOTOK)
	length = ws.ws_row, width = ws.ws_col;
#endif
    if (--length <= 0)
	length = 23;
    if (--width <= 0)
	width = 79;

    rows = cols = 0;

    while (fgets (buffer, sizeof buffer, fp))
	for (bp = buffer; *bp; bp++)
	    pagchar (*bp);

    (void) fflush (stdout);
}


static pagchar (ch)
char   ch;
{
    char    buffer[BUFSIZ];

    switch (ch) {
        case '\n':
	    cols = 0;
	    if (++rows < length)
		break;
	    (void) putc (0x07, stdout);
	    (void) fflush (stdout);
	    buffer[0] = NULL;
	    (void) read (fileno (stdout), buffer, sizeof buffer);
	    if (buffer[0] == '\n')
		rows = 0;
	    else {
		(void) putc ('\n', stdout);
		rows = length / 3;
	    }
	    return;

	case '\t':
	    cols |= 07;
	    cols++;
	    break;

	case '\b':
	    cols--;
	    break;

	case '\r':
	    cols = 0;
	    break;

	default:
	    if (ch >= ' ')
		cols++;
	    break;
	}

    if (cols >= width) {
	pagchar ('\n');
	pagchar (ch);
    }
    else
	(void) putc (ch, stdout);
}

/* \f

   BIND */

/* ARGSUSED */

int	f_bind (vec)
char  **vec;
{
    if (didbind) {
	didbind = 0;
	return OK;
    }

#ifdef	notdef
    if (dish_running == NOTOK || kill (dish_running, 0) == NOTOK)
	return dish ("bind", 0);

    return OK;
#else
    return dish ("bind", 0);
#endif
}

/* ARGSUSED */

/* \f

   QUIT */

int	f_quit (vec)
char  **vec;
{
    if (vec && *++vec != NULL && strcmp (*vec, "-help") == 0) {
	fprintf (stdfp, "quit\n");
	fprintf (stdfp, "    terminate fred\n");

	return OK;
    }

    if (dish_running != NOTOK) {
	(void) kill (dish_running, SIGHUP);

	dish_running = NOTOK;
    }
    
    return DONE;
}