Skip to content

Commit dc54492

Browse files
committed
script: support non-option argument as command
1 parent 49a7b29 commit dc54492

File tree

1 file changed

+62
-4
lines changed

1 file changed

+62
-4
lines changed

term-utils/script.c

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ static void __attribute__((__noreturn__)) usage(void)
190190
{
191191
FILE *out = stdout;
192192
fputs(USAGE_HEADER, out);
193-
fprintf(out, _(" %s [options] [file]\n"), program_invocation_short_name);
193+
fprintf(out, _(" %s [options] [file] -- [command]\n"), program_invocation_short_name);
194194

195195
fputs(USAGE_SEPARATOR, out);
196196
fputs(_("Make a typescript of a terminal session.\n"), out);
@@ -758,6 +758,31 @@ static void die_if_link(struct script_control *ctl, const char *filename)
758758
"Program not started."), filename);
759759
}
760760

761+
static char *concat_command(int argc, char *argv[])
762+
{
763+
int i;
764+
size_t len = 0;
765+
char *result, *p;
766+
767+
for (i = 0; i < argc; i++)
768+
len += strlen(argv[i]) + 1;
769+
770+
if (len == 0)
771+
return NULL;
772+
773+
p = result = xmalloc(len + 1);
774+
if (!result)
775+
return NULL;
776+
777+
for (i = 0; i < argc; i++) {
778+
memcpy(p, argv[i], strlen(argv[i]));
779+
p += strlen(argv[i]);
780+
*p++ = ' ';
781+
}
782+
*p = '\0';
783+
return result;
784+
}
785+
761786
int main(int argc, char **argv)
762787
{
763788
struct script_control ctl = {
@@ -768,6 +793,7 @@ int main(int argc, char **argv)
768793
int ch, format = 0, caught_signal = 0, rc = 0, echo = 1;
769794
const char *outfile = NULL, *infile = NULL;
770795
const char *timingfile = NULL, *shell = NULL;
796+
char *posixly_correct;
771797

772798
enum { FORCE_OPTION = CHAR_MAX + 1 };
773799

@@ -813,6 +839,10 @@ int main(int argc, char **argv)
813839

814840
ctl.isterm = isatty(STDIN_FILENO);
815841

842+
/* assure the order of argv[] unchanged */
843+
posixly_correct = getenv("POSIXLY_CORRECT");
844+
setenv("POSIXLY_CORRECT", "1", 1);
845+
816846
while ((ch = getopt_long(argc, argv, "aB:c:eE:fI:O:o:qm:T:t::Vh", longopts, NULL)) != -1) {
817847

818848
err_exclusive_options(ch, longopts, excl, excl_st);
@@ -888,12 +918,20 @@ int main(int argc, char **argv)
888918
errtryhelp(EXIT_FAILURE);
889919
}
890920
}
921+
922+
/* restore POSIXLY_CORRECT */
923+
if (posixly_correct)
924+
setenv("POSIXLY_CORRECT", posixly_correct, 1);
925+
else
926+
unsetenv("POSIXLY_CORRECT");
927+
891928
argc -= optind;
892929
argv += optind;
893930

894931
/* default if no --log-* specified */
895932
if (!outfile && !infile) {
896-
if (argc > 0) {
933+
/* if argv[0] is not after --, use argv[0] as outfile */
934+
if (argc > 0 && strcmp(argv[-1], "--") != 0) {
897935
outfile = argv[0];
898936
argc--;
899937
argv++;
@@ -906,9 +944,29 @@ int main(int argc, char **argv)
906944
log_associate(&ctl, &ctl.out, outfile, SCRIPT_FMT_RAW);
907945
}
908946

947+
/* skip -- to non-option arguments */
948+
if (argc > 0 && strcmp(argv[0], "--") == 0) {
949+
argc--;
950+
argv++;
951+
}
952+
953+
/* concat non-option arguments as command */
954+
if (argc > 0 && strcmp(argv[-1], "--") == 0) {
955+
if (ctl.command != NULL) {
956+
warnx(_("conflicting arguments of --command and non-option arguments"));
957+
errtryhelp(EXIT_FAILURE);
958+
}
959+
960+
ctl.command = concat_command(argc, argv);
961+
if (!ctl.command)
962+
errx(EXIT_FAILURE, _("failed to concatenate arguments"));
963+
964+
ctl.command_norm = xstrdup(ctl.command);
965+
strrep(ctl.command_norm, '\n', ' ');
966+
argc = 0;
967+
}
968+
909969
if (argc > 0) {
910-
/* only one filename is accepted. if --log-out was given,
911-
* freestanding filename is ignored */
912970
warnx(_("unexpected number of arguments"));
913971
errtryhelp(EXIT_FAILURE);
914972
}

0 commit comments

Comments
 (0)