Solved

Is PrintScreen possible on Linux?

Posted on 1998-10-19
3
579 Views
Last Modified: 2008-03-10

Is it possible to use the printscreen-key to dump the text on the page to default printer?

If possible - how do you do it?

0
Comment
Question by:jonnybe
3 Comments
 

Expert Comment

by:shivinder_jit
ID: 2007496
are you using a terminal or a pc  to connect to the server?
0
 

Author Comment

by:jonnybe
ID: 2007497

I am running a 486 PC as a workstation with RedHat Linux 5.1 and want to use printscreen from a text-based telnet-session.


0
 
LVL 2

Accepted Solution

by:
JYoungman earned 100 total points
ID: 2007498
To dump a virtual console to a graphic file, run this program:-

/* vcdump
 *
 *    Copyright (C) 1998,  James A Youngman <jay@gnu.org>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 * Utility which generates a screendump of a Linux console,
 * in full colour, as a PPM or PNG file.
 *
 *  Output file sizes:-
 *   (the input is an 80x25 VC containing the Red Hat "cabaret" filesystem
 *    administration tool)
 *  Plain PPM             2321189 bytes
 *  Raw   PPM           768014 bytes
 *        PNG             9076 bytes (About 2K of which is text data, etc.)
 *
 * TODO list:-
 *      1. Do the right thing for a monochrome display.
 *
 *      2. Test with differently-sized screen modes, and differently-
 *         sized fonts cells.
 *    
 *      3. Find out if it is possible to use console fonts with widths
 *         other than 8; if so, fix this program since it assumes that
 *         it is not.
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <getopt.h>
#include <unistd.h>

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/kd.h>

#include <ppm.h>            /* we need libppm for writing the output. */

#ifdef USE_PNG
#include <png.h>            /* PNG support is optional. */
#endif

#define PROGNAME "vcdump"


#define FONT_BYTES           (8192)
#define FONT_LINES_PER_CHAR  (32)
#define VGA_PALDEPTH         (63)
#define VGA_COLOURS          (16) /* Number of colours in the VGA palette */
#define EFFECTS_PALETTE_SIZE (VGA_COLOURS * 2)
#define BG_COLOUR_BANK       (EFFECTS_PALETTE_SIZE / 2)

struct tagVcsaScreenInfo
{
  unsigned char lines, cols;      /* screen size */
  unsigned char x,     y;      /* cursor position */
};


static char rcs_id[] = "$Id: vcdump.c,v 1.6 1998/04/06 07:54:01 james Exp $";


/* colour_translations[] is an array; the on-screen colour is looked up in
 * this table before deciding which colour to use in the output file; this
 * allows us to make any given colour a copy of something else.  Typically,
 * this allows us to change a grey background into a white one.
 *
 * For output files which contain palettes, this is all done by palette
 * manipulation; for non-palette output files (PPM) this is done by modifying
 * the output for the relevant pixels.
 *
 * The first sixteen entries of the palette are used for the foreground
 * colours, and the second sixteen for the backgound colours.
 */
static unsigned colour_translations[EFFECTS_PALETTE_SIZE];

static int
screen_rows_to_font_height(int rr)
{
  /* This table is from the resizecons.c file in the Linux kbd package.
   */
  switch (rr)
    {
    case 25 : return 16;
    case 28 : return 14;
    case 30 : return 16;
    case 34 : return 14;
    case 36 : return 12;
    case 40 : return 12;
    case 44 : return 9;  
    case 50 : return 8;  
    case 60 : return 8;  
    default : return 8;  
    }
}

/* in_textmode()
 *
 * Returns nonzero if the VC to which the passed in fd refers is in
 * text mode.
 */
static int
in_textmode(int fd)
{
  long lmode;
  if (0 == ioctl(fd, KDGETMODE, &lmode))
    {
      return (lmode == KD_TEXT) ? 1 : 0;
    }
  else
    {
      perror("ioctl(KDGETMODE)");
      return 0;
    }
}

/* capture_vca
 *
 * Capture the text and attribute data from the vcsa device to which
 * fd refers.
 */
unsigned char *
capture_vca(int fd, struct tagVcsaScreenInfo *ps)
{
  void *p;
  size_t slen = sizeof(*ps);
  size_t ncells;

  /* Rewind to the start of the screen data */
  if (-1 == lseek(fd, 0, SEEK_SET))
    {
      perror("lseek (vcsa)");
      return NULL;
    }

  /* Read the header information, which contains the size */
  if (slen != read(fd, ps, slen))
    {
      perror("short read of header from vcsa device");
      return NULL;
    }
 
  /* Allocate a buffer for the screen data. */
  ncells = ps->lines * ps->cols;
  slen = 2u * ncells;
  p = malloc(slen);
  if (p)
    {
      /* Read in the screen data. */
      if (slen != read(fd, p, slen))
      {
        perror("short read of screen data from vcsa device");
        return NULL;
      }
      return p;                  /* done. */
    }
  else
    {
      perror("out of memory for screen data");
      return NULL;
    }
}

/* get_font()
 *
 * Capture the font information for the VC to which fd refers.
 */
int
get_font(int fd, unsigned char buf[FONT_BYTES])
{
  int i;
  i = ioctl(fd,GIO_FONT,buf);
  if (i)
    {
      perror("GIO_FONT ioctl error");
      return 0;
    }
  return 1;
}

/* get_vc_fds()
 *
 * Given a VC number, open the /dev/tty* and /dev/vcsa* devices
 * corresponding to it.
 */
int
get_vc_fds(int vcnum, int *vca_fd, int *tty_fd)
{
  char name[20];

  sprintf(name, "/dev/vcsa%d", vcnum);
  *vca_fd = open(name, O_RDONLY);
  if (*vca_fd < 0)
    perror(name);
 
  sprintf(name, "/dev/tty%d", vcnum);
  *tty_fd = open(name, O_RDONLY);
  if (*tty_fd < 0)
    perror(name);

  return (vca_fd >= 0) && (tty_fd >= 0);
}


/* Palette entries for the default VGA palette.  These are from table
 * 8.14 "Initial Values in the Color Registers", from "Programmer's
 * Guide to the EGA and VGA cards", by Richard E. Ferraro, 2nd Edn.,
 * Addison-Wesley, ISBN 0-201-57025-4.
 *
 * The VGA palette is 6-bit, and 2^6=64, so 63 is full-scale.
 */
struct tagPal { unsigned  r, g, b; };
const struct tagPal initial_vga_palette[VGA_COLOURS] =
{
  { 0,  0,  0}, { 0,  0, 42},      /* black,               blue, */
  { 0, 42,  0}, { 0, 42, 42},      /* green,               cyan, */
  {42,  0,  0}, {42,  0, 42},      /* red,                 magenta */
  {42, 21,  0}, {42, 42, 42},      /* brown,               white */
  {21, 21, 21}, {21, 21, 63},      /* gray,                light blue,  */
  {21, 63, 21}, {21, 63, 63},      /* light green,         light cyan  */
  {63, 21, 21}, {63, 21, 63},      /* light red,               light magenta,*/
  {63, 63, 21}, {63, 63, 63}      /* light brown (=yellow), bright white. */
};


/* decode_pixel()
 *
 * Select the background or foreground colour for a given pixel,
 * according to wether it is a foreground or background pixel.  Decode
 * the attribute into a libppm "pixel" value.
 */
void ppm_decode_pixel(pixel *pix, int is_on, int full_attrib)
{
  struct tagPal tp;
  int colour;
 
  if (!is_on)
    {
      full_attrib >>= 4;      /* select the background portion. */
      full_attrib &= 0x0F;
      colour = colour_translations[full_attrib+BG_COLOUR_BANK];
    }
  else
    {
      full_attrib &= 0x0F;
      colour = colour_translations[full_attrib];
    }

  /* The effects palette has 32 entries composed of two lots of
   * the same set of 16 colours.  Using (colour % 16) as the
   * lookup index then does the right thing.
   */
  tp = initial_vga_palette[colour % VGA_COLOURS];
  PPM_ASSIGN(*pix, tp.r, tp.g, tp.b);
}



/* get_font_row()
 *
 * Extract one scan row of the font information for a particular character.
 */
int get_font_row(int ascii, int charline, unsigned char font_buf[FONT_BYTES])
{
  return font_buf[ascii*FONT_LINES_PER_CHAR + charline];
}

static void oom(void)
{
  fprintf(stderr, "Fatal error: Out of memory.\n");
  exit(EXIT_FAILURE);
}

/* dump_to_ppm_file()
 *
 * Given the screen and font data, generate a PPM output file from it.
 */
