aboutsummaryrefslogtreecommitdiffstats
path: root/dos
diff options
context:
space:
mode:
authorShao Miller <shao.miller@yrdsb.edu.on.ca>2010-07-03 19:06:10 -0400
committerShao Miller <shao.miller@yrdsb.edu.on.ca>2010-07-03 19:06:10 -0400
commit1fb6b70cdacaf3ca3c069a6d96434eed3b6bc22f (patch)
tree7dcd6a881e9df4ad6a43ebe7b864a4eade64e869 /dos
parent07aafae7c67b32e432c26ff83279ec83e61592e4 (diff)
downloadsyslinux-devel-1fb6b70cdacaf3ca3c069a6d96434eed3b6bc22f.tar.gz
syslinux-devel-1fb6b70cdacaf3ca3c069a6d96434eed3b6bc22f.tar.xz
syslinux-devel-1fb6b70cdacaf3ca3c069a6d96434eed3b6bc22f.zip
dos: Work-in-progress
Diffstat (limited to 'dos')
-rwxr-xr-x[-rw-r--r--]dos/Makefile5
-rw-r--r--dos/ctype.h3
-rwxr-xr-xdos/getopt.h25
-rwxr-xr-xdos/getopt_long.c152
-rw-r--r--dos/stdio.h2
-rwxr-xr-x[-rw-r--r--]dos/stdlib.h3
-rw-r--r--dos/strchr.c17
-rw-r--r--dos/string.h2
-rw-r--r--dos/strntoumax.c73
-rw-r--r--dos/strtoul.c15
-rw-r--r--dos/sysexits.h1
-rwxr-xr-x[-rw-r--r--]dos/syslinux.c21
12 files changed, 305 insertions, 14 deletions
diff --git a/dos/Makefile b/dos/Makefile
index 574b65ec..3d19ff29 100644..100755
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -28,6 +28,7 @@ INCLUDES = -include code16.h -nostdinc -iwithprefix include \
SRCS = syslinux.c \
../libinstaller/fat.c \
../libinstaller/syslxmod.c \
+ ../libinstaller/syslxopt.c \
../libinstaller/setadv.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c \
@@ -35,8 +36,8 @@ SRCS = syslinux.c \
$(wildcard ../libfat/*.c)
OBJS = header.o crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
LIBOBJS = int2526.o conio.o memcpy.o memset.o memmove.o skipatou.o atou.o \
- malloc.o free.o getsetsl.o \
- argv.o printf.o __divdi3.o __udivmoddi4.o
+ malloc.o free.o getopt_long.o getsetsl.o strchr.o strtoul.o \
+ strntoumax.o argv.o printf.o __divdi3.o __udivmoddi4.o
VPATH = .:../libfat:../libinstaller
diff --git a/dos/ctype.h b/dos/ctype.h
new file mode 100644
index 00000000..c0d00c04
--- /dev/null
+++ b/dos/ctype.h
@@ -0,0 +1,3 @@
+static int isspace(int c) {
+ return (c == ' ');
+}
diff --git a/dos/getopt.h b/dos/getopt.h
new file mode 100755
index 00000000..a1b74b10
--- /dev/null
+++ b/dos/getopt.h
@@ -0,0 +1,25 @@
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+/* (Very slightly) adapted from klibc */
+
+struct option {
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+enum {
+ no_argument = 0,
+ required_argument = 1,
+ optional_argument = 2,
+};
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+extern int getopt_long(int, char *const *, const char *,
+ const struct option *, int *);
+
+#endif /* _GETOPT_H */
diff --git a/dos/getopt_long.c b/dos/getopt_long.c
new file mode 100755
index 00000000..14587797
--- /dev/null
+++ b/dos/getopt_long.c
@@ -0,0 +1,152 @@
+/*
+ * getopt.c
+ *
+ * getopt_long(), or at least a common subset thereof:
+ *
+ * - Option reordering is not supported
+ * - -W foo is not supported
+ * - First optstring character "-" not supported.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include "mystuff.h"
+
+char *optarg;
+int optind, opterr, optopt;
+static struct getopt_private_state {
+ const char *optptr;
+ const char *last_optstring;
+ char *const *last_argv;
+} pvt;
+
+static inline const char *option_matches(const char *arg_str,
+ const char *opt_name)
+{
+ while (*arg_str != '\0' && *arg_str != '=') {
+ if (*arg_str++ != *opt_name++)
+ return NULL;
+ }
+
+ if (*opt_name)
+ return NULL;
+
+ return arg_str;
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring,
+ const struct option *longopts, int *longindex)
+{
+ const char *carg;
+ const char *osptr;
+ int opt;
+
+ /* getopt() relies on a number of different global state
+ variables, which can make this really confusing if there is
+ more than one use of getopt() in the same program. This
+ attempts to detect that situation by detecting if the
+ "optstring" or "argv" argument have changed since last time
+ we were called; if so, reinitialize the query state. */
+
+ if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
+ optind < 1 || optind > argc) {
+ /* optind doesn't match the current query */
+ pvt.last_optstring = optstring;
+ pvt.last_argv = argv;
+ optind = 1;
+ pvt.optptr = NULL;
+ }
+
+ carg = argv[optind];
+
+ /* First, eliminate all non-option cases */
+
+ if (!carg || carg[0] != '-' || !carg[1])
+ return -1;
+
+ if (carg[1] == '-') {
+ const struct option *lo;
+ const char *opt_end = NULL;
+
+ optind++;
+
+ /* Either it's a long option, or it's -- */
+ if (!carg[2]) {
+ /* It's -- */
+ return -1;
+ }
+
+ for (lo = longopts; lo->name; lo++) {
+ if ((opt_end = option_matches(carg+2, lo->name)))
+ break;
+ }
+ if (!opt_end)
+ return '?';
+
+ if (longindex)
+ *longindex = lo-longopts;
+
+ if (*opt_end == '=') {
+ if (lo->has_arg)
+ optarg = (char *)opt_end+1;
+ else
+ return '?';
+ } else if (lo->has_arg == 1) {
+ if (!(optarg = argv[optind]))
+ return '?';
+ optind++;
+ }
+
+ if (lo->flag) {
+ *lo->flag = lo->val;
+ return 0;
+ } else {
+ return lo->val;
+ }
+ }
+
+ if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
+ /* Someone frobbed optind, change to new opt. */
+ pvt.optptr = carg + 1;
+ }
+
+ opt = *pvt.optptr++;
+
+ if (opt != ':' && (osptr = strchr(optstring, opt))) {
+ if (osptr[1] == ':') {
+ if (*pvt.optptr) {
+ /* Argument-taking option with attached
+ argument */
+ optarg = (char *)pvt.optptr;
+ optind++;
+ } else {
+ /* Argument-taking option with non-attached
+ argument */
+ if (argv[optind + 1]) {
+ optarg = (char *)argv[optind+1];
+ optind += 2;
+ } else {
+ /* Missing argument */
+ optind++;
+ return (optstring[0] == ':')
+ ? ':' : '?';
+ }
+ }
+ return opt;
+ } else {
+ /* Non-argument-taking option */
+ /* pvt.optptr will remember the exact position to
+ resume at */
+ if (!*pvt.optptr)
+ optind++;
+ return opt;
+ }
+ } else {
+ /* Unknown option */
+ optopt = opt;
+ if (!*pvt.optptr)
+ optind++;
+ return '?';
+ }
+}
diff --git a/dos/stdio.h b/dos/stdio.h
index 2c256669..c7ca25cb 100644
--- a/dos/stdio.h
+++ b/dos/stdio.h
@@ -16,6 +16,8 @@ int printf(const char *fmt, ...);
#define stdout 1
#define stderr 2
+#define EOF (-1)
+
#define fprintf(x, y, ...) printf(y, ## __VA_ARGS__)
#endif /* STDIO_H */
diff --git a/dos/stdlib.h b/dos/stdlib.h
index 71af6907..d3467056 100644..100755
--- a/dos/stdlib.h
+++ b/dos/stdlib.h
@@ -10,4 +10,7 @@ void *malloc(size_t);
void *calloc(size_t, size_t);
void free(void *);
+extern unsigned long int strtoul(const char *nptr,
+ char **endptr, int base);
+
#endif
diff --git a/dos/strchr.c b/dos/strchr.c
new file mode 100644
index 00000000..83153113
--- /dev/null
+++ b/dos/strchr.c
@@ -0,0 +1,17 @@
+/*
+ * strchr.c
+ */
+
+#include <string.h>
+#include "mystuff.h"
+
+char *strchr(const char *s, int c)
+{
+ while (*s != (char)c) {
+ if (!*s)
+ return NULL;
+ s++;
+ }
+
+ return (char *)s;
+}
diff --git a/dos/string.h b/dos/string.h
index 5ee829e8..f648de2d 100644
--- a/dos/string.h
+++ b/dos/string.h
@@ -21,4 +21,6 @@ static inline int memcmp(const void *__m1, const void *__m2, unsigned int __n)
return rv;
}
+extern char *strchr(const char *s, int c);
+
#endif /* _STRING_H */
diff --git a/dos/strntoumax.c b/dos/strntoumax.c
new file mode 100644
index 00000000..d8bc73bc
--- /dev/null
+++ b/dos/strntoumax.c
@@ -0,0 +1,73 @@
+/*
+ * strntoumax.c
+ *
+ * The strntoumax() function and associated
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ctype.h>
+
+static inline int digitval(int ch)
+{
+ if (ch >= '0' && ch <= '9') {
+ return ch - '0';
+ } else if (ch >= 'A' && ch <= 'Z') {
+ return ch - 'A' + 10;
+ } else if (ch >= 'a' && ch <= 'z') {
+ return ch - 'a' + 10;
+ } else {
+ return -1;
+ }
+}
+
+uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n)
+{
+ int minus = 0;
+ uintmax_t v = 0;
+ int d;
+
+ while (n && isspace((unsigned char)*nptr)) {
+ nptr++;
+ n--;
+ }
+
+ /* Single optional + or - */
+ if (n && *nptr == '-') {
+ minus = 1;
+ nptr++;
+ n--;
+ } else if (n && *nptr == '+') {
+ nptr++;
+ }
+
+ if (base == 0) {
+ if (n >= 2 && nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) {
+ n -= 2;
+ nptr += 2;
+ base = 16;
+ } else if (n >= 1 && nptr[0] == '0') {
+ n--;
+ nptr++;
+ base = 8;
+ } else {
+ base = 10;
+ }
+ } else if (base == 16) {
+ if (n >= 2 && nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) {
+ n -= 2;
+ nptr += 2;
+ }
+ }
+
+ while (n && (d = digitval(*nptr)) >= 0 && d < base) {
+ v = v * base + d;
+ n--;
+ nptr++;
+ }
+
+ if (endptr)
+ *endptr = (char *)nptr;
+
+ return minus ? -v : v;
+}
diff --git a/dos/strtoul.c b/dos/strtoul.c
new file mode 100644
index 00000000..3be94307
--- /dev/null
+++ b/dos/strtoul.c
@@ -0,0 +1,15 @@
+/*
+ * strtoul.c
+ *
+ * strtoul() function
+ */
+
+#include <stddef.h>
+#include <inttypes.h>
+
+extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n);
+
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ return (unsigned long) strntoumax(nptr, endptr, base, ~(size_t) 0);
+}
diff --git a/dos/sysexits.h b/dos/sysexits.h
new file mode 100644
index 00000000..483d3bab
--- /dev/null
+++ b/dos/sysexits.h
@@ -0,0 +1 @@
+#define EX_USAGE 0x40
diff --git a/dos/syslinux.c b/dos/syslinux.c
index 9574553d..891980e8 100644..100755
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -18,15 +18,18 @@
*/
#include <errno.h>
+#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <stdarg.h>
+//#include <stdarg.h>
#include "mystuff.h"
#include "syslinux.h"
#include "libfat.h"
#include "setadv.h"
+#include "sysexits.h"
+#include "syslxopt.h"
const char *program = "syslinux"; /* Name of program */
uint16_t dos_version;
@@ -44,12 +47,6 @@ void pause(void)
# define pause() ((void)0)
#endif
-void __attribute__ ((noreturn)) usage(void)
-{
- puts("Usage: syslinux [-sfmar][-d directory] <drive>: [bootsecfile]\n");
- exit(1);
-}
-
void unlock_device(int);
void __attribute__ ((noreturn)) die(const char *msg)
@@ -617,7 +614,7 @@ int main(int argc, char *argv[])
if (**argp == '-') {
opt = *argp + 1;
if (!*opt)
- usage();
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
while (*opt) {
switch (*opt) {
@@ -641,13 +638,13 @@ int main(int argc, char *argv[])
subdir = *++argp;
break;
default:
- usage();
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
}
opt++;
}
} else {
if (bootsecfile)
- usage();
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
else if (device)
bootsecfile = *argp;
else
@@ -656,7 +653,7 @@ int main(int argc, char *argv[])
}
if (!device)
- usage();
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
/*
* Create an ADV in memory... this should be smarter.
@@ -668,7 +665,7 @@ int main(int argc, char *argv[])
*/
dev_fd = (device[0] & ~0x20) - 0x40;
if (dev_fd < 1 || dev_fd > 26 || device[1] != ':' || device[2])
- usage();
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
set_lock_device(dev_fd);