Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kcontrol / kfontinst / kio / Server.cpp
blob5bd85e0ef4eb119068bddc82f096c1d0a208b659
1 /*
2 * KFontInst - KDE Font Installer
4 * Copyright 2003-2007 Craig Drummond <craig@kde.org>
6 * ----
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 // This file contains code taken from kdebase/runtime/kdesu/kdesud/kdesud.cpp
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <pwd.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/un.h>
37 #include <sys/stat.h>
38 #include <signal.h>
39 #include <QtCore/QFile>
40 #include <QtCore/QDir>
41 #include <QtCore/QFileInfo>
42 #include <config-workspace.h>
43 #include <KDE/KStandardDirs>
44 #include <KDE/KDebug>
45 #include "Server.h"
46 #include "Socket.h"
47 #include "Misc.h"
49 #ifndef SUN_LEN
50 #define SUN_LEN(ptr) ((socklen_t) (((struct sockaddr_un *) 0)->sun_path) \
51 + strlen ((ptr)->sun_path))
52 #endif
54 typedef unsigned ksocklen_t;
56 namespace KFI
59 #define KFI_SOCKET_SUFFIX "kio_fonts_"
60 #define KFI_SOCKET_SUFFIX_LEN 10
61 CServer::CServer()
62 : itsFd(-1),
63 itsOpen(false)
65 QString sockName;
66 int thisPid(getpid());
68 sockName.sprintf(KFI_SOCKET_SUFFIX"%d", thisPid);
70 QString nameAndPath(KStandardDirs::locateLocal("socket", sockName));
72 itsName=QFile::encodeName(nameAndPath);
74 // Remove any old sockets that are no longer active
75 QDir dir(Misc::getDir(nameAndPath));
76 QStringList nameFilters;
78 nameFilters.append(KFI_SOCKET_SUFFIX"*");
79 dir.setFilter(QDir::System|QDir::CaseSensitive);
80 dir.setNameFilters(nameFilters);
82 QFileInfoList list(dir.entryInfoList());
84 for (int i = 0; i < list.size(); ++i)
86 QFileInfo fileInfo(list.at(i));
88 if(fileInfo.ownerId()==getuid() && fileInfo.groupId()==getgid())
90 int pid=fileInfo.fileName().mid(KFI_SOCKET_SUFFIX_LEN).toInt();
92 if(0!=pid && pid!=thisPid && 0!=kill(pid, 0))
93 ::unlink(QFile::encodeName(fileInfo.absoluteFilePath()));
98 bool CServer::open()
100 if(itsOpen)
101 return true;
103 ksocklen_t addrlen;
104 struct stat s;
106 int stat_err=lstat(itsName, &s);
107 if(!stat_err && S_ISLNK(s.st_mode))
109 kWarning() << "Someone is running a symlink attack on you" ;
110 if(unlink(itsName))
112 kWarning() << "Could not delete symlink" ;
113 return false;
117 if (!access(itsName, R_OK|W_OK))
119 kWarning() << "stale socket exists" ;
120 if (unlink(itsName))
122 kWarning() << "Could not delete stale socket" ;
123 return false;
127 itsFd = socket(PF_UNIX, SOCK_STREAM, 0);
128 if (itsFd < 0)
130 kError() << "socket(): " << strerror(errno) << endl;
131 return false;
134 struct sockaddr_un addr;
135 addr.sun_family = AF_UNIX;
136 strncpy(addr.sun_path, itsName, sizeof(addr.sun_path)-1);
137 addr.sun_path[sizeof(addr.sun_path)-1] = '\000';
138 addrlen = SUN_LEN(&addr);
139 if (bind(itsFd, (struct sockaddr *)&addr, addrlen) < 0)
141 kError() << "bind(): " << strerror(errno) << endl;
142 return false;
145 struct linger lin;
146 lin.l_onoff = lin.l_linger = 0;
147 if (setsockopt(itsFd, SOL_SOCKET, SO_LINGER, (char *) &lin,
148 sizeof(linger)) < 0)
150 kError() << "setsockopt(SO_LINGER): " << strerror(errno) << endl;
151 return false;
154 int opt = 1;
155 if (setsockopt(itsFd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt,
156 sizeof(opt)) < 0)
158 kError() << "setsockopt(SO_REUSEADDR): " << strerror(errno) << endl;
159 return false;
161 opt = 1;
162 if (setsockopt(itsFd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
163 sizeof(opt)) < 0)
165 kError() << "setsockopt(SO_KEEPALIVE): " << strerror(errno) << endl;
166 return false;
168 chmod(itsName, 0600);
169 if (listen(itsFd, 1) < 0)
171 kError() << "listen(): " << strerror(errno) << endl;
172 return false;
175 itsOpen=true;
176 return true;
179 void CServer::close()
181 if(itsFd>=0)
182 ::close(itsFd);
183 if(!itsName.isEmpty())
184 unlink(itsName);
185 itsOpen=false;
188 CSocket * CServer::waitForClient(int timeout)
190 if(itsOpen)
191 for(;;)
193 fd_set fdSet;
194 struct timeval tv;
196 tv.tv_sec = timeout;
197 tv.tv_usec = 0;
199 FD_ZERO(&fdSet);
200 FD_SET(itsFd, &fdSet);
202 if(select(itsFd + 1, &fdSet, NULL, NULL, &tv)<0)
203 if (errno == EINTR)
204 continue;
205 else
207 kError() << "select(): " << strerror(errno) << endl;
208 break;
211 if(FD_ISSET(itsFd, &fdSet))
213 struct sockaddr_un clientname;
214 ksocklen_t addrlen(64);
215 int fd(-1);
217 if((fd=accept(itsFd, (struct sockaddr *) &clientname, &addrlen))>=0)
218 return new CSocket(fd);
220 else
222 kError() << "select timeout" << endl;
223 break;
227 return NULL;