static int
dump_to_ppm_file(FILE *fp,
             struct tagVcsaScreenInfo *psi,
             unsigned char *text_data,
             unsigned char font_buf[FONT_BYTES],
             int forceplain)
{
  int x, y, charline, nlines;
  const unsigned char *row;
  unsigned char ascii, attr;
  pixel *prow, *pixptr;

  nlines = screen_rows_to_font_height(psi->lines);

  prow = ppm_allocrow(psi->cols * 8);
  if (NULL == prow)
    {
      oom();
      return 0;
    }

  ppm_writeppminit(fp,
               psi->cols*8, psi->lines*nlines,
               VGA_PALDEPTH, forceplain);

  /* Work from top to bottom of the screen.
   */
  for (y=0; y < psi->lines; ++y)
    {
      /* Within each row, work from top to bottom of the character definitions.
       */
      for (charline=0; charline<nlines; ++charline)
      {
        row = text_data + y*(psi->cols * 2);
        pixptr = prow;

        /* Within the given scanline for this row, work from left to right.
         */
        for (x=0; x < psi->cols; ++x)
          {
            int i, fontline;
            
            ascii = *row++;
            attr = *row++;

            /* Extract the pixels for this row of this character,
             * working left to right.  
             * (TODO: maybe optimise fontline==0 or fontline==0xFF)
             */
            fontline = get_font_row(ascii, charline, font_buf);
            for (i=0; i<8; i++)
            {
              int mask = 1 << (7-i);
              ppm_decode_pixel(pixptr++, fontline & mask, attr );
            }
          }
        /* Write out the pixel row...
         */
        ppm_writeppmrow(fp, prow, psi->cols*8, VGA_PALDEPTH, forceplain);
      }
    }
 
  ppm_freerow(prow);
  return EXIT_SUCCESS;
}

#ifdef USE_PNG



/* dump_to_png_file
 *
 * Dump a VC to a PNG file; we dump the data as an image with a
 * palette with 8-bit depth.  The least significant two bits of the
 * intensities in the palette are zero (VGA palette range is 0...63).
 * Instead of a 16-entry palette, we produce as 32 entry one, the
 * first and second sixteen colours being dumped as the same colour.
 * The first set is used for the foreground colours, the second
 * sixteen for the background colours.  A typical use for this is to
 * brichten the grey background to bright white for greater clearness
 * when printed.
 */
