Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

psh: Implement a parser for "quoted" commands #182

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

gerard5
Copy link
Contributor

@gerard5 gerard5 commented Jun 29, 2023

Work in progress - do not merge.

I open this pull-request for discussion, maybe someone has already found better solution.

psh tests may fail because this change:

  • uses quotes and spaces (tests may assume this is invalid use case)
  • does not modify the command history buffer as it was originally with strtok, see description below.

Description

This pull-request adds support for quoted commands (single ' and double " quote), a quote inside quote requires an escape character \' or \" depending on the main type of quote used. Example:
"argument text \"inner quote\" 'other quote' end" or 'argument text \'inner quote\' "other quote" end'

The efects of this change:
2023-06-29-084224_692x153_scrot

2023-06-29-084549_590x260_scrot

Before the change (originally), the strtok() function was used, which modifies the command line stored in the command history, I implemented the function behaves similarly except that it allows the use of quotes. There is one, but ... now it uses a scratchpad where it stores a copy of the command line it is working on. This is necessary because the characters ", ' and \" \" are overwritten and the text is moved in the buffer, without the scratch buffer, the command history would be modified and the command would lose its meaning.

Support for \ without quotes is missing now, maybe I'll add this once I extend path completion to also support \ , so
e.g. cat /dir\ with\ spaces/file\ with\ spaces is not supported in this pull-request, instead use cat "/dir with spaces/file with spaces":

2023-06-29-091630_454x143_scrot

Motivation and Context

Need to support arguments that contains spaces and quotation marks.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

How Has This Been Tested?

  • Already covered by automatic testing.
  • New test added: (add PR link here).
  • Tested by hand on: ia32-generic, nil-imxrt1176

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing linter checks and tests passed.
  • My changes generate no new compilation warnings for any of the targets.

Special treatment

  • This PR needs additional PRs to work (list the PRs, preferably in merge-order).
  • I will merge this PR by myself when appropriate.

@gerard5 gerard5 self-assigned this Jun 29, 2023
@gerard5 gerard5 marked this pull request as ready for review June 29, 2023 07:43
Change adds support for quoted commands (single ', and double "
quote), a quote inside quote requires an escape character \' or \"
depending on the main type of quote used. Example:
"argument text \"inner quote\" 'other quote' end" or
'argument text \'inner quote\' "other quote" end'.

JIRA: RTOS-512
Let `echo` command output the arguments as received from parser,
do not eat " quote mark.

JIRA: RTOS-512
@@ -77,7 +77,7 @@ const psh_appentry_t *psh_findapp(char *appname)
}


static char *psh_stralloc(char *oldstr, const char *str)
char *psh_stralloc(char *oldstr, const char *str)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A slightly simpler version of psh_stralloc()

char *psh_stralloc_t(char *oldstr, const char *str)
{
	char *newstr = strdup(str);
	
	if (newstr != NULL) {
		free(oldstr);
	}

	return newstr;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it.

Comment on lines +845 to +847
while (*ptr != '\0' && isspace(*ptr)) {
ptr++;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
while (*ptr != '\0' && isspace(*ptr)) {
ptr++;
}
while (isspace(*ptr) != 0) {
ptr++;
}

Comment on lines +858 to +860
if (*ptr == '\0' || *(ptr - 1) != '\\') {
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be added to skip the psh_unescape() function call if there is no backaslash in quotation marks.
On top declare:

int need_unscape = 0;
Suggested change
if (*ptr == '\0' || *(ptr - 1) != '\\') {
break;
}
if (*ptr == '\0') {
break;
}
if (*(ptr - 1) == '\\') {
need_unscape = 1;
}
else {
break;
}

and return

return (need_unscape == 0) ? ret : psh_unescape(ret, quote);

Comment on lines +872 to +874
while (*ptr != '\0' && isspace(*ptr)) {
ptr++;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this was lost somewhere early.

Suggested change
while (*ptr != '\0' && isspace(*ptr)) {
ptr++;
}

You skip the whitespace characters at the beginning of the function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants