-rw-r--r-- | noncore/settings/usermanager/userdialog.cpp | 32 | ||||
-rw-r--r-- | noncore/settings/usermanager/userdialog.h | 3 | ||||
-rw-r--r-- | noncore/settings/usermanager/usermanager.cpp | 8 | ||||
-rw-r--r-- | noncore/settings/usermanager/usermanager.h | 9 |
4 files changed, 42 insertions, 10 deletions
diff --git a/noncore/settings/usermanager/userdialog.cpp b/noncore/settings/usermanager/userdialog.cpp index b7827a4..90e27d5 100644 --- a/noncore/settings/usermanager/userdialog.cpp +++ b/noncore/settings/usermanager/userdialog.cpp @@ -1,186 +1,197 @@ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include "userdialog.h" #include <qlayout.h> #include <qlabel.h> #include <qmessagebox.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <signal.h> #include "passwd.h" /** * UserDialog constructor. Setup the dialog, fill the groupComboBox & groupsListView with all groups. * */ UserDialog::UserDialog(QWidget* parent, const char* name, bool modal, WFlags fl) : QDialog(parent, name, modal, fl) { QVBoxLayout *layout = new QVBoxLayout(this); myTabWidget=new QTabWidget(this,"User Tab Widget"); layout->addWidget(myTabWidget); setupTab1(); setupTab2(); + accounts->groupStringList.sort(); // And also fill the listview & the combobox with all available groups. for( QStringList::Iterator it = accounts->groupStringList.begin(); it!=accounts->groupStringList.end(); ++it) { accounts->splitGroupEntry(*it); - //new QListViewItem(groupsListView,accounts->gr_name); new QCheckListItem(groupsListView,accounts->gr_name,QCheckListItem::CheckBox); groupComboBox->insertItem(accounts->gr_name); } - showMaximized(); } /** * Empty destructor. * */ UserDialog::~UserDialog() { } /** * Creates the first tab, all userinfo is here. * */ void UserDialog::setupTab1() { QPixmap mypixmap; QWidget *tabpage = new QWidget(myTabWidget,"page1"); QVBoxLayout *layout = new QVBoxLayout(tabpage); layout->setMargin(5); // Picture picturePushButton = new QPushButton(tabpage,"Label"); picturePushButton->setMinimumSize(48,48); picturePushButton->setMaximumSize(48,48); picturePushButton->setPixmap(Resource::loadPixmap("usermanager/usericon")); // Load default usericon. connect(picturePushButton,SIGNAL(clicked()),this,SLOT(clickedPicture())); // Clicking the picture should invoke pictureselector. // Login QLabel *loginLabel=new QLabel(tabpage,"Login: "); loginLabel->setText("Login: "); loginLineEdit=new QLineEdit(tabpage,"Login: "); // UID QLabel *uidLabel=new QLabel(tabpage,"uid: "); uidLabel->setText("UserID: "); uidLineEdit=new QLineEdit(tabpage,"uid: "); uidLineEdit->setEnabled(false); // Username (gecos) QLabel *gecosLabel=new QLabel(tabpage,"gecos"); gecosLabel->setText("Username: "); gecosLineEdit=new QLineEdit(tabpage,"gecos"); // Password QLabel *passwordLabel=new QLabel(tabpage,"password"); passwordLabel->setText("Password: "); passwordLineEdit=new QLineEdit(tabpage,"password"); passwordLineEdit->setEchoMode(QLineEdit::Password); // Shell QLabel *shellLabel=new QLabel(tabpage,"shell"); shellLabel->setText("Shell: "); shellComboBox=new QComboBox(tabpage,"shell"); shellComboBox->setEditable(true); shellComboBox->insertItem("/bin/sh"); shellComboBox->insertItem("/bin/ash"); shellComboBox->insertItem("/bin/false"); // Primary Group QLabel *groupLabel=new QLabel(tabpage,"group"); groupLabel->setText("Primary group: "); groupComboBox=new QComboBox(tabpage,"PrimaryGroup"); - // Widget layout + // Copy /etc/skel + QLabel *skelLabel=new QLabel(tabpage,"skel"); + skelLabel->setText("Copy /etc/skel: "); + skelCheckBox=new QCheckBox(tabpage); + skelCheckBox->setChecked(true); + skelLabel->setDisabled(true); + skelCheckBox->setDisabled(true); + + // Widget layout QHBoxLayout *hlayout=new QHBoxLayout(-1,"hlayout"); layout->addWidget(picturePushButton); layout->addSpacing(5); layout->addLayout(hlayout); QVBoxLayout *vlayout1=new QVBoxLayout(-1,"vlayout1"); QVBoxLayout *vlayout2=new QVBoxLayout(-1,"vlayout2"); // First column, labels vlayout1->addWidget(loginLabel); vlayout1->addSpacing(5); vlayout1->addWidget(uidLabel); vlayout1->addSpacing(5); vlayout1->addWidget(gecosLabel); vlayout1->addSpacing(5); vlayout1->addWidget(passwordLabel); vlayout1->addSpacing(5); vlayout1->addWidget(shellLabel); vlayout1->addSpacing(5); vlayout1->addWidget(groupLabel); + vlayout1->addSpacing(5); + vlayout1->addWidget(skelLabel); // Second column, data vlayout2->addWidget(loginLineEdit); vlayout2->addSpacing(5); vlayout2->addWidget(uidLineEdit); vlayout2->addSpacing(5); vlayout2->addWidget(gecosLineEdit); vlayout2->addSpacing(5); vlayout2->addWidget(passwordLineEdit); vlayout2->addSpacing(5); vlayout2->addWidget(shellComboBox); vlayout2->addSpacing(5); vlayout2->addWidget(groupComboBox); + vlayout2->addSpacing(5); + vlayout2->addWidget(skelCheckBox); hlayout->addLayout(vlayout1); hlayout->addLayout(vlayout2); myTabWidget->addTab(tabpage,"User Info"); } /** * Creates the second tab containing additional groups for the user. * */ void UserDialog::setupTab2() { QWidget *tabpage = new QWidget(myTabWidget,"page2"); QVBoxLayout *layout = new QVBoxLayout(tabpage); layout->setMargin(5); // Additional groups groupsListView=new QListView(tabpage,"groups"); groupsListView->addColumn("Additional groups"); groupsListView->setColumnWidthMode(0,QListView::Maximum); groupsListView->setMultiSelection(false); groupsListView->setAllColumnsShowFocus(false); layout->addSpacing(5); // Grouplist layout->addWidget(groupsListView); myTabWidget->addTab(tabpage,"User Groups"); } /** * Static function that creates the userinfo dialog. * The user will be prompted to add a user. * * @param uid This is a suggested available UID. * @param gid This is a suggested available GID. * * @return <code>true</code> if the user was successfully added, otherwise <code>false</code>. * */ bool UserDialog::addUser(int uid, int gid) { UserDialog *adduserDialog=new UserDialog(); adduserDialog->setCaption(tr("Add User")); adduserDialog->userID=uid; // Set next available UID as default uid. adduserDialog->groupID=gid; // Set next available GID as default gid. // Insert default group into groupComboBox adduserDialog->groupComboBox->insertItem("<create new group>",0); adduserDialog->uidLineEdit->setText(QString::number(uid)); // Show the dialog! @@ -203,142 +214,151 @@ bool UserDialog::addUser(int uid, int gid) { for ( ; it.current(); ++it ) { temp=(QCheckListItem*)it.current(); if (temp->isOn() ) accounts->addGroupMember(it.current()->text(0),adduserDialog->loginLineEdit->text()); } // Copy image to pics/users/ if(!(adduserDialog->userImage.isNull())) { QDir d; if(!(d.exists("/opt/QtPalmtop/pics/users"))) { d.mkdir("/opt/QtPalmtop/pics/users"); } QString filename="/opt/QtPalmtop/pics/users/"+accounts->pw_name+".png"; // adduserDialog->userImage=adduserDialog->userImage.smoothScale(48,48); adduserDialog->userImage.save(filename,"PNG"); } return true; } /** * Deletes the user account. * * @param username User to be deleted. * * @return <code>true</code> if the user was successfully deleted, otherwise <code>false</code>. * */ bool UserDialog::delUser(const char *username) { if((accounts->findUser(username))) { // Does that user exist? if(!(accounts->delUser(username))) { // Delete the user. QMessageBox::information(0,"Ooops!","Something went wrong\nUnable to delete user: "+QString(username)+"."); } } else { QMessageBox::information(0,"Invalid Username","That username ("+QString(username)+")does not exist."); return false; } return true; } /** * This displays a confirmation dialog wether a user should be deleted or not. * (And also deletes the account) * * @param username User to be deleted. * * @return <code>true</code> if the user was successfully deleted, otherwise <code>false</code>. * */ bool UserDialog::editUser(const char *username) { + int invalid_group=0; UserDialog *edituserDialog=new UserDialog(); // Create Dialog edituserDialog->setCaption(tr("Edit User")); accounts->findUser(username); // Locate user in database and fill variables in 'accounts' object. - accounts->findGroup(accounts->pw_gid); // Locate the user's primary group, and fill group variables in 'accounts' object. + if(!(accounts->findGroup(accounts->pw_gid))) { // Locate the user's primary group, and fill group variables in 'accounts' object. + invalid_group=1; + } // Fill widgets with userinfo. edituserDialog->loginLineEdit->setText(accounts->pw_name); edituserDialog->uidLineEdit->setText(QString::number(accounts->pw_uid)); edituserDialog->gecosLineEdit->setText(accounts->pw_gecos); // Set password to '........', we will later check if this still is the contents, if not, the password has been changed. edituserDialog->passwordLineEdit->setText("........"); // If this user is not using /bin/sh,/bin/ash or /bin/false as shell, add that entry to the shell-combobox. if(accounts->pw_shell!="/bin/sh" && accounts->pw_shell!="/bin/ash" && accounts->pw_shell!="/bin/false") { edituserDialog->shellComboBox->insertItem(accounts->pw_shell,0); edituserDialog->shellComboBox->setCurrentItem(0); } // Select the primary group for this user. for(int i=0;i<edituserDialog->groupComboBox->count();++i) { if(accounts->gr_name==edituserDialog->groupComboBox->text(i)) { edituserDialog->groupComboBox->setCurrentItem(i); + break; } } + if(invalid_group) { + edituserDialog->groupComboBox->insertItem("<Undefined group>",0); + edituserDialog->groupComboBox->setCurrentItem(0); + } // Select the groups in the listview, to which the user belongs. QCheckListItem *temp; QRegExp userRegExp(QString("[:\\s]%1\\s").arg(username)); QStringList tempList=accounts->groupStringList.grep(userRegExp); // Find all entries in the group database, that the user is a member of. for(QStringList::Iterator it=tempList.begin(); it!=tempList.end(); ++it) { // Iterate over all of them. QListViewItemIterator lvit( edituserDialog->groupsListView ); // Compare to all groups. for ( ; lvit.current(); ++lvit ) { if(lvit.current()->text(0)==(*it).left((*it).find(":"))) { temp=(QCheckListItem*)lvit.current(); temp->setOn(true); // If we find a line with that groupname, select it.; } } } if(!(edituserDialog->exec())) return false; // SHOW THE DIALOG! accounts->findUser(username); // Fill user variables in 'acccounts' object. accounts->pw_name=edituserDialog->loginLineEdit->text(); // Has the password been changed ? Make a new "crypt":ed password. if(edituserDialog->passwordLineEdit->text()!="........") accounts->pw_passwd=crypt(edituserDialog->passwordLineEdit->text(), accounts->crypt_make_salt()); // Set all variables in accounts object, that will be used when calling 'updateUser()' accounts->pw_uid=edituserDialog->uidLineEdit->text().toInt(); - accounts->findGroup(edituserDialog->groupComboBox->currentText()); // Fill all group variables in 'accounts' object. - accounts->pw_gid=accounts->gr_gid; + if(accounts->findGroup(edituserDialog->groupComboBox->currentText())) { // Fill all group variables in 'accounts' object. + accounts->pw_gid=accounts->gr_gid; // Only do this if the group is a valid group (ie. "<Undefined group>"), otherwise keep the old group. + } accounts->pw_gecos=edituserDialog->gecosLineEdit->text(); accounts->pw_shell=edituserDialog->shellComboBox->currentText(); // Update userinfo, using the information stored in the user variables stored in the accounts object. accounts->updateUser(username); // Remove user from all groups he/she is a member of. (could be done in a better way I guess, this was simple though.) for(QStringList::Iterator it=tempList.begin(); it!=tempList.end(); ++it) { accounts->delGroupMember((*it).left((*it).find(":")),username); } // Add User to additional groups that he/she is a member of. QListViewItemIterator it( edituserDialog->groupsListView ); for ( ; it.current(); ++it ) { temp=(QCheckListItem*)it.current(); if ( temp->isOn() ) accounts->addGroupMember(it.current()->text(0),edituserDialog->loginLineEdit->text()); } // Copy image to pics/users/ if(!(edituserDialog->userImage.isNull())) { QDir d; if(!(d.exists("/opt/QtPalmtop/pics/users"))) { d.mkdir("/opt/QtPalmtop/pics/users"); } QString filename="/opt/QtPalmtop/pics/users/"+accounts->pw_name+".png"; // edituserDialog->userImage=edituserDialog->userImage.smoothScale(48,48); edituserDialog->userImage.save(filename,"PNG"); } return true; } /** * "OK" has been clicked. Verify some information before closing the dialog. * */ void UserDialog::accept() { // Add checking... valid username? username taken? if(loginLineEdit->text().isEmpty()) { QMessageBox::information(0,"Empty Login","Please enter a login."); return; } QDialog::accept(); } /** * This slot is called when the usericon is clicked, this loads (should) the iconselector. * */ diff --git a/noncore/settings/usermanager/userdialog.h b/noncore/settings/usermanager/userdialog.h index a878588..133b35d 100644 --- a/noncore/settings/usermanager/userdialog.h +++ b/noncore/settings/usermanager/userdialog.h @@ -1,58 +1,61 @@ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef USERDIALOG_H #define USERDIALOG_H #include <qdialog.h> #include <qlineedit.h> #include <qcombobox.h> #include <qlistview.h> #include <qtabwidget.h> #include <qpushbutton.h> +#include <qcheckbox.h> #include <qpe/resource.h> #include <opie/ofiledialog.h> class UserDialog : public QDialog { Q_OBJECT private: QTabWidget *myTabWidget; QPushButton *picturePushButton; QLineEdit *loginLineEdit; QLineEdit *uidLineEdit; QLineEdit *gecosLineEdit; QLineEdit *passwordLineEdit; QComboBox *shellComboBox; QComboBox *groupComboBox; + QLabel *skelLabel; + QCheckBox *skelCheckBox; QListView *groupsListView; QStringList groupMembers; QString pictureLocation; QImage userImage; int groupID; int userID; void setupTab1(void); void setupTab2(void); void accept(void); private slots: void clickedPicture(void); public: UserDialog( QWidget* parent = 0, const char* name = 0, bool modal=true, WFlags fl = 0 ); ~UserDialog(); static bool addUser(int uid, int gid); static bool editUser(const char *username); static bool delUser(const char *username); }; #endif diff --git a/noncore/settings/usermanager/usermanager.cpp b/noncore/settings/usermanager/usermanager.cpp index 2735e6a..57efa71 100644 --- a/noncore/settings/usermanager/usermanager.cpp +++ b/noncore/settings/usermanager/usermanager.cpp @@ -9,119 +9,122 @@ #include "usermanager.h" #include <qlayout.h> #include <stdio.h> #include <qmessagebox.h> #include <qfile.h> #include <qpe/resource.h> #include <qregexp.h> /** * The mainwindow constructor. * * @param QWidget *parent * @param const char *name * @ param WFlags fl * */ UserConfig::UserConfig(QWidget* parent, const char* name, WFlags fl) : QMainWindow(parent, name, fl) { setCaption(tr("OPIE User Manager")); // Create an instance of the global object 'accounts'. This holds all user/group info, and functions to modify them. accounts=new Passwd(); accounts->open(); // This actually loads the files /etc/passwd & /etc/group into memory. // Create the toolbar. QPEToolBar *toolbar = new QPEToolBar(this,"Toolbar"); toolbar->setHorizontalStretchable(1); // Is there any other way to get the toolbar to stretch of the full screen!? adduserToolButton = new QToolButton(Resource::loadPixmap("usermanager/adduser"),"Add User",0,this,SLOT(addUser()),toolbar,"Add User"); edituserToolButton = new QToolButton(Resource::loadPixmap("usermanager/edituser"),"Edit User",0,this,SLOT(editUser()),toolbar,"Edit User"); deleteuserToolButton = new QToolButton(Resource::loadPixmap("usermanager/deleteuser"),"Delete User",0,this,SLOT(delUser()),toolbar,"Delete User"); QToolButton *userstext = new QToolButton(0,"User",0,0,0,toolbar,"User"); userstext->setUsesTextLabel(true); toolbar->addSeparator(); addgroupToolButton = new QToolButton(Resource::loadPixmap("usermanager/addgroup"),"Add Group",0,this,SLOT(addGroup()),toolbar,"Add Group"); editgroupToolButton = new QToolButton(Resource::loadPixmap("usermanager/editgroup"),"Edit Group",0,this,SLOT(editGroup()),toolbar,"Edit Group"); deletegroupToolButton = new QToolButton(Resource::loadPixmap("usermanager/deletegroup"),"Delete Group",0,this,SLOT(delGroup()),toolbar,"Delete Group"); QToolButton *groupstext = new QToolButton(0,"Group",0,0,0,toolbar,"Group"); groupstext->setUsesTextLabel(true); addToolBar(toolbar,"myToolBar"); // Add a tabwidget and all the tabs. myTabWidget = new QTabWidget(this,"My Tab Widget"); setupTabAccounts(); setupTabAllUsers(); setupTabAllGroups(); + userPopupMenu.insertItem("Copy",0); getUsers(); // Fill out the iconview & listview with all users. getGroups(); // Fill out the group listview with all groups. setCentralWidget(myTabWidget); } UserConfig::~UserConfig() { accounts->close(); delete accounts; } void UserConfig::setupTabAccounts() { QWidget *tabpage = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(tabpage); layout->setMargin(5); usersIconView=new QListView(tabpage,"users"); usersIconView->addColumn("Icon"); usersIconView->addColumn("Username"); usersIconView->setAllColumnsShowFocus(true); layout->addWidget(usersIconView); + connect(usersIconView,SIGNAL(returnPressed(QListViewItem *)),this,SLOT(showUserMenu(QListViewItem *))); + myTabWidget->addTab(tabpage,"Users"); } void UserConfig::setupTabAllUsers() { QWidget *tabpage = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(tabpage); layout->setMargin(5); usersListView=new QListView(tabpage,"allusers"); usersListView->addColumn("UID"); usersListView->addColumn("Login"); usersListView->addColumn("Username"); layout->addWidget(usersListView); usersListView->setSorting(1,1); usersListView->setAllColumnsShowFocus(true); myTabWidget->addTab(tabpage,"All Users"); } void UserConfig::setupTabAllGroups() { QWidget *tabpage = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(tabpage); layout->setMargin(5); groupsListView=new QListView(tabpage,"groups"); groupsListView->addColumn("GID"); groupsListView->addColumn("Groupname"); layout->addWidget(groupsListView); groupsListView->setSorting(1,1); groupsListView->setAllColumnsShowFocus(true); myTabWidget->addTab(tabpage,"All Groups"); } void UserConfig::getUsers() { QString mytext; QPixmap mypixmap; QListViewItem *listviewitem; // Empty the iconview & the listview. usersIconView->clear(); usersListView->clear(); // availableUID is used as a deposite for the next available UID on the system, this should start at an ID over 500. availableUID=500; for(QStringList::Iterator it=accounts->passwdStringList.begin(); it!=accounts->passwdStringList.end(); ++it) { accounts->splitPasswdEntry(*it); // Split the string into it's components and store in variables in the accounts object. ("pr_name" and so on.) new QListViewItem(usersListView,QString::number(accounts->pw_uid),accounts->pw_name,accounts->pw_gecos); if((accounts->pw_uid>=500) && (accounts->pw_uid<65000)) { // Is this user a "normal" user ? @@ -199,48 +202,53 @@ void UserConfig::delUser() { // Update views. getUsers(); getGroups(); } } } else { QMessageBox::information(this,"No selection","No user has been selected."); } } } void UserConfig::getGroups() { groupsListView->clear(); // Empty the listview. availableGID=500; // We need to find the next free GID, and are only interested in values between 500 & 65000. for(QStringList::Iterator it=accounts->groupStringList.begin(); it!=accounts->groupStringList.end(); ++it) { // Split the list into lines. accounts->splitGroupEntry(*it); // Split the line into its components and fill the variables of 'accounts'. (gr_name, gr_uid & gr_mem). new QListViewItem(groupsListView,QString::number(accounts->gr_gid),accounts->gr_name); if((accounts->gr_gid>=availableGID) && (accounts->gr_gid<65000)) availableGID=accounts->gr_gid+1; // Maybe a new free GID. } } void UserConfig::addGroup() { if(GroupDialog::addGroup(availableGID)) getGroups(); // Bring up the add group dialog. } void UserConfig::editGroup() { int gid; if(groupsListView->currentItem()) { // Any group selected? gid=groupsListView->currentItem()->text(0).toInt(); // Get the GID from the listview. if(GroupDialog::editGroup(gid)) getGroups(); // Bring up the edit group dialog. } else { QMessageBox::information(this,"No selection","No group has been selected."); } } void UserConfig::delGroup() { const char *groupname; if(groupsListView->currentItem()) { // Any group selected? groupname=groupsListView->currentItem()->text(1); // Get the groupname from the listview. if(QMessageBox::warning(this,"Delete group","Are you sure you want to\ndelete the group \""+QString(groupname)+"\" ?","&No","&Yes",0,0,1)) { // If confirmed, try to delete the group. if(GroupDialog::delGroup(groupname)) getGroups(); // And also update the view afterwards if the user was deleted. } } else { QMessageBox::information(this,"No selection","No group has been selected."); } } + +void UserConfig::showUserMenu(QListViewItem *item) { +// userPopupMenu.exec(item->mapToGlobal(QPoint(0,0))); + qWarning("Pressed!"); +} diff --git a/noncore/settings/usermanager/usermanager.h b/noncore/settings/usermanager/usermanager.h index 9909242..6782923 100644 --- a/noncore/settings/usermanager/usermanager.h +++ b/noncore/settings/usermanager/usermanager.h @@ -1,65 +1,66 @@ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef USERCONFIG_H #define USERCONFIG_H #include <qmainwindow.h> #include <qtabwidget.h> #include <qlistview.h> -//#include <qiconview.h> - -#include <qpe/qpemenubar.h> #include <qpopupmenu.h> -#include <qpe/qpetoolbar.h> #include <qtoolbutton.h> +#include <qpe/qpetoolbar.h> + #include "userdialog.h" #include "groupdialog.h" #include "passwd.h" class UserConfig : public QMainWindow { Q_OBJECT public: UserConfig( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); ~UserConfig(); private: QToolButton *adduserToolButton; QToolButton *edituserToolButton; QToolButton *deleteuserToolButton; QToolButton *addgroupToolButton; QToolButton *editgroupToolButton; QToolButton *deletegroupToolButton; QTabWidget *myTabWidget; QListView *usersIconView; QListView *usersListView; QListView *groupsListView; + QPopupMenu userPopupMenu; + QPopupMenu groupPopupMenu; int availableUID; int availableGID; void setupTabAccounts(); void setupTabAllUsers(); void setupTabAllGroups(); void setupTabPrefs(); void setupTabAbout(); void getUsers(); void getGroups(); private slots: void addUser(); void editUser(); void delUser(); void addGroup(); void editGroup(); void delGroup(); + void showUserMenu(QListViewItem *item); }; #endif // USERCONFIG_H |