static int
dump_to_png_file(FILE *fp,
             struct tagVcsaScreenInfo *psi,
             unsigned char *screen_text_data,
             unsigned char font_buf[FONT_BYTES],
             int forceplain)
{
  int x, y, charline, nlines, i;
  const unsigned char *row, *q;
  char *timestr;
  unsigned char ascii, attr;
  png_structp png_ptr;
  png_infop info_ptr;
  png_color my_png_palette[EFFECTS_PALETTE_SIZE];
  png_color output_palette[EFFECTS_PALETTE_SIZE];
  png_color_8 six_sig_bits;
  png_byte *pngimage_row, *pixptr;
  png_time conversion_time;
  time_t ttnow;
  png_text tentry[5];
  int colchars;
  char *p, *txt;

 
  /* The 6-bit VGA palette in initial_vga_palette needs
   * to be scaled up by 2 bit positions to look like an
   * 8-bit palette.
   */
  for (i=0; i<VGA_COLOURS; ++i)
    {
      /* foreground entries. */
      my_png_palette[i].red   = initial_vga_palette[i].r << 2;
      my_png_palette[i].green = initial_vga_palette[i].g << 2;
      my_png_palette[i].blue  = initial_vga_palette[i].b << 2;

      /* background entries. */
      my_png_palette[BG_COLOUR_BANK + i].red   = my_png_palette[i].red;  
      my_png_palette[BG_COLOUR_BANK + i].green = my_png_palette[i].green;
      my_png_palette[BG_COLOUR_BANK + i].blue  = my_png_palette[i].blue;  
    }

  /* The palette we actually output consists of this scaled palette
   * modified by the effects of colour_translations[] (see the -e
   * option).
   */
  for (i=0; i<32; ++i)
      output_palette[i] = my_png_palette[colour_translations[i]];
 
  six_sig_bits.red = six_sig_bits.green = six_sig_bits.blue = 6;
 
  nlines = screen_rows_to_font_height(psi->lines);

  pngimage_row = malloc(psi->cols * 8);
  if (!pngimage_row)
    oom();
 
  /* Init the png stuff */
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (NULL == png_ptr)
    return EXIT_FAILURE;      /* TODO: make verbose */
     
  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
      png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
      return EXIT_FAILURE;
    }
  if (setjmp(png_ptr->jmpbuf))
    {
      png_destroy_write_struct(&png_ptr, &info_ptr);
      return EXIT_FAILURE;
    }
  png_init_io(png_ptr, fp);
  png_set_IHDR(png_ptr, info_ptr, psi->cols*8, psi->lines*nlines,
             8,            /* color depth */
             PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
             PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  png_set_PLTE(png_ptr, info_ptr, output_palette, 32);
  png_set_sBIT(png_ptr, info_ptr, &six_sig_bits);
  ttnow = time(NULL);
  png_convert_from_time_t(&conversion_time, ttnow);
  png_set_tIME(png_ptr, info_ptr, &conversion_time);
  png_write_info(png_ptr, info_ptr);
 

 

  /* Work from top to bottom of the screen.
   */
  for (y=0; y < psi->lines; ++y)
    {
      /* Within each row, work from top to bottom of the character definitions.
       */
      for (charline=0; charline<nlines; ++charline)
      {
        row = screen_text_data + y*(psi->cols * 2);
        pixptr = pngimage_row;

        /* Within the given scanline for this row, work from left to right.
         */
        for (x=0; x < psi->cols; ++x)
          {
            int i, fontline;
            
            ascii = *row++;
            attr = *row++;

            /* Extract the pixels for this row of this character,
             * working left to right.
             */
            fontline = get_font_row(ascii, charline, font_buf);
            for (i=0; i<8; i++)
            {
              int mask = 1 << (7-i);
              int nclr;
              if (fontline & mask)
                {
                  nclr = attr & 0x0F; /* fg pixel. */
                }
              else
                {
                  nclr = (attr & 0xF0) >> 4; /* bg pixel. */
                  nclr += BG_COLOUR_BANK; /* second palette group for bg. */
                }

              *pixptr++ = nclr;
            }
          }
        /* Write out the pixel row...
         */
        png_write_rows(png_ptr, &pngimage_row, 1);
      }
    }
 
  colchars = psi->cols + 1;      /* +1 for '\n' */


  /* Write out the ASCII text into the Comments section of the PNG file.
   */
  if ( NULL ==  (txt = malloc(sizeof(png_textp) * psi->lines * colchars + 1)) )
    oom();
  p = txt;
 
  q = screen_text_data;
  for (i=0; i<psi->lines; ++i)
    {
      int j = psi->cols;
      while (j--)
      {
        int ch = *q;

        if (ch >= 128 || ch < 0) /* keep only 7-bit characters. */
          ch = ' ';

        *p++ = ch;
        q += 2;
      }
      *p++ = '\n';
    }
  *p++ = '\0';
  tentry[0].compression = PNG_TEXT_COMPRESSION_NONE;
  tentry[0].key = "Comment";
  tentry[0].text = txt;

  tentry[1].compression = PNG_TEXT_COMPRESSION_NONE;
  tentry[1].key = "Software";
  tentry[1].text = PROGNAME " $Revision: 1.6 $ (C) 1998, James Youngman";

  tentry[2].compression = PNG_TEXT_COMPRESSION_NONE;
  tentry[2].key = "Description";
  tentry[2].text = "Image dumped from a Linux Virtual Console";

  tentry[3].compression = PNG_TEXT_COMPRESSION_NONE;
  tentry[3].key = "Creation Time";
  if ( (time_t)-1 == ttnow )      /* call failed */
    timestr = "4004 BC";
  else
    timestr = ctime(&ttnow);
  tentry[3].text = timestr;

  /* The output of ctime() doesn't indicate that it is in UTC.
   * I don't want to faff around with arbitrary length buffers
   * and certainly don't want to have a fixed-size one.  So I'll
   * put another text string in that makes this plain.
   */
  tentry[4].compression = PNG_TEXT_COMPRESSION_NONE;
  tentry[4].key = "UTC Creation Time";
  tentry[4].text = timestr;


  png_set_text(png_ptr, info_ptr, tentry, 5);

 
  png_write_end(png_ptr, info_ptr);
 
  free(pngimage_row);
  free(txt);
 
  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
 
  return EXIT_SUCCESS;
 
}
#endif


