summaryrefslogtreecommitdiff
path: root/extras/scsi_id/scsi_id.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras/scsi_id/scsi_id.c')
-rw-r--r--extras/scsi_id/scsi_id.c124
1 files changed, 64 insertions, 60 deletions
diff --git a/extras/scsi_id/scsi_id.c b/extras/scsi_id/scsi_id.c
index d34d9284e5..df18271b48 100644
--- a/extras/scsi_id/scsi_id.c
+++ b/extras/scsi_id/scsi_id.c
@@ -23,7 +23,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <getopt.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
@@ -33,12 +32,19 @@
#include <stdarg.h>
#include <ctype.h>
#include <sys/stat.h>
-#include <sys/libsysfs.h>
+#ifdef __KLIBC__
+/*
+ * Assume built under udev with KLIBC
+ */
+#include <libsysfs.h>
+#else
+#include <sysfs/libsysfs.h>
+#endif
#include "scsi_id.h"
-#ifndef VERSION
+#ifndef SCSI_ID_VERSION
#warning No version
-#define VERSION "unknown"
+#define SCSI_ID_VERSION "unknown"
#endif
/*
@@ -49,36 +55,11 @@
#define CONFIG_FILE "/etc/scsi_id.config"
-#define MAX_NAME_LEN 72
-
-#define MAX_SERIAL_LEN 128
-
static const char short_options[] = "bc:d:ef:gip:s:vV";
-static const struct option long_options[] = {
- {"broken", no_argument, NULL, 'b'}, /* also per dev */
- {"callout", required_argument, NULL, 'c'}, /* also per dev */
- {"device", required_argument, NULL, 'd'},
- {"stderr", no_argument, NULL, 'e'},
- {"file", required_argument, NULL, 'f'},
- {"good", no_argument, NULL, 'g'}, /* also per dev */
- {"busid", no_argument, NULL, 'i'}, /* also per dev */
- {"page", required_argument, NULL, 'p'}, /* also per dev */
- {"devpath", required_argument, NULL, 's'},
- {"verbose", no_argument, NULL, 'v'},
- {"version", no_argument, NULL, 'V'},
- {0, 0, 0, 0}
-};
/*
* Just duplicate per dev options.
*/
static const char dev_short_options[] = "bc:gp:";
-static const struct option dev_long_options[] = {
- {"broken", no_argument, NULL, 'b'}, /* also per dev */
- {"callout", required_argument, NULL, 'c'}, /* also per dev */
- {"good", no_argument, NULL, 'g'}, /* also per dev */
- {"page", required_argument, NULL, 'p'}, /* also per dev */
- {0, 0, 0, 0}
-};
char sysfs_mnt_path[SYSFS_PATH_MAX];
@@ -105,8 +86,13 @@ void log_message (int level, const char *format, ...)
vfprintf(stderr, format, args);
} else {
static int logging_init = 0;
+ static unsigned char logname[32];
if (!logging_init) {
- openlog ("scsi_id", LOG_PID, LOG_DAEMON);
+ /*
+ * klibc does not have LOG_PID.
+ */
+ snprintf(logname, 32, "scsi_id[%d]", getpid());
+ openlog (logname, 0, LOG_DAEMON);
logging_init = 1;
}
@@ -295,7 +281,7 @@ static int argc_count(char *opts)
static int get_file_options(char *vendor, char *model, int *argc,
char ***newargv)
{
- char buffer[256];
+ char *buffer;
FILE *fd;
char *buf;
char *str1;
@@ -303,7 +289,6 @@ static int get_file_options(char *vendor, char *model, int *argc,
int lineno;
int c;
int retval = 0;
- static char *prog_string = "arg0";
dprintf("vendor='%s'; model='%s'\n", vendor, model);
fd = fopen(config_file, "r");
@@ -318,16 +303,31 @@ static int get_file_options(char *vendor, char *model, int *argc,
}
}
+ /*
+ * Allocate a buffer rather than put it on the stack so we can
+ * keep it around to parse any options (any allocated newargv
+ * points into this buffer for its strings).
+ */
+ buffer = malloc(MAX_BUFFER_LEN);
+ if (!buffer) {
+ log_message(LOG_WARNING, "Can't allocate memory.\n");
+ return -1;
+ }
+
*newargv = NULL;
lineno = 0;
-
while (1) {
vendor_in = model_in = options_in = NULL;
- buf = fgets(buffer, sizeof(buffer), fd);
+ buf = fgets(buffer, MAX_BUFFER_LEN, fd);
if (buf == NULL)
break;
lineno++;
+ if (buf[strlen(buffer) - 1] != '\n') {
+ log_message(LOG_WARNING,
+ "Config file line %d too long.\n", lineno);
+ break;
+ }
while (isspace(*buf))
buf++;
@@ -419,18 +419,24 @@ static int get_file_options(char *vendor, char *model, int *argc,
* Something matched. Allocate newargv, and store
* values found in options_in.
*/
- c = argc_count(options_in) + 2;
+ strcpy(buffer, options_in);
+ c = argc_count(buffer) + 2;
*newargv = calloc(c, sizeof(**newargv));
if (!*newargv) {
log_message(LOG_WARNING,
- "Can't allocate memory\n");
+ "Can't allocate memory.\n");
retval = -1;
} else {
*argc = c;
c = 0;
- (*newargv)[c] = prog_string; /* nothing */
+ /*
+ * argv[0] at 0 is skipped by getopt, but
+ * store the buffer address there for
+ * alter freeing.
+ */
+ (*newargv)[c] = buffer;
for (c = 1; c < *argc; c++)
- (*newargv)[c] = strsep(&options_in, " ");
+ (*newargv)[c] = strsep(&buffer, " ");
}
} else {
/*
@@ -439,26 +445,26 @@ static int get_file_options(char *vendor, char *model, int *argc,
retval = 1;
}
}
+ if (retval != 0)
+ free(buffer);
fclose(fd);
return retval;
}
static int set_options(int argc, char **argv, const char *short_opts,
- const struct option *long_opts, char *target,
- char *maj_min_dev)
+ char *target, char *maj_min_dev)
{
int option;
- int option_ind;
/*
- * optind is a global extern used by getopt_long. Since we can
- * call set_options twice (once for command line, and once for
- * config file) we have to reset this back to 0.
+ * optind is a global extern used by getopt. Since we can call
+ * set_options twice (once for command line, and once for config
+ * file) we have to reset this back to 1. [Note glibc handles
+ * setting this to 0, but klibc does not.]
*/
- optind = 0;
+ optind = 1;
while (1) {
- option = getopt_long(argc, argv, short_options, long_options,
- &option_ind);
+ option = getopt(argc, argv, short_options);
if (option == -1)
break;
@@ -521,7 +527,7 @@ static int set_options(int argc, char **argv, const char *short_opts,
case 'V':
log_message(LOG_WARNING, "scsi_id version: %s\n",
- VERSION);
+ SCSI_ID_VERSION);
exit(0);
break;
@@ -544,8 +550,6 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
char *vendor;
char *model;
int option;
- int option_ind;
-
*good_bad = all_good;
*page_code = default_page_code;
@@ -562,7 +566,7 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
}
model = sysfs_get_attr(scsi_dev, "model");
- if (!vendor) {
+ if (!model) {
log_message(LOG_WARNING, "%s: no model attribute\n",
scsi_dev->name);
return -1;
@@ -570,10 +574,9 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
retval = get_file_options(vendor, model, &newargc, &newargv);
- optind = 0; /* global extern, reset to 0 */
+ optind = 1; /* reset this global extern */
while (retval == 0) {
- option = getopt_long(newargc, newargv, dev_short_options,
- dev_long_options, &option_ind);
+ option = getopt(newargc, newargv, dev_short_options);
if (option == -1)
break;
@@ -616,8 +619,10 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
}
}
- if (newargv)
+ if (newargv) {
+ free(newargv[0]);
free(newargv);
+ }
return retval;
}
@@ -747,7 +752,6 @@ static int scsi_id(const char *target_path, char *maj_min_dev)
dprintf("%s\n", serial);
retval = 0;
}
- fflush(stdout);
sysfs_close_class_device(scsi_dev);
if (!dev_specified)
@@ -797,8 +801,8 @@ int main(int argc, char **argv)
strncpy(target_path, sysfs_mnt_path, MAX_NAME_LEN);
strncat(target_path, devpath, MAX_NAME_LEN);
} else {
- if (set_options(argc, argv, short_options, long_options,
- target_path, maj_min_dev) < 0)
+ if (set_options(argc, argv, short_options, target_path,
+ maj_min_dev) < 0)
exit(1);
}
@@ -811,8 +815,8 @@ int main(int argc, char **argv)
if (retval < 0) {
exit(1);
} else if (newargv && (retval == 0)) {
- if (set_options(newargc, newargv, short_options, long_options,
- target_path, maj_min_dev) < 0)
+ if (set_options(newargc, newargv, short_options, target_path,
+ maj_min_dev) < 0)
exit(1);
free(newargv);
}