summaryrefslogtreecommitdiffstats
path: root/kuser/kgroupfiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kuser/kgroupfiles.cpp')
-rw-r--r--kuser/kgroupfiles.cpp402
1 files changed, 402 insertions, 0 deletions
diff --git a/kuser/kgroupfiles.cpp b/kuser/kgroupfiles.cpp
new file mode 100644
index 0000000..bab8841
--- /dev/null
+++ b/kuser/kgroupfiles.cpp
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 1998 Denis Perchine <dyp@perchine.com>
+ * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu>
+ * Former maintainer: Adriaan de Groot <groot@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include "globals.h"
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <grp.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <qstring.h>
+#include <qdir.h>
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+
+#include "kglobal_.h"
+#include "kgroupfiles.h"
+#include "misc.h"
+#include "editDefaults.h"
+
+KGroupFiles::KGroupFiles( KUserPrefsBase *cfg ) : KGroups( cfg )
+{
+ gs_backuped = FALSE;
+ gr_backuped = FALSE;
+ gn_backuped = FALSE;
+
+ smode = 0400;
+ mode = 0644;
+ uid = 0;
+ gid = 0;
+
+ caps = Cap_Passwd;
+
+ reload();
+}
+
+KGroupFiles::~KGroupFiles()
+{
+ mGroups.clear();
+}
+
+bool KGroupFiles::reload()
+{
+ struct group *p;
+ KU::KGroup *tmpKG = 0;
+ struct stat st;
+ QString filename;
+ QString group_filename;
+ QString nisgroup_filename;
+ int rc = 0;
+ int group_errno = 0;
+ int nisgroup_errno = 0;
+ char processing_file = '\0';
+ #define GROUP 0x01
+ #define NISGROUP 0x02
+ #define MAXFILES 2
+
+ // Prepare to read KUser configuration
+
+ group_filename = mCfg->groupsrc();
+ nisgroup_filename = mCfg->nisgroupsrc();
+ if(!group_filename.isEmpty()) {
+ processing_file = processing_file | GROUP;
+ filename.append(group_filename);
+ }
+
+ // Start reading group file(s)
+
+ for(int k = 0; k < MAXFILES; k++) {
+ rc = stat(QFile::encodeName(filename), &st);
+ if(rc != 0) {
+ KMessageBox::error( 0, i18n("stat call on file %1 failed: %2\nCheck KUser settings.").
+ arg(filename).arg(QString::fromLatin1(strerror(errno))) );
+ if( (processing_file & GROUP) != 0 ) {
+ group_errno = errno;
+ if(!nisgroup_filename.isEmpty()) {
+ processing_file = processing_file & ~GROUP;
+ processing_file = processing_file | NISGROUP;
+ filename.truncate(0);
+ filename.append(nisgroup_filename);
+ }
+ continue;
+ }
+ else{
+ nisgroup_errno = errno;
+ break;
+ }
+ }
+
+ mode = st.st_mode;
+ uid = st.st_uid;
+ gid = st.st_gid;
+
+ // We are reading our configuration specified group file
+#ifdef HAVE_FGETGRENT
+ FILE *fgrp = fopen(QFile::encodeName(filename), "r");
+ QString tmp;
+ if (fgrp == NULL) {
+ KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(filename) );
+ return FALSE;
+ }
+
+ while ((p = fgetgrent(fgrp)) != NULL) {
+#else
+ setgrent();
+ while ((p = getgrent()) != NULL) {
+#endif
+ tmpKG = new KU::KGroup();
+ tmpKG->setGID(p->gr_gid);
+ tmpKG->setName(QString::fromLocal8Bit(p->gr_name));
+ tmpKG->setPwd(QString::fromLocal8Bit(p->gr_passwd));
+
+ char *u_name;
+ int i = 0;
+ while ((u_name = p->gr_mem[i])!=0) {
+ tmpKG->addUser(QString::fromLocal8Bit(u_name));
+ i++;
+ }
+
+ mGroups.append(tmpKG);
+ }
+
+ // End reading filename
+
+#ifdef HAVE_FGETGRENT
+ fclose(fgrp);
+#else
+ endgrent();
+#endif
+ if(!nisgroup_filename.isEmpty()) {
+ if(nisgroup_filename == group_filename)
+ break;
+ processing_file = processing_file & ~GROUP;
+ processing_file = processing_file | NISGROUP;
+ filename.truncate(0);
+ filename.append(nisgroup_filename);
+ }
+ else
+ break;
+
+ } // end of processing files, for loop
+
+ if( (group_errno == 0) && (nisgroup_errno == 0) )
+ return(TRUE);
+ if( (group_errno != 0) && (nisgroup_errno != 0) )
+ return(FALSE);
+ else
+ return(TRUE);
+}
+
+bool KGroupFiles::save()
+{
+ kdDebug() << "KGroupFiles::save() " << endl;
+ FILE *group_fd = NULL;
+ FILE *gshadow_fd = NULL;
+ FILE *nisgroup_fd = NULL;
+ gid_t mingid = 0;
+ int nis_groups_written = 0;
+ gid_t tmp_gid = 0;
+ QString tmpGe, tmpSe, tmp2;
+ QString group_filename, new_group_filename;
+ QString gshadow_filename, new_gshadow_filename;
+ QString nisgroup_filename, new_nisgroup_filename;
+
+ char errors_found = '\0';
+ #define NOMINGID 0x01
+ #define NONISGROUP 0x02
+
+ // read KUser configuration info
+
+ group_filename = mCfg->groupsrc();
+ new_group_filename = group_filename + QString::fromLatin1(KU_CREATE_EXT);
+#ifdef HAVE_SHADOW
+ gshadow_filename = mCfg->gshadowsrc();
+ if ( !KStandardDirs::exists( gshadow_filename ) )
+ gshadow_filename = QString::null;
+ else
+ new_gshadow_filename = gshadow_filename + QString::fromLatin1(KU_CREATE_EXT);
+#endif
+ nisgroup_filename = mCfg->nisgroupsrc();
+ new_nisgroup_filename = nisgroup_filename + QString::fromLatin1(KU_CREATE_EXT);
+ if( nisgroup_filename != group_filename ) {
+ mingid = mCfg->nismingid();
+ }
+
+ // Backup file(s)
+
+ if(!group_filename.isEmpty()) {
+ if (!gr_backuped) {
+ if ( !backup(group_filename) ) return false;
+ gr_backuped = TRUE;
+ }
+ }
+ if(!gshadow_filename.isEmpty()) {
+ if (!gs_backuped) {
+ if ( !backup(gshadow_filename) ) return false;
+ gs_backuped = TRUE;
+ }
+ }
+ if(!nisgroup_filename.isEmpty() && (nisgroup_filename != group_filename)) {
+ if (!gn_backuped) {
+ if ( !backup(nisgroup_filename) ) return false;
+ gn_backuped = TRUE;
+ }
+ }
+
+ // Open file(s)
+
+ if(!group_filename.isEmpty()) {
+ if((group_fd = fopen(QFile::encodeName(new_group_filename), "w")) == NULL) {
+ KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_group_filename) );
+ return false;
+ }
+ }
+
+ if(!gshadow_filename.isEmpty()) {
+ if((gshadow_fd = fopen(QFile::encodeName(new_gshadow_filename), "w")) == NULL) {
+ KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_gshadow_filename) );
+ if ( group_fd ) fclose ( group_fd );
+ return false;
+ }
+ }
+
+ if(!nisgroup_filename.isEmpty() && (nisgroup_filename != group_filename)) {
+ if((nisgroup_fd = fopen(QFile::encodeName(new_nisgroup_filename), "w")) == NULL) {
+ KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_nisgroup_filename) );
+ if ( group_fd ) fclose ( group_fd );
+ if ( gshadow_fd ) fclose ( gshadow_fd );
+ return false;
+ }
+ }
+
+ QPtrListIterator<KU::KGroup> it( mGroups );
+ KU::KGroup *gr;
+ bool addok = false;
+
+ gr = (*it);
+
+ while (true) {
+
+ if ( gr == 0 ) {
+ if ( addok ) break;
+ it = QPtrListIterator<KU::KGroup> ( mAdd );
+ gr = (*it);
+ addok = true;
+ if ( gr == 0 ) break;
+ };
+
+ if ( mDel.containsRef( gr ) ) {
+ ++it;
+ gr = (*it);
+ continue;
+ }
+ if ( mMod.contains( gr ) ) gr = &( mMod[ gr ] );
+
+#ifdef HAVE_SHADOW
+ if ( addok && !mCfg->gshadowsrc().isEmpty() )
+ gr->setPwd("x");
+#endif
+
+ tmpGe = gr->getName();
+ tmpGe.replace( ',', "_" );
+ tmpGe.replace( ':', "_" );
+ gr->setName( tmpGe );
+
+ tmp_gid = gr->getGID();
+ tmpGe += ":" +
+ gr->getPwd() + ":" +
+ QString::number( gr->getGID() ) + ":";
+ tmpSe = gr->getName() + ":!::";
+ for (uint j=0; j<gr->count(); j++) {
+ if (j != 0) {
+ tmpGe += ',';
+ tmpSe += ',';
+ }
+ gr->user( j ).replace( ',', "_" );
+ gr->user( j ).replace( ':', "_" );
+ tmpGe += gr->user( j) ;
+ tmpSe += gr->user( j );
+ }
+ tmpGe += '\n'; tmpSe += '\n';
+
+ if( (nisgroup_fd != 0) && (mingid != 0) ) {
+ if(mingid <= tmp_gid) {
+ fputs(tmpGe.local8Bit(), nisgroup_fd);
+ nis_groups_written++;
+ ++it;
+ gr = (*it);
+ continue;
+ }
+ }
+
+ if( (nisgroup_fd != 0) && (mingid == 0) ) {
+ errors_found = errors_found | NOMINGID;
+ }
+
+ if( (nisgroup_fd == 0) && (mingid != 0) ) {
+ errors_found = errors_found | NONISGROUP;
+ }
+
+ fputs( tmpGe.local8Bit(), group_fd );
+ if ( gshadow_fd ) fputs( tmpSe.local8Bit(), gshadow_fd );
+ ++it;
+ gr = (*it);
+ }
+
+ if(group_fd) {
+ fclose(group_fd);
+ chmod(QFile::encodeName(new_group_filename), mode);
+ chown(QFile::encodeName(new_group_filename), uid, gid);
+ rename(QFile::encodeName(new_group_filename),
+ QFile::encodeName(group_filename));
+ }
+
+ if(gshadow_fd) {
+ fclose(gshadow_fd);
+ chmod(QFile::encodeName(new_gshadow_filename), mode);
+ chown(QFile::encodeName(new_gshadow_filename), uid, gid);
+ rename(QFile::encodeName(new_gshadow_filename),
+ QFile::encodeName(gshadow_filename));
+ }
+
+ if(nisgroup_fd) {
+ fclose(nisgroup_fd);
+ chmod(QFile::encodeName(nisgroup_filename), mode);
+ chown(QFile::encodeName(nisgroup_filename), uid, gid);
+ rename(QFile::encodeName(new_nisgroup_filename),
+ QFile::encodeName(nisgroup_filename));
+ }
+
+ if( (errors_found & NOMINGID) != 0 ) {
+ KMessageBox::error( 0, i18n("Unable to process NIS group file without a minimum GID specified.\nPlease update KUser settings (File Source Settings).") );
+ }
+
+ if( (errors_found & NONISGROUP) != 0 ) {
+ KMessageBox::error( 0, i18n("Specifying NIS minimum GID requires NIS file(s).\nPlease update KUser settings (File Source Settings).") );
+ }
+
+#ifdef GRMKDB
+ if( (nis_groups_written > 0) || (nisgroup_filename == group_filename) ) {
+ if (system(GRMKDB) != 0) {
+ KMessageBox::error( 0, i18n("Unable to build NIS group databases.") );
+ return FALSE;
+ }
+ }
+#endif
+
+ return TRUE;
+}
+
+bool KGroupFiles::dbcommit()
+{
+ bool ret;
+ mode_t mode;
+
+ kdDebug() << "KGroupFiles dbcommit" << endl;
+ mAddSucc.clear();
+ mDelSucc.clear();
+ mModSucc.clear();
+ if ( mDel.isEmpty() && mAdd.isEmpty() && mMod.isEmpty() )
+ return true;
+
+ mode = umask(0077);
+ ret = save();
+ umask( mode );
+ if ( !ret ) return false;
+
+ mDelSucc = mDel;
+ mAddSucc = mAdd;
+ mModSucc = mMod;
+ mDel.clear();
+ mAdd.clear();
+ mMod.clear();
+
+ return true;
+}
+