#!perl -w # location_thing.plx # pudge@pobox.com, 2000.05.25 - 2001.03.06 # This script is designed for me to switch locations easily on my # PowerBook. Location Manager is a nice start, but it does not do # a complete job. It will, set my Internet prefs, but I have long # since decided that because the _only_ thing I want to change # is my SMTP host when I go from place to place, it is not worth # the effort of keeping everything else in sync. Also, LM will not # change my AirPort network, and will not change my Hosts file. # So I change AirPort networks with Apple events, change my Hosts # file with Perl, and change my SMTP host with Mac::InternetConfig. use File::Spec::Functions; use Mac::Apps::Launch; use Mac::Files; use Mac::Glue ':all'; use Mac::InternetConfig; use Symbol; use enum qw(AWAY HOME WORK); use strict; my($kc, $ap); # other glues # get and launch Location Manager my $lm_path = catfile( FindFolder(kOnSystemDisk, kControlPanelFolderType), 'Location Manager' ); my $lm = new Mac::Glue 'Location Manager'; $lm->launch($lm_path); $lm->activate; END { for ($lm, $ap, $kc) { $_->quit if $_ } } # find all locations, display dialog my $loc = get_location($lm, get_location_names($lm)); # adjust Hosts file my $where = ($loc =~ m|^Home / |) ? HOME : ($loc =~ m|^OSDN / |) ? WORK : AWAY; my $mailhost = ($loc =~ m|^OSDN / |) ? 'relay1.shore.net' : ($loc eq 'Abroad / Modem') ? 'smtp.valinux.com' : 'fire.he.net'; set_hosts($where, $mailhost); # set location $lm->set( $lm->prop('current_location'), to => $lm->obj('location' => $loc) ); warn $^E if $^E; set_airport() if $loc =~ m| / WaveLAN\b| && ($where == HOME || $where == WORK); # set current AirPort network sub set_airport { $ap = new Mac::Glue 'AirPort'; if ($where == HOME) { my $network = 'PudgeLAN'; $kc = new Mac::Glue 'Keychain'; $kc->unlock; my $pass = $kc->get($kc->prop(password => key => whose(name => equals => $network), keychain => 1 )); $ap->join($network, with_password => $pass); } elsif ($where == WORK) { $ap->join('WaveLAN'); } } # get all locations sub get_location_names { my($lm) = @_; my @locs; for (my $i = 0; $i <= $lm->count('each' => 'location'); $i++) { push @locs, $lm->get( $lm->prop(name => 'location' => $i) ); } return @locs; } # location dialog sub get_location { my($lm, @locs) = @_; my $len = @locs < 3 ? 3 : @locs > 15 ? 15 : @locs; my $size = 16.5 * $len; my $dialog = { size => [260, 95 + $size], contents => [ { class => 'list box', bounds => [10, 36, 250, 36 + $size], contents => \@locs, }, { class => 'push button', bounds => [190, 65 + $size, 250, 85 + $size], name => 'OK', }, { class => 'push button', bounds => [110, 65 + $size, 170, 85 + $size], name => 'Cancel' } ], timeout_after => 60, }; my @results = $lm->dd_auto_dialog($dialog, grayscale => 1); die $^E if $^E; if ($results[1]) { return $locs[$results[0] - 1]; } else { exit; } } # fix Hosts file sub set_hosts { my($where, $mailhost) = @_; $InternetConfig{kICSMTPHost()} = $mailhost; my $hosts = gensym; my $hostsfile = catfile( FindFolder(kOnSystemDisk, kPreferencesFolderType), "Hosts" ); open $hosts, "< $hostsfile\0" or die "Can't open $hostsfile: $!"; my @hosts = <$hosts>; for (grep { /; (?:HOME|AWAY)$/ } @hosts) { if ($where == HOME) { s/^;+// if /; HOME$/; s/^(;+)?/;/ if /; AWAY$/; } else { s/^;+// if /; AWAY$/; s/^(;+)?/;/ if /; HOME$/; } } close $hosts or die "Can't close $hostsfile: $!"; open $hosts, "> $hostsfile\0" or die "Can't open $hostsfile: $!"; print $hosts @hosts; close $hosts or die "Can't close $hostsfile: $!"; } __END__