auto import from //depot/cupcake/@135843
diff --git a/tools/lsd/cmdline.c b/tools/lsd/cmdline.c
new file mode 100644
index 0000000..a3445cd
--- /dev/null
+++ b/tools/lsd/cmdline.c
@@ -0,0 +1,130 @@
+#include <debug.h>
+#include <cmdline.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <ctype.h>
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+static struct option long_options[] = {
+	{"verbose", no_argument, 0, 'V'},
+	{"help", no_argument, 0, 'h'},
+	{"print-info", no_argument, 0, 'p'},
+	{"list-needed-libs", no_argument, 0, 'n'},
+	{"lookup",     required_argument, 0, 'L'},
+	{0, 0, 0, 0},
+};
+
+/* This array must parallel long_options[] */
+static const char *descriptions[] = {
+	"print verbose output",
+	"print help screen",
+	"for each file, generate a listing of all dependencies that each symbol "
+	     "satisfies",
+	"print out a list of needed libraries",
+	"provide a directory for library lookup"
+};
+
+void print_help(void)
+{
+    fprintf(stdout, 
+			"invokation:\n"
+			"\tlsd file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] "
+			"[-Vpn]\n"
+			"or\n"
+			"\tlsd -h\n\n");
+	fprintf(stdout, "options:\n");
+	struct option *opt = long_options;
+	const char **desc = descriptions;
+	while (opt->name) {
+		fprintf(stdout, "\t-%c\n"
+						"\t--%-15s: %s\n",
+				opt->val,
+				opt->name,
+				*desc);
+		opt++;
+		desc++;
+	}
+}
+
+int get_options(int argc, char **argv,
+				int *list_needed_libs,
+				int *info,
+                char ***dirs,
+                int *num_dirs,
+                int *verbose)
+{
+    int c;
+
+	ASSERT(list_needed_libs);
+	*list_needed_libs = 0;
+	ASSERT(info);
+	*info = 0;
+    ASSERT(verbose);
+    *verbose = 0;
+    ASSERT(dirs);
+	*dirs = NULL;
+    ASSERT(num_dirs);
+    int size = 0;
+    *num_dirs = 0;
+
+    while (1) {
+        /* getopt_long stores the option index here. */
+        int option_index = 0;
+
+        c = getopt_long (argc, argv, 
+                         "VhpnL:",
+                         long_options, 
+                         &option_index);
+        /* Detect the end of the options. */
+        if (c == -1) break;
+
+        if (isgraph(c)) {
+            INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
+        }
+
+#define SET_STRING_OPTION(name) do { \
+    ASSERT(optarg);                  \
+    (*name) = strdup(optarg);        \
+} while(0)
+
+        switch (c) {
+        case 0:
+            /* If this option set a flag, do nothing else now. */
+            if (long_options[option_index].flag != 0)
+                break;
+            INFO ("option %s", long_options[option_index].name);
+            if (optarg)
+                INFO (" with arg %s", optarg);
+            INFO ("\n");
+            break;
+        case 'h': print_help(); exit(1); break;
+		case 'V': *verbose = 1; break;
+		case 'p': *info = 1; break;
+		case 'n': *list_needed_libs = 1; break;
+        case 'L': 
+            {
+                if (*num_dirs == size) {
+                    size += 10;
+                    *dirs = (char **)REALLOC(*dirs, size * sizeof(char *));
+                }
+                SET_STRING_OPTION(((*dirs) + *num_dirs));
+                (*num_dirs)++;
+            }
+			break;
+        case '?':
+            /* getopt_long already printed an error message. */
+            break;
+
+#undef SET_STRING_OPTION
+
+        default:
+            FAILIF(1, "Unknown option");
+        }
+    }
+
+    return optind;
+}