home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / a / bin / modules-.2 / modules- / modules-1.2.8 / depmod / config.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-31  |  10.5 KB  |  437 lines

  1. /* #Specification: /etc/conf.modules / format
  2.     Modules may be located at different place in the filesystem.
  3.     We expect some standard to emerge. We expect that the
  4.     FSSTND will address this in the future.
  5.  
  6.     There will always be some need to override this, especially for
  7.     modules developpers.
  8.  
  9.     The file /etc/conf.modules will contain different definition to
  10.     control the manipulation of the module.
  11.  
  12.     The format will be fairly simple:
  13.  
  14.     parameter=value
  15.     .
  16.     parameter=value
  17.  
  18.     Standard Unix style comments and continuation line are supported.
  19.     Comments begin with a # and continue until the end of the line.
  20.     A line continue on the next one if the last non-white character
  21.     is a \.
  22. */
  23. /* #Specification: /etc/conf.modules / format / official name */
  24. #include <stdio.h>
  25. #include <assert.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29. #include <ctype.h>
  30. #include <sys/stat.h>
  31. #include <sys/utsname.h>
  32. #include <signal.h>
  33. #include <limits.h>
  34. #include "link.h"
  35.  
  36. struct PATH_TYPE{
  37.     char *type;
  38.     char *path;
  39. };
  40.  
  41. static PATH_TYPE tb[100];
  42. static int nb=0;
  43. static char *depfile=NULL;
  44. char *optlist[100];
  45. static int optavail = 0;
  46. char *aliaslist[100]={
  47.     "char-major-6 lp",
  48.     "binfmt-332 iBCS",
  49.     "iso9660 isofs",
  50.     "slip0 slip",
  51.     "slip1 slip",
  52.     "ppp0 ppp",
  53.     "ppp1 ppp",
  54.     "plip0 plip",
  55.     "plip1 plip",
  56.     "dummy0 dummy",
  57. };
  58. int aliasavail = 10;
  59.  
  60. /*
  61.     Do a popen with error message reporting.
  62.     If quit != 0, the function does not return if an error occur.
  63.  
  64.     Return the FILE *. Must be close with pclose().
  65. */
  66. FILE *popen_err (
  67.     const char *cmd,
  68.     const char *mode,
  69.     int quit)
  70. {
  71.     FILE *ret = popen (cmd,mode);
  72.     if (ret == NULL){
  73.         depmod_error("Can't execute: %s",cmd);
  74.         if (quit) exit(-1);
  75.     }
  76.     return ret;
  77. }
  78.  
  79. /*
  80.     Read the configuration file.
  81.     Return -1 if any error. Error messages a generated.
  82. */
  83. int config_read ()
  84. {
  85.     int ret = 0;
  86.     char depfile_tmp[PATH_MAX];
  87.     depfile_tmp[0] = '\0';
  88.  
  89.     /* #Specification: /etc/conf.modules / missing
  90.         This file is optional. No error is printed if it
  91.         is missing. If it is missing the following content
  92.         is assumed.
  93.  
  94.         path[boot]=/lib/modules/boot
  95.         path[fs]=/lib/modules/`uname -r`/fs
  96.         path[misc]=/lib/modules/`uname -r`/misc
  97.         path[net]=/lib/modules/`uname -r`/net
  98.         path[scsi]=/lib/modules/`uname -r`/scsi
  99.  
  100.         path[fs]=/lib/modules/default/fs
  101.         path[misc]=/lib/modules/default/misc
  102.         path[net]=/lib/modules/default/net
  103.         path[scsi]=/lib/modules/default/scsi
  104.     
  105.         path[fs]=/lib/modules/fs
  106.         path[misc]=/lib/modules/misc
  107.         path[net]=/lib/modules/net
  108.         path[scsi]=/lib/modules/scsi
  109.         
  110.         The idea is that modprobe will look first it the
  111.         modules compiled for the current release of the kernel.
  112.         If not found, it will look into the default release.
  113.         And if not found, it will look in the other directory.
  114.         
  115.         The strategy should be like this. When you install a
  116.         new linux, the modules should go in a directory
  117.         related to the release of the kernel you are installing.
  118.         Then you do a symlink default to this directory.
  119.         
  120.         Each time you compile a new kernel, the make modules_install
  121.         will set new directory, but won't change de default.
  122.  
  123.         When you get a module unrelated to the kernel distribution
  124.         you place it in one of the last three directory.
  125.         
  126.         This is the default strategy. Off course you can overide
  127.         this in /etc/conf.modules.
  128.     */
  129.     tb[0].type = strdup_err("boot");
  130.     tb[0].path = strdup_err("/lib/modules/boot");
  131.     nb = 1;
  132.     {
  133.         static char *tbpath[]={
  134.             NULL,
  135.             "/lib/modules/default",
  136.             "/lib/modules"
  137.         };
  138.         struct utsname uts_info;
  139.         uname(&uts_info);
  140.         char firstline[PATH_MAX];
  141.         sprintf (firstline,"/lib/modules/%s",uts_info.release);
  142.         tbpath[0] = firstline;
  143.         for (int i=0; i<sizeof(tbpath)/sizeof(tbpath[0]); i++){
  144.             static char *tbtype[]={"fs","misc","net","scsi"};
  145.             for (int t=0; t<sizeof(tbtype)/sizeof(tbtype[0]); t++){
  146.                 char *type = tbtype[t];
  147.                 tb[nb].type = strdup_err(type);
  148.                 char path[100];
  149.                 sprintf (path,"%s/%s",tbpath[i],type);
  150.                 tb[nb].path = strdup_err (path);
  151.                 nb++;
  152.             }
  153.         }
  154.     }
  155.     FILE *fin = fopen (ETC_CONF_MODULES,"r");
  156.     if (fin != NULL){
  157.         char buf[1000];
  158.         int noline = 0;
  159.         int no_path_so_far = 1;
  160.         while (fgets_strip(buf,sizeof(buf)-1,fin,&noline)!=NULL){
  161.             char *parm = str_skip (buf);
  162.             if (*parm != '\0'){
  163.                 int one_err = 1;
  164.                 char *pt = parm;
  165.                 while (*pt > ' ' && *pt != '=') pt++;
  166.                 if (pt > parm){
  167.                     if (*pt != '='){
  168.                         *pt++ = '\0';
  169.                         pt = str_skip (pt);
  170.                     }
  171.                     if (strcmp(parm,"options")==0){
  172.                         optlist[optavail++] = strdup_err(pt);
  173.                         one_err = 0;
  174.                     }else if (strcmp(parm,"alias")==0){
  175.                         // Replace default definitions
  176.                         char modname[100];
  177.                         sscanf(pt, "%s", modname);
  178.                         int len = strlen(modname);
  179.                         int i;
  180.                         for (i = 0; i < aliasavail; i++) {
  181.                             if (strncmp(aliaslist[i], modname, len) == 0
  182.                                 && isspace(aliaslist[i][len])) {
  183.                                 aliaslist[i] = strdup_err(pt);
  184.                                 break;
  185.                             }
  186.                         }
  187.                         if (i == aliasavail)
  188.                             aliaslist[aliasavail++] = strdup_err(pt);
  189.                         one_err = 0;
  190.                     }else if (*pt == '='){
  191.                         *pt++ = '\0';
  192.                         pt = str_skip (pt);
  193.                         if (strcmp(parm,"depfile")==0){
  194.                             strcpy (depfile_tmp,pt);
  195.                             one_err = 0;
  196.                         }else if (strncmp(parm,"path",4)==0){
  197.                             /* #Specification: config file / path parameter
  198.                                 The path parameter specify a directory to
  199.                                 search for module. This parameter may
  200.                                 be repeated multiple time.
  201.  
  202.                                 Optionally the path parameter carries
  203.                                 a tag. This tells us a little more about
  204.                                 the purpose of this directory and
  205.                                 allows some automated operations.
  206.                                 The tag is sticked to the path word
  207.                                 enclose in square braket.
  208.                                 #
  209.                                 path[boot]=/lib/modules/boot
  210.                                 #
  211.  
  212.                                 This identify the path a of directory
  213.                                 holdding modules loadable a boot time.
  214.  
  215.                                 Hopefully, insmod will have an option
  216.                                 to load a list of module using
  217.                                 such a tag.
  218.  
  219.                                 If the tag is missing, the word "misc"
  220.                                 is assumed.
  221.                             */
  222.                             if (no_path_so_far){
  223.                                 /*    #Specification: config file / path / default
  224.                                     Whenever there is a path[] specification
  225.                                     in the config file, all the default
  226.                                     path are reset.    
  227.                                 */
  228.                                 no_path_so_far = 0;
  229.                                 for (int n=1; n<nb; n++){
  230.                                     free (tb[n].path);
  231.                                     free (tb[n].type);
  232.                                 }
  233.                                 nb = 1;
  234.                             }
  235.                             assert (nb<sizeof(tb)/sizeof(tb[0]));    
  236.                             if (parm[4] == '\0'){
  237.                                 tb[nb].type = strdup_err ("misc");
  238.                                 tb[nb].path = strdup_err (pt);
  239.                                 nb++;
  240.                                 one_err = 0;
  241.                             }else if (parm[4] == '['){
  242.                                 char *pt_type = parm+5;
  243.                                 while (*pt_type != '\0' && *pt_type != ']'){
  244.                                     pt_type++;
  245.                                 }
  246.                                 if (*pt_type == ']' && pt_type[1] == '\0'){
  247.                                     *pt_type = '\0';        
  248.                                     tb[nb].type = strdup_err (parm+5);
  249.                                     tb[nb].path = strdup_err (pt);
  250.                                     nb++;
  251.                                     one_err = 0;
  252.                                 }
  253.                             }
  254.                         }
  255.                     }
  256.                 }
  257.                 if (one_err){
  258.                     depmod_error ("Invalid line %d in " ETC_CONF_MODULES "\n\t%s"
  259.                         ,noline,buf);
  260.                     ret = -1;
  261.                 }
  262.             }
  263.         }
  264.         fclose (fin);
  265.     }
  266.     if (ret != -1){
  267.         if (depfile_tmp[0] == '\0'){
  268.             /* #Specification: config file / depfile parameter
  269.                 The default value for the depfile parameter is:
  270.  
  271.                 depfile=/lib/modules/`uname -r`/modules.dep
  272.  
  273.                 If the config file exist but lack a depfile
  274.                 specification, it is used also since the system
  275.                 can't work without one.
  276.  
  277.                 Once we have the depfile value, we pass to the shell
  278.                 with a popen() to resolve whatever shell construct in
  279.                 its value. We execute a echo command.
  280.  
  281.                 echo read_value
  282.             */
  283.             strcpy (depfile_tmp,"/lib/modules/`uname -r`/modules.dep");
  284.         }
  285.         char cmd[PATH_MAX+10];
  286.         sprintf (cmd,"echo %s",depfile_tmp);
  287.         FILE *fin = popen_err (cmd,"r",0);
  288.         if (fin != NULL){
  289.             if (fgets(depfile_tmp,sizeof(depfile_tmp)-1,fin)!=NULL){
  290.                 strip_end (depfile_tmp);
  291.                 depfile = strdup_err (depfile_tmp);
  292.             }else{
  293.                 ret = -1;
  294.             }
  295.             pclose (fin);
  296.         }
  297.     }
  298.     return ret;
  299. }
  300.  
  301. /*
  302.     Add conditionally a file name if it exist
  303. */
  304. static int config_add (const char *acc, char *lst[], int &nb)
  305. {
  306.     int ret = 0;
  307.     if (access(acc, R_OK) == 0) {
  308.         lst[nb++] = strdup_err (acc);
  309.         ret = 1;
  310.     }
  311.     return ret;
  312. }
  313.  
  314. /*
  315.     Find out all modules matching the name "match" in directory of type "type"
  316.  
  317.     Return the number of module located and placed in lst[]. The caller
  318.     must free all entry in lst[] itself by doing a tbstr_free(lst,nb);
  319. */
  320. int config_lstmod (
  321.     const char *match,
  322.     const char *type,        // Type of directory (path[type]), or NULL
  323.                             // to match all
  324.     char *lst[],
  325.     int many)            // Are we looking for the first match or all
  326. {
  327.     /* #Specification: reading directory / echo command
  328.         We are using the command echo to locate entries in directories.
  329.         This has the advantage of allowing complex wildcard specification
  330.         in /etc/conf.modules. For example.
  331.  
  332.         path[misc]=/lib/modules/1.1.5?/misc
  333.     */
  334.     char cmd[1000];
  335.     int find_one = 0;
  336.     int ret = 0;
  337.     {
  338.         char *pt = stpcpy (cmd,"echo ");
  339.  
  340.         for (int i=0; i<nb; i++){
  341.             if (type == NULL || strcmp(tb[i].type,type)==0){
  342.                 char acc[PATH_MAX];
  343.                 sprintf(acc, "%s/%s", tb[i].path, match);
  344.                 pt = stpcpy (pt,acc);
  345.                 if (!many && strpbrk(acc, SHELL_WILD)==NULL) {
  346.                     if (config_add (acc,lst,ret)) return 1;
  347.                 }
  348.  
  349.                 *pt++ = ' ';
  350.                 find_one = 1;
  351.             }
  352.         }
  353.         *pt = '\0';
  354.     }
  355.     if (find_one){
  356.         int fd2 = dup(2);
  357.         if (fd2 == -1){
  358.             depmod_error ("Out of file handle");
  359.         }else{
  360.             close (2);
  361.             FILE *fin = popen_err (cmd,"r",1);
  362.             if (fin != NULL){
  363.                 char acc[PATH_MAX];
  364.                 char *pt = acc;
  365.                 int carac;
  366.                 while ((carac = fgetc(fin))!=EOF){
  367.                     if (!isspace (carac)){
  368.                         *pt++ = carac;
  369.                     }else if (pt > acc){
  370.                         *pt = '\0';
  371.                         config_add (acc,lst,ret);
  372.                         pt = acc;
  373.                     }
  374.                 }
  375.                 if (pt > acc){
  376.                     *pt = '\0';
  377.                     config_add (acc,lst,ret);
  378.                 }
  379.                 pclose (fin);
  380.             }
  381.             dup2(fd2,2);
  382.             close (fd2);
  383.         }
  384.     }
  385.     return ret;
  386. }
  387.  
  388. /*
  389.     Return the path of the depandancy file to produce
  390. */
  391. const char *config_getdepfile()
  392. {
  393.     return depfile;
  394. }
  395.  
  396. /*
  397.     Print out all the configuration in use
  398. */
  399. void config_show ()
  400. {
  401.     PATH_TYPE *pttb = tb;
  402.     for (int i=0; i<nb; i++, pttb++){
  403.         if (pttb->type != NULL){
  404.             printf ("path[%s]=%s\n",pttb->type,pttb->path);
  405.         }else{
  406.             printf ("path=%s\n",pttb->path);
  407.         }
  408.     }
  409.     puts ("# Aliases");
  410.     for (i=0; i<aliasavail; i++) printf ("alias %s\n",aliaslist[i]);
  411.     puts ("# Options");
  412.     for (i=0; i<optavail; i++) printf ("options %s\n",optlist[i]);
  413. }
  414.  
  415. #ifdef TEST
  416.  
  417. int main (int argc, char *argv[])
  418. {
  419.     if (argc != 3){
  420.         depmod_error ("type and match");
  421.     }else if (config_read() == -1){
  422.         depmod_error ("Can't read configuration file");
  423.     }else{
  424.         char *lst[1000];
  425.         int nb = config_lstmod (argv[1],argv[2],lst);
  426.         for (int i=0; i<nb; i++){
  427.             printf ("\t%s\n",lst[i]);
  428.         }
  429.         tbstr_free (lst,nb);
  430.     }
  431.     return 0;
  432. }
  433.  
  434. #endif
  435.  
  436.  
  437.