Add build infrastructure and argument parsing class

Change-Id: Ifb8f283733fe4de531859dc895da35a3a01071a0
Signed-off-by: Eddie James <eajames@linux.ibm.com>
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..d113997
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,22 @@
+bin_PROGRAMS = obmc-ikvm
+
+noinst_HEADERS = \
+	ikvm_args.hpp
+
+obmc_ikvm_SOURCES = \
+	ikvm_args.cpp \
+	obmc-ikvm.cpp
+
+obmc_ikvm_CXXFLAGS = \
+	$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
+	$(PHOSPHOR_LOGGING_CFLAGS) \
+	$(PTHREAD_CFLAGS) \
+	$(SDBUSPLUS_CFLAGS) \
+	$(LIBVNCSERVER_CFLAGS)
+
+obmc_ikvm_LDFLAGS = \
+	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+	$(PHOSPHOR_LOGGING_LIBS) \
+	$(PTHREAD_LIBS) \
+	$(SDBUSPLUS_LIBS) \
+	$(LIBVNCSERVER_LIBS)
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..50b75b7
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+AUTOCONF_FILES="Makefile.in aclocal.m4 ar-lib autom4te.cache compile \
+        config.guess config.h.in config.sub configure depcomp install-sh \
+        ltmain.sh missing *libtool test-driver"
+
+case $1 in
+    clean)
+        test -f Makefile && make maintainer-clean
+        for file in ${AUTOCONF_FILES}; do
+            find -name "$file" | xargs -r rm -rf
+        done
+        exit 0
+        ;;
+esac
+
+autoreconf -i
+echo 'Run "./configure ${CONFIGURE_FLAGS} && make"'
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..6713160
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,29 @@
+# Initialization
+AC_PREREQ([2.69])
+AC_INIT([obmc-ikvm], [1.0], [https://github.com/openbmc/obmc-ikvm/issues])
+AC_LANG([C++])
+AC_CONFIG_HEADERS([config.h])
+AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz])
+AM_SILENT_RULES([yes])
+
+# Checks for programs.
+AC_PROG_CXX
+AM_PROG_AR
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+# Checks for typedefs, structures, and compiler characteristics.
+AX_CXX_COMPILE_STDCXX_17([noext])
+AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
+
+# Checks for libraries.
+AC_CHECK_LIB([pthread], [pthread_create])
+PKG_CHECK_MODULES([LIBVNCSERVER], [libvncserver], , AC_MSG_ERROR(["Requires libvncserver package."]))
+PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus], , AC_MSG_ERROR(["Requires sdbusplus package."]))
+PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging], , AC_MSG_ERROR(["Requires phosphor-logging package."]))
+PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces], , AC_MSG_ERROR(["Requires phosphor-dbus-interfaces package."]))
+
+LT_INIT
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/ikvm_args.cpp b/ikvm_args.cpp
new file mode 100644
index 0000000..61a773a
--- /dev/null
+++ b/ikvm_args.cpp
@@ -0,0 +1,55 @@
+#include "ikvm_args.hpp"
+
+#include <getopt.h>
+#include <rfb/rfb.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace ikvm
+{
+
+Args::Args(int argc, char* argv[]) : frameRate(30), commandLine(argc, argv)
+{
+    int option;
+    const char* opts = "f:hi:v:";
+    struct option lopts[] = {{"frameRate", 1, 0, 'f'},
+                             {"help", 0, 0, 'h'},
+                             {"input", 1, 0, 'i'},
+                             {"videoDevice", 1, 0, 'v'},
+                             {0, 0, 0, 0}};
+
+    while ((option = getopt_long(argc, argv, opts, lopts, NULL)) != -1)
+    {
+        switch (option)
+        {
+            case 'f':
+                frameRate = (int)strtol(optarg, NULL, 0);
+                if (frameRate < 0 || frameRate > 60)
+                    frameRate = 30;
+                break;
+            case 'h':
+                printUsage();
+                exit(0);
+            case 'i':
+                inputPath = std::string(optarg);
+                break;
+            case 'v':
+                videoPath = std::string(optarg);
+                break;
+        }
+    }
+}
+
+void Args::printUsage()
+{
+    // use fprintf(stderr to match rfbUsage()
+    fprintf(stderr, "OpenBMC IKVM daemon\n");
+    fprintf(stderr, "Usage: obmc-ikvm [options]\n");
+    fprintf(stderr, "-f frame rate          try this frame rate\n");
+    fprintf(stderr, "-h, --help             show this message and exit\n");
+    fprintf(stderr, "-i device              HID gadget device\n");
+    fprintf(stderr, "-v device              V4L2 device\n");
+    rfbUsage();
+}
+
+} // namespace ikvm
diff --git a/ikvm_args.hpp b/ikvm_args.hpp
new file mode 100644
index 0000000..489718b
--- /dev/null
+++ b/ikvm_args.hpp
@@ -0,0 +1,111 @@
+#pragma once
+
+#include <string>
+
+namespace ikvm
+{
+
+/*
+ * @class Args
+ * @brief Command line argument parser and storage
+ */
+class Args
+{
+  public:
+    /*
+     * @struct CommandLine
+     * @brief Stores the original command line arguments for later use
+     */
+    struct CommandLine
+    {
+        /*
+         * @brief Constructs CommandLine object
+         *
+         * @param[in] c - Number of arguments
+         * @param[in] v - Array of arguments
+         */
+        CommandLine(int c, char** v) : argc(c), argv(v)
+        {
+        }
+        ~CommandLine() = default;
+        CommandLine(const CommandLine&) = default;
+        CommandLine& operator=(const CommandLine&) = default;
+        CommandLine(CommandLine&&) = default;
+        CommandLine& operator=(CommandLine&&) = default;
+
+        int argc;
+        char** argv;
+    };
+
+    /*
+     * @brief Constructs Args object
+     *
+     * @param[in] argc - The number of arguments in the command line call
+     * @param[in] argv - The array of arguments from the command line
+     */
+    Args(int argc, char* argv[]);
+    ~Args() = default;
+    Args(const Args&) = default;
+    Args& operator=(const Args&) = default;
+    Args(Args&&) = default;
+    Args& operator=(Args&&) = default;
+
+    /*
+     * @brief Get the original command line arguments
+     *
+     * @return Reference to the CommandLine structure storing the original
+     *         command line arguments
+     */
+    inline const CommandLine& getCommandLine() const
+    {
+        return commandLine;
+    }
+
+    /*
+     * @brief Get the desired video frame rate
+     *
+     * @return Value of the desired frame rate in frames per second
+     */
+    inline int getFrameRate() const
+    {
+        return frameRate;
+    }
+
+    /*
+     * @brief Get the path to the USB input device
+     *
+     * @return Reference to the string storing the path to the input device
+     */
+    inline const std::string& getInputPath() const
+    {
+        return inputPath;
+    }
+
+    /*
+     * @brief Get the path to the V4L2 video device
+     *
+     * @return Reference to the string storing the path to the video device
+     */
+    inline const std::string& getVideoPath() const
+    {
+        return videoPath;
+    }
+
+  private:
+    /* @brief Prints the application usage to stderr */
+    void printUsage();
+
+    /*
+     * @brief Desired frame rate (in frames per second) of the video
+     *        stream
+     */
+    int frameRate;
+    /* @brief Path to the USB input device */
+    std::string inputPath;
+    /* @brief Path to the V4L2 video device */
+    std::string videoPath;
+    /* @brief Original command line arguments passed to the application */
+    CommandLine commandLine;
+};
+
+} // namespace ikvm
diff --git a/obmc-ikvm.cpp b/obmc-ikvm.cpp
new file mode 100644
index 0000000..fa413c1
--- /dev/null
+++ b/obmc-ikvm.cpp
@@ -0,0 +1,8 @@
+#include "ikvm_args.hpp"
+
+int main(int argc, char* argv[])
+{
+    ikvm::Args args(argc, argv);
+
+    return 0;
+}