summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Blin <oblin@mandriva.org>2005-04-19 16:19:56 +0000
committerOlivier Blin <oblin@mandriva.org>2005-04-19 16:19:56 +0000
commitb7459f3dbbd35b6cc41e04fad99163a4b73151f5 (patch)
treee33aa737e691727110a1d205a6d1e3a7398f451b
parente507ca693ee23532885e30b5c6c5c6c577a17dc0 (diff)
downloaddrakx-b7459f3dbbd35b6cc41e04fad99163a4b73151f5.tar
drakx-b7459f3dbbd35b6cc41e04fad99163a4b73151f5.tar.gz
drakx-b7459f3dbbd35b6cc41e04fad99163a4b73151f5.tar.bz2
drakx-b7459f3dbbd35b6cc41e04fad99163a4b73151f5.tar.xz
drakx-b7459f3dbbd35b6cc41e04fad99163a4b73151f5.zip
move wireless stuff in wireless.pm
-rw-r--r--perl-install/network/netconnect.pm24
-rw-r--r--perl-install/network/network.pm143
-rw-r--r--perl-install/network/tools.pm51
-rw-r--r--perl-install/network/wireless.pm198
4 files changed, 213 insertions, 203 deletions
diff --git a/perl-install/network/netconnect.pm b/perl-install/network/netconnect.pm
index a71423b9c..f5ff46949 100644
--- a/perl-install/network/netconnect.pm
+++ b/perl-install/network/netconnect.pm
@@ -82,7 +82,7 @@ sub real_main {
my $intf = $o_intf ||= {};
my $first_time = $o_first_time || 0;
my ($network_configured, $cnx_type, $type, @all_cards, %eth_intf, %all_eth_intf);
- my (%connections, @connection_list, $is_wireless);
+ my (%connections, @connection_list);
my ($modem, $modem_name, $modem_conf_read, $modem_dyn_dns, $modem_dyn_ip);
my $cable_no_auth;
my ($adsl_type, @adsl_devices, $adsl_failed, $adsl_answer, %adsl_cards, %adsl_data, $adsl_data, $adsl_provider, $adsl_old_provider);
@@ -90,7 +90,7 @@ sub real_main {
my ($isdn, $isdn_name, $isdn_type, %isdn_cards, @isdn_dial_methods);
my $my_isdn = join('', N("Manual choice"), " (", N("Internal ISDN card"), ")");
my ($ndiswrapper_driver, $ndiswrapper_inf_file);
- my $wireless_use_wpa;
+ my ($is_wireless, $wireless_key, $wireless_use_wpa);
my ($module, $auto_ip, $protocol, $onboot, $needhostname, $peerdns, $peeryp, $peerntpd, $hotplug, $track_network_id); # lan config
my $success = 1;
my $ethntf = {};
@@ -1117,9 +1117,13 @@ notation (for example, 1.2.3.4).")),
ndiswrapper =>
{
+ pre => sub {
+ require network::wireless;
+ },
data => sub {
+ my @drv = network::wireless::ndiswrapper_installed_drivers();
[ { label => N("Choose an ndiswrapper driver"), type => "list", val => \$ndiswrapper_driver,
- list => [ N("Install a new driver"), N("Use already installed driver (%s)", join(", ", network::tools::ndiswrapper_installed_drivers())) ] } ];
+ list => [ N("Install a new driver"), if_(@drv, N("Use already installed driver (%s)", join(", ", @drv))) ] } ];
},
complete => sub {
unless ($in->do_pkgs->ensure_is_installed('ndiswrapper', '/usr/sbin/ndiswrapper')) {
@@ -1134,10 +1138,10 @@ notation (for example, 1.2.3.4).")),
}
},
post => sub {
- if (keys %eth_intf ) {
+ if (keys %eth_intf) {
return 'ndiswrapper_intf';
} else {
- $ntf_name = network::tools::ndiswrapper_setup();
+ $ntf_name = network::wireless::ndiswrapper_setup();
$ethntf = $intf->{$ntf_name} ||= { DEVICE => $ntf_name };
return 'lan_protocol';
}
@@ -1157,7 +1161,7 @@ notation (for example, 1.2.3.4).")),
#- if another module is loaded for the wireless interface, unload it before using ndiswrapper
my $eth = find { $_->[0] eq $ntf_name } @all_cards;
$eth and modules::unload($eth->[1]);
- $ntf_name = network::tools::ndiswrapper_setup();
+ $ntf_name = network::wireless::ndiswrapper_setup();
$ethntf = $intf->{$ntf_name} ||= { DEVICE => $ntf_name };
return 'lan_protocol';
},
@@ -1171,6 +1175,7 @@ notation (for example, 1.2.3.4).")),
$ethntf->{WIRELESS_MODE} ||= "Managed";
$ethntf->{WIRELESS_ESSID} ||= "any";
$wireless_use_wpa = exists $ethntf->{WIRELESS_WPA_DRIVER};
+ $wireless_use_wpa or $wireless_key = network::wireless::convert_wep_key_for_iwconfig($intf->{WIRELESS_ENC_KEY});
},
name => N("Please enter the wireless parameters for this card:"),
data => sub {
@@ -1238,11 +1243,12 @@ See iwpriv(8) man page for further information."),
post => sub {
# untranslate parameters
$ethntf->{WIRELESS_MODE} = $wireless_mode{$ethntf->{WIRELESS_MODE}};
- $module =~ /^prism2_/ and network::network::wlan_ng_configure($in, $ethntf, $module);
+ $module =~ /^prism2_/ and network::wireless::wlan_ng_configure($in, $ethntf, $module);
if ($wireless_use_wpa) {
- $ethntf->{WIRELESS_WPA_DRIVER} = network::network::wpa_supplicant_get_driver($module);
- network::network::wpa_supplicant_configure($in, $ethntf);
+ $ethntf->{WIRELESS_WPA_DRIVER} = network::wireless::wpa_supplicant_get_driver($module);
+ network::wireless::wpa_supplicant_configure($in, $ethntf);
} else {
+ $intf->{WIRELESS_ENC_KEY} = network::wireless::get_wep_key_from_iwconfig($wireless_key);
delete $ethntf->{WIRELESS_WPA_DRIVER};
}
return "static_hostname";
diff --git a/perl-install/network/network.pm b/perl-install/network/network.pm
index cfd40b9a5..500bea186 100644
--- a/perl-install/network/network.pm
+++ b/perl-install/network/network.pm
@@ -158,10 +158,6 @@ sub write_interface_conf {
defined($intf->{METRIC}) or $intf->{METRIC} = network::tools::get_default_metric(network::tools::get_interface_type($intf)),
$intf->{BOOTPROTO} =~ s/dhcp.*/dhcp/;
- if (local $intf->{WIRELESS_ENC_KEY} = $intf->{WIRELESS_ENC_KEY}) {
- network::tools::convert_wep_key_for_iwconfig($intf->{WIRELESS_ENC_KEY});
- }
-
setVarsInSh($file, $intf, qw(DEVICE BOOTPROTO IPADDR NETMASK NETWORK BROADCAST ONBOOT HWADDR METRIC MII_NOT_SUPPORTED TYPE USERCTL ATM_ADDR),
qw(WIRELESS_MODE WIRELESS_ESSID WIRELESS_NWID WIRELESS_FREQ WIRELESS_SENS WIRELESS_RATE WIRELESS_ENC_KEY WIRELESS_RTS WIRELESS_FRAG WIRELESS_IWCONFIG WIRELESS_IWSPY WIRELESS_IWPRIV WIRELESS_WPA_DRIVER),
if_($intf->{BOOTPROTO} eq "dhcp", qw(DHCP_CLIENT DHCP_HOSTNAME NEEDHOSTNAME PEERDNS PEERYP PEERNTPD DHCP_TIMEOUT)),
@@ -426,7 +422,6 @@ sub read_all_conf {
my $intf = findIntf($intf, $device);
add2hash($intf, { getVarsFromSh("$::prefix/etc/sysconfig/network-scripts/$_") });
$intf->{DEVICE} ||= $device;
- $intf->{WIRELESS_ENC_KEY} = network::tools::get_wep_key_from_iwconfig($intf->{WIRELESS_ENC_KEY});
}
}
if (my $default_intf = network::tools::get_default_gateway_interface($netc, $intf)) {
@@ -480,144 +475,6 @@ sub easy_dhcp {
1;
}
-#- FIXME: to be improved (quotes, comments) and moved in common files
-sub wlan_ng_update_vars {
- my ($file, $vars) = @_;
- substInFile {
- while (my ($key, $value) = each(%$vars)) {
- s/^#?\Q$key\E=(?:"[^#]*"|[^#\s]*)(\s*#.*)?/$key=$value$1/ and delete $vars->{$key};
- }
- $_ .= join('', map { "$_=$vars->{$_}\n" } keys %$vars) if eof;
- } $file;
-}
-
-sub wlan_ng_configure {
- my ($in, $ethntf, $module) = @_;
- $in->do_pkgs->install('prism2-utils');
- if ($ethntf->{WIRELESS_ESSID}) {
- my $wlan_conf_file = "$::prefix/etc/wlan/wlan.conf";
- my @wlan_devices = split(/ /, (cat_($wlan_conf_file) =~ /^WLAN_DEVICES="(.*)"/m)[0]);
- push @wlan_devices, $ethntf->{DEVICE} unless member($ethntf->{DEVICE}, @wlan_devices);
- #- enable device and make it use the choosen ESSID
- wlan_ng_update_vars($wlan_conf_file,
- {
- WLAN_DEVICES => qq("@wlan_devices"),
- "SSID_$ethntf->{DEVICE}" => qq("$ethntf->{WIRELESS_ESSID}"),
- "ENABLE_$ethntf->{DEVICE}" => "y"
- });
- my $wlan_ssid_file = "$::prefix/etc/wlan/wlancfg-$ethntf->{WIRELESS_ESSID}";
- #- copy default settings for this ESSID if config file does not exist
- -f $wlan_ssid_file or cp_f("$::prefix/etc/wlan/wlancfg-DEFAULT", $wlan_ssid_file);
- #- enable/disable encryption
- wlan_ng_update_vars($wlan_ssid_file,
- {
- (map { $_ => $ethntf->{WIRELESS_ENC_KEY} ? "true" : "false" } qw(lnxreq_hostWEPEncrypt lnxreq_hostWEPDecrypt dot11PrivacyInvoked dot11ExcludeUnencrypted)),
- AuthType => $ethntf->{WIRELESS_ENC_KEY} ? qq("sharedkey") : qq("opensystem"),
- if_($ethntf->{WIRELESS_ENC_KEY},
- dot11WEPDefaultKeyID => 0,
- dot11WEPDefaultKey0 => qq("$ethntf->{WIRELESS_ENC_KEY}")
- )
- });
- #- hide settings for non-root users
- chmod 0600, $wlan_conf_file;
- chmod 0600, $wlan_ssid_file;
- }
- #- apply settings on wlan interface
- require services;
- services::restart($module eq 'prism2_cs' ? 'pcmcia' : 'wlan');
-}
-
-sub wpa_supplicant_get_driver {
- my ($module) = @_;
- $module =~ /^hostap_/ ? "hostap" :
- $module eq "prism54" ? "prism54" :
- $module =~ /^ath_/ ? "madwifi" :
- $module =~ /^at76c50|atmel_/ ? "atmel" :
- $module eq "ndiswrapper" ? "ndiswrapper" :
- $module =~ /^ipw2[12]00$/ ? "ipw" :
- "wext";
-}
-
-sub wpa_supplicant_configure {
- my ($in, $ethntf) = @_;
- require services;
- $in->do_pkgs->install('wpa_supplicant');
-
- wpa_supplicant_add_network({
- ssid => qq("$ethntf->{WIRELESS_ESSID}"),
- psk => network::tools::convert_key_for_wpa_supplicant($ethntf->{WIRELESS_ENC_KEY}),
- scan_ssid => 1,
- });
-}
-
-sub wpa_supplicant_add_network {
- my ($new_network) = @_;
- my $wpa_supplicant_conf = "$::prefix/etc/wpa_supplicant.conf";
- my $s;
- my %network;
- foreach (cat_($wpa_supplicant_conf)) {
- if (%network) {
- #- in a "network = {}" block
- if (/^\s*(\w+)=(.*?)(\s*#.*)?$/) {
- push @{$network{entries}}, { key => $1, value => $2, comment => $3 };
- $1 eq 'ssid' and $network{ssid} = $2;
- } elsif (/^\}/) {
- #- end of network block, write it
- $s .= "network={$network{comment}\n";
- my $update = $network{ssid} eq $new_network->{ssid};
- foreach (@{$network{entries}}) {
- my $key = $_->{key};
- if ($update) {
- #- do not write entry if not provided in the new network
- exists $new_network->{$key} or next;
- #- update value from the new network
- $_->{value} = delete $new_network->{$key};
- }
- if ($key) {
- $s .= " $key=$_->{value}$_->{comment}\n";
- } else {
- $s .= " $_->{comment}\n";
- }
- }
- if ($update) {
- while (my ($key, $value) = each(%$new_network)) {
- $s .= " $key=$value\n";
- }
- }
- $s .= "}\n";
- undef %network;
- $update and undef $new_network;
- } else {
- #- unrecognized, keep it anyway
- push @{$network{entries}}, { comment => $_ };
- }
- } else {
- if (/^\s*network={(.*)/) {
- #- beginning of a new network block
- $network{comment} = $1;
- } else {
- #- keep other options, comments
- $s .= $_;
- }
- }
- }
- if ($new_network) {
- #- network wasn't found, write it
- $s .= "\nnetwork={\n";
- #- write ssid first
- if (my $ssid = delete $new_network->{ssid}) {
- $s .= " ssid=$ssid\n";
- }
- while (my ($key, $value) = each(%$new_network)) {
- $s .= " $key=$value\n";
- }
- $s .= "}\n";
- }
- output($wpa_supplicant_conf, $s);
- #- hide keys for non-root users
- chmod 0600, $wpa_supplicant_conf;
-}
-
#- configureNetwork2 : configure the network interfaces.
#- input
#- $prefix
diff --git a/perl-install/network/tools.pm b/perl-install/network/tools.pm
index 84b35a70b..6d7c5b7af 100644
--- a/perl-install/network/tools.pm
+++ b/perl-install/network/tools.pm
@@ -210,32 +210,6 @@ sub is_dynamic_host {
any { defined $_->{DHCP_HOSTNAME} } values %$intf;
}
-sub convert_wep_key_for_iwconfig {
- #- 5 or 13 characters, consider the key as ASCII and prepend "s:"
- #- else consider the key as hexadecimal, do not strip dashes
- #- always quote the key as string
- my ($key) = @_;
- member(length($key), (5, 13)) ? "s:$key" : $key;
-}
-
-sub get_wep_key_from_iwconfig {
- #- strip "s:" if the key is 5 or 13 characters (ASCII)
- #- else the key as hexadecimal, do not modify
- my ($key) = @_;
- $key =~ s/^s:// if member(length($key), (7,15));
- $key;
-}
-
-sub convert_key_for_wpa_supplicant {
- my ($key) = @_;
- if ($key =~ /^([[:xdigit:]]{4}[\:-])+[[:xdigit:]]{2,}$/) {
- $key =~ s/[\:-]//g;
- return lc($key);
- } else {
- return qq("$key");
- }
-}
-
#- returns interface whose IP address matchs given IP address, according to its network mask
sub find_matching_interface {
my ($intf, $address) = @_;
@@ -296,29 +270,4 @@ sub get_default_metric {
$idx * 10;
}
-sub ndiswrapper_installed_drivers() {
- `ndiswrapper -l` =~ /(\w+)\s+driver present/mg;
-}
-
-sub ndiswrapper_available_drivers() {
- `ndiswrapper -l` =~ /(\w+)\s+driver present, hardware present/mg;
-}
-
-sub ndiswrapper_setup() {
- eval { modules::unload("ndiswrapper") };
- #- unload ndiswrapper first so that the newly installed .inf files will be read
- eval { modules::load("ndiswrapper") };
-
- #- FIXME: move this somewhere in get_eth_cards, so that configure_eth_aliases correctly writes ndiswrapper
- #- find the first interface matching an ndiswrapper driver, try ethtool then sysfs
- my @available_drivers = network::tools::ndiswrapper_available_drivers();
- my $ntf_name = find {
- my $drv = c::getNetDriver($_) || readlink("/sys/class/net/$_/driver");
- $drv =~ s!.*/!!;
- member($drv, @available_drivers);
- } detect_devices::getNet();
- #- fallback on wlan0
- return $ntf_name || "wlan0";
-}
-
1;
diff --git a/perl-install/network/wireless.pm b/perl-install/network/wireless.pm
new file mode 100644
index 000000000..96a607ce6
--- /dev/null
+++ b/perl-install/network/wireless.pm
@@ -0,0 +1,198 @@
+package network::wireless;
+
+use strict;
+use common;
+use modules;
+use detect_devices;
+use c;
+
+sub convert_wep_key_for_iwconfig {
+ #- 5 or 13 characters, consider the key as ASCII and prepend "s:"
+ #- else consider the key as hexadecimal, do not strip dashes
+ #- always quote the key as string
+ my ($key) = @_;
+ member(length($key), (5, 13)) ? "s:$key" : $key;
+}
+
+sub get_wep_key_from_iwconfig {
+ #- strip "s:" if the key is 5 or 13 characters (ASCII)
+ #- else the key as hexadecimal, do not modify
+ my ($key) = @_;
+ $key =~ s/^s:// if member(length($key), (7,15));
+ $key;
+}
+
+sub convert_key_for_wpa_supplicant {
+ my ($key) = @_;
+ if ($key =~ /^([[:xdigit:]]{4}[\:-])+[[:xdigit:]]{2,}$/) {
+ $key =~ s/[\:-]//g;
+ return lc($key);
+ } else {
+ return qq("$key");
+ }
+}
+
+#- FIXME: to be improved (quotes, comments) and moved in common files
+sub wlan_ng_update_vars {
+ my ($file, $vars) = @_;
+ substInFile {
+ while (my ($key, $value) = each(%$vars)) {
+ s/^#?\Q$key\E=(?:"[^#]*"|[^#\s]*)(\s*#.*)?/$key=$value$1/ and delete $vars->{$key};
+ }
+ $_ .= join('', map { "$_=$vars->{$_}\n" } keys %$vars) if eof;
+ } $file;
+}
+
+sub wlan_ng_configure {
+ my ($in, $ethntf, $module) = @_;
+ $in->do_pkgs->install('prism2-utils');
+ if ($ethntf->{WIRELESS_ESSID}) {
+ my $wlan_conf_file = "$::prefix/etc/wlan/wlan.conf";
+ my @wlan_devices = split(/ /, (cat_($wlan_conf_file) =~ /^WLAN_DEVICES="(.*)"/m)[0]);
+ push @wlan_devices, $ethntf->{DEVICE} unless member($ethntf->{DEVICE}, @wlan_devices);
+ #- enable device and make it use the choosen ESSID
+ wlan_ng_update_vars($wlan_conf_file,
+ {
+ WLAN_DEVICES => qq("@wlan_devices"),
+ "SSID_$ethntf->{DEVICE}" => qq("$ethntf->{WIRELESS_ESSID}"),
+ "ENABLE_$ethntf->{DEVICE}" => "y"
+ });
+ my $wlan_ssid_file = "$::prefix/etc/wlan/wlancfg-$ethntf->{WIRELESS_ESSID}";
+ #- copy default settings for this ESSID if config file does not exist
+ -f $wlan_ssid_file or cp_f("$::prefix/etc/wlan/wlancfg-DEFAULT", $wlan_ssid_file);
+ #- enable/disable encryption
+ wlan_ng_update_vars($wlan_ssid_file,
+ {
+ (map { $_ => $ethntf->{WIRELESS_ENC_KEY} ? "true" : "false" } qw(lnxreq_hostWEPEncrypt lnxreq_hostWEPDecrypt dot11PrivacyInvoked dot11ExcludeUnencrypted)),
+ AuthType => $ethntf->{WIRELESS_ENC_KEY} ? qq("sharedkey") : qq("opensystem"),
+ if_($ethntf->{WIRELESS_ENC_KEY},
+ dot11WEPDefaultKeyID => 0,
+ dot11WEPDefaultKey0 => qq("$ethntf->{WIRELESS_ENC_KEY}")
+ )
+ });
+ #- hide settings for non-root users
+ chmod 0600, $wlan_conf_file;
+ chmod 0600, $wlan_ssid_file;
+ }
+ #- apply settings on wlan interface
+ require services;
+ services::restart($module eq 'prism2_cs' ? 'pcmcia' : 'wlan');
+}
+
+sub wpa_supplicant_get_driver {
+ my ($module) = @_;
+ $module =~ /^hostap_/ ? "hostap" :
+ $module eq "prism54" ? "prism54" :
+ $module =~ /^ath_/ ? "madwifi" :
+ $module =~ /^at76c50|atmel_/ ? "atmel" :
+ $module eq "ndiswrapper" ? "ndiswrapper" :
+ $module =~ /^ipw2[12]00$/ ? "ipw" :
+ "wext";
+}
+
+sub wpa_supplicant_configure {
+ my ($in, $ethntf) = @_;
+ require services;
+ $in->do_pkgs->install('wpa_supplicant');
+
+ wpa_supplicant_add_network({
+ ssid => qq("$ethntf->{WIRELESS_ESSID}"),
+ psk => network::tools::convert_key_for_wpa_supplicant($ethntf->{WIRELESS_ENC_KEY}),
+ scan_ssid => 1,
+ });
+}
+
+sub wpa_supplicant_add_network {
+ my ($new_network) = @_;
+ my $wpa_supplicant_conf = "$::prefix/etc/wpa_supplicant.conf";
+ my $s;
+ my %network;
+ foreach (cat_($wpa_supplicant_conf)) {
+ if (%network) {
+ #- in a "network = {}" block
+ if (/^\s*(\w+)=(.*?)(\s*#.*)?$/) {
+ push @{$network{entries}}, { key => $1, value => $2, comment => $3 };
+ $1 eq 'ssid' and $network{ssid} = $2;
+ } elsif (/^\}/) {
+ #- end of network block, write it
+ $s .= "network={$network{comment}\n";
+ my $update = $network{ssid} eq $new_network->{ssid};
+ foreach (@{$network{entries}}) {
+ my $key = $_->{key};
+ if ($update) {
+ #- do not write entry if not provided in the new network
+ exists $new_network->{$key} or next;
+ #- update value from the new network
+ $_->{value} = delete $new_network->{$key};
+ }
+ if ($key) {
+ $s .= " $key=$_->{value}$_->{comment}\n";
+ } else {
+ $s .= " $_->{comment}\n";
+ }
+ }
+ if ($update) {
+ while (my ($key, $value) = each(%$new_network)) {
+ $s .= " $key=$value\n";
+ }
+ }
+ $s .= "}\n";
+ undef %network;
+ $update and undef $new_network;
+ } else {
+ #- unrecognized, keep it anyway
+ push @{$network{entries}}, { comment => $_ };
+ }
+ } else {
+ if (/^\s*network={(.*)/) {
+ #- beginning of a new network block
+ $network{comment} = $1;
+ } else {
+ #- keep other options, comments
+ $s .= $_;
+ }
+ }
+ }
+ if ($new_network) {
+ #- network wasn't found, write it
+ $s .= "\nnetwork={\n";
+ #- write ssid first
+ if (my $ssid = delete $new_network->{ssid}) {
+ $s .= " ssid=$ssid\n";
+ }
+ while (my ($key, $value) = each(%$new_network)) {
+ $s .= " $key=$value\n";
+ }
+ $s .= "}\n";
+ }
+ output($wpa_supplicant_conf, $s);
+ #- hide keys for non-root users
+ chmod 0600, $wpa_supplicant_conf;
+}
+
+sub ndiswrapper_installed_drivers() {
+ `ndiswrapper -l` =~ /(\w+)\s+driver present/mg;
+}
+
+sub ndiswrapper_available_drivers() {
+ `ndiswrapper -l` =~ /(\w+)\s+driver present, hardware present/mg;
+}
+
+sub ndiswrapper_setup() {
+ eval { modules::unload("ndiswrapper") };
+ #- unload ndiswrapper first so that the newly installed .inf files will be read
+ eval { modules::load("ndiswrapper") };
+
+ #- FIXME: move this somewhere in get_eth_cards, so that configure_eth_aliases correctly writes ndiswrapper
+ #- find the first interface matching an ndiswrapper driver, try ethtool then sysfs
+ my @available_drivers = ndiswrapper_available_drivers();
+ my $ntf_name = find {
+ my $drv = c::getNetDriver($_) || readlink("/sys/class/net/$_/driver");
+ $drv =~ s!.*/!!;
+ member($drv, @available_drivers);
+ } detect_devices::getNet();
+ #- fallback on wlan0
+ return $ntf_name || "wlan0";
+}
+
+1;