OSDN Git Service

[fix] : Fixed SC2124
[alterlinux/dmc.git] / dmc
1 #!/usr/bin/env bash
2 #
3 # Yamada Hayao
4 # Twitter: @Hayao0819
5 # Email  : hayao@fascode.net
6 #
7 # (c) 2019-2021 Fascode Network.
8 #
9 # dmc
10 #
11 # LICENSE: THE SUSHI-WARE LICENSE
12 # https://github.com/MakeNowJust/sushi-ware
13 #
14 #
15 # 参考資料
16 # https://qiita.com/laikuaut/items/4bc07eabce56ee30812d
17 # https://qiita.com/t_nakayama0714/items/80b4c94de43643f4be51
18
19 script_usage(){
20     echo "usage: dmc [options] [command]"
21     echo
22     echo "A simple tool for switching LightDM Greeters"
23     echo
24     echo " LightDM command:"
25     echo "    autologin [username] [session]    Set up automatic login (with blank username to disable)"
26     echo "    greeter                           Run greeter setup wizard"
27     echo "    greeter-create [file]             Set the specified executable file as Greeter"
28     echo "    greeter-change [greeter]          Specify the greeter to use"
29     echo "    greeter-edit [greeter]            Edit the greeter configs"
30     echo "    greeter-list                      Show a list of currently installed Greeters"
31     echo "    remove                            Removes all changes made by this command"
32     echo "    edit                              Edit lightdm config"
33     echo "    show-config                       Show current settings"
34     echo
35     echo " GDM command:"
36     echo "    autologin [username] [session]    Set up automatic login (with blank username to disable)"
37     echo "    cursor                            Run cursor selection wizard"
38     #echo "    cursor-change [cursor]            Specify the cursor theme"
39     echo "    cursor-list                       Show a list of cursor theme"
40     echo "    sound [true or false]             Toggle the sound when an event occurs"
41     echo "    logo [image]                      Specify the logo of the login screen"
42     echo "    tap [true or false]               Toggle whether to recognize the tap as a click"
43     echo "    accessibility [true or false]     Toggle whether to show accessibility menu"
44     echo "    root-login [true or false]        Toggle whether to enable root login"
45     echo
46     echo " Webkit2 command:"
47     echo "    theme                             Run theme selection wizard"
48     echo "    theme-change [theme]              Specify the theme"
49     echo
50     echo " Qtquick command:"
51     echo "    back                              Specify the background image"
52     echo
53     echo " General option:"
54     echo "    -m | --mode                       Specifiy the target you want to set"
55     echo "    -e | --editer                     Specifiy the editor to use for editing"
56     echo "    -h | --help                       This help message and exit"
57     echo "    --non-interactive                 Run in non-interactive mode"
58     echo "    --noroot                          No check root permission"
59     echo "    --write-all-files                 Allows rewriting of all configuration files"
60     echo
61     echo " Supported modes:"
62     echo "    Display managers: lightdm, gdm"
63     echo "    LightDM greeters: webkit2, qtquick"
64     echo
65 }
66
67 set -eu
68
69 # エラー
70 msg_error() {
71     echo "${@}" 1>&2
72 }
73
74 # 警告
75 msg_warn() {
76     echo "${@}" 1>&2
77 }
78
79 # rootチェック
80 check_root(){
81     if [[ "${NOROOT}" = false ]] && (( "${UID}" != 0 )); then
82         msg_error "You have to run as root"
83         exit 1
84     fi
85 }
86
87 # 数値チェック
88 check_int(){
89     set +e
90     #if (( "$(expr "${1}" + 1 >/dev/null 2>&1; printf "${?}")" < 2 )); then
91     if printf "%s" "${1}" | grep -E "^[0-9]+$" 1>/dev/null 2>&1; then
92         set -e
93         return 0
94     else
95         set -e
96         return 1
97     fi
98 }
99
100 check_bool(){
101     if [[ -n "${1}" ]] && { [[ "${1}" = "true" ]] ||[[ "${1}" = "false" ]]; }; then
102         return 0
103     else
104         return 1
105     fi
106 }
107
108 # crudini ラッパー
109 wrapper(){
110     local _command="${1}"
111     shift 1
112     if which "${_command}" >/dev/null 2>&1; then
113         $(which "${_command}") "${@}"
114     else
115         msg_error "${_command} was not found"
116         exit 1
117     fi
118 }
119
120 crudini(){
121     wrapper crudini "${@}"
122 }
123
124 jq(){
125     wrapper jq "${@}"
126 }
127
128
129 # カーソルテーマの一覧を取得
130 get_cursor_theme(){
131     # カーソルテーマの一覧を取得
132     # 参考: https://wiki.archlinux.jp/index.php/%E3%82%AB%E3%83%BC%E3%82%BD%E3%83%AB%E3%83%86%E3%83%BC%E3%83%9E
133     # 参考: https://wiki.archlinux.jp/index.php/GDM
134     #echo "Searching cursor themes..." 1>&2
135     local _dir _cursor_theme_dir_list _find_cursor_dir_list=("/usr/share/icons" "${HOME}/.local/share/icons" "${HOME}/.icons")
136     for _dir in "${_find_cursor_dir_list[@]}"; do
137         if [[ -d "${_dir}" ]]; then
138             _cursor_theme_dir_list=($(find "${_dir}" -type d -name "cursors" | xargs -i dirname {} | sort))
139         fi
140     done
141     
142     local _cursor_theme _cursor_theme_name _temp
143     for _cursor_theme in "${_cursor_theme_dir_list[@]}"; do
144         _temp+=("$(cat "${_cursor_theme}/cursor.theme" 2> /dev/null | grep -E "^Name=" | sed "s|^Name=||g")")
145         if [[ -z "${_temp}" ]]; then
146             _cursor_theme_name+=("$(basename "${_cursor_theme}")")
147         fi
148     done
149     echo "${_cursor_theme_name[@]}"
150 }
151
152 #== LightDM用の汎用関数 ==#
153 # キーが設定されている設定ファイル
154 lightdm_get_source_file(){
155     local key="${1}"
156     local source_name="$(lightdm --show-config 2>&1 | grep -E "^[A-Z]  ${key}=" | cut -d ' ' -f 1)"
157     local source_path="$(lightdm --show-config 2>&1 | grep -x -A "$(lightdm --show-config 2>&1 | wc -l)" "Sources:" | grep -xv "Sources" | grep -E "^${source_name}  " | sed "s|^${source_name}  ||g")"
158     if [[ -n "${source_path}" ]]; then
159         echo -n "${source_path}"
160     else
161         echo -n ""
162     fi
163 }
164
165
166 # 設定ファイルの値を変更する
167 lightdm_set_config(){
168     local key="${1}" value="${2}" file=${3-${LIGHTDM_CONFIG}}
169     if [[ "${WRITE_ALL_FILES}" = true ]] && [[ -n "$(lightdm_get_source_file "${1}")" ]]; then
170         crudini --set "$(lightdm_get_source_file "${1}")" 'Seat:*' "${1}" "${2}"
171     else
172         crudini --set "${file}" 'Seat:*' "${1}" "${2}"
173     fi
174
175     if [[ ! "$(lightdm_get_value "${1}")" = "${2}" ]]; then
176         msg_error "Failed to change the setting value. A value has already been set for $(lightdm_get_source_file "${1}")"
177         msg_error "lightdm-config does not manipulate other configuration files for safety. Comment out the settings in that file."
178     fi
179 }
180
181 # 設定ファイルのキーを削除する
182 lightdm_remove_key(){
183     local key="${1}" _config
184     if cat "${LIGHTDM_CONFIG}" | grep -E "^ ?${key}.+" > /dev/null; then
185         sed -i -r "s|^ ?${key} ?=.+||g" "${LIGHTDM_CONFIG}"
186         sed -i '/^$/d' "${LIGHTDM_CONFIG}"
187     fi
188 }
189
190 # 設定ファイルを作成
191 lightdm_init_configs(){
192     check_root
193     if [[ ! -f "${LIGHTDM_CONFIG}" ]]; then
194         mkdir -p "$(dirname "${LIGHTDM_CONFIG}")"
195         touch "${LIGHTDM_CONFIG}"
196         echo "[Seat:*]" > "${LIGHTDM_CONFIG}"
197     fi
198 }
199
200 # 現在設定されている値を取得する
201 lightdm_get_value(){
202     local _current_value="$(lightdm --show-config 2>&1 | grep -E "^[A-Z]  ${1}=" | sed "s|^[A-Z]  ||g" | cut -d "=" -f "2")"
203     if [[ "${_current_value}" ]]; then
204         echo -n "${_current_value}"
205         return 0
206     else
207         echo -n ""
208         return 0
209     fi
210 }
211
212 #== LightDM用コマンド ==#
213 # greeter-changeコマンド
214 command_lightdm_greeter_change() {
215     # 引数チェック
216     if [[ -z "${1}" ]]; then
217         msg_error "Please specify Greeter."
218         script_usage
219         exit 1
220     fi
221
222     # 指定されたGreeterが正しいか確認
223     if ! printf "%s\n" "${LIGHTDM_GREETERS[@]}" | grep -x "${1}" > /dev/null 2>&2; then
224         msg_error "The greeter (${1}) doesn't exist."
225         exit 1
226     else
227         lightdm_set_config "greeter-session" "${1}"
228     fi
229 }
230
231 # greeter-createコマンド
232 command_lightdm_greeter_create(){
233     if [[ -z "${1}" ]]; then
234         msg_error "Please specify Greeter."
235         script_usage
236         exit 1
237     fi
238     if [[ ! -f "${1}" ]]; then
239         msg_error "${1} does not exist."
240         script_usage
241         exit 1
242     fi
243     if [[ ! -x "${1}" ]]; then
244         msg_error "hoge is not an executable file."
245         script_usage
246         exit 1
247     fi
248
249     local path="${1}"
250     local filename="$(basename "${1}")"
251
252     if [[ -f "/usr/share/xgreeters/${filename}.desktop" ]]; then
253         msg_error "Greeter with the same name already exists."
254         exit 1
255     fi
256     cat > "/usr/share/xgreeters/${filename}.desktop"  <<EOF
257 [Desktop Entry]
258 Name=LightDM custom Greeter ${filename}
259 Comment=LightDM Greeter
260 Exec=${path}
261 Type=Application
262 EOF
263 }
264
265 # greeter-listコマンド
266 command_lightdm_greeter_list() {
267     echo "Available Lightdm greeter list:"
268     local _greeter
269     for _greeter in "${LIGHTDM_GREETERS[@]}"; do
270         if [[ "${_greeter}" = "${LIGHTDM_CURRENT_GREETER}" ]]; then
271             echo " * ${_greeter}"
272         else
273             echo "   ${_greeter}"
274         fi
275     done
276 }
277
278 # greeterコマンド
279 run_greeter_wizard(){
280     # グリーターの数を確認
281     if (( ${#LIGHTDM_GREETERS[@]} < 1 )); then
282         msg_error "LightDM Greeter was not found."
283         exit 1
284     fi
285
286     # 質問する
287     local _c _greeter
288     echo "Please select the greeter to use."
289     for (( _c=1; _c<=${#LIGHTDM_GREETERS[@]}; _c++)); do
290         _greeter="${LIGHTDM_GREETERS[$(( _c - 1 ))]}"
291         if [[ "${_greeter}" = "${LIGHTDM_CURRENT_GREETER}" ]]; then
292             echo " * ${_c}: ${_greeter}"
293         else
294             echo "   ${_c}: ${_greeter}"
295         fi
296         unset _greeter
297     done
298     echo -n "(1 ~ ${#LIGHTDM_GREETERS[@]}) > "
299     read -r _input
300
301     local _recall
302     _recall(){
303         echo "Please enter the correct value."
304         run_greeter_wizard
305         exit 0
306     }
307
308     # 回答を解析
309     if check_int "${_input}"; then
310         # 数字が入力された
311         if (( 1 <= _input)) && (( _input <= ${#LIGHTDM_GREETERS[@]} )); then
312             _greeter="${LIGHTDM_GREETERS[$(( _input - 1 ))]}"
313         else
314             _recall
315         fi
316     else
317         # 文字が入力された
318         if printf "%s\n" "${LIGHTDM_GREETERS[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
319             _greeter="${_input}"
320         else
321             _recall
322         fi
323     fi
324
325     # 結果に応じて処理を実行
326     if [[ -n "${_greeter}" ]]; then
327         command_lightdm_greeter_change "${_greeter}"
328     else
329         run_greeter_wizard
330         exit 0
331     fi
332     echo "Changed greeter to ${_greeter}"
333 }
334
335 # removeコマンド
336 command_lightdm_remove(){
337     if [[ ! -f "${LIGHTDM_CONFIG}" ]]; then
338         return 0
339     else
340         local _yes_or_no
341         echo -ne "Are you sure you want to delete all settings?\nThis change is irreversible.\n (y or n) > "
342         read -r -n 1 _yes_or_no
343         if [[ "${_yes_or_no}" = "y" ]]; then
344             mv "${LIGHTDM_CONFIG}" "${LIGHTDM_CONFIG}.disabled"
345         fi
346     fi
347 }
348
349 # greeter-edit
350 command_lightdm_greeter_edit(){
351     if [[ "${NON_INTERACTIVE}" = true ]]; then
352         msg_error "You cannot use this command in non-interactive mode."
353         exit 1
354     fi
355     local _greeter="${1:-${LIGHTDM_CURRENT_GREETER}}"
356     if [[ -z "${GREETER_CONFIG["${_greeter}"]+SET}" ]]; then
357         msg_error "This Greeter is not currently supported."
358         msg_error "Please report the problem here."
359         msg_error "https://github.com/FascodeNet/lightdm-config/issues"
360         exit 1
361     else
362         if [[ -z ${1} ]]; then
363             msg_warn "Greeter was not specified. Open the currently configured Greeter configuration file."
364             echo -n "(Enter to continue) > "
365             read -r
366         fi
367         set -u
368         bash -c "${USE_EDITOR} ${GREETER_CONFIG["${_greeter}"]}"
369         exit
370     fi
371 }
372
373 # edit
374 command_lightdm_edit(){
375     if [[ "${NON_INTERACTIVE}" = true ]]; then
376         msg_error "You cannot use this command in non-interactive mode."
377         exit 1
378     fi
379     for _config in "${LIGHTDM_LOADED_CONFIG[@]}"; do
380         echo -ne "Edit ${_config} ? (y or n)> "
381         read -r -n 1 _yes_or_no
382         echo
383         if [[ "${_yes_or_no}" = "y" ]]; then
384             bash -c "${USE_EDITOR} ${_config}"
385         fi
386     done
387 }
388
389 # autologin
390 command_lightdm_auto_login(){
391     if [[ -z "${1+SET}" ]]; then
392         # 既に自動ログインが設定されているかを確認
393         local autologin_user="$(lightdm_get_value autologin-user)"
394         if [[ -n "${autologin_user}" ]]; then
395             # autologinを無効化
396             for _autologin in "autologin-guest" "autologin-user" "autologin-user-timeout" "autologin-in-background" "autologin-session"; do
397                 remove_key "${_autologin}"
398             done
399             echo "Canceled automatic login of ${autologin_user}"
400         fi
401     else
402         local autologin_user="${1}" autologin_session
403         if [[ -v 2 ]]; then
404             autologin_session="${2}"
405         fi
406
407         # ユーザーチェック
408         if ! getent passwd "${autologin_user}" 1> /dev/null 2>&1; then
409             echo "${autologin_user} is a non-existent user."
410             exit 1
411         fi
412
413         # セッションを設定
414         if [[ -z "${autologin_session+SET}" ]]; then
415             if (( $(ls "/usr/share/xsessions" 2> /dev/null | wc -l) <= 1 )); then
416                 autologin_session="$(ls "/usr/share/xsessions" | sed 's|.desktop$||g')"
417             elif [[ "${NON_INTERACTIVE}" = true ]]; then
418                 # 非対話モード
419                 # ~/.dmrcの値を設定します
420                 autologin_session="$(cat "${HOME}/.dmrc" | grep -E '^Session=' | cut -d '=' -f 2)"
421                 if [[ -z "${autologin_session}" ]]; then
422                     msg_error "Failed to set the session."
423                     msg_error "Not specified and ~/.dmrc does not exist either."
424                     exit 1
425                 fi
426             else
427                 echo "Select the desktop session to autologin"
428                 local session
429                 for session in "/usr/share/xsessions/"*; do
430                     echo "   ${session}"
431                 done
432                 echo -n "(session name) > "
433                 read -r session
434                 if [[ -f "/usr/share/xsessions/${session}.desktop" ]]; then
435                     autologin_session="${session}"
436                 else
437                     msg_error "Please enter the correct session name."
438                     exit 1
439                 fi
440             fi
441         else
442             # 既に値が設定済み
443             if [[ ! -f "/usr/share/xsessions/${autologin_session}.desktop" ]]; then
444                 # 存在しないセッションが指定された場合
445                 msg_error "This is a session (${autologin_session}) that does not exist."
446                 exit 1
447             fi
448         fi
449
450         # autologin グループを設定
451         if ! getent group "autologin" 1> /dev/null 2>&1; then
452             LANG=C groupadd -r "autologin"
453         fi
454         LANG=C gpasswd -a "${autologin_user}" "autologin"
455
456         # 設定を書き込み
457         lightdm_set_config "autologin-guest" "false"
458         lightdm_set_config "autologin-user" "${autologin_user}"
459         lightdm_set_config "autologin-user-timeout" "0"
460         lightdm_set_config "autologin-in-background" "false"
461         lightdm_set_config "autologin-session" "${autologin_session}"
462
463         echo "${autologin_user} will automatically log in with ${autologin_session}"
464     fi
465
466 }
467
468 # show-config
469 command_lightdm_show_config(){
470    lightdm --show-config 2>&1 
471 }
472
473 #== GDM用の汎用関数 ==#
474 gdm_init_configs(){
475     check_root
476     if [[ ! -f "/etc/dconf/profile/gdm" ]]; then
477         mkdir -p "/etc/dconf/profile"
478         touch "/etc/dconf/profile/gdm"
479         echo -e "user-db:user\nsystem-db:gdm\nfile-db:/usr/share/gdm/greeter-dconf-defaults" > "/etc/dconf/profile/gdm"
480     fi
481
482     local _file
483     for _file in "${DISPLAY_MANAGER_CONFIG["gdm-dconf"]}" "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}"; do
484         if [[ ! -f "${_file}" ]]; then
485             mkdir -p "$(dirname "${_file}")"
486             touch "${_file}"
487         fi
488     done
489 }
490
491 # gdm_dconf_set_config <dconf path> <key> <value>
492 gdm_dconf_set_config(){
493     if check_int "${3}" || check_bool "${3}"; then
494         crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-dconf"]}" "${1}" "${2}" "${3}"
495     else
496         crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-dconf"]}" "${1}" "${2}" "\"${3}\""
497     fi
498     gdm_update
499 }
500
501 # gdm_dconf_get_value <dconf path> <key>
502 gdm_dconf_get_value(){
503     dconf dump / | crudini --get - "${1}" "${2}"
504 }
505
506 # gdm_custom_get_value <section> <key>
507 gdm_custom_get_value(){
508     crudini --get "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}" "${1}" "${2}"
509 }
510
511 # gdm_custom_set_config <section> <key> <value>
512 gdm_custom_set_config(){
513     if check_int "${3}" || check_bool "${3}"; then
514         crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}" "${1}" "${2}" "${3}"
515     else
516         crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}" "${1}" "${2}" "\"${3}\""
517     fi
518     gdm_update
519 }
520
521 gdm_update(){
522     dconf update
523 }
524
525
526 #== GDM用コマンド ==#
527 command_gdm_logo(){
528     if [[ -z "${1+SET}" ]]; then
529         msg_error "Please specify the image of background"
530         exit 1
531     fi
532     if [[ ! -f "${1}" ]]; then
533         msg_error "${1} was not found."
534         exit 1
535     fi
536
537     local _backgrounf_file="/usr/share/backgrounds/gdm/background"
538     mkdir -p "$(dirname "${_backgrounf_file}")"
539     cp "${1}" "${_backgrounf_file}"
540     chmod 644 "${_backgrounf_file}"
541     
542     gdm_dconf_set_config "org/gnome/login-screen" "logo" "${_backgrounf_file}"
543 }
544
545 command_gdm_cursor_wizard(){
546     # 一覧を生成
547     local _c
548     unset _cursor_theme
549     echo "Please select the cursor theme to use."
550     for (( _c=1; _c<=${#CURSOR_THEMES[@]}; _c++)); do
551         _cursor_theme="${CURSOR_THEMES[$(( _c - 1 ))]}"
552         echo "   ${_c}: ${_cursor_theme}"
553         unset _cursor_theme
554     done
555
556     # 質問する
557     local _input
558     echo -n "(1 ~ ${#CURSOR_THEMES[@]}) > "
559     read -r _input
560
561     local _recall
562     _recall(){
563         echo "Please enter the correct value."
564         command_gdm_cursor_wizard
565         exit 0
566     }
567
568     # 回答を解析
569     if check_int "${_input}"; then
570         # 数字が入力された
571         if (( 1 <= _input)) && (( _input <= ${#CURSOR_THEMES[@]} )); then
572             _cursor_theme="${CURSOR_THEMES[$(( _input - 1 ))]}"
573         else
574             _recall
575         fi
576     else
577         # 文字が入力された
578         if printf "%s\n" "${CURSOR_THEMES[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
579             _cursor_theme="${_input}"
580         else
581             _recall
582         fi
583     fi
584
585     if [[ -n "${_cursor_theme}" ]]; then
586         command_gdm_cursor_change "${_cursor_theme}"
587     else
588         command_gdm_cursor_wizard
589         exit 0
590     fi
591     echo "Changed cursor to ${_cursor_theme}"
592 }
593
594 command_gdm_cursor_change(){
595     if [[ -z "${1+SET}" ]]; then
596         msg_error "Please specify the cursor theme"
597         exit 1
598     fi
599     if ! printf "%s\n" "${CURSOR_THEMES[@]}" | grep -x "${1}" 1>/dev/null 2>&1; then
600         msg_error "The cursor theme (${1}) was not found"
601         exit 1
602     fi
603     gdm_dconf_set_config "org/gnome/desktop/interface" "cursor-theme" "${1}"
604 }
605
606 command_gdm_sound(){
607     local _arg="$(echo "${1-""}" | tr A-Z a-z)"
608     if ! check_bool "${_arg}"; then
609         msg_error "Please specify true or false"
610         script_usage
611         exit 1
612     fi
613     gdm_dconf_set_config "org/gnome/desktop/sound" "event-sounds" "${_arg}"
614 }
615
616 command_gdm_tap(){
617     local _arg="$(echo "${1-""}" | tr A-Z a-z)"
618     if ! check_bool "${_arg}"; then
619         msg_error "Please specify true or false"
620         script_usage
621         exit 1
622     fi
623     gdm_dconf_set_config "org/gnome/desktop/peripherals/touchpad" "tap-to-click" "${_arg}"
624 }
625
626 # autologin
627 command_gdm_auto_login(){
628     if [[ -z "${1+SET}" ]]; then
629         # 既に自動ログインが設定されているかを確認
630         local autologin="$(gdm_custom_get_value daemon AutomaticLoginEnable)"
631         if [[ "${autologin}" = "True" ]]; then
632             gdm_custom_set_config "daemon" "AutomaticLoginEnable" "False"
633             echo "Canceled automatic login of $(gdm_custom_get_value "daemon" "AutomaticLogin")"
634         fi
635     else
636         local autologin_user="${1}" autologin_session
637         if [[ -v 2 ]]; then
638             autologin_session="${2}"
639         fi
640
641         # ユーザーチェック
642         if ! getent passwd "${autologin_user}" 1> /dev/null 2>&1; then
643             echo "${autologin_user} is a non-existent user."
644             exit 1
645         fi
646
647         # セッションを設定 (WayLandのセッションは現在サポートされていません)
648         if [[ -z "${autologin_session+SET}" ]]; then
649             if (( $(ls "/usr/share/xsessions" 2> /dev/null | wc -l) <= 1 )); then
650                 autologin_session="$(ls "/usr/share/xsessions" | sed 's|.desktop$||g')"
651             elif [[ "${NON_INTERACTIVE}" = true ]]; then
652                 # 非対話モード
653                 # ~/.dmrcの値を設定します
654                 autologin_session="$(cat "${HOME}/.dmrc" | grep -E '^Session=' | cut -d '=' -f 2)"
655                 if [[ -z "${autologin_session}" ]]; then
656                     msg_error "Failed to set the session."
657                     msg_error "Not specified and ~/.dmrc does not exist either."
658                     exit 1
659                 fi
660             else
661                 echo "Select the desktop session to autologin"
662                 local session
663                 for session in "/usr/share/xsessions/"*; do
664                     echo "   $(basename ${session} | sed "s|.desktop$||g")"
665                 done
666                 echo -n "(session name) > "
667                 read -r session
668                 if [[ -f "/usr/share/xsessions/${session}.desktop" ]]; then
669                     autologin_session="${session}"
670                 else
671                     msg_error "Please enter the correct session name."
672                     exit 1
673                 fi
674             fi
675         else
676             # 既に値が設定済み
677             if [[ ! -f "/usr/share/xsessions/${autologin_session}.desktop" ]]; then
678                 # 存在しないセッションが指定された場合
679                 msg_error "This is a session (${autologin_session}) that does not exist."
680                 exit 1
681             fi
682         fi
683
684         # autologin グループを設定
685         if ! getent group "autologin" 1> /dev/null 2>&1; then
686             LANG=C groupadd -r "autologin"
687         fi
688         LANG=C gpasswd -a "${autologin_user}" "autologin"
689
690         # 設定を書き込み
691         gdm_custom_set_config "daemon" "AutomaticLoginEnable" "True"
692         gdm_custom_set_config "daemon" "AutomaticLogin" "${autologin_user}"
693         
694         # セッションを指定
695         crudini --set "/var/lib/AccountsService/users/${autologin_user}" "User" "Session" "${autologin_session}"
696         crudini --set "/var/lib/AccountsService/users/${autologin_user}" "User" "XSession" "${autologin_session}"
697
698         echo "${autologin_user} will automatically log in with ${autologin_session}"
699     fi
700
701 }
702
703 # accessibility コマンド
704 command_gdm_accessibility(){
705     local _arg="$(echo "${1-""}" | tr A-Z a-z)"
706     if ! check_bool "${_arg}"; then
707         msg_error "Please specify true or false"
708         script_usage
709         exit 1
710     fi
711     gdm_dconf_set_config "org/gnome/desktop/interface" "toolkit-accessibility" "${_arg}"
712 }
713
714 # root-login コマンド
715 command_gdm_root_login(){
716     local _arg="$(echo "${1-""}" | tr A-Z a-z)"
717     if ! check_bool "${_arg}"; then
718         msg_error "Please specify true or false"
719         script_usage
720         exit 1
721     fi
722     gdm_custom_set_config "daemon" "AllowRoot" "${_arg}"
723 }
724
725 #== Webkit2用の汎用関数 ==#
726 webkit2_init_configs(){
727     check_root
728     if [[ ! -f "${GREETER_CONFIG["lightdm-webkit2-greeter"]}" ]]; then
729         mkdir -p "$(dirname "${GREETER_CONFIG["lightdm-webkit2-greeter"]}")"
730         touch "${GREETER_CONFIG["lightdm-webkit2-greeter"]}"
731     fi
732 }
733
734 # webkit2_get_value <section> <key>
735 webkit2_get_value(){
736     crudini --get "${GREETER_CONFIG["lightdm-webkit2-greeter"]}" "${1}" "${2}"
737 }
738
739 # webkit2_set_config <section> <key> <value>
740 webkit2_set_config(){
741     crudini --set "${GREETER_CONFIG["lightdm-webkit2-greeter"]}" "${1}" "${2}" "${3}"
742 }
743
744 #== webkit2用コマンド ==#
745 command_webkit2_theme_wizard(){
746     local _theme_list=($(ls /usr/share/lightdm-webkit/themes))
747     local _current_theme=$(webkit2_get_value greeter webkit_theme | sed "s|\"||g")
748     local _theme _c
749     echo "Please select the theme to use."
750     for (( _c=1; _c<=${#_theme_list[@]}; _c++)); do
751         _theme="${_theme_list[$(( _c - 1 ))]}"
752         if [[ "${_theme}" = "${_current_theme}" ]]; then
753             echo " * ${_c}: ${_theme}"
754         else
755             echo "   ${_c}: ${_theme}"
756         fi
757         unset _theme
758     done
759
760     # 質問する
761     local _input
762     echo -n "(1 ~ ${#_theme_list[@]}) > "
763     read -r _input
764
765     # shellcheck disable=SC2034
766     local _recall
767     _recall(){
768         echo "Please enter the correct value."
769         command_webkit2_theme_wizard
770         exit 0
771     }
772
773     # 回答を解析
774     if check_int "${_input}"; then
775         # 数字が入力された
776         if (( 1 <= _input)) && (( _input <= ${#_theme_list[@]} )); then
777             _theme="${_theme_list[$(( _input - 1 ))]}"
778         else
779             _recall
780         fi
781     else
782         # 文字が入力された
783         if printf "%s\n" "${_theme_list[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
784             _theme="${_input}"
785         else
786             _recall
787         fi
788     fi
789
790     if [[ -n "${_theme}" ]]; then
791         command_webkit2_theme_change "${_theme}"
792         echo "Changed the theme to ${_theme}"
793     else
794         command_webkit2_theme_wizard
795         exit 0
796     fi
797     
798 }
799
800 command_webkit2_theme_change(){
801     if [[ -z "${1+SET}" ]]; then
802         msg_error "Please specify the theme name"
803         exit 1
804     fi
805     if [[ ! -d "/usr/share/lightdm-webkit/themes/${1}" ]]; then
806         msg_error "The specified theme (${1}) does not exist"
807         exit 1
808     fi
809
810     webkit2_set_config "greeter" "webkit_theme" "${1}"
811 }
812
813 #== Qtquick用の汎用関数 ==#
814 qtquick_init_configs(){
815     check_root
816     if [[ ! -f "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" ]] || [[ -z "$(cat "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")" ]]; then
817         mkdir -p "$(dirname "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")"
818         touch "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
819         #echo -e "{\n\n}\n" > "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
820         qtquick_set_config background_path "file:///hoge/fuga.png"
821         qtquick_set_config theme "qrc:/Login.qml"
822     fi
823 }
824
825 #qtquick_get_value <key>
826 qtquick_get_value(){
827     cat "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" | jq ".${1}"
828 }
829
830 # command_qtquick_back <key> <value>
831 qtquick_set_config(){
832     local _tempfile="/tmp/$(basename "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")-$(cat /dev/urandom | base64 | fold -w 10 | head -n 1)"
833     cp "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" "${_tempfile}"
834     cat "${_tempfile}" | jq -r ".${1}|=\"${2}\"" > "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
835     chmod 644 "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
836 }
837
838 #== Qtquick用コマンド ==#
839 command_qtquick_back(){
840     if [[ -z "${1+SET}" ]]; then
841         msg_error "Please specify the image of background"
842         exit 1
843     fi
844     if [[ ! -f "${1}" ]]; then
845         msg_error "${1} was not found."
846         exit 1
847     fi
848
849     local _backgrounf_file="/usr/share/backgrounds/lightdm/qtquick-greeter"
850     mkdir -p "$(dirname "${_backgrounf_file}")"
851     cp "${1}" "${_backgrounf_file}"
852     chmod 644 "${_backgrounf_file}"
853     
854     qtquick_set_config "background_path" "file://${_backgrounf_file}"
855 }
856
857
858 # 変数を設定
859 declare -A GREETER_CONFIG=(
860     ["lightdm-webkit2-greeter"]="/etc/lightdm/lightdm-webkit2-greeter.conf"
861     ["lightdm-slick-greeter"]="/etc/lightdm/slick-greeter.conf"
862     ["lightdm-gtk-greeter"]="/etc/lightdm/lightdm-gtk-greeter.conf"
863     ["io.elementary.greeter"]="/etc/lightdm/io.elementary.greeter.conf"
864     ["lightdm-mini-greeter"]="/etc/lightdm/lightdm-mini-greeter.conf"
865     ["lightdm-qtquick-greeter"]="/etc/lightdm/lightdm-qtquick-greeter.json"
866 )
867
868 declare -A DISPLAY_MANAGER_CONFIG=(
869     ["lightdm"]="/etc/lightdm/lightdm.conf.d/00-dmc-lightdm.conf"
870     ["gdm-dconf"]="/etc/dconf/db/gdm.d/00-dmc-gdm"
871     ["gdm-custom"]="/etc/gdm/custom.conf"
872 )
873
874
875 #== CONFIGS ==#
876
877 # LightDM - 設定ファイル
878 LIGHTDM_CONFIG="${DISPLAY_MANAGER_CONFIG["lightdm"]}"
879
880 # LightDM - Greeterのディレクトリ
881 LIGHTDM_GREETERS_DIR="$(lightdm_get_value "greeters-directory")"
882 : "${LIGHTDM_GREETERS_DIR:="/usr/share/xgreeters"}"
883
884 # LightDM - Greeter一覧
885 LIGHTDM_GREETERS=( $( (ls "${LIGHTDM_GREETERS_DIR}" | sed "s|.desktop$||g") 2> /dev/null ))
886
887 # LightDM - 現在設定されているGreeter
888 LIGHTDM_CURRENT_GREETER="$(lightdm --show-config 2>&1 | grep "greeter-session" | cut -d "=" -f 2)"
889 : "${LIGHTDM_CURRENT_GREETER:="lightdm-gtk-greeter"}"
890
891 # LightDM - 読み込まれた設定ファイルの一覧
892 LIGHTDM_LOADED_CONFIG=()
893 while read -r line; do
894     LIGHTDM_LOADED_CONFIG+=("${line}")
895 done < <(printf "%s\n" $(lightdm --show-config 2>&1 | grep -x -A "$(lightdm --show-config 2>&1 | wc -l)" "Sources:" | grep -v "Sources") | sed -E "s|^[A-Z]$||g" | tr -d " ")
896
897 # Global
898 CURSOR_THEMES=($(get_cursor_theme))
899 USE_EDITOR="${EDITOR:-vi}"
900 DISPLAY_MANAGER="lightdm"
901
902 # dmc config
903 NON_INTERACTIVE=false
904 WRITE_ALL_FILES=false
905 NOROOT=false
906
907
908 #== 引数解析 ==#
909 ARGUMENT="${*}"
910 OPTS="m:e:h"
911 OPTL="mode:,editor:,help,non-interactive,noroot,write-all-files"
912 if ! OPT="$(getopt -o ${OPTS} -l ${OPTL} -- ${ARGUMENT})"; then
913     exit 1
914 fi
915
916 eval set -- "${OPT}"
917 unset OPT OPTS OPTL
918
919 while true; do
920     case "${1}" in
921         -m | --mode)
922             DISPLAY_MANAGER="${2}"
923             shift 2
924             ;;
925         -e | --editor)
926             USE_EDITOR="${2}"
927             shift 2
928             ;;
929         -h | --help)
930             script_usage
931             exit 0
932             ;;
933         --non-interactive)
934             NON_INTERACTIVE=true
935             shift 1
936             ;;
937         --noroot)
938             NOROOT=true
939             shift 1
940             ;;
941         --write-all-files)
942             WRITE_ALL_FILES=true
943             shift 1
944             ;;
945         --)
946             shift 1
947             break
948             ;;
949     esac
950 done
951
952 COMMAND="${1:-null}"
953 if (( "${#}" >= 1 )); then
954     shift 1
955 fi
956 COMMAND_ARGS="${*}"
957 : ${COMMAND_ARGS-""} # サブコマンドの引数が何も指定されなかった場合に空文字を代入
958
959 if [[ "${COMMAND}" = "null" ]]; then
960     script_usage
961     exit 1
962 fi
963
964 case "${DISPLAY_MANAGER}" in
965     "lightdm")
966         case "${COMMAND}" in
967             "autologin")
968                 lightdm_init_configs
969                 command_lightdm_auto_login ${COMMAND_ARGS}
970                 ;;
971             "greeter")
972                 lightdm_init_configs
973                 run_greeter_wizard
974                 ;;
975             "greeter-change")
976                 lightdm_init_configs
977                 command_lightdm_greeter_change ${COMMAND_ARGS}
978                 ;;
979             "greeter-create")
980                 lightdm_init_configs
981                 command_lightdm_greeter_create ${COMMAND_ARGS}
982                 ;;
983             "greeter-list")
984                 command_lightdm_greeter_list
985                 ;;
986             "greeter-edit")
987                 check_root
988                 command_lightdm_greeter_edit ${COMMAND_ARGS}
989                 ;;
990             "remove")
991                 check_root
992                 command_lightdm_remove
993                 ;;
994             "edit")
995                 check_root
996                 command_lightdm_edit
997                 ;;
998             "show-config")
999                 command_lightdm_show_config
1000                 ;;
1001             *)
1002                 msg_error "Undefined commnad(${COMMAND})"
1003                 ;;
1004         esac
1005         ;;
1006     "gdm")
1007         case "${COMMAND}" in
1008             "autologin")
1009                 gdm_init_configs
1010                 command_gdm_auto_login ${COMMAND_ARGS}
1011                 ;;
1012             "cursor")
1013                 gdm_init_configs
1014                 command_gdm_cursor_wizard
1015                 ;;
1016             "sound")
1017                 gdm_init_configs
1018                 command_gdm_sound ${COMMAND_ARGS}
1019                 ;;
1020             "logo")
1021                 gdm_init_configs
1022                 command_gdm_logo ${COMMAND_ARGS}
1023                 ;;
1024             "tap")
1025                 gdm_init_configs
1026                 command_gdm_tap ${COMMAND_ARGS}
1027                 ;;
1028             "accessibility")
1029                 gdm_init_configs
1030                 command_gdm_accessibility ${COMMAND_ARGS}
1031                 ;;
1032             "root-login")
1033                 gdm_init_configs
1034                 command_gdm_root_login ${COMMAND_ARGS}
1035                 ;;
1036             *)
1037                 msg_error "Undefined commnad(${COMMAND})"
1038                 ;;
1039         esac
1040         ;;
1041     "webkit2")
1042         case "${COMMAND}" in
1043             "theme")
1044                 webkit2_init_configs
1045                 command_webkit2_theme_wizard
1046                 ;;
1047             "theme-change")
1048                 webkit2_init_configs
1049                 command_webkit2_theme_change ${COMMAND_ARGS}
1050                 ;;
1051             *)
1052                 msg_error "Undefined commnad(${COMMAND})"
1053                 ;;
1054         esac
1055         ;;
1056     "qtquick")
1057         case "${COMMAND}" in
1058             "back")
1059                 qtquick_init_configs
1060                 command_qtquick_back ${COMMAND_ARGS}
1061                 ;;
1062         esac
1063         ;;
1064     *)
1065         msg_error "A display manager that is not currently supported."
1066         exit 1
1067         ;;
1068 esac
1069 exit 0