typedef int (*dumper)(FILE *fp,
                 struct tagVcsaScreenInfo *psi,
                 unsigned char *text_data,
                 unsigned char font_buf[FONT_BYTES],
                 int forceplain);


struct tagDumpDefs
{
  const char *name;
  int plainflag;
  dumper dumpfn;
} dumpers[ ] =
{
  { "ppm",     0, dump_to_ppm_file },    
  { "ppmraw",  0, dump_to_ppm_file },    
  { "ppmtext", 1, dump_to_ppm_file },
#ifdef USE_PNG  
  { "png",     0, dump_to_png_file }
#endif
};
#define NDUMPERS (sizeof(dumpers)/sizeof(dumpers[0]))


dumper
set_output_type(const char *name, int *plain)
{
  int i;
  for (i=0; i<NDUMPERS; ++i)
    {
      if (0 == strcmp(name, dumpers[i].name))
      {
        *plain = dumpers[i].plainflag;
        return dumpers[i].dumpfn;
      }
    }
  return (dumper)0;
}

void
show_output_types(FILE *f)
{
  int i;
  for (i=0; i<NDUMPERS; ++i)
    fprintf(f, "%s%s", dumpers[i].name, i<(NDUMPERS-1) ? ", " : "");
}


/* Colour names.
 */
enum
{
  Black=0,
  Blue, Green, Cyan, Red, Magenta, Brown, White, Grey, LightBlue,
  LightGreen, LightCyan, LightRed, LightMagenta, Yellow, BrightWhite,

  FgBlack=0,
  FgBlue,         FgGreen,  FgCyan,      FgRed,        FgMagenta,  FgBrown,
  FgWhite,        FgGrey,   FgLightBlue, FgLightGreen, FgLightCyan, FgLightRed,
  FgLightMagenta, FgYellow, FgBrightWhite,

  BgBlack=16,
  BgBlue,         BgGreen,  BgCyan,      BgRed,        BgMagenta,   BgBrown,
  BgWhite,        BgGrey,   BgLightBlue, BgLightGreen, BgLightCyan, BgLightRed,
  BgLightMagenta, BgYellow, BgBrightWhite

};

static void
init_colour_translations(void)
{
  unsigned i;
  for (i=0; i<EFFECTS_PALETTE_SIZE; ++i)
    colour_translations[i] = i;      /* normal one-to-one mapping.*/
}


/* Colour effect -- convert white background to bright white.
 *
 * This is useful when the output is going to be printed.
 */
static void effect_bright_white_bg(void)
{
  colour_translations[BgWhite] = BgBrightWhite;
  colour_translations[BgGrey] = BgWhite;
}

/* Colour effect -- convert white foreground to bright white.
 *
 * This is useful when the output is going to be printed.
 */
static void effect_bright_white_fg(void)
{
  colour_translations[FgWhite] = FgBrightWhite;
  colour_translations[FgGrey] = FgWhite;
}

struct tagColourEffects
{
  const char *name;
  void (*fn)(void);
}
effect_table[] =
{
  { "brighten-white-bg", effect_bright_white_bg },
  { "brighten-white-fg", effect_bright_white_fg }
};
#define NEFFECTS (sizeof(effect_table)/sizeof(effect_table[0]))


void show_effects(FILE *f)
{
  int i;
  for (i=0; i<NEFFECTS; ++i)
    fprintf(stderr, "%s%s", effect_table[i].name, i<(NEFFECTS-1) ? ", " : "");
}

int
do_effect(const char *what)
{
  int i;
  for (i=0; i<NEFFECTS; ++i)
    {
      if (0 == strcmp(what, effect_table[i].name))
      {
        (effect_table[i].fn)();
        return 1;            /* OK. */
      }
    }
  return 0;                  /* fail. */
}


/* capture()
 *
 * Capture a specific VC to the given FILE.
 */
static int
capture(int vc, FILE *f, dumper dumpfunc, int plain)
{
  int vcsa_fd, tty_fd;
  struct tagVcsaScreenInfo si;
  unsigned char font_buf[FONT_BYTES];
  unsigned char * text_data;
 
  if (get_vc_fds(vc, &vcsa_fd, &tty_fd))
    {
      if (in_textmode(tty_fd))
      {
        if ( NULL != (text_data = capture_vca(vcsa_fd, &si)) )
          {
            if (get_font(tty_fd, font_buf))
            {
              return (dumpfunc)(f, &si, text_data, font_buf, plain);
            }
          }
      }
      else
      {
        fprintf(stderr, "tty%d is not in text mode.\n", vc);
      }
    }
  return EXIT_FAILURE;
}

