summaryrefslogtreecommitdiffstats
path: root/lilo-config/common
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit37333bf25ad9a4c538250f5af2f9f1d666362883 (patch)
treec45e8df5b9efbffe07eb3d9340df7811c7e16943 /lilo-config/common
downloadtdeadmin-37333bf25ad9a4c538250f5af2f9f1d666362883.tar.gz
tdeadmin-37333bf25ad9a4c538250f5af2f9f1d666362883.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeadmin@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lilo-config/common')
-rw-r--r--lilo-config/common/Config.cc66
-rw-r--r--lilo-config/common/Config.h40
-rw-r--r--lilo-config/common/Disks.cc294
-rw-r--r--lilo-config/common/Disks.h49
-rw-r--r--lilo-config/common/Files.cc70
-rw-r--r--lilo-config/common/Files.h47
-rw-r--r--lilo-config/common/Makefile.am11
-rw-r--r--lilo-config/common/String.cc437
-rw-r--r--lilo-config/common/String.h96
-rw-r--r--lilo-config/common/lilo.cc585
-rw-r--r--lilo-config/common/lilo.h77
-rw-r--r--lilo-config/common/tests/Makefile.am9
-rw-r--r--lilo-config/common/tests/String.cc77
13 files changed, 1858 insertions, 0 deletions
diff --git a/lilo-config/common/Config.cc b/lilo-config/common/Config.cc
new file mode 100644
index 0000000..37921ba
--- /dev/null
+++ b/lilo-config/common/Config.cc
@@ -0,0 +1,66 @@
+/* Config.cc
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#include "Config.h"
+void ConfigFile::set(String const &key, String const &value, bool const &quote, bool const &removeIfEmpty, String const &prefix)
+{
+ String re="[ \t]*" + key + "[ \t]*=";
+ String s=grep(re);
+ if(value.empty() && removeIfEmpty) {
+ if(!s.empty())
+ remove(s);
+ } else if(s.empty()) {
+ if(quote)
+ insert(end(), prefix + key + "=\"" + value + "\"");
+ else
+ insert(end(), prefix + key + "=" + value);
+ } else {
+ for(iterator it=begin(); it!=end(); it++)
+ if(!(*it).regex(re).empty()) {
+ if(quote)
+ (*it)=prefix + key + "=\"" + value +"\"";
+ else
+ (*it)=prefix + key + "=" + value;
+ break;
+ }
+ }
+}
+String const ConfigFile::get(String const &key, String const &dflt, bool const &unquote)
+{
+ String s=grep("[ \t]*" + key + "[ \t]*=").simplifyWhiteSpace();
+ if(s.empty())
+ return dflt;
+ s=s.mid(s.locate("=")+2).simplifyWhiteSpace();
+ if(unquote) {
+ if(s.chr(0)=='"')
+ s=s.mid(2);
+ if(s.chr(s.size()-1)=='"')
+ s=s.left(s.size()-1);
+ }
+ return s.simplifyWhiteSpace();
+}
diff --git a/lilo-config/common/Config.h b/lilo-config/common/Config.h
new file mode 100644
index 0000000..6ac6334
--- /dev/null
+++ b/lilo-config/common/Config.h
@@ -0,0 +1,40 @@
+/* Config.h
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#ifndef _CONFIGFILE_H_
+#define _CONFIGFILE_H_ 1
+
+#include "String.h"
+class ConfigFile:public StringList
+{
+public:
+ void set(String const &key, String const &value, bool const &quote=true, bool const &removeIfEmpty=true, String const &prefix="");
+ String const get(String const &key, String const &dflt="", bool const &unquote=true);
+};
+
+#endif
diff --git a/lilo-config/common/Disks.cc b/lilo-config/common/Disks.cc
new file mode 100644
index 0000000..b4a417d
--- /dev/null
+++ b/lilo-config/common/Disks.cc
@@ -0,0 +1,294 @@
+/* Disks.cc
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#include "Disks.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+StringList ptable::disklist()
+{
+ /* The basics behind scanning for a disk are simple: If it can be *
+ * opened, it exists. *
+ * Using access() is not sufficient - that's successful if the device *
+ * node exists but there's no actual device. *
+ * Checking /proc/devices would work, but it wouldn't autoload modules*
+ * so chances are we'd be missing something. */
+ StringList dsk;
+ int fd;
+ bool finished=false;
+ #define CHECK_DEV(d) if((fd=open(d, O_RDONLY))<0) { \
+ finished=true; \
+ continue; \
+ } \
+ close(fd); \
+ dsk+=d
+ String dev="/dev/hd"; // IDE devices: /dev/hd[a-t]
+ for(char a='a'; a<='t'; a++) {
+ // We can't use finished for IDE drives - it's perfectly OK
+ // to have a /dev/hdc but no /dev/hdb.
+ CHECK_DEV(dev+a);
+ }
+ finished=false;
+ dev="/dev/sd"; // SCSI disks 0-25
+ for(char a='a'; a<='z' && !finished; a++) {
+ CHECK_DEV(dev+a);
+ }
+ for(char prefix='a'; prefix <='d' && !finished; prefix++) {
+ dev="/dev/sd" + prefix; // SCSI disks 26-127
+ for(char a='a'; (a<='x' || (a<='z' && prefix<'d')) && !finished; a++) {
+ CHECK_DEV(dev+a);
+ }
+ }
+ finished=false;
+ dev="/dev/i2o/hd"; // I2O disks 0-25: /dev/i2o/hd[a-z]
+ for(char a='a'; a<='z' && !finished; a++) {
+ CHECK_DEV(dev+a);
+ }
+ for(char prefix='a'; prefix <='d' && !finished; prefix++) {
+ dev="/dev/i2o/hd" + prefix; // I2O disks 26-127
+ for(char a='a'; (a<='x' || (a<='z' && prefix<'d')) && !finished; a++) {
+ CHECK_DEV(dev+a);
+ }
+ }
+ finished=false;
+ dev="/dev/pd"; // Parallel port disks: /dev/pd[a-d]
+ for(char a='a'; a<='d' && !finished; a++) {
+ CHECK_DEV(dev+a);
+ }
+ finished=false;
+ for(unsigned int i=0; i<=31 && !finished; i++) { // Software RAID
+ String device;
+ device.sprintf("/dev/md%u", i);
+ CHECK_DEV(device);
+ }
+ finished=false;
+ for(unsigned int i=0; i<=7; i++) { //Compaq Smart Array
+ for(unsigned int j=0; j<=15 && !finished; j++) {
+ String device;
+ device.sprintf("/dev/ida/c%ud%u", i, j);
+ CHECK_DEV(device);
+ }
+ }
+ finished=false;
+ for(unsigned int i=0; i<=7; i++) { // Mylex DAC960
+ for(unsigned int j=0; j<=31 && !finished; j++) {
+ String device;
+ device.sprintf("/dev/rd/c%ud%u", i, j);
+ CHECK_DEV(device);
+ }
+ }
+ finished=false;
+ dev="/dev/ed"; // MCA ESDI harddisks: /dev/ed[ab]
+ for(char a='a'; a<='b' && !finished; a++) {
+ CHECK_DEV(dev+a);
+ }
+ finished=false;
+ dev="/dev/xd"; // XT (8-bit) harddisks: /dev/xd[ab]
+ for(char a='a'; a<='b' && !finished; a++) {
+ CHECK_DEV(dev+a);
+ }
+ return dsk;
+}
+StringList ptable::partlist()
+{
+ StringList s;
+ StringList d=disklist();
+ for(StringList::const_iterator it=d.begin(); it!=d.end(); it++) {
+ for(int i=1; i<32; i++) {
+ String drive;
+ drive.sprintf("%s%u", (*it).cstr(), i);
+ int fd=open(drive, O_RDONLY);
+ if(fd>=0) {
+ char test;
+ if(read(fd, &test, 1)>0)
+ s += drive;
+ close(fd);
+ } else
+ break;
+ }
+ }
+ return s;
+}
+ptable::ptable(StringList const &disks)
+{
+ partition.clear();
+ id.clear();
+ mountpt.clear();
+ for(StringList::const_iterator it=disks.begin(); it!=disks.end(); it++)
+ scandisk(*it);
+}
+ptable::ptable(String const &disk)
+{
+ partition.clear();
+ id.clear();
+ mountpt.clear();
+ scandisk(disk);
+}
+void ptable::scandisk(String const &disk)
+{
+ String cmd;
+ cmd.sprintf("fdisk -l %s 2>&1", (char*)disk);
+ FILE *fdisk=popen(cmd, "r");
+ char *buf=(char *) malloc(1024);
+ String dev;
+ while(fgets(buf, 1024, fdisk)) {
+ if(strncmp("/dev/", buf, 5)==0) { // Partition entry
+ // We don't care about active vs. non-active partitions.
+ // Remove the sign.
+ while(strchr(buf, '*')) *strchr(buf, '*')=' ';
+ // blanks are blanks...
+ while(strchr(buf, '\t')) *strchr(buf, '\t')=' ';
+ // Get the device
+ *strchr(buf, ' ')=0;
+ dev=buf;
+ partition += buf;
+ // And figure out where/if it's mounted
+ mountpt[dev]=mountpoint(dev);
+ // Lastly, get the partition type.
+ strcpy(buf, buf+strlen(buf)+1);
+ while(isspace(*buf)) strcpy(buf, buf+1);
+ strcpy(buf, strchr(buf, ' ')); // skip Start
+ while(isspace(*buf)) strcpy(buf, buf+1);
+ strcpy(buf, strchr(buf, ' ')); // skip End
+ while(isspace(*buf)) strcpy(buf, buf+1);
+ strcpy(buf, strchr(buf, ' ')); // skip Blocks
+ while(isspace(*buf)) strcpy(buf, buf+1);
+ id[dev]=strtol(buf, NULL, 16);
+ }
+ }
+ pclose(fdisk);
+ free(buf);
+}
+String ptable::mountpoint(String const &device, bool fstab_fallback)
+{
+ char *buf=new char[1024];
+ FILE *f=fopen("/etc/mtab", "r");
+ String mp="";
+ while(fgets(buf, 1024, f)) {
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ if(device.cmp(buf)) {
+ strcpy(buf, buf+strlen(buf)+1);
+ while(isspace(*buf))
+ strcpy(buf, buf+1);
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ mp=buf;
+ mp=mp.simplifyWhiteSpace();
+ break;
+ }
+ }
+ fclose(f);
+ if(mp.empty() && fstab_fallback) {
+ f=fopen("/etc/fstab", "r");
+ while(fgets(buf, 1024, f)) {
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ if(device.cmp(buf)) {
+ strcpy(buf, buf+strlen(buf)+1);
+ while(isspace(*buf))
+ strcpy(buf, buf+1);
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ mp=buf;
+ mp=mp.simplifyWhiteSpace();
+ break;
+ }
+ }
+ fclose(f);
+ }
+ delete buf;
+ return mp;
+}
+String ptable::device(String const &mountpt, bool fstab_fallback)
+{
+ char *buf=new char[1024];
+ FILE *f=fopen("/etc/mtab", "r");
+ String dev="";
+ while(fgets(buf, 1024, f)) {
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ String device=buf;
+ strcpy(buf, buf+strlen(buf)+1);
+ while(isspace(*buf))
+ strcpy(buf, buf+1);
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ String mp=buf;
+ mp=mp.simplifyWhiteSpace();
+ if(mp==mountpt) {
+ dev=device;
+ break;
+ }
+ }
+ fclose(f);
+
+ if(dev.empty() && fstab_fallback) {
+ // The FS is not mounted - maybe it could be, though.
+ f=fopen("/etc/fstab", "r");
+ while(fgets(buf, 1024, f)) {
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ String device=buf;
+ strcpy(buf, buf+strlen(buf)+1);
+ while(isspace(*buf))
+ strcpy(buf, buf+1);
+ if(strchr(buf,' '))
+ *strchr(buf, ' ')=0;
+ if(strchr(buf,'\t'))
+ *strchr(buf, '\t')=0;
+ String mp=buf;
+ mp=mp.simplifyWhiteSpace();
+ if(mp==mountpt) {
+ dev=device;
+ break;
+ }
+ }
+ fclose(f);
+ }
+ delete buf;
+ return dev;
+}
diff --git a/lilo-config/common/Disks.h b/lilo-config/common/Disks.h
new file mode 100644
index 0000000..8965694
--- /dev/null
+++ b/lilo-config/common/Disks.h
@@ -0,0 +1,49 @@
+/* Disks.h
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#ifndef _DISKS_H_
+#define _DISKS_H_ 1
+#include "String.h"
+#include <list>
+#include <map>
+class ptable {
+public:
+ ptable(StringList const &disks=disklist());
+ ptable(String const &disk);
+ static StringList disklist();
+ static StringList partlist();
+ static String mountpoint(String const &device, bool fstab_fallback=false);
+ static String device(String const &mountpt, bool fstab_fallback=false);
+protected:
+ void scandisk(String const &disk);
+public:
+ StringList partition;
+ std::map<String,int> id;
+ std::map<String,String> mountpt;
+};
+#endif
diff --git a/lilo-config/common/Files.cc b/lilo-config/common/Files.cc
new file mode 100644
index 0000000..19af29d
--- /dev/null
+++ b/lilo-config/common/Files.cc
@@ -0,0 +1,70 @@
+/* Files.cc
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#include "Files.h"
+#include <glob.h>
+#include <sys/stat.h>
+#define ISSET(x,y) ((x&y)==y)
+StringList &Files::glob(String name, enum Types types, bool dotfiles, bool braces)
+{
+ glob_t gl;
+ int flags=0;
+ StringList *result;
+ if(dotfiles)
+ flags |= GLOB_PERIOD;
+ if(braces)
+ flags |= GLOB_BRACE;
+ ::glob(name, flags, NULL, &gl);
+ if(types==Any)
+ result=new StringList(gl.gl_pathv, gl.gl_pathc);
+ else {
+ struct stat s;
+ result=new StringList;
+ for(unsigned int i=0; i<gl.gl_pathc; i++) {
+ if(!lstat(gl.gl_pathv[i], &s)) {
+ if(S_ISLNK(s.st_mode) && !ISSET(types,Link))
+ continue;
+ if(S_ISREG(s.st_mode) && !ISSET(types,File))
+ continue;
+ if(S_ISDIR(s.st_mode) && !ISSET(types,Dir))
+ continue;
+ if(S_ISCHR(s.st_mode) && !ISSET(types,CharDevice))
+ continue;
+ if(S_ISBLK(s.st_mode) && !ISSET(types,BlockDevice))
+ continue;
+ if(S_ISFIFO(s.st_mode) && !ISSET(types,Fifo))
+ continue;
+ if(S_ISSOCK(s.st_mode) && !ISSET(types,Socket))
+ continue;
+ result->insert(result->end(), gl.gl_pathv[i]);
+ }
+ }
+ }
+ globfree(&gl);
+ return *result;
+}
diff --git a/lilo-config/common/Files.h b/lilo-config/common/Files.h
new file mode 100644
index 0000000..ad1fa3b
--- /dev/null
+++ b/lilo-config/common/Files.h
@@ -0,0 +1,47 @@
+/* Files.h
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#ifndef _FILES_H_
+#define _FILES_H_ 1
+#include "String.h"
+class Files {
+public:
+ enum Types { File = 0x1,
+ Dir = 0x2,
+ Link = 0x4,
+ CharDevice = 0x8,
+ BlockDevice= 0x10,
+ Device = CharDevice | BlockDevice,
+ Fifo = 0x20,
+ Socket = 0x40,
+ All = File | Dir | Link | Device | Fifo | Socket,
+ Any = All
+ };
+ static StringList &glob(String name, enum Types types=All, bool dotfiles=true, bool braces=true);
+};
+#endif
diff --git a/lilo-config/common/Makefile.am b/lilo-config/common/Makefile.am
new file mode 100644
index 0000000..37b44eb
--- /dev/null
+++ b/lilo-config/common/Makefile.am
@@ -0,0 +1,11 @@
+# SUBDIRS = tests
+
+noinst_LTLIBRARIES = libcommon.la
+INCLUDES = $(all_includes)
+
+noinst_HEADERS = \
+ String.h Files.h Disks.h Config.h lilo.h
+
+libcommon_la_SOURCES = \
+ String.cc Files.cc Disks.cc Config.cc lilo.cc
+
diff --git a/lilo-config/common/String.cc b/lilo-config/common/String.cc
new file mode 100644
index 0000000..f8a0e35
--- /dev/null
+++ b/lilo-config/common/String.cc
@@ -0,0 +1,437 @@
+/* String.cc
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#define _GNU_SOURCE 1
+#include <features.h>
+#include <string.h>
+#include <string>
+#include "String.h"
+#include <stdio.h>
+#include <regex.h>
+#include <stdlib.h>
+
+using namespace std;
+
+void String::sprintf(const char *format, ...)
+{
+ va_list arg;
+ va_start(arg, format);
+ char *buf=0;
+ int size=vsnprintf(buf, 0, format, arg);
+ if(size==-1) { /* ARGH!!! */
+ cerr << "WARNING: Your C library (libc) does not conform to the ISO C99 standard!" << endl << "Consider upgrading to glibc 2.1 or higher!" << endl;
+ int bufsiz=1024;
+ while(size==-1) {
+ buf=(char *) malloc(bufsiz);
+ size=vsnprintf(buf, 0, format, arg);
+ bufsiz+=1024;
+ free(buf);
+ }
+ }
+ buf=(char *) malloc(size+1);
+ vsnprintf(buf, size+1, format, arg);
+ string str=buf;
+ *this=buf;
+ va_end(arg);
+ free(buf);
+ return;
+}
+bool String::readfile(String filename)
+{
+ FILE *f=fopen(filename, "r");
+ if(!f)
+ return false;
+
+ string str="";
+ char *buf=(char *) malloc(1024);
+ while(!feof(f) && !ferror(f)) {
+ if(!fgets(buf, 1024, f))
+ continue;
+ str += buf;
+ };
+ *this=buf;
+ free(buf);
+ fclose(f);
+ return true;
+}
+char *String::cstr() const
+{
+ char *a=new char[size()+1];
+ a[size()]=0;
+ strncpy(a, data(), size());
+ return a;
+}
+bool String::cmp(char const * const s) const
+{
+ if(size() != strlen(s))
+ return false;
+ return (strncmp(data(), s, size())==0);
+}
+bool String::casecmp(char const * const s) const
+{
+ if(size() != strlen(s))
+ return false;
+ return (strncasecmp(data(), s, size())==0);
+}
+bool String::contains(String const &s, bool cs) const
+{
+ if(cs)
+ if(strstr(cstr(), s.cstr()))
+ return true;
+ else
+ return false;
+ else
+ if(strcasestr(cstr(), s.cstr()))
+ return true;
+ else
+ return false;
+}
+int String::locate(String const &s, bool cs, unsigned int startat) const
+{
+ if(startat>=size())
+ return -1;
+
+ char *s0=cstr(), *s1=s.cstr(), *s2;
+ int r;
+ if(cs)
+ s2=strstr(s0+startat, s1);
+ else
+ s2=strcasestr(s0+startat, s1);
+ if(s2==NULL) {
+ delete [] s0;
+ delete [] s1;
+ return -1;
+ }
+ r=(s2-s0);
+ if(startat>0) r++;
+ delete [] s0;
+ delete [] s1;
+ return r;
+}
+String const String::operator +(char const &s) {
+ char a[2];
+ a[0]=s;
+ a[1]=0;
+ String st=cstr();
+ st+=a;
+ return st;
+}
+String const String::operator +(char const * const s) {
+ String st=cstr();
+ st += s;
+ return st;
+}
+bool String::operator ==(char s) {
+ if(size()==1 && cstr()[0]==s)
+ return true;
+ else
+ return false;
+}
+bool String::operator !=(char s) {
+ if(size()!=1 || cstr()[0]!=s)
+ return true;
+ else
+ return false;
+}
+String String::simplifyWhiteSpace() const {
+ char *s=cstr();
+ for(unsigned int i=0; i<size(); i++)
+ if(isspace(s[i]))
+ s[i]=' ';
+ while(*s==' ')
+ strcpy(s, s+1);
+ int l = strlen(s);
+ while(l && (s[l-1]==' '))
+ s[--l]=0;
+
+ while(strstr(s, " "))
+ strcpy(strstr(s, " "), strstr(s, " ")+1);
+ return s;
+}
+String String::left(unsigned int num) const
+{
+ if(num==0) return "";
+ char *s=cstr();
+ if(size()<=num)
+ return s;
+ s[num]=0;
+ return s;
+}
+String String::right(unsigned int num) const
+{
+ if(num==0) return "";
+ char *s=cstr();
+ if(size()<=num)
+ return s;
+ strcpy(s, s+strlen(s)-num);
+ return s;
+}
+String String::mid(unsigned int start, unsigned int num) const
+{
+ if(start>=size())
+ return "";
+ char *s=cstr();
+ start--;
+ if(start>0)
+ strcpy(s, s+start);
+ if(num>0 && num<=strlen(s))
+ s[num]=0;
+ return s;
+}
+String &String::regex(String const &expr, bool cs) const
+{
+ regex_t regexp;
+ int err;
+ regmatch_t reg[1];
+ String *ret=new String("");
+ if((err=regcomp(&regexp, expr, cs?REG_EXTENDED:REG_EXTENDED|REG_ICASE))) {
+ regfree(&regexp);
+ return *ret;
+ }
+ err=regexec(&regexp, cstr(), 1, reg, 0);
+ regfree(&regexp);
+ if(err)
+ return *ret;
+ if(reg[0].rm_so!=-1) {
+ char *s=strdup(cstr()+reg[0].rm_so);
+ s[reg[0].rm_eo-reg[0].rm_so]=0;
+ delete ret;
+ ret=new String(s);
+ free(s);
+ }
+ return *ret;
+}
+String &String::replace(String const &what, String const &with, bool all) const
+{
+ String *result;
+ if(!contains(what)) {
+ result=new String(*this);
+ return *result;
+ }
+ result=new String;
+ *result=left(locate(what));
+ *result+=with;
+ if(!all) {
+ *result+=right(size()-locate(what)-what.size());
+ } else {
+ unsigned int start=locate(what)+what.size()+1;
+ int loc;
+ while((loc=locate(what, true, start+1))!=-1) {
+ *result+=mid(start, loc-start);
+ *result+=with;
+ start=locate(what, true, start)+what.size();
+ }
+ if(size()>start)
+ *result+=right(size()-start+1);
+ }
+ return *result;
+}
+String String::escapeForRegExp(String const &s)
+{
+ static const char meta[] = "$()*+.?[\\]^{|}";
+ String quoted = s;
+ int i = 0;
+
+ while ( i < (int) quoted.length() ) {
+ if ( strchr(meta, quoted.at(i)) != 0 )
+ quoted.insert( i++, "\\" );
+ i++;
+ }
+ return quoted;
+}
+StringList::StringList(String const &s)
+{
+ clear();
+ char *st=strdup((char const * const)s);
+ char *tok;
+ char *line=strtok_r(st, "\n", &tok);
+ while(line) {
+ if(line[strlen(line)-1]=='\r') // Handle sucking OSes
+ line[strlen(line)-1]=0;
+ insert(end(), line);
+ line=strtok_r(NULL, "\n", &tok);
+ }
+ free(st);
+}
+
+StringList::StringList(char **strs, int num)
+{
+ clear();
+ if(num>=0) {
+ for(int i=0; i<num; i++)
+ insert(end(), strs[i]);
+ } else {
+ for(int i=0; strs[i]!=NULL; i++)
+ insert(end(), strs[i]);
+ }
+}
+
+bool StringList::readfile(String const &filename)
+{
+ clear();
+ FILE *f=fopen(filename, "r");
+ if(!f)
+ return false;
+ char *buf=(char *) malloc(1024);
+ while(!feof(f) && !ferror(f)) {
+ if(!fgets(buf, 1024, f))
+ continue;
+ while(strlen(buf) && (buf[strlen(buf)-1]=='\n' || buf[strlen(buf)-1]=='\r'))
+ buf[strlen(buf)-1]=0;
+ insert(end(), buf);
+ };
+ free(buf);
+ fclose(f);
+ return true;
+}
+bool StringList::writefile(String const &filename) const
+{
+ FILE *f=fopen(filename, "w");
+ if(!f)
+ return false;
+ for(const_iterator it=begin(); it!=end(); it++) {
+ fputs(*it, f);
+ fputs("\n", f);
+ }
+ fclose(f);
+ return true;
+}
+void StringList::operator +=(StringList const &s)
+{
+ for(const_iterator it=s.begin(); it!=s.end(); it++)
+ insert(end(), *it);
+}
+void StringList::operator +=(StringList const * const s)
+{
+ for(const_iterator it=s->begin(); it!=s->end(); it++)
+ insert(end(), *it);
+}
+bool StringList::contains(String const &s) const
+{
+ for(const_iterator it=begin(); it!=end(); it++)
+ if(*it == s)
+ return true;
+ return false;
+}
+void StringList::remove(String const &s)
+{
+ bool done=false;
+ for(iterator it=begin(); !done && it!=end(); it++)
+ if(*it==s) {
+ erase(it);
+ done=true;
+ }
+}
+String const &StringList::grep(String const &s) const
+{
+ for(const_iterator it=begin(); it!=end(); it++)
+ if(!(*it).regex(s).empty())
+ return *it;
+ String *r=new String;
+ return *r;
+}
+int __stringlist_compare(const void *a, const void *b)
+{
+ if(a==0 && b==0)
+ return 0;
+ else if(a==0)
+ return 1;
+ else if(b==0)
+ return -1;
+ else
+ return strcmp((const char *)a,(const char *)b);
+}
+int __stringlist_compare_noncs(const void *a, const void *b)
+{
+ if(a==0 && b==0)
+ return 0;
+ else if(a==0)
+ return 1;
+ else if(b==0)
+ return -1;
+ else
+ return strcasecmp((const char *)a,(const char *)b);
+}
+void StringList::sort(bool cs)
+{
+ unsigned int i=0, s=size();
+ char **strings=new char*[s];
+ for(const_iterator it=begin(); it!=end(); it++)
+ strings[i++]=(*it).cstr();
+ if(cs)
+ qsort(strings, s, sizeof(char*), __stringlist_compare);
+ else
+ qsort(strings, s, sizeof(char*), __stringlist_compare_noncs);
+ clear();
+ for(i=0; i<s; i++) {
+ insert(end(), strings[i]);
+ delete [] strings[i];
+ }
+ delete [] strings;
+}
+StringList::operator String() const
+{
+ String s="";
+ for(const_iterator it=begin(); it!=end(); it++) {
+ s+=(*it);
+ if(s.right()!=String("\n") && s.right()!=String("\r"))
+ s+="\n";
+ }
+ return s;
+}
+
+ostream &operator <<(ostream &os, String const &s)
+{
+ if(!s.empty())
+ os << (char const * const) s;
+ return os;
+}
+ostream &operator <<(ostream &os, String const *s)
+{
+ if(!s->empty())
+ os << (char const * const) *s;
+ return os;
+}
+ostream &operator <<(ostream &os, StringList const &s)
+{
+ for(StringList::const_iterator it=s.begin(); it!=s.end(); it++) {
+ os << *it;
+ if((*it).right()!=String("\n") && (*it).right()!=String("\r"))
+ os << endl;
+ }
+ return os;
+}
+ostream &operator <<(ostream &os, StringList const *s)
+{
+ for(StringList::const_iterator it=s->begin(); it!=s->end(); it++) {
+ os << *it;
+ if((*it).right()!=String("\n") && (*it).right()!=String("\r"))
+ os << endl;
+ }
+ return os;
+}
diff --git a/lilo-config/common/String.h b/lilo-config/common/String.h
new file mode 100644
index 0000000..7b12af5
--- /dev/null
+++ b/lilo-config/common/String.h
@@ -0,0 +1,96 @@
+/* String.h
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+/* Somewhat more sane string handling functions... *
+ * Should be portable, therefore we aren't simply using QString. */
+
+#ifndef _STRING_H_
+#define _STRING_H_ 1
+#include <string>
+#include <list>
+#include <iostream>
+#include <stdarg.h>
+
+class String;
+class StringList;
+
+typedef std::list<String> strlist;
+
+class String:public std::string {
+public:
+ String():std::string("") { }
+ String(char const * const &s):std::string(s) { }
+ String(std::string const &s):std::string(s) { }
+ String const operator +(char const &s);
+ String const operator +(char const * const s);
+ bool operator ==(char s);
+ bool operator !=(char s);
+ operator char * () const { return cstr(); }
+ char * cstr() const;
+ bool cmp(char const * const s) const;
+ bool casecmp(char const * const s) const;
+ bool contains(String const &s, bool cs=true) const;
+ int locate(String const &s, bool cs=true, unsigned int startat=0) const;
+ void sprintf(const char *format, ...);
+ bool readfile(String filename);
+ String simplifyWhiteSpace() const;
+ String left(unsigned int num=1) const;
+ String right(unsigned int num=1) const;
+ String mid(unsigned int start, unsigned int num=0) const;
+ String &regex(String const &expr, bool cs=true) const;
+ String &replace(String const &what, String const &with, bool all=true) const;
+ static String escapeForRegExp(String const &s);
+ char chr(unsigned int index) const { if(index>=size()) return 0; else return data()[index]; }
+ int length() const { return size(); } // For compatibility with QString
+ char const *latin1() const { return cstr(); } // For compatibility with QString
+};
+
+class StringList:public strlist {
+public:
+ StringList() { clear(); }
+ StringList(String const &s);
+ StringList(char **strs, int num=-1);
+ bool readfile(String const &filename);
+ bool writefile(String const &filename) const;
+ void operator +=(String const &s) { insert(end(), s); }
+ void operator +=(char const * const &s) { insert(end(), s); }
+ void operator +=(StringList const &s);
+ void operator +=(StringList const * const s);
+ operator String() const;
+ bool contains(String const &s) const;
+ void remove(String const &s);
+ void add(String const &s) { insert(end(), s); }
+ String const &grep(String const &s) const;
+ void sort(bool cs=true);
+};
+
+std::ostream &operator <<(std::ostream &os, String const &s);
+std::ostream &operator <<(std::ostream &os, String const *s);
+std::ostream &operator <<(std::ostream &os, StringList const &s);
+std::ostream &operator <<(std::ostream &os, StringList const *s);
+#endif
diff --git a/lilo-config/common/lilo.cc b/lilo-config/common/lilo.cc
new file mode 100644
index 0000000..6625f0d
--- /dev/null
+++ b/lilo-config/common/lilo.cc
@@ -0,0 +1,585 @@
+/* lilo.cc
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#include "lilo.h"
+#include "Disks.h"
+#include "Files.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <fstream>
+#include <string.h>
+
+using namespace std;
+
+bool liloimage::isLinux() const {
+ const_iterator it=begin();
+ if((*it).contains("image"))
+ return true;
+ else
+ return false;
+}
+
+liloimage *liloimages::find(String const &s) const
+{
+ String t = String::escapeForRegExp(s);
+
+ String regex="^[ \t]*label[ \t]*=[ \t]*\"?" + t + "\"?[ \t]*";
+ for(const_iterator it=begin(); it!=end(); it++) {
+ if(!(*it).grep(regex).empty())
+ return (liloimage*)&(*it);
+ }
+ return 0;
+}
+void liloimages::remove(String const &s)
+{
+ liloimage *i=find(s);
+ for(iterator it=begin(); it!=end(); it++)
+ if(*it==*i) {
+ erase(it);
+ break;
+ }
+}
+
+liloconf::liloconf(String const &filename)
+{
+ checked=false;
+ defaults.clear();
+ images.clear();
+ if(filename.empty()) {
+ probe();
+ } else {
+ StringList s;
+ if(s.readfile(filename))
+ set(s);
+ else
+ probe();
+ }
+}
+void liloconf::set(StringList const &s)
+{
+ defaults.clear();
+ images.clear();
+ checked=false;
+ bool inHeader=true;
+ bool start;
+ liloimage *image=0;
+ for(StringList::const_iterator it=s.begin(); it!=s.end(); it++) {
+ String s=*it;
+ start=false;
+ s=s.simplifyWhiteSpace();
+ if(s.empty())
+ continue;
+ if(s.left(5)==(String)"other" && (s.mid(6, 1)==' ' || s.mid(6, 1)=='=')) {
+ inHeader=false;
+ start=true;
+ }
+ if(s.left(5)==(String)"image" && (s.mid(6, 1)==' ' || s.mid(6, 1)=='=')) {
+ inHeader=false;
+ start=true;
+ }
+ if(inHeader) {
+ defaults+=*it;
+ } else if(start) {
+ if(image)
+ images.insert(images.end(), *image);
+ image=new liloimage;
+ *image += *it;
+ } else {
+ *image += *it;
+ }
+ }
+ if(image)
+ images.insert(images.end(), *image);
+}
+void liloconf::set(String const &s)
+{
+ set((StringList)s);
+}
+void liloconf::writeFile(String const &filename)
+{
+ ofstream f;
+ f.open(filename, ios::out);
+ f << *this << endl;
+ f.close();
+ chmod(filename, 0600);
+}
+bool liloconf::install(bool probeonly)
+{
+ char *lilotmp=strdup("/tmp/liloXXXXXX");
+ String command;
+ int fd=mkstemp(lilotmp);
+ // Unfortunately, gcc 3.1 and higher don't have ofstream::attach
+ // anymore. Pity, used to be immensely useful.
+ // f.attach(fd);
+ close(fd);
+ ofstream f(lilotmp, ios::out);
+ f << defaults << endl;
+ for(liloimages::iterator it=images.begin(); it!=images.end(); it++) {
+ f << *it << endl;
+ }
+ f.close();
+
+ if(probeonly)
+ command.sprintf("/sbin/lilo -v -t -C %s 2>&1", (char const * const)lilotmp);
+ else
+ command.sprintf("/sbin/lilo -v -C %s 2>&1", (char const * const)lilotmp);
+ output="";
+ FILE *lilo=popen(command, "r");
+ char *buf=(char *) malloc(1024);
+ while(fgets(buf, 1024, lilo))
+ output += buf;
+ free(buf);
+ ok=(pclose(lilo)==0);
+ unlink(lilotmp);
+ free(lilotmp);
+ checked=true;
+ return ok;
+}
+bool const liloconf::isOk()
+{
+ if(!checked)
+ check();
+ return ok;
+}
+String const liloconf::liloOut()
+{
+ if(!checked)
+ check();
+ return output;
+}
+bool liloconf::probe()
+{
+ ptable p;
+ StringList drives=p.disklist();
+ String const root=p.device("/", true);
+ checked=false;
+ defaults.clear();
+ images.clear();
+ /* Set some reasonable defaults... */
+ // Try to figure out the boot device first...
+ if(drives.contains("/dev/hda")) {
+ defaults += "boot=/dev/hda"; // 1st IDE/ATAPI harddisk
+ defaults += "lba32"; // otherwise it is assumed
+ }
+ else if(drives.contains("/dev/sda")) {
+ defaults += "boot=/dev/sda"; // 1st SCSI harddisk
+ defaults += "linear"; // some SCSI disks need this
+ } else if(drives.contains("/dev/i2o/hda"))
+ defaults += "boot=/dev/i2o/hda"; // 1st I2O harddisk
+ else if(drives.contains("/dev/eda"))
+ defaults += "boot=/dev/eda"; // 1st MCA ESDI harddisk
+ else if(drives.contains("/dev/pda"))
+ defaults += "boot=/dev/pda"; // 1st Parallel port IDE disk
+ else
+ defaults += "boot=Insert_your_boot_device_here"; // shouldn't happen
+ defaults += "prompt";
+ defaults += "timeout=50";
+ if(!access("/boot/message", F_OK))
+ defaults += "message=/boot/message";
+ defaults += "root=" + root;
+
+ /* Scan for available operating systems...
+ * The list of what to do for each partition type is based on my
+ * best guess. I don't have anything but Linux (Red Hat Linux 7.0),
+ * FreeBSD (5.0-CURRENT), OpenBSD (2.6), FreeDOS (some CVS snapshot)
+ * and DR-DOS (7.03), so anything else might be wrong.
+ * If you have any additions or corrections, please send them to
+ * bero@redhat.com.
+ */
+ // Scan for Linux kernels in the currently running system
+ // The following may or may not be specific to Red Hat Linux and
+ // similar distributions... If you're using a distribution that does
+ // things differently, tell me how it should be done there.
+ StringList files=Files::glob("/boot/*", Files::File);
+ for(StringList::iterator it=files.begin(); it!=files.end(); it++) {
+ struct stat s;
+ if(lstat(*it, &s)) // If we can't stat it, it can't be a kernel
+ continue;
+ if(s.st_size<131072) // if you managed to compile a kernel at less than 128k, you're cheating. ;)
+ continue;
+ if((*it).contains("System.map") || (*it).contains("initrd")) // definitely not a kernel
+ continue;
+ if((*it).contains("vmlinux")) {
+ // If the kernel exists both in compressed and in
+ // uncompressed form, ignore the uncompressed one.
+ String compr=(*it).replace("vmlinux", "vmlinuz");
+ if(!access(compr, F_OK))
+ continue;
+ }
+ String version=(*it).regex("(test-?|pre-?)?([0-9]\\.[0-9]\\.[0-9]+)(-?[0-9A-Za-z]+)*");
+ String label=version;
+ if(version.empty()) // not a recognized kernel
+ version="linux";
+
+ if (label.empty())
+ {
+ label = (*it);
+ if (label.find('/') != string::npos)
+ label = label.right(label.length()-1-label.rfind('/'));
+ }
+ // Check if we have an initial ramdisk (initrd) for this kernel...
+ String initrd1; // first guess
+ String initrd2; // second guess
+ if((*it).contains("vmlinuz")) {
+ initrd1=(*it).replace("vmlinux", "initrd")+".img";
+ initrd2=(*it).replace("vmlinuz", "initrd.img");
+ }
+ else if((*it).contains("vmlinux")) {
+ initrd1=(*it).replace("vmlinux", "initrd")+".img";
+ initrd2=(*it).replace("vmlinuz", "initrd.img");
+ }
+ else if((*it).contains("kernel")) {
+ initrd1=(*it).replace("kernel", "initrd")+".img";
+ initrd2=(*it).replace("vmlinuz", "initrd.img");
+ }
+ else if((*it).contains("linux")) {
+ initrd1=(*it).replace("linux", "initrd")+".img";
+ initrd2=(*it).replace("vmlinuz", "initrd.img");
+ }
+ else {
+ initrd1="/boot/initrd-"+version+".img";
+ initrd2="/boot/initrd.img-"+version;
+ }
+
+ String initrd = "";
+ if(!access(initrd1, F_OK))
+ initrd = initrd1;
+ else if(!access(initrd2, F_OK))
+ initrd = initrd2;
+
+ if(label.size()>15) // LILO can't handle this
+ if(label.contains("enterprise"))
+ label=label.replace("enterprise", "E");
+ if(label.size()>15)
+ label=label.left(15);
+
+ // label, kernel, root, initrd, optional, append, vga, readonly,
+ // literal, ramdisk
+ addLinux(label, *it, root, initrd);
+ }
+ addLinux("Linux_Compiled", "/usr/src/linux/arch/i386/boot/bzImage", root, "", true); // User-compiled kernel that wasn't moved...
+
+ // Scan for other OSes... and Linux kernels on other partitions.
+ for(StringList::iterator it=p.partition.begin(); it!=p.partition.end(); it++) {
+ switch(p.id[*it]) {
+ case 0x01: // FAT12... Might be some really really old DOS.
+ case 0x04: // FAT16 < 32 M... Probably another old DOS.
+ case 0x06: // FAT16
+ case 0x0b: // FAT32
+ case 0x0c: // FAT32 (LBA)
+ case 0x0e: // FAT16 (LBA)
+ case 0x14: // Hidden FAT16 < 32 M...
+ case 0x16: // Hidden FAT16
+ case 0x1b: // Hidden FAT32
+ case 0x1c: // Hidden FAT32 (LBA)
+ case 0x1e: // Hidden FAT16 (LBA)
+ case 0x24: // NEC DOS
+ case 0x55: // EZ-Drive... I think this was some DOS tool
+ // to see "large" disks ages ago, so it may be
+ // a DOS partition... Not sure about this one.
+ case 0xc1: // DRDOS/sec
+ case 0xc4: // DRDOS/sec
+ case 0xc6: // DRDOS/sec
+ {
+ // Try to determine which type of DOS we're using
+ String mp=p.mountpt[*it];
+ String lbl="DOS";
+ if(mp.empty()) {
+ char *tmp=tmpnam(NULL);
+ tmp=tmpnam(NULL);
+ mkdir(tmp, 0700);
+ if(!mount(*it, tmp, "msdos", MS_MGC_VAL|MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL))
+ mp=tmp;
+ else if(!mount(*it, mp, "vfat", MS_MGC_VAL|MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL))
+ mp=tmp;
+ }
+ if(!mp.empty()) {
+ struct stat s;
+ if(stat(mp+"/ibmbio.com", &s) && stat(mp+"/io.sys", &s) && stat(mp+"/ntldr", &s)) // Doesn't look like a bootable DOS partition, ignore it
+ break;
+ if(!stat(mp+"/drdos.386", &s))
+ lbl="DR-DOS";
+ else if(!stat(mp+"/ntldr", &s))
+ lbl="NT";
+ else if(!stat(mp+"/msdos.sys", &s)) {
+ if(s.st_size < 4096)
+ /* msdos.sys is actual code in DOS, it's a config file in SuckOS */
+ if(!stat(mp+"/windows/system/sfc.exe", &s)) /* This is (supposed to be?) a component of Suck98 but not Suck95 */
+ lbl="Windows98";
+ else
+ lbl="Windows95";
+ }
+ if(p.mountpt[*it].empty()) {
+ umount(mp);
+ sync();
+ rmdir(mp);
+ }
+ }
+ addOther(lbl, *it);
+ break;
+ }
+ case 0x02: // Xenix root... Does Xenix actually boot this way?
+ addOther("Xenix", *it);
+ break;
+ case 0x07: // HPFS or NTFS... Is there any way to check which?
+ // (without trying to mount them... many kernels
+ // support neither)
+ case 0x17: // Hidden HPFS or NTFS
+ addOther("NT", *it);
+ break;
+ case 0x09: // AIX
+ addOther("AIX", *it);
+ break;
+ case 0x83: // My favorite :)
+ case 0xfd: // Linux RAID
+ // TODO: scan other FSes for kernels...
+ break;
+ case 0x84:
+ {
+ // CLASH: SystemSoft MobilePRO BIOS and
+ // various Dell BIOSes use the same
+ // ID (0x84) for its hibernation partitions
+ // as OS/2 does for hidden C: drives.
+ // Fortunately, hibernation partitions are easy to
+ // recognize...
+ int fd=open(*it, O_RDONLY);
+ char *header=(char *) malloc(20);
+ read(fd, header, 20);
+ close(fd);
+ if(strncmp(header, "SystemSoft", 10)==0) // It's a hibernation partition
+ break;
+ else if(strncmp(header+3, "Dell Suspend", 12)==0) { // It's a Dell hibernation partition
+ // Dell BIOSes are ultimately buggy: They don't do resume-from-disk
+ // properly.
+ // Hibernation partitions are bootable and need to be loaded by the
+ // boot manager instead.
+ addOther("SuspendToDisk", *it);
+ break;
+ }
+ addOther("OS2", *it, false, "/boot/os2_d.b");
+ }
+ case 0x0a: // OS/2 Boot Manager
+ addOther("OS2", *it, false, "/boot/os2_d.b");
+ break;
+ case 0x10: // OPUS... (what is that?)
+ addOther("OPUS", *it);
+ break;
+ case 0x3c: // Partition Magic
+ addOther("PartitionMagic", *it);
+ break;
+ case 0x40: // Venix 80286
+ addOther("Venix", *it);
+ break;
+ case 0x4d: // QNX
+ addOther("QNX", *it);
+ break;
+ case 0x52: // CP/M (does anyone dual-boot between CP/M and
+ // Linux? Would be interesting to see. ;) )
+ case 0xdb: // CP/M/CTOS
+ addOther("CPM", *it);
+ break;
+ case 0x63: // GNU/Hurd
+ addOther("GNU_Hurd", *it);
+ break;
+ case 0x64: // Novell Netware
+ case 0x65: // Novell Netware
+ addOther("Netware", *it);
+ break;
+ case 0x75: // PC/IX (what is that?)
+ addOther("PCIX", *it);
+ break;
+ case 0x80: // Old Minix
+ case 0x81: // Minix and some VERY old Linux kernels
+ addOther("Minix", *it);
+ break;
+ case 0x9f: // BSD/OS
+ case 0xb7: // BSDI
+ addOther("BSD_OS", *it);
+ break;
+ case 0xa5: // Some BSDs... Is there any way to determine which
+ // one?
+ addOther("BSD", *it);
+ break;
+ case 0xa6: // OpenBSD
+ addOther("OpenBSD", *it);
+ break;
+ case 0xa7: // NeXTSTEP
+ addOther("NeXT", *it);
+ break;
+ case 0xc7: // Syrinx (what is that?)
+ addOther("Syrinx", *it);
+ break;
+ case 0xeb: // BeOS
+ addOther("BeOS", *it);
+ break;
+ case 0xfe: // LANstep (what is that?)
+ addOther("LANstep", *it);
+ break;
+ case 0xff: // BBT (what is that?)
+ addOther("BBT", *it);
+ break;
+ }
+ }
+ // addOther("floppy", "/dev/fd0", true);
+ //Would be nice, but LILO can't handle an optional
+ //other=nonexistantdevice entry ATM.
+ return true;
+}
+void liloconf::addLinux(String const &label, String const &kernel, String const &root, String const &initrd, bool optional, String const &append, String const &vga, bool readonly, String const &literal, String const &ramdisk)
+{
+ liloimage *lx_image=new liloimage;
+ *lx_image += "image="+kernel;
+ *lx_image += "\tlabel=\""+label+"\"";
+ if(!root.empty())
+ *lx_image += "\troot="+root;
+ if(readonly)
+ *lx_image += "\tread-only";
+ else
+ *lx_image += "\tread-write";
+ if(!initrd.empty())
+ *lx_image += "\tinitrd=\""+initrd+"\"";
+ if(!append.empty())
+ *lx_image += "\tappend=\""+append+"\"";
+ if(!vga.empty())
+ *lx_image += "\tvga=\""+vga+"\"";
+ if(!literal.empty())
+ *lx_image += "\tliteral=\""+literal+"\"";
+ if(!ramdisk.empty())
+ *lx_image += "\tramdisk=\""+ramdisk+"\"";
+ if(optional)
+ *lx_image += "\toptional";
+ images.insert(images.end(), *lx_image);
+}
+void liloconf::addOther(String const &name, String const &partition, bool const &optional, String const &chain)
+{
+ liloimage *other=new liloimage;
+ *other += "other="+partition;
+ *other += "\tlabel=\""+name+"\"";
+ if(optional)
+ *other += "\toptional";
+ if(!chain.empty())
+ *other += "\tloader="+chain+"\"";
+ images.insert(images.end(), *other);
+}
+void liloconf::remove(String const &label)
+{
+ String t = String::escapeForRegExp(label);
+
+ String regex="[ \t]*label[ \t]*=[ \t]*\"?"+t+"\"?[ \t]*";
+ for(liloimages::iterator it=images.begin(); it!=images.end(); it++) {
+ if(!(*it).grep(regex).empty()) {
+ images.erase(it);
+ break;
+ }
+ }
+}
+void liloconf::removeKernel(String const &kernel)
+{
+ String t = String::escapeForRegExp(kernel);
+
+ String regex="[ \t]*(image|other)[ \t]*=[ \t]*\"?"+t+"\"?[ \t]*";
+ for(liloimages::iterator it=images.begin(); it!=images.end(); it++) {
+ if(!(*it).grep(regex).empty()) {
+ images.erase(it);
+ break;
+ }
+ }
+}
+StringList const &liloconf::entries() const
+{
+ StringList *s=new StringList;
+ for(liloimages::const_iterator it=images.begin(); it!=images.end(); it++) {
+ String lbl=(*it).grep("[ \t]*label[ \t]*=.*");
+ lbl=lbl.mid(lbl.locate("label")+6);
+ while(isspace(lbl.chr(0)) || lbl.chr(0)=='=' || lbl.chr(0)=='\"')
+ lbl=lbl.mid(2);
+ while(isspace(lbl.right().chr(0)) || lbl.right()==(String)"\"")
+ lbl=lbl.left(lbl.size()-1);
+ s->add(lbl);
+ }
+ return *s;
+}
+String const liloconf::dflt() const
+{
+ String dflt="";
+ for(StringList::const_iterator it=defaults.begin(); it!=defaults.end() && dflt.empty(); it++)
+ if(!((*it).regex("^[ \t]*default[ \t]*=")).empty())
+ dflt=(*it).simplifyWhiteSpace();
+ if(dflt.empty()) {
+ liloimages::const_iterator it=images.begin();
+ if (it != images.end())
+ dflt=(*it).grep("^[ \t]*label[ \t]*=").simplifyWhiteSpace();
+ }
+ if(!dflt.empty()) {
+ dflt=dflt.mid(dflt.locate("=")+2).simplifyWhiteSpace();
+ if(dflt.left()==(String)"\"")
+ dflt=dflt.mid(2).simplifyWhiteSpace();
+ if(dflt.right()==(String)"\"")
+ dflt=dflt.left(dflt.size()-1).simplifyWhiteSpace();
+ }
+ return dflt;
+}
+void liloconf::setDefault(String const &dflt)
+{
+ bool ready=false;
+ for(StringList::const_iterator it=defaults.begin(); !ready && it!=defaults.end(); it++)
+ if(!((*it).regex("^[ \t]*default[ \t]*=")).empty()) {
+ defaults.remove(*it);
+ ready=true;
+ }
+ defaults+="default=" + dflt;
+}
+liloconf::operator String() const
+{
+ String s=defaults;
+ s+="\n";
+ for(liloimages::const_iterator it=images.begin(); it!=images.end(); it++) {
+ s+=*it;
+ s+="\n";
+ }
+ return s;
+}
+
+ostream &operator <<(ostream &os, liloconf const &l)
+{
+ os << l.defaults << endl;
+ for(liloimages::const_iterator it=l.images.begin(); it!=l.images.end(); it++)
+ os << *it << endl;
+ return os;
+}
+ostream &operator <<(ostream &os, liloconf const *l)
+{
+ os << l->defaults << endl;
+ for(liloimages::const_iterator it=l->images.begin(); it!=l->images.end(); it++)
+ os << *it << endl;
+ return os;
+}
diff --git a/lilo-config/common/lilo.h b/lilo-config/common/lilo.h
new file mode 100644
index 0000000..c992df0
--- /dev/null
+++ b/lilo-config/common/lilo.h
@@ -0,0 +1,77 @@
+/* lilo.h
+**
+** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer
+**
+** Contributions by A. Seigo and W. Bastian.
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+#ifndef _LILO_H_
+#define _LILO_H_ 1
+#include "Config.h"
+#include <iostream>
+
+class liloimage:public ConfigFile {
+public:
+ bool isLinux() const;
+};
+
+class liloimages:public std::list<liloimage> {
+public:
+ void remove(String const &s);
+ liloimage *find(String const &s) const;
+ liloimage *operator[](String const &s) const { return find(s); }
+};
+
+class liloconf {
+ friend std::ostream &operator <<(std::ostream &os, liloconf const &l);
+ friend std::ostream &operator <<(std::ostream &os, liloconf const *l);
+public:
+ liloconf(String const &filename="/etc/lilo.conf");
+ void set(StringList const &s);
+ void set(String const &s);
+ void writeFile(String const &filename);
+ bool const isOk();
+ String const liloOut();
+ bool install(bool probeonly=false);
+ bool probe();
+ void addLinux(String const &label, String const &kernel, String const &root="", String const &initrd="", bool optional=false, String const &append="", String const &vga="", bool readonly=true, String const &literal="", String const &ramdisk="");
+ void addOther(String const &name, String const &partition, bool const &optional=false, String const &chain="");
+ void remove(String const &label);
+ void removeKernel(String const &kernel);
+ StringList const &entries() const;
+ String const dflt() const;
+ void setDefault(String const &dflt);
+ operator String() const;
+protected:
+ void check() { install(true); }
+ bool ok;
+ String output;
+public:
+ bool checked;
+ ConfigFile defaults;
+ liloimages images;
+};
+std::ostream &operator <<(std::ostream &os, liloconf const &l);
+std::ostream &operator <<(std::ostream &os, liloconf const *l);
+#endif
diff --git a/lilo-config/common/tests/Makefile.am b/lilo-config/common/tests/Makefile.am
new file mode 100644
index 0000000..8059a44
--- /dev/null
+++ b/lilo-config/common/tests/Makefile.am
@@ -0,0 +1,9 @@
+String_LDADD = ../.libs/libcommon.a
+noinst_PROGRAMS = String
+INCLUDES = -I.. $(all_includes)
+
+String_SOURCES = \
+ String.cc
+
+messages:
+
diff --git a/lilo-config/common/tests/String.cc b/lilo-config/common/tests/String.cc
new file mode 100644
index 0000000..7b0b60e
--- /dev/null
+++ b/lilo-config/common/tests/String.cc
@@ -0,0 +1,77 @@
+/*
+**
+** Copyright (C) 2000 by Bernhard Rosenkraenzer
+**
+*/
+
+/*
+** 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.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-devel@kde.org
+*/
+
+using namespace std;
+
+#include <String.h>
+int main(int argc, char **argv)
+{
+ int bugs=0;
+ String s="Microsoft sucks! Red Hat doesn't suck!";
+ String t="Microsoft sucks! Destroy Microsoft! Microsoft must die!";
+ String u="Microsoft sucks!";
+ if(s.left(16)!="Microsoft sucks!") {
+ cerr << "left() seems to be broken." << endl;
+ bugs++;
+ }
+ if(s.right(21) != "Red Hat doesn't suck!") {
+ cerr << "right() seems to be broken." << endl;
+ bugs++;
+ }
+ if(s.mid(18) != 'R') {
+ cerr << "mid() with one parameter seems to be broken." << endl;
+ bugs++;
+ }
+ if(s.mid(18, 7) != "Red Hat") {
+ cerr << "mid() with 2 parameters seems to be broken." << endl;
+ bugs++;
+ }
+ if(s.regex("Red ?[Hh]at|RED ?HAT")!="Red Hat") {
+ cerr << "regex() seems to be broken." << endl;
+ bugs++;
+ }
+ if(!s.contains("Red Hat")) {
+ cerr << "contains() seems to be broken." << endl;
+ bugs++;
+ }
+ if(t.replace("Microsoft", "Windows", false) != "Windows sucks! Destroy Microsoft! Microsoft must die!") {
+ cerr << "replace() [once] seems to be broken." << endl;
+ bugs++;
+ }
+ if(t.replace("Microsoft", "Windows") != "Windows sucks! Destroy Windows! Windows must die!") {
+ cerr << "replace() [all] seems to be broken." << endl;
+ bugs++;
+ }
+ if(u.replace("Microsoft", "Windows") != "Windows sucks!") {
+ cerr << "replace() [all, test case 2] seems to be broken." << endl;
+ bugs++;
+ }
+
+ if(bugs==0)
+ cout << "No bugs in String class detected." << endl;
+ return bugs;
+}