• 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 
30 static 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 
41 inline 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 
55 inline 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 
65 TQStringList 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 == (QChar)'~') {
79  uint opos = pos;
80  for (; ; pos++) {
81  if (pos >= args.length())
82  break;
83  c = args.unicode()[pos];
84  if (c == (QChar)'/' || c.isSpace())
85  break;
86  if (isQuoteMeta( c )) {
87  pos = opos;
88  c = (QChar)'~';
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 = (QChar)'~';
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 == (QChar)'_' || (c >= (QChar)'A' && c <= (QChar)'Z') || (c >= (QChar)'a' && c <= (QChar)'z')) {
115  uint pos2 = pos;
116  TQChar cc;
117  do
118  cc = args[pos2++];
119  while (cc == (QChar)'_' || (cc >= (QChar)'A' && cc <= (QChar)'Z') ||
120  (cc >= (QChar)'a' && cc <= (QChar)'z') || (cc >= (QChar)'0' && cc <= (QChar)'9'));
121  if (cc == (QChar)'=')
122  goto metaerr;
123  }
124  }
125  notilde:
126  do {
127  if (c == (QChar)'\'') {
128  uint spos = pos;
129  do {
130  if (pos >= args.length())
131  goto quoteerr;
132  c = args.unicode()[pos++];
133  } while (c != (QChar)'\'');
134  cret += TQConstString( args.unicode() + spos, pos - spos - 1 ).string();
135  } else if (c == (QChar)'"') {
136  for (;;) {
137  if (pos >= args.length())
138  goto quoteerr;
139  c = args.unicode()[pos++];
140  if (c == (QChar)'"')
141  break;
142  if (c == (QChar)'\\') {
143  if (pos >= args.length())
144  goto quoteerr;
145  c = args.unicode()[pos++];
146  if (c != (QChar)'"' && c != (QChar)'\\' &&
147  !((flags & AbortOnMeta) && (c == (QChar)'$' || c == (QChar)'`')))
148  cret += (QChar)'\\';
149  } else if ((flags & AbortOnMeta) && (c == (QChar)'$' || c == (QChar)'`'))
150  goto metaerr;
151  cret += c;
152  }
153  } else if (c == (QChar)'$' && args[pos] == (QChar)'\'') {
154  pos++;
155  for (;;) {
156  if (pos >= args.length())
157  goto quoteerr;
158  c = args.unicode()[pos++];
159  if (c == (QChar)'\'')
160  break;
161  if (c == (QChar)'\\') {
162  if (pos >= args.length())
163  goto quoteerr;
164  c = args.unicode()[pos++];
165  switch (c) {
166  case 'a': cret += (QChar)'\a'; break;
167  case 'b': cret += (QChar)'\b'; break;
168  case 'e': cret += (QChar)'\033'; break;
169  case 'f': cret += (QChar)'\f'; break;
170  case 'n': cret += (QChar)'\n'; break;
171  case 'r': cret += (QChar)'\r'; break;
172  case 't': cret += (QChar)'\t'; break;
173  case '\\': cret += (QChar)'\\'; break;
174  case '\'': cret += (QChar)'\''; 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 >= (QChar)'0' && c <= (QChar)'7') {
193  int hv = c - '0';
194  for (int i = 0; i < 2; i++) {
195  c = args[pos];
196  if (c < (QChar)'0' || c > (QChar)'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 == (QChar)'\\') {
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 
247 inline 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 
257 TQString 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 
283 TQString 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 
311 TQString 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 
355 TQString KShell::tildeExpand( const TQString &fname )
356 {
357  if (fname[0] == (QChar)'~') {
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 
369 TQString 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::joinArgsDQ
TQString joinArgsDQ(const TQStringList &args)
Same as above, but $'' is used instead of '' for the quoting.
Definition: kshell.cpp:311
KShell::tildeExpand
TQString tildeExpand(const TQString &path)
Performs tilde expansion on path.
Definition: kshell.cpp:355
KShell::TildeExpand
Perform tilde expansion.
Definition: kshell.h:46
KShell::homeDir
TQString homeDir(const TQString &user)
Obtain a user's home directory.
Definition: kshell.cpp:369
KShell::FoundMeta
The AbortOnMeta flag was set and a shell meta character was encoutered.
Definition: kshell.h:79
KShell::joinArgs
TQString joinArgs(const TQStringList &args)
Quotes and joins args together according to POSIX shell rules.
Definition: kshell.cpp:257
KShell::BadQuoting
Indicates a parsing error, like an unterminated quoted string.
Definition: kshell.h:73
KShell::NoError
Success.
Definition: kshell.h:68
KShell::AbortOnMeta
Bail out if a non-quoting and not quoted shell meta character is encoutered.
Definition: kshell.h:58
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

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.8.8
This website is maintained by Timothy Pearson.