home *** CD-ROM | disk | FTP | other *** search
- /* #Specification: /etc/conf.modules / format
- Modules may be located at different place in the filesystem.
- We expect some standard to emerge. We expect that the
- FSSTND will address this in the future.
-
- There will always be some need to override this, especially for
- modules developpers.
-
- The file /etc/conf.modules will contain different definition to
- control the manipulation of the module.
-
- The format will be fairly simple:
-
- parameter=value
- .
- parameter=value
-
- Standard Unix style comments and continuation line are supported.
- Comments begin with a # and continue until the end of the line.
- A line continue on the next one if the last non-white character
- is a \.
- */
- /* #Specification: /etc/conf.modules / format / official name */
- #include <stdio.h>
- #include <assert.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <ctype.h>
- #include <sys/stat.h>
- #include <sys/utsname.h>
- #include <signal.h>
- #include <limits.h>
- #include "link.h"
-
- struct PATH_TYPE{
- char *type;
- char *path;
- };
-
- static PATH_TYPE tb[100];
- static int nb=0;
- static char *depfile=NULL;
- char *optlist[100];
- static int optavail = 0;
- char *aliaslist[100]={
- "char-major-6 lp",
- "binfmt-332 iBCS",
- "iso9660 isofs",
- "slip0 slip",
- "slip1 slip",
- "ppp0 ppp",
- "ppp1 ppp",
- "plip0 plip",
- "plip1 plip",
- "dummy0 dummy",
- };
- int aliasavail = 10;
-
- /*
- Do a popen with error message reporting.
- If quit != 0, the function does not return if an error occur.
-
- Return the FILE *. Must be close with pclose().
- */
- FILE *popen_err (
- const char *cmd,
- const char *mode,
- int quit)
- {
- FILE *ret = popen (cmd,mode);
- if (ret == NULL){
- depmod_error("Can't execute: %s",cmd);
- if (quit) exit(-1);
- }
- return ret;
- }
-
- /*
- Read the configuration file.
- Return -1 if any error. Error messages a generated.
- */
- int config_read ()
- {
- int ret = 0;
- char depfile_tmp[PATH_MAX];
- depfile_tmp[0] = '\0';
-
- /* #Specification: /etc/conf.modules / missing
- This file is optional. No error is printed if it
- is missing. If it is missing the following content
- is assumed.
-
- path[boot]=/lib/modules/boot
- path[fs]=/lib/modules/`uname -r`/fs
- path[misc]=/lib/modules/`uname -r`/misc
- path[net]=/lib/modules/`uname -r`/net
- path[scsi]=/lib/modules/`uname -r`/scsi
-
- path[fs]=/lib/modules/default/fs
- path[misc]=/lib/modules/default/misc
- path[net]=/lib/modules/default/net
- path[scsi]=/lib/modules/default/scsi
-
- path[fs]=/lib/modules/fs
- path[misc]=/lib/modules/misc
- path[net]=/lib/modules/net
- path[scsi]=/lib/modules/scsi
-
- The idea is that modprobe will look first it the
- modules compiled for the current release of the kernel.
- If not found, it will look into the default release.
- And if not found, it will look in the other directory.
-
- The strategy should be like this. When you install a
- new linux, the modules should go in a directory
- related to the release of the kernel you are installing.
- Then you do a symlink default to this directory.
-
- Each time you compile a new kernel, the make modules_install
- will set new directory, but won't change de default.
-
- When you get a module unrelated to the kernel distribution
- you place it in one of the last three directory.
-
- This is the default strategy. Off course you can overide
- this in /etc/conf.modules.
- */
- tb[0].type = strdup_err("boot");
- tb[0].path = strdup_err("/lib/modules/boot");
- nb = 1;
- {
- static char *tbpath[]={
- NULL,
- "/lib/modules/default",
- "/lib/modules"
- };
- struct utsname uts_info;
- uname(&uts_info);
- char firstline[PATH_MAX];
- sprintf (firstline,"/lib/modules/%s",uts_info.release);
- tbpath[0] = firstline;
- for (int i=0; i<sizeof(tbpath)/sizeof(tbpath[0]); i++){
- static char *tbtype[]={"fs","misc","net","scsi"};
- for (int t=0; t<sizeof(tbtype)/sizeof(tbtype[0]); t++){
- char *type = tbtype[t];
- tb[nb].type = strdup_err(type);
- char path[100];
- sprintf (path,"%s/%s",tbpath[i],type);
- tb[nb].path = strdup_err (path);
- nb++;
- }
- }
- }
- FILE *fin = fopen (ETC_CONF_MODULES,"r");
- if (fin != NULL){
- char buf[1000];
- int noline = 0;
- int no_path_so_far = 1;
- while (fgets_strip(buf,sizeof(buf)-1,fin,&noline)!=NULL){
- char *parm = str_skip (buf);
- if (*parm != '\0'){
- int one_err = 1;
- char *pt = parm;
- while (*pt > ' ' && *pt != '=') pt++;
- if (pt > parm){
- if (*pt != '='){
- *pt++ = '\0';
- pt = str_skip (pt);
- }
- if (strcmp(parm,"options")==0){
- optlist[optavail++] = strdup_err(pt);
- one_err = 0;
- }else if (strcmp(parm,"alias")==0){
- // Replace default definitions
- char modname[100];
- sscanf(pt, "%s", modname);
- int len = strlen(modname);
- int i;
- for (i = 0; i < aliasavail; i++) {
- if (strncmp(aliaslist[i], modname, len) == 0
- && isspace(aliaslist[i][len])) {
- aliaslist[i] = strdup_err(pt);
- break;
- }
- }
- if (i == aliasavail)
- aliaslist[aliasavail++] = strdup_err(pt);
- one_err = 0;
- }else if (*pt == '='){
- *pt++ = '\0';
- pt = str_skip (pt);
- if (strcmp(parm,"depfile")==0){
- strcpy (depfile_tmp,pt);
- one_err = 0;
- }else if (strncmp(parm,"path",4)==0){
- /* #Specification: config file / path parameter
- The path parameter specify a directory to
- search for module. This parameter may
- be repeated multiple time.
-
- Optionally the path parameter carries
- a tag. This tells us a little more about
- the purpose of this directory and
- allows some automated operations.
- The tag is sticked to the path word
- enclose in square braket.
- #
- path[boot]=/lib/modules/boot
- #
-
- This identify the path a of directory
- holdding modules loadable a boot time.
-
- Hopefully, insmod will have an option
- to load a list of module using
- such a tag.
-
- If the tag is missing, the word "misc"
- is assumed.
- */
- if (no_path_so_far){
- /* #Specification: config file / path / default
- Whenever there is a path[] specification
- in the config file, all the default
- path are reset.
- */
- no_path_so_far = 0;
- for (int n=1; n<nb; n++){
- free (tb[n].path);
- free (tb[n].type);
- }
- nb = 1;
- }
- assert (nb<sizeof(tb)/sizeof(tb[0]));
- if (parm[4] == '\0'){
- tb[nb].type = strdup_err ("misc");
- tb[nb].path = strdup_err (pt);
- nb++;
- one_err = 0;
- }else if (parm[4] == '['){
- char *pt_type = parm+5;
- while (*pt_type != '\0' && *pt_type != ']'){
- pt_type++;
- }
- if (*pt_type == ']' && pt_type[1] == '\0'){
- *pt_type = '\0';
- tb[nb].type = strdup_err (parm+5);
- tb[nb].path = strdup_err (pt);
- nb++;
- one_err = 0;
- }
- }
- }
- }
- }
- if (one_err){
- depmod_error ("Invalid line %d in " ETC_CONF_MODULES "\n\t%s"
- ,noline,buf);
- ret = -1;
- }
- }
- }
- fclose (fin);
- }
- if (ret != -1){
- if (depfile_tmp[0] == '\0'){
- /* #Specification: config file / depfile parameter
- The default value for the depfile parameter is:
-
- depfile=/lib/modules/`uname -r`/modules.dep
-
- If the config file exist but lack a depfile
- specification, it is used also since the system
- can't work without one.
-
- Once we have the depfile value, we pass to the shell
- with a popen() to resolve whatever shell construct in
- its value. We execute a echo command.
-
- echo read_value
- */
- strcpy (depfile_tmp,"/lib/modules/`uname -r`/modules.dep");
- }
- char cmd[PATH_MAX+10];
- sprintf (cmd,"echo %s",depfile_tmp);
- FILE *fin = popen_err (cmd,"r",0);
- if (fin != NULL){
- if (fgets(depfile_tmp,sizeof(depfile_tmp)-1,fin)!=NULL){
- strip_end (depfile_tmp);
- depfile = strdup_err (depfile_tmp);
- }else{
- ret = -1;
- }
- pclose (fin);
- }
- }
- return ret;
- }
-
- /*
- Add conditionally a file name if it exist
- */
- static int config_add (const char *acc, char *lst[], int &nb)
- {
- int ret = 0;
- if (access(acc, R_OK) == 0) {
- lst[nb++] = strdup_err (acc);
- ret = 1;
- }
- return ret;
- }
-
- /*
- Find out all modules matching the name "match" in directory of type "type"
-
- Return the number of module located and placed in lst[]. The caller
- must free all entry in lst[] itself by doing a tbstr_free(lst,nb);
- */
- int config_lstmod (
- const char *match,
- const char *type, // Type of directory (path[type]), or NULL
- // to match all
- char *lst[],
- int many) // Are we looking for the first match or all
- {
- /* #Specification: reading directory / echo command
- We are using the command echo to locate entries in directories.
- This has the advantage of allowing complex wildcard specification
- in /etc/conf.modules. For example.
-
- path[misc]=/lib/modules/1.1.5?/misc
- */
- char cmd[1000];
- int find_one = 0;
- int ret = 0;
- {
- char *pt = stpcpy (cmd,"echo ");
-
- for (int i=0; i<nb; i++){
- if (type == NULL || strcmp(tb[i].type,type)==0){
- char acc[PATH_MAX];
- sprintf(acc, "%s/%s", tb[i].path, match);
- pt = stpcpy (pt,acc);
- if (!many && strpbrk(acc, SHELL_WILD)==NULL) {
- if (config_add (acc,lst,ret)) return 1;
- }
-
- *pt++ = ' ';
- find_one = 1;
- }
- }
- *pt = '\0';
- }
- if (find_one){
- int fd2 = dup(2);
- if (fd2 == -1){
- depmod_error ("Out of file handle");
- }else{
- close (2);
- FILE *fin = popen_err (cmd,"r",1);
- if (fin != NULL){
- char acc[PATH_MAX];
- char *pt = acc;
- int carac;
- while ((carac = fgetc(fin))!=EOF){
- if (!isspace (carac)){
- *pt++ = carac;
- }else if (pt > acc){
- *pt = '\0';
- config_add (acc,lst,ret);
- pt = acc;
- }
- }
- if (pt > acc){
- *pt = '\0';
- config_add (acc,lst,ret);
- }
- pclose (fin);
- }
- dup2(fd2,2);
- close (fd2);
- }
- }
- return ret;
- }
-
- /*
- Return the path of the depandancy file to produce
- */
- const char *config_getdepfile()
- {
- return depfile;
- }
-
- /*
- Print out all the configuration in use
- */
- void config_show ()
- {
- PATH_TYPE *pttb = tb;
- for (int i=0; i<nb; i++, pttb++){
- if (pttb->type != NULL){
- printf ("path[%s]=%s\n",pttb->type,pttb->path);
- }else{
- printf ("path=%s\n",pttb->path);
- }
- }
- puts ("# Aliases");
- for (i=0; i<aliasavail; i++) printf ("alias %s\n",aliaslist[i]);
- puts ("# Options");
- for (i=0; i<optavail; i++) printf ("options %s\n",optlist[i]);
- }
-
- #ifdef TEST
-
- int main (int argc, char *argv[])
- {
- if (argc != 3){
- depmod_error ("type and match");
- }else if (config_read() == -1){
- depmod_error ("Can't read configuration file");
- }else{
- char *lst[1000];
- int nb = config_lstmod (argv[1],argv[2],lst);
- for (int i=0; i<nb; i++){
- printf ("\t%s\n",lst[i]);
- }
- tbstr_free (lst,nb);
- }
- return 0;
- }
-
- #endif
-
-
-