#!/bin/sh
#
# Check strace options syntax.
#
# Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
# Copyright (c) 2016-2024 The strace developers.
# All rights reserved.
#
# SPDX-License-Identifier: GPL-2.0-or-later

. "${srcdir=.}/syntax.sh"

compiled_with_secontext=$(get_config_option ENABLE_SECONTEXT "y")
compiled_with_stacktrace="$(get_config_option ENABLE_STACKTRACE 1)"
compiled_with_libunwind="$(get_config_option USE_LIBUNWIND 1)"
compiled_with_libdw="$(get_config_option USE_LIBDW 1)"

check_e "Invalid process id: '0'" -p 0
check_e "Invalid process id: '0'" --attach=0
check_e "Invalid process id: '-42'" -p -42
check_e "Invalid process id: '-42'" --attach=-42
check_e "Invalid process id: '$$.'" -p $$.
check_e "Invalid process id: '$$.'" --attach=$$.
check_e "Invalid process id: 'a'" -p 1,a
check_e "Invalid process id: 'a'" --attach=1,a
check_e "Syscall 'chdir' for -b isn't supported" -b chdir
check_e "Syscall 'chdir' for -b isn't supported" --detach-on=chdir
check_e "Syscall 'chdir' for -b isn't supported" -b execve -b chdir
check_e "Syscall 'chdir' for -b isn't supported" --detach-on=execve --detach-on=chdir

check_e_using_grep 'exec: File *name too long' "$(printf '%4096s' ' ')"

ff_name="$(printf '%4084s' ' ')"
check_e_using_grep "$ff_name: File *name too long" -ff -o "$ff_name" true
check_e_using_grep "$ff_name: File *name too long" -ff --output="$ff_name" true

check_h 'must have PROG [ARGS] or -p PID'
check_h "must have PROG [ARGS] or -p PID" --absolute-timestamps
check_h "must have PROG [ARGS] or -p PID" --absolute-timestamps=
check_h "must have PROG [ARGS] or -p PID" --absolute-timestamps=,
check_h "must have PROG [ARGS] or -p PID" --absolute-timestamps=,s
check_h "must have PROG [ARGS] or -p PID" --absolute-timestamps=s,
check_h "must have PROG [ARGS] or -p PID" --absolute-timestamps=,,
check_h "must have PROG [ARGS] or -p PID" --absolute-timestamps=s,,none
check_h "must have PROG [ARGS] or -p PID" --timestamps --absolute-timestamps=ns --timestamps=none --absolute-timestamps=format:time,precision:s --timestamps=ns,format:unix --absolute-timestamps=us,precision:ms,unix,precision:ns --timestamps=format:none,time,precision:us
check_h "invalid --absolute-timestamps argument: 'ss'" --absolute-timestamps=ss
check_h "invalid --timestamps argument: 'format:s'" --timestamps=format:s
check_h "invalid --timestamps argument: 's,non'" --timestamps=s,non
check_h "invalid --timestamps argument: 'precision:none'" --timestamps=precision:none
check_e '-t and --absolute-timestamps cannot be provided simultaneously' -t --timestamps -p $$
check_e '-t and --absolute-timestamps cannot be provided simultaneously' --absolute-timestamps -ttt -p $$
check_e '-t and --absolute-timestamps cannot be provided simultaneously' -t --timestamps=ns -t -p $$
check_e '-t and --absolute-timestamps cannot be provided simultaneously' --timestamps=ns -t --absolute-timestamps=unix -p $$
if [ -n "$compiled_with_secontext" ]; then
	for opt in '--secontext' '-e secontext'; do
		check_e "invalid secontext ''" $opt=
		check_e "invalid secontext 'ss'" $opt=ss
		check_e "invalid secontext 'ss'" $opt=ss,full,mismatch
		check_e "invalid secontext 'ss'" $opt=full,ss,mismatch
		check_e "invalid secontext 'ss'" $opt=full,ss
		check_e "invalid secontext 'ss'" $opt=full,mismatch,ss
		check_e "invalid secontext 'ss'" $opt=!full,ss
		check_e "invalid secontext 'ss'" $opt=!full,mismatch,ss
	done
else
	for opt in '--secontext' '--secontext=full' '-e secontext=mismatch'; do
		check_e "SELinux context printing (--secontext option) is not supported by this build of strace" $opt
	done
