1/* vi: ts=8 sts=4 sw=4
2 *
3 * This file is part of the KDE project, module kdesu.
4 * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
5 *
6 * This is free software; you can use this library under the GNU Library
7 * General Public License, version 2. See the file "COPYING.LIB" for the
8 * exact licensing terms.
9 *
10 * stub.cpp: Conversation with kdesu_stub.
11 */
12
13#include "stub.h"
14#include "kcookie.h"
15
16#include <config.h>
17#include <stdlib.h>
18#include <unistd.h>
19
20#include <QtCore/QBool>
21
22#include <kdebug.h>
23
24extern int kdesuDebugArea();
25
26namespace KDESu {
27
28using namespace KDESuPrivate;
29
30StubProcess::StubProcess()
31 : d(0)
32{
33 m_User = "root";
34 m_Scheduler = SchedNormal;
35 m_Priority = 50;
36 m_pCookie = new KCookie;
37 m_bXOnly = true;
38}
39
40
41StubProcess::~StubProcess()
42{
43 delete m_pCookie;
44}
45
46
47void StubProcess::setCommand(const QByteArray &command)
48{
49 m_Command = command;
50}
51
52
53void StubProcess::setUser(const QByteArray &user)
54{
55 m_User = user;
56}
57
58
59void StubProcess::setXOnly(bool xonly)
60{
61 m_bXOnly = xonly;
62}
63
64
65void StubProcess::setPriority(int prio)
66{
67 if (prio > 100)
68 m_Priority = 100;
69 else if (prio < 0)
70 m_Priority = 0;
71 else
72 m_Priority = prio;
73}
74
75
76void StubProcess::setScheduler(int sched)
77{
78 m_Scheduler = sched;
79}
80
81
82QByteArray StubProcess::commaSeparatedList(const QList<QByteArray> &lst)
83{
84 QByteArray str;
85 for (int i = 0; i < lst.count(); ++i) {
86 str += ',';
87 str += lst.at(i);
88 }
89 return str;
90}
91
92void StubProcess::writeString(const QByteArray &str)
93{
94 QByteArray out;
95 out.reserve(str.size() + 8);
96 for (int i = 0; i < str.size(); i++) {
97 uchar c = str.at(i);
98 if (c < 32) {
99 out.append('\\');
100 out.append(c + '@');
101 } else if (c == '\\') {
102 out.append('\\');
103 out.append('/');
104 } else {
105 out.append(c);
106 }
107 }
108 writeLine(out);
109}
110
111/*
112 * Map pid_t to a signed integer type that makes sense for QByteArray;
113 * only the most common sizes 16 bit and 32 bit are special-cased.
114 */
115template<int T> struct PIDType { typedef pid_t PID_t; } ;
116template<> struct PIDType<2> { typedef qint16 PID_t; } ;
117template<> struct PIDType<4> { typedef qint32 PID_t; } ;
118
119/*
120 * Conversation with kdesu_stub. This is how we pass the authentication
121 * tokens (X11) and other stuff to kdesu_stub.
122 * return values: -1 = error, 0 = ok, 1 = kill me
123 */
124
125int StubProcess::ConverseStub(int check)
126{
127 QByteArray line, tmp;
128
129 while (1)
130 {
131 line = readLine();
132 if (line.isNull())
133 return -1;
134
135 if (line == "kdesu_stub")
136 {
137 // This makes parsing a lot easier.
138 enableLocalEcho(false);
139 if (check) writeLine("stop");
140 else writeLine("ok");
141 break;
142 }
143 }
144
145 while (1)
146 {
147 line = readLine();
148 if (line.isNull())
149 return -1;
150
151 if (line == "display") {
152 writeLine(display());
153 } else if (line == "display_auth") {
154#ifdef Q_WS_X11
155 writeLine(displayAuth());
156#else
157 writeLine("");
158#endif
159 } else if (line == "command") {
160 writeString(m_Command);
161 } else if (line == "path") {
162 QByteArray path = qgetenv("PATH");
163 if (!path.isEmpty() && path[0] == ':')
164 path = path.mid(1);
165 if (m_User == "root") {
166 if (!path.isEmpty())
167 path = "/sbin:/bin:/usr/sbin:/usr/bin:" + path;
168 else
169 path = "/sbin:/bin:/usr/sbin:/usr/bin";
170 }
171 writeLine(path);
172 } else if (line == "user") {
173 writeLine(m_User);
174 } else if (line == "priority") {
175 tmp.setNum(m_Priority);
176 writeLine(tmp);
177 } else if (line == "scheduler") {
178 if (m_Scheduler == SchedRealtime) writeLine("realtime");
179 else writeLine("normal");
180 } else if (line == "xwindows_only") {
181 if (m_bXOnly) writeLine("no");
182 else writeLine("yes");
183 } else if (line == "app_startup_id") {
184 QList<QByteArray> env = environment();
185 QByteArray tmp;
186 for(int i = 0; i < env.count(); ++i)
187 {
188 const char startup_env[] = "DESKTOP_STARTUP_ID=";
189 if (env.at(i).startsWith(startup_env))
190 tmp = env.at(i).mid(sizeof(startup_env) - 1);
191 }
192 if( tmp.isEmpty())
193 tmp = "0"; // krazy:exclude=doublequote_chars
194 writeLine(tmp);
195 } else if (line == "app_start_pid") { // obsolete
196 // Force the pid_t returned from getpid() into
197 // something QByteArray understands; avoids ambiguity
198 // between short and unsigned short in particular.
199 tmp.setNum((PIDType<sizeof(pid_t)>::PID_t)(getpid()));
200 writeLine(tmp);
201 } else if (line == "environment") { // additional env vars
202 QList<QByteArray> env = environment();
203 for (int i = 0; i < env.count(); ++i)
204 writeString(env.at(i));
205 writeLine( "" );
206 } else if (line == "end") {
207 return 0;
208 } else
209 {
210 kWarning(kdesuDebugArea()) << k_lineinfo << "Unknown request:" << line;
211 return 1;
212 }
213 }
214
215 return 0;
216}
217
218
219QByteArray StubProcess::display()
220{
221 return m_pCookie->display();
222}
223
224
225#ifdef Q_WS_X11
226QByteArray StubProcess::displayAuth()
227{
228 return m_pCookie->displayAuth();
229}
230#endif
231
232
233void StubProcess::virtual_hook( int id, void* data )
234{ PtyProcess::virtual_hook( id, data ); }
235
236}
237