]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
add new ply-terminal-session class
authorRay Strode <rstrode@redhat.com>
Mon, 21 May 2007 12:02:34 +0000 (08:02 -0400)
committerRay Strode <rstrode@redhat.com>
Mon, 21 May 2007 12:02:34 +0000 (08:02 -0400)
This commit features the first cut of a class that can run a
program and direct its console to a pseudoterminal.

src/ply-terminal-session.c [new file with mode: 0644]
src/ply-terminal-session.h [new file with mode: 0644]
src/ply-terminal.c
src/tests/ply-terminal-session-test.am [new file with mode: 0644]

diff --git a/src/ply-terminal-session.c b/src/ply-terminal-session.c
new file mode 100644 (file)
index 0000000..65e00d4
--- /dev/null
@@ -0,0 +1,200 @@
+/* ply-terminal-session.c - api for spawning a program in pseudo-terminal
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-terminal-session.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "ply-terminal.h"
+#include "ply-utils.h"
+
+struct _ply_terminal_session
+{
+  ply_terminal_t *terminal;
+  char **argv;
+};
+
+ply_terminal_session_t *
+ply_terminal_session_new (const char * const *argv)
+                          
+{
+  ply_terminal_session_t *session;
+
+  assert (argv != NULL);
+
+  session = calloc (1, sizeof (ply_terminal_session_t));
+  session->argv = ply_copy_string_array (argv);
+  session->terminal = ply_terminal_new ();
+
+  return session;
+}
+
+void
+ply_terminal_session_free (ply_terminal_session_t *session)
+{
+  if (session == NULL)
+    return;
+
+  ply_free_string_array (session->argv);
+  ply_terminal_free (session->terminal);
+  free (session);
+}
+
+static bool
+ply_terminal_session_open_console (ply_terminal_session_t *session)
+{
+  int fd;
+  const char *terminal_name;
+
+  terminal_name = ply_terminal_get_device_name (session->terminal);
+
+  fd = open (terminal_name, O_RDONLY); 
+
+  if (fd < 0)
+    return false;
+
+  assert (fd == STDIN_FILENO);
+  assert (ttyname (fd) != NULL);
+  assert (strcmp (ttyname (fd), terminal_name) == 0);
+
+  fd = open (terminal_name, O_WRONLY); 
+
+  if (fd < 0)
+    return false;
+
+  assert (fd == STDOUT_FILENO);
+  assert (ttyname (fd) != NULL);
+  assert (strcmp (ttyname (fd), terminal_name) == 0);
+
+  fd = open (terminal_name, O_WRONLY); 
+
+  if (fd < 0)
+    return false;
+
+  assert (fd == STDERR_FILENO);
+  assert (ttyname (fd) != NULL);
+  assert (strcmp (ttyname (fd), terminal_name) == 0);
+
+  return true;
+}
+
+static bool
+ply_terminal_session_execute (ply_terminal_session_t *session,
+                              bool                    look_in_path)
+{
+  ply_close_all_fds ();
+
+  if (!ply_terminal_session_open_console (session))
+    return false;
+
+  if (look_in_path)
+    execvp (session->argv[0], session->argv);
+  else
+    execv (session->argv[0], session->argv);
+
+  return false;
+}
+
+bool 
+ply_terminal_session_run (ply_terminal_session_t *session,
+                          ply_terminal_session_flags_t flags)
+{
+  int pid;
+  bool run_in_parent, look_in_path;
+  
+  assert (session != NULL);
+
+  run_in_parent = (flags & PLY_TERMINAL_SESSION_FLAGS_RUN_IN_PARENT) != 0;
+  look_in_path = (flags & PLY_TERMINAL_SESSION_FLAGS_LOOK_IN_PATH) != 0;
+
+  if (!ply_terminal_create_device (session->terminal))
+    return false;
+
+  pid = fork ();
+
+  if (pid < 0)
+    return false;
+
+  if (((pid == 0) && run_in_parent) ||
+      ((pid != 0) && !run_in_parent))
+    return true;
+
+  ply_terminal_session_execute (session, look_in_path);
+
+  _exit (errno);
+}
+
+int
+ply_terminal_session_get_fd (ply_terminal_session_t *session)
+{
+  assert (session != NULL);
+
+  return ply_terminal_get_fd (session->terminal);
+}
+
+#ifdef PLY_TERMINAL_SESSION_ENABLE_TEST
+
+#include <stdio.h>
+
+int
+main (int    argc,
+      char **argv)
+{
+  ply_terminal_session_t *session;
+  uint8_t byte;
+  int exit_code;
+  ply_terminal_session_flags_t flags;
+
+  exit_code = 0;
+
+  session = ply_terminal_session_new ((const char * const *) (argv + 1));
+
+  flags = PLY_TERMINAL_SESSION_FLAGS_RUN_IN_PARENT;
+  flags |= PLY_TERMINAL_SESSION_FLAGS_LOOK_IN_PATH;
+
+  if (!ply_terminal_session_run (session, flags))
+    {
+      perror ("could not start terminal session");
+      return errno;
+    }
+
+  while (read (ply_terminal_session_get_fd (session), 
+               &byte, sizeof (byte)) == 1)
+    printf ("%c", byte);
+
+  ply_terminal_session_free (session);
+
+  return exit_code;
+}
+
+#endif /* PLY_TERMINAL_SESSION_ENABLE_TEST */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/ply-terminal-session.h b/src/ply-terminal-session.h
new file mode 100644 (file)
index 0000000..9408f0d
--- /dev/null
@@ -0,0 +1,48 @@
+/* ply-terminal-session.h - api for spawning a program in pseudo-terminal
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written By: Ray Strode <rstrode@redhat.com>
+ */
+#ifndef PLY_TERMINAL_SESSION_H
+#define PLY_TERMINAL_SESSION_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+typedef struct _ply_terminal_session ply_terminal_session_t;
+
+typedef enum
+{
+  PLY_TERMINAL_SESSION_FLAGS_NONE = 0x0,
+  PLY_TERMINAL_SESSION_FLAGS_RUN_IN_PARENT = 0x1,
+  PLY_TERMINAL_SESSION_FLAGS_LOOK_IN_PATH = 0x2
+} ply_terminal_session_flags_t;
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+ply_terminal_session_t *ply_terminal_session_new (const char * const *argv);
+                                                  
+void ply_terminal_session_free (ply_terminal_session_t *session);
+bool ply_terminal_session_run (ply_terminal_session_t *session,
+                               ply_terminal_session_flags_t flags);
+int ply_terminal_session_get_fd (ply_terminal_session_t *session);
+#endif
+
+#endif /* PLY_TERMINAL_SESSION_H */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
index 1f0f113b377f48d4a5223a33a66e44cd30f12c80..3e2195ccf82d60de97a18456fe60e76413f3a365 100644 (file)
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <stdbool.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -70,7 +71,10 @@ ply_terminal_create_device (ply_terminal_t *terminal)
   assert (terminal != NULL);
   assert (!ply_terminal_has_device (terminal));
 
+#if 0
   terminal->fd = posix_openpt (O_RDWR | O_NOCTTY);
+#endif
+  terminal->fd = open ("/dev/ptmx", O_RDWR | O_NOCTTY);
 
   if (terminal->fd < 0)
     return false;
diff --git a/src/tests/ply-terminal-session-test.am b/src/tests/ply-terminal-session-test.am
new file mode 100644 (file)
index 0000000..6044627
--- /dev/null
@@ -0,0 +1,12 @@
+TESTS += ply-terminal-session-test
+
+ply_terminal_session_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_TERMINAL_SESSION_ENABLE_TEST
+ply_terminal_session_test_LDADD = $(PLYMOUTH_LIBS)
+
+ply_terminal_session_test_SOURCES =                                                   \
+                          $(srcdir)/../ply-utils.h                                    \
+                          $(srcdir)/../ply-utils.c                                    \
+                          $(srcdir)/../ply-terminal.h                                 \
+                          $(srcdir)/../ply-terminal.c                                 \
+                          $(srcdir)/../ply-terminal-session.h                         \
+                          $(srcdir)/../ply-terminal-session.c