Blob


1 #!/bin/sh
3 main() {
4 if [ -z "$1" ]; then
5 echo "Missing arguments" >&2
6 display_usage >&2
7 return 1
8 elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
9 display_usage
10 elif [ "$1" = "--setup" ]; then
11 shift
12 setup "$@"
13 else
14 execute "$@"
15 fi
16 }
18 execute() {
19 command=""
20 asuser=""
22 while [ -n "$1" ]; do
23 if [ "$1" = "--as" ]; then
24 if [ -z "$2" ]; then
25 echo "--as user not specified" >&2
26 display_usage >&2
27 return 1
28 elif [ -n "$asuser" ]; then
29 echo "--as user specified twice" >&2
30 display_usage >&2
31 return 1
32 fi
34 asuser="$2"
35 shift
36 shift
37 elif [ -z "$command" ]; then
38 command="$1"
39 shift
40 elif [ "$1" = "--" ]; then
41 shift
42 break
43 else
44 break
45 fi
46 done
48 if [ -z "$command" ]; then
49 echo "Command not specified" >&2
50 return 1
51 fi
53 cmdfullpath="`which -- $command`"
54 if [ -z "$cmdfullpath" ]; then
55 echo "Command not found: $command" >&2
56 return 1
57 fi
59 if [ -z "$asuser" ]; then
60 basename="`basename $cmdfullpath`"
61 asuser="$USER-$basename"
62 fi
64 otherhome="`grep ^$asuser: /etc/passwd | head -n1 | cut -d: -f6`"
65 if [ -z "$otherhome" ]; then
66 echo "Could not find home of $asuser" >&2
67 return 1
68 fi
70 authfile="$otherhome/.Xauthority"
72 set -e
73 touch $authfile
74 xauth -f $authfile generate $DISPLAY . trusted
75 chgrp $asuser $authfile
76 chmod g+r $authfile
78 cd $otherhome
80 # Closes IO handlers to avoid tty manipulation
81 # See: https://github.com/garotosopa/xodo/issues/1
83 XAUTHORITY="$authfile" exec perl -e "
84 use strict;
85 use warnings;
86 use POSIX qw(setsid uname);
87 my (\$sysname) = uname();
88 close STDIN; close STDOUT; close STDERR;
89 fork and exit;
90 setsid;
91 if (\$sysname eq \"OpenBSD\") {
92 exec 'doas', '-u', \$ARGV[0], \$ARGV[1], @ARGV[2 .. @ARGV-1];
93 } else {
94 exec 'sudo', '-u', \$ARGV[0], \$ARGV[1], (defined \$ARGV[2] ? @ARGV[2 .. @ARGV-1] : ());
95 }
96 " -- "$asuser" "$cmdfullpath" "$@"
97 }
99 setup() {
100 if [ -z "$1" ]; then
101 echo "Command not specified" >&2
102 display_usage >&2
103 return 1
104 fi
106 command="`which -- $1`"
108 if [ -z "$command" ]; then
109 echo "Command not found: $command" >&2
110 return 1
111 fi
113 basename="`basename $command`"
115 shift
117 while [ -n "$1" ]; do
118 if [ "$1" = "--as" ]; then
119 if [ -z "$2" ]; then
120 echo "--as user not specified" >&2
121 display_usage >&2
122 return 1
123 elif [ -n "$asuser" ]; then
124 echo "--as user specified twice" >&2
125 display_usage >&2
126 return 1
127 fi
129 asuser="$2"
130 shift
131 shift
132 elif [ "$1" = "--for" ]; then
133 if [ -z "$2" ]; then
134 echo "--for user not specified" >&2
135 display_usage >&2
136 return 1
137 elif [ -n "$foruser" ]; then
138 echo "--for user specified twice" >&2
139 display_usage >&2
140 return 1
141 fi
143 foruser="$2"
144 shift
145 shift
146 else
147 echo "Invalid argument: $1" >&2
148 display_usage
149 return 1
150 fi
151 done
153 foruser="${foruser-$USER}"
154 asuser="${asuser-$foruser-$basename}"
156 case "`uname`" in
157 Linux)
158 setup_function=setup_linux
159 priv_file=/etc/sudoers.d/xodo
160 ;;
161 OpenBSD)
162 setup_function=setup_openbsd
163 priv_file=/etc/doas.conf
164 ;;
165 *)
166 echo "Unsupported platform: `uname`" >&2
167 return 1
168 ;;
169 esac
171 echo "The following steps will be executed:"
172 echo " - add user $asuser if it doesn't exist;"
173 echo " - make $asuser's home readable and writable by its group;"
174 echo " - add group $asuser to user $foruser;"
175 echo " - add an entry to $priv_file"
176 echo " allowing existing user $foruser"
177 echo " to execute $command"
178 echo " as new user $asuser with no password."
180 echo -n "Proceed? [y/n] "
181 read proceed
182 if [ "$proceed" != "y" ] && [ "$proceed" != "Y" ]; then
183 echo "Aborted."
184 return 1
185 fi
187 set -e
189 $setup_function "$command" "$asuser" "$foruser"
191 echo "Done."
192 echo "If user $foruser is logged in, it must log out and in again before using xodo as $asuser, so that it gets added to the new group."
195 setup_linux() {
196 command="$1"
197 asuser="$2"
198 foruser="$3"
200 if [ -z "`grep "^$asuser:" /etc/passwd`" ]; then
201 useradd --create-home --skel /dev/null --user-group --key UMASK=002 "$asuser"
202 fi
204 usermod -aG "$asuser" "$foruser"
205 echo "$foruser ALL = ($asuser) NOPASSWD: $command" >> /etc/sudoers.d/xodo
208 setup_openbsd() {
209 command="$1"
210 asuser="$2"
211 foruser="$3"
213 if [ -z "`grep "^$asuser:" /etc/passwd`" ]; then
214 useradd -m -k "" "$asuser"
215 fi
217 usermod -G "$asuser" "$foruser"
219 otherhome="`grep "^$asuser:" /etc/passwd | head -n1 | cut -d: -f6`"
220 if [ -z "$otherhome" ]; then
221 echo "Could not find home of $asuser" >&2
222 return 1
223 fi
225 chmod g+rwX "$otherhome"
227 echo "\npermit nopass setenv { DISPLAY HOME=$otherhome USER=$asuser } $foruser as $asuser cmd $command" >> /etc/doas.conf
230 display_usage() {
231 echo "usage: xodo <command> [--as <user>] [--] [args...]"
232 echo " xodo --setup <command> [--as <user>] [--for <user>]"
233 echo " xodo --help"
236 main "$@"