Exemplo n.º 1
0
/* free this finfo and remove from list */
static int FinfoFree(char *fname)
{
  Finfo finfo;

  /* sanity check */
  if( !fname ) return 1;
  /* look for the appropriate finfo */
  if( (finfo=FinfoLookup(fname)) != NULL ){
    if( FinfoGetCurrent() == finfo ) FinfoSetCurrent(NULL);
    _FinfoFree(finfo);
    return 0;
  }
  return 1;
}
Exemplo n.º 2
0
/* process this command */
static int ProcessCmd(char *cmd, char **args, int narg, int node, int tty)
{
  char tbuf[SZ_LINE];
  Finfo finfo, tfinfo;
#if HAVE_CFITSIO
  int xlims[2], ylims[2], bin, got, hdutype, hdunum, ncard;
  int status=0, tstatus=0;
  int dims[2];
  double cens[2];
  char extname[FLEN_CARD];
  char *cols[2] = {"X", "Y"};
  char *ofile="stdout";
  char *section=NULL;
  char *filter=NULL;
  char *slice=NULL;
  char *cardstr=NULL;
  void *tcens=NULL;
  fitsfile *ifptr, *ofptr, *tfptr;
#endif
  switch(*cmd){
  case 'f':
    if( !strcmp(cmd, "fitsFile") ){
      if( narg ){
	if( !(tfinfo=FinfoLookup(args[0])) ){
	  fprintf(stderr, NOIMAGE, args[0]);
	  return 1;
	}
      } else if( !(tfinfo=FinfoGetCurrent()) ){
	fprintf(stderr, NOFINFO, cmd);
	return 1;
      }
      if( tfinfo->fitsfile ){
	if( node ) fprintf(stdout, "fitsFile\r");
	fprintf(stdout, "%s %s\n", tfinfo->fname, tfinfo->fitsfile);
	fflush(stdout);
      }
      return 0;
    }
    break;
    break;
  case 'i':
    if( !strcmp(cmd, "image") ){
      if( !narg ){
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      /* new image */
      if( !(finfo = FinfoNew(args[0])) ){
	return 1;
      }
      /* make it current */
      FinfoSetCurrent(finfo);
      if( node ) fprintf(stdout, "image\r");
      /* return the FITS file name, if possible */
      fprintf(stdout, "%s %s\n",
	      finfo->fname, finfo->fitsfile ? finfo->fitsfile : "?");
      fflush(stdout);
      return 0;
    } else if( !strcmp(cmd, "image_") ){
      if( !narg ){
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      /* new image */
      if( !(finfo = FinfoNew(args[0])) ){
	return 1;
      }
      /* make it current */
      FinfoSetCurrent(finfo);
      /* no output! */
      return 0;
    } else if( !strcmp(cmd, "imsection") ){
#if HAVE_CFITSIO
      if( !(finfo=FinfoGetCurrent()) ){
	fprintf(stderr, NOFINFO, cmd);
	return 1;
      }
      if( narg < 2 ){
	fprintf(stderr, WRONGARGS2, cmd, 2);
	return 1;
      }
      ifptr = openFITSFile(finfo->fitsfile, READONLY, EXTLIST, &hdutype,
			   &status);
      if( status ){
	fprintf(stderr, "ERROR: can't open FITS file '%s'\n", finfo->fitsfile);
	return 1;
      }
      /* process args */
      ofile = args[0];
      section = args[1];
      if( narg >= 3 && args[2] ){
	filter = args[2];
      }
      if( narg >= 4 && args[3] ){
	slice = args[3];
      }
      if( !section || !(got = parseSection(ifptr, hdutype, section,
					   xlims, ylims, dims, cens, &bin)) ){
	fprintf(stderr,
		"ERROR: can't parse section for '%s' [%s]\n",
		finfo->fitsfile, (args && args[0]) ? args[0] : "NONE");
	return 1;
      }
      /* output image */
      fits_create_file(&ofptr, ofile, &status);
      if( status ){
	fits_get_errstatus(status, tbuf);
	fprintf(stderr,
		"ERROR: can't open output FITS file to section '%s' [%s]\n",
		finfo->fitsfile, tbuf);
	return 1;
      }
      switch(hdutype){
      case IMAGE_HDU:
	/* image: let cfitsio make a section */
	if( copyImageSection(ifptr, ofptr, dims, cens, bin, slice, &status) ){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't copy image section for '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  return 1;
	}
	break;
      default:
	/* table: let jsfitsio create an image section by binning the table */
	tfptr = filterTableToImage(ifptr, filter, cols, dims, cens, 1, &status);
	if( status ){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't create image from table for '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  return 1;
	}
	fits_read_key(tfptr, TSTRING, "CTYPE1", tbuf, NULL, &status);
	if( status == 0 ){
	  if( strstr(tbuf, "--HPX") || strstr(tbuf, "--hpx") ){
	    tcens = cens;
	  }
	}
	status = 0;

	/* copy section to new image */
	if( copyImageSection(tfptr, ofptr, dims, tcens, bin, NULL, &status) ){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't copy image section for '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  return 1;
	}
	tstatus = 0;
	closeFITSFile(tfptr, &tstatus);
	break;
      }
      if( status ){
	fits_get_errstatus(status, tbuf);
	fprintf(stderr,
		"ERROR: can't create section FITS file for '%s' [%s]\n",
		finfo->fitsfile, tbuf);
	closeFITSFile(ofptr, &status);
	return 1;
      }
      // return a json object with info about original data
      fprintf(stdout, "{\"file\":\"%s\"", finfo->fitsfile);
      fprintf(stdout, ",\"type\":%d", hdutype);
      ffghdn(ifptr, &hdunum);
      fprintf(stdout, ",\"extnum\":%d", hdunum-1);
      tstatus=0;
      ffgky(ifptr, TSTRING, "EXTNAME", extname, NULL, &tstatus);
      if( !tstatus ){
	fprintf(stdout, ",\"extname\":\"%s\"", extname);
      }
      fprintf(stdout, ",\"hdus\":");
      _listhdu(finfo->fitsfile, NULL);
      tstatus=0;
      getHeaderToString(ifptr, &cardstr, &ncard, &tstatus);
      if( cardstr ){
	fprintf(stdout, ",\"ncard\":%d",ncard);
	fprintf(stdout, ",\"cardstr\":\"%s\"",cardstr);
	free(cardstr);
      }
      fprintf(stdout, "}\n");
      fflush(stdout);
      tstatus=0;
      closeFITSFile(ifptr, &tstatus);
      tstatus=0;
      closeFITSFile(ofptr, &tstatus);
      return 0;
#else
      fprintf(stderr,
	      "ERROR: for section support, build js9helper with cfitsio\n");
      return 1;
#endif
    } else if( !strcmp(cmd, "info") ){
      if( tty ){
	if( !(finfo=FinfoGetCurrent()) ){
	  fprintf(stderr, NOFINFO, cmd);
	  return 1;
	}
	/* make sure we have a wcs */
	fprintf(stdout, "fname:\t%s\n", finfo->fname);
	fprintf(stdout, "fits:\t%s\n", finfo->fitsfile?finfo->fitsfile:"N/A");
	fflush(stdout);
      }
      return 0;
    }
    break;
  case 'l':
    /* list all images */
    if( !strcmp(cmd, "list") ){
      FinfoList(stdout);
      return 0;
#if HAVE_CFITSIO
    } else if( !strcmp(cmd, "listhdus") ){
      if( !(finfo=FinfoGetCurrent()) ){
	fprintf(stderr, NOFINFO, cmd);
	return 1;
      }
      _listhdu(finfo->fitsfile, NULL);
      fflush(stdout);
      return 0;
#endif
    }
    break;
  case 's':
    if( !strcmp(cmd, "setDataPath") ){
      if( narg ){
	setenv("JS9_DATAPATH", args[0], 1);
	if( node ) fprintf(stdout, "setDataPath\r");
	fprintf(stdout, "%s\n", getenv("JS9_DATAPATH"));
	fflush(stdout);
      } else {
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      return 0;
    }
    break;
  case 'u':
    if( !strcmp(cmd, "unimage") ){
      if( !narg ){
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      /* close this image */
      FinfoFree(args[0]);
      return 0;
    }
    break;
  case '#':
  case '\0':
    return 0;
  default:
    break;
  }
  /* if we reached here, we did not recognize the command */
  fprintf(stderr, "ERROR: unknown command '%s'\n", cmd);
  /* return the news */
  return 2;
}
Exemplo n.º 3
0
/* create a new finfo record, open FITS file */
static Finfo FinfoNew(char *fname)
{
  int len;
  char *e=NULL;
  char *f=NULL;
  char *s=NULL;
#if FITS2PNG
  int i;
  unsigned char header[8];
  /* use volatile to make gcc [-Wclobbered] happy (because of setjmp below) */
  volatile Finfo finfo;	  
#else
  Finfo finfo;	  
#endif


  /* sanity check */
  if( !fname ) return NULL;
  /* return existing finfo, if possible */
  if( (finfo=FinfoLookup(fname)) ) return finfo;
  /* allocate record */
  if( !(finfo = (Finfo)xcalloc(sizeof(FinfoRec), 1)) ){
    fprintf(stderr, "ERROR: can't allocate rec for image\n");
    return NULL;
  }
  /* save file name */
  finfo->fname = xstrdup(fname);
  /* check for file type */
  if( (s = strrchr(fname, '.')) && !strcasecmp(s, ".png") ){
    /* its a PNG */
    finfo->ftype = FTYPE_PNG;
  } else {
    /* assume FITS type */
    finfo->ftype = FTYPE_FITS;
  }
  /* open file */
  switch(finfo->ftype){
  case FTYPE_PNG:
#if FITS2PNG
    /* code taken from "PNG: The Definitive Guide" by Greg Roelofs,
       Chapter 13 "Reading PNG Images" */
    /* set data path */
    datapath = getenv("JS9_DATAPATH");
    /* look for path of the PNG file */
    s = Find(fname, "r", NULL, datapath);
    if( s && *s ){
      if( !(finfo->fp = fopen(s, "rb")) ){
	fprintf(stderr, "ERROR: can't open PNG file '%s'\n", fname);
	goto error;
      }
      fread(header, 1, 8, finfo->fp);
      if( png_sig_cmp(header, 0, 8) ){
	fprintf(stderr, "ERROR: not recognized as a PNG file '%s'\n", fname);
	goto error;
      }
      /* initialize stuff */
      finfo->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
					      NULL, NULL, NULL);
      if( !finfo->png_ptr ){
	fprintf(stderr, "ERROR: png_create_read_struct failed '%s'\n", fname);
	goto error;
      }
      finfo->info_ptr = png_create_info_struct(finfo->png_ptr);
      if( !finfo->info_ptr ){
	fprintf(stderr, "ERROR: png_create_info_struct failed '%s'\n", fname);
	goto error;
      }
      if( setjmp(png_jmpbuf(finfo->png_ptr)) ){
	fprintf(stderr, "ERROR: during png init_io '%s'\n", fname);
	goto error;
      }
      png_init_io(finfo->png_ptr, finfo->fp);
      png_set_sig_bytes(finfo->png_ptr, 8);
      png_read_info(finfo->png_ptr, finfo->info_ptr);
      /* get the text chunks that come before the image */
      if( png_get_text(finfo->png_ptr, finfo->info_ptr,
		       &(finfo->text_ptr), &(finfo->num_text)) > 0 ){
	/* process all known PNG keywords */
	for(i=0; i<finfo->num_text; i++){
	  if( !strcmp(finfo->text_ptr[i].key, FITSFILE) ){
	    finfo->fitsfile = xstrdup(finfo->text_ptr[i].text);
	    /* remove the extension that was used to generate png */
	    s = strchr(finfo->fitsfile, '[');
	    if( s ){
	      *s = '\0';
	    }
	  }
	}
      }
    } else {
      fprintf(stderr, "ERROR: can't find PNG file '%s' [data path: %s]\n",
	      fname, datapath?datapath:"none");
      goto error;
    }
#else
    fprintf(stderr,
	    "ERROR: for fits2png support, build JS9 using --with-png\n");
    goto error;
#endif
    break;
    /* look for an error */
  case FTYPE_FITS:
    /* fits file can have an extension */
    f = FileRoot(fname);
    /* set data path */
    datapath = getenv("JS9_DATAPATH");
    /* look for path of the FITS file */
    s = Find(f, "r", NULL, datapath);
    xfree(f);
    if( s && *s ){
      len = strlen(s) + 1;
      /* construct full path to fits file + extension */
      e = FileExtension(fname);
      if( e ){
        len += strlen(e);
      }
      finfo->fitsfile = xmalloc(len);
      strcpy(finfo->fitsfile, s);
      if( e ){
        strcat(finfo->fitsfile, e);
      }
      xfree(s);
    } else {
      fprintf(stderr, "ERROR: can't find FITS file '%s' [data path: %s]\n",
	      fname, datapath?datapath:"none");
      goto error;
    }
    break;
  default:
    fprintf(stderr, "ERROR: unknown file type '%s'\n", fname);
    goto error;
    break;
  }
  /* add this finfo to end of list of existing finfos */
  FinfoListAdd(&finfohead, finfo);
  /* return the news */
  return finfo;
error:
  /* free up struct and return nothing */
  _FinfoFree(finfo);
  return NULL;
}
Exemplo n.º 4
0
/* process this command */
static int ProcessCmd(char *cmd, char **args, int node, int tty)
{
  int ip=0;
  char tbuf[SZ_LINE];
  Finfo finfo, tfinfo;
#if HAVE_CFITSIO
  int x0, x1, y0, y1, bin;
  int xcolnum, ycolnum, hdunum, hdutype;
  int status=0, status2=0;
  int dims[2];
  double cens[2];
  char *cols[2] = {"X", "Y"};
  char *ofile=NULL;
  char *omode=NULL;
  fitsfile *ifptr, *ofptr, *tfptr;
#endif

  switch(*cmd){
  case 'f':
    if( !strcmp(cmd, "fitsFile") ){
      if( args && word(args[0], tbuf, &ip) ){
	if( !(tfinfo=FinfoLookup(tbuf)) ){
	  fprintf(stderr, NOIMAGE, tbuf);
	  return 1;
	}
      } else if( !(tfinfo=FinfoGetCurrent()) ){
	fprintf(stderr, NOFINFO, cmd);
	return 1;
      }
      if( tfinfo->fitsfile ){
	if( node ) fprintf(stdout, "fitsFile\r");
	fprintf(stdout, "%s %s\n", tfinfo->fname, tfinfo->fitsfile);
	fflush(stdout);
      }
      return 0;
    }
    break;
    break;
  case 'i':
    if( !strcmp(cmd, "image") ){
      if( !args || !word(args[0], tbuf, &ip) ){
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      /* new image */
      if( !(finfo = FinfoNew(tbuf)) ){
	fprintf(stderr, NONEW, cmd);
	return 1;
      }
      /* make it current */
      FinfoSetCurrent(finfo);
      if( node ) fprintf(stdout, "image\r");
      /* return the FITS file name, if possible */
      fprintf(stdout, "%s %s\n",
	      finfo->fname, finfo->fitsfile ? finfo->fitsfile : "?");
      fflush(stdout);
      return 0;
    } else if( !strcmp(cmd, "image_") ){
      if( !args || !word(args[0], tbuf, &ip) ){
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      /* new image */
      if( !(finfo = FinfoNew(tbuf)) ){
	fprintf(stderr, NONEW, cmd);
	return 1;
      }
      /* make it current */
      FinfoSetCurrent(finfo);
      /* no output! */
      return 0;
    } else if( !strcmp(cmd, "imsection") ){
#if HAVE_CFITSIO
      if( !(finfo=FinfoGetCurrent()) ){
	fprintf(stderr, NOFINFO, cmd);
	return 1;
      }
      ifptr = openFITSFile(finfo->fitsfile, EXTLIST, &hdutype, &status);
      if( status ){
	fprintf(stderr, "ERROR: can't open FITS file '%s'\n", finfo->fitsfile);
	return 1;
      }
      if( !args || !parseSection(args[0], &x0, &x1, &y0, &y1, &bin) ){
	fprintf(stderr,
		"ERROR: can't parse section for '%s' [%s]\n",
		finfo->fitsfile, (args && args[1]) ? args[1] : "NONE");
	return 1;
      }
      if( args[1] ){
	omode = args[1];
      } else {
	omode = "native";
      }
      ofile = "stdout";
      // create image if ifile is an image or omode is not native
      if( (hdutype == IMAGE_HDU) || strcmp(omode, "native") ){
	fits_create_file(&ofptr, ofile, &status);
	if( status ){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't open output FITS file to section '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  return 1;
	}
	switch(hdutype){
	case IMAGE_HDU:
	  if( bin != 1 ){
	    fprintf(stderr,
		    "ERROR: imsection of an image must use bin 1 for '%s'\n",
		    finfo->fitsfile);
	    return 1;
	  }
	  snprintf(tbuf, SZ_LINE-1, "%d:%d,%d:%d", x0, x1, y0, y1);
	  fits_copy_image_section(ifptr, ofptr, tbuf, &status);
	  break;
	default:
	  dims[0] = x1 - x0 + 1;
	  dims[1] = y1 - y0 + 1;
	  cens[0] = (x0 + x1) / 2;
	  cens[1] = (y0 + y1) / 2;
	  tfptr = filterTableToImage(ifptr, NULL, cols, dims, cens, bin,
				     &status);
	  if( status ){
	    fits_get_errstatus(status, tbuf);
	    fprintf(stderr,
		    "ERROR: can't create image from table for '%s' [%s]\n",
		    finfo->fitsfile, tbuf);
	    return 1;
	  }
	  fits_copy_image_section(tfptr, ofptr, "*,*", &status);
	  closeFITSFile(tfptr, &status2);
	  break;
	}
	if( status ){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't write section FITS file for '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  closeFITSFile(ofptr, &status);
	  return 1;
	}
	closeFITSFile(ofptr, &status);
      } else {
	// extract (native) table
	snprintf(tbuf, SZ_LINE-1,
		 "x >= %d && x <= %d && y >= %d && y <= %d",
		 x0, x1, y0, y1);
	// ffselect_table(&ifptr, ofile, tbuf, &status);
	// copied from cfileio.c/ffselect_table()
	/* create new empty file to hold copy of the image */
	if (ffinit(&ofptr, ofile, &status) > 0) {
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't init section file for '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  return 1;
	}
	/* save current HDU number in input file */
	fits_get_hdu_num(ifptr, &hdunum);
	/* copy the primary array */
	fits_movabs_hdu(ifptr, 1, NULL, &status);
	if( fits_copy_hdu(ifptr, ofptr, 0, &status) > 0){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't copy primary for section file '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  fits_close_file(ofptr, &status);
	  return 1;
	}
	/* back to current hdu */
	fits_movabs_hdu(ifptr, hdunum, NULL, &status);
	/* copy all the header keywords from the input to output file */
	if (fits_copy_header(ifptr, ofptr, &status) > 0){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't copy header for section file '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  fits_close_file(ofptr, &status);
	  return 1;
	}
	/* set number of rows = 0 */
	/* warning: start of cfitsio black magic */
	fits_modify_key_lng(ofptr, "NAXIS2", 0, NULL, &status);
	(ofptr->Fptr)->numrows = 0;
	(ofptr->Fptr)->origrows = 0;
	/* force the header to be scanned */
	if (ffrdef(ofptr, &status) > 0){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't rdef for section file '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  fits_close_file(ofptr, &status);
	  return 1;
	}
	/* warning: end of cfitsio black magic */
	/* select filtered rows and write to output file */
	if (fits_select_rows(ifptr, ofptr, tbuf, &status) > 0){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't select rows for section file '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  fits_close_file(ofptr, &status);
	  return 1;
	}
	/* update params for this section */
	if( (fits_get_colnum(ofptr, CASEINSEN, "X", &xcolnum, &status) > 0) ||
	    (fits_get_colnum(ofptr, CASEINSEN, "Y", &ycolnum, &status) > 0) ){
	  fits_get_errstatus(status, tbuf);
	  fprintf(stderr,
		  "ERROR: can't find X,Y cols for section file '%s' [%s]\n",
		  finfo->fitsfile, tbuf);
	  fits_close_file(ofptr, &status);
	  return 1;
	}
	/* we can ignore errors here */
	status = 0;
	snprintf(tbuf, SZ_LINE-1, "TALEN%d", xcolnum);
	fits_modify_key_lng(ofptr, tbuf, x1-x0, NULL, &status);
	status = 0;
	snprintf(tbuf, SZ_LINE-1, "TALEN%d", ycolnum);
	fits_modify_key_lng(ofptr, tbuf, y1-y0, NULL, &status);
	status = 0;
	snprintf(tbuf, SZ_LINE-1, "TLMIN%d", xcolnum);
	fits_modify_key_flt(ofptr, tbuf, x0, 6, NULL, &status);
	status = 0;
	snprintf(tbuf, SZ_LINE-1, "TLMAX%d", xcolnum);
	fits_modify_key_flt(ofptr, tbuf, x1, 6, NULL, &status);
	status = 0;
	snprintf(tbuf, SZ_LINE-1, "TLMIN%d", ycolnum);
	fits_modify_key_flt(ofptr, tbuf, y0, 6, NULL, &status);
	status = 0;
	snprintf(tbuf, SZ_LINE-1, "TLMAX%d", ycolnum);
	fits_modify_key_flt(ofptr, tbuf, y1, 6, NULL, &status);
	/* close the output file */
	status = 0;
	fits_close_file(ofptr, &status);
      }
      closeFITSFile(ifptr, &status);
      return 0;
#else
      fprintf(stderr,
	      "ERROR: for section support, build js9helper with cfitsio\n");
      return 1;
#endif
    } else if( !strcmp(cmd, "info") ){
      if( tty ){
	if( !(finfo=FinfoGetCurrent()) ){
	  fprintf(stderr, NOFINFO, cmd);
	  return 1;
	}
	/* make sure we have a wcs */
	fprintf(stdout, "fname:\t%s\n", finfo->fname);
	fprintf(stdout, "fits:\t%s\n", finfo->fitsfile?finfo->fitsfile:"N/A");
	fflush(stdout);
      }
      return 0;
    }
    break;
  case 'l':
    /* list all images */
    if( !strcmp(cmd, "list") ){
      FinfoList(stdout);
      return 0;
    }
    break;
  case 's':
    if( !strcmp(cmd, "setDataPath") ){
      if( args && word(args[0], tbuf, &ip) ){
	setenv("JS9_DATAPATH", tbuf, 1);
	if( node ) fprintf(stdout, "setDataPath\r");
	fprintf(stdout, "%s\n", getenv("JS9_DATAPATH"));
	fflush(stdout);
      } else {
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      return 0;
    }
    break;
  case 'u':
    if( !strcmp(cmd, "unimage") ){
      if( !args || !word(args[0], tbuf, &ip) ){
	fprintf(stderr, WRONGARGS, cmd, 1, 0);
	return 1;
      }
      /* close this image */
      FinfoFree(tbuf);
      return 0;
    }
    break;
  case '#':
  case '\0':
    return 0;
  default:
    break;
  }
  /* if we reached here, we did not recognize the command */
  fprintf(stderr, "ERROR: unknown command '%s'\n", cmd);
  /* return the news */
  return 2;
}