• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
kshell.cpp
1/*
2 This file is part of the KDE libraries
3
4 Copyright (c) 2003 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
24#include <tqfile.h>
25
26#include <stdlib.h>
27#include <pwd.h>
28#include <sys/types.h>
29
30static int fromHex( TQChar c )
31{
32 if (c >= (TQChar)'0' && c <= (TQChar)'9')
33 return c - (TQChar)'0';
34 else if (c >= (TQChar)'A' && c <= (TQChar)'F')
35 return c - (TQChar)'A' + 10;
36 else if (c >= (TQChar)'a' && c <= (TQChar)'f')
37 return c - (TQChar)'a' + 10;
38 return -1;
39}
40
41inline static bool isQuoteMeta( uint c )
42{
43#if 0 // it's not worth it, especially after seeing gcc's asm output ...
44 static const uchar iqm[] = {
45 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00
47 }; // \'"$
48
49 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
50#else
51 return c == (int)'\\' || c == (int)'\'' || c == (int)'"' || c == (int)'$';
52#endif
53}
54
55inline static bool isMeta( uint c )
56{
57 static const uchar iqm[] = {
58 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8,
59 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38
60 }; // \'"$`<>|;&(){}*?#
61
62 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
63}
64
65TQStringList KShell::splitArgs( const TQString &args, int flags, int *err )
66{
67 TQStringList ret;
68 bool firstword = flags & AbortOnMeta;
69
70 for (uint pos = 0; ; ) {
71 TQChar c;
72 do {
73 if (pos >= args.length())
74 goto okret;
75 c = args.unicode()[pos++];
76 } while (c.isSpace());
77 TQString cret;
78 if ((flags & TildeExpand) && c == (TQChar)'~') {
79 uint opos = pos;
80 for (; ; pos++) {
81 if (pos >= args.length())
82 break;
83 c = args.unicode()[pos];
84 if (c == (TQChar)'/' || c.isSpace())
85 break;
86 if (isQuoteMeta( c )) {
87 pos = opos;
88 c = (TQChar)'~';
89 goto notilde;
90 }
91 if ((flags & AbortOnMeta) && isMeta( c ))
92 goto metaerr;
93 }
94 TQString ccret = homeDir( TQConstString( args.unicode() + opos, pos - opos ).string() );
95 if (ccret.isEmpty()) {
96 pos = opos;
97 c = (TQChar)'~';
98 goto notilde;
99 }
100 if (pos >= args.length()) {
101 ret += ccret;
102 goto okret;
103 }
104 pos++;
105 if (c.isSpace()) {
106 ret += ccret;
107 firstword = false;
108 continue;
109 }
110 cret = ccret;
111 }
112 // before the notilde label, as a tilde does not match anyway
113 if (firstword) {
114 if (c == (TQChar)'_' || (c >= (TQChar)'A' && c <= (TQChar)'Z') || (c >= (TQChar)'a' && c <= (TQChar)'z')) {
115 uint pos2 = pos;
116 TQChar cc;
117 do
118 cc = args[pos2++];
119 while (cc == (TQChar)'_' || (cc >= (TQChar)'A' && cc <= (TQChar)'Z') ||
120 (cc >= (TQChar)'a' && cc <= (TQChar)'z') || (cc >= (TQChar)'0' && cc <= (TQChar)'9'));
121 if (cc == (TQChar)'=')
122 goto metaerr;
123 }
124 }
125 notilde:
126 do {
127 if (c == (TQChar)'\'') {
128 uint spos = pos;
129 do {
130 if (pos >= args.length())
131 goto quoteerr;
132 c = args.unicode()[pos++];
133 } while (c != (TQChar)'\'');
134 cret += TQConstString( args.unicode() + spos, pos - spos - 1 ).string();
135 } else if (c == (TQChar)'"') {
136 for (;;) {
137 if (pos >= args.length())
138 goto quoteerr;
139 c = args.unicode()[pos++];
140 if (c == (TQChar)'"')
141 break;
142 if (c == (TQChar)'\\') {
143 if (pos >= args.length())
144 goto quoteerr;
145 c = args.unicode()[pos++];
146 if (c != (TQChar)'"' && c != (TQChar)'\\' &&
147 !((flags & AbortOnMeta) && (c == (TQChar)'$' || c == (TQChar)'`')))
148 cret += (TQChar)'\\';
149 } else if ((flags & AbortOnMeta) && (c == (TQChar)'$' || c == (TQChar)'`'))
150 goto metaerr;
151 cret += c;
152 }
153 } else if (c == (TQChar)'$' && args[pos] == (TQChar)'\'') {
154 pos++;
155 for (;;) {
156 if (pos >= args.length())
157 goto quoteerr;
158 c = args.unicode()[pos++];
159 if (c == (TQChar)'\'')
160 break;
161 if (c == (TQChar)'\\') {
162 if (pos >= args.length())
163 goto quoteerr;
164 c = args.unicode()[pos++];
165 switch (c) {
166 case 'a': cret += (TQChar)'\a'; break;
167 case 'b': cret += (TQChar)'\b'; break;
168 case 'e': cret += (TQChar)'\033'; break;
169 case 'f': cret += (TQChar)'\f'; break;
170 case 'n': cret += (TQChar)'\n'; break;
171 case 'r': cret += (TQChar)'\r'; break;
172 case 't': cret += (TQChar)'\t'; break;
173 case '\\': cret += (TQChar)'\\'; break;
174 case '\'': cret += (TQChar)'\''; break;
175 case 'c': cret += args[pos++] & 31; break;
176 case 'x':
177 {
178 int hv = fromHex( args[pos] );
179 if (hv < 0) {
180 cret += "\\x";
181 } else {
182 int hhv = fromHex( args[++pos] );
183 if (hhv > 0) {
184 hv = hv * 16 + hhv;
185 pos++;
186 }
187 cret += TQChar( hv );
188 }
189 break;
190 }
191 default:
192 if (c >= (TQChar)'0' && c <= (TQChar)'7') {
193 int hv = c - '0';
194 for (int i = 0; i < 2; i++) {
195 c = args[pos];
196 if (c < (TQChar)'0' || c > (TQChar)'7')
197 break;
198 hv = hv * 8 + (c - '0');
199 pos++;
200 }
201 cret += TQChar( hv );
202 } else {
203 cret += '\\';
204 cret += c;
205 }
206 break;
207 }
208 } else
209 cret += c;
210 }
211 } else {
212 if (c == (TQChar)'\\') {
213 if (pos >= args.length())
214 goto quoteerr;
215 c = args.unicode()[pos++];
216 if (!c.isSpace() &&
217 !((flags & AbortOnMeta) ? isMeta( c ) : isQuoteMeta( c )))
218 cret += '\\';
219 } else if ((flags & AbortOnMeta) && isMeta( c ))
220 goto metaerr;
221 cret += c;
222 }
223 if (pos >= args.length())
224 break;
225 c = args.unicode()[pos++];
226 } while (!c.isSpace());
227 ret += cret;
228 firstword = false;
229 }
230
231 okret:
232 if (err)
233 *err = NoError;
234 return ret;
235
236 quoteerr:
237 if (err)
238 *err = BadQuoting;
239 return TQStringList();
240
241 metaerr:
242 if (err)
243 *err = FoundMeta;
244 return TQStringList();
245}
246
247inline static bool isSpecial( uint c )
248{
249 static const uchar iqm[] = {
250 0xff, 0xff, 0xff, 0xff, 0xdd, 0x07, 0x00, 0xd8,
251 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38
252 }; // 0-32 \'"$`<>|;&(){}*?#
253
254 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
255}
256
257TQString KShell::joinArgs( const TQStringList &args )
258{
259 TQChar q( '\'' );
260 TQString ret;
261 for (TQStringList::ConstIterator it = args.begin(); it != args.end(); ++it) {
262 if (!ret.isEmpty())
263 ret += ' ';
264 if (!(*it).length())
265 ret.append( q ).append( q );
266 else {
267 for (uint i = 0; i < (*it).length(); i++)
268 if (isSpecial((*it).unicode()[i])) {
269 TQString tmp(*it);
270 tmp.replace( q, "'\\''" );
271 ret += q;
272 tmp += q;
273 ret += tmp;
274 goto ex;
275 }
276 ret += *it;
277 ex: ;
278 }
279 }
280 return ret;
281}
282
283TQString KShell::joinArgs( const char * const *args, int nargs )
284{
285 if (!args)
286 return TQString::null; // well, TQString::empty, in fact. qt sucks ;)
287 TQChar q( '\'' );
288 TQString ret;
289 for (const char * const *argp = args; nargs && *argp; argp++, nargs--) {
290 if (!ret.isEmpty())
291 ret += ' ';
292 if (!**argp)
293 ret.append( q ).append( q );
294 else {
295 TQString tmp( TQFile::decodeName( *argp ) );
296 for (uint i = 0; i < tmp.length(); i++)
297 if (isSpecial(tmp.unicode()[i])) {
298 tmp.replace( q, "'\\''" );
299 ret += q;
300 tmp += q;
301 ret += tmp;
302 goto ex;
303 }
304 ret += tmp;
305 ex: ;
306 }
307 }
308 return ret;
309}
310
311TQString KShell::joinArgsDQ( const TQStringList &args )
312{
313 TQChar q( '\'' ), sp( ' ' ), bs( '\\' );
314 TQString ret;
315 for (TQStringList::ConstIterator it = args.begin(); it != args.end(); ++it) {
316 if (!ret.isEmpty())
317 ret += sp;
318 if (!(*it).length())
319 ret.append( q ).append( q );
320 else {
321 for (uint i = 0; i < (*it).length(); i++)
322 if (isSpecial((*it).unicode()[i])) {
323 ret.append( '$' ).append( q );
324 for (uint pos = 0; pos < (*it).length(); pos++) {
325 int c = (*it).unicode()[pos];
326 if (c < 32) {
327 ret += bs;
328 switch (c) {
329 case '\a': ret += 'a'; break;
330 case '\b': ret += 'b'; break;
331 case '\033': ret += 'e'; break;
332 case '\f': ret += 'f'; break;
333 case '\n': ret += 'n'; break;
334 case '\r': ret += 'r'; break;
335 case '\t': ret += 't'; break;
336 case '\034': ret += 'c'; ret += '|'; break;
337 default: ret += 'c'; ret += c + '@'; break;
338 }
339 } else {
340 if (c == '\'' || c == '\\')
341 ret += bs;
342 ret += c;
343 }
344 }
345 ret.append( q );
346 goto ex;
347 }
348 ret += *it;
349 ex: ;
350 }
351 }
352 return ret;
353}
354
355TQString KShell::tildeExpand( const TQString &fname )
356{
357 if (fname[0] == (TQChar)'~') {
358 int pos = fname.find( '/' );
359 if (pos < 0)
360 return homeDir( TQConstString( fname.unicode() + 1, fname.length() - 1 ).string() );
361 TQString ret = homeDir( TQConstString( fname.unicode() + 1, pos - 1 ).string() );
362 if (!ret.isNull())
363 ret += TQConstString( fname.unicode() + pos, fname.length() - pos ).string();
364 return ret;
365 }
366 return fname;
367}
368
369TQString KShell::homeDir( const TQString &user )
370{
371 if (user.isEmpty())
372 return TQFile::decodeName( getenv( "HOME" ) );
373 struct passwd *pw = getpwnam( TQFile::encodeName( user ).data() );
374 if (!pw)
375 return TQString::null;
376 return TQFile::decodeName( pw->pw_dir );
377}
KShell::TildeExpand
@ TildeExpand
Perform tilde expansion.
Definition: kshell.h:46
KShell::AbortOnMeta
@ AbortOnMeta
Bail out if a non-quoting and not quoted shell meta character is encoutered.
Definition: kshell.h:58
KShell::joinArgs
TQString joinArgs(const TQStringList &args)
Quotes and joins args together according to POSIX shell rules.
Definition: kshell.cpp:257
KShell::splitArgs
TQStringList splitArgs(const TQString &cmd, int flags=0, int *err=0)
Splits cmd according to POSIX shell word splitting and quoting rules.
Definition: kshell.cpp:65
KShell::joinArgsDQ
TQString joinArgsDQ(const TQStringList &args)
Same as above, but $'' is used instead of '' for the quoting.
Definition: kshell.cpp:311
KShell::homeDir
TQString homeDir(const TQString &user)
Obtain a user's home directory.
Definition: kshell.cpp:369
KShell::tildeExpand
TQString tildeExpand(const TQString &path)
Performs tilde expansion on path.
Definition: kshell.cpp:355
KShell::BadQuoting
@ BadQuoting
Indicates a parsing error, like an unterminated quoted string.
Definition: kshell.h:73
KShell::FoundMeta
@ FoundMeta
The AbortOnMeta flag was set and a shell meta character was encoutered.
Definition: kshell.h:79
KShell::NoError
@ NoError
Success.
Definition: kshell.h:68

tdecore

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

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.