OSDN Git Service

[fix] : Fixed SC2162
[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 "${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 _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     local _recall
766     _recall(){
767         echo "Please enter the correct value."
768         command_webkit2_theme_wizard
769         exit 0
770     }
771
772     # 回答を解析
773     if check_int "${_input}"; then
774         # 数字が入力された
775         if (( 1 <= _input)) && (( _input <= ${#_theme_list[@]} )); then
776             _theme="${_theme_list[$(( _input - 1 ))]}"
777         else
778             _recall
779         fi
780     else
781         # 文字が入力された
782         if printf "%s\n" "${_theme_list[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
783             _theme="${_input}"
784         else
785             _recall
786         fi
787     fi
788
789     if [[ -n "${_theme}" ]]; then
790         command_webkit2_theme_change "${_theme}"
791         echo "Changed the theme to ${_theme}"
792     else
793         command_webkit2_theme_wizard
794         exit 0
795     fi
796     
797 }
798
799 command_webkit2_theme_change(){
800     if [[ -z "${1+SET}" ]]; then
801         msg_error "Please specify the theme name"
802         exit 1
803     fi
804     if [[ ! -d "/usr/share/lightdm-webkit/themes/${1}" ]]; then
805         msg_error "The specified theme (${1}) does not exist"
806         exit 1
807     fi
808
809     webkit2_set_config "greeter" "webkit_theme" "${1}"
810 }
811
812 #== Qtquick用の汎用関数 ==#
813 qtquick_init_configs(){
814     check_root
815     if [[ ! -f "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" ]] || [[ -z "$(cat "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")" ]]; then
816         mkdir -p "$(dirname "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")"
817         touch "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
818         #echo -e "{\n\n}\n" > "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
819         qtquick_set_config background_path "file:///hoge/fuga.png"
820         qtquick_set_config theme "qrc:/Login.qml"
821     fi
822 }
823
824 #qtquick_get_value <key>
825 qtquick_get_value(){
826     cat "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" | jq ".${1}"
827 }
828
829 # command_qtquick_back <key> <value>
830 qtquick_set_config(){
831     local _tempfile="/tmp/$(basename "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")-$(cat /dev/urandom | base64 | fold -w 10 | head -n 1)"
832     cp "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" "${_tempfile}"
833     cat "${_tempfile}" | jq -r ".${1}|=\"${2}\"" > "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
834     chmod 644 "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
835 }
836
837 #== Qtquick用コマンド ==#
838 command_qtquick_back(){
839     if [[ -z "${1+SET}" ]]; then
840         msg_error "Please specify the image of background"
841         exit 1
842     fi
843     if [[ ! -f "${1}" ]]; then
844         msg_error "${1} was not found."
845         exit 1
846     fi
847
848     local _backgrounf_file="/usr/share/backgrounds/lightdm/qtquick-greeter"
849     mkdir -p "$(dirname "${_backgrounf_file}")"
850     cp "${1}" "${_backgrounf_file}"
851     chmod 644 "${_backgrounf_file}"
852     
853     qtquick_set_config "background_path" "file://${_backgrounf_file}"
854 }
855
856
857 # 変数を設定
858 declare -A GREETER_CONFIG=(
859     ["lightdm-webkit2-greeter"]="/etc/lightdm/lightdm-webkit2-greeter.conf"
860     ["lightdm-slick-greeter"]="/etc/lightdm/slick-greeter.conf"
861     ["lightdm-gtk-greeter"]="/etc/lightdm/lightdm-gtk-greeter.conf"
862     ["io.elementary.greeter"]="/etc/lightdm/io.elementary.greeter.conf"
863     ["lightdm-mini-greeter"]="/etc/lightdm/lightdm-mini-greeter.conf"
864     ["lightdm-qtquick-greeter"]="/etc/lightdm/lightdm-qtquick-greeter.json"
865 )
866
867 declare -A DISPLAY_MANAGER_CONFIG=(
868     ["lightdm"]="/etc/lightdm/lightdm.conf.d/00-dmc-lightdm.conf"
869     ["gdm-dconf"]="/etc/dconf/db/gdm.d/00-dmc-gdm"
870     ["gdm-custom"]="/etc/gdm/custom.conf"
871 )
872
873
874 #== CONFIGS ==#
875
876 # LightDM - 設定ファイル
877 LIGHTDM_CONFIG="${DISPLAY_MANAGER_CONFIG["lightdm"]}"
878
879 # LightDM - Greeterのディレクトリ
880 LIGHTDM_GREETERS_DIR="$(lightdm_get_value "greeters-directory")"
881 : "${LIGHTDM_GREETERS_DIR:="/usr/share/xgreeters"}"
882
883 # LightDM - Greeter一覧
884 LIGHTDM_GREETERS=( $( (ls "${LIGHTDM_GREETERS_DIR}" | sed "s|.desktop$||g") 2> /dev/null ))
885
886 # LightDM - 現在設定されているGreeter
887 LIGHTDM_CURRENT_GREETER="$(lightdm --show-config 2>&1 | grep "greeter-session" | cut -d "=" -f 2)"
888 : "${LIGHTDM_CURRENT_GREETER:="lightdm-gtk-greeter"}"
889
890 # LightDM - 読み込まれた設定ファイルの一覧
891 LIGHTDM_LOADED_CONFIG=()
892 while read -r line; do
893     LIGHTDM_LOADED_CONFIG+=("${line}")
894 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 " ")
895
896 # Global
897 CURSOR_THEMES=($(get_cursor_theme))
898 USE_EDITOR="${EDITOR:-vi}"
899 DISPLAY_MANAGER="lightdm"
900
901 # dmc config
902 NON_INTERACTIVE=false
903 WRITE_ALL_FILES=false
904 NOROOT=false
905
906
907 #== 引数解析 ==#
908 ARGUMENT="${@}"
909 OPTS="m:e:h"
910 OPTL="mode:,editor:,help,non-interactive,noroot,write-all-files"
911 if ! OPT="$(getopt -o ${OPTS} -l ${OPTL} -- ${ARGUMENT})"; then
912     exit 1
913 fi
914
915 eval set -- "${OPT}"
916 unset OPT OPTS OPTL
917
918 while true; do
919     case "${1}" in
920         -m | --mode)
921             DISPLAY_MANAGER="${2}"
922             shift 2
923             ;;
924         -e | --editor)
925             USE_EDITOR="${2}"
926             shift 2
927             ;;
928         -h | --help)
929             script_usage
930             exit 0
931             ;;
932         --non-interactive)
933             NON_INTERACTIVE=true
934             shift 1
935             ;;
936         --noroot)
937             NOROOT=true
938             shift 1
939             ;;
940         --write-all-files)
941             WRITE_ALL_FILES=true
942             shift 1
943             ;;
944         --)
945             shift 1
946             break
947             ;;
948     esac
949 done
950
951 COMMAND="${1:-null}"
952 if (( "${#}" >= 1 )); then
953     shift 1
954 fi
955 COMMAND_ARGS="${@}"
956 : ${COMMAND_ARGS-""} # サブコマンドの引数が何も指定されなかった場合に空文字を代入
957
958 if [[ "${COMMAND}" = "null" ]]; then
959     script_usage
960     exit 1
961 fi
962
963 case "${DISPLAY_MANAGER}" in
964     "lightdm")
965         case "${COMMAND}" in
966             "autologin")
967                 lightdm_init_configs
968                 command_lightdm_auto_login ${COMMAND_ARGS}
969                 ;;
970             "greeter")
971                 lightdm_init_configs
972                 run_greeter_wizard
973                 ;;
974             "greeter-change")
975                 lightdm_init_configs
976                 command_lightdm_greeter_change ${COMMAND_ARGS}
977                 ;;
978             "greeter-create")
979                 lightdm_init_configs
980                 command_lightdm_greeter_create ${COMMAND_ARGS}
981                 ;;
982             "greeter-list")
983                 command_lightdm_greeter_list
984                 ;;
985             "greeter-edit")
986                 check_root
987                 command_lightdm_greeter_edit ${COMMAND_ARGS}
988                 ;;
989             "remove")
990                 check_root
991                 command_lightdm_remove
992                 ;;
993             "edit")
994                 check_root
995                 command_lightdm_edit
996                 ;;
997             "show-config")
998                 command_lightdm_show_config
999                 ;;
1000             *)
1001                 msg_error "Undefined commnad(${COMMAND})"
1002                 ;;
1003         esac
1004         ;;
1005     "gdm")
1006         case "${COMMAND}" in
1007             "autologin")
1008                 gdm_init_configs
1009                 command_gdm_auto_login ${COMMAND_ARGS}
1010                 ;;
1011             "cursor")
1012                 gdm_init_configs
1013                 command_gdm_cursor_wizard
1014                 ;;
1015             "sound")
1016                 gdm_init_configs
1017                 command_gdm_sound ${COMMAND_ARGS}
1018                 ;;
1019             "logo")
1020                 gdm_init_configs
1021                 command_gdm_logo ${COMMAND_ARGS}
1022                 ;;
1023             "tap")
1024                 gdm_init_configs
1025                 command_gdm_tap ${COMMAND_ARGS}
1026                 ;;
1027             "accessibility")
1028                 gdm_init_configs
1029                 command_gdm_accessibility ${COMMAND_ARGS}
1030                 ;;
1031             "root-login")
1032                 gdm_init_configs
1033                 command_gdm_root_login ${COMMAND_ARGS}
1034                 ;;
1035             *)
1036                 msg_error "Undefined commnad(${COMMAND})"
1037                 ;;
1038         esac
1039         ;;
1040     "webkit2")
1041         case "${COMMAND}" in
1042             "theme")
1043                 webkit2_init_configs
1044                 command_webkit2_theme_wizard
1045                 ;;
1046             "theme-change")
1047                 webkit2_init_configs
1048                 command_webkit2_theme_change ${COMMAND_ARGS}
1049                 ;;
1050             *)
1051                 msg_error "Undefined commnad(${COMMAND})"
1052                 ;;
1053         esac
1054         ;;
1055     "qtquick")
1056         case "${COMMAND}" in
1057             "back")
1058                 qtquick_init_configs
1059                 command_qtquick_back ${COMMAND_ARGS}
1060                 ;;
1061         esac
1062         ;;
1063     *)
1064         msg_error "A display manager that is not currently supported."
1065         exit 1
1066         ;;
1067 esac
1068 exit 0