nis-util  1.0.D108
lib/space/netgroup.cc
Go to the documentation of this file.
00001 //
00002 // nis-util - NIS Administration Utilities
00003 // Copyright (C) 2001, 2002, 2008, 2009, 2011, 2012 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or (at
00008 // your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program. If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <lib/ac/ctype.h>
00020 
00021 #include <lib/colon/passwd.h>
00022 #include <lib/rcstring/accumulator.h>
00023 #include <lib/space/hosts.h>
00024 #include <lib/space/netgroup.h>
00025 #include <lib/rcstring/accumulator.h>
00026 
00027 
00028 space_netgroup::~space_netgroup()
00029 {
00030 }
00031 
00032 
00033 space_netgroup::space_netgroup(const rcstring &a_filename) :
00034     space(a_filename)
00035 {
00036     discard_comments();
00037     discard_blank_lines();
00038     discard_backslash_newline();
00039 }
00040 
00041 
00042 space_netgroup::pointer
00043 space_netgroup::create(const rcstring &a_filename)
00044 {
00045     return pointer(new space_netgroup(a_filename));
00046 }
00047 
00048 
00049 rcstring
00050 space_netgroup::is_ok_netgroup_name(const rcstring &s)
00051 {
00052     //
00053     // Characters you can't have in a netgroup name
00054     //  - You cant have comma "," or "(" parens ")" because they
00055     //    are separators in the netgroups file.
00056     //  - You can't have space or tab, because they are used as
00057     //    field separators in many files.
00058     //  - You can't have '#' because that looks like a comment
00059     //    in may files.
00060     //  - The name must start with a letter, so that it looks
00061     //    like a word and not a number or a symbol (many parsers
00062     //    need this).  In general, the more like a C identifier it
00063     //    looks, the more programs will be able to cope with it.
00064     //
00065     // The rest of the characters rejected here are just to make
00066     // sure it looks reasonable (as well as making sure the characters
00067     // are printable).
00068     //
00069     if (s.empty())
00070         return rcstring("_");
00071 
00072     rcstring_accumulator acc;
00073     unsigned char c = s.c_str()[0];
00074     if (!isalpha(c))
00075         c = '_';
00076     acc.push_back(c);
00077     for (const char *cp = s.c_str() + 1; *cp; ++cp)
00078     {
00079         c = *cp;
00080         if (!isdigit(c) && !isalpha(c) && c != '-' && c != '_')
00081             c = '_';
00082         acc.push_back(c);
00083     }
00084     return acc.mkstr();
00085 }
00086 
00087 
00088 bool
00089 space_netgroup::parse_group(const rcstring &s, entry_t &result,
00090     const source_location &glocn)
00091 {
00092     const char *cp = s.c_str();
00093     if (*cp != '(')
00094         return false;
00095     ++cp;
00096 
00097     const char *host_begin = cp;
00098     while (*cp != ',')
00099     {
00100         if (!*cp)
00101             return false;
00102         ++cp;
00103     }
00104     const char *host_end = cp;
00105     ++cp;
00106 
00107     const char *user_begin = cp;
00108     while (*cp != ',')
00109     {
00110         if (!*cp)
00111             return false;
00112         ++cp;
00113     }
00114     const char *user_end = cp;
00115     ++cp;
00116 
00117     const char *domain_begin = cp;
00118     while (*cp != ')')
00119     {
00120         if (!*cp)
00121             return false;
00122         ++cp;
00123     }
00124     const char *domain_end = cp;
00125     ++cp;
00126 
00127     if (*cp)
00128         return false;
00129 
00130     rcstring ss = rcstring(user_begin, user_end - user_begin);
00131     if (ss == rcstring("-") || ss.empty())
00132         result.user = ss;
00133     else
00134     {
00135         result.user = colon_passwd::is_ok_user_name(ss);
00136         if (result.user != ss)
00137         {
00138             error
00139             (
00140                 glocn,
00141                 "user name %s is not valid, suggest %s instead",
00142                 ss.quote_c().c_str(),
00143                 result.user.quote_c().c_str()
00144             );
00145         }
00146     }
00147 
00148     ss = rcstring(host_begin, host_end - host_begin);
00149     if (ss == "-" || ss.empty())
00150         result.host = ss;
00151     else
00152     {
00153         rcstring other;
00154         if (!space_hosts::valid_host_name(ss, other))
00155         {
00156             error
00157             (
00158                 glocn,
00159                 "host name %s is not valid, suggest %s instead",
00160                 ss.quote_c().c_str(),
00161                 other.quote_c().c_str()
00162             );
00163             ss = other;
00164         }
00165         result.host = ss;
00166     }
00167 
00168     ss = rcstring(domain_begin, domain_end - domain_begin);
00169     if (ss == "-" || ss.empty())
00170         result.domain = ss;
00171     else
00172         error(glocn, "don't use the domain field, it is meaningless");
00173 
00174     return true;
00175 }
00176 
00177 
00178 space_netgroup::record::pointer
00179 space_netgroup::get(void)
00180 {
00181     source_location line_locn;
00182     line_t line;
00183     if (!read_one_line(line_locn, line))
00184         return record::pointer();
00185 
00186     rcstring name = is_ok_netgroup_name(line[0]);
00187     if (name != line[0])
00188     {
00189         error
00190         (
00191             line_locn,
00192             "the string %s is not a valid netgroup name, suggest %s instead",
00193             line[1].quote_c().c_str(),
00194             name.quote_c().c_str()
00195         );
00196     }
00197 
00198     record::members_t members;
00199     for (line_t::iterator it = line.begin() + 1; it != line.end(); ++it)
00200     {
00201         entry_t entry;
00202         if (!parse_group(*it, entry, line_locn))
00203         {
00204             entry.reference_to_netgroup = is_ok_netgroup_name(*it);
00205             if (entry.reference_to_netgroup != *it)
00206             {
00207                 error
00208                 (
00209                     line_locn,
00210                     "the string %s is not a valid netgroup name, "
00211                         "suggest %s instead",
00212                     it->quote_c().c_str(),
00213                     entry.reference_to_netgroup.quote_c().c_str()
00214                 );
00215             }
00216         }
00217         members.push_back(entry);
00218     }
00219     return record::create(line_locn, name, members);
00220 }
00221 
00222 
00223 bool
00224 space_netgroup::entry_t::user_any(void)
00225     const
00226 {
00227     return (user.empty());
00228 }
00229 
00230 
00231 bool
00232 space_netgroup::entry_t::user_ignore(void)
00233     const
00234 {
00235     return (user == "-");
00236 }
00237 
00238 
00239 bool
00240 space_netgroup::entry_t::user_indexing(void)
00241     const
00242 {
00243     if (!reference_to_netgroup.empty())
00244         return false;
00245     return !user_ignore();
00246 }
00247 
00248 
00249 bool
00250 space_netgroup::entry_t::host_any(void)
00251     const
00252 {
00253     return (host.empty());
00254 }
00255 
00256 
00257 bool
00258 space_netgroup::entry_t::host_ignore(void)
00259     const
00260 {
00261     return (host == "-");
00262 }
00263 
00264 
00265 bool
00266 space_netgroup::entry_t::host_indexing(void)
00267     const
00268 {
00269     if (!reference_to_netgroup.empty())
00270         return false;
00271     return !host_ignore();
00272 }
00273 
00274 
00275 rcstring
00276 space_netgroup::entry_t::representation(void)
00277 const
00278 {
00279     if (!reference_to_netgroup.empty())
00280         return reference_to_netgroup;
00281     rcstring_accumulator acc;
00282     acc.push_back('(');
00283     acc.push_back(host);
00284     acc.push_back(',');
00285     acc.push_back(user);
00286     acc.push_back(',');
00287     acc.push_back(domain);
00288     acc.push_back(')');
00289     return acc.mkstr();
00290 }
00291 
00292 
00293 space_netgroup::record::~record()
00294 {
00295 }
00296 
00297 
00298 space_netgroup::record::record(
00299     const source_location &a_locn,
00300     const rcstring &a_name,
00301     const members_t &a_members
00302 ) :
00303     locn(a_locn),
00304     name(a_name),
00305     members(a_members)
00306 {
00307 }
00308 
00309 
00310 space_netgroup::record::pointer
00311 space_netgroup::record::create(const source_location &a_locn,
00312     const rcstring &a_name, const members_t &a_members)
00313 {
00314     return pointer(new record(a_locn, a_name, a_members));
00315 }
00316 
00317 
00318 rcstring
00319 space_netgroup::record::representation(void)
00320     const
00321 {
00322     // Note: the name is NOT part of the representation.
00323     rcstring_accumulator acc;
00324     for
00325     (
00326         members_t::const_iterator it = members.begin();
00327         it != members.end();
00328         ++it
00329     )
00330     {
00331         if (!acc.empty())
00332             acc.push_back(' ');
00333         acc.push_back(it->representation());
00334     }
00335     return acc.mkstr();
00336 }
00337 
00338 
00339 bool
00340 space_netgroup::entry_t::operator==(const entry_t &arg)
00341     const
00342 {
00343     return
00344         (
00345             reference_to_netgroup == arg.reference_to_netgroup
00346         &&
00347             host == arg.host
00348         &&
00349             user == arg.user
00350         &&
00351             domain == arg.domain
00352         );
00353 }
00354 
00355 
00356 // vim: set ts=8 sw=4 et :