Logo Search packages:      
Sourcecode: dctrl-tools version File versions

rc.c

/*   grep-dctrl - grep Debian control files
     Copyright  1999, 2003, 2004  Antti-Juhani Kaijanaho

     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program; see the file COPYING.  If not, write to
     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     Boston, MA 02111-1307, USA.

*/

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "msg.h"
#include "fnutil.h"
#include "getaline.h"
#include "rc.h"
#include "strutil.h"
#include "util.h"

char const * const ifile_modes[] = { [m_error] = "m_error",
                             [m_read]  = "m_read",
                             [m_exec]  = "m_exec" };

static struct ifile parse(char * s)
{
      assert(s != 0);
      s = (char*)left_trimmed(s);
      trim_right(s);
      if (*s == 0) return (struct ifile) { .mode = m_read, .s = "-" };
      static const char at_exec[] = "@exec ";
      if (s[0] != '@') return (struct ifile){ .mode = m_read, .s = s };
      assert(s[0] == '@');
      if (s[1] == '@') return (struct ifile){ .mode = m_read, .s = s+1 };
      if (strncmp(s, at_exec, sizeof at_exec - 1) == 0) {
            return (struct ifile){ .mode = m_exec,
                               .s = s + sizeof at_exec - 1 };
      }
      debug_message(s, 0);
      message(L_IMPORTANT, _("Malformed default input file name"), 0);
      return (struct ifile){ .mode = m_error, .s = 0 };
}

static bool perms_ok(char const * fname, int fd)
{
      struct stat stat;
      int r = fstat(fd, &stat);
      if (r == -1) {
            errno_msg(L_IMPORTANT, fname);
            return false;
      }
      if (stat.st_uid != 0 && stat.st_uid != getuid()) {
            message(L_IMPORTANT, _("not owned by you or root, ignoring"),
                  fname);
            return false;
      }
      if ((stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
            message(L_IMPORTANT, _("write permissions for "
                               "group or others, ignoring"),
                  fname);
            return false;
      }
      return true;
}

struct ifile find_ifile_by_exename(const char * exename, const char * rcfname)
{
      static const char * default_rcfiles [] = {
            /* Order is significant: earlier files override later ones. */
            "~/.grep-dctrlrc",
            SYSCONF "/grep-dctrl.rc",
            0 };
      int i;
      char * fname;
      int lineno;
      FILE * f;

      assert(exename != 0);

      if (rcfname == 0) {
            struct ifile rv = { .mode = m_error, .s = 0 };
            for (i = 0;
                 rv.mode == m_error && default_rcfiles [i] != 0;
                 i++) {
                  rv = find_ifile_by_exename(exename, default_rcfiles [i]);
            }
            return rv;
      }

      assert(rcfname != 0);

      fname = fnqualify(rcfname);
      if (fname == 0) {
            errno_msg(L_IMPORTANT, rcfname);
            return (struct ifile){ .mode = m_error, .s = 0 };
      }

      message(L_INFORMATIONAL, _("reading config file"), fname);

      f = fopen(fname, "r");
      if (f == 0) {
            message(L_INFORMATIONAL, strerror(errno), fname);
            return (struct ifile){ .mode = m_error, .s = 0 };
      }

      // check permissions
      if (!perms_ok(fname, fileno(f))) {
            return (struct ifile){ .mode = m_error, .s = 0 };
      }

      lineno = 0;
      char * rv = 0;
      while (1) {
            static char * line = 0;
            char * line_exe;
            char * line_ifile;

            /* If this is not the first call, line may be non-null
               and must be freed.  It must be freed on all
               non-first iterations, too. */
            free(line);

            line = getaline (f);
            if (line == 0) {
                  message(L_FATAL, _("read failure or out of memory"),
                        fname);
                  fail();
            }

            ++lineno;

            if (*line == 0) {
                  rv = 0;
                  break;
            }

            chop_comment(line, '#');
            chomp(line);

            if (left_trimmed(line) [0] == 0) {
                  continue;
            }

            line_exe = strtok(line, " \t");
            if (line_exe == 0) {
                  line_message(L_IMPORTANT,
                             _("syntax error: need a executable name"),
                             fname, lineno);
                  continue;
            }

            line_ifile = strtok(0, "\n\t");
            if (line_ifile == 0) {
                  line_message(L_IMPORTANT,
                             _("syntax error: need an input file name"),
                             fname, lineno);
                  continue;
            }

            message(L_INFORMATIONAL, _("considering executable name"), line_exe);
            if (strcmp (exename, line_exe) == 0) {
                  message(L_INFORMATIONAL, _("yes, will use executable name"), line_exe);
                  rv = line_ifile;
                  message(L_INFORMATIONAL, _("default input file"), rv);
                  break;
            }
      }

      fclose(f);
      free(fname);

      if (rv != 0) {
            return parse(rv);
      } else {
            message(L_IMPORTANT, _("executable name not found; "
                               "reading from standard input"), 0);
            return (struct ifile) { .mode = m_read, .s = "-" };
      }
}


Generated by  Doxygen 1.6.0   Back to index