00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <errno.h>
00004 #include <fcntl.h>
00005 #include <unistd.h>
00006
00007 #include <qsocketnotifier.h>
00008
00009 #include "procctl.h"
00010 #include "filetransfer.h"
00011
00012
00013 FileTransfer::FileTransfer( Type t, IOLayer* lay )
00014 : FileTransferLayer( lay ), m_type( t ), m_pid ( 0 ) {
00015 signal(SIGPIPE, SIG_IGN );
00016
00017 m_pid = 0;
00018 m_not = 0l;
00019 m_proc = 0l;
00020 }
00021 FileTransfer::~FileTransfer() {
00022 }
00023
00032 void FileTransfer::sendFile( const QString& file ) {
00033 m_prog =-1;
00034 m_fd = layer()->rawIO();
00035
00036
00037
00038 m_file = file;
00039 if ( pipe( m_comm ) < 0 )
00040 m_comm[0] = m_comm[1] = 0;
00041 if ( pipe( m_info ) < 0 )
00042 m_info[0] = m_info[1] = 0;
00043
00044
00045 m_pid = fork();
00046 switch( m_pid ) {
00047 case -1:
00048 emit error( StartError, tr("Was not able to fork") );
00049 slotExec();
00050 break;
00051 case 0:{
00052 setupChild();
00053
00054 char* verbose = "-vv";
00055 char* binray = "-b";
00056
00057
00058 char* typus;
00059 switch(m_type ) {
00060 default:
00061 case SZ:
00062 typus = "";
00063 break;
00064 case SX:
00065 typus = "-X";
00066 break;
00067 case SY:
00068 typus = "--ymodem";
00069 break;
00070 }
00071
00072
00073 execlp("sz", "sz", verbose, binray, file.latin1(), typus, NULL );
00074
00075
00076 char resultByte =1;
00077 if (m_info[1] )
00078 write(m_info[1], &resultByte, 1 );
00079 _exit( -1 );
00080 break;
00081 }
00082 default:{
00083 if ( m_info[1] )
00084 close( m_info[1] );
00085 if ( m_info[0] ) for (;;) {
00086 char resultByte; int len;
00087 len = read(m_info[0], &resultByte, 1 );
00088
00089 if ( len == 1 ) {
00090 emit error( StartError, tr("Could not start") );
00091 return;
00092 }
00093 if ( len == -1 )
00094 if ( (errno == ECHILD ) || (errno == EINTR ) )
00095 continue;
00096
00097
00098 break;
00099 }
00100 if ( m_info[0] )
00101 close( m_info[0] );
00102
00103
00104
00105
00106 m_not = new QSocketNotifier(m_comm[0], QSocketNotifier::Read );
00107 connect(m_not, SIGNAL(activated(int) ),
00108 this, SLOT(slotRead() ) );
00109 if ( pipe(m_term) < 0 )
00110 m_term[0] = m_term[1] = 0;
00111
00112 ProcCtl::self()->add(m_pid, m_term[1] );
00113 m_proc = new QSocketNotifier(m_term[0], QSocketNotifier::Read );
00114 connect(m_proc, SIGNAL(activated(int) ),
00115 this, SLOT(slotExec() ) );
00116
00117 }
00118 break;
00119 }
00120 }
00121
00122
00123
00124 void FileTransfer::sendFile( const QFile& file ) {
00125 sendFile( file.name() );
00126 }
00127
00128
00129
00130
00131
00132 void FileTransfer::setupChild() {
00133
00134
00135
00136
00137 if (m_info[0] )
00138 close(m_info[0] );
00139
00140
00141
00142
00143 if (m_info[1] )
00144 fcntl(m_info[1], F_SETFD, FD_CLOEXEC );
00145
00146 if (m_comm[0] )
00147 close( m_comm[0] );
00148
00149
00150
00151
00152
00153
00154 dup2( m_fd, STDIN_FILENO );
00155 dup2( m_fd, STDOUT_FILENO );
00156 dup2( m_comm[1], STDERR_FILENO );
00157 }
00158
00159
00160
00161
00162
00163 void FileTransfer::slotRead() {
00164 QByteArray ar(4096);
00165 int len = read(m_comm[0], ar.data(), 4096 );
00166 for (int i = 0; i < len; i++ ) {
00167
00168 }
00169 ar.resize( len );
00170 QString str( ar );
00171 QStringList lis = QStringList::split(' ', str );
00172
00173
00174
00175 if ( lis[0].simplifyWhiteSpace() == "Transfer" ) {
00176 return;
00177 }
00178
00179
00180
00181 slotProgress( lis );
00182
00183
00184 }
00185
00186
00187
00188 void FileTransfer::slotProgress( const QStringList& list ) {
00189 if ( m_type != SZ )
00190 return;
00191 bool complete = true;
00192 int min, sec;
00193 int bps;
00194 unsigned long sent, total;
00195
00196 min = sec = bps = -1;
00197 sent = total = 0;
00198
00199
00200
00201
00202 QStringList progi = QStringList::split('/', list[2].simplifyWhiteSpace() );
00203 sent = progi[0].toULong(&complete );
00204 if (!complete ) return;
00205
00206 total = progi[1].toULong(&complete );
00207 if (!complete || total == 0) {
00208 return;
00209 }
00210
00211
00212 double pro = (double)sent/total;
00213 int prog = pro * 100;
00214
00215
00216 progi = QStringList::split(':', list[3].simplifyWhiteSpace() );
00217 bps = progi[1].toInt();
00218
00219
00220 progi = QStringList::split(':', list[5].simplifyWhiteSpace() );
00221 min = progi[0].toInt();
00222 sec = progi[1].toInt();
00223
00224
00225 if ( prog > m_prog ) {
00226 m_prog = prog;
00227 emit progress(m_file, m_prog, bps, -1, min , sec );
00228 }
00229
00230 }
00231 void FileTransfer::cancel() {
00232 if(m_pid > 0) ::kill(m_pid,9 );
00233
00234 }
00235 void FileTransfer::slotExec() {
00236 char buf[2];
00237 ::read(m_term[0], buf, 1 );
00238 delete m_proc;
00239 delete m_not;
00240 m_proc = m_not = 0l;
00241 close( m_term[0] );
00242 close( m_term[1] );
00243 close( m_comm[0] );
00244 close( m_comm[1] );
00245 layer()->closeRawIO( m_fd );
00246 emit sent();
00247 m_pid = 0;
00248 }