C   23

cc

Guest on 21st September 2022 01:41:02 PM

  1. include <sys/param.h>
  2.  
  3. #include <ctype.h>
  4. #include <err.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9.  
  10. #define NELEMS(a) (sizeof(a) / sizeof(a[0]))
  11.  
  12. static const char *
  13. parse_config(const char *conffile, const char *cctype)
  14. {
  15.         FILE *conf;
  16.         char *line = NULL;
  17.         size_t linecap = 0;
  18.         ssize_t linelen;
  19.         char *walk, *value;
  20.         int confline = 0;
  21.         char ccpathbuf[MAXPATHLEN];
  22.         const char *ccpath = NULL;
  23.        
  24.         if ((conf = fopen(conffile, "r")) == NULL)
  25.                 return (NULL);
  26.  
  27.         while ((linelen = getline(&line, &linecap, conf)) > 0) {
  28.                 confline++;
  29.                 walk = line;
  30.                 walk += strspn(walk, " \t\n\r");
  31.                 if (*walk == '\0')
  32.                         continue;
  33.                 /* consider # as a comment line */
  34.                 if (*walk == '#')
  35.                         continue;
  36.  
  37.                 value = strchr(walk, '=');
  38.                 if (value == NULL)
  39.                         value = strchr(walk, ':');
  40.                 if (value == NULL)
  41.                         errx(1, "Malformed line in the configuration file: %s line: %d",
  42.                             conffile, confline);
  43.  
  44.                 *value = '\0';
  45.                 value++;
  46.  
  47.                 /* ignore lines not concernant if cctype we are looking for */
  48.                 if (strncmp(walk, cctype, strlen(cctype)) != 0)
  49.                         continue;
  50.                 walk += strlen(cctype);
  51.  
  52.                 /*
  53.                  * allow space and tabs after the key, if anything else if found, then
  54.                  * skip the line we consider the key not to be our cctype
  55.                  */
  56.                 if (strspn(walk, " \t") != strlen(walk))
  57.                         continue;
  58.  
  59.                 value += strspn(value, " \t");
  60.                 if (*value == '\0' || *value == '\n')
  61.                         errx(1, "Invalid value for %s, line %d in the configuration file %s",
  62.                             cctype, confline, conffile);
  63.  
  64.                 /* trim space an the end of the value */
  65.                 walk = value + strlen(value) - 1;
  66.                 while (walk > value && isspace(*walk)) {
  67.                         *walk = '\0';
  68.                         walk--;
  69.                 }
  70.                 strlcpy(ccpathbuf, value, MAXPATHLEN);
  71.                 ccpath = ccpathbuf;
  72.                 break;
  73.         }
  74.  
  75.         free(line);
  76.         fclose(conf);
  77.         return (ccpath);
  78. }
  79.  
  80. static const char *
  81. get_cc_from_config(const char *cctype)
  82. {
  83.         char confpath[MAXPATHLEN];
  84.         unsigned int i;
  85.         const char *confpaths[] = {
  86.                 NULL,
  87.                 NULL,
  88.                 "/etc/compiler.conf",
  89.                 "/etc/defaults/compiler.conf",
  90.         };
  91.         const char *ccpath;
  92.         const char *localbase;
  93.  
  94.         /*
  95.          * In order we first try to get the configuration from
  96.          * LOCALBASE/etc/compiler.conf then from /etc/compiler.conf
  97.          * only then we try to fallback on /etc/defaults/compiler.conf
  98.          */
  99.  
  100.         localbase = getenv("LOCALBASE");
  101.         if (localbase == NULL)
  102.                 localbase = "/usr/local";
  103.         snprintf(confpath, MAXPATHLEN, "%s/etc/compiler.conf", localbase);
  104.         confpaths[1] = getenv("COMPILER_CONF");
  105.         confpaths[0] = confpath;
  106.         for (i = 0; i < NELEMS(confpaths); i++) {
  107.                 if (confpaths[i] == NULL)
  108.                         continue;
  109.                 ccpath = parse_config(confpaths[i], cctype);
  110.                 if (ccpath != NULL)
  111.                         return (ccpath);
  112.         }
  113.  
  114.         return (NULL);
  115. }
  116.  
  117. int
  118. main(int argc __unused, char *argv[])
  119. {
  120.         const char *ccpath = NULL;
  121.         const char *cctype = NULL;
  122.         const char *progname = getprogname();
  123.  
  124.         if (strcmp(progname, "cc") == 0) {
  125.                 cctype = "CC";
  126.         } else if (strcmp(progname, "cpp") == 0) {
  127.                 cctype = "CPP";
  128.         } else if (strcmp(progname, "c++") == 0) {
  129.                 cctype = "CXX";
  130.         } else {
  131.                 errx(1, "Invalid progname, this can only be used as cc, c++ or cpp");
  132.         }
  133.         ccpath = get_cc_from_config(cctype);
  134.         if (ccpath == NULL)
  135.                 errx(1, "Unable to determine the value of %s", getprogname());
  136.  
  137.         execvp(ccpath, argv);
  138.         err(1, "%s", ccpath);
  139. }

Raw Paste


Login or Register to edit or fork this paste. It's free.