summaryrefslogtreecommitdiffstats
path: root/kioslave/floppy/program.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave/floppy/program.cpp')
-rw-r--r--kioslave/floppy/program.cpp201
1 files changed, 201 insertions, 0 deletions
diff --git a/kioslave/floppy/program.cpp b/kioslave/floppy/program.cpp
new file mode 100644
index 000000000..7cfd4989a
--- /dev/null
+++ b/kioslave/floppy/program.cpp
@@ -0,0 +1,201 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000-2002 Alexander Neundorf <[email protected]>
+
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+#include "program.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#include <kdebug.h>
+
+Program::Program(const QStringList &args)
+:m_pid(0)
+,mArgs(args)
+,mStarted(false)
+{
+}
+
+Program::~Program()
+{
+ if (m_pid!=0)
+ {
+ ::close(mStdin[0]);
+ ::close(mStdout[0]);
+ ::close(mStderr[0]);
+
+ ::close(mStdin[1]);
+ ::close(mStdout[1]);
+ ::close(mStderr[1]);
+
+ int s(0);
+ //::wait(&s);
+ ::waitpid(m_pid,&s,0);
+ this->kill();
+ ::waitpid(m_pid,&s,WNOHANG);
+ };
+}
+
+bool Program::start()
+{
+ if (mStarted) return false;
+ if (pipe(mStdout)==-1) return false;
+ if (pipe(mStdin )==-1) return false;
+ if (pipe(mStderr )==-1) return false;
+
+ int notificationPipe[2];
+ if (pipe(notificationPipe )==-1) return false;
+
+ m_pid=fork();
+
+ if (m_pid>0)
+ {
+ //parent
+ ::close(mStdin[0]);
+ ::close(mStdout[1]);
+ ::close(mStderr[1]);
+ ::close(notificationPipe[1]);
+ mStarted=true;
+ fd_set notifSet;
+ FD_ZERO(&notifSet);
+ FD_SET(notificationPipe[0],&notifSet);
+ struct timeval tv;
+ //wait up to five seconds
+
+ kdDebug(7101)<<"**** waiting for notification"<<endl;
+ //0.2 sec
+ tv.tv_sec=0;
+ tv.tv_usec=1000*200;
+ int result=::select(notificationPipe[0]+1,&notifSet,0,0,&tv);
+/* if (result<1)
+ {
+ kdDebug(7101)<<"**** waiting for notification: failed "<<result<<endl;
+ return false;
+ }
+ else*/
+ if(result==1)
+ {
+ char buf[256];
+ result=::read(notificationPipe[0],buf,256);
+ //if execvp() failed the child sends us "failed"
+ if (result>0)
+ return false;
+ };
+ kdDebug(7101)<<"**** waiting for notification: succeeded"<<result<<endl;
+ return true;
+ }
+ else if (m_pid==-1)
+ {
+ //failed
+ return false;
+ }
+ else if (m_pid==0)
+ {
+ ::close(notificationPipe[0]);
+
+ //child
+ ::close(0); // close the stdios
+ ::close(1);
+ ::close(2);
+
+ dup(mStdin[0]);
+ dup(mStdout[1]);
+ dup(mStderr[1]);
+
+ ::close(mStdin[1]);
+ ::close(mStdout[0]);
+ ::close(mStderr[0]);
+
+ fcntl(mStdin[0], F_SETFD, FD_CLOEXEC);
+ fcntl(mStdout[1], F_SETFD, FD_CLOEXEC);
+ fcntl(mStderr[1], F_SETFD, FD_CLOEXEC);
+
+ char **arglist=(char**)malloc((mArgs.count()+1)*sizeof(char*));
+ int c=0;
+
+ for (QStringList::Iterator it=mArgs.begin(); it!=mArgs.end(); ++it)
+ {
+ arglist[c]=(char*)malloc((*it).length()+1);
+ strcpy(arglist[c], (*it).latin1());
+ c++;
+ }
+ arglist[mArgs.count()]=0;
+ //make parsing easier
+ putenv(strdup("LANG=C"));
+ execvp(arglist[0], arglist);
+ //we only get here if execvp() failed
+ ::write(notificationPipe[1],"failed",strlen("failed"));
+ ::close(notificationPipe[1]);
+ _exit(-1);
+ };
+ return false;
+}
+
+bool Program::isRunning()
+{
+ return mStarted;
+}
+
+int Program::select(int secs, int usecs, bool& stdoutReceived, bool& stderrReceived/*, bool& stdinWaiting*/)
+{
+ stdoutReceived=false;
+ stderrReceived=false;
+
+ struct timeval tv;
+ tv.tv_sec=secs;
+ tv.tv_usec=usecs;
+
+ fd_set readFDs;
+ FD_ZERO(&readFDs);
+ FD_SET(stdoutFD(),&readFDs);
+ FD_SET(stderrFD(),&readFDs);
+
+ int maxFD=stdoutFD();
+ if (stderrFD()>maxFD) maxFD=stderrFD();
+
+ /*fd_set writeFDs;
+ FD_ZERO(&writeFDs);
+ FD_SET(stdinFD(),&writeFDs);
+ if (stdinFD()>maxFD) maxFD=stdinFD();*/
+ maxFD++;
+
+ int result=::select(maxFD,&readFDs,/*&writeFDs*/0,0,&tv);
+ if (result>0)
+ {
+ stdoutReceived=FD_ISSET(stdoutFD(),&readFDs);
+ stderrReceived=FD_ISSET(stderrFD(),&readFDs);
+ //stdinWaiting=(FD_ISSET(stdinFD(),&writeFDs));
+ };
+ return result;
+}
+
+int Program::kill()
+{
+ if (m_pid==0)
+ return -1;
+ return ::kill(m_pid, SIGTERM);
+ //::kill(m_pid, SIGKILL);
+}
+