File indexing completed on 2024-05-12 03:55:00

0001 /*
0002     This file is part of the KDE libraries
0003 
0004     SPDX-FileCopyrightText: 2003, 2007 Oswald Buddenhagen <ossi@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 #ifndef KSHELL_H
0009 #define KSHELL_H
0010 
0011 #include <QStringList>
0012 #include <kcoreaddons_export.h>
0013 #include <qglobal.h>
0014 
0015 class QString;
0016 
0017 /**
0018  * \namespace KShell
0019  * Emulates some basic system shell functionality.
0020  * @see KStringHandler
0021  */
0022 namespace KShell
0023 {
0024 /**
0025  * Flags for splitArgs().
0026  * @see Options
0027  */
0028 enum Option {
0029     NoOptions = 0,
0030 
0031     /**
0032      * Perform tilde expansion.
0033      * On Windows, this flag is ignored, as the Windows shell has no
0034      * equivalent functionality.
0035      */
0036     TildeExpand = 1,
0037 
0038     /**
0039      * Put the parser into full shell mode and bail out if a too complex
0040      * construct is encountered.
0041      * A particular purpose of this flag is finding out whether the
0042      * command line being split would be executable directly (via
0043      * KProcess::setProgram()) or whether it needs to be run through
0044      * a real shell (via KProcess::setShellCommand()). Note, however,
0045      * that shell builtins are @em not recognized - you need to do that
0046      * yourself (compare with a list of known commands or verify that an
0047      * executable exists for the named command).
0048      *
0049      * Meta characters that cause a bail-out are the command separators
0050      * @c semicolon and @c ampersand, the redirection symbols @c less-than,
0051      * @c greater-than and the @c pipe @c symbol and the grouping symbols
0052      * opening and closing @c parentheses.
0053      *
0054      * Further meta characters on *NIX are the grouping symbols
0055      * opening and closing @c braces, the command substitution symbol
0056      * @c backquote, the generic substitution symbol @c dollar (if
0057      * not followed by an apostrophe), the wildcards @c asterisk,
0058      * @c question @c mark and opening and closing @c square @c brackets
0059      * and the comment symbol @c hash @c mark.
0060      * Additionally, a variable assignment in the first word is recognized.
0061      *
0062      * A further meta character on Windows is the environment variable
0063      * expansion symbol @c percent. Occurrences of @c \%PERCENT_SIGN% as
0064      * inserted by quoteArg() are converted back and cause no bail-out,
0065      * though.
0066      */
0067     AbortOnMeta = 2,
0068 };
0069 /**
0070  * Stores a combination of #Option values.
0071  */
0072 Q_DECLARE_FLAGS(Options, Option)
0073 Q_DECLARE_OPERATORS_FOR_FLAGS(Options)
0074 
0075 /**
0076  * Status codes from splitArgs()
0077  */
0078 enum Errors {
0079     /**
0080      * Success.
0081      */
0082     NoError = 0,
0083 
0084     /**
0085      * Indicates a parsing error, like an unterminated quoted string.
0086      */
0087     BadQuoting,
0088 
0089     /**
0090      * The AbortOnMeta flag was set and an unhandled shell meta character
0091      * was encountered.
0092      */
0093     FoundMeta,
0094 };
0095 
0096 /**
0097  * Splits @p cmd according to system shell word splitting and quoting rules.
0098  * Can optionally perform tilde expansion and/or abort if it finds shell
0099  * meta characters it cannot process.
0100  *
0101  * On *NIX the behavior is based on the POSIX shell and bash:
0102  * - Whitespace splits tokens
0103  * - The backslash quotes the following character
0104  * - A string enclosed in single quotes is not split. No shell meta
0105  *   characters are interpreted.
0106  * - A string enclosed in double quotes is not split. Within the string,
0107  *   the backslash quotes shell meta characters - if it is followed
0108  *   by a "meaningless" character, the backslash is output verbatim.
0109  * - A string enclosed in $'' is not split. Within the string, the
0110  *   backslash has a similar meaning to the one in C strings. Consult
0111  *   the bash manual for more information.
0112  *
0113  * On Windows, the behavior is defined by the Microsoft C runtime. Qt and
0114  * many other implementations comply with this standard, but many do not.
0115  * - Whitespace splits tokens
0116  * - A string enclosed in double quotes is not split
0117  *   - 2N double quotes within a quoted string yield N literal quotes.
0118  *     This is not documented on MSDN.
0119  * - Backslashes have special semantics iff they are followed by a double
0120  *   quote:
0121  *   - 2N backslashes + double quote => N backslashes and begin/end quoting
0122  *   - 2N+1 backslashes + double quote => N backslashes + literal quote
0123  *
0124  * If AbortOnMeta is used on Windows, this function applies cmd shell
0125  * semantics before proceeding with word splitting:
0126  * - Cmd ignores @em all special chars between double quotes.
0127  *   Note that the quotes are @em not removed at this stage - the
0128  *   tokenization rules described above still apply.
0129  * - The @c circumflex is the escape char for everything including
0130  *   itself.
0131  *
0132  * @param cmd the command to split
0133  * @param flags operation flags, see \ref Option
0134  * @param err if not NULL, a status code will be stored at the pointer
0135  *  target, see \ref Errors
0136  * @return a list of unquoted words or an empty list if an error occurred
0137  */
0138 KCOREADDONS_EXPORT QStringList splitArgs(const QString &cmd, Options flags = NoOptions, Errors *err = nullptr);
0139 
0140 /**
0141  * Quotes and joins @p args together according to system shell rules.
0142  *
0143  * If the output is fed back into splitArgs(), the AbortOnMeta flag
0144  * needs to be used on Windows. On *NIX, no such requirement exists.
0145  *
0146  * See quoteArg() for more info.
0147  *
0148  * @param args a list of strings to quote and join
0149  * @return a command suitable for shell execution
0150  */
0151 KCOREADDONS_EXPORT QString joinArgs(const QStringList &args);
0152 
0153 /**
0154  * Quotes @p arg according to system shell rules.
0155  *
0156  * This function can be used to quote an argument string such that
0157  * the shell processes it properly. This is e.g. necessary for
0158  * user-provided file names which may contain spaces or quotes.
0159  * It also prevents expansion of wild cards and environment variables.
0160  *
0161  * On *NIX, the output is POSIX shell compliant.
0162  * On Windows, it is compliant with the argument splitting code of the
0163  * Microsoft C runtime and the cmd shell used together.
0164  * Occurrences of the @c percent @c sign are replaced with
0165  * @c \%PERCENT_SIGN% to prevent spurious variable expansion;
0166  * related KDE functions are prepared for this.
0167  *
0168  * @param arg the argument to quote
0169  * @return the quoted argument
0170  */
0171 KCOREADDONS_EXPORT QString quoteArg(const QString &arg);
0172 
0173 /**
0174  * Performs tilde expansion on @p path. Interprets "~/path" and
0175  * "~user/path". If the path starts with an escaped tilde ("\~" on UNIX,
0176  * "^~" on Windows), the escape char is removed and the path is returned
0177  * as is.
0178  *
0179  * Note that if @p path starts with a tilde but cannot be properly expanded,
0180  * this function will return an empty string.
0181  *
0182  * @param path the path to tilde-expand
0183  * @return the expanded path
0184  */
0185 KCOREADDONS_EXPORT QString tildeExpand(const QString &path);
0186 
0187 /**
0188  * Performs tilde collapse on @p path. If path did not start by the user
0189  * homedir returns path unchanged.
0190  *
0191  * @param path the path to tilde-collpase
0192  * @return the collapsed path
0193  * @since 5.67
0194  */
0195 KCOREADDONS_EXPORT QString tildeCollapse(const QString &path);
0196 }
0197 
0198 #endif /* KSHELL_H */