fi

for opt in 'id' \
	   'id:' \
	   '-1' \
	   '2147483648' \
	   'id:rand' \
	   'id:randomm' \
	   '2,3,radomm,4' \
	   'format' \
	   'format:' \
	   'id:format' \
	   'id:format:full' \
	   'format:id:0'
do
	check_h "invalid --tips argument: '$opt'" --tips="$opt"
done
for opt in '--tips' \
	   '--tips=' \
	   '--tips=0' \
	   '--tips=id:0 --tips' \
	   '--tips=1,id:42' \
	   '--tips=1 --tips=id:42' \
	   '--tips=random' \
	   '--tips --tips=random' \
	   '--tips=id:random,23' \
	   '--tips=id:random,23 --tips=random,2,3,id:4,5' \
	   '--tips=format:none' \
	   '--tips=format:compact --tips' \
	   '--tips --tips=format:full,3,none,id:42,compact'
do
	check_h "invalid -a argument: '-42'" $opt -a -42
done

check_h 'PROG [ARGS] must be specified with --argv0' --argv0=sample -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' -D -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' -DD -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' -DDD -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' -DDDD -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' --daemonize -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' --daemonize=grandchild -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' --daemonize=pgroup -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' --daemonize=Pgrp -p $$
check_h 'PROG [ARGS] must be specified with -D/--daemonize' --daemonize=SESSION -p $$
check_h 'Too many -D'\''s (4), maximum supported -D count is 3' -DDDD /bin/true
check_e '-D and --daemonize cannot be provided simultaneously' -D --daemonize -p $$
check_e '-D and --daemonize cannot be provided simultaneously' --daemonize -D -p $$
check_e '-D and --daemonize cannot be provided simultaneously' --daemonize -v -D /bit/true
check_h "invalid --daemonize argument: 'pgr'" --daemonize=pgr
check_h '-c/--summary-only and -C/--summary are mutually exclusive' -c -C true
check_h '-c/--summary-only and -C/--summary are mutually exclusive' --summary-only --summary true
check_h '-c/--summary-only and -C/--summary are mutually exclusive' -C -c true
check_h '-c/--summary-only and -C/--summary are mutually exclusive' --summary --summary-only true
check_h '(-c/--summary-only or -C/--summary) and -ff/--output-separately are mutually exclusive' -c -ff true
check_h '(-c/--summary-only or -C/--summary) and -ff/--output-separately are mutually exclusive' --summary-only -ff true
check_h '(-c/--summary-only or -C/--summary) and -ff/--output-separately are mutually exclusive' -C -ff true
check_h '(-c/--summary-only or -C/--summary) and -ff/--output-separately are mutually exclusive' --summary -ff true
check_h '-w/--summary-wall-clock must be given with (-c/--summary-only or -C/--summary)' -w true
check_h '-w/--summary-wall-clock must be given with (-c/--summary-only or -C/--summary)' --summary-wall-clock true
check_h '-U/--summary-columns must be given with (-c/--summary-only or -C/--summary)' -U name,time,count,errors true
check_h '-U/--summary-columns must be given with (-c/--summary-only or -C/--summary)' --summary-columns=name,time,count,errors true
check_h 'piping the output and -ff/--output-separately are mutually exclusive' -o '|' -ff true
check_h 'piping the output and -ff/--output-separately are mutually exclusive' --output='|' -ff true
check_h 'piping the output and -ff/--output-separately are mutually exclusive' -o '!' -ff true
check_h 'piping the output and -ff/--output-separately are mutually exclusive' --output='!' -ff true
check_h "invalid -a argument: '-42'" -a -42
check_h "invalid -O argument: '-42'" -O -42
check_h "invalid -s argument: '-42'" -s -42
check_h "invalid --string-limit argument: '-42'" --string-limit=-42
check_h "invalid -s argument: '1073741824'" -s 1073741824
check_h "invalid --string-limit argument: '1073741824'" --string-limit=1073741824
check_h "must have PROG [ARGS] or -p PID" --follow-forks
check_h "must have PROG [ARGS] or -p PID" --follow-forks --output-separately
check_h "must have PROG [ARGS] or -p PID" -f --output-separately
check_h "must have PROG [ARGS] or -p PID" --output-separately
check_e '-f and --follow-forks cannot be provided simultaneously' -f --follow-forks -p $$
check_e '-ff and --output-separately cannot be provided simultaneously' --output-separately -ff -p $$
check_h "invalid -I argument: '0x1'" -I 0x1
check_h "invalid -I argument: '0'" -I 0
check_h "must have PROG [ARGS] or -p PID" -I1
check_h "must have PROG [ARGS] or -p PID" -I 2
check_h "must have PROG [ARGS] or -p PID" -I3
check_h "must have PROG [ARGS] or -p PID" -I 4
check_h "invalid -I argument: '5'" -I 5
check_h "must have PROG [ARGS] or -p PID" -I always
check_h "must have PROG [ARGS] or -p PID" -I anywhere
check_h "must have PROG [ARGS] or -p PID" -Iwaiting
check_h "must have PROG [ARGS] or -p PID" -I never
check_h "must have PROG [ARGS] or -p PID" -Inever_tstp
check_h "invalid -I argument: '=never'" -I=never
check_h "invalid -I argument: 'nevertheless'" -Inevertheless
check_h "invalid -I argument: 'nev'" -Inev
check_h "invalid --interruptible argument: '0x1'" --interruptible=0x1
check_h "invalid --interruptible argument: '0'" --interruptible=0
check_h "must have PROG [ARGS] or -p PID" --interruptible 1
check_h "must have PROG [ARGS] or -p PID" --interruptible=2
check_h "invalid --interruptible argument: '5'" --interruptible=5
check_h "must have PROG [ARGS] or -p PID" --interruptible=anywhere
check_h "must have PROG [ARGS] or -p PID" --interruptible=waiting
check_h "must have PROG [ARGS] or -p PID" --interruptible=never
check_h "must have PROG [ARGS] or -p PID" --interruptible=never_tstp
check_h "invalid --interruptible argument: 'nevertheless'" --interruptible=nevertheless
check_h "invalid --interruptible argument: 'nev'" --interruptible=nev
check_h "must have PROG [ARGS] or -p PID" --relative-timestamps
check_h "must have PROG [ARGS] or -p PID" --relative-timestamps=s
check_h "must have PROG [ARGS] or -p PID" --relative-timestamps=ms
check_h "must have PROG [ARGS] or -p PID" --relative-timestamps=us
check_h "must have PROG [ARGS] or -p PID" --relative-timestamps=ns
check_h "invalid --relative-timestamps argument: 'n'" --relative-timestamps=n
check_h "invalid --relative-timestamps argument: 'ss'" --relative-timestamps=ss
check_h "must have PROG [ARGS] or -p PID" --syscall-times
check_h "must have PROG [ARGS] or -p PID" --syscall-times=s
check_h "must have PROG [ARGS] or -p PID" --syscall-times=ms
check_h "must have PROG [ARGS] or -p PID" --syscall-times=us
check_h "must have PROG [ARGS] or -p PID" --syscall-times=ns
check_h "invalid --syscall-times argument: 'n'" --syscall-times=n
check_h "invalid --syscall-times argument: 'ss'" --syscall-times=ss
check_h "must have PROG [ARGS] or -p PID" --strings-in-hex
check_h "must have PROG [ARGS] or -p PID" --strings-in-hex=all
check_h "must have PROG [ARGS] or -p PID" --strings-in-hex=non-ascii
check_h "invalid --strings-in-hex argument: 'al'" --strings-in-hex=al
check_h "invalid --strings-in-hex argument: 'alll'" --strings-in-hex=alll
check_h "invalid --strings-in-hex argument: 'ascii'" --strings-in-hex=ascii
check_h "invalid --syscall-limit argument: '-5'" --syscall-limit -5
check_h "invalid --syscall-limit argument: '0'" --syscall-limit=0
check_h "must have PROG [ARGS] or -p PID" --syscall-limit=2
check_h "must have PROG [ARGS] or -p PID" --syscall-limit 5
check_h "must have PROG [ARGS] or -p PID" --quiet=all
check_h "must have PROG [ARGS] or -p PID" --quiet=none
check_h "must have PROG [ARGS] or -p PID" --quiet=\!attach
check_h "must have PROG [ARGS] or -p PID" --quiet=exit,exits,personality
check_e "invalid quiet 'detach'" --quiet=detach -p $$
check_e "invalid quiet 'fds'" -q --quiet=fds -p $$
check_e "invalid quiet 'detach'" --quiet=detach -p $$
check_e '-q and -e quiet/--quiet cannot be provided simultaneously' -q --quiet -p $$
check_e '-q and -e quiet/--quiet cannot be provided simultaneously' -q -e q=none -p $$
check_e '-q and -e quiet/--quiet cannot be provided simultaneously' -q -e silent=attach,personality -p $$
check_e '--kill-on-exit and -p/--attach are mutually exclusive options' --kill-on-exit -p $$
check_e '--kill-on-exit and -p/--attach are mutually exclusive options' --kill-on-exit -p $$ true

