diff options
Diffstat (limited to 'autoshart.sh')
-rwxr-xr-x | autoshart.sh | 242 |
1 files changed, 0 insertions, 242 deletions
diff --git a/autoshart.sh b/autoshart.sh deleted file mode 100755 index 9e9a1a7..0000000 --- a/autoshart.sh +++ /dev/null | |||
@@ -1,242 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | # AUTOSHART: autostart *.desktop files | ||
3 | # Copyright (C) 2022 Case Duckworth <acdw@acdw.net> | ||
4 | # Licensed under the Fair license. See COPYING for details. | ||
5 | # | ||
6 | # Commentary: | ||
7 | # | ||
8 | # An autostart script. Called "autoshart" because I literally sharted it out, | ||
9 | # and have /not/ tested it at all. So, caveat emptor, I guess. | ||
10 | # | ||
11 | # Freedesktop autostart specification: | ||
12 | # https://specifications.freedesktop.org/autostart-spec/latest/ | ||
13 | # Freedesktop desktop entry specification: | ||
14 | # https://specifications.freedesktop.org/desktop-entry-spec/latest/ | ||
15 | # | ||
16 | # Prior art: | ||
17 | # - dex -- https://github.com/jceb/dex | ||
18 | # | ||
19 | # Code: | ||
20 | |||
21 | usage() { | ||
22 | cat <<EOF | ||
23 | AUTOSHART: autostart without the shit | ||
24 | USAGE: autoshart -h | ||
25 | autoshart [-k] [-n] [-q] | ||
26 | |||
27 | FLAGS: | ||
28 | -h Show this help and exit. | ||
29 | -k Kill all processes started by autoshart and exit. | ||
30 | -n Only print what would happen; don't execute anything. | ||
31 | -q Don't print any output. | ||
32 | EOF | ||
33 | } | ||
34 | |||
35 | main() { | ||
36 | PID_FILE="${AUTOSHART_PID_FILE:-/tmp/autoshart.pid}" | ||
37 | FOUND_FILE="${AUTOSHART_FOUND_FILE:-/tmp/autoshart.found}" | ||
38 | RUN=true | ||
39 | QUIET=false | ||
40 | while getopts hknq opt; do | ||
41 | case "$opt" in | ||
42 | h) usage ;; | ||
43 | k) auto_kill ;; | ||
44 | n) RUN=false ;; | ||
45 | q) QUIET=true ;; | ||
46 | esac | ||
47 | done | ||
48 | shift "$((OPTIND - 1))" | ||
49 | auto_search | ||
50 | } | ||
51 | |||
52 | ## Library functions | ||
53 | |||
54 | auto_kill() { | ||
55 | cat "$PID_FILE" | xargs kill | ||
56 | } | ||
57 | |||
58 | auto_start() { ## auto_start FILE | ||
59 | eprint "$1" | ||
60 | # When the .desktop file has the Hidden key set to true, the .desktop | ||
61 | # file MUST be ignored. When multiple .desktop files with the same name | ||
62 | # exists in multiple directories then only the Hidden key in the most | ||
63 | # important .desktop file must be considered: If it is set to true all | ||
64 | # .desktop files with the same name in the other directories MUST be | ||
65 | # ignored as well. | ||
66 | hidden="$(get Hidden "$1")" | ||
67 | test "$hidden" = true && return "$(die 1 "Stopped: Hidden: $1")" | ||
68 | # This specification defines 3 types of desktop entries: Application | ||
69 | # (type 1), Link (type 2) and Directory (type 3). To allow the addition | ||
70 | # of new types in the future, implementations should ignore desktop | ||
71 | # entries with an unknown type. (REQUIRED) | ||
72 | type="$(get Type "$1")" | ||
73 | test "$type" = Application || return "$(die 2 "Error: Bad desktop type: ${type:-[none]}")" | ||
74 | # Specific name of the application, for example "Mozilla". (REQUIRED) | ||
75 | name="$(get Name "$1" | head -n1)" | ||
76 | test -n "$name" || return "$(die 3 "Error: No application name")" | ||
77 | # Program to execute, possibly with arguments. See the Exec key for | ||
78 | # details on how this key works. The Exec key is required if | ||
79 | # DBusActivatable is not set to true. Even if DBusActivatable is true, | ||
80 | # Exec should be specified for compatibility with implementations that | ||
81 | # do not understand DBusActivatable. (Makes no sense to be omitted in an | ||
82 | # autostart context --- acdw) | ||
83 | exec="$(get Exec "$1")" | ||
84 | test -n "$exec" || return "$(die 4 "Error: No Exec key: $1")" | ||
85 | # The OnlyShowIn entry may contain a list of strings identifying | ||
86 | # the desktop environments that MUST autostart this application, all | ||
87 | # other desktop environments MUST NOT autostart this application. The | ||
88 | # NotShowIn entry may contain a list of strings identifying the desktop | ||
89 | # environments that MUST NOT autostart this application, all other | ||
90 | # desktop environments MUST autostart this application. Only one of | ||
91 | # these keys, either OnlyShowIn or NotShowIn, may appear in a single | ||
92 | # .desktop file. | ||
93 | # | ||
94 | ### The OnlyShowIn, NotShowIn keys are specified thus: | ||
95 | # | ||
96 | # A list of strings identifying the desktop environments that should | ||
97 | # display/not display a given desktop entry. | ||
98 | # | ||
99 | # By default, a desktop file should be shown, unless an OnlyShowIn key | ||
100 | # is present, in which case, the default is for the file not to be | ||
101 | # shown. | ||
102 | # | ||
103 | # If $XDG_CURRENT_DESKTOP is set then it contains a colon-separated list | ||
104 | # of strings. In order, each string is considered. If a matching entry | ||
105 | # is found in OnlyShowIn then the desktop file is shown. If an entry is | ||
106 | # found in NotShowIn then the desktop file is not shown. If none of the | ||
107 | # strings match then the default action is taken (as above). | ||
108 | # | ||
109 | # $XDG_CURRENT_DESKTOP should have been set by the login manager, | ||
110 | # according to the value of the DesktopNames found in the session | ||
111 | # file. The entry in the session file has multiple values separated in | ||
112 | # the usual way: with a semicolon. | ||
113 | # | ||
114 | # The same desktop name may not appear in both OnlyShowIn and NotShowIn | ||
115 | # of a group. | ||
116 | # | ||
117 | ### I think this "functionality" is dubious at best and pretty | ||
118 | ### ... silly. --- acdw | ||
119 | onlyshowin="$(get OnlyShowIn "$1")" | ||
120 | notshowin="$(get NotShowIn "$1")" | ||
121 | if test -n "$onlyshowin" && test -n "$notshowin"; then | ||
122 | return "$(die 5 "Error: Incompatible keys: OnlyShowIn, NotShowIn: $1")" | ||
123 | elif test -n "$onlyshowin"; then | ||
124 | start=false | ||
125 | else | ||
126 | start=true | ||
127 | fi | ||
128 | |||
129 | # This is so cursed | ||
130 | quit="$( | ||
131 | echo "$XDG_CURRENT_DESKTOP" | tr : \\n | | ||
132 | while read desktop; do | ||
133 | case "$onlyshowin;$notshowin" in | ||
134 | *$desktop*) | ||
135 | if test -n "$onlyshowin"; then | ||
136 | break | ||
137 | elif test -n "$notshowin"; then | ||
138 | echo true | ||
139 | die 6 "Stopped: NotShowIn=$notshowin" | ||
140 | fi | ||
141 | ;; | ||
142 | *) | ||
143 | if ! $start; then | ||
144 | echo true | ||
145 | die 6 "Stopped: OnlyShowIn=$onlyshowin" | ||
146 | fi | ||
147 | ;; | ||
148 | esac | ||
149 | done | ||
150 | echo false | ||
151 | )" | ||
152 | if $quit; then | ||
153 | return 6 | ||
154 | fi | ||
155 | |||
156 | # A .desktop file with a non-empty TryExec field MUST NOT be autostarted | ||
157 | # if the value of the TryExec key does NOT match with an installed | ||
158 | # executable program. The value of the TryExec field may either be an | ||
159 | # absolute path or the name of an executable without any path | ||
160 | # components. If the name of an executable is specified without any path | ||
161 | # components then the $PATH environment is searched to find a matching | ||
162 | # executable program. | ||
163 | tryexec="$(get TryExec "$1")" | ||
164 | if test -n "$tryexec"; then | ||
165 | command -v "$tryexec" | grep -v ^alias | grep -q / || | ||
166 | return "$(die 7 "Error: TryExec command not found: $tryexec")" | ||
167 | fi | ||
168 | # If all these tests pass, we're ready to go | ||
169 | # XXX: probably won't do quoting properly | ||
170 | eprint "> $exec" | ||
171 | if $RUN; then | ||
172 | $exec & | ||
173 | print $! >>"$PID_FILE" | ||
174 | fi | ||
175 | : | ||
176 | } | ||
177 | |||
178 | auto_search() { ## auto_search | ||
179 | # The Autostart Directories are $XDG_CONFIG_DIRS/autostart as defined | ||
180 | # in accordance with the "Referencing this specification" section in | ||
181 | # the "desktop base directory specification". | ||
182 | # | ||
183 | # If the same filename is located under multiple Autostart Directories | ||
184 | # only the file under the most important directory should be used. | ||
185 | # | ||
186 | # Example: If $XDG_CONFIG_HOME is not set the Autostart Directory in the | ||
187 | # user's home directory is ~/.config/autostart/ | ||
188 | # | ||
189 | # Example: If $XDG_CONFIG_DIRS is not set the system wide Autostart | ||
190 | # Directory is /etc/xdg/autostart/ | ||
191 | # | ||
192 | # Example: If $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS are not set and the | ||
193 | # two files /etc/xdg/autostart/foo.desktop and | ||
194 | # ~/.config/autostart/foo.desktop exist then only the file | ||
195 | # ~/.config/autostart/foo.desktop will be used because | ||
196 | # ~/.config/autostart/ is more important than /etc/xdg/autostart/ | ||
197 | echo "${XDG_CONFIG_HOME:-$HOME/.config}:${XDG_CONFIG_DIRS:-/etc/xdg}" | tr : \\n | | ||
198 | sed 's,$,/autostart,' | | ||
199 | while read dir; do | ||
200 | if test -d "$dir"; then | ||
201 | for desktop in "$dir"/*.desktop; do | ||
202 | if ! grep -q "$desktop" "$FOUND_FILE"; then | ||
203 | auto_start "$desktop" && | ||
204 | # `echo' here is | ||
205 | # important; it /needs/ | ||
206 | # to be output to the | ||
207 | # $FOUND_FILE | ||
208 | echo "$desktop" >>"$FOUND_FILE" | ||
209 | else | ||
210 | eprint "Already executed: $desktop" | ||
211 | fi | ||
212 | done | ||
213 | fi | ||
214 | done | ||
215 | } | ||
216 | |||
217 | ## Convenience functions | ||
218 | |||
219 | get() { # get KEY FILE | ||
220 | grep "^$1" "${2:-}" 2>/dev/null | cut -d= -f2- | ||
221 | } | ||
222 | |||
223 | print() { | ||
224 | $QUIET || printf '%s\n' "$*" | ||
225 | } | ||
226 | |||
227 | eprint() { | ||
228 | print "$@" >&2 | ||
229 | } | ||
230 | |||
231 | die() { | ||
232 | errcode="$1" | ||
233 | shift | ||
234 | eprint "! $@" | ||
235 | echo $errcode | ||
236 | exit $errcode | ||
237 | } | ||
238 | |||
239 | ## Entry point | ||
240 | |||
241 | test "$DEBUG" && set -x | ||
242 | main "$@" | ||