gboolean 
seahorse_vfs_data_write_all (gpgme_data_t data, const void* buffer, gint len, GError **err)
{
    guchar *text = (guchar*)buffer;
    gint written;
    
    if (len < 0)
        len = strlen ((gchar*)text);
    
    while (len > 0) {
        written = gpgme_data_write (data, (void*)text, len);
        if (written < 0) {
            if (errno == EAGAIN || errno == EINTR)
                continue;
            g_set_error (err, G_FILE_ERROR, g_file_error_from_errno (errno), 
                         "%s", strerror (errno));
            return FALSE;
        }
        
        len -= written;
        text += written;
    }
    
    return TRUE;
}
示例#2
0
文件: data.c 项目: dbarabash/gpgme
gpgme_error_t
_gpgme_data_inbound_handler (void *opaque, int fd)
{
  struct io_cb_data *data = (struct io_cb_data *) opaque;
  gpgme_data_t dh = (gpgme_data_t) data->handler_value;
  char buffer[BUFFER_SIZE];
  char *bufp = buffer;
  gpgme_ssize_t buflen;
  TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_inbound_handler", dh,
	      "fd=0x%x", fd);

  buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE);
  if (buflen < 0)
    return gpg_error_from_syserror ();
  if (buflen == 0)
    {
      _gpgme_io_close (fd);
      return TRACE_ERR (0);
    }

  do
    {
      gpgme_ssize_t amt = gpgme_data_write (dh, bufp, buflen);
      if (amt == 0 || (amt < 0 && errno != EINTR))
	return TRACE_ERR (gpg_error_from_syserror ());
      bufp += amt;
      buflen -= amt;
    }
  while (buflen > 0);
  return TRACE_ERR (0);
}
示例#3
0
文件: t-data.c 项目: gpg/gpgme
void
write_test (round_t round, gpgme_data_t data)
{
  char buffer[1024];
  size_t amt;

  amt = gpgme_data_write (data, text, strlen (text));
  if (amt != strlen (text))
    fail_if_err (gpgme_error_from_errno (errno));

  gpgme_data_seek (data, 0, SEEK_SET);

  if (round == TEST_INOUT_NONE)
    read_once_test (round, data);
  else
    {
      amt = gpgme_data_read (data, buffer, sizeof (buffer));

      if (amt != strlen (text2) || strncmp (buffer, text2, strlen (text2)))
	{
	  fprintf (stderr, "%s:%d: (%i) gpgme_data_read returned wrong data\n",
		   __FILE__, __LINE__, round);
	  exit (1);
	}

      amt = gpgme_data_read (data, buffer, sizeof (buffer));
      if (amt)
	{
	  fprintf (stderr, "%s:%d: (%i) gpgme_data_read did not signal EOF\n",
		   __FILE__, __LINE__, round);
	  exit (1);
	}
    }
}
示例#4
0
gpgme_error_t
_gpgme_data_inbound_handler(void *opaque, int fd)
{
    gpgme_data_t dh = (gpgme_data_t) opaque;
    char buffer[BUFFER_SIZE];
    char *bufp = buffer;
    ssize_t buflen;

    buflen = _gpgme_io_read(fd, buffer, BUFFER_SIZE);
    if(buflen < 0)
        return gpg_error_from_errno(errno);
    if(buflen == 0)
    {
        _gpgme_io_close(fd);
        return 0;
    }

    do
    {
        ssize_t amt = gpgme_data_write(dh, bufp, buflen);
        if(amt == 0 || (amt < 0 && errno != EINTR))
            return gpg_error_from_errno(errno);
        bufp += amt;
        buflen -= amt;
    }
    while(buflen > 0);
    return 0;
}
示例#5
0
JNIEXPORT void JNICALL
Java_com_freiheit_gnupg_GnuPGData_gpgmeDataRead(JNIEnv * env, jobject self,
						jlong data, jobject in)
{
    gpgme_error_t err;

    jclass inputStream = (*env)->GetObjectClass(env, in);
    if (inputStream == NULL) {
        fprintf(stderr, "input stream NULL! abort.\n");
	return;
    }

    jmethodID readMethod = (*env)->GetMethodID(env, inputStream,
					       "read", "([BII)I");
    if (readMethod == NULL) {
        fprintf(stderr, "read method NULL! abort.\n");
	return;
    }

    jbyteArray jbuf = (*env)->NewByteArray(env, BUFSIZE);	//GETMEM(0)
    jlong nread;

    err = (gpgme_data_seek (DATA(data), (off_t)0, SEEK_SET) < 0);
    if (UTILS_onErrorThrowException(env, err)) {
	return;
    }

    ssize_t written;
    while ((nread = (*env)->CallIntMethod(env, in, readMethod,
					  jbuf, (jint)0, BUFSIZE)) != -1) {

	jbyte *buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
	if (buf == NULL) {
	    return;
	}

	written = gpgme_data_write(DATA(data), buf, nread);
	if ((*env)->ExceptionCheck(env)) {
	    (*env)->DeleteLocalRef(env, jbuf);
	    return;
	}

    }
    (*env)->DeleteLocalRef(env, jbuf);	//RELMEM(0)

}
示例#6
0
int 
seahorse_gpgme_data_write_all (gpgme_data_t data, const void* buffer, size_t len)
{
	guchar *text = (guchar*)buffer;
	gint written = 0;
    
	if (len < 0)
		len = strlen ((gchar*)text);
    
	while (len > 0) {
		written = gpgme_data_write (data, (void*)text, len);
		if (written < 0) {
			if (errno == EAGAIN || errno == EINTR)
				continue;
			return -1;
		}
        
		len -= written;
		text += written;
	}
    
	return written;
}
示例#7
0
char *CGPGHelper::Decrypt(const char *szCipher)
{
#ifdef HAVE_LIBGPGME
  if (!mCtx) return 0;

  size_t nRead = 0;
  gpgme_data_t cipher, plain;

  CGPGMEMutex mutex;
  if (!mutex.Lock()) return 0;
  if (gpgme_data_new(&cipher) != GPG_ERR_NO_ERROR) return 0;
  char *buf = strdup(szCipher);
  gpgme_error_t err;
  gpgme_data_write(cipher, buf, strlen(buf));
  free(buf);

  if (gpgme_data_new(&plain) != GPG_ERR_NO_ERROR)
  {
    gpgme_data_release(cipher);
    return 0;
  }

  gpgme_data_seek(cipher, 0, SEEK_SET);
  if ((err = gpgme_op_decrypt(mCtx, cipher, plain)) != GPG_ERR_NO_ERROR)
    gLog.Warn("%s[GPG] gpgme message decryption failed: %s\n", L_WARNxSTR, gpgme_strerror(err));
  
  gpgme_data_release(cipher);
  buf = gpgme_data_release_and_get_mem(plain, &nRead);
  if (!buf) return 0;
  buf = (char *)realloc(buf, nRead+1);
  buf[nRead] = 0;
  return buf;
#else
  return 0;
#endif
}
示例#8
0
static gpgme_error_t
status_handler (void *opaque, int fd)
{
  struct io_cb_data *data = (struct io_cb_data *) opaque;
  engine_gpgsm_t gpgsm = (engine_gpgsm_t) data->handler_value;
  gpgme_error_t err = 0;
  char *line;
  size_t linelen;

  do
    {
      err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
      if (err)
	{
	  /* Try our best to terminate the connection friendly.  */
	  /*	  assuan_write_line (gpgsm->assuan_ctx, "BYE"); */
          TRACE3 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
		  "fd 0x%x: error from assuan (%d) getting status line : %s",
                  fd, err, gpg_strerror (err));
	}
      else if (linelen >= 3
	       && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
	       && (line[3] == '\0' || line[3] == ' '))
	{
	  if (line[3] == ' ')
	    err = atoi (&line[4]);
	  if (! err)
	    err = gpg_error (GPG_ERR_GENERAL);
          TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
		  "fd 0x%x: ERR line - mapped to: %s",
                  fd, err ? gpg_strerror (err) : "ok");
	  /* Try our best to terminate the connection friendly.  */
	  /*	  assuan_write_line (gpgsm->assuan_ctx, "BYE"); */
	}
      else if (linelen >= 2
	       && line[0] == 'O' && line[1] == 'K'
	       && (line[2] == '\0' || line[2] == ' '))
	{
	  if (gpgsm->status.fnc)
	    err = gpgsm->status.fnc (gpgsm->status.fnc_value,
				     GPGME_STATUS_EOF, "");

	  if (!err && gpgsm->colon.fnc && gpgsm->colon.any)
            {
              /* We must tell a colon function about the EOF. We do
                 this only when we have seen any data lines.  Note
                 that this inlined use of colon data lines will
                 eventually be changed into using a regular data
                 channel. */
              gpgsm->colon.any = 0;
              err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, NULL);
            }
          TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
		  "fd 0x%x: OK line - final status: %s",
                  fd, err ? gpg_strerror (err) : "ok");
	  _gpgme_io_close (gpgsm->status_cb.fd);
	  return err;
	}
      else if (linelen > 2
	       && line[0] == 'D' && line[1] == ' '
	       && gpgsm->colon.fnc)
        {
	  /* We are using the colon handler even for plain inline data
             - strange name for that function but for historic reasons
             we keep it.  */
          /* FIXME We can't use this for binary data because we
             assume this is a string.  For the current usage of colon
             output it is correct.  */
          char *src = line + 2;
	  char *end = line + linelen;
	  char *dst;
          char **aline = &gpgsm->colon.attic.line;
	  int *alinelen = &gpgsm->colon.attic.linelen;

	  if (gpgsm->colon.attic.linesize < *alinelen + linelen + 1)
	    {
	      char *newline = realloc (*aline, *alinelen + linelen + 1);
	      if (!newline)
		err = gpg_error_from_syserror ();
	      else
		{
		  *aline = newline;
		  gpgsm->colon.attic.linesize += linelen + 1;
		}
	    }
	  if (!err)
	    {
	      dst = *aline + *alinelen;

	      while (!err && src < end)
		{
		  if (*src == '%' && src + 2 < end)
		    {
		      /* Handle escaped characters.  */
		      ++src;
		      *dst = _gpgme_hextobyte (src);
		      (*alinelen)++;
		      src += 2;
		    }
		  else
		    {
		      *dst = *src++;
		      (*alinelen)++;
		    }

		  if (*dst == '\n')
		    {
		      /* Terminate the pending line, pass it to the colon
			 handler and reset it.  */

		      gpgsm->colon.any = 1;
		      if (*alinelen > 1 && *(dst - 1) == '\r')
			dst--;
		      *dst = '\0';

		      /* FIXME How should we handle the return code?  */
		      err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline);
		      if (!err)
			{
			  dst = *aline;
			  *alinelen = 0;
			}
		    }
		  else
		    dst++;
		}
	    }
          TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
		  "fd 0x%x: D line; final status: %s",
                  fd, err? gpg_strerror (err):"ok");
        }
      else if (linelen > 2
	       && line[0] == 'D' && line[1] == ' '
	       && gpgsm->inline_data)
        {
          char *src = line + 2;
	  char *end = line + linelen;
	  char *dst = src;
          ssize_t nwritten;

          linelen = 0;
          while (src < end)
            {
              if (*src == '%' && src + 2 < end)
                {
                  /* Handle escaped characters.  */
                  ++src;
                  *dst++ = _gpgme_hextobyte (src);
                  src += 2;
                }
              else
                *dst++ = *src++;

              linelen++;
            }

          src = line + 2;
          while (linelen > 0)
            {
              nwritten = gpgme_data_write (gpgsm->inline_data, src, linelen);
              if (!nwritten || (nwritten < 0 && errno != EINTR)
                  || nwritten > linelen)
                {
                  err = gpg_error_from_syserror ();
                  break;
                }
              src += nwritten;
              linelen -= nwritten;
            }

          TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
		  "fd 0x%x: D inlinedata; final status: %s",
                  fd, err? gpg_strerror (err):"ok");
        }
      else if (linelen > 2
	       && line[0] == 'S' && line[1] == ' ')
	{
	  char *rest;
	  gpgme_status_code_t r;

	  rest = strchr (line + 2, ' ');
	  if (!rest)
	    rest = line + linelen; /* set to an empty string */
	  else
	    *(rest++) = 0;

	  r = _gpgme_parse_status (line + 2);

	  if (r >= 0)
	    {
	      if (gpgsm->status.fnc)
		err = gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest);
	    }
	  else
	    fprintf (stderr, "[UNKNOWN STATUS]%s %s", line + 2, rest);
          TRACE3 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
		  "fd 0x%x: S line (%s) - final status: %s",
                  fd, line+2, err? gpg_strerror (err):"ok");
	}
      else if (linelen >= 7
               && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
               && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
               && line[6] == 'E'
               && (line[7] == '\0' || line[7] == ' '))
        {
          char *keyword = line+7;

          while (*keyword == ' ')
            keyword++;;
          default_inq_cb (gpgsm, keyword);
          assuan_write_line (gpgsm->assuan_ctx, "END");
        }

    }
  while (!err && assuan_pending_line (gpgsm->assuan_ctx));

  return err;
}
示例#9
0
ssize_t GpgME::Data::write( const void * buffer, size_t length ) {
  return gpgme_data_write( d->data, buffer, length );
}
示例#10
0
static gpgme_error_t
gpgconf_conf_save (void *engine, gpgme_conf_comp_t comp)
{
  gpgme_error_t err;
  int amt = 0;
  /* We use a data object to store the new configuration.  */
  gpgme_data_t conf;
  gpgme_conf_opt_t option;
  int something_changed = 0;

  err = gpgme_data_new (&conf);
  if (err)
    return err;

  option = comp->options;
  while (!err && amt >= 0 && option)
    {
      if (option->change_value)
	{
	  unsigned int flags = 0;
	  char buf[16];

	  something_changed = 1;

	  amt = gpgme_data_write (conf, option->name, strlen (option->name));
	  if (amt >= 0)
	    amt = gpgme_data_write (conf, ":", 1);
	  if (amt < 0)
	    break;

	  if (!option->new_value)
	    flags |= GPGME_CONF_DEFAULT;
	  snprintf (buf, sizeof (buf), "%u", flags);
	  buf[sizeof (buf) - 1] = '\0';

	  amt = gpgme_data_write (conf, buf, strlen (buf));
	  if (amt >= 0)
	    amt = gpgme_data_write (conf, ":", 1);
	  if (amt < 0)
	    break;

	  if (option->new_value)
	    {
	      err = arg_to_data (conf, option, option->new_value);
	      if (err)
		break;
	    }
	  amt = gpgme_data_write (conf, "\n", 1);
	}
      option = option->next;
    }
  if (!err && amt < 0)
    err = gpg_error_from_syserror ();
  if (err || !something_changed)
    goto bail;

  err = gpgme_data_seek (conf, 0, SEEK_SET);
  if (err)
    goto bail;

  err = gpgconf_write (engine, "--change-options", comp->name, conf);
 bail:
  gpgme_data_release (conf);
  return err;
}
示例#11
0
static gpgme_error_t
arg_to_data (gpgme_data_t conf, gpgme_conf_opt_t option, gpgme_conf_arg_t arg)
{
  gpgme_error_t err = 0;
  int amt = 0;
  char buf[16];

  while (amt >= 0 && arg)
    {
      switch (option->alt_type)
	{
	case GPGME_CONF_NONE:
	case GPGME_CONF_UINT32:
	default:
	  snprintf (buf, sizeof (buf), "%u", arg->value.uint32);
	  buf[sizeof (buf) - 1] = '\0';
	  amt = gpgme_data_write (conf, buf, strlen (buf));
	  break;

	case GPGME_CONF_INT32:
	  snprintf (buf, sizeof (buf), "%i", arg->value.uint32);
	  buf[sizeof (buf) - 1] = '\0';
	  amt = gpgme_data_write (conf, buf, strlen (buf));
	  break;


	case GPGME_CONF_STRING:
          /* The complex types below are only here to silent the
             compiler warning. */
        case GPGME_CONF_FILENAME:
        case GPGME_CONF_LDAP_SERVER:
        case GPGME_CONF_KEY_FPR:
        case GPGME_CONF_PUB_KEY:
        case GPGME_CONF_SEC_KEY:
        case GPGME_CONF_ALIAS_LIST:
          if (arg->value.string)
            {
              /* One quote character, and three times to allow for
                 percent escaping.  */
              char *ptr = arg->value.string;
              amt = gpgme_data_write (conf, "\"", 1);
              if (amt < 0)
                break;

              while (!err && *ptr)
                {
                  switch (*ptr)
                    {
                    case '%':
                      amt = gpgme_data_write (conf, "%25", 3);
                      break;

                    case ':':
                      amt = gpgme_data_write (conf, "%3a", 3);
                      break;

                    case ',':
                      amt = gpgme_data_write (conf, "%2c", 3);
                      break;

                    default:
                      amt = gpgme_data_write (conf, ptr, 1);
                    }
                  ptr++;
                }
            }
	  break;
	}

      if (amt < 0)
	break;

      arg = arg->next;
      /* Comma separator.  */
      if (arg)
	amt = gpgme_data_write (conf, ",", 1);
    }

  if (amt < 0)
    return gpg_error_from_syserror ();

  return 0;
}
示例#12
0
static void
at_puts (gpgme_data_t a, const char *s)
{
  gpgme_data_write (a, s, strlen (s));
}
示例#13
0
int main()
{
   int fd;

   gpgme_ctx_t g_context;
   gpgme_engine_info_t enginfo;
   gpgme_data_t data;

   gpgme_error_t gerr;
   gpg_err_code_t gpg_err;

   gpgme_data_t g_plain;
   gpgme_data_t g_plain_recv;
   gpgme_data_t g_encrypt;
   gpgme_data_t g_encrypt_send;

   gpgme_key_t g_recipient[MAX_RCP+1];
   char *p;
   char b_encrypt[BIGBUF+1];

   char msg[EOF_L_MESSAGE];
   char msg_in[EOF_L_MESSAGE];

   int i, tmp;

   for(i=0;i<EOF_L_MESSAGE; i++) msg_in[i] = 0;
   for(i=0;i<EOF_L_MESSAGE; i++) msg[i] = 0;
   for(i=0;i<=BIGBUF; i++) b_encrypt[i] = 0;

   gpgme_check_version(NULL);

   gerr = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
   if(gerr != GPG_ERR_NO_ERROR) return 10;

   p = (char *) gpgme_get_protocol_name(GPGME_PROTOCOL_OpenPGP);
   printf("Version: %s\n",p);

   gerr = gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, NULL, home);

   if(gerr == GPG_ERR_NO_ERROR) {
      printf("gpgme_set_engine_info: ok\n");
   } else {
      printf("gpgme_set_engine_info: err\n");
   }

   /* get engine information */
   gerr = gpgme_get_engine_info(&enginfo);
   if(gerr != GPG_ERR_NO_ERROR) return 3;

   printf("file=%s, home=%s\n",enginfo->file_name,enginfo->home_dir);

   /* create our own context */
   gerr = gpgme_new(&g_context);
   if(gerr != GPG_ERR_NO_ERROR) return 1;

   /* FIXME: both needed? */
   /* FIXME: why is the path (FILE_NAME) needed? */
   /* FIXME: /usr/bin/gpg must be changed to ~/.ceof/gpg/binary or similar */
   gerr = gpgme_ctx_set_engine_info (g_context, GPGME_PROTOCOL_OpenPGP,
               "/usr/bin/gpg",home);
   if(gerr != GPG_ERR_NO_ERROR) return 4;

   /* do not ascii armor data; use 1 for testing */
   //gpgme_set_armor(g_context, 0);
   gpgme_set_armor(g_context, 1);

   /* create buffers */
   gerr = gpgme_data_new(&data);
   if(gerr != GPG_ERR_NO_ERROR) return 12;

   gerr = gpgme_data_new(&g_plain_recv);
   if(gerr != GPG_ERR_NO_ERROR) return 20;

   gerr = gpgme_data_new(&g_encrypt);
   if(gerr != GPG_ERR_NO_ERROR) return 14;

   gerr = gpgme_data_new(&g_encrypt_send);
   if(gerr != GPG_ERR_NO_ERROR) return 24;

   /* fill buffers */
   /* gerr = gpgme_data_new(&g_plain);
   if(gerr != GPG_ERR_NO_ERROR) return 13;

   printf("strlen(%s) = %d\n",msg,i);
   i -= gpgme_data_write(g_plain, msg, i);
   if(i) {
      printf("size mismatch\n");
      return 12;
   } */
   strncpy(msg, "==> Erste Nachricht\n\n", EOF_L_MESSAGE);
   i = strlen(msg);
   gerr = gpgme_data_new_from_mem (&g_plain, msg, i, 0);


   /* setup recipient */
   gerr = gpgme_op_keylist_start(g_context, "nico schottelius", 0);
   if(gerr != GPG_ERR_NO_ERROR) return 11;

   i=0;
   gerr = gpgme_op_keylist_next(g_context, &g_recipient[0]);
   while((gpg_err = gpg_err_code(gerr)) != GPG_ERR_EOF) {
      /* for testing: one call of gpgme_op_keylist_next is enough */
      break;
      if(gerr == GPG_ERR_INV_VALUE) {
         printf("invalid pointer\n");
         return 15;
      } else if(gerr == GPG_ERR_ENOMEM) {
         printf("no mem\n");
         return 16;
      }

      printf ("%s: %s <%s> (%d)\n", g_recipient[0]->subkeys->keyid, g_recipient[0]->uids->name, g_recipient[0]->uids->email, i);
      i++;

      /* FIXME: this resets the good filled buffer ... */
      gerr = gpgme_op_keylist_next(g_context, &g_recipient[0]);
   }
   g_recipient[1] = NULL;

   /* all above seems to be wrong ... */
   gerr = gpgme_get_key(g_context,"775506B45998BF57D0D4AFF27C6E747C38616ADC", &g_recipient[0], 0);
   if(gerr != GPG_ERR_NO_ERROR) return 32;


   /* en/decrypt message */
   //gerr = gpgme_op_encrypt_sign(g_context, g_recipient, 0, g_plain, g_encrypt);
   gerr = gpgme_op_encrypt(g_context, g_recipient, 0, g_plain, g_encrypt);
   if(gerr != GPG_ERR_NO_ERROR) {
      printf("gerr=%d\n",gerr);
      return 18;
   }

   /* transfer the data into our own buffer,
    * so the data is saved; you cannot
    * reuse the gpgme buffers directly as in
    *    gerr = gpgme_op_decrypt(g_context, g_encrypt, g_plain_recv);
    *
    */
   i = gpgme_data_seek(g_encrypt, 0, SEEK_END);

   if(i > BIGBUF) return 22;
   printf("buflen: %d\n",i);
   
   /* reset to the beginning */
   gpgme_data_seek(g_encrypt, 0, SEEK_SET);

   if(gpgme_data_read(g_encrypt, b_encrypt, i) == -1) {
      perror("pgme_data_read");
      return 23;
   }
   printf("crypt:\n%s\n", b_encrypt);
   fd = open("testcrypt",O_RDWR|O_CREAT);
   if(fd == -1) return 40;
   if(write_all(fd, b_encrypt, BIGBUF) <= 0) return 41;
   close(fd);

   /* until here it works, testcrypt contains
    * data and can be decrypted ...
    *
    * perhaps the context needs some reset?
    */

   if((tmp = gpgme_data_write(g_encrypt_send, b_encrypt, i)) == -1) {
      perror("pgme_data_write");
      return 23;
   }
   printf("crypt-wrote:%d\n", tmp);

   /* look for contexts */

   gerr = gpgme_op_decrypt(g_context, g_encrypt_send, g_plain_recv);
   if(gerr != GPG_ERR_NO_ERROR) {
      printf("gerr=%d\n",gerr);
      return 19;
   }

   /* open communication channel: netcat */

   /* listen for input from:
    * stdin
    * communication channel
    */

   /* de/encode data from comm channel */

   return 1;
}