Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

filetransfer.cpp

Go to the documentation of this file.
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 //    m_fd = ::open("/dev/ttyS0", O_RDWR);
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         /* exec */
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         /* we should never return from here */
00073         execlp("sz", "sz", verbose,  binray, file.latin1(), typus, NULL );
00074 
00075         /* communication for error!*/
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             /* len == 1 start up failed */
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             // len == 0 or something like this
00098             break;
00099         }
00100         if ( m_info[0] )
00101             close( m_info[0] );
00102 
00103 
00104 
00105         /* replace by QSocketNotifier!!! */
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  * let's call the one with the filename
00123  */
00124 void FileTransfer::sendFile( const QFile& file ) {
00125     sendFile( file.name() );
00126 }
00127 
00128 /*
00129  * setting up communication
00130  * between parent child and ioLayer
00131  */
00132 void FileTransfer::setupChild() {
00133     /*
00134      * we do not want to read from our
00135      * information channel
00136      */
00137     if (m_info[0] )
00138         close(m_info[0] );
00139     /*
00140      * FD_CLOEXEC will close the
00141      * fd on successful exec
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      * now set the communication
00150      * m_fd STDIN_FILENO
00151      *      STDOUT_FILENO
00152      *      STDERR_FILENO
00153      */
00154     dup2( m_fd, STDIN_FILENO );
00155     dup2( m_fd, STDOUT_FILENO );
00156     dup2( m_comm[1], STDERR_FILENO );
00157 }
00158 
00159 /*
00160  * read from the stderr of the child
00161  * process
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         // printf("%c", ar[i] );
00168     }
00169     ar.resize( len );
00170     QString str( ar );
00171     QStringList lis = QStringList::split(' ', str );
00172     /*
00173      * Transfer finished.. either complete or incomplete
00174      */
00175     if ( lis[0].simplifyWhiteSpace() == "Transfer" ) {
00176         return;
00177     }
00178     /*
00179      * do progress reading
00180      */
00181     slotProgress( lis );
00182 
00183 
00184 }
00185 /*
00186  * find the progress
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     // Data looks like this
00200     //  0      1         2          3      4     5
00201     // Bytes Sent 65536/11534336 BPS:7784 ETA 24:33
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     // speed
00216     progi = QStringList::split(':', list[3].simplifyWhiteSpace() );
00217     bps = progi[1].toInt();
00218 
00219     // time
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 }

Generated on Sat Nov 5 16:16:49 2005 for OPIE by  doxygen 1.4.2