check_h 'must have PROG [ARGS] or -p PID' -P .
check_h 'must have PROG [ARGS] or -p PID' -P . -P..
check_h 'must have PROG [ARGS] or -p PID' --trace-path=.
check_h 'must have PROG [ARGS] or -p PID' --trace-path=. --trace-path ..
check_e "Requested path \"///\" resolved into \"/\"
$STRACE_EXE: Requested path \"/.\" resolved into \"/\"
$STRACE_EXE: -q and -e quiet/--quiet cannot be provided simultaneously" -q --quiet -P /// -P/. .

for i in time time_percent time-percent time_total time-total total_time total-time min_time min-time time_min time-min shortest max_time max-time time_max time-max longest avg_time avg-time time_avg time-avg calls count error errors name syscall syscall_name syscall-name none nothing; do
	check_h "must have PROG [ARGS] or -p PID" -S "$i"
	check_h "must have PROG [ARGS] or -p PID" --summary-sort-by="$i"
	if [ "$i" != none ] && [ "$i" != nothing ]; then
		check_h "must have PROG [ARGS] or -p PID" -c -U "$i"
		check_h "must have PROG [ARGS] or -p PID" --summary-only --summary-columns="$i"
	fi
done
for i in time,time_total,avg_time,calls,errors,name time_percent,total_time,time_avg,count,error,syscall_name; do
	check_h "must have PROG [ARGS] or -p PID" -c -U "$i"
	check_h "must have PROG [ARGS] or -p PID" --summary-only --summary-columns="$i"
