File indexing completed on 2024-04-21 15:55:40
0001 /*************************************************************************** 0002 begin : Sat Sept 9 2003 0003 edit : Wed Jan 14 2009 0004 copyright : (C) 2003 by Jeroen Wijnhout, 2007-2009 by Thomas Braun 0005 email : Jeroen.Wijnhout@kdemail.net 0006 ***************************************************************************/ 0007 0008 /*************************************************************************** 0009 * * 0010 * This program is free software; you can redistribute it and/or modify * 0011 * it under the terms of the GNU General Public License as published by * 0012 * the Free Software Foundation; either version 2 of the License, or * 0013 * (at your option) any later version. * 0014 * * 0015 ***************************************************************************/ 0016 0017 #include "kilelyxserver.h" 0018 0019 #include <sys/stat.h> 0020 #include <stdlib.h> //getenv 0021 #ifndef _MSC_VER 0022 #include <unistd.h> //read 0023 #else 0024 #include <io.h> 0025 #endif 0026 #include <fcntl.h> 0027 0028 #include "kileactions.h" 0029 #include "kiledebug.h" 0030 0031 #include <QDir> 0032 #include <QFile> 0033 #include <QFileInfo> 0034 #include <QSocketNotifier> 0035 #include <QRegExp> 0036 0037 #include <KLocalizedString> 0038 0039 KileLyxServer::KileLyxServer(bool startMe) : 0040 m_running(false) 0041 { 0042 #ifndef _MSC_VER 0043 m_perms = S_IRUSR | S_IWUSR; 0044 #else 0045 m_perms = 0; 0046 #endif 0047 KILE_DEBUG_MAIN << "===KileLyxServer::KileLyxServer(bool" << startMe << ")=== "; 0048 0049 m_tempDir = new QTemporaryDir(); 0050 if(!m_tempDir->isValid()) { 0051 KILE_DEBUG_MAIN << "an error occurred while creating a tempfile" ; 0052 return; 0053 } 0054 0055 m_links << ".lyxpipe.in" << ".lyx/lyxpipe.in"; 0056 m_links << ".lyxpipe.out" << ".lyx/lyxpipe.out"; 0057 0058 for(int i = 0; i < m_links.count() ; ++i) { 0059 m_pipes.append( m_tempDir->path() + QDir::separator() + m_links[i] ); 0060 m_links[i].prepend(QDir::homePath() + QDir::separator() ); 0061 KILE_DEBUG_MAIN << "m_pipes[" << i << "]=" << m_pipes[i]; 0062 KILE_DEBUG_MAIN << "m_links[" << i << "]=" << m_links[i]; 0063 } 0064 0065 if(startMe) { 0066 start(); 0067 } 0068 } 0069 0070 KileLyxServer::~KileLyxServer() 0071 { 0072 stop(); 0073 removePipes(); 0074 0075 delete m_tempDir; 0076 0077 for(QList<QFile*>::iterator i = m_pipeIn.begin(); i != m_pipeIn.end(); ++i) { 0078 delete *i; 0079 } 0080 0081 for(QList<QSocketNotifier*>::iterator i = m_notifier.begin(); i != m_notifier.end(); ++i) { 0082 delete *i; 0083 } 0084 } 0085 0086 bool KileLyxServer::start() 0087 { 0088 if (m_running) { 0089 stop(); 0090 } 0091 0092 KILE_DEBUG_MAIN << "Starting the LyX server..."; 0093 0094 if (openPipes()) { 0095 QSocketNotifier *notifier; 0096 for(QList<QFile*>::iterator it = m_pipeIn.begin(); it != m_pipeIn.end(); ++it) { 0097 if ((*it)->fileName().right(3) == ".in" ) { 0098 notifier = new QSocketNotifier((*it)->handle(), QSocketNotifier::Read, this); 0099 connect(notifier, SIGNAL(activated(int)), this, SLOT(receive(int))); 0100 m_notifier.append(notifier); 0101 KILE_DEBUG_MAIN << "Created notifier for " << (*it)->fileName(); 0102 } 0103 else { 0104 KILE_DEBUG_MAIN << "No notifier created for " << (*it)->fileName(); 0105 } 0106 } 0107 m_running=true; 0108 } 0109 0110 return m_running; 0111 } 0112 0113 bool KileLyxServer::openPipes() 0114 { 0115 KILE_DEBUG_MAIN << "===bool KileLyxServer::openPipes()==="; 0116 0117 #ifdef Q_OS_WIN 0118 qCritical() << "kile's lyx server can not work on windows since we don't have pipes"; 0119 qCritical() << "And also lyx itself does not support it, see https://wiki.lyx.org/LyX/LyXServer"; 0120 return false; 0121 #else 0122 bool opened = false; 0123 QFileInfo pipeInfo,linkInfo; 0124 QFile *file; 0125 struct stat buf; 0126 struct stat *stats = &buf; 0127 0128 QDir lyxDir(QDir::homePath() + QDir::separator() + ".lyx"); 0129 if(!lyxDir.exists()) { 0130 KILE_DEBUG_MAIN << "Directory " << lyxDir.absolutePath() << " does not exist"; 0131 if(mkdir(QFile::encodeName( lyxDir.path() ), m_perms | S_IXUSR) == -1) { 0132 qCritical() << "Could not create directory"; 0133 } 0134 else { 0135 KILE_DEBUG_MAIN << "Directory created successfully"; 0136 } 0137 } 0138 0139 for(int i = 0; i < m_pipes.count(); ++i) { 0140 pipeInfo.setFile(m_pipes[i]); 0141 linkInfo.setFile(m_links[i]); 0142 0143 QFile::remove(linkInfo.absoluteFilePath()); 0144 linkInfo.refresh(); 0145 0146 KILE_DEBUG_MAIN << "pipe=" << m_pipes[i] << Qt::endl; 0147 KILE_DEBUG_MAIN << "link=" << m_links[i] << Qt::endl; 0148 0149 if(!pipeInfo.exists()) { 0150 //create the dir first 0151 if(!QFileInfo::exists(pipeInfo.absolutePath())) { 0152 if(mkdir(QFile::encodeName( pipeInfo.path() ), m_perms | S_IXUSR) == -1) { 0153 qCritical() << "Could not create directory for pipe"; 0154 continue; 0155 } 0156 else { 0157 KILE_DEBUG_MAIN << "Created directory " << pipeInfo.path(); 0158 } 0159 } 0160 if (mkfifo(QFile::encodeName( pipeInfo.absoluteFilePath() ), m_perms) != 0) { 0161 qCritical() << "Could not create pipe: " << pipeInfo.absoluteFilePath(); 0162 continue; 0163 } 0164 else { 0165 KILE_DEBUG_MAIN << "Created pipe: " << pipeInfo.absoluteFilePath(); 0166 } 0167 } 0168 0169 if(symlink(QFile::encodeName(pipeInfo.absoluteFilePath()),QFile::encodeName(linkInfo.absoluteFilePath())) != 0) { 0170 qCritical() << "Could not create symlink: " << linkInfo.absoluteFilePath() << " --> " << pipeInfo.absoluteFilePath(); 0171 continue; 0172 } 0173 0174 // the file object will be deleted at the shutdown of the server in KileLyxServer::stop() 0175 file = new QFile(pipeInfo.absoluteFilePath()); 0176 pipeInfo.refresh(); 0177 0178 if(pipeInfo.exists() && file->open(QIODevice::ReadWrite)) { // in that order we don't create the file if it does not exist 0179 KILE_DEBUG_MAIN << "Opened file: " << pipeInfo.absoluteFilePath(); 0180 fstat(file->handle(),stats); 0181 if(!S_ISFIFO(stats->st_mode)) { 0182 qCritical() << "The file " << pipeInfo.absoluteFilePath() << "we just created is not a pipe!"; 0183 file->close(); 0184 delete file; 0185 continue; 0186 } 0187 else { 0188 m_pipeIn.append(file); 0189 m_file.insert(file->handle(), file); 0190 opened = true; 0191 KILE_DEBUG_MAIN << "everything is correct :)" << Qt::endl; 0192 } 0193 } 0194 else { 0195 qCritical() << "Could not open " << pipeInfo.absoluteFilePath(); 0196 } 0197 } 0198 return opened; 0199 #endif 0200 } 0201 0202 void KileLyxServer::stop() 0203 { 0204 KILE_DEBUG_MAIN << "Stopping the LyX server..."; 0205 0206 for(QList<QFile*>::iterator it = m_pipeIn.begin(); it != m_pipeIn.end(); ++it) { 0207 (*it)->close(); 0208 delete *it; 0209 } 0210 0211 for(QList<QSocketNotifier*>::iterator i = m_notifier.begin(); i != m_notifier.end(); ++i) { 0212 delete *i; 0213 } 0214 0215 m_pipeIn.clear(); 0216 m_notifier.clear(); 0217 0218 m_running=false; 0219 } 0220 0221 void KileLyxServer::removePipes() 0222 { 0223 for (int i = 0; i < m_links.count(); ++i) { 0224 QFile::remove(m_links[i]); 0225 } 0226 for (int i = 0; i < m_pipes.count(); ++i) { 0227 QFile::remove(m_pipes[i]); 0228 } 0229 } 0230 0231 void KileLyxServer::processLine(const QString &line) 0232 { 0233 KILE_DEBUG_MAIN << "===void KileLyxServer::processLine(const QString " << line << ")==="; 0234 0235 QRegExp reCite(":citation-insert:(.*)$"); 0236 QRegExp reBibtexdbadd(":bibtex-database-add:(.*)$"); 0237 QRegExp rePaste(":paste:(.*)$"); 0238 0239 if(line.indexOf(reCite) != -1) { 0240 emit(insert(KileAction::TagData(i18n("Cite"), "\\cite{"+reCite.cap(1)+'}'))); 0241 } 0242 else if(line.indexOf(reBibtexdbadd) != -1) { 0243 emit(insert(KileAction::TagData(i18n("Add BibTeX database"), "\\bibliography{"+ reBibtexdbadd.cap(1) + '}'))); 0244 } 0245 else if(line.indexOf(rePaste) != -1) { 0246 emit(insert(KileAction::TagData(i18n("Paste"), rePaste.cap(1)))); 0247 } 0248 } 0249 0250 void KileLyxServer::receive(int fd) 0251 { 0252 if(m_file[fd]) { 0253 int bytesRead; 0254 int const size = 256; 0255 char buffer[size]; 0256 if((bytesRead = read(fd, buffer, size - 1)) > 0) { 0257 buffer[bytesRead] = '\0'; // turn it into a c string 0258 QStringList cmds = QString(buffer).trimmed().split('\n'); 0259 for(int i = 0; i < cmds.count(); ++i) { 0260 processLine(cmds[i]); 0261 } 0262 } 0263 } 0264 } 0265