void
usage(const char *prog)
{
  fprintf(stderr, "%s: [-o output-file] [-t TYPE] [-e EFFECT] VC-number\n",
        prog);
  fprintf(stderr, "TYPE can be one of ");
  show_output_types(stderr);
  fprintf(stderr, "\n");
  fprintf(stderr, "EFFECT can be one of ");
  show_effects(stderr);
  fprintf(stderr, "\n");
 
}

int main(int argc, char *argv[])
{
  int opt, vc_num;
  const char *output_file_name = NULL;
  FILE *output_file;
  int ret;
  dumper dumpfunc = dump_to_ppm_file;
  int plain_flag = 0;
 
  init_colour_translations();
   
  /* Options:
   * -o output-file-name
   * -t ppm|ppmraw|ppmtext|png
   * -e effect-name
   */
  while ( (opt = getopt(argc, argv, "o:t:e:")) != EOF )
    {
      if ('?' == opt)
      {
        fprintf(stderr, "Unknown option -%c\n", opt);
        usage(argv[0]);
        exit(EXIT_FAILURE);
      }
      else if (':' == opt)
      {
        fprintf(stderr, "-%c: Missing argument\n", opt);
        usage(argv[0]);
        exit(EXIT_FAILURE);
      }
      else if ('o' == opt)
      {
        output_file_name = optarg;
      }
      else if ('e' == opt)
      {
        if (0 == do_effect(optarg))
          {
            fprintf(stderr, "Unkown effect type \"%s\"."
                  "  Known types are:-\n", optarg);
            show_effects(stderr);
            fprintf(stderr, "\n");
            return (EXIT_FAILURE);
          }
      }
      else if ('t' == opt)
      {
        dumpfunc = set_output_type(optarg, &plain_flag);
        if (0 == dumpfunc)
          {
            usage(argv[0]);
            exit(EXIT_FAILURE);
          }
      }
      else
      {
        fprintf(stderr, "getopt() returned %d, weird.\n", opt);
      }
    }
 
  /* Sole non-option argument should be the VC number.
   */
  if (optind < argc)
    {
      if (optind == argc-1)
      {
        const char *vc_arg = argv[optind];
        vc_num = atoi(vc_arg);
        if (0 == vc_arg)
          {
            fprintf(stderr, "Invalid VC number \"%s\"\n", vc_arg);
            usage(argv[0]);
            return EXIT_FAILURE;
          }
      }
      else
      {
        fprintf(stderr, "Too many arguments.\n");
        usage(argv[0]);
        return EXIT_FAILURE;
      }
    }
  else
    {
      fprintf(stderr, "Not enough arguments.\n");
      usage(argv[0]);
      return EXIT_FAILURE;
    }

  /* Actually do the VC capture...
   */
  if (output_file_name)
    {
      output_file = fopen(output_file_name, "wb");
      if (NULL == output_file)
      {
        perror(output_file_name);
        return EXIT_FAILURE;
      }
    }
  else
    {
      output_file = stdout;
    }
  ret = capture(vc_num, output_file, dumpfunc, plain_flag);
  if (output_file_name)
    fclose(output_file);
  exit(ret);
}

/*
 * Local Variables: !
 * compile-command: "make vcdump CPPFLAGS='-DUSE_PNG=1' LDLIBS='-lppm -lpbm -lpgm -lpng -lz' CFLAGS='-g'" !
 * End: !
 */


0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Hello fellow BSD lovers, I've created a patch process for patching openjdk6 for BSD (FreeBSD specifically), although I tried to keep all BSD versions in mind when creating my patch. Welcome to OpenJDK6 on BSD First let me start with a little …
Java performance on Solaris - Managing CPUs There are various resource controls in operating system which directly/indirectly influence the performance of application. one of the most important resource controls is "CPU".   In a multithreaded…
Learn several ways to interact with files and get file information from the bash shell. ls lists the contents of a directory: Using the -a flag displays hidden files: Using the -l flag formats the output in a long list: The file command gives us mor…
Learn how to get help with Linux/Unix bash shell commands. Use help to read help documents for built in bash shell commands.: Use man to interface with the online reference manuals for shell commands.: Use man to search man pages for unknown command…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now