done
for i in non syscall_names; do
	check_h "invalid sortby: '$i'" -S "$i"
	check_h "invalid sortby: '$i'" --summary-sort-by="$i"
	check_h "unknown column name: '$i'" -U "$i"
	check_h "unknown column name: '$i'" --summary-columns="$i"
done
check_h "unknown column name: ''" -U time,,name
check_h "call summary column has been provided more than once: 'time_percent' (-U option residual: 'time_percent,time_total')" -U time,time_percent,time_total

check_e '-x and --strings-in-hex cannot be provided simultaneously' -x --strings-in-hex -p $$
check_e '-x and --strings-in-hex cannot be provided simultaneously' --strings-in-hex -p $$ -xx
check_h "invalid -X argument: 'test'" -Xtest
check_h "invalid --const-print-style argument: 'test'" --const-print-style=test
check_h "invalid -X argument: 'a'" -Xa
check_h "invalid --const-print-style argument: 'a'" --const-print-style=a
check_h "invalid -X argument: 'abbreviated'" -X abbreviated
check_h "invalid --const-print-style argument: 'abbreviated'" --const-print-style=abbreviated
check_h "must have PROG [ARGS] or -p PID" --decode-fds
check_h "must have PROG [ARGS] or -p PID" --decode-fds=all
check_h "must have PROG [ARGS] or -p PID" --decode-fds=none
check_h "must have PROG [ARGS] or -p PID" --decode-fds=path
check_h "must have PROG [ARGS] or -p PID" --decode-fds=socket,dev
check_h "must have PROG [ARGS] or -p PID" --decode-fds=\!path
check_h "must have PROG [ARGS] or -p PID" --decode-fds=socket,path,dev
check_e "invalid decode-fds 'p'" --decode-fds=p -p $$
check_e "invalid decode-fds 'device'" -y --decode-fds=device -p $$
check_e "invalid decode-fds 'name'" --decode-fds=path,name -p $$
check_e "invalid decode-fds 'sock'" -e decode-fd=sock -y -p $$
check_e '-y and --decode-fds cannot be provided simultaneously' -y --decode-fds -p $$
check_e '-y and --decode-fds cannot be provided simultaneously' -e decode-fd=all -yy -p $$
check_e '-y and --decode-fds cannot be provided simultaneously' --decode-fds=none -y -p $$

