Skip to content
Snippets Groups Projects
async.c 2.73 KiB
Newer Older
slevy's avatar
slevy committed
#include <stdio.h>
#include <stdlib.h>
/*
 * Async communication with external modules (subprocesses) for partiview.
 *
 * Stuart Levy, slevy@ncsa.uiuc.edu
 * National Center for Supercomputing Applications,
 * University of Illinois 2001.
 * This file is part of partiview, released under the
 * Illinois Open Source License; see the file LICENSE.partiview for details.
slevy's avatar
slevy committed

slevy's avatar
slevy committed
#ifdef WIN32
# include "winjunk.h"
#endif

slevy's avatar
slevy committed
#include "specks.h"
slevy's avatar
slevy committed
#include "partiviewc.h"
slevy's avatar
slevy committed
#include "findfile.h"	/* for tokenize() */
slevy's avatar
slevy committed
#include "futil.h"

#include <ctype.h>
#undef isspace		/* for irix 6.5 backward compat, sigh */
slevy's avatar
slevy committed

#if unix
# include <unistd.h>
#endif

#define MAX_ASYNC 8

FILE *asyncmd[MAX_ASYNC];

int specks_add_async( struct stuff *st, char *cmdstr, int replytoo )
{
  int i;

#if unix  /* not WIN32 */
  if(cmdstr == NULL)
    return -1;
  for(i = 0; i < MAX_ASYNC; i++) {
    if(asyncmd[i] == NULL) {
	asyncmd[i] = popen(cmdstr, "r");
#if !CAVEMENU
	parti_asyncfd( fileno( asyncmd[i] ) );
#endif
	return i;
    }
  }
#endif /*unix*/
  msg("Sorry, all %d async-command slots full: can't run %s", MAX_ASYNC, cmdstr);
  return -1;
}

int specks_check_async( struct stuff **stp )
{
  int i, any = 0;
  char *av[128];
  int ac;
  char buf[5120], tbuf[5120];
  static int reentered = 0;	/* Don't allow recursion! */

#if unix  /* not WIN32 */

  if(stp == NULL || *stp == NULL) return 0;
  if(reentered>0) return 0;
  reentered = 1;

  for(i = 0; i < MAX_ASYNC; i++) {
    int brackets = 0;
    int none = 1;
    int nlines = 0;

    while(asyncmd[i] && (none || brackets > 0)) {
	int c = (brackets>0) ? fnextc(asyncmd[i], 1)
			     : async_fnextc(asyncmd[i], 1);
	switch(c) {
	case EOF:
	    if(getenv("DBG")) msg("Closing async %d", i);
#if !CAVEMENU
	    parti_unasyncfd( fileno( asyncmd[i] ) );
#endif
	    pclose(asyncmd[i]);
	    asyncmd[i] = NULL;
	    break;
	case -2: /* NODATA */
	    none = 0;
	    break;
	default:
	    /* Got something.  Assume that we can read a whole line quickly. */
	    if(fgets(buf, sizeof(buf), asyncmd[i]) == NULL) {
		if(getenv("DBG")) msg("fgets: Closing async %d", i);
		pclose(asyncmd[i]);
		asyncmd[i] = NULL;
		break;
	    }
	    nlines++;
	    any++;

	    for(c = 0; isspace(buf[c]) || buf[c] == '{' || buf[c] == '}'; c++) {
		if(buf[c] == '{') brackets++;
		else if(buf[c] == '}' && brackets > 0) brackets--;
		buf[c] = ' ';
	    }
	    if(getenv("DBG")) msg("async %d[%d]{%d}: %s", i, nlines, brackets, buf);
	    ac = tokenize( buf, tbuf, COUNT(av), av, 0 );
	    if(ac > 0) {
		none = 0;
#if CAVEMENU
		if(!specks_parse_args( stp, ac, av ))
		    VIDI_queue_commandstr( buf );

#else /* non-virdir version */
		parti_redraw();
		specks_parse_args( stp, ac, av );
#endif
	    }

	}
    }
  }
  reentered = 0;
#endif /*unix not WIN32*/
  return any;
}