nis-util
1.0.D108
|
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 :