check_h "incorrect personality designator '' in qualification 'getcwd@'" -e trace=getcwd@
check_h "incorrect personality designator '42' in qualification 'getcwd@42'" -e trace=getcwd@42
check_h "incorrect personality designator '42' in qualification 'getcwd@42'" -e trace=gettid,getcwd@42
check_h "incorrect personality designator '42' in qualification '23@42'" -e trace=23@42,123
check_h "incorrect personality designator 'ohmy' in qualification '/getcwd@ohmy'" \
	-e trace=/getcwd@ohmy

check_h '--seccomp-bpf cannot be used without -f/--follow-forks, disabling
-w/--summary-wall-clock must be given with (-c/--summary-only or -C/--summary)' --seccomp-bpf -w /
check_h '--seccomp-bpf is not enabled for processes attached with -p
-w/--summary-wall-clock must be given with (-c/--summary-only or -C/--summary)' --seccomp-bpf -f -p 1 -w

check_h 'option -F is deprecated, please use -f/--follow-forks instead
-w/--summary-wall-clock must be given with (-c/--summary-only or -C/--summary)' -F -w /
check_h 'option -F is deprecated, please use -f/--follow-forks instead
-w/--summary-wall-clock must be given with (-c/--summary-only or -C/--summary)' -FF -w /
check_h 'deprecated option -F ignored
-w/--summary-wall-clock must be given with (-c/--summary-only or -C/--summary)' -fF -w /

check_e "invalid -e kvm= argument: 'chdir'" -e kvm=chdir
check_e "invalid -e kvm= argument: 'chdir'" --kvm=chdir

check_h "must have PROG [ARGS] or -p PID" -e decode-pid=all
check_h "must have PROG [ARGS] or -p PID" --decode-pid=none
check_h "must have PROG [ARGS] or -p PID" -e decode-pids=comm
check_h "must have PROG [ARGS] or -p PID" --decode-pid=pidns,comm
check_h "must have PROG [ARGS] or -p PID" -e decode-pid=\!pidns
check_h "must have PROG [ARGS] or -p PID" --decode-pids=\!comm,pidns
check_h "must have PROG [ARGS] or -p PID" -Y -e decode-pids=\!comm,pidns
check_h "must have PROG [ARGS] or -p PID" --decode-pids=\!comm,pidns -Y
check_h "must have PROG [ARGS] or -p PID" --pidns-translation -e decode-pids=\!comm,pidns -Y
check_h "must have PROG [ARGS] or -p PID" --decode-pids=\!comm,pidns --pidns-translation
check_e "invalid decode-pids ''" --decode-pids=
check_e "invalid decode-pids ''" -e decode-pids=
check_e "invalid decode-pids 'chdir'" --decode-pids=chdir
check_e "invalid decode-pids 'gettid'" -e decode-pid=comm,gettid

check_h "must have PROG [ARGS] or -p PID" -e trace-fds=0
check_h "must have PROG [ARGS] or -p PID" -e trace-fd=1,2,3
check_h "must have PROG [ARGS] or -p PID" -e fd='!1'
check_h "must have PROG [ARGS] or -p PID" -e fds='!0,2147483647'
check_e "invalid descriptor '-1'" --trace-fds=-1
check_e "invalid descriptor '2147483648'" --trace-fd=2147483648

case "$STRACE_NATIVE_ARCH" in
x86_64)
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@64
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@32
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@x32
	;;
x32)
	check_h "incorrect personality designator '64' in qualification 'getcwd@64'" -e trace=getcwd@64
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@32
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@x32
	;;
aarch64|powerpc64|s390x|sparc64|tile)
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@64
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@32
	check_h "incorrect personality designator 'x32' in qualification 'getcwd@x32'" -e trace=getcwd@x32
	;;
