Re: [Toybox] [New Toy] - modprobe

2013-12-19 Thread ibid . ag
On Thu, Dec 19, 2013 at 11:28:17AM +0530, Ashwini Sharma wrote:
> Hi,
> 
> comments inline...
> 
> attached is the modified file.
> this also includes the fix for alias loading. There was an error in
> modprobe_main().
> 
> llist_pop() returns the struct ag_list*, whereas this was assigned to
> char*, which is modified
> as below.
> 
>   char *real = ((struct arg_list*)llist_pop(&module->rnames))->arg;
>   struct module_s *m2 = get_mod(real, 0);
> 
> regards,
> Ashwini

Looks good for a first version.
And yes, it fixes alias loading.

Thanks,
Isaac Dunham
___
Toybox mailing list
Toybox@lists.landley.net
http://lists.landley.net/listinfo.cgi/toybox-landley.net


Re: [Toybox] [New Toy] - modprobe

2013-12-18 Thread ibid . ag
On Tue, Dec 17, 2013 at 04:39:39PM +0530, Ashwini Sharma wrote:
> Hi List,
> 
> An implementation for modprobe is attached.
> go thru the same and let me know your inputs.
> 
> regards,
> Ashwini

It doesn't quite work.
Specifically, when I try loading by alias:
modprobe -v $ALIAS
I get the message:
"probing $ALIAS by realname"
Which indicates that no alias is matched; presumably this is because
get_mod always returns NULL in this case.

Using resolve_modalias, I can get the real module name and then load it
manually. The source for resolve_modalias is attached.

The only config files presemt are modules.alias, modules.dep, and
modules.symbols.

Thanks,
Isaac Dunham

> 
> /*
>  * Returns struct module_s from the data base if found, NULL otherwise.
>  * if ps - create module entry, add it to data base and return the same mod.
>  */
> static struct module_s *get_mod(char *mod, uint8_t ps)
> {
>   char name[MODNAME_LEN];
>   struct module_s *modentry;
>   struct arg_list *temp;
>   unsigned i, hash = 0;
> 
>   path2mod(mod, name);
>   for (i = 0; name[i]; i++) hash = ((hash*31) + hash) + name[i];
>   hash %= DBASE_SIZE;
>   for (temp = TT.dbase[hash]; temp; temp = temp->next) {
> modentry = (struct module_s *) temp->arg;
> if (!strcmp(modentry->name, name)) return modentry;
>   }
>   if (!ps) return NULL;

This line is the problem, but I'm not sure what's the right fix.

>   modentry = xzalloc(sizeof(*modentry));
>   modentry->name = xstrdup(name);
>   llist_add(&TT.dbase[hash], modentry);
>   return modentry;
> }
> 

> /*
>  * Action to be taken on all config files in default directories
>  * checks for aliases, options, install, remove and blacklist
>  */
> static int config_action(struct dirtree *node)
> {
>   FILE *fc;
>   char *filename, *tokens[3], *line, *linecp;
>   struct module_s *modent;
>   int tcount = 0;
> 
>   if (!dirtree_notdotdot(node)) return 0;
>   if (S_ISDIR(node->st.st_mode)) return DIRTREE_RECURSE;
> 
>   if (!S_ISREG(node->st.st_mode)) return 0; // process only regular file
>   filename = dirtree_path(node, NULL);
>   if (!(fc = fopen(filename, "r"))) {
> free(filename);
> return 0;
>   }
>   for (line = linecp = NULL; read_line(fc, &line) > 0; 
>   free(line), free(linecp), line = linecp = NULL) {
> char *tk = NULL;
> 
> if (!strlen(line)) continue; 
> linecp = xstrdup(line);
> for (tk = strtok(linecp, "# \t"), tcount = 0; tk;
> tk = strtok(NULL, "# \t"), tcount++) {
>   tokens[tcount] = tk;
>   if (tcount == 2) {
> tokens[2] = line + strlen(tokens[0]) + strlen(tokens[1]) + 2;
> break;
>   }
> }
> if (!tk) continue; 
> // process the tokens[0] contains first word of config line.
> if (!strcmp(tokens[0], "alias")) {
>   struct arg_list *temp;
>   char aliase[MODNAME_LEN], *realname;
> 
>   if (!tokens[2]) continue;
>   path2mod(tokens[1], aliase);
>   for (temp = TT.probes; temp; temp = temp->next) {
> modent = (struct module_s *) temp->arg;
> if (fnmatch(aliase, modent->name, 0)) continue;
> realname = path2mod(tokens[2], NULL);
> llist_add(&modent->rnames, realname);
> if (modent->flags & MOD_NDDEPS) {
>   modent->flags &= ~MOD_NDDEPS;
>   TT.nudeps--;
> }
> modent = get_mod(realname, 1);
> if (!(modent->flags & MOD_NDDEPS)) {
>   modent->flags |= MOD_NDDEPS;
>   TT.nudeps++;
> }
>   }
> } else if (!strcmp(tokens[0], "options")) {
>   if (!tokens[2]) continue;
>   modent = get_mod(tokens[1], 1);
>   modent->opts = add_opts(modent->opts, tokens[2]);
> } else if (!strcmp(tokens[0], "include"))
>   dirtree_read(tokens[1], config_action);
> else if (!strcmp(tokens[0], "blacklist"))
>   get_mod(tokens[1], 1)->flags |= MOD_BLACKLIST;
> else if (!strcmp(tokens[0], "install")) continue;
> else if (!strcmp(tokens[0], "remove")) continue;
> else error_msg("Invalid option %s found in file %s", tokens[0], filename);
>   }
>   fclose(fc);
>   free(filename);
>   return 0;
> }

