You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeadmin/kuser/kuser.cpp

1054 lines
22 KiB

/*
* 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>
#include <sys/types.h>
#include <sys/file.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include <fcntl.h>
#include <tqstring.h>
#include <tqdir.h>
#include "kglobal_.h"
#include "kuser.h"
#include "misc.h"
#include <kstandarddirs.h>
#include <kmessagebox.h>
#include <kprocess.h>
#include <kdebug.h>
#include <kio/netaccess.h>
#include <kurl.h>
// class KUser
KU::KUser::KUser()
{
p_change = 0;
p_expire = -1;
p_uid = 0;
p_gid = 100;
s_min = 0;
s_max = 99999;
s_warn = 7;
s_inact = -1;
// s_flag = 0;
caps = 0;
isCreateHome = false;
isCreateMailBox = false;
isCopySkel = false;
isDeleteHome = false;
isDeleteMailBox = false;
isDisabled = true;
}
KU::KUser::KUser(const KU::KUser *user)
{
copy(user);
}
void KU::KUser::copy(const KU::KUser *user)
{
if ( user != this ) {
caps = user->caps;
p_name = user->p_name;
p_surname = user->p_surname;
p_email = user->p_email;
p_pwd = user->p_pwd;
p_dir = user->p_dir;
p_shell = user->p_shell;
p_fname = user->p_fname;
p_office = user->p_office;
p_ophone = user->p_ophone;
p_hphone = user->p_hphone;
p_class = user->p_class;
p_change = user->p_change;
p_expire = user->p_expire;
p_office1 = user->p_office1;
p_office2 = user->p_office2;
p_address = user->p_address;
p_uid = user->p_uid;
p_gid = user->p_gid;
s_pwd = user->s_pwd;
s_min = user->s_min;
s_max = user->s_max;
s_warn = user->s_warn;
s_inact = user->s_inact;
s_flag = user->s_flag;
sam_lmpwd = user->sam_lmpwd;
sam_ntpwd = user->sam_ntpwd;
sam_loginscript = user->sam_loginscript;
sam_profile = user->sam_profile;
sam_homedrive = user->sam_homedrive;
sam_homepath = user->sam_homepath;
sam_workstations = user->sam_workstations;
sam_domain = user->sam_domain;
sid = user->sid;
pgroup_sid = user->pgroup_sid;
isCreateHome = user->isCreateHome;
isCreateMailBox = user->isCreateMailBox;
isDeleteHome = user->isDeleteHome;
isDeleteMailBox = user->isDeleteMailBox;
isCopySkel = user->isCopySkel;
isDisabled = user->isDisabled;
}
}
KU::KUser::~KUser()
{
}
void KU::KUser::setCaps( int data )
{
caps = data;
}
int KU::KUser::getCaps()
{
return caps;
}
bool KU::KUser::getDeleteHome()
{
return isDeleteHome;
}
bool KU::KUser::getDeleteMailBox()
{
return isDeleteMailBox;
}
bool KU::KUser::getCreateHome()
{
return isCreateHome;
}
bool KU::KUser::getCreateMailBox()
{
return isCreateMailBox;
}
bool KU::KUser::getCopySkel()
{
return isCopySkel;
}
const TQString &KU::KUser::getName() const
{
return p_name;
}
const TQString &KU::KUser::getSurname() const
{
return p_surname;
}
const TQString &KU::KUser::getEmail() const
{
return p_email;
}
const TQString &KU::KUser::getPwd() const
{
return p_pwd;
}
const TQString &KU::KUser::getHomeDir() const
{
return p_dir;
}
const TQString &KU::KUser::getShell() const
{
return p_shell;
}
const TQString &KU::KUser::getFullName() const
{
return p_fname;
}
bool KU::KUser::getDisabled() const
{
return isDisabled;
}
// FreeBSD apparently uses the GECOS fields differently than other Unices.
// Create some better named functions to make the FreeBSD code clear
const TQString &KU::KUser::getOffice() const
{
return p_office;
}
const TQString &KU::KUser::getWorkPhone() const
{
return p_ophone;
}
const TQString &KU::KUser::getHomePhone() const
{
return p_hphone;
}
// New fields needed for the FreeBSD /etc/master.passwd file
const TQString &KU::KUser::getClass() const
{
return p_class;
}
const TQString &KU::KUser::getOffice1() const
{
return p_office1;
}
const TQString &KU::KUser::getOffice2() const
{
return p_office2;
}
const TQString &KU::KUser::getAddress() const
{
return p_address;
}
uid_t KU::KUser::getUID() const
{
return p_uid;
}
gid_t KU::KUser::getGID() const
{
return p_gid;
}
const TQString &KU::KUser::getSPwd() const
{
return s_pwd;
}
time_t KU::KUser::getLastChange() const
{
return p_change;
}
int KU::KUser::getMin() const
{
return s_min;
}
int KU::KUser::getMax() const
{
return s_max;
}
int KU::KUser::getWarn() const
{
return s_warn;
}
int KU::KUser::getInactive() const
{
return s_inact;
}
int KU::KUser::getFlag() const
{
return s_flag;
}
time_t KU::KUser::getExpire() const
{
return p_expire;
}
const TQString &KU::KUser::getLMPwd() const // sam_lmpwd,
{
return sam_lmpwd;
}
const TQString &KU::KUser::getNTPwd() const //sam_ntpwd,
{
return sam_ntpwd;
}
const TQString &KU::KUser::getLoginScript() const //sam_loginscript,
{
return sam_loginscript;
}
const TQString &KU::KUser::getProfilePath() const // sam_profile,
{
return sam_profile;
}
const TQString &KU::KUser::getHomeDrive() const //sam_homedrive,
{
return sam_homedrive;
}
const TQString &KU::KUser::getHomePath() const //sam_homepath;
{
return sam_homepath;
}
const TQString &KU::KUser::getWorkstations() const //sam_workstation;
{
return sam_workstations;
}
const TQString &KU::KUser::getDomain() const //sam_domain;
{
return sam_domain;
}
const SID &KU::KUser::getSID() const //sid,
{
return sid;
}
const SID &KU::KUser::getPGSID() const //pgroup_sid;
{
return pgroup_sid;
}
void KU::KUser::setName(const TQString &data)
{
p_name = data;
}
void KU::KUser::setSurname(const TQString &data)
{
p_surname = data;
}
void KU::KUser::setEmail(const TQString &data)
{
p_email = data;
}
void KU::KUser::setPwd(const TQString &data)
{
p_pwd = data;
}
void KU::KUser::setHomeDir(const TQString &data)
{
p_dir = data;
}
void KU::KUser::setShell(const TQString &data)
{
p_shell = data;
}
void KU::KUser::setFullName(const TQString &data)
{
p_fname = data;
}
void KU::KUser::setDisabled(bool data)
{
isDisabled = data;
}
// FreeBSD apparently uses the GECOS fields differently than other Unices.
// Create some better named functions to make the FreeBSD code clear
void KU::KUser::setOffice(const TQString &data)
{
p_office = data;
}
void KU::KUser::setWorkPhone(const TQString &data)
{
p_ophone = data;
}
void KU::KUser::setHomePhone(const TQString &data)
{
p_hphone = data;
}
// New fields needed for the FreeBSD /etc/master.passwd file
void KU::KUser::setClass(const TQString &data)
{
p_class = data;
}
void KU::KUser::setLastChange(time_t data)
{
p_change = data;
}
void KU::KUser::setExpire(time_t data)
{
p_expire = data;
}
void KU::KUser::setOffice1(const TQString &data)
{
p_office1 = data;
}
void KU::KUser::setOffice2(const TQString &data)
{
p_office2 = data;
}
void KU::KUser::setAddress(const TQString &data)
{
p_address = data;
}
void KU::KUser::setUID(uid_t data)
{
p_uid = data;
}
void KU::KUser::setGID(gid_t data)
{
p_gid = data;
}
void KU::KUser::setSPwd(const TQString &data)
{
s_pwd = data;
}
void KU::KUser::setMin(int data)
{
s_min = data;
}
void KU::KUser::setMax(int data)
{
s_max = data;
}
void KU::KUser::setWarn(int data)
{
s_warn = data;
}
void KU::KUser::setInactive(int data)
{
s_inact = data;
}
void KU::KUser::setLMPwd( const TQString &data ) // sam_lmpwd,
{
sam_lmpwd = data;
}
void KU::KUser::setNTPwd( const TQString &data ) //sam_ntpwd,
{
sam_ntpwd = data;
}
void KU::KUser::setLoginScript( const TQString &data ) //sam_loginscript,
{
sam_loginscript = data;
}
void KU::KUser::setProfilePath( const TQString &data) // sam_profile,
{
sam_profile = data;
}
void KU::KUser::setHomeDrive( const TQString &data ) //sam_homedrive,
{
sam_homedrive = data;
}
void KU::KUser::setHomePath( const TQString &data ) //sam_homepath;
{
sam_homepath = data;
}
void KU::KUser::setWorkstations( const TQString &data ) //sam_workstation;
{
sam_workstations = data;
}
void KU::KUser::setDomain( const TQString &data ) //sam_domain
{
sam_domain = data;
}
void KU::KUser::setSID( const SID &data ) //sid,
{
sid = data;
}
void KU::KUser::setPGSID( const SID &data ) //pgroup_sid;
{
pgroup_sid = data;
}
void KU::KUser::setFlag(int data)
{
s_flag = data;
}
void KU::KUser::setCreateHome(bool data)
{
isCreateHome = data;
}
void KU::KUser::setCreateMailBox(bool data)
{
isCreateMailBox = data;
}
void KU::KUser::setCopySkel(bool data)
{
isCopySkel = data;
}
void KU::KUser::setDeleteHome(bool data)
{
isDeleteHome = data;
}
void KU::KUser::setDeleteMailBox(bool data)
{
isDeleteMailBox = data;
}
int KU::KUser::createHome()
{
if(p_dir.isNull() || p_dir.isEmpty()) {
KMessageBox::sorry( 0, i18n("Cannot create home folder for %1: it is null or empty.").arg(p_name) );
return(0);
}
if (mkdir(TQFile::encodeName(p_dir), 0700) != 0) {
if (errno != EEXIST)
{
KMessageBox::error( 0, i18n("Cannot create home folder %1.\nError: %2").arg(p_dir).arg(TQString::fromLocal8Bit(strerror(errno))) );
return(0);
}
}
if (chown(TQFile::encodeName(p_dir), p_uid, p_gid) != 0) {
KMessageBox::error( 0, i18n("Cannot change owner of home folder %1.\nError: %2").arg(p_dir).arg(TQString::fromLocal8Bit(strerror(errno))) );
return(1);
}
if (chmod(TQFile::encodeName(p_dir), KU_HOMEDIR_PERM) != 0) {
KMessageBox::error( 0, i18n("Cannot change permissions on home folder %1.\nError: %2").arg(p_dir).arg(TQString::fromLocal8Bit(strerror(errno))) );
return(1);
}
return(1);
}
int KU::KUser::tryCreate(const TQString &dir)
{
struct stat sb;
int rc = 0;
rc = stat(TQFile::encodeName(dir), &sb);
if (rc == 0) {
if (S_ISDIR(sb.st_mode)) {
if (KMessageBox::warningContinueCancel( 0,
i18n("Folder %1 already exists!\nWill make %2 owner and change permissions.\nDo you want to continue?").arg(dir).arg(p_name),
TQString(), KStdGuiItem::cont() ) == KMessageBox::Continue) {
if (chown(TQFile::encodeName(dir), p_uid, p_gid) != 0) {
KMessageBox::error( 0, i18n("Cannot change owner of %1 folder.\nError: %2") .arg(dir).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
return(0);
} else {
KMessageBox::information( 0, i18n("Folder %1 left 'as is'.\nVerify ownership and permissions for user %2 who may not be able to log in!").arg(dir).arg(p_name) );
return(-1);
}
} else {
KMessageBox::information( 0, i18n("%1 exists and is not a folder. User %2 will not be able to log in!").arg(dir).arg(p_name) );
return(-1);
}
} else {
if (errno == ENOENT) {
if (mkdir(TQFile::encodeName(dir), 0700) != 0) {
KMessageBox::error( 0, i18n("Cannot create %1 folder.\nError: %2").arg(dir).arg(TQString::fromLocal8Bit(strerror(errno))));
return(-1);
}
if (chown(TQFile::encodeName(dir), p_uid, p_gid) != 0) {
KMessageBox::error( 0, i18n("Cannot change owner of %1 folder.\nError: %2").arg(dir).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
return(0);
} else {
KMessageBox::error( 0, i18n("stat call on %1 failed.\nError: %2").arg(dir).arg(TQString::fromLocal8Bit(strerror(errno))) );
return(-1);
}
}
}
int KU::KUser::createMailBox()
{
TQString mailboxpath;
int fd;
mailboxpath = TQFile::decodeName(MAIL_SPOOL_DIR) + "/" + p_name;
if((fd = open(TQFile::encodeName(mailboxpath), O_CREAT|O_EXCL|O_WRONLY,
S_IRUSR|S_IWUSR)) < 0) {
if (errno != EEXIST)
{
KMessageBox::error( 0, i18n("Cannot create %1: %2")
.arg(mailboxpath)
.arg(TQString::fromLocal8Bit(strerror(errno))) );
return -1;
}
}
close(fd);
if (chown(TQFile::encodeName(mailboxpath), p_uid, KU_MAILBOX_GID) != 0) {
KMessageBox::error( 0, i18n("Cannot change owner on mailbox: %1\nError: %2")
.arg(mailboxpath).arg(TQString::fromLocal8Bit(strerror(errno))) );
return -1;
}
if (chmod(TQFile::encodeName(mailboxpath), KU_MAILBOX_PERM) != 0) {
KMessageBox::error( 0, i18n("Cannot change permissions on mailbox: %1\nError: %2")
.arg(mailboxpath).arg(TQString::fromLocal8Bit(strerror(errno))) );
return -1;
}
return 0;
}
void KU::KUser::copyDir(const TQString &srcPath, const TQString &dstPath)
{
mode_t mode;
TQDir s(srcPath);
TQDir d(dstPath);
TQString dot = TQString::fromLatin1(".");
TQString dotdot = TQString::fromLatin1("..");
s.setFilter( TQDir::All | TQDir::Hidden | TQDir::System );
for (uint i=0; i<s.count(); i++) {
TQString name(s[i]);
if (name == dot)
continue;
if (name == dotdot)
continue;
TQString filename(s.filePath(name));
TQFileInfo info(filename);
mode = 0;
if ( info.permission(TQFileInfo::ReadOwner) ) mode |= S_IRUSR;
if ( info.permission(TQFileInfo::WriteOwner) ) mode |= S_IWUSR;
if ( info.permission(TQFileInfo::ExeOwner) ) mode |= S_IXUSR;
if ( info.permission(TQFileInfo::ReadGroup) ) mode |= S_IRGRP;
if ( info.permission(TQFileInfo::WriteGroup) ) mode |= S_IWGRP;
if ( info.permission(TQFileInfo::ExeGroup) ) mode |= S_IXGRP;
if ( info.permission(TQFileInfo::ReadOther) ) mode |= S_IROTH;
if ( info.permission(TQFileInfo::WriteOther) ) mode |= S_IWOTH;
if ( info.permission(TQFileInfo::ExeOther) ) mode |= S_IXOTH;
if ( info.isSymLink() ) {
TQString link = info.readLink();
if (symlink(TQFile::encodeName(link),TQFile::encodeName(d.filePath(name))) != 0) {
KMessageBox::error( 0, i18n("Error creating symlink %1.\nError: %2")
.arg(d.filePath(s[i])).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
} else if ( info.isDir() ) {
TQDir dir(filename);
d.mkdir(name, FALSE);
copyDir(s.filePath(name), d.filePath(name));
if (chown(TQFile::encodeName(d.filePath(name)), p_uid, p_gid) != 0) {
KMessageBox::error( 0, i18n("Cannot change owner of folder %1.\nError: %2")
.arg(d.filePath(s[i])).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
if (chmod(TQFile::encodeName(d.filePath(name)), mode) != 0) {
KMessageBox::error( 0, i18n("Cannot change permissions on folder %1.\nError: %2")
.arg(d.filePath(s[i])).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
} else {
if (copyFile(filename, d.filePath(name)) == -1) {
continue;
}
if (chown(TQFile::encodeName(d.filePath(name)), p_uid, p_gid) != 0) {
KMessageBox::error( 0, i18n("Cannot change owner of file %1.\nError: %2")
.arg(d.filePath(s[i])).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
if (chmod(TQFile::encodeName(d.filePath(name)), mode) != 0) {
KMessageBox::error( 0, i18n("Cannot change permissions on file %1.\nError: %2")
.arg(d.filePath(s[i])).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
}
}
}
int KU::KUser::copySkel()
{
TQDir s(TQFile::decodeName(SKELDIR));
TQDir d(p_dir);
mode_t mode;
if (!s.exists()) {
KMessageBox::error( 0, i18n("Folder %1 does not exist, cannot copy skeleton for %2.").arg(s.absPath()).arg(p_name) );
return (-1);
}
if (!d.exists()) {
KMessageBox::error( 0, i18n("Folder %1 does not exist, cannot copy skeleton.").arg(d.absPath()) );
return (-1);
}
mode = umask(0007);
copyDir(s.absPath(), d.absPath());
umask( mode );
return 0;
}
int KU::KUser::removeHome()
{
struct stat sb;
if (!stat(TQFile::encodeName(p_dir), &sb))
if (S_ISDIR(sb.st_mode) && sb.st_uid == p_uid) {
if (!KIO::NetAccess::del(KURL::fromPathOrURL(p_dir))) {
KMessageBox::error( 0, i18n("Cannot remove home folder %1.\nError: %2")
.arg(p_dir).arg(KIO::NetAccess::lastErrorString()) );
}
} else {
KMessageBox::error( 0, i18n("Removal of home folder %1 failed (uid = %2, gid = %3).").arg(p_dir).arg(sb.st_uid).arg(sb.st_gid) );
}
else {
KMessageBox::error( 0, i18n("stat call on file %1 failed.\nError: %2")
.arg(p_dir).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
return 0;
}
//TODO: remove at jobs too.
int KU::KUser::removeCrontabs()
{
TQString file;
TQString command;
file = TQFile::decodeName(CRONTAB_DIR) + "/" + p_name;
if ( access(TQFile::encodeName(file), F_OK) == 0 ) {
command = TQString::fromLatin1("crontab -u %1 -r").arg(KProcess::quote(p_name));
if ( system(TQFile::encodeName(command)) != 0 ) {
KMessageBox::error( 0, i18n("Cannot remove crontab %1.\nError: %2")
.arg(command).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
}
return 0;
}
int KU::KUser::removeMailBox()
{
TQString file;
file = TQFile::decodeName(MAIL_SPOOL_DIR) + "/" + p_name;
if (remove(TQFile::encodeName(file)) != 0) {
KMessageBox::error( 0, i18n("Cannot remove mailbox %1.\nError: %2")
.arg(file).arg(TQString::fromLocal8Bit(strerror(errno))) );
}
return 0;
}
int KU::KUser::removeProcesses()
{
// be paranoid -- kill all processes owned by that user, if not root.
if (p_uid != 0)
switch (fork()) {
case 0:
setuid(p_uid);
kill(-1, 9);
_exit(0);
break;
case -1:
KMessageBox::error( 0,
i18n("Cannot fork while trying to kill processes for uid %1.").arg(p_uid) );
break;
}
return 0;
}
KU::KUsers::KUsers(KUserPrefsBase *cfg)
{
mUsers.setAutoDelete(TRUE);
mCfg = cfg;
}
KU::KUsers::~KUsers()
{
mUsers.clear();
}
const TQString &KU::KUsers::getDOMSID() const
{
return domsid;
}
void KU::KUsers::parseGecos( const char *gecos, TQString &name,
TQString &field1, TQString &field2, TQString &field3 )
{
int no = 0;
const char *s = gecos;
const char *pos = NULL;
// At least one part of the string exists
for(;;) {
pos = strchr(s, ',');
TQString val;
if(pos == NULL)
val = TQString::fromLocal8Bit(s);
else
val = TQString::fromLocal8Bit(s, (int)(pos-s));
switch(no) {
case 0: name = val; break;
case 1: field1 = val; break;
case 2: field2 = val; break;
case 3: field3 = val; break;
}
if(pos == NULL) break;
s = pos+1;
no++;
}
}
void KU::KUsers::fillGecos(KU::KUser *user, const char *gecos)
{
TQString name,field1,field2,field3;
parseGecos( gecos, name, field1, field2, field3 );
user->setFullName( name );
caps & Cap_BSD ? user->setOffice( field1 ) : user->setOffice1( field1 );
caps & Cap_BSD ? user->setWorkPhone( field2 ) : user->setOffice2( field2 );
caps & Cap_BSD ? user->setHomePhone( field3 ) : user->setAddress( field3 );
}
bool KU::KUsers::doCreate(KU::KUser *user)
{
TQString h_dir;
if(user->getCreateMailBox()) {
user->createMailBox();
user->setCreateMailBox(false);
}
if(user->getCreateHome()) {
if(user->createHome()) {
user->setCreateHome(false);
} else {
return false; // if createHome fails, copySkel is irrelevant!
}
if(user->getCopySkel()) {
if((user->copySkel()) == 0) {
user->setCopySkel(false);
}
}
}
return TRUE;
}
bool KU::KUsers::doDelete( KU::KUser *user )
{
kdDebug() << "delete user: " << user->getName() << " uid: " << user->getUID() << endl;
if ( user->isDeleteHome ) {
user->removeHome();
user->removeCrontabs();
}
if ( user->isDeleteMailBox )
user->removeMailBox();
/*
user->removeProcesses();
*/
return TRUE;
}
KU::KUser *KU::KUsers::lookup(const TQString & name)
{
KU::KUser *user;
TQPtrListIterator<KU::KUser> it( mUsers );
while ( (user = it.current()) != 0 && user->getName() != name ) ++it;
return user;
}
KU::KUser *KU::KUsers::lookup(uid_t uid)
{
KU::KUser *user;
TQPtrListIterator<KU::KUser> it( mUsers );
while ( (user = it.current()) != 0 && user->getUID() != uid ) ++it;
return user;
}
KU::KUser *KU::KUsers::lookup_sam( const SID &sid )
{
KU::KUser *user;
TQPtrListIterator<KU::KUser> it( mUsers );
while ( (user = it.current()) != 0 && user->getSID() != sid ) ++it;
return user;
}
KU::KUser *KU::KUsers::lookup_sam( const TQString &sid )
{
KU::KUser *user;
TQPtrListIterator<KU::KUser> it( mUsers );
while ( (user = it.current()) != 0 && user->getSID().getSID() != sid ) ++it;
return user;
}
KU::KUser *KU::KUsers::lookup_sam( uint rid )
{
KU::KUser *user;
TQPtrListIterator<KU::KUser> it( mUsers );
while ( (user = it.current()) != 0 && user->getSID().getRID() != rid ) ++it;
return user;
}
uid_t KU::KUsers::first_free()
{
uid_t t;
for (t = mCfg->firstUID() ; t<65534; t++)
if (lookup(t) == NULL)
return t;
return NO_FREE;
}
uint KU::KUsers::first_free_sam()
{
uint t;
for (t = 1000; t<65534; t++)
if (lookup_sam(t) == NULL)
return t;
return 0;
}
uint KU::KUsers::count() const
{
return mUsers.count();
}
KU::KUser *KU::KUsers::operator[](uint num)
{
return mUsers.at(num);
}
KU::KUser *KU::KUsers::first()
{
return mUsers.first();
}
KU::KUser *KU::KUsers::next()
{
return mUsers.next();
}
void KU::KUsers::add(KU::KUser *user)
{
mAdd.append( user );
}
void KU::KUsers::del(KU::KUser *user)
{
mDel.append( user );
}
void KU::KUsers::mod(KU::KUser *uold, const KU::KUser &unew)
{
mMod.insert( uold, unew );
}
void KU::KUsers::commit()
{
kdDebug() << "KU::KUsers::commit()" << endl;
KU::KUser *user;
DelIt dit( mDelSucc );
AddIt ait( mAddSucc );
ModIt mit = mModSucc.begin();
//commit modifications
while ( mit != mModSucc.end() ) {
*(mit.key()) = mit.data();
mit++;
}
//commit deletes
while ( (user = dit.current()) != 0 ) {
++dit;
doDelete( user );
mUsers.remove( user );
}
//commit additions
while ( (user = ait.current()) != 0 ) {
++ait;
doCreate( user );
mUsers.append( user );
}
//clear the unsuccessful modifications
cancelMods();
}
void KU::KUsers::cancelMods()
{
KU::KUser *user;
while ( (user = mAdd.first()) ) {
delete user;
mAdd.remove();
}
mDel.clear();
mMod.clear();
}