*)
	pers="$((SIZEOF_LONG * 8))"
	inv_pers="$((96 - pers))"
	check_h "must have PROG [ARGS] or -p PID" -e trace=getcwd@"$pers"
	check_h "incorrect personality designator '$inv_pers' in qualification 'getcwd@$inv_pers'" -e trace=getcwd@"$inv_pers"
	check_h "incorrect personality designator 'x32' in qualification 'getcwd@x32'" -e trace=getcwd@x32
esac

../zeroargc "$STRACE_EXE" /bin/true 2> "$LOG" &&
	dump_log_and_fail_with \
		'zeroargc strace failed to handle the error properly'
cat > "$EXP" << __EOF__
$STRACE_EXE: must have PROG [ARGS] or -p PID
Try '$STRACE_EXE -h' for more information.
__EOF__
diff -u -- "$EXP" "$LOG" > /dev/null || {
	cat > "$EXP" <<- '__EOF__'
	strace: must have PROG [ARGS] or -p PID
	Try 'strace -h' for more information.
	__EOF__
	match_diff "$LOG" "$EXP" \
		"zeroargc $STRACE $args output mismatch"
}

check_uid_gid_syntax()
{
	check_e "Invalid UID:GID pair 'uid:gid'" -u uid:gid true
	check_e "Invalid UID:GID pair '4294967295:4294967294'" \
		-u 4294967295:4294967294 true
	check_e "Invalid UID:GID pair '4294967294:4294967295'" \
		-u 4294967294:4294967295 true
	run_strace --user="$(id -u):$(id -g)" -qq -enone /bin/true
}

uid="${UID:-`id -u`}"
if [ "$uid" -ge 0 ]; then
	if [ "$uid" -eq 0 ]; then
		check_uid_gid_syntax
		umsg="Cannot find user '!no such user!'"
	else
		if [ "$(fakeroot ../block_reset_run 15 id -u 2>&1)" = 0 ]; then
			saved_STRACE=$STRACE
			STRACE="fakeroot -- $STRACE"
			check_uid_gid_syntax
			umsg="Cannot find user '!no such user!'"
			check_e "$umsg" -u '!no such user!' true
			STRACE=$saved_STRACE
		fi
		umsg='You must be root to use the -u/--username option'
	fi

	check_e "$umsg" -u '!no such user!' true

	for c in i/--instruction-pointer n/--syscall-number r/--relative-timestamps t/--absolute-timestamps T/--syscall-times y/--decode-fds; do
		check_e "-$c has no effect with -c/--summary-only
$STRACE_EXE: $umsg" -u '!no such user!' -c -${c%%/*} true
	done

	check_e "-i/--instruction-pointer has no effect with -c/--summary-only
$STRACE_EXE: -n/--syscall-number has no effect with -c/--summary-only
$STRACE_EXE: -r/--relative-timestamps has no effect with -c/--summary-only
$STRACE_EXE: -t/--absolute-timestamps has no effect with -c/--summary-only
$STRACE_EXE: -T/--syscall-times has no effect with -c/--summary-only
$STRACE_EXE: -y/--decode-fds has no effect with -c/--summary-only
$STRACE_EXE: Only the last of -z/--successful-only/-Z/--failed-only options will take effect. See status qualifier for more complex filters.
$STRACE_EXE: $umsg" -u '!no such user!' -cinrtTyzZ true

	if [ -n "$compiled_with_secontext" ]; then
		check_e "--secontext has no effect with -c/--summary-only
$STRACE_EXE: $umsg" -u '!no such user!' -c --secontext true
	else
		check_e "SELinux context printing (--secontext option) is not supported by this build of strace" -c --secontext true
	fi

	if [ -n "$compiled_with_stacktrace" ]; then
		check_e "-k/--stack-trace has no effect with -c/--summary-only
$STRACE_EXE: $umsg" -u '!no such user!' -c -k true
	fi

	for c in --output-separately -A/--output-append-mode; do
		check_e "$c has no effect without -o/--output
$STRACE_EXE: $umsg" -u '!no such user!' ${c%%/*} true
	done

	check_e "-S/--summary-sort-by has no effect without (-c/--summary-only or -C/--summary)
$STRACE_EXE: $umsg" -u '!no such user!' --summary-sort-by errors true

	check_e "--output-separately has no effect without -o/--output
