delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / runtime / kioslave / floppy / program.cpp
blob076f5b9aa6535589101648fc1933a5f1ca0b62d6
1 /* This file is part of the KDE project
2 Copyright (C) 2000-2002 Alexander Neundorf <neundorf@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "program.h"
22 #include <config-runtime.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <sys/ioctl.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <sys/socket.h>
30 #include <sys/wait.h>
31 #include <signal.h>
33 #include <kdebug.h>
35 Program::Program(const QStringList &args)
36 :m_pid(0)
37 ,mArgs(args)
38 ,mStarted(false)
42 Program::~Program()
44 if (m_pid!=0)
46 ::close(mStdin[0]);
47 ::close(mStdout[0]);
48 ::close(mStderr[0]);
50 ::close(mStdin[1]);
51 ::close(mStdout[1]);
52 ::close(mStderr[1]);
54 int s(0);
55 //::wait(&s);
56 ::waitpid(m_pid,&s,0);
57 this->kill();
58 ::waitpid(m_pid,&s,WNOHANG);
62 bool Program::start()
64 if (mStarted) return false;
65 if (pipe(mStdout)==-1) return false;
66 if (pipe(mStdin )==-1) return false;
67 if (pipe(mStderr )==-1) return false;
69 int notificationPipe[2];
70 if (pipe(notificationPipe )==-1) return false;
72 m_pid=fork();
74 if (m_pid>0)
76 //parent
77 ::close(mStdin[0]);
78 ::close(mStdout[1]);
79 ::close(mStderr[1]);
80 ::close(notificationPipe[1]);
81 mStarted=true;
82 fd_set notifSet;
83 FD_ZERO(&notifSet);
84 FD_SET(notificationPipe[0],&notifSet);
85 struct timeval tv;
86 //wait up to five seconds
88 kDebug(7101)<<"**** waiting for notification";
89 //0.2 sec
90 tv.tv_sec=0;
91 tv.tv_usec=1000*200;
92 int result=::select(notificationPipe[0]+1,&notifSet,0,0,&tv);
93 /* if (result<1)
95 kDebug(7101)<<"**** waiting for notification: failed "<<result;
96 return false;
98 else*/
99 if(result==1)
101 char buf[256];
102 result=::read(notificationPipe[0],buf,256);
103 //if execvp() failed the child sends us "failed"
104 if (result>0)
105 return false;
107 kDebug(7101)<<"**** waiting for notification: succeeded"<<result;
108 return true;
110 else if (m_pid==-1)
112 //failed
113 return false;
115 else if (m_pid==0)
117 ::close(notificationPipe[0]);
119 //child
120 dup2(mStdin[0], 0);
121 dup2(mStdout[1], 1);
122 dup2(mStderr[1], 2);
124 ::close(mStdin[1]);
125 ::close(mStdout[0]);
126 ::close(mStderr[0]);
128 fcntl(mStdin[0], F_SETFD, FD_CLOEXEC);
129 fcntl(mStdout[1], F_SETFD, FD_CLOEXEC);
130 fcntl(mStderr[1], F_SETFD, FD_CLOEXEC);
132 char **arglist=(char**)malloc((mArgs.count()+1)*sizeof(char*));
133 int c=0;
135 for (QStringList::const_iterator it=mArgs.constBegin(); it!=mArgs.constEnd(); ++it)
137 arglist[c]=(char*)malloc((*it).length()+1);
138 strcpy(arglist[c], (*it).toLatin1());
139 c++;
141 arglist[mArgs.count()]=0;
142 //make parsing easier
143 putenv(strdup("LANG=C"));
144 execvp(arglist[0], arglist);
145 //we only get here if execvp() failed
146 ::write(notificationPipe[1],"failed",strlen("failed"));
147 ::close(notificationPipe[1]);
148 _exit(-1);
150 return false;
153 bool Program::isRunning()
155 return mStarted;
158 int Program::select(int secs, int usecs, bool& stdoutReceived, bool& stderrReceived/*, bool& stdinWaiting*/)
160 stdoutReceived=false;
161 stderrReceived=false;
163 struct timeval tv;
164 tv.tv_sec=secs;
165 tv.tv_usec=usecs;
167 fd_set readFDs;
168 FD_ZERO(&readFDs);
169 FD_SET(stdoutFD(),&readFDs);
170 FD_SET(stderrFD(),&readFDs);
172 int maxFD=stdoutFD();
173 if (stderrFD()>maxFD) maxFD=stderrFD();
175 /*fd_set writeFDs;
176 FD_ZERO(&writeFDs);
177 FD_SET(stdinFD(),&writeFDs);
178 if (stdinFD()>maxFD) maxFD=stdinFD();*/
179 maxFD++;
181 int result=::select(maxFD,&readFDs,/*&writeFDs*/0,0,&tv);
182 if (result>0)
184 stdoutReceived=FD_ISSET(stdoutFD(),&readFDs);
185 stderrReceived=FD_ISSET(stderrFD(),&readFDs);
186 //stdinWaiting=(FD_ISSET(stdinFD(),&writeFDs));
188 return result;
191 int Program::kill()
193 if (m_pid==0)
194 return -1;
195 return ::kill(m_pid, SIGTERM);
196 //::kill(m_pid, SIGKILL);