summaryrefslogtreecommitdiff
path: root/core
authorharlekin <harlekin>2002-06-10 09:39:23 (UTC)
committer harlekin <harlekin>2002-06-10 09:39:23 (UTC)
commitca3838f3aa3bbfa3aba61f7aaa285b9be67ca426 (patch) (side-by-side diff)
treeb14274bbff3cd1140b9b1a1c84c2e97b712f1828 /core
parent81add8ce87168282bb56a15f0406f3fec75cf610 (diff)
downloadopie-ca3838f3aa3bbfa3aba61f7aaa285b9be67ca426.zip
opie-ca3838f3aa3bbfa3aba61f7aaa285b9be67ca426.tar.gz
opie-ca3838f3aa3bbfa3aba61f7aaa285b9be67ca426.tar.bz2
initial try
Diffstat (limited to 'core') (more/less context) (ignore whitespace changes)
-rw-r--r--core/applets/obex/kprocctrl.cpp268
-rw-r--r--core/applets/obex/kprocctrl.h120
-rw-r--r--core/applets/obex/kprocess.cpp915
-rw-r--r--core/applets/obex/kprocess.h804
-rw-r--r--core/applets/obex/obex.cc119
-rw-r--r--core/applets/obex/obex.cpp0
-rw-r--r--core/applets/obex/obex.h81
-rw-r--r--core/applets/obex/obex.pro11
-rw-r--r--core/applets/obex/obexdlg.ui258
-rw-r--r--core/applets/obex/obeximpl.cc50
-rw-r--r--core/applets/obex/obeximpl.h25
-rwxr-xr-xcore/applets/obex/processwrapper.cc114
12 files changed, 2765 insertions, 0 deletions
diff --git a/core/applets/obex/kprocctrl.cpp b/core/applets/obex/kprocctrl.cpp
new file mode 100644
index 0000000..330b0ee
--- a/dev/null
+++ b/core/applets/obex/kprocctrl.cpp
@@ -0,0 +1,268 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESSCONTROLLER -- A helper class for KProcess
+//
+// version 0.3.1, Jan, 8th 1997
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+// Ported by Holger Freyther
+//
+
+//#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <qsocketnotifier.h>
+#include "kprocess.h"
+#include "kprocctrl.h"
+
+KProcessController *KProcessController::theKProcessController = 0;
+
+struct sigaction KProcessController::oldChildHandlerData;
+bool KProcessController::handlerSet = false;
+
+KProcessController::KProcessController()
+{
+ assert( theKProcessController == 0 );
+
+ if (0 > pipe(fd))
+ printf(strerror(errno));
+
+ notifier = new QSocketNotifier(fd[0], QSocketNotifier::Read);
+ notifier->setEnabled(true);
+ QObject::connect(notifier, SIGNAL(activated(int)),
+ this, SLOT(slotDoHousekeeping(int)));
+ connect( &delayedChildrenCleanupTimer, SIGNAL( timeout()),
+ SLOT( delayedChildrenCleanup()));
+
+ theKProcessController = this;
+
+ setupHandlers();
+}
+
+
+void KProcessController::setupHandlers()
+{
+ if( handlerSet )
+ return;
+ struct sigaction act;
+ act.sa_handler=theSigCHLDHandler;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGCHLD);
+ // Make sure we don't block this signal. gdb tends to do that :-(
+ sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0);
+
+ act.sa_flags = SA_NOCLDSTOP;
+
+ // CC: take care of SunOS which automatically restarts interrupted system
+ // calls (and thus does not have SA_RESTART)
+
+#ifdef SA_RESTART
+ act.sa_flags |= SA_RESTART;
+#endif
+
+ sigaction( SIGCHLD, &act, &oldChildHandlerData );
+
+ act.sa_handler=SIG_IGN;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGPIPE);
+ act.sa_flags = 0;
+ sigaction( SIGPIPE, &act, 0L);
+ handlerSet = true;
+}
+
+void KProcessController::resetHandlers()
+{
+ if( !handlerSet )
+ return;
+ sigaction( SIGCHLD, &oldChildHandlerData, 0 );
+ // there should be no problem with SIGPIPE staying SIG_IGN
+ handlerSet = false;
+}
+
+// block SIGCHLD handler, because it accesses processList
+void KProcessController::addKProcess( KProcess* p )
+{
+ sigset_t newset, oldset;
+ sigemptyset( &newset );
+ sigaddset( &newset, SIGCHLD );
+ sigprocmask( SIG_BLOCK, &newset, &oldset );
+ processList.append( p );
+ sigprocmask( SIG_SETMASK, &oldset, 0 );
+}
+
+void KProcessController::removeKProcess( KProcess* p )
+{
+ sigset_t newset, oldset;
+ sigemptyset( &newset );
+ sigaddset( &newset, SIGCHLD );
+ sigprocmask( SIG_BLOCK, &newset, &oldset );
+ processList.remove( p );
+ sigprocmask( SIG_SETMASK, &oldset, 0 );
+}
+
+//using a struct which contains both the pid and the status makes it easier to write
+//and read the data into the pipe
+//especially this solves a problem which appeared on my box where slotDoHouseKeeping() received
+//only 4 bytes (with some debug output around the write()'s it received all 8 bytes)
+//don't know why this happened, but when writing all 8 bytes at once it works here, aleXXX
+struct waitdata
+{
+ pid_t pid;
+ int status;
+};
+
+void KProcessController::theSigCHLDHandler(int arg)
+{
+ struct waitdata wd;
+// int status;
+// pid_t this_pid;
+ int saved_errno;
+
+ saved_errno = errno;
+ // since waitpid and write change errno, we have to save it and restore it
+ // (Richard Stevens, Advanced programming in the Unix Environment)
+
+ bool found = false;
+ if( theKProcessController != 0 ) {
+ // iterating the list doesn't perform any system call
+ for( QValueList<KProcess*>::ConstIterator it = theKProcessController->processList.begin();
+ it != theKProcessController->processList.end();
+ ++it )
+ {
+ if( !(*it)->isRunning())
+ continue;
+ wd.pid = waitpid( (*it)->pid(), &wd.status, WNOHANG );
+ if ( wd.pid > 0 ) {
+ ::write(theKProcessController->fd[1], &wd, sizeof(wd));
+ found = true;
+ }
+ }
+ }
+ if( !found && oldChildHandlerData.sa_handler != SIG_IGN
+ && oldChildHandlerData.sa_handler != SIG_DFL )
+ oldChildHandlerData.sa_handler( arg ); // call the old handler
+ // handle the rest
+ if( theKProcessController != 0 ) {
+ static const struct waitdata dwd = { 0, 0 }; // delayed waitpid()
+ ::write(theKProcessController->fd[1], &dwd, sizeof(dwd));
+ } else {
+ int dummy;
+ while( waitpid( -1, &dummy, WNOHANG ) > 0 )
+ ;
+ }
+
+ errno = saved_errno;
+}
+
+
+
+void KProcessController::slotDoHousekeeping(int )
+{
+ unsigned int bytes_read = 0;
+ unsigned int errcnt=0;
+ // read pid and status from the pipe.
+ struct waitdata wd;
+ while ((bytes_read < sizeof(wd)) && (errcnt < 50)) {
+ int r = ::read(fd[0], ((char *)&wd) + bytes_read, sizeof(wd) - bytes_read);
+ if (r > 0) bytes_read += r;
+ else if (r < 0) errcnt++;
+ }
+ if (errcnt >= 50) {
+ fprintf(stderr,
+ "Error: Max. error count for pipe read "
+ "exceeded in KProcessController::slotDoHousekeeping\n");
+ return; // it makes no sense to continue here!
+ }
+ if (bytes_read != sizeof(wd)) {
+ fprintf(stderr,
+ "Error: Could not read info from signal handler %d <> %d!\n",
+ bytes_read, sizeof(wd));
+ return; // it makes no sense to continue here!
+ }
+ if (wd.pid==0) { // special case, see delayedChildrenCleanup()
+ delayedChildrenCleanupTimer.start( 1000, true );
+ return;
+ }
+
+ for( QValueList<KProcess*>::ConstIterator it = processList.begin();
+ it != processList.end();
+ ++it ) {
+ KProcess* proc = *it;
+ if (proc->pid() == wd.pid) {
+ // process has exited, so do emit the respective events
+ if (proc->run_mode == KProcess::Block) {
+ // If the reads are done blocking then set the status in proc
+ // but do nothing else because KProcess will perform the other
+ // actions of processHasExited.
+ proc->status = wd.status;
+ proc->runs = false;
+ } else {
+ proc->processHasExited(wd.status);
+ }
+ return;
+ }
+ }
+}
+
+// this is needed e.g. for popen(), which calls waitpid() checking
+// for its forked child, if we did waitpid() directly in the SIGCHLD
+// handler, popen()'s waitpid() call would fail
+void KProcessController::delayedChildrenCleanup()
+{
+ struct waitdata wd;
+ while(( wd.pid = waitpid( -1, &wd.status, WNOHANG ) ) > 0 ) {
+ for( QValueList<KProcess*>::ConstIterator it = processList.begin();
+ it != processList.end();
+ ++it )
+ {
+ if( !(*it)->isRunning() || (*it)->pid() != wd.pid )
+ continue;
+ // it's KProcess, handle it
+ ::write(fd[1], &wd, sizeof(wd));
+ break;
+ }
+ }
+}
+
+KProcessController::~KProcessController()
+{
+ assert( theKProcessController == this );
+ resetHandlers();
+
+ notifier->setEnabled(false);
+
+ close(fd[0]);
+ close(fd[1]);
+
+ delete notifier;
+ theKProcessController = 0;
+}
+
+//#include "kprocctrl.moc"
diff --git a/core/applets/obex/kprocctrl.h b/core/applets/obex/kprocctrl.h
new file mode 100644
index 0000000..ac82b9d
--- a/dev/null
+++ b/core/applets/obex/kprocctrl.h
@@ -0,0 +1,120 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESSCONTROLLER -- A helper class for KProcess
+//
+// version 0.3.1, Jan 8th 1997
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+//
+
+#ifndef __KPROCCTRL_H__
+#define __KPROCCTRL_H__
+
+#include <qvaluelist.h>
+#include <qtimer.h>
+
+#include "kprocess.h"
+
+class KProcessControllerPrivate;
+class QSocketNotifier;
+
+/**
+ * @short Used internally by @ref KProcess
+ * @internal
+ * @author Christian Czezakte <e9025461@student.tuwien.ac.at>
+ *
+ * A class for internal use by KProcess only. -- Exactly one instance
+ * of this class is generated by the first instance of KProcess that is
+ * created (a pointer to it gets stored in @ref theKProcessController ).
+ *
+ * This class takes care of the actual (UN*X) signal handling.
+*/
+class KProcessController : public QObject
+{
+ Q_OBJECT
+
+public:
+ KProcessController();
+ ~KProcessController();
+ //CC: WARNING! Destructor Not virtual (but you don't derive classes from this anyhow...)
+
+public:
+
+ /**
+ * Only a single instance of this class is allowed at a time,
+ * and this static variable is used to track the one instance.
+ */
+ static KProcessController *theKProcessController;
+
+ /**
+ * Automatically called upon SIGCHLD.
+ *
+ * Normally you do not need to do anything with this function but
+ * if your application needs to disable SIGCHLD for some time for
+ * reasons beyond your control, you should call this function afterwards
+ * to make sure that no SIGCHLDs where missed.
+ */
+ static void theSigCHLDHandler(int signal);
+ // handler for sigchld
+
+ /**
+ * @internal
+ */
+ static void setupHandlers();
+ /**
+ * @internal
+ */
+ static void resetHandlers();
+ /**
+ * @internal
+ */
+ void addKProcess( KProcess* );
+ /**
+ * @internal
+ */
+ void removeKProcess( KProcess* );
+ public slots:
+ /**
+ * @internal
+ */
+ void slotDoHousekeeping(int socket);
+
+ private slots:
+ void delayedChildrenCleanup();
+private:
+ int fd[2];
+ QSocketNotifier *notifier;
+ static struct sigaction oldChildHandlerData;
+ static bool handlerSet;
+ QValueList<KProcess*> processList;
+ QTimer delayedChildrenCleanupTimer;
+
+ // Disallow assignment and copy-construction
+ KProcessController( const KProcessController& );
+ KProcessController& operator= ( const KProcessController& );
+
+ KProcessControllerPrivate *d;
+};
+
+
+
+#endif
+
diff --git a/core/applets/obex/kprocess.cpp b/core/applets/obex/kprocess.cpp
new file mode 100644
index 0000000..ce7ed3e
--- a/dev/null
+++ b/core/applets/obex/kprocess.cpp
@@ -0,0 +1,915 @@
+/*
+
+ $Id$
+
+ This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+
+//
+// KPROCESS -- A class for handling child processes in KDE without
+// having to take care of Un*x specific implementation details
+//
+// version 0.3.1, Jan 8th 1998
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+//
+// Changes:
+//
+// March 2nd, 1998: Changed parameter list for KShellProcess:
+// Arguments are now placed in a single string so that
+// <shell> -c <commandstring> is passed to the shell
+// to make the use of "operator<<" consistent with KProcess
+
+#include "kprocess.h"
+#define _MAY_INCLUDE_KPROCESSCONTROLLER_
+#include "kprocctrl.h"
+
+//#include <config.h>
+
+#include <qfile.h>
+#include <qsocketnotifier.h>
+#include <qregexp.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_INITGROUPS
+#include <grp.h>
+#endif
+#include <pwd.h>
+
+#include <qapplication.h>
+#include <qmap.h>
+//#include <kdebug.h>
+
+/////////////////////////////
+// public member functions //
+/////////////////////////////
+
+class KProcessPrivate {
+public:
+ KProcessPrivate() : useShell(false) { }
+
+ bool useShell;
+ QMap<QString,QString> env;
+ QString wd;
+ QCString shell;
+};
+
+
+KProcess::KProcess()
+ : QObject(),
+ run_mode(NotifyOnExit),
+ runs(false),
+ pid_(0),
+ status(0),
+ keepPrivs(false),
+ innot(0),
+ outnot(0),
+ errnot(0),
+ communication(NoCommunication),
+ input_data(0),
+ input_sent(0),
+ input_total(0),
+ d(0)
+{
+ if (0 == KProcessController::theKProcessController) {
+ (void) new KProcessController();
+ CHECK_PTR(KProcessController::theKProcessController);
+ }
+
+ KProcessController::theKProcessController->addKProcess(this);
+ out[0] = out[1] = -1;
+ in[0] = in[1] = -1;
+ err[0] = err[1] = -1;
+}
+
+void
+KProcess::setEnvironment(const QString &name, const QString &value)
+{
+ if (!d)
+ d = new KProcessPrivate;
+ d->env.insert(name, value);
+}
+
+void
+KProcess::setWorkingDirectory(const QString &dir)
+{
+ if (!d)
+ d = new KProcessPrivate;
+ d->wd = dir;
+}
+
+void
+KProcess::setupEnvironment()
+{
+ if (d)
+ {
+ QMap<QString,QString>::Iterator it;
+ for(it = d->env.begin(); it != d->env.end(); ++it)
+ setenv(QFile::encodeName(it.key()).data(),
+ QFile::encodeName(it.data()).data(), 1);
+ if (!d->wd.isEmpty())
+ chdir(QFile::encodeName(d->wd).data());
+ }
+}
+
+void
+KProcess::setRunPrivileged(bool keepPrivileges)
+{
+ keepPrivs = keepPrivileges;
+}
+
+bool
+KProcess::runPrivileged() const
+{
+ return keepPrivs;
+}
+
+
+KProcess::~KProcess()
+{
+ // destroying the KProcess instance sends a SIGKILL to the
+ // child process (if it is running) after removing it from the
+ // list of valid processes (if the process is not started as
+ // "DontCare")
+
+ KProcessController::theKProcessController->removeKProcess(this);
+ // this must happen before we kill the child
+ // TODO: block the signal while removing the current process from the process list
+
+ if (runs && (run_mode != DontCare))
+ kill(SIGKILL);
+
+ // Clean up open fd's and socket notifiers.
+ closeStdin();
+ closeStdout();
+ closeStderr();
+
+ // TODO: restore SIGCHLD and SIGPIPE handler if this is the last KProcess
+ delete d;
+}
+
+void KProcess::detach()
+{
+ KProcessController::theKProcessController->removeKProcess(this);
+
+ runs = false;
+ pid_ = 0;
+
+ // Clean up open fd's and socket notifiers.
+ closeStdin();
+ closeStdout();
+ closeStderr();
+}
+
+bool KProcess::setExecutable(const QString& proc)
+{
+ if (runs) return false;
+
+ if (proc.isEmpty()) return false;
+
+ if (!arguments.isEmpty())
+ arguments.remove(arguments.begin());
+ arguments.prepend(QFile::encodeName(proc));
+
+ return true;
+}
+
+KProcess &KProcess::operator<<(const QStringList& args)
+{
+ QStringList::ConstIterator it = args.begin();
+ for ( ; it != args.end() ; ++it )
+ arguments.append(QFile::encodeName(*it));
+ return *this;
+}
+
+KProcess &KProcess::operator<<(const QCString& arg)
+{
+ return operator<< (arg.data());
+}
+
+KProcess &KProcess::operator<<(const char* arg)
+{
+ arguments.append(arg);
+ return *this;
+}
+
+KProcess &KProcess::operator<<(const QString& arg)
+{
+ arguments.append(QFile::encodeName(arg));
+ return *this;
+}
+
+void KProcess::clearArguments()
+{
+ arguments.clear();
+}
+
+bool KProcess::start(RunMode runmode, Communication comm)
+{
+ uint i;
+ uint n = arguments.count();
+ char **arglist;
+
+ if (runs || (0 == n)) {
+ return false; // cannot start a process that is already running
+ // or if no executable has been assigned
+ }
+ run_mode = runmode;
+ status = 0;
+
+ QCString shellCmd;
+ if (d && d->useShell)
+ {
+ if (d->shell.isEmpty())
+ {
+ qWarning( "Could not find a valid shell" );
+ return false;
+ }
+
+ arglist = static_cast<char **>(malloc( (4)*sizeof(char *)));
+ for (i=0; i < n; i++) {
+ shellCmd += arguments[i];
+ shellCmd += " "; // CC: to separate the arguments
+ }
+
+ arglist[0] = d->shell.data();
+ arglist[1] = (char *) "-c";
+ arglist[2] = shellCmd.data();
+ arglist[3] = 0;
+ }
+ else
+ {
+ arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *)));
+ for (i=0; i < n; i++)
+ arglist[i] = arguments[i].data();
+ arglist[n]= 0;
+ }
+
+ if (!setupCommunication(comm))
+ qWarning( "Could not setup Communication!");
+
+ // We do this in the parent because if we do it in the child process
+ // gdb gets confused when the application runs from gdb.
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+#ifdef HAVE_INITGROUPS
+ struct passwd *pw = getpwuid(uid);
+#endif
+
+ int fd[2];
+ if (0 > pipe(fd))
+ {
+ fd[0] = fd[1] = 0; // Pipe failed.. continue
+ }
+
+ runs = true;
+
+ QApplication::flushX();
+
+ // WABA: Note that we use fork() and not vfork() because
+ // vfork() has unclear semantics and is not standardized.
+ pid_ = fork();
+
+ if (0 == pid_) {
+ if (fd[0])
+ close(fd[0]);
+ if (!runPrivileged())
+ {
+ setgid(gid);
+#if defined( HAVE_INITGROUPS)
+ if(pw)
+ initgroups(pw->pw_name, pw->pw_gid);
+#endif
+ setuid(uid);
+ }
+ // The child process
+ if(!commSetupDoneC())
+ qWarning( "Could not finish comm setup in child!" );
+
+ setupEnvironment();
+
+ // Matthias
+ if (run_mode == DontCare)
+ setpgid(0,0);
+ // restore default SIGPIPE handler (Harri)
+ struct sigaction act;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGPIPE);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigaction(SIGPIPE, &act, 0L);
+
+ // We set the close on exec flag.
+ // Closing of fd[1] indicates that the execvp succeeded!
+ if (fd[1])
+ fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ execvp(arglist[0], arglist);
+ char resultByte = 1;
+ if (fd[1])
+ write(fd[1], &resultByte, 1);
+ _exit(-1);
+ } else if (-1 == pid_) {
+ // forking failed
+
+ runs = false;
+ free(arglist);
+ return false;
+ } else {
+ if (fd[1])
+ close(fd[1]);
+ // the parent continues here
+
+ // Discard any data for stdin that might still be there
+ input_data = 0;
+
+ // Check whether client could be started.
+ if (fd[0]) for(;;)
+ {
+ char resultByte;
+ int n = ::read(fd[0], &resultByte, 1);
+ if (n == 1)
+ {
+ // Error
+ runs = false;
+ close(fd[0]);
+ free(arglist);
+ pid_ = 0;
+ return false;
+ }
+ if (n == -1)
+ {
+ if ((errno == ECHILD) || (errno == EINTR))
+ continue; // Ignore
+ }
+ break; // success
+ }
+ if (fd[0])
+ close(fd[0]);
+
+ if (!commSetupDoneP()) // finish communication socket setup for the parent
+ qWarning( "Could not finish comm setup in parent!" );
+
+ if (run_mode == Block) {
+ commClose();
+
+ // The SIGCHLD handler of the process controller will catch
+ // the exit and set the status
+ while(runs)
+ {
+ KProcessController::theKProcessController->
+ slotDoHousekeeping(0);
+ }
+ runs = FALSE;
+ emit processExited(this);
+ }
+ }
+ free(arglist);
+ return true;
+}
+
+
+
+bool KProcess::kill(int signo)
+{
+ bool rv=false;
+
+ if (0 != pid_)
+ rv= (-1 != ::kill(pid_, signo));
+ // probably store errno somewhere...
+ return rv;
+}
+
+
+
+bool KProcess::isRunning() const
+{
+ return runs;
+}
+
+
+
+pid_t KProcess::pid() const
+{
+ return pid_;
+}
+
+
+
+bool KProcess::normalExit() const
+{
+ int _status = status;
+ return (pid_ != 0) && (!runs) && (WIFEXITED((_status)));
+}
+
+
+
+int KProcess::exitStatus() const
+{
+ int _status = status;
+ return WEXITSTATUS((_status));
+}
+
+
+
+bool KProcess::writeStdin(const char *buffer, int buflen)
+{
+ bool rv;
+
+ // if there is still data pending, writing new data
+ // to stdout is not allowed (since it could also confuse
+ // kprocess...
+ if (0 != input_data)
+ return false;
+
+ if (runs && (communication & Stdin)) {
+ input_data = buffer;
+ input_sent = 0;
+ input_total = buflen;
+ slotSendData(0);
+ innot->setEnabled(true);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+void KProcess::suspend()
+{
+ if ((communication & Stdout) && outnot)
+ outnot->setEnabled(false);
+}
+
+void KProcess::resume()
+{
+ if ((communication & Stdout) && outnot)
+ outnot->setEnabled(true);
+}
+
+bool KProcess::closeStdin()
+{
+ bool rv;
+
+ if (communication & Stdin) {
+ communication = (Communication) (communication & ~Stdin);
+ delete innot;
+ innot = 0;
+ close(in[1]);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+bool KProcess::closeStdout()
+{
+ bool rv;
+
+ if (communication & Stdout) {
+ communication = (Communication) (communication & ~Stdout);
+ delete outnot;
+ outnot = 0;
+ close(out[0]);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+bool KProcess::closeStderr()
+{
+ bool rv;
+
+ if (communication & Stderr) {
+ communication = static_cast<Communication>(communication & ~Stderr);
+ delete errnot;
+ errnot = 0;
+ close(err[0]);
+ rv = true;
+ } else
+ rv = false;
+ return rv;
+}
+
+
+/////////////////////////////
+// protected slots //
+/////////////////////////////
+
+
+
+void KProcess::slotChildOutput(int fdno)
+{
+ if (!childOutput(fdno))
+ closeStdout();
+}
+
+
+void KProcess::slotChildError(int fdno)
+{
+ if (!childError(fdno))
+ closeStderr();
+}
+
+
+void KProcess::slotSendData(int)
+{
+ if (input_sent == input_total) {
+ innot->setEnabled(false);
+ input_data = 0;
+ emit wroteStdin(this);
+ } else
+ input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent);
+}
+
+
+
+//////////////////////////////
+// private member functions //
+//////////////////////////////
+
+
+
+void KProcess::processHasExited(int state)
+{
+ if (runs)
+ {
+ runs = false;
+ status = state;
+
+ commClose(); // cleanup communication sockets
+
+ // also emit a signal if the process was run Blocking
+ if (DontCare != run_mode)
+ {
+ emit processExited(this);
+ }
+ }
+}
+
+
+
+int KProcess::childOutput(int fdno)
+{
+ if (communication & NoRead) {
+ int len = -1;
+ emit receivedStdout(fdno, len);
+ errno = 0; // Make sure errno doesn't read "EAGAIN"
+ return len;
+ }
+ else
+ {
+ char buffer[1024];
+ int len;
+
+ len = ::read(fdno, buffer, 1024);
+
+ if ( 0 < len) {
+ emit receivedStdout(this, buffer, len);
+ }
+ return len;
+ }
+}
+
+
+
+int KProcess::childError(int fdno)
+{
+ char buffer[1024];
+ int len;
+
+ len = ::read(fdno, buffer, 1024);
+
+ if ( 0 < len)
+ emit receivedStderr(this, buffer, len);
+ return len;
+}
+
+
+
+int KProcess::setupCommunication(Communication comm)
+{
+ int ok;
+
+ communication = comm;
+
+ ok = 1;
+ if (comm & Stdin)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0;
+
+ if (comm & Stdout)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0;
+
+ if (comm & Stderr)
+ ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0;
+
+ return ok;
+}
+
+
+
+int KProcess::commSetupDoneP()
+{
+ int ok = 1;
+
+ if (communication != NoCommunication) {
+ if (communication & Stdin)
+ close(in[0]);
+ if (communication & Stdout)
+ close(out[1]);
+ if (communication & Stderr)
+ close(err[1]);
+
+ // Don't create socket notifiers and set the sockets non-blocking if
+ // blocking is requested.
+ if (run_mode == Block) return ok;
+
+ if (communication & Stdin) {
+// ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK));
+ innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this);
+ CHECK_PTR(innot);
+ innot->setEnabled(false); // will be enabled when data has to be sent
+ QObject::connect(innot, SIGNAL(activated(int)),
+ this, SLOT(slotSendData(int)));
+ }
+
+ if (communication & Stdout) {
+// ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK));
+ outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this);
+ CHECK_PTR(outnot);
+ QObject::connect(outnot, SIGNAL(activated(int)),
+ this, SLOT(slotChildOutput(int)));
+ if (communication & NoRead)
+ suspend();
+ }
+
+ if (communication & Stderr) {
+// ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK));
+ errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this );
+ CHECK_PTR(errnot);
+ QObject::connect(errnot, SIGNAL(activated(int)),
+ this, SLOT(slotChildError(int)));
+ }
+ }
+ return ok;
+}
+
+
+
+int KProcess::commSetupDoneC()
+{
+ int ok = 1;
+ struct linger so;
+ memset(&so, 0, sizeof(so));
+
+ if (communication & Stdin)
+ close(in[1]);
+ if (communication & Stdout)
+ close(out[0]);
+ if (communication & Stderr)
+ close(err[0]);
+
+ if (communication & Stdin)
+ ok &= dup2(in[0], STDIN_FILENO) != -1;
+ else {
+ int null_fd = open( "/dev/null", O_RDONLY );
+ ok &= dup2( null_fd, STDIN_FILENO ) != -1;
+ close( null_fd );
+ }
+ if (communication & Stdout) {
+ ok &= dup2(out[1], STDOUT_FILENO) != -1;
+ ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so));
+ }
+ else {
+ int null_fd = open( "/dev/null", O_WRONLY );
+ ok &= dup2( null_fd, STDOUT_FILENO ) != -1;
+ close( null_fd );
+ }
+ if (communication & Stderr) {
+ ok &= dup2(err[1], STDERR_FILENO) != -1;
+ ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, reinterpret_cast<char *>(&so), sizeof(so));
+ }
+ else {
+ int null_fd = open( "/dev/null", O_WRONLY );
+ ok &= dup2( null_fd, STDERR_FILENO ) != -1;
+ close( null_fd );
+ }
+ return ok;
+}
+
+
+
+void KProcess::commClose()
+{
+ if (NoCommunication != communication) {
+ bool b_in = (communication & Stdin);
+ bool b_out = (communication & Stdout);
+ bool b_err = (communication & Stderr);
+ if (b_in)
+ delete innot;
+
+ if (b_out || b_err) {
+ // If both channels are being read we need to make sure that one socket buffer
+ // doesn't fill up whilst we are waiting for data on the other (causing a deadlock).
+ // Hence we need to use select.
+
+ // Once one or other of the channels has reached EOF (or given an error) go back
+ // to the usual mechanism.
+
+ int fds_ready = 1;
+ fd_set rfds;
+
+ int max_fd = 0;
+ if (b_out) {
+ fcntl(out[0], F_SETFL, O_NONBLOCK);
+ if (out[0] > max_fd)
+ max_fd = out[0];
+ delete outnot;
+ outnot = 0;
+ }
+ if (b_err) {
+ fcntl(err[0], F_SETFL, O_NONBLOCK);
+ if (err[0] > max_fd)
+ max_fd = err[0];
+ delete errnot;
+ errnot = 0;
+ }
+
+
+ while (b_out || b_err) {
+ // * If the process is still running we block until we
+ // receive data. (p_timeout = 0, no timeout)
+ // * If the process has already exited, we only check
+ // the available data, we don't wait for more.
+ // (p_timeout = &timeout, timeout immediately)
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ struct timeval *p_timeout = runs ? 0 : &timeout;
+
+ FD_ZERO(&rfds);
+ if (b_out)
+ FD_SET(out[0], &rfds);
+
+ if (b_err)
+ FD_SET(err[0], &rfds);
+
+ fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout);
+ if (fds_ready <= 0) break;
+
+ if (b_out && FD_ISSET(out[0], &rfds)) {
+ int ret = 1;
+ while (ret > 0) ret = childOutput(out[0]);
+ if ((ret == -1 && errno != EAGAIN) || ret == 0)
+ b_out = false;
+ }
+
+ if (b_err && FD_ISSET(err[0], &rfds)) {
+ int ret = 1;
+ while (ret > 0) ret = childError(err[0]);
+ if ((ret == -1 && errno != EAGAIN) || ret == 0)
+ b_err = false;
+ }
+ }
+ }
+
+ if (b_in) {
+ communication = (Communication) (communication & ~Stdin);
+ close(in[1]);
+ }
+ if (b_out) {
+ communication = (Communication) (communication & ~Stdout);
+ close(out[0]);
+ }
+ if (b_err) {
+ communication = (Communication) (communication & ~Stderr);
+ close(err[0]);
+ }
+ }
+}
+
+void KProcess::setUseShell(bool useShell, const char *shell)
+{
+ if (!d)
+ d = new KProcessPrivate;
+ d->useShell = useShell;
+ d->shell = shell;
+ if (d->shell.isEmpty())
+ d->shell = searchShell();
+}
+
+QString KProcess::quote(const QString &arg)
+{
+ QString res = arg;
+ res.replace(QRegExp(QString::fromLatin1("\'")),
+ QString::fromLatin1("'\"'\"'"));
+ res.prepend('\'');
+ res.append('\'');
+ return res;
+}
+
+QCString KProcess::searchShell()
+{
+ QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace();
+ if (!isExecutable(tmpShell))
+ {
+ tmpShell = "/bin/sh";
+ }
+
+ return tmpShell;
+}
+
+bool KProcess::isExecutable(const QCString &filename)
+{
+ struct stat fileinfo;
+
+ if (filename.isEmpty()) return false;
+
+ // CC: we've got a valid filename, now let's see whether we can execute that file
+
+ if (-1 == stat(filename.data(), &fileinfo)) return false;
+ // CC: return false if the file does not exist
+
+ // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets
+ if ( (S_ISDIR(fileinfo.st_mode)) ||
+ (S_ISCHR(fileinfo.st_mode)) ||
+ (S_ISBLK(fileinfo.st_mode)) ||
+#ifdef S_ISSOCK
+ // CC: SYSVR4 systems don't have that macro
+ (S_ISSOCK(fileinfo.st_mode)) ||
+#endif
+ (S_ISFIFO(fileinfo.st_mode)) ||
+ (S_ISDIR(fileinfo.st_mode)) ) {
+ return false;
+ }
+
+ // CC: now check for permission to execute the file
+ if (access(filename.data(), X_OK) != 0) return false;
+
+ // CC: we've passed all the tests...
+ return true;
+}
+
+void KProcess::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+
+///////////////////////////
+// CC: Class KShellProcess
+///////////////////////////
+
+KShellProcess::KShellProcess(const char *shellname):
+ KProcess()
+{
+ setUseShell(true, shellname);
+}
+
+
+KShellProcess::~KShellProcess() {
+}
+
+QString KShellProcess::quote(const QString &arg)
+{
+ return KProcess::quote(arg);
+}
+
+bool KShellProcess::start(RunMode runmode, Communication comm)
+{
+ return KProcess::start(runmode, comm);
+}
+
+void KShellProcess::virtual_hook( int id, void* data )
+{ KProcess::virtual_hook( id, data ); }
+
+//#include "kprocess.moc"
diff --git a/core/applets/obex/kprocess.h b/core/applets/obex/kprocess.h
new file mode 100644
index 0000000..e70f7e7
--- a/dev/null
+++ b/core/applets/obex/kprocess.h
@@ -0,0 +1,804 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//
+// KPROCESS -- A class for handling child processes in KDE without
+// having to take care of Un*x specific implementation details
+//
+// version 0.3.1, Jan 8th 1998
+//
+// (C) Christian Czezatke
+// e9025461@student.tuwien.ac.at
+//
+
+#ifndef __kprocess_h__
+#define __kprocess_h__
+
+#include <sys/types.h> // for pid_t
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <qvaluelist.h>
+#include <qcstring.h>
+#include <qobject.h>
+
+class QSocketNotifier;
+class KProcessPrivate;
+
+/**
+ * Child process invocation, monitoring and control.
+ *
+ * @sect General usage and features
+ *
+ *This class allows a KDE application to start child processes without having
+ *to worry about UN*X signal handling issues and zombie process reaping.
+ *
+ *@see KProcIO
+ *
+ *Basically, this class distinguishes three different ways of running
+ *child processes:
+ *
+ *@li KProcess::DontCare -- The child process is invoked and both the child
+ *process and the parent process continue concurrently.
+ *
+ *Starting a DontCare child process means that the application is
+ *not interested in any notification to determine whether the
+ *child process has already exited or not.
+ *
+ *@li KProcess::NotifyOnExit -- The child process is invoked and both the
+ *child and the parent process run concurrently.
+ *
+ *When the child process exits, the KProcess instance
+ *corresponding to it emits the Qt signal @ref processExited().
+ *
+ *Since this signal is @em not emitted from within a UN*X
+ *signal handler, arbitrary function calls can be made.
+ *
+ *Be aware: When the KProcess objects gets destructed, the child
+ *process will be killed if it is still running!
+ *This means in particular, that you cannot use a KProcess on the stack
+ *with KProcess::NotifyOnExit.
+ *
+ *@li KProcess::Block -- The child process starts and the parent process
+ *is suspended until the child process exits. (@em Really not recommended
+ *for programs with a GUI.)
+ *
+ *KProcess also provides several functions for determining the exit status
+ *and the pid of the child process it represents.
+ *
+ *Furthermore it is possible to supply command-line arguments to the process
+ *in a clean fashion (no null -- terminated stringlists and such...)
+ *
+ *A small usage example:
+ *<pre>
+ *KProcess *proc = new KProcess;
+ *
+ **proc << "my_executable";
+ **proc << "These" << "are" << "the" << "command" << "line" << "args";
+ *QApplication::connect(proc, SIGNAL(processExited(KProcess *)),
+ * pointer_to_my_object, SLOT(my_objects_slot(KProcess *)));
+ *proc->start();
+ *</pre>
+ *
+ *This will start "my_executable" with the commandline arguments "These"...
+ *
+ *When the child process exits, the respective Qt signal will be emitted.
+ *
+ *@sect Communication with the child process
+ *
+ *KProcess supports communication with the child process through
+ *stdin/stdout/stderr.
+ *
+ *The following functions are provided for getting data from the child
+ *process or sending data to the child's stdin (For more information,
+ *have a look at the documentation of each function):
+ *
+ *@li bool @ref writeStdin(char *buffer, int buflen);
+ *@li -- Transmit data to the child process's stdin.
+ *
+ *@li bool @ref closeStdin();
+ *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)).
+ *Returns false if you try to close stdin for a process that has been started
+ *without a communication channel to stdin.
+ *
+ *@li bool @ref closeStdout();
+ *@li -- Closes the child process's stdout.
+ *Returns false if you try to close stdout for a process that has been started
+ *without a communication channel to stdout.
+ *
+ *@li bool @ref closeStderr();
+ *@li -- Closes the child process's stderr.
+ *Returns false if you try to close stderr for a process that has been started
+ *without a communication channel to stderr.
+ *
+ *
+ *@sect QT signals:
+ *
+ *@li void @ref receivedStdout(KProcess *proc, char *buffer, int buflen);
+ *@li void @ref receivedStderr(KProcess *proc, char *buffer, int buflen);
+ *@li -- Indicates that new data has arrived from either the
+ *child process's stdout or stderr.
+ *
+ *@li void @ref wroteStdin(KProcess *proc);
+ *@li -- Indicates that all data that has been sent to the child process
+ *by a prior call to @ref writeStdin() has actually been transmitted to the
+ *client .
+ *
+ *@author Christian Czezakte e9025461@student.tuwien.ac.at
+ *
+ *
+ **/
+class KProcess : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Modes in which the communication channel can be opened.
+ *
+ * If communication for more than one channel is required,
+ * the values have to be or'ed together, for example to get
+ * communication with stdout as well as with stdin, you would
+ * specify @p Stdin @p | @p Stdout
+ *
+ * If @p NoRead is specified in conjunction with @p Stdout,
+ * no data is actually read from @p Stdout but only
+ * the signal @ref childOutput(int fd) is emitted.
+ */
+ enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4,
+ AllOutput = 6, All = 7,
+ NoRead };
+
+ /**
+ * Run-modes for a child process.
+ */
+ enum RunMode {
+ /**
+ * The application does not receive notifications from the subprocess when
+ * it is finished or aborted.
+ */
+ DontCare,
+ /**
+ * The application is notified when the subprocess dies.
+ */
+ NotifyOnExit,
+ /**
+ * The application is suspended until the started process is finished.
+ */
+ Block };
+
+ /**
+ * Constructor
+ */
+ KProcess();
+
+ /**
+ *Destructor:
+ *
+ * If the process is running when the destructor for this class
+ * is called, the child process is killed with a SIGKILL, but
+ * only if the run mode is not of type @p DontCare.
+ * Processes started as @p DontCare keep running anyway.
+ */
+ virtual ~KProcess();
+
+ /**
+ @deprecated
+
+ The use of this function is now deprecated. -- Please use the
+ "operator<<" instead of "setExecutable".
+
+ Sets the executable to be started with this KProcess object.
+ Returns false if the process is currently running (in that
+ case the executable remains unchanged.)
+
+ @see operator<<
+
+ */
+ bool setExecutable(const QString& proc);
+
+
+ /**
+ * Sets the executable and the command line argument list for this process.
+ *
+ * For example, doing an "ls -l /usr/local/bin" can be achieved by:
+ * <pre>
+ * KProcess p;
+ * ...
+ * p << "ls" << "-l" << "/usr/local/bin"
+ * </pre>
+ *
+ **/
+ KProcess &operator<<(const QString& arg);
+ /**
+ * Similar to previous method, takes a char *, supposed to be in locale 8 bit already.
+ */
+ KProcess &operator<<(const char * arg);
+ /**
+ * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already.
+ */
+ KProcess &operator<<(const QCString & arg);
+
+ /**
+ * Sets the executable and the command line argument list for this process,
+ * in a single method call, or add a list of arguments.
+ **/
+ KProcess &operator<<(const QStringList& args);
+
+ /**
+ * Clear a command line argument list that has been set by using
+ * the "operator<<".
+ */
+ void clearArguments();
+
+ /**
+ * Starts the process.
+ * For a detailed description of the
+ * various run modes and communication semantics, have a look at the
+ * general description of the KProcess class.
+ *
+ * The following problems could cause this function to
+ * return false:
+ *
+ * @li The process is already running.
+ * @li The command line argument list is empty.
+ * @li The starting of the process failed (could not fork).
+ * @li The executable was not found.
+ *
+ * @param comm Specifies which communication links should be
+ * established to the child process (stdin/stdout/stderr). By default,
+ * no communication takes place and the respective communication
+ * signals will never get emitted.
+ *
+ * @return true on success, false on error
+ * (see above for error conditions)
+ **/
+ virtual bool start(RunMode runmode = NotifyOnExit,
+ Communication comm = NoCommunication);
+
+ /**
+ * Stop the process (by sending it a signal).
+ *
+ * @param signo The signal to send. The default is SIGTERM.
+ * @return @p true if the signal was delivered successfully.
+ */
+ virtual bool kill(int signo = SIGTERM);
+
+ /**
+ @return @p true if the process is (still) considered to be running
+ */
+ bool isRunning() const;
+
+ /** Returns the process id of the process.
+ *
+ * If it is called after
+ * the process has exited, it returns the process id of the last
+ * child process that was created by this instance of KProcess.
+ *
+ * Calling it before any child process has been started by this
+ * KProcess instance causes pid() to return 0.
+ **/
+ pid_t pid() const;
+
+ /**
+ * Use pid().
+ * @deprecated
+ */
+ pid_t getPid() const { return pid(); }
+
+ /**
+ * Suspend processing of data from stdout of the child process.
+ */
+ void suspend();
+
+ /**
+ * Resume processing of data from stdout of the child process.
+ */
+ void resume();
+
+ /**
+ * @return @p true if the process has already finished and has exited
+ * "voluntarily", ie: it has not been killed by a signal.
+ *
+ * Note that you should check @ref KProcess::exitStatus() to determine
+ * whether the process completed its task successful or not.
+ */
+ bool normalExit() const;
+
+ /**
+ * Returns the exit status of the process.
+ *
+ * Please use
+ * @ref KProcess::normalExit() to check whether the process has exited
+ * cleanly (i.e., @ref KProcess::normalExit() returns @p true) before calling
+ * this function because if the process did not exit normally,
+ * it does not have a valid exit status.
+ */
+ int exitStatus() const;
+
+
+ /**
+ * Transmit data to the child process's stdin.
+ *
+ * KProcess::writeStdin may return false in the following cases:
+ *
+ * @li The process is not currently running.
+ *
+ * @li Communication to stdin has not been requested in the @ref start() call.
+ *
+ * @li Transmission of data to the child process by a previous call to
+ * @ref writeStdin() is still in progress.
+ *
+ * Please note that the data is sent to the client asynchronously,
+ * so when this function returns, the data might not have been
+ * processed by the child process.
+ *
+ * If all the data has been sent to the client, the signal
+ * @ref wroteStdin() will be emitted.
+ *
+ * Please note that you must not free "buffer" or call @ref writeStdin()
+ * again until either a @ref wroteStdin() signal indicates that the
+ * data has been sent or a @ref processHasExited() signal shows that
+ * the child process is no longer alive...
+ **/
+ bool writeStdin(const char *buffer, int buflen);
+
+ /**
+ * This causes the stdin file descriptor of the child process to be
+ * closed indicating an "EOF" to the child.
+ *
+ * @return @p false if no communication to the process's stdin
+ * had been specified in the call to @ref start().
+ */
+ bool closeStdin();
+
+ /**
+ * This causes the stdout file descriptor of the child process to be
+ * closed.
+ *
+ * @return @p false if no communication to the process's stdout
+ * had been specified in the call to @ref start().
+ */
+ bool closeStdout();
+
+ /**
+ * This causes the stderr file descriptor of the child process to be
+ * closed.
+ *
+ * @return @p false if no communication to the process's stderr
+ * had been specified in the call to @ref start().
+ */
+ bool closeStderr();
+
+ /**
+ * Lets you see what your arguments are for debugging.
+ */
+
+ const QValueList<QCString> &args() { return arguments; }
+
+ /**
+ * Controls whether the started process should drop any
+ * setuid/segid privileges or whether it should keep them
+ *
+ * The default is @p false : drop privileges
+ */
+ void setRunPrivileged(bool keepPrivileges);
+
+ /**
+ * Returns whether the started process will drop any
+ * setuid/segid privileges or whether it will keep them
+ */
+ bool runPrivileged() const;
+
+ /**
+ * Modifies the environment of the process to be started.
+ * This function must be called before starting the process.
+ */
+ void setEnvironment(const QString &name, const QString &value);
+
+ /**
+ * Changes the current working directory (CWD) of the process
+ * to be started.
+ * This function must be called before starting the process.
+ */
+ void setWorkingDirectory(const QString &dir);
+
+ /**
+ * Specify whether to start the command via a shell or directly.
+ * The default is to start the command directly.
+ * If @p useShell is true @p shell will be used as shell, or
+ * if shell is empty, the standard shell is used.
+ * @p quote A flag indicating whether to quote the arguments.
+ *
+ * When using a shell, the caller should make sure that all filenames etc.
+ * are properly quoted when passed as argument.
+ * @see quote()
+ */
+ void setUseShell(bool useShell, const char *shell = 0);
+
+ /**
+ * This function can be used to quote an argument string such that
+ * the shell processes it properly. This is e. g. necessary for
+ * user-provided file names which may contain spaces or quotes.
+ * It also prevents expansion of wild cards and environment variables.
+ */
+ static QString quote(const QString &arg);
+
+ /**
+ * Detaches KProcess from child process. All communication is closed.
+ * No exit notification is emitted any more for the child process.
+ * Deleting the KProcess will no longer kill the child process.
+ * Note that the current process remains the parent process of the
+ * child process.
+ */
+ void detach();
+
+
+
+signals:
+
+ /**
+ * Emitted after the process has terminated when
+ * the process was run in the @p NotifyOnExit (==default option to
+ * @ref start()) or the @ref Block mode.
+ **/
+ void processExited(KProcess *proc);
+
+
+ /**
+ * Emitted, when output from the child process has
+ * been received on stdout.
+ *
+ * To actually get
+ * these signals, the respective communication link (stdout/stderr)
+ * has to be turned on in @ref start().
+ *
+ * @param buffer The data received.
+ * @param buflen The number of bytes that are available.
+ *
+ * You should copy the information contained in @p buffer to your private
+ * data structures before returning from this slot.
+ **/
+ void receivedStdout(KProcess *proc, char *buffer, int buflen);
+
+ /**
+ * Emitted when output from the child process has
+ * been received on stdout.
+ *
+ * To actually get these signals, the respective communications link
+ * (stdout/stderr) has to be turned on in @ref start() and the
+ * @p NoRead flag should have been passed.
+ *
+ * You will need to explicitly call resume() after your call to start()
+ * to begin processing data from the child process's stdout. This is
+ * to ensure that this signal is not emitted when no one is connected
+ * to it, otherwise this signal will not be emitted.
+ *
+ * The data still has to be read from file descriptor @p fd.
+ **/
+ void receivedStdout(int fd, int &len);
+
+
+ /**
+ * Emitted, when output from the child process has
+ * been received on stderr.
+ * To actually get
+ * these signals, the respective communication link (stdout/stderr)
+ * has to be turned on in @ref start().
+ *
+ * @param buffer The data received.
+ * @param buflen The number of bytes that are available.
+ *
+ * You should copy the information contained in @p buffer to your private
+ * data structures before returning from this slot.
+ */
+ void receivedStderr(KProcess *proc, char *buffer, int buflen);
+
+ /**
+ * Emitted after all the data that has been
+ * specified by a prior call to @ref writeStdin() has actually been
+ * written to the child process.
+ **/
+ void wroteStdin(KProcess *proc);
+
+
+protected slots:
+
+ /**
+ * This slot gets activated when data from the child's stdout arrives.
+ * It usually calls "childOutput"
+ */
+ void slotChildOutput(int fdno);
+
+ /**
+ * This slot gets activated when data from the child's stderr arrives.
+ * It usually calls "childError"
+ */
+ void slotChildError(int fdno);
+ /*
+ Slot functions for capturing stdout and stderr of the child
+ */
+
+ /**
+ * Called when another bulk of data can be sent to the child's
+ * stdin. If there is no more data to be sent to stdin currently
+ * available, this function must disable the QSocketNotifier "innot".
+ */
+ void slotSendData(int dummy);
+
+protected:
+
+ /**
+ * Sets up the environment according to the data passed via
+ * setEnvironment(...)
+ */
+ void setupEnvironment();
+
+ /**
+ * The list of the process' command line arguments. The first entry
+ * in this list is the executable itself.
+ */
+ QValueList<QCString> arguments;
+ /**
+ * How to run the process (Block, NotifyOnExit, DontCare). You should
+ * not modify this data member directly from derived classes.
+ */
+ RunMode run_mode;
+ /**
+ * true if the process is currently running. You should not
+ * modify this data member directly from derived classes. For
+ * reading the value of this data member, please use "isRunning()"
+ * since "runs" will probably be made private in later versions
+ * of KProcess.
+ */
+ bool runs;
+
+ /**
+ * The PID of the currently running process (see "getPid()").
+ * You should not modify this data member in derived classes.
+ * Please use "getPid()" instead of directly accessing this
+ * member function since it will probably be made private in
+ * later versions of KProcess.
+ */
+ pid_t pid_;
+
+ /**
+ * The process' exit status as returned by "waitpid". You should not
+ * modify the value of this data member from derived classes. You should
+ * rather use @ref exitStatus than accessing this data member directly
+ * since it will probably be made private in further versions of
+ * KProcess.
+ */
+ int status;
+
+
+ /**
+ * See setRunPrivileged()
+ */
+ bool keepPrivs;
+
+ /*
+ Functions for setting up the sockets for communication.
+ setupCommunication
+ -- is called from "start" before "fork"ing.
+ commSetupDoneP
+ -- completes communication socket setup in the parent
+ commSetupDoneC
+ -- completes communication setup in the child process
+ commClose
+ -- frees all allocated communication resources in the parent
+ after the process has exited
+ */
+
+ /**
+ * This function is called from "KProcess::start" right before a "fork" takes
+ * place. According to
+ * the "comm" parameter this function has to initialize the "in", "out" and
+ * "err" data member of KProcess.
+ *
+ * This function should return 0 if setting the needed communication channels
+ * was successful.
+ *
+ * The default implementation is to create UNIX STREAM sockets for the communication,
+ * but you could overload this function and establish a TCP/IP communication for
+ * network communication, for example.
+ */
+ virtual int setupCommunication(Communication comm);
+
+ /**
+ * Called right after a (successful) fork on the parent side. This function
+ * will usually do some communications cleanup, like closing the reading end
+ * of the "stdin" communication channel.
+ *
+ * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and
+ * "errnot" and connect their Qt slots to the respective KProcess member functions.
+ *
+ * For a more detailed explanation, it is best to have a look at the default
+ * implementation of "setupCommunication" in kprocess.cpp.
+ */
+ virtual int commSetupDoneP();
+
+ /**
+ * Called right after a (successful) fork, but before an "exec" on the child
+ * process' side. It usually just closes the unused communication ends of
+ * "in", "out" and "err" (like the writing end of the "in" communication
+ * channel.
+ */
+ virtual int commSetupDoneC();
+
+
+ /**
+ * Immediately called after a process has exited. This function normally
+ * calls commClose to close all open communication channels to this
+ * process and emits the "processExited" signal (if the process was
+ * not running in the "DontCare" mode).
+ */
+ virtual void processHasExited(int state);
+
+ /**
+ * Should clean up the communication links to the child after it has
+ * exited. Should be called from "processHasExited".
+ */
+ virtual void commClose();
+
+
+ /**
+ * the socket descriptors for stdin/stdout/stderr.
+ */
+ int out[2];
+ int in[2];
+ int err[2];
+
+ /**
+ * The socket notifiers for the above socket descriptors.
+ */
+ QSocketNotifier *innot;
+ QSocketNotifier *outnot;
+ QSocketNotifier *errnot;
+
+ /**
+ * Lists the communication links that are activated for the child
+ * process. Should not be modified from derived classes.
+ */
+ Communication communication;
+
+ /**
+ * Called by "slotChildOutput" this function copies data arriving from the
+ * child process's stdout to the respective buffer and emits the signal
+ * "@ref receivedStderr".
+ */
+ int childOutput(int fdno);
+
+ /**
+ * Called by "slotChildOutput" this function copies data arriving from the
+ * child process's stdout to the respective buffer and emits the signal
+ * "@ref receivedStderr"
+ */
+ int childError(int fdno);
+
+ // information about the data that has to be sent to the child:
+
+ const char *input_data; // the buffer holding the data
+ int input_sent; // # of bytes already transmitted
+ int input_total; // total length of input_data
+
+ /**
+ * @ref KProcessController is a friend of KProcess because it has to have
+ * access to various data members.
+ */
+ friend class KProcessController;
+
+
+private:
+ /**
+ * Searches for a valid shell.
+ * Here is the algorithm used for finding an executable shell:
+ *
+ * @li Try the executable pointed to by the "SHELL" environment
+ * variable with white spaces stripped off
+ *
+ * @li If your process runs with uid != euid or gid != egid, a shell
+ * not listed in /etc/shells will not used.
+ *
+ * @li If no valid shell could be found, "/bin/sh" is used as a last resort.
+ */
+ QCString searchShell();
+
+ /**
+ * Used by @ref searchShell in order to find out whether the shell found
+ * is actually executable at all.
+ */
+ bool isExecutable(const QCString &filename);
+
+ // Disallow assignment and copy-construction
+ KProcess( const KProcess& );
+ KProcess& operator= ( const KProcess& );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KProcessPrivate *d;
+};
+
+class KShellProcessPrivate;
+
+/**
+* @obsolete
+*
+* This class is obsolete. Use KProcess and KProcess::setUseShell(true)
+* instead.
+*
+* @short A class derived from @ref KProcess to start child
+* processes through a shell.
+* @author Christian Czezakte <e9025461@student.tuwien.ac.at>
+* @version $Id$
+*/
+class KShellProcess: public KProcess
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Constructor
+ *
+ * By specifying the name of a shell (like "/bin/bash") you can override
+ * the mechanism for finding a valid shell as described in KProcess::searchShell()
+ */
+ KShellProcess(const char *shellname=0);
+
+ /**
+ * Destructor.
+ */
+ ~KShellProcess();
+
+ /**
+ * Starts up the process. -- For a detailed description
+ * have a look at the "start" member function and the detailed
+ * description of @ref KProcess .
+ */
+ virtual bool start(RunMode runmode = NotifyOnExit,
+ Communication comm = NoCommunication);
+
+ /**
+ * This function can be used to quote an argument string such that
+ * the shell processes it properly. This is e. g. necessary for
+ * user-provided file names which may contain spaces or quotes.
+ * It also prevents expansion of wild cards and environment variables.
+ */
+ static QString quote(const QString &arg);
+
+private:
+
+ QCString shell;
+
+ // Disallow assignment and copy-construction
+ KShellProcess( const KShellProcess& );
+ KShellProcess& operator= ( const KShellProcess& );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KShellProcessPrivate *d;
+};
+
+
+
+#endif
+
diff --git a/core/applets/obex/obex.cc b/core/applets/obex/obex.cc
new file mode 100644
index 0000000..f2ceff8
--- a/dev/null
+++ b/core/applets/obex/obex.cc
@@ -0,0 +1,119 @@
+
+
+#include "kprocess.h"
+#include "obex.h"
+
+using namespace OpieObex;
+
+Obex::Obex( QObject *parent, const char* name )
+ : QObject(parent, name )
+{
+ m_rec = 0;
+ m_send=0;
+ m_count = 0;
+};
+Obex::~Obex() {
+ delete m_rec;
+ delete m_send;
+}
+void Obex::receive() {
+ m_rec = new KProcess();
+ *m_rec << "irobex_palm3";
+ // connect to the necessary slots
+ connect(m_rec, SIGNAL(processExited(KProcess*) ),
+ this, SLOT(slotExited(KProcess*) ) );
+
+ connect(m_rec, SIGNAL(receivedStdout(KProcess*, char*, int ) ),
+ this, SLOT(slotStdOut(KProcess*, char*, int) ) );
+
+ if(!m_rec->start(KProcess::NotifyOnExit, KProcess::AllOutput) ) {
+ qWarning("could not start :(");
+ emit done( false );
+ }
+ emit currentTry(m_count );
+
+}
+void Obex::send( const QString& fileName) {
+ m_count = 0;
+ m_file = fileName;
+ sendNow();
+}
+void Obex::sendNow(){
+ if ( m_count >= 15 ) { // could not send
+ emit error(-1 );
+ }
+ // KProcess inititialisation
+ m_send = new KProcess();
+ *m_send << "irobex_palm3";
+ *m_send << m_file;
+
+ // connect to slots Exited and and StdOut
+ connect(m_send, SIGNAL(processExited(KProcess*) ),
+ this, SLOT(slotExited(KProcess*)) );
+ connect(m_send, SIGNAL(receivedStdout(KProcess*, char*, int )),
+ this, SLOT(slotStdOut(KProcess*, char*, int) ) );
+ // now start it
+ if (!m_send->start(/*KProcess::NotifyOnExit, KProcess::AllOutput*/ ) ) {
+ m_count = 15;
+ emit error(-1 );
+ }
+ // end
+ m_count++;
+ emit currentTry( m_count );
+}
+
+void Obex::slotExited(KProcess* proc ){
+ if (proc == m_rec ) { // recieve process
+ recieved();
+ }else if ( proc == m_send ) {
+ sendEnd();
+ }
+}
+void Obex::slotStdOut(KProcess* proc, char* buf, int len){
+ if ( proc == m_rec ) { // only recieve
+ QCString cstring( buf, len );
+ m_outp.append( cstring.data() );
+ }
+}
+
+void Obex::recieved() {
+ if (m_rec->normalExit() ) {
+ if ( m_rec->exitStatus() == 0 ) { // we got one
+ QString filename = parseOut();
+ emit receivedFile( filename );
+ }
+ }else{
+ emit error(-1);
+ };
+ delete m_rec;
+}
+void Obex::sendEnd() {
+ if (m_send->normalExit() ) {
+ if ( m_send->exitStatus() == 0 ) {
+ delete m_send;
+ m_send=0;
+ emit sent();
+ }else if (m_send->exitStatus() == 255 ) { // it failed maybe the other side wasn't ready
+ // let's try it again
+ delete m_send;
+ m_send = 0;
+ sendNow();
+ }
+ }else {
+ emit error( -1 );
+ delete m_send;
+ m_send = 0;
+ }
+}
+QString Obex::parseOut( ){
+ QString path;
+ QStringList list = QStringList::split("\n", m_outp);
+ QStringList::Iterator it;
+ for (it = list.begin(); it != list.end(); ++it ) {
+ if ( (*it).startsWith("Wrote" ) ) {
+ QStringList pathes = QStringList::split(' ', (*it) );
+ path = pathes[1];
+ }
+ }
+ return path;
+}
diff --git a/core/applets/obex/obex.cpp b/core/applets/obex/obex.cpp
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/core/applets/obex/obex.cpp
diff --git a/core/applets/obex/obex.h b/core/applets/obex/obex.h
new file mode 100644
index 0000000..17b8141
--- a/dev/null
+++ b/core/applets/obex/obex.h
@@ -0,0 +1,81 @@
+
+
+#ifndef OpieObex_H
+#define OpieObex_H
+
+#include <qobject.h>
+
+class KProcess;
+class QCopChannel;
+namespace OpieObex {
+ class Obex : public QObject {
+ Q_OBJECT
+ public:
+ /**
+ * Obex c'tor look
+ */
+ Obex( QObject *parent, const char* name);
+ /**
+ * d'tor
+ */
+ ~Obex();
+
+ /**
+ * Starting listening to irda after enabled by the applet
+ * a signal gets emitted when recieved a file
+ */
+ void receive();
+ void send( const QString& );
+ signals:
+
+ /**
+ * a signal
+ * @param path The path to the recieved file
+ */
+ void receivedFile( const QString& path);
+ /**
+ * error signal if the program couldn't be started or the
+ * the connection timed out
+ */
+ void error( int );
+ /**
+ * The current try to receive data
+ */
+ void currentTry(unsigned int);
+ /**
+ * signal sent The file got beamed to the remote location
+ */
+ void sent();
+ // private slots
+ void done(bool);
+
+ private:
+ uint m_count;
+ QString m_file;
+ QString m_outp;
+ KProcess *m_send;
+ KProcess *m_rec;
+
+ private slots:
+
+ /**
+ * send over palm obex
+ */
+
+ //void send(const QString&);
+
+ // the process exited
+ void slotExited(KProcess* proc) ;
+ void slotStdOut(KProcess*, char*, int);
+
+ private:
+ void sendNow();
+ QString parseOut();
+ void recieved();
+ void sendEnd();
+
+ };
+};
+
+
+#endif
diff --git a/core/applets/obex/obex.pro b/core/applets/obex/obex.pro
new file mode 100644
index 0000000..ce07ac9
--- a/dev/null
+++ b/core/applets/obex/obex.pro
@@ -0,0 +1,11 @@
+TEMPLATE = lib
+CONFIG += qt warn_on release
+HEADERS = kprocess.h kprocctrl.h obex.h
+SOURCES = kprocess.cpp kprocctrl.cpp obex.cc
+TARGET = obex
+DESTDIR = ../../plugins/applets
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += ../$(OPIEDIR)/include
+LIBS += -lqpe
+VERSION = 0.0.1
+
diff --git a/core/applets/obex/obexdlg.ui b/core/applets/obex/obexdlg.ui
new file mode 100644
index 0000000..ab58e59
--- a/dev/null
+++ b/core/applets/obex/obexdlg.ui
@@ -0,0 +1,258 @@
+<!DOCTYPE UI><UI>
+<class>ObexDlg</class>
+<author>me</author>
+<widget>
+ <class>QWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Form1</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>208</width>
+ <height>246</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>OBEX Sending</string>
+ </property>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout5</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>60</y>
+ <width>200</width>
+ <height>70</height>
+ </rect>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Sending:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer6</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Fixed</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>lblPath</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>filename</string>
+ </property>
+ <property stdset="1">
+ <name>textFormat</name>
+ <enum>RichText</enum>
+ </property>
+ <property stdset="1">
+ <name>alignment</name>
+ <set>AlignTop|AlignLeft</set>
+ </property>
+ <property>
+ <name>hAlign</name>
+ </property>
+ <property>
+ <name>vAlign</name>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer7</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer8</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout6</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>20</x>
+ <y>170</y>
+ <width>170</width>
+ <height>34</height>
+ </rect>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer9</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget>
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>PushButton2</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer10</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer11</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+</widget>
+<connections>
+ <connection>
+ <sender>PushButton2</sender>
+ <signal>clicked()</signal>
+ <receiver>Form1</receiver>
+ <slot>slotCancel()</slot>
+ </connection>
+ <slot access="public">slotCancel()</slot>
+</connections>
+</UI>
diff --git a/core/applets/obex/obeximpl.cc b/core/applets/obex/obeximpl.cc
new file mode 100644
index 0000000..a3004ab
--- a/dev/null
+++ b/core/applets/obex/obeximpl.cc
@@ -0,0 +1,50 @@
+
+
+#include "obex.h"
+#include "obeximpl.h"
+
+using namespace OpieObex;
+
+ObexImpl::ObexImpl( )
+ : QObject {
+ // register to a channel
+ m_obex = new Obex(this, "obex");
+ m_chan = new QCopChannel("QPE/Obex" );
+ cconnect(m_chan, SIGNAL(received(const QCString&, const QByteArray& ) ),
+ this, SLOT(slotMessage(const QCString&, const QByteArray&) ) );
+}
+ObexImpl::~ObexImpl() {
+ delete m_obex;
+ delete m_chan;
+}
+QRESULT ObexImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) {
+ *iface = 0;
+ if( uuid == IID_QUknown )
+ *iface = this;
+ else if( uuid == IID_ObexInterface )
+ *iface = this;
+
+ if(*iface )
+ (*iface)->addRef();
+ return QS_OK;
+
+}
+void ObexImpl::slotMessage( const QCString& msg, const QByteArray&data ) {
+ QDataStrean stream( data, IO_ReadOnly );
+ if(msg == "send(QString,QString,QString)" ) {
+ QString desc;
+ stream >> desc;
+ QString filename;
+ stream >> filename;
+ m_obex->send(filename );
+ QCopEnvelope e ("QPE/Obex", "done(QString)" ):
+ e << filename;
+ }else if( ) {
+
+ }
+}
+
+Q_EXPORT_INTERFACE()
+{
+ Q_CREATE_INSTANCE( IrdaAppletImpl )
+}
diff --git a/core/applets/obex/obeximpl.h b/core/applets/obex/obeximpl.h
new file mode 100644
index 0000000..996627b
--- a/dev/null
+++ b/core/applets/obex/obeximpl.h
@@ -0,0 +1,25 @@
+
+#ifndef OpieObexImpl_H
+#define OpieObexImpl_H
+
+#include "../obexinterface.h"
+#include <qpe/qcopenvelope_qws.h>
+
+namespace OpieObex {
+ class Obex;
+ class ObexImpl : public ObexInterface, public QObject {
+ Q_OBJECT
+ public:
+ ObexImpl();
+ virtual ObexImpl();
+ QRESULT queryInterface( const QUuid&, QUnknownInterface** );
+ Q_REFCOUNT // for reference counting (macro )
+ private:
+ ulong ref;
+ Obex* m_obex; // obex lib
+ QCopChannel *m_chan;
+ private slots:
+ void slotMessage( const QCString&, const QByteArray& );
+ };
+};
+#endif
diff --git a/core/applets/obex/processwrapper.cc b/core/applets/obex/processwrapper.cc
new file mode 100755
index 0000000..ebc7794
--- a/dev/null
+++ b/core/applets/obex/processwrapper.cc
@@ -0,0 +1,114 @@
+//
+m_rec == KProcess
+m_count = int // the number of tries to recieve
+m_send == KProcess
+m_file == QString filename to send
+m_outp == the output of the process
+
+//
+
+
+void receive() {
+ m_rec = new KProcess();
+ *m_rec << "irobex_palm3";
+ // connect to the necessary slots
+ connect(m_rec, SIGNAL(processExited(KProcess*) ),
+ this, SLOT(slotExited(KProcess*) ) );
+
+ connect(m_rec, SIGNAL(receivedStdout(KProcess*, char*, int ) ),
+ this, SLOT(slotStdOut(KProcess*, char*, int) ) );
+
+ if(!m_rec->start(KProcess::NotifyOnExit, KProcess::AllOutput) ) {
+ qWarning("could not start :(");
+ emit done( false );
+ }
+ emit try(m_count )
+}
+void send(const QString &fileName) {
+ m_count = 0;
+ m_file = fileName;
+ sendNow();
+}
+void sendNow() {
+ if ( m_count >= 15 ) { // could not send
+ emit error(-1 );
+ }
+ // KProcess inititialisation
+ m_send = new KProcess();
+ m_send << "irobex_palm3";
+ m_send << m_file;
+
+ // connect to slots Exited and and StdOut
+ connect(m_send, SIGNAL(processExited(KProcess*) ),
+ this, SLOT(slotExited(KProcess*)) );
+ connect(m_send, SIGNAL(receivedStdout(KProcess*, char*, int ) )
+ this, SLOT(slotStdOut(KProcess*, char*, int) ) );
+ // now start it
+ if (!m_send->start(/*KProcess::NotifyOnExit, KProcess::AllOutput*/ ) ) {
+ m_count = 15;
+ emit error(-1 );
+ }
+ // end
+ m_count++;
+ emit try( m_count );
+}
+
+void recieved() {
+ if (m_rec->normalExit() ) {
+ if ( m_rec->exitStatus() == 0 ) { // we got one
+ QString filename = parseOut();
+ emit recievedFile( filename );
+ }
+ }else{
+ emit error(-1);
+ };
+ delete m_rec;
+}
+
+
+void slotExited(KProcess* proc) {
+ if (proc == m_rec ) { // recieve process
+ recieved();
+ }else if ( proc == m_send ) {
+ send();
+ }
+}
+
+
+void send() {
+ if (m_send->normalExit() ) {
+ if ( m_send->exitStatus() == 0 ) {
+ delete m_send;
+ m_send=0;
+ emit sent();
+ }else if (m_send->exitStatus() == 255 ) { // it failed maybe the other side wasn't ready
+ // let's try it again
+ delete m_send;
+ m_send = 0;
+ sendNow();
+ }
+ }else {
+ emit error( -1 );
+ delete m_send;
+ m_send = 0;
+ }
+
+}
+void parseOut() {
+ QStringList list = QStringList::split("\n", m_outp);
+ QStringList::Iterator it;
+ for (it = list.begin(); it != list.end(); ++it ) {
+ if ( (*it).startsWith("Wrote" ) ) {
+ QStringList pathes = QStringList::split(' ', (*it) );
+ QString path = pathes[1];
+ }
+ }
+}
+
+void slotStdOut(KProcess* proc, char* buf, int len) {
+ if ( proc == m_rec ) { // only recieve
+ QCString cstring( buf, len );
+ m_outp.append( cstring.data() );
+ }
+
+}