$STRACE_EXE: -A/--output-append-mode has no effect without -o/--output
$STRACE_EXE: $umsg" -u '!no such user!' --output-separately --output-append-mode true

	check_e "$umsg" -u '!no such user!' -ff true
	check_e "$umsg" -u '!no such user!' --output-separately --follow-forks true

	check_e "Only the last of -z/--successful-only/-Z/--failed-only options will take effect. See status qualifier for more complex filters.
$STRACE_EXE: $umsg" -u '!no such user!' -z --successful-only true
	check_e "Only the last of -z/--successful-only/-Z/--failed-only options will take effect. See status qualifier for more complex filters.
$STRACE_EXE: $umsg" -u '!no such user!' --successful-only -Z true
	check_e "Only the last of -z/--successful-only/-Z/--failed-only options will take effect. See status qualifier for more complex filters.
$STRACE_EXE: $umsg" -u '!no such user!' --successful-only --failed-only true

	check_e "-n/--syscall-number has no effect with -c/--summary-only
$STRACE_EXE: $umsg" --user='!no such user!' --syscall-number --summary-only true

	check_e "-i/--instruction-pointer has no effect with -c/--summary-only
$STRACE_EXE: $umsg" --user='!no such user!' --instruction-pointer --summary-only true
fi

check_e_using_grep 'ptrace_setoptions = 0x[[:xdigit:]]+' -d /
check_e_using_grep 'ptrace_setoptions = 0x[[:xdigit:]]+' --debug /

check_h "invalid --stack-trace-frame-limit argument: '1073741824'" --stack-trace-frame-limit 1073741824
check_h "invalid --stack-trace-frame-limit argument: '0'" --stack-trace-frame-limit=0
if [ -z "$compiled_with_stacktrace" ]; then
	check_e "Stack traces (-k/--stack-trace option) are not supported by this build of strace" -k
	check_e "Stack traces (-k/--stack-trace option) are not supported by this build of strace" --stack-trace
	check_e "Stack traces (-k/--stack-trace option) are not supported by this build of strace" --stack-traces
	check_e "Stack traces (-k/--stack-trace option) are not supported by this build of strace" --stack-trace=symbol
	check_e "Stack traces (-k/--stack-trace option) are not supported by this build of strace" --stack-traces=symbol
	check_e "Stack traces (-k/--stack-trace option) are not supported by this build of strace" --stack-trace=source
	check_e "Stack traces (-k/--stack-trace option) are not supported by this build of strace" --stack-traces=source
	check_e "Stack traces (--stack-trace-frame-limit option) are not supported by this build of strace" \
		--stack-trace-frame-limit=1
else
	check_e "--stack-trace-frame-limit has no effect without -k/--stack-trace
$STRACE_EXE: $umsg" -u '!no such user!' --stack-trace-frame-limit=1 true
	if [ -n "$compiled_with_libunwind" ]; then
		check_e "Stack traces with source line information (-kk/--stack-trace=source option) are not supported by this build of strace" -kk
		check_e "Stack traces with source line information (-kk/--stack-trace=source option) are not supported by this build of strace" --stack-trace=source
		check_e "Stack traces with source line information (-kk/--stack-trace=source option) are not supported by this build of strace" --stack-traces=source
	elif [ -n "$compiled_with_libdw" ]; then
		check_e "Too many -k options" -kkk
	fi
fi

check_zero -p "$$  $$" -V
check_zero -p "$$   $$" -V
check_zero -p "$$    $$" -V
check_zero -p "$$,,$$" -V
check_zero -p "$$, ,$$" -V
check_zero -p "$$, , ,$$" -V
check_zero -p "$$, ,, ,$$" -V

args='-p 2147483647'
$STRACE $args 2> "$LOG" &&
	dump_log_and_fail_with \
		"strace $args failed to handle the error properly"

for cmd in PTRACE_SEIZE PTRACE_ATTACH; do
	cat > "$EXP" << __EOF__
$STRACE_EXE: attach: ptrace($cmd, 2147483647): No such process
__EOF__
	diff -- "$EXP" "$LOG" ||
		continue
	args=
	break
done

[ -z "$args" ] ||
	dump_log_and_fail_with \
		"strace $args failed to print expected diagnostics"
