1 /* 2 This file is part of the KDE libraries 3 4 SPDX-FileCopyrightText: 2003, 2007 Oswald Buddenhagen <ossi@kde.org> 5 6 SPDX-License-Identifier: LGPL-2.0-or-later 7 */ 8 #ifndef KSHELL_H 9 #define KSHELL_H 10 11 #include <QStringList> 12 #include <kcoreaddons_export.h> 13 #include <qglobal.h> 14 15 class QString; 16 17 /** 18 * \namespace KShell 19 * Emulates some basic system shell functionality. 20 * @see KStringHandler 21 */ 22 namespace KShell 23 { 24 /** 25 * Flags for splitArgs(). 26 * @see Options 27 */ 28 enum Option { 29 NoOptions = 0, 30 31 /** 32 * Perform tilde expansion. 33 * On Windows, this flag is ignored, as the Windows shell has no 34 * equivalent functionality. 35 */ 36 TildeExpand = 1, 37 38 /** 39 * Put the parser into full shell mode and bail out if a too complex 40 * construct is encountered. 41 * A particular purpose of this flag is finding out whether the 42 * command line being split would be executable directly (via 43 * KProcess::setProgram()) or whether it needs to be run through 44 * a real shell (via KProcess::setShellCommand()). Note, however, 45 * that shell builtins are @em not recognized - you need to do that 46 * yourself (compare with a list of known commands or verify that an 47 * executable exists for the named command). 48 * 49 * Meta characters that cause a bail-out are the command separators 50 * @c semicolon and @c ampersand, the redirection symbols @c less-than, 51 * @c greater-than and the @c pipe @c symbol and the grouping symbols 52 * opening and closing @c parentheses. 53 * 54 * Further meta characters on *NIX are the grouping symbols 55 * opening and closing @c braces, the command substitution symbol 56 * @c backquote, the generic substitution symbol @c dollar (if 57 * not followed by an apostrophe), the wildcards @c asterisk, 58 * @c question @c mark and opening and closing @c square @c brackets 59 * and the comment symbol @c hash @c mark. 60 * Additionally, a variable assignment in the first word is recognized. 61 * 62 * A further meta character on Windows is the environment variable 63 * expansion symbol @c percent. Occurrences of @c \%PERCENT_SIGN% as 64 * inserted by quoteArg() are converted back and cause no bail-out, 65 * though. 66 */ 67 AbortOnMeta = 2, 68 }; 69 /** 70 * Stores a combination of #Option values. 71 */ 72 Q_DECLARE_FLAGS(Options, Option) 73 Q_DECLARE_OPERATORS_FOR_FLAGS(Options) 74 75 /** 76 * Status codes from splitArgs() 77 */ 78 enum Errors { 79 /** 80 * Success. 81 */ 82 NoError = 0, 83 84 /** 85 * Indicates a parsing error, like an unterminated quoted string. 86 */ 87 BadQuoting, 88 89 /** 90 * The AbortOnMeta flag was set and an unhandled shell meta character 91 * was encountered. 92 */ 93 FoundMeta, 94 }; 95 96 /** 97 * Splits @p cmd according to system shell word splitting and quoting rules. 98 * Can optionally perform tilde expansion and/or abort if it finds shell 99 * meta characters it cannot process. 100 * 101 * On *NIX the behavior is based on the POSIX shell and bash: 102 * - Whitespace splits tokens 103 * - The backslash quotes the following character 104 * - A string enclosed in single quotes is not split. No shell meta 105 * characters are interpreted. 106 * - A string enclosed in double quotes is not split. Within the string, 107 * the backslash quotes shell meta characters - if it is followed 108 * by a "meaningless" character, the backslash is output verbatim. 109 * - A string enclosed in $'' is not split. Within the string, the 110 * backslash has a similar meaning to the one in C strings. Consult 111 * the bash manual for more information. 112 * 113 * On Windows, the behavior is defined by the Microsoft C runtime. Qt and 114 * many other implementations comply with this standard, but many do not. 115 * - Whitespace splits tokens 116 * - A string enclosed in double quotes is not split 117 * - 2N double quotes within a quoted string yield N literal quotes. 118 * This is not documented on MSDN. 119 * - Backslashes have special semantics iff they are followed by a double 120 * quote: 121 * - 2N backslashes + double quote => N backslashes and begin/end quoting 122 * - 2N+1 backslashes + double quote => N backslashes + literal quote 123 * 124 * If AbortOnMeta is used on Windows, this function applies cmd shell 125 * semantics before proceeding with word splitting: 126 * - Cmd ignores @em all special chars between double quotes. 127 * Note that the quotes are @em not removed at this stage - the 128 * tokenization rules described above still apply. 129 * - The @c circumflex is the escape char for everything including 130 * itself. 131 * 132 * @param cmd the command to split 133 * @param flags operation flags, see \ref Option 134 * @param err if not NULL, a status code will be stored at the pointer 135 * target, see \ref Errors 136 * @return a list of unquoted words or an empty list if an error occurred 137 */ 138 KCOREADDONS_EXPORT QStringList splitArgs(const QString &cmd, Options flags = NoOptions, Errors *err = nullptr); 139 140 /** 141 * Quotes and joins @p args together according to system shell rules. 142 * 143 * If the output is fed back into splitArgs(), the AbortOnMeta flag 144 * needs to be used on Windows. On *NIX, no such requirement exists. 145 * 146 * See quoteArg() for more info. 147 * 148 * @param args a list of strings to quote and join 149 * @return a command suitable for shell execution 150 */ 151 KCOREADDONS_EXPORT QString joinArgs(const QStringList &args); 152 153 /** 154 * Quotes @p arg according to system shell rules. 155 * 156 * This function can be used to quote an argument string such that 157 * the shell processes it properly. This is e.g. necessary for 158 * user-provided file names which may contain spaces or quotes. 159 * It also prevents expansion of wild cards and environment variables. 160 * 161 * On *NIX, the output is POSIX shell compliant. 162 * On Windows, it is compliant with the argument splitting code of the 163 * Microsoft C runtime and the cmd shell used together. 164 * Occurrences of the @c percent @c sign are replaced with 165 * @c \%PERCENT_SIGN% to prevent spurious variable expansion; 166 * related KDE functions are prepared for this. 167 * 168 * @param arg the argument to quote 169 * @return the quoted argument 170 */ 171 KCOREADDONS_EXPORT QString quoteArg(const QString &arg); 172 173 /** 174 * Performs tilde expansion on @p path. Interprets "~/path" and 175 * "~user/path". If the path starts with an escaped tilde ("\~" on UNIX, 176 * "^~" on Windows), the escape char is removed and the path is returned 177 * as is. 178 * 179 * Note that if @p path starts with a tilde but cannot be properly expanded, 180 * this function will return an empty string. 181 * 182 * @param path the path to tilde-expand 183 * @return the expanded path 184 */ 185 KCOREADDONS_EXPORT QString tildeExpand(const QString &path); 186 187 /** 188 * Performs tilde collapse on @p path. If path did not start by the user 189 * homedir returns path unchanged. 190 * 191 * @param path the path to tilde-collpase 192 * @return the collapsed path 193 * @since 5.67 194 */ 195 KCOREADDONS_EXPORT QString tildeCollapse(const QString &path); 196 } 197 198 #endif /* KSHELL_H */ 199