> 
> void modprobe_main(void)
> {
>   struct utsname uts;
>   char **argv = toys.optargs, *procline = NULL;
>   FILE *fs;
>   struct module_s *module;
>   unsigned flags = toys.optflags;
> 
>   dbg = dummy;
>   if (flags & FLAG_v) dbg = xprintf;
> 
>   if ((toys.optc < 1) && (((flags & FLAG_r) && (flags & FLAG_l))
> ||(!((flags & FLAG_r)||(flags & FLAG_l) {
> toys.exithelp++;
> error_exit(" Syntex Error.");
>   }
>   // Check for -r flag without arg if yes then do auto remove.
>   if ((flags & FLAG_r) && (!toys.optc)) {
> if (rm_mod(NULL, O_NONBLOCK | O_EXCL) != 0)   perror_exit("rmmod");
> return;
>   }
> 
>   // change directory to /lib/modules// 
>   xchdir("/lib/modules");
>   uname(&uts);
>   xchdir(uts.release);
> 
>   // modules.dep processing for dependency check.
>   if (flags & FLAG_l) {
> if (depmode_read_entry(to

Re: [Toybox] [New Toy] - modprobe

2013-12-17 Thread ibid . ag
On Tue, Dec 17, 2013 at 04:39:39PM +0530, Ashwini Sharma wrote:
> Hi List,
> 
> An implementation for modprobe is attached.
> go thru the same and let me know your inputs.
> 
> regards,
> Ashwini

For comments see below.
No big issues with style that I can see, except that it should be
default n until Rob's looked over it.
At 575 lines, it's largeish, but it seems reasonable to me...
except perhaps for use of modules.dep:
http://lists.landley.net/pipermail/toybox-landley.net/2013-August/001294.html
http://lists.landley.net/pipermail/toybox-landley.net/2013-August/001297.html


> /* modprobe.c - modprobe utility.
>  *
>  * Copyright 2012 Madhur Verma 
>  * Copyright 2013 Kyungwan Han 
>  *
>  * No Standard.
> 
> USE_MODPROBE(NEWTOY(modprobe, "alrqvsDb", TOYFLAG_SBIN))
> 
> config MODPROBE
>   bool "modprobe"
>   default y
>   help
> usage: modprobe [-alrqvsDb] MODULE [symbol=value][...]
> 
> modprobe utility - inserts modules and dependencies.
> 
> -a  Load multiple MODULEs
> -l  List (MODULE is a pattern)
> -r  Remove MODULE (stacks) or do autoclean
> -q  Quiet
> -v  Verbose
> -s  Log to syslog
> -D  Show dependencies
> -b  Apply blacklist to module names too
> */
> #define FOR_modprobe
> #include "toys.h"
> #include 
> #include 
> 
> GLOBALS(
>   struct arg_list *probes;
>   struct arg_list *dbase[256];
>   char *cmdopts;
>   int nudeps;
>   uint8_t symreq;
> )
> 
> /* Note: if "#define DBASE_SIZE" modified, 
>  * Please update GLOBALS dbase[256] accordingly.
>  */
> #define DBASE_SIZE  256
> #define MODNAME_LEN 256

Any reason not to use sizeof(TT.dbase)?
> 
> // Modules flag definations
> #define MOD_ALOADED   0x0001
> #define MOD_BLACKLIST 0x0002
> #define MOD_FNDDEPMOD 0x0004
> #define MOD_NDDEPS0x0008

I can see using the macros, but I seem to remember Rob mentioning somewhere
before that defining things just before you need them can clarify the
code a little.

That would mean moving them just above config_action().

> static void (*dbg)(char *format, ...);
> // dummy interface for debugging.
> static void dummy(char *format, ...)
> {
> }
> 
> // Current probing modules info
> struct module_s {
>   uint32_t flags;
>   char *cmdname, *name, *depent, *opts;
>   struct arg_list *rnames, *dep;
> };
> 
> // Converts path name FILE to module name.
> static char *path2mod(char *file, char *mod)
> {
>   int i;
>   char *from, *lslash;
> 
>   if (!file) return NULL;
>   if (!mod) mod = xmalloc(MODNAME_LEN);
>   
>   lslash = strrchr(file, '/');
>   if (!lslash || (lslash == file && !lslash[1])) from = file;
>   else from = lslash + 1;

A home-made basename()?

>   for (i = 0; i < (MODNAME_LEN-1) && from[i] && from[i] != '.'; i++)
>   mod[i] = (from[i] == '-') ? '_' : from[i];
>   mod[i] = '\0';
>   return mod;
> }
I presume you are only using this part for display.
modprobe dm_crypt or dm-crypt will load dm-crypt.ko 
modprobe micheal-mic or micheal_mic will load micheal_mic.ko
Whatever you do, either gets displayed with an '_'
 
> // locate character in string.
> static char *strchr_nul(char *s, int c)
> {
>   while(*s != '\0' && *s != c) s++;
>   return (char*)s;
> }

I'm guessing this is because strchrnul is a non-standard glibc
extension?
I don't know about uclibc or newlib (if the latter is relevant),
but musl does include it.
$ nm /opt/musl/lib/libc.a |grep strchrnul
 U __strchrnul
 U __strchrnul
strchrnul.o:
 T __strchrnul
 W strchrnul
 U __strchrnul

> // Add options in opts from toadd.
> static char *add_opts(char *opts, char *toadd)
> {
>   if (toadd) {
> int optlen = 0;
> 
> if (opts) optlen = strlen(opts);
> opts = xrealloc(opts, optlen + strlen(toadd) + 2);
> sprintf(opts + optlen, " %s", toadd);
>   }
>   return opts;
> }
> 
> // Remove first element from the list and return it.
> static void *llist_popme(struct arg_list **head)
> {
>   char *data = NULL;
>   struct arg_list *temp = *head;
> 
>   if (temp) {
> data = temp->arg;
> *head = temp->next;
> free(temp);
>   }
>   return data;
> }
> 
> // Add new node at the beginning of the list.
> static void llist_add(struct arg_list **old, void *data)
> {
>   struct arg_list *new = xmalloc(sizeof(struct arg_list));
> 
>   new->arg = (char*)data;
>   new->next = *old;
>   *old = new;
> }
> 
> // Add new node at tail of list.
> static void llist_add_tail(struct arg_list **head, void *data)
> {
>   while (*head) head = &(*head)->next;
>   *head = xzalloc(sizeof(struct arg_list));
>   (*head)->arg = (char*)data;
> }
> 
> // Reverse list order.
> static struct arg_list *llist_rev(struct arg_list *list)
> {
>   struct arg_list *rev = NULL;
> 
>   while (list) {
> struct arg_list *next = list->next;
> 
> list->next = rev;
> rev = list;
> list = next;
>   }
>   return rev;
> }
> 
> /*
>  * Returns struct module_s from the data base if found, NULL otherwise.
>  * if ps - create module entry, ad

[Toybox] [New Toy] - modprobe

2013-12-17 Thread Ashwini Sharma
Hi List,

An implementation for modprobe is attached.
go thru the same and let me know your inputs.

regards,
Ashwini
/* modprobe.c - modprobe utility.
 *
 * Copyright 2012 Madhur Verma 
 * Copyright 2013 Kyungwan Han 
 *
 * No Standard.

USE_MODPROBE(NEWTOY(modprobe, "alrqvsDb", TOYFLAG_SBIN))

config MODPROBE
  bool "modprobe"
  default y
  help
usage: modprobe [-alrqvsDb] MODULE [symbol=value][...]

modprobe utility - inserts modules and dependencies.

-a  Load multiple MODULEs
-l  List (MODULE is a pattern)
-r  Remove MODULE (stacks) or do autoclean
-q  Quiet
-v  Verbose
-s  Log to syslog
-D  Show dependencies
-b  Apply blacklist to module names too
*/
#define FOR_modprobe
#include "toys.h"
#include 
#include 

GLOBALS(
  struct arg_list *probes;
  struct arg_list *dbase[256];
  char *cmdopts;
  int nudeps;
  uint8_t symreq;
)

/* Note: if "#define DBASE_SIZE" modified, 
 * Please update GLOBALS dbase[256] accordingly.
 */
#define DBASE_SIZE  256
#define MODNAME_LEN 256

// Modules flag definations
#define MOD_ALOADED   0x0001
#define MOD_BLACKLIST 0x0002
#define MOD_FNDDEPMOD 0x0004
#define MOD_NDDEPS0x0008

static void (*dbg)(char *format, ...);
// dummy interface for debugging.
static void dummy(char *format, ...)
{
}

// Current probing modules info
struct module_s {
  uint32_t flags;
  char *cmdname, *name, *depent, *opts;
  struct arg_list *rnames, *dep;
};

// Converts path name FILE to module name.
static char *path2mod(char *file, char *mod)
{
	int i;
	char *from, *lslash;

	if (!file) return NULL;
	if (!mod) mod = xmalloc(MODNAME_LEN);
	
  lslash = strrchr(file, '/');
  if (!lslash || (lslash == file && !lslash[1])) from = file;
  else from = lslash + 1;
  
  for (i = 0; i < (MODNAME_LEN-1) && from[i] && from[i] != '.'; i++)
		mod[i] = (from[i] == '-') ? '_' : from[i];
	mod[i] = '\0';
	return mod;
}

// locate character in string.
static char *strchr_nul(char *s, int c)
{
  while(*s != '\0' && *s != c) s++;
  return (char*)s;
}

// Add options in opts from toadd.
static char *add_opts(char *opts, char *toadd)
{
  if (toadd) {
int optlen = 0;

if (opts) optlen = strlen(opts);
opts = xrealloc(opts, optlen + strlen(toadd) + 2);
sprintf(opts + optlen, " %s", toadd);
  }
  return opts;
}

// Remove first element from the list and return it.
static void *llist_popme(struct arg_list **head)
{
  char *data = NULL;
  struct arg_list *temp = *head;

  if (temp) {
data = temp->arg;
*head = temp->next;
free(temp);
  }
  return data;
}

// Add new node at the beginning of the list.
static void llist_add(struct arg_list **old, void *data)
{
  struct arg_list *new = xmalloc(sizeof(struct arg_list));

  new->arg = (char*)data;
  new->next = *old;
  *old = new;
}

// Add new node at tail of list.
static void llist_add_tail(struct arg_list **head, void *data)
{
  while (*head) head = &(*head)->next;
  *head = xzalloc(sizeof(struct arg_list));
  (*head)->arg = (char*)data;
}

// Reverse list order.
static struct arg_list *llist_rev(struct arg_list *list)
{
  struct arg_list *rev = NULL;

  while (list) {
struct arg_list *next = list->next;

list->next = rev;
rev = list;
list = next;
  }
  return rev;
}

/*
 * Returns struct module_s from the data base if found, NULL otherwise.
 * if ps - create module entry, add it to data base and return the same mod.
 */
static struct module_s *get_mod(char *mod, uint8_t ps)
{
  char name[MODNAME_LEN];
  struct module_s *modentry;
  struct arg_list *temp;
  unsigned i, hash = 0;

  path2mod(mod, name);
  for (i = 0; name[i]; i++) hash = ((hash*31) + hash) + name[i];
  hash %= DBASE_SIZE;
  for (temp = TT.dbase[hash]; temp; temp = temp->next) {
modentry = (struct module_s *) temp->arg;
if (!strcmp(modentry->name, name)) return modentry;
  }
  if (!ps) return NULL;
  modentry = xzalloc(sizeof(*modentry));
  modentry->name = xstrdup(name);
  llist_add(&TT.dbase[hash], modentry);
  return modentry;
}

/*
 * Read a line from file with \ continuation and escape commented line.
 * Return the line in allocated string (*li)
 */
static int read_line(FILE *fl, char **li)
{
  char *nxtline = NULL, *line;
  int len, nxtlen, linelen, nxtlinelen;

  while (1) {
line = NULL;
linelen = nxtlinelen = 0;
len = getline(&line, (size_t*)&linelen, fl);
if (len <= 0) return len;
// checking for commented lines.
if (line[0] != '#') break;
free(line);
  }
  for (;;) {
if (line[len - 1] == '\n') len--;
// checking line continuation.
if (!len || line[len - 1] != '\\') break;
len--;
nxtlen = getline(&nxtline, (size_t*)&nxtlinelen, fl);
if (nxtlen <= 0) break;
if (linelen < len + nxtlen + 1) {
  linelen = len + nxtlen + 1;
  line = xrealloc(line, linelen);
}
memcpy(&line[len], nxtline, nxtlen);
len += nxtlen;
  }
  line[len] = '\0';
  *li = xstrdup(line);
  if (line) free(line);
  if (nxtline) free(nxtline);
  return len;
}

/*
 * Action