Example #1
0
/* this outputs an argv: */
static void
_tmesh_ls_output_argv(char **_output, struct tmesh_parser_argv *argv, unsigned int skip)
{
  unsigned int argc;
  char **args;
  argc = argv->tmesh_parser_argv_argc;
  args = argv->tmesh_parser_argv_argv;
  assert(argc > 0 && argc >= skip);
  argc -= skip;
  args += skip;
  for (; argc-- > 0; ) {
    tme_output_append(_output, " ");
    tme_output_append(_output, *(args++));
  }
}
Example #2
0
/* the "pwd" command: */
static int
_tmesh_command_pwd(struct tmesh *tmesh, struct tmesh_parser_value *value, char **_output)
{
  _tmesh_fs_pathname_dir(tmesh->tmesh_cwd, _output, NULL);
  tme_output_append(_output, "\n");
  return (TME_OK);
}
Example #3
0
/* the "connect" command: */
static int
_tmesh_command_connect(struct tmesh *tmesh, struct tmesh_parser_value *value, char **_output)
{
  struct tmesh_fs_dirent *parent, *entry;
  char *pathname;
  struct tmesh_fs_element *element0, *element1;
  char **element0_args;
  char **element1_args;
  char **creation_args;
  struct tmesh_fs_element_conn *conn0, *conn1, **prev;
  int which;
  int rc;
  
  /* get and NULL-terminate all argument lists: */
  element0_args = value->tmesh_parser_value_argvs[0].tmesh_parser_argv_argv;
  assert(element0_args != NULL);
  element0_args[value->tmesh_parser_value_argvs[0].tmesh_parser_argv_argc] = NULL;
  element1_args = value->tmesh_parser_value_argvs[1].tmesh_parser_argv_argv;
  if (element1_args != NULL) {
    element1_args[value->tmesh_parser_value_argvs[1].tmesh_parser_argv_argc] = NULL;
  }
  creation_args = value->tmesh_parser_value_argvs[2].tmesh_parser_argv_argv;
  if (creation_args != NULL) {
    creation_args[value->tmesh_parser_value_argvs[2].tmesh_parser_argv_argc] = NULL;
  }
  
  /* check any other element to connect to: */
  element1 = NULL;
  if (element1_args != NULL) {

    /* look up the element: */
    pathname = element1_args[0];
    rc = _tmesh_fs_lookup(tmesh,
			  &pathname,
			  &parent, &entry,
			  _output,
			  TMESH_SEARCH_NORMAL);
    if (rc != TME_OK) {
      return (rc);
    }

    /* this must be an element: */
    if (entry->tmesh_fs_dirent_type != TMESH_FS_DIRENT_ELEMENT) {
      tme_output_append(_output, element1_args[0]);
      return (ENOTSOCK);
    }
    element1 = entry->tmesh_fs_dirent_value;
  }

  /* check the element: */
  pathname = element0_args[0];
  rc = _tmesh_fs_lookup(tmesh,
			&pathname,
			&parent, &entry,
			_output,
			TMESH_SEARCH_LAST_PART_OK);
  if (rc != TME_OK) {
    return (rc);
  }
  
  /* if the name exists: */
  if (entry != NULL) {

    /* it must be an element: */
    if (entry->tmesh_fs_dirent_type != TMESH_FS_DIRENT_ELEMENT) {
      tme_output_append(_output, value->tmesh_parser_value_pathname0);
      return (ENOTSOCK);
    }
    element0 = entry->tmesh_fs_dirent_value;

    /* we must have been given no creation arguments: */
    if (creation_args != NULL) {
      return (EEXIST);
    }
  }

  /* otherwise, the name doesn't exist: */
  else {

    /* we must have been given some creation arguments: */
    if (creation_args == NULL) {
      return (ENOENT);
    }

    /* allocate the new element: */
    element0 = tme_new0(struct tmesh_fs_element, 1);

    /* set this element's parent and link it into the directory: */
    element0->tmesh_fs_element_parent = parent;
    entry = _tmesh_fs_link(parent, tme_strdup(pathname), 
			   TMESH_FS_DIRENT_ELEMENT, element0);

    /* open the log for this element: */
    pathname = NULL;
    _tmesh_fs_pathname_element(element0, &pathname, NULL);
    (*tmesh->tmesh_support.tmesh_support_log_open)
      (&tmesh->tmesh_support,
       &element0->tmesh_fs_element_element.tme_element_log_handle,
       pathname,
       creation_args[0]);
    tme_free(pathname);

    /* create the element: */
    rc = tme_element_new(&element0->tmesh_fs_element_element,
			 (const char **) creation_args,
			 NULL,
			 _output);
    
    /* if the creation failed: */
    if (rc != TME_OK) {

      /* close the log for this element: */
      (*tmesh->tmesh_support.tmesh_support_log_close)
	(&tmesh->tmesh_support,
	 &element0->tmesh_fs_element_element.tme_element_log_handle);

      /* unlink and free this entry: */
      _tmesh_fs_unlink(entry);
      tme_free(entry->tmesh_fs_dirent_name);
      tme_free(entry);
      return (rc);
    }

    /* the creation succeeded.  set the generation number and preserve
       the creation arguments: */
    element0->tmesh_fs_element_gen = ++tmesh->tmesh_gen_last;
    element0->tmesh_fs_element_argv = value->tmesh_parser_value_argvs[2];
    _tmesh_gc_release_argv(tmesh, &element0->tmesh_fs_element_argv);
  }

  /* if we have another element, make a connection: */
  if (element1 != NULL) {
    rc = tme_element_connect(&element0->tmesh_fs_element_element, 
			     (const char **) element0_args,
			     &element1->tmesh_fs_element_element, 
			     (const char **) element1_args,
			     _output, &which);

    /* if the connection failed: */
    if (rc != TME_OK) {
      return (rc);
    }

    /* allocate the new connections: */
    for (prev = &element0->tmesh_fs_element_conns;
	 (conn0 = *prev) != NULL;
	 prev = &conn0->tmesh_fs_element_conn_next);
    *prev = conn0 = tme_new0(struct tmesh_fs_element_conn, 1);
    for (prev = &element1->tmesh_fs_element_conns;
	 (conn1 = *prev) != NULL;
	 prev = &conn1->tmesh_fs_element_conn_next);
    *prev = conn1 = tme_new0(struct tmesh_fs_element_conn, 1);

    /* remember the connections: */
    conn0->tmesh_fs_element_conn_element = element0;
    conn0->tmesh_fs_element_conn_gen = tmesh->tmesh_gen_last;
    conn0->tmesh_fs_element_conn_other = conn1;
    conn0->tmesh_fs_element_conn_argv = value->tmesh_parser_value_argvs[0];
    _tmesh_gc_release_argv(tmesh, &conn0->tmesh_fs_element_conn_argv);
    conn1->tmesh_fs_element_conn_element = element1;
    conn1->tmesh_fs_element_conn_gen = tmesh->tmesh_gen_last;
    conn1->tmesh_fs_element_conn_other = conn0;
    conn1->tmesh_fs_element_conn_argv = value->tmesh_parser_value_argvs[1];
    _tmesh_gc_release_argv(tmesh, &conn1->tmesh_fs_element_conn_argv);
  }
Example #4
0
/* the "ls" command: */
static int
_tmesh_command_ls(struct tmesh *tmesh, struct tmesh_parser_value *value, char **_output)
{
  char *opts, *pathname, opt;
  struct tmesh_fs_dirent *parent, *entry;
  int type;
  void *what;
  int rc;
  int flags;

  /* take apart any options: */
  opts = value->tmesh_parser_value_strings[0];
  flags = TMESH_LS_NORMAL;
  if (opts != NULL) {
    assert(*opts == '-');
    for (; (opt = *(++opts)) != '\0'; ) {
      switch (opt) {

	/* 'a' lists all directory entries, and all connections on elements: */
      case 'a': flags |= TMESH_LS_ALL; break;

	/* 'l' lists absolute pathnames for elements: */
      case 'l': flags |= TMESH_LS_ABSOLUTE; break;

	/* 'R' recurses: */
      case 'R': flags |= TMESH_LS_RECURSE; break;

	/* an unknown option: */
      default:
	tme_output_append(_output,
			  "ls: %s '-%c'\n",
			  _("invalid option"),
			  opt);
	return (EINVAL);
      }
    }
  }

  /* if a path name is given, look it up: */
  pathname = value->tmesh_parser_value_strings[1];
  if (pathname != NULL) {
    rc = _tmesh_fs_lookup(tmesh,
			  &pathname,
			  &parent, &entry,
			  _output,
			  TMESH_SEARCH_NORMAL);
    
    /* if the lookup failed: */
    if (rc != TME_OK) {
      return (rc);
    }

    /* get what we're listing: */
    type = entry->tmesh_fs_dirent_type;
    what = entry->tmesh_fs_dirent_value;
  }

  /* otherwise, list the cwd: */
  else {
    type = TMESH_FS_DIRENT_DIR;
    what = tmesh->tmesh_cwd;
  }

  /* dispatch on the type: */
  switch (type) {
  case TMESH_FS_DIRENT_DIR:
    _tmesh_ls_dir(what, _output, what, flags);
    break;
  case TMESH_FS_DIRENT_ELEMENT:
    _tmesh_ls_element(what, _output, flags);
    break;
  default: assert(FALSE);
  }
    
  return (TME_OK);
}
Example #5
0
/* this lists a directory: */
static void
_tmesh_ls_dir(struct tmesh_fs_dirent *parent,
	      char **_output,
	      struct tmesh_fs_dirent *parent_top,
	      int flags)
{
  struct tmesh_fs_dirent *entry, *dir;
  struct tmesh_fs_element *element;
  int pass;

  /* list this directory: */
  for (pass = 0; ++pass < 2;) {

    /* if this is pass two, but we're not recursing, stop: */
    if (pass == 2
	&& !(flags & TMESH_LS_RECURSE)) {
      return;
    }

    /* loop over the entries in the directory: */
    entry = parent;
    do {
      
      /* dispatch on the directory entry's type: */
      switch (entry->tmesh_fs_dirent_type) {

	/* this is a subdirectory: */
      case TMESH_FS_DIRENT_DIR:
	dir = entry->tmesh_fs_dirent_value;

	/* handle a "." or ".." subdirectory: */
	if (!strcmp(entry->tmesh_fs_dirent_name, ".")
	    || !strcmp(entry->tmesh_fs_dirent_name, "..")) {
	
	  /* if we're listing all, and this is pass one: */
	  if ((flags & TMESH_LS_ALL)
	      && pass == 1) {
	    
	    /* output the directory's name: */
	    _tmesh_fs_pathname_dir(dir, _output, 
				   ((flags & TMESH_LS_ABSOLUTE)
				    ? NULL
				    : parent));
	    tme_output_append(_output, "\n");
	  }
	}

	/* otherwise this is a regular subdirectory: */
	else {

	  /* if this is pass one: */
	  if (pass == 1) {

	    /* output the directory's name: */
	    _tmesh_fs_pathname_dir(dir, _output, 
				   ((flags & TMESH_LS_ABSOLUTE)
				    ? NULL
				    : parent));
	    tme_output_append(_output, "/\n");
	  }

	  /* otherwise, this is pass two: */
	  else {

	    /* output the directory's name and recurse: */
	    tme_output_append(_output, "\n./");
	    _tmesh_fs_pathname_dir(dir, _output, 
				   ((flags & TMESH_LS_ABSOLUTE)
				    ? NULL
				    : parent_top));
	    tme_output_append(_output, ":\n");
	    _tmesh_ls_dir(dir, _output, parent_top, flags);
	  }
	}
	break;

	/* this is an element: */
      case TMESH_FS_DIRENT_ELEMENT:
	element = entry->tmesh_fs_dirent_value;
	_tmesh_ls_element(element, _output, flags);
	break;

      default: assert(FALSE);
      }
    
      /* if this was the last entry in the directory, we're done: */
      entry = entry->tmesh_fs_dirent_next;
    } while (entry != parent);
  }
}
Example #6
0
/* this lists an element: */
static void
_tmesh_ls_element(struct tmesh_fs_element *element,
		  char **_output,
		  int flags)
{
  int output_element_argv;
  struct tmesh_fs_element *element_other;
  struct tmesh_fs_element_conn *conn, *conn_other;

  /* we haven't yet output the element's argv: */
  output_element_argv = FALSE;

  /* loop over the element's connections: */
  for (conn = element->tmesh_fs_element_conns;
       conn != NULL;
       conn = conn->tmesh_fs_element_conn_next) {

    /* if we're not showing all connections, and this connection was
       made after this element was created, skip it: */
    if (!(flags & TMESH_LS_ALL)
	&& (conn->tmesh_fs_element_conn_gen
	    > element->tmesh_fs_element_gen)) {
      continue;
    }

    /* output this element's name and connection argv: */
    _tmesh_fs_pathname_element(element, _output, 
			       ((flags & TMESH_LS_ABSOLUTE)
				? NULL
				: element->tmesh_fs_element_parent));
    _tmesh_ls_output_argv(_output, &conn->tmesh_fs_element_conn_argv, 1);

    /* get the other side of this connection: */
    conn_other = conn->tmesh_fs_element_conn_other;
    element_other = conn_other->tmesh_fs_element_conn_element;
    tme_output_append(_output, " at ");      

    /* output the other element's name and connection argv: */
    _tmesh_fs_pathname_element(element_other, _output, 
			       ((flags & TMESH_LS_ABSOLUTE)
				? NULL
				: element->tmesh_fs_element_parent));
    _tmesh_ls_output_argv(_output, &conn_other->tmesh_fs_element_conn_argv, 1);

    /* if we haven't output the element's creation argv yet, do so: */
    if (!output_element_argv) {
      tme_output_append(_output, ":");
      _tmesh_ls_output_argv(_output, &element->tmesh_fs_element_argv, 0);
      output_element_argv = TRUE;
    }

    /* output a newline: */
    tme_output_append(_output, "\n");
  }

  /* if we haven't output the element's creation argv yet, do so: */
  if (!output_element_argv) {
    _tmesh_fs_pathname_element(element, _output, 
			       ((flags & TMESH_LS_ABSOLUTE)
				? NULL
				: element->tmesh_fs_element_parent));
    tme_output_append(_output, ":");
    _tmesh_ls_output_argv(_output, &element->tmesh_fs_element_argv, 0);
    tme_output_append(_output, "\n");
  }    
}
Example #7
0
/* the new serial function: */
TME_ELEMENT_SUB_NEW_DECL(tme_host_posix,serial) {
  struct tme_posix_serial *serial;
  const char *filename_in;
  const char *filename_out;
  int fd_in, fd_out;
  int usage;
  int arg_i;
  int saved_errno;
  int emulate_break;

  /* initialize: */
  filename_in = NULL;
  filename_out = NULL;
  emulate_break = FALSE;
  arg_i = 1;
  usage = FALSE;

  /* loop reading our arguments: */
  for (;;) {

    /* the device we're supposed to use for input: */
    if (TME_ARG_IS(args[arg_i + 0], "device-input")
	&& args[arg_i + 1] != NULL
	&& filename_in == NULL) {
      filename_in = args[arg_i + 1];
      arg_i += 2;
    }

    /* the device we're supposed to use for output: */
    else if (TME_ARG_IS(args[arg_i + 0], "device-output")
	     && args[arg_i + 1] != NULL
	     && filename_out == NULL) {
      filename_out = args[arg_i + 1];
      arg_i += 2;
    }

    /* the device we're supposed to use for input and output: */
    else if (TME_ARG_IS(args[arg_i + 0], "device")
	     && args[arg_i + 1] != NULL
	     && filename_in == NULL
	     && filename_out == NULL) {
      filename_in = filename_out = args[arg_i + 1];
      arg_i += 2;
    }

    /* if we're supposed to emulate break: */
    else if (TME_ARG_IS(args[arg_i + 0], "break-carats")) {
      emulate_break = TRUE;
      arg_i++;
    }

    /* if we've run out of arguments: */
    else if (args[arg_i + 0] == NULL) {

      /* we must have been given input and output devices: */
      if (filename_in == NULL
	  || filename_out == NULL) {
	usage = TRUE;
      }
      break;
    }

    /* this is a bad argument: */
    else {
      tme_output_append_error(_output,
			      "%s %s", 
			      args[arg_i],
			      _("unexpected"));
      usage = TRUE;
      break;
    }
  }

  if (usage) {
    tme_output_append_error(_output, 
			    "%s %s { device %s | { device-input %s device-output %s } } [break-carats]",
			    _("usage:"),
			    args[0],
			    _("DEVICE"),
			    _("DEVICE"),
			    _("DEVICE"));
    return (EINVAL);
  }

  /* open the devices: */
  fd_in = fd_out = -1;
  if (fd_in < 0
      && !strcmp(filename_in, "-")) {
    fd_in = STDIN_FILENO;
  }
  if (fd_out < 0
      && !strcmp(filename_out, "-")) {
    fd_out = STDOUT_FILENO;
  }
  if (fd_in < 0) {
    if (strcmp(filename_in, filename_out) == 0) {
      if (strcmp(filename_in, "pty") == 0) {
	fd_in = fd_out = posix_openpt(O_RDWR | O_NONBLOCK);
	if (fd_in != -1) {
	  int serrno;
	  if (grantpt(fd_in) == -1) {
bad:	     serrno = errno;
	    (void)close(fd_in);
	    (void)close(fd_out);
	    errno = serrno;
	  } else {
	    filename_in = filename_out = ptsname(fd_in);
	    if (filename_in) {
	      tme_output_append(_output, "Using %s as console\n", filename_in);
	    } else {
	      goto bad;
	    }
	  }
	}
      } else {
	fd_in = fd_out = open(filename_in, O_RDWR | O_NONBLOCK);
      }
    }
    else {
      fd_in = open(filename_in, O_RDONLY | O_NONBLOCK);
    }
    if (fd_in < 0) {
      tme_output_append_error(_output, "%s", filename_in);
      return (errno);
    }
  }
  if (fd_out < 0) {
    fd_out = open(filename_out, O_WRONLY | O_NONBLOCK);
    if (fd_out < 0) {
      saved_errno = errno;
      close(fd_in);
      tme_output_append_error(_output, "%s", filename_out);
      return (saved_errno);
    }
  }

  /* start the serial structure: */
  serial = tme_new0(struct tme_posix_serial, 1);
  serial->tme_posix_serial_element = element;
  serial->tme_posix_serial_fd_in = fd_in;
  serial->tme_posix_serial_fd_out = fd_out;
  serial->tme_posix_serial_emulate_break = emulate_break;
  serial->tme_posix_serial_ctrl_callout = 0;
  serial->tme_posix_serial_ctrl_callout_last = 0;
  tme_serial_buffer_init(&serial->tme_posix_serial_buffer_in, 
			 TME_POSIX_SERIAL_BUFFER_SIZE);
  tme_serial_buffer_init(&serial->tme_posix_serial_buffer_out, 
			 TME_POSIX_SERIAL_BUFFER_SIZE);

  /* start the threads: */
  tme_mutex_init(&serial->tme_posix_serial_mutex);
  tme_cond_init(&serial->tme_posix_serial_cond_writer);
  tme_thread_create((tme_thread_t) _tme_posix_serial_th_writer, serial);
  tme_thread_create((tme_thread_t) _tme_posix_serial_th_reader, serial);
  tme_thread_create((tme_thread_t) _tme_posix_serial_th_ctrl, serial);

  /* fill the element: */
  element->tme_element_private = serial;
  element->tme_element_connections_new = _tme_posix_serial_connections_new;

  return (TME_OK);
}