diff --git a/WebminCore.pm b/WebminCore.pm index e5a2f2a21..9968848c9 100644 --- a/WebminCore.pm +++ b/WebminCore.pm @@ -23,7 +23,7 @@ $main::export_to_caller = 1; # Add functions in web-lib-funcs.pl # Generated with : # grep -h "^sub " web-lib-funcs.pl ui-lib.pl | sed -e 's/sub //' | xargs echo -@EXPORT = qw(read_file read_file_cached read_file_cached_with_stat write_file html_escape html_unescape html_strip quote_escape quote_literal_escape quote_javascript default_webmin_temp_dir tempname_dir tempname_dir_sys tempname transname transname_timestamped trunc indexof indexoflc sysprint check_ipaddress check_ip6address is_non_public_ipaddress generate_icon urlize un_urlize include copydata ReadParseMime ReadParse read_fully read_parse_mime_callback read_parse_mime_javascript PrintHeader header get_html_title get_html_framed_title get_html_status_line popup_header footer popup_footer load_module_preferences load_theme_library redirect kill_byname kill_byname_logged find_byname error error_stderr popup_error register_error_handler call_error_handlers error_setup wait_for fast_wait_for has_command make_date make_date_relative file_chooser_button popup_window_button popup_window_link read_acl acl_filename acl_check get_miniserv_config_file get_miniserv_config put_miniserv_config restart_miniserv reload_miniserv check_os_support http_download complete_http_download http_post ftp_download ftp_upload no_proxy open_socket download_timeout ftp_command to_ipaddress to_ip6address to_hostname icons_table replace_meta replace_file_line read_file_lines flush_file_lines unflush_file_lines unix_user_input unix_group_input hlink user_chooser_button group_chooser_button foreign_check foreign_exists foreign_available foreign_require foreign_call foreign_config foreign_installed foreign_defined get_system_hostname get_webmin_version get_webmin_version_release get_webmin_full_version get_module_acl get_group_module_acl save_module_acl save_group_module_acl init_config load_language_auto load_language text_subs text encode_base64 decode_base64 encode_base32 decode_base32 get_module_info get_all_module_infos list_themes get_theme_info list_locales list_languages safe_language read_env_file write_env_file lock_file unlock_file test_lock unlock_all_files can_lock_file webmin_log additional_log var_dump webmin_debug_log system_logged backquote_logged backquote_with_timeout backquote_command kill_logged rename_logged rename_file symlink_logged symlink_file link_file make_dir make_dir_recursive set_ownership_permissions unlink_logged unlink_file copy_permissions_source_dest copy_source_dest move_source_dest remote_session_name verify_session_id remote_foreign_require remote_foreign_call remote_foreign_check remote_foreign_config remote_eval remote_write remote_read remote_finished remote_error_setup remote_rpc_call remote_multi_callback remote_multi_callback_error serialise_variable unserialise_variable other_groups date_chooser_button help_file read_help_file seed_random disk_usage_kb recursive_disk_usage help_search_link can_use_http_ssl make_http_connection validate_ssl_connection read_http_connection write_http_connection close_http_connection read_http_headers get_http_auth_reason clean_environment reset_environment clean_language progress_callback switch_to_remote_user switch_to_unix_user eval_as_unix_user create_user_config_dirs create_missing_homedir filter_javascript resolve_links simplify_path same_file flush_webmin_caches list_usermods available_usermods get_available_module_infos get_visible_module_infos get_visible_modules_categories is_under_directory parse_http_url check_clicks_function load_entities_map entities_to_ascii get_product_name get_charset get_display_hostname save_module_config save_user_module_config nice_size get_perl_path get_goto_module select_all_link select_invert_link select_rows_link check_pid_file get_mod_lib module_root_directory list_mime_types guess_mime_type open_tempfile close_tempfile print_tempfile is_selinux_enabled get_clear_file_attributes reset_file_attributes cleanup_tempnames open_lock_tempfile END month_to_number number_to_month supports_ipv6 execute_command execute_command_logged open_readfile open_execute_command translate_filename translate_command register_filename_callback register_command_callback capture_function_output capture_function_output_tempfile modules_chooser_button substitute_template substitute_pattern running_in_zone running_in_vserver running_in_xen running_in_openvz list_categories is_readonly_mode command_as_user list_osdn_mirrors convert_osdn_url get_current_dir supports_users supports_symlinks quote_path get_windows_root read_file_contents write_file_contents read_file_contents_limit unix_crypt split_quoted_string write_to_http_cache check_in_http_cache clear_http_cache supports_javascript get_module_name get_module_variable clear_time_locale reset_time_locale callers_package web_libs_package get_userdb_string connect_userdb disconnect_userdb split_userdb_string uniquelc list_combined_webmin_menu list_modules_webmin_menu module_to_menu_item list_combined_system_info shell_is_bash compare_version_numbers convert_to_json convert_from_json print_json get_referer_relative get_webmin_email_url get_webmin_browser_url trim ui_link ui_help ui_img ui_link_button ui_table_start ui_table_end ui_table_row ui_table_hr ui_table_span ui_columns_start ui_columns_row ui_columns_header ui_checked_columns_row ui_radio_columns_row ui_columns_end ui_columns_table ui_form_columns_table ui_form_elements_wrapper ui_form_start ui_form_end ui_form_end_side_by_side ui_textbox ui_filebox ui_bytesbox ui_upload ui_password ui_hidden ui_select ui_multi_select ui_multi_select_javascript ui_radio ui_yesno_radio ui_radio_row ui_checkbox ui_oneradio ui_textarea ui_user_textbox ui_users_textbox ui_group_textbox ui_groups_textbox ui_opt_textbox ui_submit ui_reset ui_button ui_date_input ui_buttons_start ui_buttons_end ui_buttons_row ui_buttons_hr ui_post_header ui_pre_footer ui_print_header ui_print_unbuffered_header ui_print_footer ui_config_link ui_print_endpage ui_subheading ui_links_row ui_hidden_javascript ui_hidden_start ui_hidden_end ui_hidden_table_row_start ui_hidden_table_row_end ui_hidden_table_start ui_hidden_table_end ui_tabs_start ui_tabs_end ui_tabs_start_tab ui_tabs_start_tabletab ui_tabs_end_tab ui_tabs_end_tabletab ui_max_text_width ui_radio_selector ui_radio_selector_javascript ui_switch_theme_javascript ui_grid_table ui_radio_table ui_up_down_arrows ui_hr ui_nav_link ui_confirmation_form ui_text_color ui_alert_box js_disable_inputs ui_page_flipper js_checkbox_disable js_redirect ui_webmin_link ui_line_break_double ui_page_refresh ui_details ui_div_row ui_space ui_newline ui_text_wrap ui_element_inline ui_paginations ui_hide_outside_of_viewport ui_read_file_contents_limit ui_note ui_brh ui_tag_start ui_tag_content ui_tag_end ui_tag ui_alert ui_button_icon ui_link_icon ui_icon ui_br ui_p ui_div ui_text_mask get_python_cmd get_buffer_size get_buffer_size_binary get_webprefix get_sub_ref_name setvar getvar delvar print_call_stack webmin_user_can_rpc webmin_user_login_mode webmin_user_is_admin webmin_user_is get_current_theme_info_cached miniserv_using_default_cert is_int float is_float parse_accepted_language get_default_system_locale get_http_redirect get_http_cookie create_wrapper get_lock_links_dir allocate_miniserv_websocket get_miniserv_websocket_url remove_miniserv_websocket cleanup_miniserv_websockets get_miniserv_websockets_modules get_webmin_base_url encrypt_phrase decrypt_phrase is_encrypt_phrase); +@EXPORT = qw(read_file read_file_cached read_file_cached_with_stat write_file html_escape html_unescape html_strip quote_escape quote_literal_escape quote_javascript default_webmin_temp_dir tempname_dir tempname_dir_sys tempname transname transname_timestamped trunc indexof indexoflc sysprint check_ipaddress check_ip6address is_non_public_ipaddress generate_icon urlize un_urlize include copydata ReadParseMime ReadParse read_fully read_parse_mime_callback read_parse_mime_javascript PrintHeader header get_html_title get_html_framed_title get_html_status_line popup_header footer popup_footer load_module_preferences load_theme_library redirect kill_byname kill_byname_logged find_byname error error_stderr popup_error register_error_handler call_error_handlers error_setup wait_for fast_wait_for has_command make_date make_date_relative file_chooser_button popup_window_button popup_window_link read_acl acl_filename acl_check get_miniserv_config_file get_miniserv_config put_miniserv_config restart_miniserv reload_miniserv check_os_support http_download complete_http_download http_post ftp_download ftp_upload no_proxy open_socket download_timeout ftp_command to_ipaddress to_ip6address to_hostname icons_table replace_meta replace_file_line read_file_lines flush_file_lines unflush_file_lines unix_user_input unix_group_input hlink user_chooser_button group_chooser_button foreign_check foreign_exists foreign_available foreign_require foreign_call foreign_config foreign_installed foreign_defined get_system_hostname get_webmin_version get_webmin_version_release get_webmin_full_version get_module_acl get_group_module_acl save_module_acl save_group_module_acl init_config load_language_auto load_language text_subs text encode_base64 decode_base64 encode_base32 decode_base32 get_module_info get_all_module_infos list_themes get_theme_info list_locales list_languages safe_language read_env_file write_env_file lock_file unlock_file test_lock unlock_all_files can_lock_file webmin_log additional_log var_dump webmin_debug_log system_logged backquote_logged backquote_with_timeout backquote_command kill_logged rename_logged rename_file symlink_logged symlink_file link_file make_dir make_dir_recursive set_ownership_permissions unlink_logged unlink_file copy_permissions_source_dest copy_source_dest move_source_dest remote_session_name verify_session_id remote_foreign_require remote_foreign_call remote_foreign_check remote_foreign_config remote_eval remote_write remote_read remote_finished remote_error_setup remote_rpc_call remote_multi_callback remote_multi_callback_error serialise_variable unserialise_variable other_groups date_chooser_button help_file read_help_file seed_random disk_usage_kb recursive_disk_usage help_search_link can_use_http_ssl make_http_connection validate_ssl_connection read_http_connection write_http_connection close_http_connection read_http_headers get_http_auth_reason clean_environment reset_environment clean_language progress_callback switch_to_remote_user switch_to_unix_user eval_as_unix_user create_user_config_dirs create_missing_homedir filter_javascript resolve_links simplify_path same_file flush_webmin_caches list_usermods available_usermods get_available_module_infos get_visible_module_infos get_visible_modules_categories is_under_directory parse_http_url check_clicks_function load_entities_map entities_to_ascii get_product_name get_charset get_display_hostname save_module_config save_user_module_config nice_size get_perl_path get_goto_module select_all_link select_invert_link select_rows_link check_pid_file get_mod_lib module_root_directory list_mime_types guess_mime_type open_tempfile close_tempfile print_tempfile is_selinux_enabled get_clear_file_attributes reset_file_attributes cleanup_tempnames open_lock_tempfile END month_to_number number_to_month supports_ipv6 execute_command execute_command_logged open_readfile open_execute_command translate_filename translate_command register_filename_callback register_command_callback capture_function_output capture_function_output_tempfile modules_chooser_button substitute_template substitute_pattern running_in_zone running_in_vserver running_in_xen running_in_openvz list_categories is_readonly_mode command_as_user list_osdn_mirrors convert_osdn_url get_current_dir supports_users supports_symlinks quote_path get_windows_root read_file_contents write_file_contents read_file_contents_limit unix_crypt split_quoted_string write_to_http_cache check_in_http_cache clear_http_cache supports_javascript get_module_name get_module_variable clear_time_locale reset_time_locale callers_package web_libs_package get_userdb_string connect_userdb disconnect_userdb split_userdb_string uniquelc list_combined_webmin_menu list_modules_webmin_menu module_to_menu_item list_combined_system_info shell_is_bash compare_version_numbers convert_to_json convert_from_json print_json get_referer_relative get_webmin_email_url get_webmin_browser_url trim ui_link ui_help ui_img ui_link_button ui_table_start ui_table_end ui_table_row ui_table_hr ui_table_span ui_columns_start ui_columns_row ui_columns_header ui_checked_columns_row ui_radio_columns_row ui_columns_end ui_columns_table ui_form_columns_table ui_form_elements_wrapper ui_form_start ui_form_end ui_form_end_side_by_side ui_form_grouped_buttons ui_textbox ui_filebox ui_bytesbox ui_upload ui_password ui_hidden ui_select ui_multi_select ui_multi_select_javascript ui_radio ui_yesno_radio ui_radio_row ui_checkbox ui_oneradio ui_textarea ui_user_textbox ui_users_textbox ui_group_textbox ui_groups_textbox ui_opt_textbox ui_submit ui_reset ui_button ui_date_input ui_buttons_start ui_buttons_end ui_buttons_row ui_buttons_hr ui_post_header ui_pre_footer ui_print_header ui_print_unbuffered_header ui_print_footer ui_config_link ui_print_endpage ui_subheading ui_links_row ui_hidden_javascript ui_hidden_start ui_hidden_end ui_hidden_table_row_start ui_hidden_table_row_end ui_hidden_table_start ui_hidden_table_end ui_tabs_start ui_tabs_end ui_tabs_start_tab ui_tabs_start_tabletab ui_tabs_end_tab ui_tabs_end_tabletab ui_max_text_width ui_radio_selector ui_radio_selector_javascript ui_switch_theme_javascript ui_grid_table ui_radio_table ui_up_down_arrows ui_hr ui_nav_link ui_confirmation_form ui_text_color ui_alert_box js_disable_inputs ui_page_flipper js_checkbox_disable js_redirect ui_webmin_link ui_line_break_double ui_page_refresh ui_details ui_div_row ui_space ui_newline ui_text_wrap ui_element_inline ui_paginations ui_hide_outside_of_viewport ui_read_file_contents_limit ui_note ui_brh ui_tag_start ui_tag_content ui_tag_end ui_tag ui_alert ui_button_icon ui_link_icon ui_icon ui_br ui_p ui_div ui_text_mask get_python_cmd get_buffer_size get_buffer_size_binary get_webprefix get_sub_ref_name setvar getvar delvar print_call_stack webmin_user_can_rpc webmin_user_login_mode webmin_user_is_admin webmin_user_is get_current_theme_info_cached miniserv_using_default_cert is_int float is_float parse_accepted_language get_default_system_locale get_http_redirect get_http_cookie create_wrapper get_lock_links_dir allocate_miniserv_websocket get_miniserv_websocket_url remove_miniserv_websocket cleanup_miniserv_websockets get_miniserv_websockets_modules get_webmin_base_url encrypt_phrase decrypt_phrase is_encrypt_phrase); # Add global variables in web-lib.pl push(@EXPORT, qw(&unique)); diff --git a/bind8/conf_zonedef.cgi b/bind8/conf_zonedef.cgi index a17937b63..7b00c673a 100755 --- a/bind8/conf_zonedef.cgi +++ b/bind8/conf_zonedef.cgi @@ -92,7 +92,7 @@ if (&supports_dnssec()) { # Default algorithm print &ui_table_row($text{'zonedef_alg'}, - &ui_select("alg", $config{'tmpl_dnssecalg'} || "RSASHA1", + &ui_select("alg", $config{'tmpl_dnssecalg'} || "RSASHA256", [ &list_dnssec_algorithms() ]), 3); # Default size diff --git a/gray-theme/unauthenticated/gray-theme.css b/gray-theme/unauthenticated/gray-theme.css index abd48242c..91c2f2604 100644 --- a/gray-theme/unauthenticated/gray-theme.css +++ b/gray-theme/unauthenticated/gray-theme.css @@ -1,4 +1,10 @@ @font-face{font-family:FramedTheme;src:url(data:application/font-woff2;charset=utf-8;base64,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) format('woff2');font-weight:400;font-style:normal}.ff{display:inline-block;font:normal normal normal 14px/1 FramedTheme;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ff-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.ff-2x{font-size:2em}.ff-3x{font-size:3em}.ff-4x{font-size:4em}.ff-5x{font-size:5em}.ff-fw{width:1.28571429em;text-align:center}.ff-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.ff-ul>li{position:relative}.ff-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.ff-li.ff-lg{left:-1.85714286em}.ff-webmin:before{content:'\f000'}.ff-virtualmin:before{content:'\f001'}.ff-virtualmin-tick:before{content:'\f002'}.ff-cloudmin:before{content:'\f003'}.ff-sign-out:before{content:'\f008'}.ff-refresh:before{content:'\f009'}.ff-home:before{content:'\f00b'}.ff-chart:before{content:'\f00c'}.ff-exclamation-triangle:before{content:'\f00d'}.ff-play-circle:before{content:'\f00e'}.ff-mail:before{content:'\f00f'}.ff-address-book:before{content:'\f010'}.ff-signature:before{content:'\f011'}.ff-lock:before{content:'\f012'}.ff-folder-open:before{content:'\f013'}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} +:root { + --text-color-danger: #bc0303; + --text-color-success: #3c763d; + --text-color-warning: #b58900; + --text-color-info: #108eda; +} body {margin: 8px; color: #212121; line-height:1.5em; text-align:left;} p { margin-top:4px; } table { border-width: 0px; @@ -920,16 +926,16 @@ body > .mode > b[data-mode="server-manager"] > a > .ff-cloudmin { min-width: 15px !important; } .text-danger { - color: #bc0303; + color: var(--text-color-danger); } .text-success { - color: #3c763d; + color: var(--text-color-success); } .text-warning { - color: #b58900; + color: var(--text-color-warning); } .text-info { - color: #108eda; + color: var(--text-color-info); } /* Utility used by forms that need fields to consume the available row width. */ .w-100 { diff --git a/mailboxes/boxes-lib.pl b/mailboxes/boxes-lib.pl index ac413b75e..5e5b8447e 100755 --- a/mailboxes/boxes-lib.pl +++ b/mailboxes/boxes-lib.pl @@ -2087,10 +2087,20 @@ foreach $f (@files) { $i++; next; } + local $idx = $i++; local $mail = &read_mail_file($f, $_[3]); - $mail->{'idx'} = $i++; - $mail->{'id'} = $f; # ID is relative path, like cur/4535534 - $mail->{'id'} = substr($mail->{'id'}, length($_[0])+1); + if (!$mail && !$_[4]) { + # The cached Maildir file list can be stale if another client + # deleted or moved a message. Re-read it once before returning + # blank entries to the caller. + &flush_maildir_cachefile($_[0]); + return &list_maildir($_[0], $_[1], $_[2], $_[3], 1); + } + if ($mail) { + $mail->{'idx'} = $idx; + $mail->{'id'} = $f; # ID is relative path, like cur/4535534 + $mail->{'id'} = substr($mail->{'id'}, length($_[0])+1); + } push(@rv, $mail); } return @rv; @@ -2110,9 +2120,11 @@ return map { substr($_, length($file)+1) } &get_maildir_files($file); sub select_maildir { local ($file, $ids, $headersonly) = @_; +local $retried = $_[3]; &mark_read_maildir($file); local @files = &get_maildir_files($file); local @rv; +local $missing; foreach my $i (@$ids) { local $path = "$file/$i"; local $mail = &read_mail_file($path, $headersonly); @@ -2139,8 +2151,15 @@ foreach my $i (@$ids) { # Get index in directory $mail->{'idx'} = &indexof($path, @files); } + else { + $missing = 1; + } push(@rv, $mail); } +if ($missing && !$retried) { + &flush_maildir_cachefile($file); + return &select_maildir($file, $ids, $headersonly, 1); + } return @rv; } @@ -2167,7 +2186,7 @@ else { # Check the on-disk cache file local $cachefile = &get_maildir_cachefile($_[0]); local @cst = $cachefile ? stat($cachefile) : ( ); - if ($cst[9] >= $newest) { + if ($cst[9] > $newest) { # Can read the cache open(CACHE, "<", $cachefile); while() { @@ -2188,6 +2207,32 @@ else { # Flagged as deleted by IMAP .. skip next; } + # Skip entries that cannot be read as messages. + local $path = "$_[0]/$d/$f"; + local @fst = stat($path); + if (!@fst) { + &error_stderr("Skipping Maildir file ". + "$path : stat failed : ". + "$!"); + next; + } + if (!$fst[7]) { + &error_stderr("Skipping Maildir file ". + "$path : file is zero ". + "bytes"); + next; + } + if (!-r _) { + my $m = sprintf("%04o",$fst[2] & 07777); + my $o = getpwuid($fst[4]) || $fst[4]; + my $g = getgrgid($fst[5]) || $fst[5]; + &error_stderr("Skipping Maildir file ". + "$path : not readable by". + " current user, owner=". + "$o($fst[4]):$g($fst[5])". + " mode=$m"); + next; + } push(@shorts, "$d/$f") } closedir(DIR); @@ -2661,11 +2706,13 @@ sub read_mail_file my ($file, $headersonly) = @_; # Open and read the mail file +local @st = stat($file); +return undef if (@st && !$st[7]); &open_as_mail_user(MAIL, $file) || return undef; my $mail = &read_mail_fh(MAIL, 0, $headersonly); -$mail->{'file'} = $file; close(MAIL); -local @st = stat($file); + +$mail->{'file'} = $file; $mail->{'size'} = $st[7]; $mail->{'time'} = $st[9]; $mail->{'ctime'} = $st[10]; diff --git a/mailboxes/folders-lib.pl b/mailboxes/folders-lib.pl index a699ce1fa..0e35e2b6e 100755 --- a/mailboxes/folders-lib.pl +++ b/mailboxes/folders-lib.pl @@ -174,6 +174,7 @@ elsif ($_[2]->{'type'} == 4) { local $count = $rv[2]; return () if (!$count); $_[2]->{'lastchange'} = $rv[3] if ($rv[3]); + $_[2]->{'mailcount'} = $count; # Work out what range we want local ($start, $end) = &compute_start_end($_[0], $_[1], $count); @@ -458,6 +459,7 @@ elsif ($folder->{'type'} == 4) { } local $h = $irv[1]; local $count = $irv[2]; + $folder->{'mailcount'} = $count; return () if (!$count); $folder->{'lastchange'} = $irv[3] if ($irv[3]); @@ -637,8 +639,9 @@ elsif ($folder->{'type'} == 4) { } local $h = $rv[1]; local $count = $rv[2]; + $folder->{'mailcount'} = $count; return () if (!$count); - $folder->{'lastchange'} = $irv[3] if ($irv[3]); + $folder->{'lastchange'} = $rv[3] if ($rv[3]); @rv = &imap_command($h, "FETCH 1:$count UID"); foreach my $uid (@{$rv[1]}) { @@ -708,6 +711,8 @@ else { sub mailbox_list_mails_sorted { local ($start, $end, $folder, $headersonly, $error, $field, $dir) = @_; +local ($requested_start, $requested_end) = ($start, $end); +local $retried = $_[7]; print DEBUG "mailbox_list_mails_sorted from $start to $end\n"; if (!$field) { # Default to current ordering @@ -738,11 +743,25 @@ local @rv = map { undef } (0 .. scalar(@sorter)-1); local @wantids = map { $sorter[$_] } ($start .. $end); print DEBUG "wantids = ",scalar(@wantids),"\n"; local @mails = &mailbox_select_mails($folder, \@wantids, $headersonly); +local @missing; for(my $i=0; $i<@mails; $i++) { + if (!$mails[$i]) { + push(@missing, $wantids[$i]); + next; + } $rv[$start+$i] = $mails[$i]; print DEBUG "setting $start+$i to ",$mails[$i]," id ",$wantids[$i],"\n"; $mails[$i]->{'sortidx'} = $start+$i; } +if (@missing && !$retried) { + # A sorted IMAP list can contain UIDs for messages that were + # expunged or moved by another client. Force one rebuild so stale + # entries don't render as blank 1969/no-subject rows. + &force_new_index_recheck($folder); + return &mailbox_list_mails_sorted($requested_start, $requested_end, + $folder, $headersonly, $error, + $field, $dir, 1); + } print DEBUG "rv = ",scalar(@rv),"\n"; return @rv; } @@ -808,7 +827,9 @@ local $ifile = &folder_new_sort_index_file($folder); &open_dbm_db($index, $ifile, 0600); print DEBUG "indexchange=$index->{'lastchange'} folderchange=$folder->{'lastchange'}\n"; if ($index->{'lastchange'} != $folder->{'lastchange'} || - !$folder->{'lastchange'}) { + !$folder->{'lastchange'} || + (defined($folder->{'mailcount'}) && + $index->{'mailcount'} != $folder->{'mailcount'})) { # The mail file has changed .. get IDs and update the index with any # that are missing local @ids = &mailbox_idlist($folder); @@ -823,6 +844,7 @@ if ($index->{'lastchange'} != $folder->{'lastchange'} || local @mails = scalar(@newids) ? &mailbox_select_mails($folder, \@newids, 1) : ( ); foreach my $mail (@mails) { + next if (!$mail || !defined($mail->{'id'})); foreach my $f (@index_fields) { if ($f eq "date") { # Convert date to Unix time diff --git a/mailboxes/mailboxes-lib.pl b/mailboxes/mailboxes-lib.pl index 98cebc09b..8a1f2389e 100755 --- a/mailboxes/mailboxes-lib.pl +++ b/mailboxes/mailboxes-lib.pl @@ -1209,6 +1209,7 @@ print &ui_columns_start(\@hcols, 100, 0, \@tds); # Show rows for actual mail messages my $i = 0; foreach my $mail (@mail) { + next if (!$mail); local $idx = $mail->{'idx'}; local $cols = 0; local @cols; diff --git a/net/net-detect.pl b/net/net-detect.pl new file mode 100644 index 000000000..c87ded6d6 --- /dev/null +++ b/net/net-detect.pl @@ -0,0 +1,32 @@ +# net-detect.pl +# Helper functions for choosing the network config backend + +sub net_has_network_manager_config +{ +my ($dir) = @_; +$dir ||= "/etc/NetworkManager/system-connections"; +my @files = glob("$dir/*.nmconnection"); +return -d $dir && scalar(@files); +} + +sub net_has_netplan_config +{ +my ($dir) = @_; +$dir ||= "/etc/netplan"; +return &has_command("netplan") && + -d $dir; +} + +sub net_auto_backend +{ +my ($os_type, $netplan_dir, $nm_conn_dir) = @_; +return "netplan" + if ($os_type eq "debian-linux" && + &net_has_netplan_config($netplan_dir)); +return "nm" + if (($os_type eq "redhat-linux" || $os_type eq "debian-linux") && + &net_has_network_manager_config($nm_conn_dir)); +return undef; +} + +1; diff --git a/net/net-lib.pl b/net/net-lib.pl index 9023a2d3d..318dcfd4d 100755 --- a/net/net-lib.pl +++ b/net/net-lib.pl @@ -6,6 +6,9 @@ use WebminCore; &init_config(); %access = &get_module_acl(); $access{'ipnodes'} = $access{'hosts'}; +do "net-detect.pl"; + +$auto_net_mode = &net_auto_backend($gconfig{'os_type'}); if (-r "$module_root_directory/$gconfig{'os_type'}-$gconfig{'os_version'}-lib.pl") { do "$gconfig{'os_type'}-$gconfig{'os_version'}-lib.pl"; @@ -23,20 +26,16 @@ elsif ($gconfig{'os_type'} eq 'slackware-linux' && do "$gconfig{'os_type'}-9.1-ALL-lib.pl"; $net_mode = $gconfig{'os_type'}."/9.1"; } -elsif ($gconfig{'os_type'} eq 'redhat-linux' && - -d "/etc/NetworkManager/system-connections" && - glob("/etc/NetworkManager/system-connections/*.nmconnection")) { - # Special case for systems with network manager - do 'nm-lib.pl'; - $net_mode = "nm"; - } -elsif ($gconfig{'os_type'} eq 'debian-linux' && - &has_command("netplan") && - -d "/etc/netplan") { +elsif ($auto_net_mode eq "netplan") { # Special case for newer Ubuntu versions do "netplan-lib.pl"; $net_mode = "netplan"; } +elsif ($auto_net_mode eq "nm") { + # Special case for systems with network manager + do 'nm-lib.pl'; + $net_mode = "nm"; + } else { do "$gconfig{'os_type'}-lib.pl"; $net_mode = $gconfig{'os_type'}; diff --git a/net/nm-lib.pl b/net/nm-lib.pl index 7120a789e..5a0624a12 100644 --- a/net/nm-lib.pl +++ b/net/nm-lib.pl @@ -231,7 +231,7 @@ my $method6 = $iface->{'auto6'} ? "auto" : # Update nameservers my @ns = $iface->{'nameserver'} ? @{$iface->{'nameserver'}} : (); my @ns4 = grep { &check_ipaddress($_) } @ns; -my @ns6 = grep { &check_ip6address($ns6) } @ns; +my @ns6 = grep { &check_ip6address($_) } @ns; &save_nm_config($cfg, "ipv4", "dns", @ns4 ? join(" ", @ns4) : undef) if (@ns4); &save_nm_config($cfg, "ipv6", "dns", @ns6 ? join(" ", @ns6) : undef) if (@ns6); my @sr = $iface->{'search'} ? @{$iface->{'search'}} : (); diff --git a/net/t/run-tests.t b/net/t/run-tests.t index 8012538ac..21f936e3e 100644 --- a/net/t/run-tests.t +++ b/net/t/run-tests.t @@ -4,6 +4,7 @@ use warnings; use Test::More; use Cwd qw(abs_path); use File::Basename qw(dirname); +use File::Path qw(make_path); use File::Temp qw(tempdir); my $root = abs_path(dirname(__FILE__)."/../..") or die "rootdir: $!"; @@ -58,6 +59,7 @@ close($fh) || die "close $file: $!"; sub lock_file { return 1; } sub unlock_file { return 1; } sub error { die join("", @_), "\n"; } +sub unflush_file_lines { delete($file_cache{$_[0]}); } sub has_command { return $_[0] eq "netplan" ? "/usr/sbin/netplan" : undef; } sub execute_command_logged { @@ -68,6 +70,13 @@ $$stdout = $out if (ref($stdout)); $$stderr = $out if (ref($stderr) && $stderr ne $stdout); return $command_status{$cmd} || 0; } +sub backquote_logged +{ +my ($cmd) = @_; +push(@commands, $cmd); +$? = $command_status{$cmd} || 0; +return $command_output{$cmd} || ""; +} sub check_ipaddress { return $_[0] =~ /^\d+\.\d+\.\d+\.\d+$/; } sub check_ip6address { return $_[0] =~ /:/; } sub check_ipaddress_any { return &check_ipaddress($_[0]) || &check_ip6address($_[0]); } @@ -83,6 +92,29 @@ return -1; } unshift(@INC, "$root/net", $root); +do "$root/net/net-detect.pl" || die "net-detect.pl: $@ $!"; + +my $detect_root = tempdir(CLEANUP => 1); +my $detect_netplan = "$detect_root/netplan"; +my $detect_no_netplan = "$detect_root/no-netplan"; +my $detect_nm = "$detect_root/NetworkManager/system-connections"; +my $detect_nm_empty = "$detect_root/NetworkManager-empty/system-connections"; +make_path($detect_netplan, $detect_nm, $detect_nm_empty); +write_text("$detect_nm/eth0.nmconnection", ""); + +is(main::net_auto_backend("debian-linux", $detect_netplan, $detect_nm_empty), + "netplan", "Debian uses Netplan when the config directory exists"); +is(main::net_auto_backend("debian-linux", $detect_no_netplan, $detect_nm), + "nm", "Debian uses NetworkManager when only nmconnection files exist"); +is(main::net_auto_backend("redhat-linux", $detect_no_netplan, $detect_nm), + "nm", "Red Hat still uses NetworkManager when nmconnection files exist"); +write_text("$detect_netplan/50-cloud-init.yaml", ""); +is(main::net_auto_backend("debian-linux", $detect_netplan, $detect_nm), + "netplan", "Debian prefers Netplan over NetworkManager when YAML exists"); +unlink("$detect_netplan/50-cloud-init.yaml"); +is(main::net_auto_backend("debian-linux", $detect_no_netplan, $detect_nm_empty), + undef, "Debian falls back when no Netplan or NetworkManager config exists"); + do "$root/net/netplan-lib.pl" || die "netplan-lib.pl: $@ $!"; { @@ -167,4 +199,37 @@ is_deeply(\@commands, "(cd / && /usr/sbin/netplan apply)" ], "apply_network validates before applying"); +do "$root/net/nm-lib.pl" || die "nm-lib.pl: $@ $!"; +my $nmfile = "$tmp/eth0.nmconnection"; +write_text($nmfile, <<'NM'); +[connection] +id=eth0 +uuid=11111111-2222-3333-4444-555555555555 +type=ethernet +interface-name=eth0 + +[ipv4] +method=auto + +[ipv6] +method=disabled +NM +my $nmcfg = main::read_nm_config($nmfile); +my $nmiface = { + 'name' => 'eth0', + 'fullname' => 'eth0', + 'file' => $nmfile, + 'cfg' => $nmcfg, + 'edit' => 1, + 'up' => 1, + 'dhcp' => 1, + 'address6' => [ ], + 'netmask6' => [ ], + 'nameserver' => [ "2001:4860:4860::8888" ], + }; +@commands = ( ); +main::save_interface($nmiface, [ $nmiface ]); +like(join("\n", @commands), qr/ipv6\.dns/, + "NetworkManager save_interface writes IPv6 nameservers"); + done_testing(); diff --git a/phpini/phpini-lib.pl b/phpini/phpini-lib.pl index a81dffdf1..ebd7d8276 100755 --- a/phpini/phpini-lib.pl +++ b/phpini/phpini-lib.pl @@ -468,6 +468,14 @@ elsif ($file =~ /\/(php-fpm)\.conf/) { return $init; } } +# Generic /etc/php.ini config shared by EL PHP-FPM packages +elsif ($file eq "/etc/php.ini") { + my $init = "php-fpm"; + my $st = &init::action_status($init); + if ($st) { + return $init; + } + } return undef; } diff --git a/proc/proc-lib.pl b/proc/proc-lib.pl index 14be79216..f339c7585 100755 --- a/proc/proc-lib.pl +++ b/proc/proc-lib.pl @@ -249,11 +249,11 @@ do { local $oldexit = $?; } while($xp > 0); } -# pty_process_exec(command, [uid, gid], [force-binary-name]) +# pty_process_exec(command, [uid, gid], [force-binary-name], [skip-stty]) # Starts the given command in a new pty and returns the pty filehandle and PID sub pty_process_exec { -local ($cmd, $uid, $gid, $binary) = @_; +local ($cmd, $uid, $gid, $binary, $skip_stty) = @_; if (&is_readonly_mode()) { # When in readonly mode, don't run the command $cmd = "/bin/true"; @@ -262,6 +262,13 @@ if (&is_readonly_mode()) { if ($gconfig{'debug_what_cmd'}); my ($ptyfh, $ttyfh, $pty, $tty, $TIOCSCTTY); +my $set_pty_raw_noecho = sub { + my ($ttyfh) = @_; + eval "use IO::Stty"; + if (!$@) { + IO::Stty::stty($ttyfh, 'raw', '-echo'); + } + }; eval "use IO::Pty"; if (!$@) { @@ -281,10 +288,7 @@ if (!$@) { $ptyfh->make_slave_controlling_terminal(); # Turn off echoing, if we can - eval "use IO::Stty"; - if (!$@) { - IO::Stty::stty($ttyfh, 'raw', '-echo'); - } + $set_pty_raw_noecho->($ttyfh) if (!$skip_stty); close(STDIN); close(STDOUT); close(STDERR); untie(*STDIN); untie(*STDOUT); untie(*STDERR); @@ -342,10 +346,7 @@ elsif (defined &linux_openpty && }; # Turn off echoing, if we can - eval "use IO::Stty"; - if (!$@) { - IO::Stty::stty($ttyfh, 'raw', '-echo'); - } + $set_pty_raw_noecho->($ttyfh) if (!$skip_stty); close(STDIN); close(STDOUT); close(STDERR); untie(*STDIN); untie(*STDOUT); untie(*STDERR); @@ -397,10 +398,7 @@ else { } # Turn off echoing, if we can - eval "use IO::Stty"; - if (!$@) { - IO::Stty::stty($ttyfh, 'raw', '-echo'); - } + $set_pty_raw_noecho->($ttyfh) if (!$skip_stty); if (defined(&open_controlling_pty)) { &open_controlling_pty($ptyfh, $ttyfh, $pty, $tty); diff --git a/setup.pl b/setup.pl index 6cebaa4e8..274f14840 100755 --- a/setup.pl +++ b/setup.pl @@ -494,7 +494,7 @@ else { $cert = &tempname(); $key = &tempname(); $addtextsup = &get_openssl_version() >= 1.1 ? "-addext subjectAltName=DNS:$host,DNS:localhost -addext extendedKeyUsage=serverAuth" : ""; - open(SSL, "| openssl req -newkey rsa:2048 -x509 -nodes -out $cert -keyout $key -days 1825 -sha256 -subj '/CN=$host/C=US/L=Santa Clara' $addtextsup >/dev/null 2>&1"); + open(SSL, "| openssl req -newkey rsa:4096 -x509 -nodes -out $cert -keyout $key -days 1825 -sha256 -subj '/CN=$host/C=US/L=Santa Clara' $addtextsup >/dev/null 2>&1"); print SSL ".\n"; print SSL ".\n"; print SSL ".\n"; diff --git a/setup.sh b/setup.sh index 2aa919d88..fb4f18b72 100755 --- a/setup.sh +++ b/setup.sh @@ -607,7 +607,7 @@ else addtextsup="" fi # We can generate a new SSL key for this host - openssl req -newkey rsa:2048 -x509 -nodes -out $tempdir/cert -keyout $tempdir/key -days 1825 -sha256 -subj "/CN=$host/C=US/L=Santa Clara" $addtextsup >/dev/null 2>&1 </dev/null 2>&1 <= 6.5) { return "ed25519"; } if ($version{'type'} eq 'openssh' && $version{'number'} >= 3.2) { - return "rsa1"; + return "rsa"; } return undef; } diff --git a/sshd/useradmin_update.pl b/sshd/useradmin_update.pl index fc0fa96e6..4b3660f9d 100755 --- a/sshd/useradmin_update.pl +++ b/sshd/useradmin_update.pl @@ -11,12 +11,13 @@ if ($config{'sync_create'} && &has_command($config{'keygen_path'}) && local $cmd; local $type = $config{'sync_type'} || &get_preferred_key_type(); local $tflag = $type ? "-t $type" : ""; + local $bflag = $type eq "rsa" ? "-b 4096" : ""; if ($config{'sync_pass'} && $uinfo->{'passmode'} == 3) { - $cmd = "$config{'keygen_path'} $tflag -P ". + $cmd = "$config{'keygen_path'} $tflag $bflag -P ". quotemeta($uinfo->{'plainpass'}); } else { - $cmd = "$config{'keygen_path'} $tflag -P \"\""; + $cmd = "$config{'keygen_path'} $tflag $bflag -P \"\""; } &system_logged("echo '' | ".&command_as_user($uinfo->{'user'}, 0, $cmd). " >/dev/null 2>&1"); diff --git a/status/status-lib.pl b/status/status-lib.pl index f0455648a..6a11ef597 100755 --- a/status/status-lib.pl +++ b/status/status-lib.pl @@ -493,7 +493,10 @@ return ( { 'id' => 'tmobile', 'domain' => 't.vodafone.ne.jp' }, { 'id' => 'bellcanada', 'desc' => 'Bell Canada', - 'domain' => 'txt.bellmobility.ca' }, + 'domain' => 'txt.bell.ca' }, + { 'id' => 'luckymobile', + 'desc' => 'Lucky Mobile', + 'domain' => 'txt.bell.ca' }, { 'id' => 'bellsouth', 'desc' => 'Bell South', 'domain' => 'sms.bellsouth.com' }, diff --git a/ui-lib.pl b/ui-lib.pl index e556f6759..92db4a5e4 100755 --- a/ui-lib.pl +++ b/ui-lib.pl @@ -1,6 +1,7 @@ use vars qw($theme_no_table $ui_radio_selector_donejs $module_name $ui_multi_select_donejs, $ui_formcount, - $ui_form_end_side_by_side_donecss); + $ui_form_end_side_by_side_donecss, + $ui_form_grouped_buttons_donecss); =head1 ui-lib.pl @@ -817,6 +818,48 @@ $rv .= &_ui_form_end_nojs($nojs); return $rv; } +=head2 ui_form_grouped_buttons(&groups, [width]) + +Returns HTML for a responsive row of submit buttons, without closing the form. +Each button uses the same array format as C. + +Pass an array of button groups. A group can be a normal button list, or a list +of button lists when you want a visible gap between sets of buttons. Groups are +spread across the row when there is room, and wrap on narrow screens. Buttons +inside the same list stay visually joined. + +Example : + + my @save_buttons = ([ undef, $text{'save'} ]); + my @control_buttons = ([ 'start', $text{'start'} ], + [ 'stop', $text{'stop'} ]); + my @delete_buttons = ([ 'delete', $text{'delete'} ]); + + print &ui_form_grouped_buttons([ + [ \@save_buttons, \@control_buttons ], + \@delete_buttons, + ]); + +=cut +sub ui_form_grouped_buttons +{ +return &theme_ui_form_grouped_buttons(@_) if (defined(&theme_ui_form_grouped_buttons)); +my ($groups, $width) = @_; +$groups ||= [ ]; +my @groups = grep { $_ && ref($_) eq 'ARRAY' && @$_ } @$groups; +return "" if (!@groups); + +my %attrs = ( 'class' => 'ui_form_grouped_buttons' ); +$attrs{'style'} = "width:$width" if ($width); +my $rv = &_ui_form_grouped_buttons_css(); +$rv .= &ui_tag_start('div', \%attrs); +foreach my $group (@groups) { + $rv .= &_ui_form_grouped_buttons_group($group); + } +$rv .= &ui_tag_end('div'); +return $rv; +} + sub _ui_form_end_buttons_table { my ($buttons, $width, $formid, $class) = @_; @@ -850,6 +893,54 @@ $rv .= "\n"; return $rv; } +sub _ui_form_grouped_buttons_group +{ +my ($group) = @_; +my @clusters = &_ui_form_grouped_buttons_clusters($group); +return "" if (!@clusters); +my $rv = &ui_tag_start('div', { 'class' => 'ui_form_grouped_group' }); +foreach my $cluster (@clusters) { + $rv .= &_ui_form_grouped_buttons_cluster($cluster); + } +$rv .= &ui_tag_end('div'); +return $rv; +} + +sub _ui_form_grouped_buttons_clusters +{ +my ($group) = @_; +return ( ) if (!$group || ref($group) ne 'ARRAY' || !@$group); +foreach my $item (@$group) { + next if (!defined($item)); + return ref($item) eq 'ARRAY' && + (!@$item || ref($item->[0]) eq 'ARRAY') ? + grep { $_ && ref($_) eq 'ARRAY' && @$_ } @$group : + ( $group ); + } +return ( ); +} + +sub _ui_form_grouped_buttons_cluster +{ +my ($buttons) = @_; +return "" if (!$buttons || !@$buttons); +my $rv = &ui_tag_start('span', { 'class' => 'ui_form_grouped_cluster' }); +foreach my $b (@$buttons) { + next if (!defined($b)); + if (ref($b)) { + my $submit = &ui_submit($b->[1], $b->[0], $b->[3], $b->[4]); + chomp($submit); + $rv .= $submit; + $rv .= $b->[2] ? " ".$b->[2] : ""; + } + elsif ($b) { + $rv .= $b; + } + } +$rv .= &ui_tag_end('span'); +return $rv; +} + sub _ui_form_end_side_by_side_css { return "" if ($ui_form_end_side_by_side_donecss++); @@ -876,6 +967,41 @@ return <<'EOF'; EOF } +sub _ui_form_grouped_buttons_css +{ +return "" if ($ui_form_grouped_buttons_donecss++); +my $css = <<'EOF'; +.ui_form_grouped_buttons { + display: flex; + flex-wrap: wrap; + gap: 0.5em 0.45em; + align-items: flex-start; + justify-content: space-between; + width: 100%; +} +.ui_form_grouped_group { + display: flex; + flex-wrap: wrap; + flex: 0 0 auto; + align-items: center; + width: max-content; + max-width: 100%; + margin: 0 -0.45em -0.45em 0; +} +.ui_form_grouped_cluster { + display: flex; + flex-wrap: wrap; + align-items: center; + max-width: 100%; + margin: 0 0.45em 0 0; +} +.ui_form_grouped_cluster .ui_submit { + margin: 0 0 0.45em 0; +} +EOF +return &ui_tag('style', $css, { 'type' => 'text/css' }); +} + sub _ui_form_end_nojs { my ($nojs) = @_; @@ -2719,16 +2845,17 @@ Returns HTML for a text string, with its color determined by $type. sub ui_text_color { my ($text, $type) = @_; -my ($color); +my ($color, $class_type); if (defined (&theme_ui_text_color)) { return &theme_ui_text_color(@_); } -if ($type eq "success") { $color = "#3c763d"; } -elsif ($type eq "info") { $color = "#31708f"; } -elsif ($type eq "warn") { $color = "#8a6d3b"; } -elsif ($type eq "danger") { $color = "#a94442"; } -return "$text"; +$class_type = $type eq "warn" ? "warning" : $type; +if ($type eq "success") { $color = "var(--text-color-success, #3c763d)"; } +elsif ($type eq "info") { $color = "var(--text-color-info, #31708f)"; } +elsif ($type eq "warn") { $color = "var(--text-color-warning, #8a6d3b)"; } +elsif ($type eq "danger") { $color = "var(--text-color-danger, #a94442)"; } +return "$text"; } =head2 ui_alert_box(msg, type) @@ -3934,4 +4061,3 @@ return $rv; } 1; - diff --git a/usermin/change_ssl.cgi b/usermin/change_ssl.cgi index d57b81ef1..9a4b67924 100755 --- a/usermin/change_ssl.cgi +++ b/usermin/change_ssl.cgi @@ -47,7 +47,7 @@ elsif ($in{'cipher_list_def'} == 3) { # Generate file needed for PFS my $out = &backquote_command( "openssl dhparam -out ". - quotemeta($miniserv{'dhparams_file'})." 2048 2>&1"); + quotemeta($miniserv{'dhparams_file'})." 4096 2>&1"); if ($?) { &error(&text('ssl_edhparams', "
".&html_escape($out)."
")); diff --git a/usermin/usermin-lib.pl b/usermin/usermin-lib.pl index d84404266..fc66486dc 100755 --- a/usermin/usermin-lib.pl +++ b/usermin/usermin-lib.pl @@ -41,7 +41,7 @@ $latest_page_url = "$http_proto://$update_host/index6.html"; $latest_rpm = "$http_proto://$update_host/download/usermin-latest.noarch.rpm"; $latest_tgz = "$http_proto://$update_host/download/usermin-latest.tar.gz"; -$default_key_size = 2048; +$default_key_size = 4096; $cron_cmd = "$module_config_directory/update.pl"; diff --git a/webmin/change_ssl.cgi b/webmin/change_ssl.cgi index b3509fb98..16df935df 100755 --- a/webmin/change_ssl.cgi +++ b/webmin/change_ssl.cgi @@ -47,7 +47,7 @@ elsif ($in{'cipher_list_def'} == 3) { # Generate file needed for PFS my $out = &backquote_command( "openssl dhparam -out ". - quotemeta($miniserv{'dhparams_file'})." 2048 2>&1"); + quotemeta($miniserv{'dhparams_file'})." 4096 2>&1"); if ($?) { &error(&text('ssl_edhparams', "
".&html_escape($out)."
")); diff --git a/webmin/letsencrypt-lib.pl b/webmin/letsencrypt-lib.pl index c863744cb..dabf3354e 100755 --- a/webmin/letsencrypt-lib.pl +++ b/webmin/letsencrypt-lib.pl @@ -269,7 +269,7 @@ if ($letsencrypt_cmd) { } } $dir =~ s/\/[^\/]+$//; - $size ||= 2048; + $size ||= 4096; my $out; my $common_flags = " --duplicate". " --force-renewal". diff --git a/webmin/webmin-lib.pl b/webmin/webmin-lib.pl index 86c3c1f64..4f9760d95 100755 --- a/webmin/webmin-lib.pl +++ b/webmin/webmin-lib.pl @@ -64,7 +64,7 @@ our $third_port = $primary_port; our $third_page = "/cgi-bin/third.cgi"; our $third_ssl = $primary_ssl; -our $default_key_size = "2048"; +our $default_key_size = "4096"; our $webmin_yum_repo_file = "/etc/yum.repos.d/webmin.repo"; our $webmin_yum_repo_url = "https://download.webmin.com/download/newkey/yum"; diff --git a/xterm/shellserver.pl b/xterm/shellserver.pl index 1c25dd9d2..513d980ba 100755 --- a/xterm/shellserver.pl +++ b/xterm/shellserver.pl @@ -86,7 +86,8 @@ if ($config{'rcfile'} ne '0') { $shelllogin = undef; } } -my ($shellfh, $pid) = proc::pty_process_exec($shellexec, $uid, $gid, $shelllogin); +my ($shellfh, $pid) = proc::pty_process_exec( + $shellexec, $uid, $gid, $shelllogin, 1); reset_environment(); my $shcmd = "'$shellexec".($shelllogin ? " $shelllogin" : "")."'"; if (!$pid) {