--- /dev/null
+/* Copyright 2007, Robert Nelson\r
+ * Released under terms of the GNU General Public License as\r
+ * required by the license on 'mtxl.c'.\r
+ * $Date: 2007-01-28 19:23:33 -0800 (Sun, 28 Jan 2007) $\r
+ * $Revision: 125 $\r
+ */\r
+\r
+/* This is a generic SCSI device control program. It operates by\r
+ * directly sending commands to the device.\r
+ */\r
+\r
+/* \r
+ * Commands:\r
+ * load -- Load medium\r
+ * unload -- Unload medium\r
+ * start -- Start device\r
+ * stop -- Stop device\r
+ * lock -- Lock medium\r
+ * unlock -- Unlock medium\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "mtx.h"\r
+#include "mtxl.h"\r
+\r
+#if HAVE_UNISTD_H\r
+#include <unistd.h>\r
+#endif\r
+\r
+#if HAVE_SYS_TYPES_H\r
+#include <sys/types.h>\r
+#endif\r
+\r
+#ifdef _MSC_VER\r
+#include <io.h>\r
+#endif\r
+\r
+char *argv0;\r
+\r
+/* the device handle we're operating upon. */\r
+static char *device; /* the device name. */\r
+static DEVICE_TYPE DeviceFD = (DEVICE_TYPE) -1;\r
+\r
+static int S_load(void);\r
+static int S_unload(void);\r
+static int S_start(void);\r
+static int S_stop(void);\r
+static int S_lock(void);\r
+static int S_unlock(void);\r
+\r
+struct command_table_struct\r
+{\r
+ char *name;\r
+ int (*command)(void);\r
+}\r
+ command_table[] =\r
+{\r
+ { "load", S_load },\r
+ { "unload", S_unload },\r
+ { "start", S_start },\r
+ { "stop", S_stop },\r
+ { "lock", S_lock },\r
+ { "unlock", S_unlock },\r
+ { NULL, NULL } /* terminate list */\r
+};\r
+\r
+void Usage(void)\r
+{\r
+ FatalError("Usage: scsieject -f <generic-device> <command> where <command> is:\n load | unload | start | stop | lock | unlock\n");\r
+}\r
+\r
+/* open_device() -- set the 'DeviceFD' variable.... */\r
+void open_device(void)\r
+{\r
+ if (DeviceFD != -1)\r
+ {\r
+ SCSI_CloseDevice("Unknown", DeviceFD);\r
+ }\r
+\r
+ DeviceFD = SCSI_OpenDevice(device);\r
+}\r
+\r
+/* we see if we've got a file open. If not, we open one :-(. Then\r
+ * we execute the actual command. Or not :-(. \r
+ */ \r
+int execute_command(struct command_table_struct *command)\r
+{\r
+ /*\r
+ * If the device is not already open, then open it from the \r
+ * environment.\r
+ */\r
+ if (DeviceFD == -1)\r
+ {\r
+ /* try to get it from STAPE or TAPE environment variable... */\r
+ if ((device = getenv("STAPE")) == NULL &&\r
+ (device = getenv("TAPE")) == NULL)\r
+ {\r
+ Usage(); /* Doesn't return */\r
+ }\r
+\r
+ open_device();\r
+ }\r
+\r
+ /* okay, now to execute the command... */\r
+ return command->command();\r
+}\r
+\r
+\r
+/* parse_args():\r
+ * Basically, we are parsing argv/argc. We can have multiple commands\r
+ * on a line, such as "load start" to load a tape and start the device.\r
+ * We execute these commands one at a time as we come to them. If we don't \r
+ * have a -f at the start and the default device isn't defined in a TAPE or \r
+ * STAPE environment variable, we exit.\r
+ */ \r
+\r
+int parse_args(int argc, char **argv)\r
+{\r
+ int index, retval;\r
+ struct command_table_struct *command;\r
+\r
+ argv0 = argv[0];\r
+\r
+ for (index = 1; index < argc; index++)\r
+ {\r
+ if (strcmp(argv[index], "-f") == 0)\r
+ {\r
+ index++;\r
+ if (index >= argc)\r
+ {\r
+ Usage(); /* Doesn't return */\r
+ }\r
+ device = argv[index];\r
+ open_device();\r
+ }\r
+ else\r
+ {\r
+ for (command = &command_table[0]; command->name != NULL; command++)\r
+ {\r
+ if (strcmp(command->name, argv[index]) == 0)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (command->name == NULL)\r
+ {\r
+ Usage(); /* Doesn't return */\r
+ }\r
+\r
+ retval = execute_command(command);\r
+\r
+ if (retval < 0)\r
+ {\r
+ /* Command failed, we probably shouldn't continue */\r
+ return retval;\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int S_load(void)\r
+{\r
+ int result = LoadUnload(DeviceFD, 1);\r
+\r
+ if (result < 0)\r
+ {\r
+ fputs("scsieject: load failed\n", stderr);\r
+ fflush(stderr);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+int S_unload(void)\r
+{\r
+ int result = LoadUnload(DeviceFD, 0);\r
+\r
+ if (result < 0)\r
+ {\r
+ fputs("scsieject: unload failed\n", stderr);\r
+ fflush(stderr);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+int S_start(void)\r
+{\r
+ int result = StartStop(DeviceFD, 1);\r
+\r
+ if (result < 0)\r
+ {\r
+ fputs("scsieject: start failed\n", stderr);\r
+ fflush(stderr);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+int S_stop(void)\r
+{\r
+ int result = StartStop(DeviceFD, 0);\r
+\r
+ if (result < 0)\r
+ {\r
+ fputs("scsieject: stop failed\n", stderr);\r
+ fflush(stderr);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+int S_lock(void)\r
+{\r
+ int result = LockUnlock(DeviceFD, 1);\r
+\r
+ if (result < 0)\r
+ {\r
+ fputs("scsieject: lock failed\n", stderr);\r
+ fflush(stderr);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+int S_unlock(void)\r
+{\r
+ int result = LockUnlock(DeviceFD, 0);\r
+\r
+ if (result < 0)\r
+ {\r
+ fputs("scsieject: unlock failed\n", stderr);\r
+ fflush(stderr);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* See parse_args for the scoop. parse_args does all. */\r
+int main(int argc, char **argv)\r
+{\r
+ parse_args(argc, argv);\r
+\r
+ if (device)\r
+ {\r
+ SCSI_CloseDevice(device, DeviceFD);\r
+ }\r
+\r
+ exit(0);\r
+}\r