ARG_MAX
| Shells
| whatshell
| portability
| permissions
| UUOC
| ancient
| -
| ../Various
| HOME
"$@"
| echo/printf
| set -e
| test
| tty defs
| tty chars
| $()
vs )
| IFS
| using siginfo
| nanosleep
| line charset
| locale
set arg1 arg2 ...
) and options
(e.g. set -e
for exit upon error), sometimes also called flags.
It is necessary to distinguish options from arguments, to be able to use arguments with leading dashes.
Nowadays, this is usually achieved by using --
as delimiter (set -e -- -arg1 -arg2
).
Yet, this is frequently seen with a single dash as delimiter. Why?
set --
was not implemented originally, but came with the second release
of the Bourne shell. Apparently, it gets confused since then.
--
, yet. You would receive "bad option(s)" instead.
-
is not intended to terminate options.
-x
and -v
and it is documented as such.
+
to turn off an option is not implemented, yet, either.
set -e -u
),
but only combined (set -eu
).
-
to set arguments with leading dashes:
set - -argumentNote: If
-x
or -v
had been active before, you would have to set them again now.
#!/bin/sh -
" works the same way. But you even wouldn't notice the abuse,
-x
and -v
is not only triggered by
"-
" but by the leading dash in any option,
\0
is missing. See the endnote for the code.
-x
or -v
a second time,
if you have set any other option after the first time.
--
" to explicitly end options.
set -eu -- -firstargument
.
-")
is also gone. See the endnote for code.
+
to turn off a respective option.
-"
to turn off -x
and -v
is not documented anymore. However, it remains unchanged in the code.
+
,
this feature has become useless.
Or it remains active for backwards compatibility only.
#!/bin/sh -
" still works.
#!/bin/sh --
"
--
" since SunOS 5.7.
-
"
does not change any of the flags.
-
" still can be abused this way.
At the beginning of some scripts you will see an equivalent to set --
,
"#!/bin/sh --
" or "#!/bin/sh -
".
This fixes a security hole. The problem is as follows
#!/bin/sh
as first line
./-i
" to this script
PATH
, e.g. PATH=$PATH:
-i
"
If the script doesn't force end of options, you will get an interactive shell:
The kernel starts the the interpreter with the script as argument, which is -i
.
Be aware, that your shell might change the path from -i
to ./-i
,
like bash does (all releases).
Bourne, Korn and Almquist shells, pdksh (and its derivatives) keep the path.
By the way, there's an alternative to set --
, you could use a dummy and shift it away:
set -options dummy arguments; shiftAnd there's another meaning of "
set --
":
Modern bourne compatible shells allow to unset the parameter list this way.
However, in the traditional Bourne shell this doesn't change anything.
Alternatively, you can either shift until there are no parameters left,
while shift 2>/dev/null; do :; done
or similar to the abovementioned workaround
set -options dummy; shift
The following was released under the license of Caldera.
Version 7
INT options(argc,argv) STRING *argv; INT argc; { REG STRING cp; REG STRING *argp=argv; REG STRING flagc; STRING flagp; IF argc>1 ANDF *argp[1]=='-' THEN cp=argp[1]; flags &= ~(execpr|readpr); WHILE *++cp DO [...]
System III
INT options(argc,argv) STRING *argv; INT argc; { REG STRING cp; REG STRING *argp=argv; REG STRING flagc; STRING flagp; IF argc>1 ANDF *argp[1]=='-' THEN IF argp[1][1] == '-' THEN /* if first argument is "--" then options are not to be changed Fix for problems getting $1 starting with a "-" */ argp[1] = argp[0]; argc--; return(argc); FI cp = argp[1]; IF cp[1] == '\0' THEN flags &= ~(execpr|readpr) FI /* Step along 'flagchar[]' looking for matches. 'sicr' are not legal with 'set' command. */ WHILE *++cp DO flagc=flagchar;