• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • util
kshell_unix.cpp
Go to the documentation of this file.
1/*
2 This file is part of the KDE libraries
3
4 Copyright (c) 2003,2007 Oswald Buddenhagen <ossi@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "kshell.h"
23#include "kshell_p.h"
24
25#include <kuser.h>
26
27#include <QtCore/QChar>
28#include <QtCore/QStringList>
29
30static int fromHex( QChar cUnicode )
31{
32 char c = cUnicode.toLatin1 ();
33
34 if (c >= '0' && c <= '9')
35 return c - '0';
36 else if (c >= 'A' && c <= 'F')
37 return c - 'A' + 10;
38 else if (c >= 'a' && c <= 'f')
39 return c - 'a' + 10;
40 return -1;
41}
42
43inline static bool isQuoteMeta( QChar cUnicode )
44{
45#if 0 // it's not worth it, especially after seeing gcc's asm output ...
46 static const uchar iqm[] = {
47 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00
49 }; // \'"$
50
51 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
52#else
53 char c = cUnicode.toLatin1();
54 return c == '\\' || c == '\'' || c == '"' || c == '$';
55#endif
56}
57
58inline static bool isMeta( QChar cUnicode )
59{
60 static const uchar iqm[] = {
61 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8,
62 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x38
63 }; // \'"$`<>|;&(){}*?#[]
64
65 uint c = cUnicode.unicode();
66
67 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
68}
69
70QStringList KShell::splitArgs( const QString &args, Options flags, Errors *err)
71{
72 QStringList ret;
73 bool firstword = flags & AbortOnMeta;
74
75 for (int pos = 0; ; ) {
76 QChar c;
77 do {
78 if (pos >= args.length())
79 goto okret;
80 c = args.unicode()[pos++];
81 } while (c.isSpace());
82 QString cret;
83 if ((flags & TildeExpand) && c == QLatin1Char('~')) {
84 int opos = pos;
85 for (; ; pos++) {
86 if (pos >= args.length())
87 break;
88 c = args.unicode()[pos];
89 if (c == QLatin1Char('/') || c.isSpace())
90 break;
91 if (isQuoteMeta( c )) {
92 pos = opos;
93 c = QLatin1Char('~');
94 goto notilde;
95 }
96 if ((flags & AbortOnMeta) && isMeta( c ))
97 goto metaerr;
98 }
99 QString ccret = homeDir( args.mid(opos, pos-opos) );
100 if (ccret.isEmpty()) {
101 pos = opos;
102 c = QLatin1Char('~');
103 goto notilde;
104 }
105 if (pos >= args.length()) {
106 ret += ccret;
107 goto okret;
108 }
109 pos++;
110 if (c.isSpace()) {
111 ret += ccret;
112 firstword = false;
113 continue;
114 }
115 cret = ccret;
116 }
117 // before the notilde label, as a tilde does not match anyway
118 if (firstword) {
119 if (c == QLatin1Char('_') ||
120 (c >= QLatin1Char('A') && c <= QLatin1Char('Z')) ||
121 (c >= QLatin1Char('a') && c <= QLatin1Char('z')))
122 {
123 int pos2 = pos;
124 QChar cc;
125 do {
126 if (pos2 >= args.length()) {
127 // Exactly one word
128 ret += args.mid(pos - 1);
129 goto okret;
130 }
131 cc = args.unicode()[pos2++];
132 } while (cc == QLatin1Char('_') ||
133 (cc >= QLatin1Char('A') && cc <= QLatin1Char('Z')) ||
134 (cc >= QLatin1Char('a') && cc <= QLatin1Char('z')) ||
135 (cc >= QLatin1Char('0') && cc <= QLatin1Char('9')));
136 if (cc == QLatin1Char('='))
137 goto metaerr;
138 }
139 }
140 notilde:
141 do {
142 if (c == QLatin1Char('\'')) {
143 int spos = pos;
144 do {
145 if (pos >= args.length())
146 goto quoteerr;
147 c = args.unicode()[pos++];
148 } while (c != QLatin1Char('\''));
149 cret += args.mid(spos, pos-spos-1);
150 } else if (c == QLatin1Char('"')) {
151 for (;;) {
152 if (pos >= args.length())
153 goto quoteerr;
154 c = args.unicode()[pos++];
155 if (c == QLatin1Char('"'))
156 break;
157 if (c == QLatin1Char('\\')) {
158 if (pos >= args.length())
159 goto quoteerr;
160 c = args.unicode()[pos++];
161 if (c != QLatin1Char('"') &&
162 c != QLatin1Char('\\') &&
163 !((flags & AbortOnMeta) &&
164 (c == QLatin1Char('$') ||
165 c == QLatin1Char('`'))))
166 cret += QLatin1Char('\\');
167 } else if ((flags & AbortOnMeta) &&
168 (c == QLatin1Char('$') ||
169 c == QLatin1Char('`')))
170 goto metaerr;
171 cret += c;
172 }
173 } else if (c == QLatin1Char('$') && pos < args.length() &&
174 args.unicode()[pos] == QLatin1Char('\'')) {
175 pos++;
176 for (;;) {
177 if (pos >= args.length())
178 goto quoteerr;
179 c = args.unicode()[pos++];
180 if (c == QLatin1Char('\''))
181 break;
182 if (c == QLatin1Char('\\')) {
183 if (pos >= args.length())
184 goto quoteerr;
185 c = args.unicode()[pos++];
186 switch (c.toLatin1()) {
187 case 'a': cret += QLatin1Char('\a'); break;
188 case 'b': cret += QLatin1Char('\b'); break;
189 case 'e': cret += QLatin1Char('\033'); break;
190 case 'f': cret += QLatin1Char('\f'); break;
191 case 'n': cret += QLatin1Char('\n'); break;
192 case 'r': cret += QLatin1Char('\r'); break;
193 case 't': cret += QLatin1Char('\t'); break;
194 case '\\': cret += QLatin1Char('\\'); break;
195 case '\'': cret += QLatin1Char('\''); break;
196 case 'c':
197 if (pos >= args.length())
198 goto quoteerr;
199 cret += args.unicode()[pos++].toLatin1() & 31;
200 break;
201 case 'x':
202 {
203 if (pos >= args.length())
204 goto quoteerr;
205 int hv = fromHex( args.unicode()[pos++] );
206 if (hv < 0)
207 goto quoteerr;
208 if (pos < args.length()) {
209 int hhv = fromHex( args.unicode()[pos] );
210 if (hhv > 0) {
211 hv = hv * 16 + hhv;
212 pos++;
213 }
214 cret += QChar( hv );
215 }
216 break;
217 }
218 default:
219 if (c.toLatin1() >= '0' && c.toAscii() <= '7') {
220 char cAscii = c.toLatin1();
221 int hv = cAscii - '0';
222 for (int i = 0; i < 2; i++) {
223 if (pos >= args.length())
224 break;
225 c = args.unicode()[pos];
226 if (c.toLatin1() < '0' || c.toAscii() > '7')
227 break;
228 hv = hv * 8 + (c.toLatin1() - '0');
229 pos++;
230 }
231 cret += QChar( hv );
232 } else {
233 cret += QLatin1Char('\\');
234 cret += c;
235 }
236 break;
237 }
238 } else
239 cret += c;
240 }
241 } else {
242 if (c == QLatin1Char('\\')) {
243 if (pos >= args.length())
244 goto quoteerr;
245 c = args.unicode()[pos++];
246 } else if ((flags & AbortOnMeta) && isMeta( c ))
247 goto metaerr;
248 cret += c;
249 }
250 if (pos >= args.length())
251 break;
252 c = args.unicode()[pos++];
253 } while (!c.isSpace());
254 ret += cret;
255 firstword = false;
256 }
257
258 okret:
259 if (err)
260 *err = NoError;
261 return ret;
262
263 quoteerr:
264 if (err)
265 *err = BadQuoting;
266 return QStringList();
267
268 metaerr:
269 if (err)
270 *err = FoundMeta;
271 return QStringList();
272}
273
274inline static bool isSpecial( QChar cUnicode )
275{
276 static const uchar iqm[] = {
277 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
278 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
279 }; // 0-32 \'"$`<>|;&(){}*?#!~[]
280
281 uint c = cUnicode.unicode ();
282 return ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) || cUnicode.isSpace();
283}
284
285QString KShell::quoteArg( const QString &arg )
286{
287 if (!arg.length())
288 return QString::fromLatin1("''");
289 for (int i = 0; i < arg.length(); i++)
290 if (isSpecial( arg.unicode()[i] )) {
291 QChar q( QLatin1Char('\'') );
292 return QString( arg ).replace( q, QLatin1String("'\\''") ).prepend( q ).append( q );
293 }
294 return arg;
295}
QStringList
QString
kshell.h
kshell_p.h
isMeta
static bool isMeta(QChar cUnicode)
Definition: kshell_unix.cpp:58
fromHex
static int fromHex(QChar cUnicode)
Definition: kshell_unix.cpp:30
isSpecial
static bool isSpecial(QChar cUnicode)
Definition: kshell_unix.cpp:274
isQuoteMeta
static bool isQuoteMeta(QChar cUnicode)
Definition: kshell_unix.cpp:43
kuser.h
KShell::quoteArg
QString quoteArg(const QString &arg)
Quotes arg according to system shell rules.
Definition: kshell_unix.cpp:285
KShell::homeDir
QString homeDir(const QString &user)
Definition: kshell.cpp:29
KShell::splitArgs
QStringList splitArgs(const QString &cmd, Options flags=NoOptions, Errors *err=0)
Splits cmd according to system shell word splitting and quoting rules.
Definition: kshell_unix.cpp:70
KShell::TildeExpand
@ TildeExpand
Perform tilde expansion.
Definition: kshell.h:47
KShell::AbortOnMeta
@ AbortOnMeta
Put the parser into full shell mode and bail out if a too complex construct is encoutered.
Definition: kshell.h:78
KShell::Errors
Errors
Status codes from splitArgs()
Definition: kshell.h:85
KShell::BadQuoting
@ BadQuoting
Indicates a parsing error, like an unterminated quoted string.
Definition: kshell.h:94
KShell::FoundMeta
@ FoundMeta
The AbortOnMeta flag was set and an unhandled shell meta character was encoutered.
Definition: kshell.h:100
KShell::NoError
@ NoError
Success.
Definition: kshell.h:89
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal