--- /dev/null
+#!/usr/bin/perl
+# setexec: turns a file's executability on or off, same semantics as rsync's --executability
+# usage: setexec { + | - | --reference=<file> } <file> [...]
+
+$cmd = $ARGV[0];
+shift @ARGV;
+
+if ($cmd =~ /^--reference=(.*)$/) {
+ $ref_file = $1;
+ @stbuf = stat($ref_file);
+ if (@stbuf == 0) {
+ die "setexec: stat($ref_file): $!\n";
+ }
+ $ref_perms = $stbuf[2] & 07777;
+ if (($ref_perms & 0111) == 0) {
+ $cmd = '-';
+ } else {
+ $cmd = '+';
+ }
+} elsif ($cmd ne '+' && $cmd ne '-') {
+ die "usage: setexec { + | - | --reference=<file> } <file> [...]\n";
+}
+
+sub docmd($$) {
+ my ($cmd, $perms) = @_;
+ if ($cmd eq '+') {
+ return $perms | ($perms & 0444) >> 2;
+ } elsif ($cmd eq '-') {
+ return $perms & ~0111;
+ }
+}
+
+file: foreach $file (@ARGV) {
+ @stbuf = stat($file);
+ if (@stbuf == 0) {
+ warn "setexec: stat($file): $!, skipping file\n";
+ next file;
+ }
+ $perms = $stbuf[2] & 07777;
+ $perms = docmd($cmd, $perms);
+ chmod($perms, $file) or warn "setexec: chmod($perms, $file): $!, skipping file\n";
+}