10Sstevel@tonic-gate#!/usr/bin/perl 20Sstevel@tonic-gate 30Sstevel@tonic-gate# This utility translates from aspppd configuration to Solaris PPP 4.0 40Sstevel@tonic-gate# (or ANU ppp-2.4.0; aka pppd). It can also revert to previous aspppd 50Sstevel@tonic-gate# configuration (discarding the pppd configuration), but does not 60Sstevel@tonic-gate# translate new configuration files into old. 70Sstevel@tonic-gate# 80Sstevel@tonic-gate# This script provides only a suggested translation for your existing 90Sstevel@tonic-gate# aspppd configuration. You will need to evaluate for yourself 100Sstevel@tonic-gate# whether the translation is appropriate for your operating 110Sstevel@tonic-gate# environment. 120Sstevel@tonic-gate 13*11262SRajagopal.Andra@Sun.COM# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 14*11262SRajagopal.Andra@Sun.COM# Use is subject to license terms. 150Sstevel@tonic-gate# 160Sstevel@tonic-gate 170Sstevel@tonic-gate# Steps in translation: 180Sstevel@tonic-gate# - parse /etc/asppp.cf 19*11262SRajagopal.Andra@Sun.COM# - check for aspppls in /etc/passwd (or NIS) 200Sstevel@tonic-gate# - read in current /etc/ppp/options configuration file 210Sstevel@tonic-gate# - read list of configured serial ports from pmadm 220Sstevel@tonic-gate# - read in UUCP configuration files 230Sstevel@tonic-gate# - create translated configuration 240Sstevel@tonic-gate# - write files back out 250Sstevel@tonic-gate 260Sstevel@tonic-gate# Known issues: 270Sstevel@tonic-gate# - translation with point-to-multipoint is incomplete 280Sstevel@tonic-gate 290Sstevel@tonic-gateuse Getopt::Std; 300Sstevel@tonic-gateuse Fcntl; 310Sstevel@tonic-gateuse POSIX qw(tmpnam ENOSYS); 320Sstevel@tonic-gateuse Sys::Hostname; 330Sstevel@tonic-gate 340Sstevel@tonic-gate# Secure the path if we're running under RBAC. 350Sstevel@tonic-gate$ENV{PATH} = ( "/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/ucb" ) 360Sstevel@tonic-gate if $< != $>; 370Sstevel@tonic-gate 380Sstevel@tonic-gate# General path names that can be configured. 390Sstevel@tonic-gatelocal($rootetc) = "/etc/"; 400Sstevel@tonic-gatelocal($passwd) = $rootetc . "passwd"; 410Sstevel@tonic-gatelocal($passwdlck) = $rootetc . ".pwd.lock"; 420Sstevel@tonic-gatelocal($asfile) = $rootetc . "asppp.cf"; 430Sstevel@tonic-gatelocal($astemp) = $rootetc . "asppp.temp.cf"; 440Sstevel@tonic-gatelocal($asmoved) = $rootetc . "asppp.saved.cf"; 450Sstevel@tonic-gatelocal($uucpdir) = $rootetc . "uucp/"; 460Sstevel@tonic-gatelocal($Devices) = $uucpdir . "Devices"; 470Sstevel@tonic-gatelocal($Devconfig) = $uucpdir . "Devconfig"; 480Sstevel@tonic-gatelocal($Dialers) = $uucpdir . "Dialers"; 490Sstevel@tonic-gatelocal($Dialcodes) = $uucpdir . "Dialcodes"; 500Sstevel@tonic-gatelocal($Limits) = $uucpdir . "Limits"; 510Sstevel@tonic-gatelocal($Sysfiles) = $uucpdir . "Sysfiles"; 520Sstevel@tonic-gatelocal($Systems) = $uucpdir . "Systems"; 530Sstevel@tonic-gatelocal($pppdir) = $rootetc . "ppp/"; 540Sstevel@tonic-gatelocal($options) = $pppdir . "options"; 550Sstevel@tonic-gatelocal($ttyprefix) = $pppdir . "options."; 560Sstevel@tonic-gatelocal($peersdir) = $pppdir . "peers/"; 570Sstevel@tonic-gatelocal($initd) = $rootetc . "init.d/"; 580Sstevel@tonic-gatelocal($asctl) = $initd . "asppp"; 590Sstevel@tonic-gatelocal($pppdctl) = $initd . "pppd"; 600Sstevel@tonic-gatelocal($sedpasswd) = "/tmp/sed-passwd"; 610Sstevel@tonic-gate 620Sstevel@tonic-gate# Fake asppp keyword used to keep track of dial-in paths. 630Sstevel@tonic-gatelocal($isdialin) = "-is-dial-in"; 640Sstevel@tonic-gate 650Sstevel@tonic-gate# Limits and Sysfiles are keyed on "service=". 660Sstevel@tonic-gate# Devconfig is keyed on "service=" and "device=". 670Sstevel@tonic-gate# Dialcodes, Dialers, Systems, and Devices are single keyword files. 680Sstevel@tonic-gate# Devices alone may have multiple entries for a given key. 690Sstevel@tonic-gate 700Sstevel@tonic-gate# Internal data structures 710Sstevel@tonic-gatelocal(@sysfiles,@limits,@devconfig); 720Sstevel@tonic-gatelocal(@sysdefault) = ( "systems=" . $Systems, "dialers=" . $Dialers, 730Sstevel@tonic-gate "devices=" . $Devices ); 740Sstevel@tonic-gatelocal(@limitdefault) = ( "max=-1" ); 750Sstevel@tonic-gatelocal(@devdefault) = ( "pop=", "push=", "connecttime=-1", "expecttime=-1", 760Sstevel@tonic-gate "msgtime=-1" ); 770Sstevel@tonic-gate 780Sstevel@tonic-gate# List of keywords for which ifconfig takes an additional parameter. 790Sstevel@tonic-gatelocal($ifconfigtakes) = ( 800Sstevel@tonic-gate addif => 1, 810Sstevel@tonic-gate removeif => 1, 820Sstevel@tonic-gate auth_algs => 1, 830Sstevel@tonic-gate encr_algs => 1, 840Sstevel@tonic-gate encr_auth_algs => 1, 850Sstevel@tonic-gate broadcast => 1, 860Sstevel@tonic-gate destination => 1, 870Sstevel@tonic-gate index => 1, 880Sstevel@tonic-gate metric => 1, 890Sstevel@tonic-gate modinsert => 1, 900Sstevel@tonic-gate modremove => 1, 910Sstevel@tonic-gate mtu => 1, 920Sstevel@tonic-gate netmask => 1, 930Sstevel@tonic-gate set => 1, 940Sstevel@tonic-gate subnet => 1, 950Sstevel@tonic-gate tdst => 1, 960Sstevel@tonic-gate tsrc => 1, 970Sstevel@tonic-gate wait => 1, 980Sstevel@tonic-gate 990Sstevel@tonic-gate# These are keywords, but do not take an additional parameter. 1000Sstevel@tonic-gate ether => 0, 1010Sstevel@tonic-gate inet => 0, 1020Sstevel@tonic-gate inet6 => 0, 1030Sstevel@tonic-gate arp => 0, 1040Sstevel@tonic-gate -arp => 0, 1050Sstevel@tonic-gate auto-revarp => 0, 1060Sstevel@tonic-gate modlist => 0, 1070Sstevel@tonic-gate plumb => 0, 1080Sstevel@tonic-gate unplumb => 0, 1090Sstevel@tonic-gate private => 0, 1100Sstevel@tonic-gate -private => 0, 1110Sstevel@tonic-gate nud => 0, 1120Sstevel@tonic-gate -nud => 0, 1130Sstevel@tonic-gate trailers => 0, 1140Sstevel@tonic-gate -trailers => 0, 1150Sstevel@tonic-gate up => 0, 1160Sstevel@tonic-gate down => 0, 1170Sstevel@tonic-gate xmit => 0, 1180Sstevel@tonic-gate -xmit => 0, 1190Sstevel@tonic-gate auto-dhcp => 0, 1200Sstevel@tonic-gate dhcp => 0, 1210Sstevel@tonic-gate primary => 0, 1220Sstevel@tonic-gate drop => 0, 1230Sstevel@tonic-gate extend => 0, 1240Sstevel@tonic-gate inform => 0, 1250Sstevel@tonic-gate ping => 0, 1260Sstevel@tonic-gate release => 0, 1270Sstevel@tonic-gate start => 0, 1280Sstevel@tonic-gate status => 0 1290Sstevel@tonic-gate); 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate# print number of something in English. 1320Sstevel@tonic-gatesub nof 1330Sstevel@tonic-gate{ 1340Sstevel@tonic-gate local($num, $item, @rest) = @_; 1350Sstevel@tonic-gate print "No ", $item, "s", @rest if $num == 0; 1360Sstevel@tonic-gate print "1 ", $item, @rest if $num == 1; 1370Sstevel@tonic-gate print $num, " ", $item, "s", @rest if $num > 1; 1380Sstevel@tonic-gate} 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate# ask a yes or no question. 1410Sstevel@tonic-gatesub yesno 1420Sstevel@tonic-gate{ 1430Sstevel@tonic-gate local ($query, $default) = @_; 1440Sstevel@tonic-gate local ($ans, $defans); 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate return $default unless (-t STDIN) && (-t STDOUT) && !$opt_n; 1470Sstevel@tonic-gate $defans = $default ? "Yn" : "yN"; 1480Sstevel@tonic-gate while (1) { 1490Sstevel@tonic-gate print $query, " [", $defans, "]? "; 1500Sstevel@tonic-gate chomp($ans = <STDIN>); 1510Sstevel@tonic-gate return $default unless $ans; 1520Sstevel@tonic-gate return 1 if $ans =~ /^[Yy1Tt]/; 1530Sstevel@tonic-gate return 0 if $ans =~ /^[Nn0Ff]/; 1540Sstevel@tonic-gate print "Please enter 'y' or 'n'.\n"; 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate} 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate# Put quotes around a string, if necessary. 1590Sstevel@tonic-gate# The tests here aren't perfect -- they think that \\\' isn't an 1600Sstevel@tonic-gate# escaped quote -- but they're good enough. 1610Sstevel@tonic-gatesub requote 1620Sstevel@tonic-gate{ 1630Sstevel@tonic-gate local($_) = @_; 1640Sstevel@tonic-gate if (/^$/) { 1650Sstevel@tonic-gate "\"\""; 1660Sstevel@tonic-gate } elsif (/^'/ || /[^\\]'/ || /\\\\'/) { 1670Sstevel@tonic-gate# Has unescaped quotes; must use " or redo quoting. 1680Sstevel@tonic-gate if (/^"/ || /[^\\]"/ || /\\\\"/) { 1690Sstevel@tonic-gate# Both kinds of quotes; redo the quoting. 1700Sstevel@tonic-gate s/^"/\\"/; 1710Sstevel@tonic-gate s/([^\\]|\\\\)"/$1\\"/g; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate "\"" . $_ . "\""; 1740Sstevel@tonic-gate } elsif (/^"/ || /[^\\]"/ || /\\\\"/) { 1750Sstevel@tonic-gate "'" . $_ . "'"; 1760Sstevel@tonic-gate } elsif (/\s/) { 1770Sstevel@tonic-gate "\"" . $_ . "\""; 1780Sstevel@tonic-gate } else { 1790Sstevel@tonic-gate $_; 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate} 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate# Get a single line from a UUCP configuration file and return as a 1840Sstevel@tonic-gate# reference to an array of words. Removes comments and escapes. 1850Sstevel@tonic-gate# (This is a modified version of the standard Perl shellwords function 1860Sstevel@tonic-gate# that understands C escape sequences and continuation lines.) 1870Sstevel@tonic-gate# Optionally returns lead-in, source text, and trailing component 1880Sstevel@tonic-gate# for editing. 1890Sstevel@tonic-gatesub uucpline 1900Sstevel@tonic-gate{ 1910Sstevel@tonic-gate local($input, $file, $triplet) = @_; 1920Sstevel@tonic-gate local(@words,$snippet,$field,$havefield,$cont,@triparray,$maytrail); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate $cont = ""; 1950Sstevel@tonic-gate $maytrail = ""; 1960Sstevel@tonic-gate while (<$input>) { 1970Sstevel@tonic-gate # remove leading whitespace 1980Sstevel@tonic-gate if (s/^(\s+)//) { 1990Sstevel@tonic-gate $maytrail .= $1; 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate if ($cont eq "") { 2020Sstevel@tonic-gate if (s/^(\#(.|\n)*)$//) { 2030Sstevel@tonic-gate $triparray[0] .= $maytrail . $1; 2040Sstevel@tonic-gate $maytrail = ""; 2050Sstevel@tonic-gate next; 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate if (s/^(\\?\n?)$//) { 2080Sstevel@tonic-gate $triparray[0] .= $maytrail . $1; 2090Sstevel@tonic-gate $maytrail = ""; 2100Sstevel@tonic-gate next; 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate $triparray[0] .= $maytrail; 2130Sstevel@tonic-gate $maytrail = ""; 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate $snippet = $_; 2160Sstevel@tonic-gate if (s/^(([^\#\\]|\\.)*)\\\n$//) { 2170Sstevel@tonic-gate $maytrail .= $snippet; 2180Sstevel@tonic-gate $cont .= $1; 2190Sstevel@tonic-gate next; 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate if (/^(([^\\\#]|\\[^\#])*)(\#?(.|\n)*)$/) { 2220Sstevel@tonic-gate $_ = $maytrail . $1; 2230Sstevel@tonic-gate $maytrail = $3; 2240Sstevel@tonic-gate if (s/((\s|\n)*)$//) { 2250Sstevel@tonic-gate $maytrail = $1 . $maytrail; 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate $triparray[1] = $_; 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate $_ = $cont . $snippet; 2300Sstevel@tonic-gate $cont = ""; 2310Sstevel@tonic-gate s/\n$//; 2320Sstevel@tonic-gate while ($_ ne '') { 2330Sstevel@tonic-gate for (;;) { 2340Sstevel@tonic-gate if (s/^#.*//) { 2350Sstevel@tonic-gate last; 2360Sstevel@tonic-gate } elsif (s/^"(([^"\\]|\\.)*)"//) { 2370Sstevel@tonic-gate $snippet = $1; 2380Sstevel@tonic-gate } elsif (s/^"//) { 2390Sstevel@tonic-gate warn "Unmatched double quote in $file: \"$_\n"; 2400Sstevel@tonic-gate } elsif (s/^'(([^'\\]|\\.)*)'//) { 2410Sstevel@tonic-gate $snippet = $1; 2420Sstevel@tonic-gate } elsif (s/^'//) { 2430Sstevel@tonic-gate warn "Unmatched single quote in $file: '$_\n"; 2440Sstevel@tonic-gate } elsif (s/^\\s//) { 2450Sstevel@tonic-gate# \s works in chat, but not in the pppd option files 2460Sstevel@tonic-gate $snippet = " "; 2470Sstevel@tonic-gate } elsif (s/^(\\.)//) { 2480Sstevel@tonic-gate $snippet = $1; 2490Sstevel@tonic-gate } elsif (s/^([^\s\\'"#]+)//) { 2500Sstevel@tonic-gate $snippet = $1; 2510Sstevel@tonic-gate } else { 2520Sstevel@tonic-gate s/^\s+//; 2530Sstevel@tonic-gate last; 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate $havefield = 1; 2560Sstevel@tonic-gate $field .= $snippet; 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate push(@words, $field) if $havefield; 2590Sstevel@tonic-gate $havefield = 0; 2600Sstevel@tonic-gate $field = ''; 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate last; 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate $triparray[2] .= $maytrail; 2650Sstevel@tonic-gate @$triplet = @triparray; 2660Sstevel@tonic-gate warn "Bad continuation line in $file: $cont\n" if $cont ne ''; 2670Sstevel@tonic-gate \@words; 2680Sstevel@tonic-gate} 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate# Given a logical UUCP file name, return a list of all of the files 2710Sstevel@tonic-gate# that should be read. 2720Sstevel@tonic-gatesub uucpfiles 2730Sstevel@tonic-gate{ 2740Sstevel@tonic-gate local ($file) = @_; 2750Sstevel@tonic-gate local (@flist, $value) = (); 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate for $value (@sysfiles, @sysdefault) { 2780Sstevel@tonic-gate if ($value =~ /^$file=/i) { 2790Sstevel@tonic-gate $value =~ s/^$file=//i; 2800Sstevel@tonic-gate for $file (split /:/, $value) { 2810Sstevel@tonic-gate $file = $uucpdir . $file if $file !~ /^\//; 2820Sstevel@tonic-gate push @flist, $file; 2830Sstevel@tonic-gate } 2840Sstevel@tonic-gate last; 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate @flist; 2880Sstevel@tonic-gate} 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate# Given a file name and some key words, parse the contents of the file 2910Sstevel@tonic-gate# and return a reference to a hash constructed from this. All keys 2920Sstevel@tonic-gate# except the last must match exactly. The last is used to order the 2930Sstevel@tonic-gate# hash. 2940Sstevel@tonic-gatesub uucpkeyfile 2950Sstevel@tonic-gate{ 2960Sstevel@tonic-gate local($file,@keylist) = @_; 2970Sstevel@tonic-gate local($lastkey,$keyval,$words,$i,$flag,%byservice); 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate open(SVCFILE, '<' . $file) || return undef; 3000Sstevel@tonic-gate $lastkey = pop @keylist; 3010Sstevel@tonic-gate while (@{$words = uucpline(SVCFILE, $file)}) { 3020Sstevel@tonic-gate $flag = 1; 3030Sstevel@tonic-gate foreach $keyval (@keylist) { 3040Sstevel@tonic-gate $flag = 0; 3050Sstevel@tonic-gate $i = 0; 3060Sstevel@tonic-gate while ($i < @$words) { 3070Sstevel@tonic-gate if ($$words[$i] eq $keyval) { 3080Sstevel@tonic-gate splice @$words, $i, 1; 3090Sstevel@tonic-gate $flag = 1; 3100Sstevel@tonic-gate last; 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate $i++; 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate last unless $flag; 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate next unless $flag; 3170Sstevel@tonic-gate foreach $i (0 .. @{$words}) { 3180Sstevel@tonic-gate if (@{$words}[$i] =~ /^$lastkey(.*)/i) { 3190Sstevel@tonic-gate splice @{$words}, $i, 1; 3200Sstevel@tonic-gate $byservice{$1} = $words; 3210Sstevel@tonic-gate last; 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate close SVCFILE; 3260Sstevel@tonic-gate \%byservice; 3270Sstevel@tonic-gate} 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate# This reads a UUCP file that is keyed on the first token on each 3300Sstevel@tonic-gate# line. Duplicates are not permitted; the first encountered is used 3310Sstevel@tonic-gate# and the rest are silently discarded. A hash indexed on the first 3320Sstevel@tonic-gate# token and containing an array of tokens in each bucket is returned. 3330Sstevel@tonic-gate# Used for Dialcodes, Dialers, and Systems. 3340Sstevel@tonic-gatesub uucpposfiles 3350Sstevel@tonic-gate{ 3360Sstevel@tonic-gate local(@files) = @_; 3370Sstevel@tonic-gate local($keyval,$words,%keyeddata); 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate foreach $file (@files) { 3400Sstevel@tonic-gate if (!open(POSFILE, '<' . $file)) { 3410Sstevel@tonic-gate warn "$file: $!\n"; 3420Sstevel@tonic-gate next; 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate while (@{$words = uucpline(POSFILE, $file)}) { 3450Sstevel@tonic-gate $keyval = shift @{$words}; 3460Sstevel@tonic-gate next if $keyeddata{$keyval}; 3470Sstevel@tonic-gate $keyeddata{$keyval} = $words; 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate close POSFILE; 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate \%keyeddata; 3520Sstevel@tonic-gate} 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate# This reads a UUCP file that is keyed on the first token on each line 3550Sstevel@tonic-gate# and may have duplicate entries. Each entry of the hash contains an 3560Sstevel@tonic-gate# array. Each entry of that array points to an array of tokens 3570Sstevel@tonic-gate# representing one parsed line. Used for the Devices file. 3580Sstevel@tonic-gatesub uucpdevices 3590Sstevel@tonic-gate{ 3600Sstevel@tonic-gate local(@files) = @_; 3610Sstevel@tonic-gate local($keyval,$words,%keyeddata); 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate foreach $file (@files) { 3640Sstevel@tonic-gate if (!open(POSFILE, '<' . $file)) { 3650Sstevel@tonic-gate warn "$file: $!\n"; 3660Sstevel@tonic-gate next; 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate while (@{$words = uucpline(POSFILE, $file)}) { 3690Sstevel@tonic-gate $keyval = shift @{$words}; 3700Sstevel@tonic-gate push @{$keyeddata{$keyval}}, $words; 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate close POSFILE; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate \%keyeddata; 3750Sstevel@tonic-gate} 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate# For a path defined in asppp.cf, copy over defaults, validate the 3780Sstevel@tonic-gate# required options, and save in the hash to be returned. 3790Sstevel@tonic-gatesub savepath 3800Sstevel@tonic-gate{ 3810Sstevel@tonic-gate local($paths, $options, $defref) = @_; 3820Sstevel@tonic-gate local($peer,$intf); 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate return if $options == $defref; 3850Sstevel@tonic-gate foreach $key (keys %$defref) { 3860Sstevel@tonic-gate $$options{$key} = $$defref{$key} unless defined($$options{$key}); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate $peer = $$options{"peer_system_name"}; 3890Sstevel@tonic-gate warn("Discarded path with no peer system name.\n"), return 3900Sstevel@tonic-gate unless defined($peer); 3910Sstevel@tonic-gate $intf = $$options{"interface"}; 3920Sstevel@tonic-gate warn("Missing interface on path to peer \"$peer\".\n"), return 3930Sstevel@tonic-gate unless defined($intf); 3940Sstevel@tonic-gate warn("Bad interface $intf on path to peer \"$peer\".\n"), return 3950Sstevel@tonic-gate unless $intf =~ /^ipd([0-9]+|ptp[0-9]+|ptp\*)$/; 3960Sstevel@tonic-gate warn("Missing peer IP address for point-to-multipoint path to \"", 3970Sstevel@tonic-gate $peer, "\".\n"), return 3980Sstevel@tonic-gate if $intf =~ /^ipd[0-9]+$/ && !defined($$options{"peer_ip_address"}); 3990Sstevel@tonic-gate warn "Multiple definitions of path to peer \"$peer\".\n", 4000Sstevel@tonic-gate if defined($paths{$peer}); 4010Sstevel@tonic-gate warn "Odd version number ", $$options{"version"}, 4020Sstevel@tonic-gate " encountered in path to peer \"", $peer, "\" (ignored).\n" 4030Sstevel@tonic-gate if defined($$options{"version"}) && $$options{"version"} != 1; 4040Sstevel@tonic-gate $paths{$peer} = $options; 4050Sstevel@tonic-gate} 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate# Parse through asppp.cf. Unlike the UUCP files, lines don't matter 4080Sstevel@tonic-gate# here. The parsing is modal, with "path" introducing a PPP session 4090Sstevel@tonic-gate# description and "defaults" reverting back to global definitions. 4100Sstevel@tonic-gatesub readaspppcf 4110Sstevel@tonic-gate{ 4120Sstevel@tonic-gate local($aspppcf) = @_; 4130Sstevel@tonic-gate local(%aspppdkey) = ( 4140Sstevel@tonic-gate chap_name => 1, 4150Sstevel@tonic-gate chap_peer_secret => 1, 4160Sstevel@tonic-gate chap_peer_name => 1, 4170Sstevel@tonic-gate chap_secret => 1, 4180Sstevel@tonic-gate debug_level => 1, 4190Sstevel@tonic-gate default_route => 0, 4200Sstevel@tonic-gate ifconfig => -1, 4210Sstevel@tonic-gate inactivity_timeout => 1, 4220Sstevel@tonic-gate interface => 1, 4230Sstevel@tonic-gate# sic; aspppd is seriously confused! ACCM isn't in IPCP. 4240Sstevel@tonic-gate ipcp_async_map => 1, 4250Sstevel@tonic-gate ipcp_compression => 1, 4260Sstevel@tonic-gate lcp_compression => 1, 4270Sstevel@tonic-gate lcp_mru => 1, 4280Sstevel@tonic-gate negotiate_address => 1, 4290Sstevel@tonic-gate pap_id => 1, 4300Sstevel@tonic-gate pap_password => 1, 4310Sstevel@tonic-gate pap_peer_id => 1, 4320Sstevel@tonic-gate pap_peer_password => 1, 4330Sstevel@tonic-gate peer_ip_address => 1, 4340Sstevel@tonic-gate peer_system_name => 1, 4350Sstevel@tonic-gate require_authentication => 2, 4360Sstevel@tonic-gate version => 1, 4370Sstevel@tonic-gate will_do_authentication => 2 4380Sstevel@tonic-gate ); 4390Sstevel@tonic-gate local($words,$word,$prevword,$i,$errors,%defaults,%ifconfig,%paths); 4400Sstevel@tonic-gate local($options); 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate open ASPPPD, "<" . $aspppcf || die "$aspppcf: $!\n"; 4430Sstevel@tonic-gate print "Reading configuration from $aspppcf\n" if $opt_v; 4440Sstevel@tonic-gate $defaults{inactivity_timeout} = 120; 4450Sstevel@tonic-gate $defaults{ipcp_compression} = "vj"; 4460Sstevel@tonic-gate $defaults{lcp_compression} = "on"; 4470Sstevel@tonic-gate $options = \%defaults; 4480Sstevel@tonic-gate while (@{$words = uucpline(ASPPPD, $aspppcf)}) { 4490Sstevel@tonic-gate if ($$words[0] =~ /^ifconfig$/i) { 4500Sstevel@tonic-gate warn "$prevword with missing argument ignored.\n" 4510Sstevel@tonic-gate if defined($prevword); 4520Sstevel@tonic-gate undef $prevword; 4530Sstevel@tonic-gate shift @$words; # discard 'ifconfig' keyword 4540Sstevel@tonic-gate $word = shift @$words; 4550Sstevel@tonic-gate warn("Bad interface on ifconfig $word.\n"), next 4560Sstevel@tonic-gate unless $word =~ /^ipd([0-9]+|ptp[0-9]+)$/; 4570Sstevel@tonic-gate $ifconfig{$word} = \@$words; 4580Sstevel@tonic-gate next; 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate unshift @{$words}, $prevword if defined($prevword); 4610Sstevel@tonic-gate undef $prevword; 4620Sstevel@tonic-gate while ($word = lc(shift @{$words})) { 4630Sstevel@tonic-gate $_ = $word; 4640Sstevel@tonic-gate if (/^defaults$/i) { 4650Sstevel@tonic-gate savepath(\%paths, $options, \%defaults); 4660Sstevel@tonic-gate $options = \%defaults; 4670Sstevel@tonic-gate next ; 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate if (/^path$/i) { 4700Sstevel@tonic-gate local(%pathopts); 4710Sstevel@tonic-gate savepath(\%paths, $options, \%defaults); 4720Sstevel@tonic-gate $options = \%pathopts; 4730Sstevel@tonic-gate next; 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate if (!defined($i = $aspppdkey{$word})) { 4760Sstevel@tonic-gate die "Too many errors in $aspppcf; aborting.\n" 4770Sstevel@tonic-gate if ++$errors > 5; 4780Sstevel@tonic-gate warn "Ignoring unknown keyword $word in $aspppcf\n"; 4790Sstevel@tonic-gate next; 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate warn("$_ unexpected; remainder of line ignored.\n"), 4820Sstevel@tonic-gate last if $i == -1; 4830Sstevel@tonic-gate warn("Duplicate $_ in path ignored.\n"), next 4840Sstevel@tonic-gate if $options != \%defaults && defined($$options{$_}); 4850Sstevel@tonic-gate $$options{$_} = 1 if $i == 0; 4860Sstevel@tonic-gate next if $i == 0; 4870Sstevel@tonic-gate $prevword = $_, last unless defined($word = shift @{$words}); 4880Sstevel@tonic-gate $$options{$_} = $word if $i == 1; 4890Sstevel@tonic-gate if ($i == 2) { 4900Sstevel@tonic-gate undef $$options{$_}, next if $word =~ /^off$/; 4910Sstevel@tonic-gate $$options{$_} = $word; 4920Sstevel@tonic-gate if ($word = shift @{$words}) { 4930Sstevel@tonic-gate if ($word =~ /^(p|ch)ap$/) { 4940Sstevel@tonic-gate $$options{$_} .= " " . $word; 4950Sstevel@tonic-gate } else { 4960Sstevel@tonic-gate unshift @{$words}, $word; 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate } 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate warn "Odd trailing keyword \"$prevword\" ignored in $aspppcf\n" 5030Sstevel@tonic-gate if $prevword; 5040Sstevel@tonic-gate savepath(\%paths, $options, \%defaults); 5050Sstevel@tonic-gate die "No paths defined for aspppd.\n" if 0+(keys %paths) == 0; 5060Sstevel@tonic-gate die "No interfaces defined for aspppd.\n" if 0+(keys %ifconfig) == 0; 5070Sstevel@tonic-gate if ($opt_v) { 5080Sstevel@tonic-gate nof 0+(keys %paths), "path", " and "; 5090Sstevel@tonic-gate nof 0+(keys %ifconfig), "interface", " defined for aspppd.\n"; 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate close ASPPPD; 5120Sstevel@tonic-gate ( \%ifconfig, \%paths ); 5130Sstevel@tonic-gate} 5140Sstevel@tonic-gate 515*11262SRajagopal.Andra@Sun.COM# Read /etc/passwd (or NIS) and return hash of users for whom 5160Sstevel@tonic-gate# the default shell is aspppls. Each hash entry contains the user's 5170Sstevel@tonic-gate# home directory path. 5180Sstevel@tonic-gatesub readpasswd 5190Sstevel@tonic-gate{ 5200Sstevel@tonic-gate local(%users,@pwe); 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate setpwent(); 5230Sstevel@tonic-gate while (@pwe = getpwent()) { 5240Sstevel@tonic-gate $users{$pwe[0]} = $pwe[7] if $pwe[8] =~ /\/aspppls$/; 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate endpwent(); 5270Sstevel@tonic-gate nof 0+(keys %users), "aspppd dial in user", " found.\n" 5280Sstevel@tonic-gate if $opt_v; 5290Sstevel@tonic-gate \%users; 5300Sstevel@tonic-gate} 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate# Parse through pmadm output to find enabled serial ports. 5330Sstevel@tonic-gate# Field 9 has 'I' (modem dial-out only or initialize only), 'b' 5340Sstevel@tonic-gate# (bidirectional) or is blank (modem dial-in only or terminal-hardwired). 5350Sstevel@tonic-gate# For that latter case, field 18 (software-carrier) has 'y'. 5360Sstevel@tonic-gate# Field 3 has 'x' if disabled. 5370Sstevel@tonic-gatesub getserialports 5380Sstevel@tonic-gate{ 5390Sstevel@tonic-gate local(%dialin, %dialout); 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate open PMADM, "pmadm -L|" || (warn "pmadm: $!\n", return undef); 5420Sstevel@tonic-gate while (<PMADM>) { 5430Sstevel@tonic-gate split /:/; 5440Sstevel@tonic-gate if ($_[3] !~ /x/) { 5450Sstevel@tonic-gate $dialin{$_[2]} = $_[8] if $_[9] ne "I"; 5460Sstevel@tonic-gate $dialout{$_[2]} = $_[8] if $_[9] ne ""; 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate close PMADM; 5500Sstevel@tonic-gate ( \%dialin, \%dialout ); 5510Sstevel@tonic-gate} 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate# Convert an ifconfig statement into a local and remote address pair. 5540Sstevel@tonic-gatesub ifconf_addr 5550Sstevel@tonic-gate{ 5560Sstevel@tonic-gate local($ifconf) = @_; 5570Sstevel@tonic-gate local($arg, $narg, $lcladdr, $remaddr); 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate shift @$ifconf; # lose the interface name 5600Sstevel@tonic-gate while (@$ifconf) { 5610Sstevel@tonic-gate local($arg, $narg); 5620Sstevel@tonic-gate $arg = shift @$ifconf; 5630Sstevel@tonic-gate $narg = shift @$ifconf if $ifconfigtakes{$arg}; 5640Sstevel@tonic-gate if (exists($ifconfigtakes{$arg})) { 5650Sstevel@tonic-gate if ($arg eq "set") { 5660Sstevel@tonic-gate $lcladdr = $narg; 5670Sstevel@tonic-gate } elsif ($arg eq "destination") { 5680Sstevel@tonic-gate $remaddr = $narg; 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate } elsif (!defined($lcladdr)) { 5710Sstevel@tonic-gate $lcladdr = $arg; 5720Sstevel@tonic-gate } elsif (!defined($remaddr)) { 5730Sstevel@tonic-gate $remaddr = $arg; 5740Sstevel@tonic-gate } 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate ( $lcladdr, $remaddr ); 5770Sstevel@tonic-gate} 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate# Convert a hash of aspppd options into an array of pppd options. The 5800Sstevel@tonic-gate# third argument ($chatpath) is undef for dial-in or a path to the 5810Sstevel@tonic-gate# chat script file otherwise. 5820Sstevel@tonic-gatesub convert_options 5830Sstevel@tonic-gate{ 5840Sstevel@tonic-gate local ($pppdargs, $opts, $chatpath, $user) = @_; 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate# Do the pppd option conversions. 5870Sstevel@tonic-gate push(@$pppdargs, "defaultroute") if $$opts{default_route}; 5880Sstevel@tonic-gate push(@$pppdargs, "idle " . $$opts{inactivity_timeout}) 5890Sstevel@tonic-gate if $$opts{inactivity_timeout} != 0; 5900Sstevel@tonic-gate push(@$pppdargs, "asyncmap " . $$opts{ipcp_async_map}) 5910Sstevel@tonic-gate if $$opts{ipcp_async_map}; 5920Sstevel@tonic-gate push(@$pppdargs, "novj") if !$$opts{ipcp_compression}; 5930Sstevel@tonic-gate local($peer); 5940Sstevel@tonic-gate if ($$opts{require_authentication}) { 5950Sstevel@tonic-gate local (@authopts); 5960Sstevel@tonic-gate if ($$opts{require_authentication} =~ /chap/) { 5970Sstevel@tonic-gate push(@authopts, "require-chap"); 5980Sstevel@tonic-gate $peer = $$opts{chap_peer_name}; 5990Sstevel@tonic-gate } else { 6000Sstevel@tonic-gate push(@authopts, "require-pap"); 6010Sstevel@tonic-gate $peer = $$opts{pap_peer_id}; 6020Sstevel@tonic-gate } 6030Sstevel@tonic-gate push(@authopts, "remotename " . requote($peer)) if $peer; 6040Sstevel@tonic-gate push(@authopts, "auth"); 6050Sstevel@tonic-gate if ($chatpath) { 6060Sstevel@tonic-gate push(@$pppdargs, @authopts); 6070Sstevel@tonic-gate } elsif ($dialin_auth == 3) { 6080Sstevel@tonic-gate# mixed authentication; must use wrapper script. 6090Sstevel@tonic-gate local($sfile) = $pppdir . "dial-in." . $user; 6100Sstevel@tonic-gate $scriptfiles{$sfile} = "#!/bin/sh\n"; 6110Sstevel@tonic-gate $scriptfiles{$sfile} .= "exec /usr/bin/pppd @authopts\n"; 6120Sstevel@tonic-gate $dialinshell{$user} = $sfile; 6130Sstevel@tonic-gate } 6140Sstevel@tonic-gate } elsif ($dialin_auth < 2) { 6150Sstevel@tonic-gate push(@$pppdargs, "noauth"); 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate push(@$pppdargs, "noaccomp nopcomp") if !$$opts{lcp_compression}; 6180Sstevel@tonic-gate push(@$pppdargs, "mru " . $$opts{lcp_mru}) if $$opts{lcp_mru}; 6190Sstevel@tonic-gate push(@$pppdargs, "noipdefault ipcp-accept-local") 6200Sstevel@tonic-gate if $$opts{negotiate_address}; 6210Sstevel@tonic-gate local($myname,$csecret,$psecret,$passopt); 6220Sstevel@tonic-gate if ($$opts{will_do_authentication} =~ /chap/i) { 6230Sstevel@tonic-gate $myname = $$opts{chap_name}; 6240Sstevel@tonic-gate $csecret = $$opts{chap_secret}; 6250Sstevel@tonic-gate } 6260Sstevel@tonic-gate $myname = "" if !$myname; 6270Sstevel@tonic-gate if ($$opts{will_do_authentication} =~ /pap/i) { 6280Sstevel@tonic-gate if ($myname ne "" && $$opts{pap_id} ne "" && 6290Sstevel@tonic-gate $myname ne $$opts{pap_id}) { 6300Sstevel@tonic-gate warn "pppd cannot have separate local names for PAP and CHAP; using CHAP name:\n"; 6310Sstevel@tonic-gate warn "\t\"$myname\"\n"; 6320Sstevel@tonic-gate } else { 6330Sstevel@tonic-gate $myname = $$opts{pap_id} if $$opts{pap_id} ne ""; 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate $psecret = $$opts{pap_password}; 6360Sstevel@tonic-gate } 6370Sstevel@tonic-gate if ($$opts{will_do_authentication}) { 6380Sstevel@tonic-gate if ($chatpath && 6390Sstevel@tonic-gate ($$opts{will_do_authentication} !~ /chap/i || 6400Sstevel@tonic-gate $$opts{will_do_authentication} !~ /pap/i || 6410Sstevel@tonic-gate $csecret eq $psecret)) { 6420Sstevel@tonic-gate push(@$pppdargs, 6430Sstevel@tonic-gate "password " . requote($csecret ? $csecret : $psecret)); 6440Sstevel@tonic-gate $passopt = 1; 6450Sstevel@tonic-gate } 6460Sstevel@tonic-gate push @$pppdargs, "user " . requote($myname); 6470Sstevel@tonic-gate push(@$pppdargs, "remotename " . requote($peer)) 6480Sstevel@tonic-gate if $peer && !$$opts{require_authentication}; 6490Sstevel@tonic-gate } else { 6500Sstevel@tonic-gate $myname = "NeverAuthenticate"; 6510Sstevel@tonic-gate } 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate push(@$pppdargs, "debug") if $$opts{debug_level} >= 8; 6540Sstevel@tonic-gate push(@$pppdargs, "kdebug 3") if $$opts{debug_level} >= 9; 6550Sstevel@tonic-gate local($lcladdr, $remaddr) = ifconf_addr($$ifconfig{$$opts{interface}}); 6560Sstevel@tonic-gate if ($chatpath) { 6570Sstevel@tonic-gate if ($$opts{debug_level} >= 4) { 6580Sstevel@tonic-gate push(@pppdargs, "connect \"/usr/bin/chat -vf $chatpath\""); 6590Sstevel@tonic-gate } else { 6600Sstevel@tonic-gate push(@pppdargs, "connect \"/usr/bin/chat -f $chatpath\""); 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate push(@$pppdargs, "user " . requote($myname)); 6630Sstevel@tonic-gate local($str) = $remaddr; 6640Sstevel@tonic-gate $str = $$opts{peer_ip_address} if $$opts{peer_ip_address}; 6650Sstevel@tonic-gate push(@$pppdargs, $lcladdr . ":" . $str) 6660Sstevel@tonic-gate if !$opt_s && ($lcladdr || $str); 6670Sstevel@tonic-gate } else { 6680Sstevel@tonic-gate push(@$pppdargs, "user " . requote($myname)) 6690Sstevel@tonic-gate if $myname eq "NeverAuthenticate"; 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate if ($$opts{interface} && $opt_s) { 6720Sstevel@tonic-gate if ($$opts{interface} =~ /^ipd[0-9]+$/) { 6730Sstevel@tonic-gate push(@$pppdargs, $lcladdr . ":") if $lcladdr; 6740Sstevel@tonic-gate } elsif ($$opts{interface} =~ /^ipd(|ptp)([0-9]+)$/) { 6750Sstevel@tonic-gate push(@pppdargs, "unit " . $2); 6760Sstevel@tonic-gate } else { 6770Sstevel@tonic-gate push(@pppdargs, "plumbed"); 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate# Convert the secrets 6820Sstevel@tonic-gate if ($chatpath) { 6830Sstevel@tonic-gate $addsecret = ""; 6840Sstevel@tonic-gate } elsif ($$opts{peer_ip_address}) { 6850Sstevel@tonic-gate $addsecret = " " . $$opts{peer_ip_address}; 6860Sstevel@tonic-gate } else { 6870Sstevel@tonic-gate $addsecret = " *"; 6880Sstevel@tonic-gate } 6890Sstevel@tonic-gate if ($$opts{require_authentication}) { 6900Sstevel@tonic-gate local($lclname, $secret, $authf); 6910Sstevel@tonic-gate $lclname = $$opts{will_do_authentication} ? $myname : hostname(); 6920Sstevel@tonic-gate if ($$opts{require_authentication} =~ /chap/) { 6930Sstevel@tonic-gate $secret = $$opts{chap_peer_secret}; 6940Sstevel@tonic-gate $authf = \%chapsecrets; 6950Sstevel@tonic-gate } else { 6960Sstevel@tonic-gate $secret = $$opts{pap_peer_password}; 6970Sstevel@tonic-gate $authf = \%papsecrets; 6980Sstevel@tonic-gate } 6990Sstevel@tonic-gate ${$$authf{$peer}}{$lclname} = requote($secret) . $addsecret; 7000Sstevel@tonic-gate } 7010Sstevel@tonic-gate if ($$opts{will_do_authentication} && !$passopt) { 7020Sstevel@tonic-gate ${$chapsecrets{$myname}}{$peer} = requote($csecret) if $csecret; 7030Sstevel@tonic-gate ${$papsecrets{$myname}}{$peer} = requote($psecret) if $psecret; 7040Sstevel@tonic-gate } 7050Sstevel@tonic-gate} 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate# Translate options for a dial-in user. 7080Sstevel@tonic-gatesub translatedialin 7090Sstevel@tonic-gate{ 7100Sstevel@tonic-gate local($peer) = @_; 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate $optname = $$dialinusers{$peer}; 7130Sstevel@tonic-gate $optname .= "/" if $optname !~ /\/$/; 7140Sstevel@tonic-gate $optname .= ".ppprc"; 7150Sstevel@tonic-gate if (exists($optfiles{$optname})) { 7160Sstevel@tonic-gate warn "Home directories of $peer and $optuser{$optname} are the same ($optfiles{$optname}\n"; 7170Sstevel@tonic-gate warn "Ignoring configuration for $peer.\n"; 7180Sstevel@tonic-gate return; 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate $optuser{$optname} = $peer; 7210Sstevel@tonic-gate $dialinshell{$peer} = "/usr/bin/pppd"; 7220Sstevel@tonic-gate local (@pppdargs); 7230Sstevel@tonic-gate convert_options(\@pppdargs, $$paths{$peer}, undef, $peer); 7240Sstevel@tonic-gate push @pppdargs, "nologfd"; 7250Sstevel@tonic-gate $optfiles{$optname} = \@pppdargs; 7260Sstevel@tonic-gate} 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate# Translate ifconfig entries in asppp.cf into either an ifconfig 7290Sstevel@tonic-gate# script for strict translation or a set of per-port IP addresses 7300Sstevel@tonic-gate# for normal translation. Also translate ipdX interfaces into 7310Sstevel@tonic-gate# Ethernet aliases to make routing daemon happy. 7320Sstevel@tonic-gatesub translateifconfig 7330Sstevel@tonic-gate{ 7340Sstevel@tonic-gate local (@ifconfiglist,$cstr,$etherif,$intf,$ifconf,$addstr,$port); 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate open IFLIST, "/usr/sbin/ifconfig -au4|" || die "cannot run ifconfig: $!\n"; 7370Sstevel@tonic-gate while (<IFLIST>) { 7380Sstevel@tonic-gate $etherif = $1 if !$etherif && /^([^:]*).*UP.*BROADCAST/; 7390Sstevel@tonic-gate } 7400Sstevel@tonic-gate close IFLIST; 7410Sstevel@tonic-gate $etherif = $1 if !$etherif && glob("/etc/hostname.*") =~ /[^\.]*.(.*)/; 7420Sstevel@tonic-gate $etherif = $1 if !$etherif && glob("/etc/dhcp.*") =~ /[^\.]*.(.*)/; 7430Sstevel@tonic-gate $etherif = "hme0" if !$etherif; 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate $cstr = ""; 7460Sstevel@tonic-gate foreach $intf (keys %$ifconfig) { 7470Sstevel@tonic-gate $ifconf = $$ifconfig{$intf}; 7480Sstevel@tonic-gate if ($intf =~ /ipd[0-9]+/) { 7490Sstevel@tonic-gate shift @$ifconf; 7500Sstevel@tonic-gate $cstr .= "ifconfig $etherif addif @$ifconf\n"; 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate $ndialin = 0+(keys %$dialin); 7550Sstevel@tonic-gate $addstr = ""; 7560Sstevel@tonic-gate foreach $intf (keys %downif) { 7570Sstevel@tonic-gate $ifconf = $downif{$intf}; 7580Sstevel@tonic-gate if ($intf =~ /ipdptp([0-9]+)/ && --$ndialin >= 0) { 7590Sstevel@tonic-gate push @ifconfiglist, $ifconf; 7600Sstevel@tonic-gate $addstr .= "ifconfig sppp" . $1 . " @$ifconf\n"; 7610Sstevel@tonic-gate } 7620Sstevel@tonic-gate } 7630Sstevel@tonic-gate if ($ndialin > 0) { 7640Sstevel@tonic-gate if (@ifconfiglist) { 7650Sstevel@tonic-gate print "Fewer ifconfigs (", $#ifconfiglist+1, 7660Sstevel@tonic-gate ") than dial-in lines (", $ndialin+$#ifconfiglist+1, ")\n"; 7670Sstevel@tonic-gate } else { 7680Sstevel@tonic-gate print "No ifconfigs for "; 7690Sstevel@tonic-gate nof $ndialin, "dial-in port", ".\n"; 7700Sstevel@tonic-gate } 7710Sstevel@tonic-gate } elsif ($ndialin < 0) { 7720Sstevel@tonic-gate if (@ifconfiglist) { 7730Sstevel@tonic-gate print "Ignoring ", -$ndialin, " of "; 7740Sstevel@tonic-gate nof $#ifconfiglist-$ndialin+1, "ifconfig", 7750Sstevel@tonic-gate " (too few dial-in ports)\n"; 7760Sstevel@tonic-gate } else { 7770Sstevel@tonic-gate print "Ignoring all "; 7780Sstevel@tonic-gate nof -$ndialin, "ifconfig line", " (no dial-in ports)\n"; 7790Sstevel@tonic-gate } 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate if ($opt_s) { 7830Sstevel@tonic-gate # Strict translation uses pre-plumbed interfaces. 7840Sstevel@tonic-gate $cstr .= $addstr; 7850Sstevel@tonic-gate } else { 7860Sstevel@tonic-gate foreach $port (values %$dialin) { 7870Sstevel@tonic-gate last if !@ifconfiglist; 7880Sstevel@tonic-gate $port =~ s+/dev/++; 7890Sstevel@tonic-gate $port =~ s+/+.+g; 7900Sstevel@tonic-gate $optfile = $ttyprefix . $port; 7910Sstevel@tonic-gate $ifconf = pop @ifconfiglist; 7920Sstevel@tonic-gate local ($lcladdr, $remaddr) = ifconf_addr($ifconf); 7930Sstevel@tonic-gate next if !defined($lcladdr) || !defined($remaddr); 7940Sstevel@tonic-gate local (@pppdargs) = $lcladdr . ":" . $remaddr; 7950Sstevel@tonic-gate $optfiles{$optfile} = \@pppdargs; 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate } 7980Sstevel@tonic-gate $scriptfiles{$pppdir . "ifconfig"} = $cstr if $cstr; 7990Sstevel@tonic-gate} 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate# Attempt to modify global passwd file using sed script stored in 8020Sstevel@tonic-gate# the $sedpasswd temporary file. 8030Sstevel@tonic-gatesub rewrite_passwd 8040Sstevel@tonic-gate{ 8050Sstevel@tonic-gate print "Updating local passwd file (if any).\n" if $opt_v; 8060Sstevel@tonic-gate if (!sysopen(PWDLCK, $passwdlck, O_WRONLY|O_CREAT, 0600)) { 8070Sstevel@tonic-gate warn "Unable to lock password file: $!\n"; 8080Sstevel@tonic-gate } else { 8090Sstevel@tonic-gate $lockstr = pack "ssLLiiLLLL", F_WRLCK, 0, 0, 0, 0, 0, 0, 0, 0, 0; 8100Sstevel@tonic-gate eval { 8110Sstevel@tonic-gate local $SIG{ARLM} = sub { 8120Sstevel@tonic-gate die "alarm while locking password file\n" 8130Sstevel@tonic-gate }; 8140Sstevel@tonic-gate alarm 15; 8150Sstevel@tonic-gate fcntl PWDLCK, F_SETLKW, $lockstr || 8160Sstevel@tonic-gate die "cannot lock password file: $!\n"; 8170Sstevel@tonic-gate alarm 0; 8180Sstevel@tonic-gate }; 8190Sstevel@tonic-gate if ($@) { 8200Sstevel@tonic-gate warn $@; 8210Sstevel@tonic-gate } else { 8220Sstevel@tonic-gate warn "Password update failed.\n" 8230Sstevel@tonic-gate if (system("sed -f $sedpasswd < $passwd > ${passwd}.new") || 8240Sstevel@tonic-gate !(rename "${passwd}.new", $passwd)); 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate $lockstr = pack "ssLLiiLLLL", F_UNLCK, 0, 0, 0, 0, 0, 0, 0, 0, 0; 8270Sstevel@tonic-gate fcntl PWDLCK, F_SETLK, $lockstr; 8280Sstevel@tonic-gate close PWDLCK; 8290Sstevel@tonic-gate } 830*11262SRajagopal.Andra@Sun.COM if (($ypmaster = `/usr/bin/ypwhich 2>/dev/null`) && $? == 0) { 8310Sstevel@tonic-gate $ypmaster =~ /(.*)\n/; 8320Sstevel@tonic-gate ($ypmaster) = gethostbyname($1); 8330Sstevel@tonic-gate ($thishost) = gethostbyname(hostname); 8340Sstevel@tonic-gate if ($ypmaster eq $thishost) { 8350Sstevel@tonic-gate system("cd /var/yp && make") 8360Sstevel@tonic-gate if yesno("Rebuild NIS/YP maps", $opt_y); 8370Sstevel@tonic-gate } else { 8380Sstevel@tonic-gate warn "Not running on NIS/YP master $1; unable to update user shells\n"; 8390Sstevel@tonic-gate print "Use 'sed -f $sedpasswd <$passwd >${passwd}.new' on the master\n"; 8400Sstevel@tonic-gate print "and then remake the NIS/YP database.\n"; 8410Sstevel@tonic-gate undef $sedpasswd; 8420Sstevel@tonic-gate } 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate unlink $sedpasswd if $sedpasswd; 8450Sstevel@tonic-gate} 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate# Show usage message. 8480Sstevel@tonic-gatesub usage 8490Sstevel@tonic-gate{ 8500Sstevel@tonic-gate print "Usage:\n\n"; 8510Sstevel@tonic-gate print "\t$0 [-rsvy]\n\n"; 8520Sstevel@tonic-gate print " -n - non-interactive mode.\n"; 8530Sstevel@tonic-gate print " -r - revert back to aspppd configuration.\n"; 8540Sstevel@tonic-gate print " -s - use strict translation.\n"; 8550Sstevel@tonic-gate print " -v - print more detail of the operations performed.\n"; 8560Sstevel@tonic-gate print " -y - assume 'yes' as default answer where reasonable.\n"; 8570Sstevel@tonic-gate exit; 8580Sstevel@tonic-gate} 8590Sstevel@tonic-gate 8600Sstevel@tonic-gate# Correct an environment variable so that it points at either a useful 8610Sstevel@tonic-gate# executable program, or nothing at all. 8620Sstevel@tonic-gatesub fixpath 8630Sstevel@tonic-gate{ 8640Sstevel@tonic-gate local ($prog, $deflt) = @_; 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate $prog = $deflt if $prog eq ""; 8670Sstevel@tonic-gate if ($prog !~ /^(\.\/|\/)/) { 8680Sstevel@tonic-gate local ($_) = $ENV{PATH}; 8690Sstevel@tonic-gate $_ = "/bin:/usr/bin:/sbin:/usr/sbin" if $_ eq ""; 8700Sstevel@tonic-gate split /:/; 8710Sstevel@tonic-gate foreach (@_) { 8720Sstevel@tonic-gate $prog = $_ . "/" . $prog, last if -x $_ . "/" . $prog; 8730Sstevel@tonic-gate } 8740Sstevel@tonic-gate } 8750Sstevel@tonic-gate $prog = "" if !(-x $prog); 8760Sstevel@tonic-gate $prog; 8770Sstevel@tonic-gate} 8780Sstevel@tonic-gate 8790Sstevel@tonic-gategetopts('nrsvy') || usage; 8800Sstevel@tonic-gate 8810Sstevel@tonic-gatedie "Need permission to modify system files.\n" 8820Sstevel@tonic-gate unless ($> == 0 || yesno "This script should be run as root. Continue"); 8830Sstevel@tonic-gate 8840Sstevel@tonic-gateif ($opt_r) { 8850Sstevel@tonic-gate local ($intemp); 8860Sstevel@tonic-gate 8870Sstevel@tonic-gate# Revert to previous configuration. Just rename the aspppd file back 8880Sstevel@tonic-gate# and undo changes to the passwd file. 8890Sstevel@tonic-gate 8900Sstevel@tonic-gate die "No saved aspppd configuration exists.\n" unless -f $asmoved; 8910Sstevel@tonic-gate if (-e $astemp) { 8920Sstevel@tonic-gate die "$astemp is not a file\n" unless -f $asfile; 8930Sstevel@tonic-gate unlink $astemp || die "Cannot remove temporary $astemp: $!\n"; 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate $intemp = 0; 8960Sstevel@tonic-gate if (-e $asfile) { 8970Sstevel@tonic-gate die "$asfile is not a file\n" unless -f $asfile; 8980Sstevel@tonic-gate die "Not modifying configuration.\n" 8990Sstevel@tonic-gate unless yesno "Remove existing $asfile", $opt_y; 9000Sstevel@tonic-gate rename $asfile, $astemp || die "Cannot rename existing $asfile: $!\n"; 9010Sstevel@tonic-gate $intemp = 1; 9020Sstevel@tonic-gate } 9030Sstevel@tonic-gate 9040Sstevel@tonic-gate if (rename $asmoved, $asfile) { 9050Sstevel@tonic-gate unlink $astemp || warn "$astemp: $!\n" if $intemp; 9060Sstevel@tonic-gate } else { 9070Sstevel@tonic-gate $failure = "Cannot rename $asmoved to $asfile: $!\n"; 9080Sstevel@tonic-gate rename $astemp, $asfile || 9090Sstevel@tonic-gate die "$failure\nand cannot recover: $!\n" . 9100Sstevel@tonic-gate "Saved current asppp.cf in $astemp\n" 9110Sstevel@tonic-gate if $intemp; 9120Sstevel@tonic-gate die $failure; 9130Sstevel@tonic-gate } 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate $( = $); 9160Sstevel@tonic-gate $< = $>; 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate system($pppdctl, "stop") if -x $pppdctl; 9190Sstevel@tonic-gate # remove pppd autostart files. 9200Sstevel@tonic-gate unlink $pppdir . "ifconfig"; 9210Sstevel@tonic-gate unlink $pppdir . "demand"; 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate system($asctl, "start") if -x $asctl; 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate open SEDFILE, ">$sedpasswd" || die "Cannot write $sedpasswd: $!\n"; 9260Sstevel@tonic-gate local ($escdir) = $pppdir; 9270Sstevel@tonic-gate $escdir =~ s+/+\\/+g; 9280Sstevel@tonic-gate print SEDFILE "/${escdir}dial-in\\./s+[^:]*\$+/usr/sbin/aspppls+\n"; 9290Sstevel@tonic-gate print SEDFILE "/\\/usr\\/bin\\/pppd/s+[^:]*\$+/usr/sbin/aspppls+\n"; 9300Sstevel@tonic-gate close SEDFILE; 9310Sstevel@tonic-gate 9320Sstevel@tonic-gate rewrite_passwd; 9330Sstevel@tonic-gate 9340Sstevel@tonic-gate exit 0; 9350Sstevel@tonic-gate} 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate$aspppcf = $asfile; 9380Sstevel@tonic-gateif (!(-f $asfile)) { 9390Sstevel@tonic-gate die "No aspppd configuration exists; nothing to convert.\n" 9400Sstevel@tonic-gate unless -f $asmoved; 9410Sstevel@tonic-gate die "No changes made.\n" 9420Sstevel@tonic-gate unless yesno "Already converted; rerun anyway"; 9430Sstevel@tonic-gate $aspppcf = $asmoved; 9440Sstevel@tonic-gate} 9450Sstevel@tonic-gate 9460Sstevel@tonic-gateprint "This script provides only a suggested translation for your existing aspppd\n"; 9470Sstevel@tonic-gateprint "configuration. You will need to evaluate for yourself whether the translation\n"; 9480Sstevel@tonic-gateprint "is appropriate for your operating environment.\n"; 9490Sstevel@tonic-gatedie "No changes made.\n" 9500Sstevel@tonic-gate unless yesno "Continue", 1; 9510Sstevel@tonic-gate 9520Sstevel@tonic-gate# Read in the asppp.cf file first; there's no reason to continue on to 9530Sstevel@tonic-gate# the UUCP files if this file isn't readable or has no paths defined. 9540Sstevel@tonic-gatelocal($ifconfig, $paths) = readaspppcf($aspppcf); 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate# Loop over the ifconfigs and build a list of the down ones. 9570Sstevel@tonic-gateforeach $intf (keys %$ifconfig) { 9580Sstevel@tonic-gate local(@words) = @{$$ifconfig{$intf}}; 9590Sstevel@tonic-gate while ($word = shift @words) { 9600Sstevel@tonic-gate shift @words if $ifconfigtakes{$word}; 9610Sstevel@tonic-gate if ($word =~ /^down$/) { 9620Sstevel@tonic-gate warn("Why is $intf declared down?\n"), last 9630Sstevel@tonic-gate if $intf =~ /^ipd[0-9]+$/; 9640Sstevel@tonic-gate $downif{$intf} = $$ifconfig{$intf}; 9650Sstevel@tonic-gate delete $$ifconfig{$intf}; 9660Sstevel@tonic-gate last; 9670Sstevel@tonic-gate } 9680Sstevel@tonic-gate } 9690Sstevel@tonic-gate} 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate# Read /etc/passwd for dial-in users configured for aspppd. 9720Sstevel@tonic-gatelocal($dialinusers) = readpasswd; 9730Sstevel@tonic-gate 9740Sstevel@tonic-gate# Read in existing pppd configuration. All we really care about 9750Sstevel@tonic-gate# is the setting of the "auth" option. 9760Sstevel@tonic-gateundef $authoption; 9770Sstevel@tonic-gateif (open(OPTIONS,"<" . $options)) { 9780Sstevel@tonic-gate while (@{$words = uucpline(OPTIONS, $options)}) { 9790Sstevel@tonic-gate while ($_ = pop @$words) { 9800Sstevel@tonic-gate $authoption = $_ if /auth/i; 9810Sstevel@tonic-gate } 9820Sstevel@tonic-gate } 9830Sstevel@tonic-gate close OPTIONS; 9840Sstevel@tonic-gate $authoption = "unknown" if !defined($authoption); 9850Sstevel@tonic-gate} 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate$dialin_auth = 0; 9880Sstevel@tonic-gateif ($authoption =~ /^auth$/i) { 9890Sstevel@tonic-gate $dialin_auth = 1; 9900Sstevel@tonic-gate} elsif ($authoption =~ /^noauth$/i) { 9910Sstevel@tonic-gate $dialin_auth = 2; 9920Sstevel@tonic-gate} elsif (defined($authoption)) { 9930Sstevel@tonic-gate $dialin_auth = 3; 9940Sstevel@tonic-gate} 9950Sstevel@tonic-gate 9960Sstevel@tonic-gate# Check that there's a path for each dial in user 9970Sstevel@tonic-gateforeach $user (keys %$dialinusers) { 9980Sstevel@tonic-gate if (!defined($$paths{$user})) { 9990Sstevel@tonic-gate warn "Dial-in user ", $user, 10000Sstevel@tonic-gate " does not have a corresponding dial-in path.\n"; 10010Sstevel@tonic-gate delete $$dialinusers{$user}; 10020Sstevel@tonic-gate next; 10030Sstevel@tonic-gate } 10040Sstevel@tonic-gate $intf = ${$$paths{$user}}{"interface"}; 10050Sstevel@tonic-gate if ($intf eq "ipdptp*") { 10060Sstevel@tonic-gate if (0+keys(%downif) == 0) { 10070Sstevel@tonic-gate warn "Dial-in user $path has no available \"down\" interfaces.\n"; 10080Sstevel@tonic-gate delete $$dialinusers{$user}; 10090Sstevel@tonic-gate next; 10100Sstevel@tonic-gate } 10110Sstevel@tonic-gate } else { 10120Sstevel@tonic-gate if (!defined($downif{$intf}) && !defined($$ifconfig{$intf})) { 10130Sstevel@tonic-gate warn "Dial-in path $user has undefined $intf; deleted.\n"; 10140Sstevel@tonic-gate delete $$dialinusers{$user}; 10150Sstevel@tonic-gate next; 10160Sstevel@tonic-gate } 10170Sstevel@tonic-gate } 10180Sstevel@tonic-gate ${$$paths{$user}}{$isdialin} = 1; 10190Sstevel@tonic-gate# 0 - no info (no options file, "noauth" on call) 10200Sstevel@tonic-gate# 1 - all auth ("auth" in options, "noauth" on call) 10210Sstevel@tonic-gate# 2 - all noauth ("noauth" in options) 10220Sstevel@tonic-gate# 3 - mixed; use auth ("noauth" in options, wrapper script for "auth") 10230Sstevel@tonic-gate if (${$$paths{$user}}{require_authentication}) { 10240Sstevel@tonic-gate if ($dialin_auth == 2) { 10250Sstevel@tonic-gate $dialin_auth = 3; 10260Sstevel@tonic-gate } elsif ($dialin_auth == 0) { 10270Sstevel@tonic-gate $dialin_auth = 1; 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate } else { 10300Sstevel@tonic-gate if ($dialin_auth == 1) { 10310Sstevel@tonic-gate $dialin_auth = 3; 10320Sstevel@tonic-gate } elsif ($dialin_auth == 0) { 10330Sstevel@tonic-gate $dialin_auth = 2; 10340Sstevel@tonic-gate } 10350Sstevel@tonic-gate } 10360Sstevel@tonic-gate} 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate# Get lists of usable dial-in and dial-out ports. 10390Sstevel@tonic-gatelocal($dialin,$dialout) = getserialports; 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate# Read and parse the UUCP Sysfiles, Devconfig, and Limits files. 10420Sstevel@tonic-gate# These are keyed with the "service=" string. The Sysfiles file can 10430Sstevel@tonic-gate# augment or override the list of files read for a given service. 10440Sstevel@tonic-gateprint "Reading UUCP configuration.\n" if $opt_v; 10450Sstevel@tonic-gate@sysfiles = @{${uucpkeyfile($Sysfiles,"service=")}{"ppp"}}; 10460Sstevel@tonic-gate@limits = @{${uucpkeyfile($Limits,"service=")}{"ppp"}}; 10470Sstevel@tonic-gate%devconfig = %{uucpkeyfile($Devconfig,"service=ppp","device=")}; 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate# Now read in the UUCP files corresponding to this service. 10500Sstevel@tonic-gate$systems = uucpposfiles(uucpfiles("systems")); 10510Sstevel@tonic-gate$dialers = uucpposfiles(uucpfiles("dialers")); 10520Sstevel@tonic-gate$dialcodes = uucpposfiles($Dialcodes); 10530Sstevel@tonic-gate$devices = uucpdevices(uucpfiles("devices")); 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate# just to make sure 10560Sstevel@tonic-gate$$dialcodes{""} = (); 10570Sstevel@tonic-gate 10580Sstevel@tonic-gate# Loop over paths. Dial-out only paths are translated into demand-dial 10590Sstevel@tonic-gate# configurations. Dial-in only paths are translated into appropriate 10600Sstevel@tonic-gate# log-in entries. 10610Sstevel@tonic-gatelocal (@bidirectional); 10620Sstevel@tonic-gateforeach $peer (keys %$paths) { 10630Sstevel@tonic-gate if (exists($$systems{$peer})) { 10640Sstevel@tonic-gate $sline = $$systems{$peer}; 10650Sstevel@tonic-gate if ($$sline[0] eq "Never") { 10660Sstevel@tonic-gate if (${$$paths{$peer}}{$isdialin}) { 10670Sstevel@tonic-gate translatedialin($peer); 10680Sstevel@tonic-gate } else { 10690Sstevel@tonic-gate print "We never call $peer, and he never calls us.\n" 10700Sstevel@tonic-gate if $opt_v; 10710Sstevel@tonic-gate } 10720Sstevel@tonic-gate delete $$paths{$peer}; 10730Sstevel@tonic-gate next; 10740Sstevel@tonic-gate } 10750Sstevel@tonic-gate push @bidirectional, $peer if ${$$paths{$peer}}{$isdialin}; 10760Sstevel@tonic-gate print "Ignoring time restriction on $peer\n" 10770Sstevel@tonic-gate if $$sline[0] ne "Any"; 10780Sstevel@tonic-gate $dlist = $$devices{$$sline[1]}; 10790Sstevel@tonic-gate $class = $$sline[2]; 10800Sstevel@tonic-gate $i = 0; 10810Sstevel@tonic-gate while ($i < @$dlist) { 10820Sstevel@tonic-gate local($dev) = $$dlist[$i]; 10830Sstevel@tonic-gate if ($$dev[1] ne "-") { 10840Sstevel@tonic-gate print "Ignoring device $$dev[0]; 801-type not supported.\n"; 10850Sstevel@tonic-gate splice @$dlist, $i, 1; 10860Sstevel@tonic-gate next; 10870Sstevel@tonic-gate } 10880Sstevel@tonic-gate $i++; 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate # Make sure that classes match. 10910Sstevel@tonic-gate next if $$dev[2] ne "Any" && $class ne "Any" && $$dev[2] ne $class; 10920Sstevel@tonic-gate # Prepend "/dev/" if it's not present in the device name. 10930Sstevel@tonic-gate if (exists($$dialout{$$dev[0]})) { 10940Sstevel@tonic-gate # This just seems odd. 10950Sstevel@tonic-gate $dname = $$dialout{$$dev[0]}; 10960Sstevel@tonic-gate $dname =~ s+/dev/term/+/dev/cua/+; 10970Sstevel@tonic-gate } else { 10980Sstevel@tonic-gate $dname = ($$dev[0] =~ m+^/+ ? $$dev[0] : ("/dev/" . $$dev[0])); 10990Sstevel@tonic-gate } 11000Sstevel@tonic-gate # Skip devices that aren't supposed to be used for dial-out. 11010Sstevel@tonic-gate next if $dname =~ m+^/dev/term/+; 11020Sstevel@tonic-gate next if $dname =~ m+^/dev/tty[a-z]$+; 11030Sstevel@tonic-gate # Make sure this is a character device and we have access to it. 11040Sstevel@tonic-gate next unless -w $dname && -c $dname; 11050Sstevel@tonic-gate warn "Dialer for $$dev[3] is missing.\n" 11060Sstevel@tonic-gate unless exists($warned{$$dev[3]}) || 11070Sstevel@tonic-gate exists($$dialers{$$dev[3]}); 11080Sstevel@tonic-gate $warned{$$dev[3]} = 1; 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate # Expand keywords from Dialcodes file. Should have \T or \D. 11110Sstevel@tonic-gate $phone = $$sline[3]; 11120Sstevel@tonic-gate $xphone = ($$dev[4] eq "\\T" && $phone =~ /^([A-Za-z]*)(.*)$/ ? 11130Sstevel@tonic-gate "@{$$dialcodes{$1}}" . $2 : $phone); 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate # Make a copy of the dialing script. 11160Sstevel@tonic-gate local(@dials) = @{$$dialers{$$dev[3]}}; 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate # Translate dial tone and wait characters from Dialers file. 11190Sstevel@tonic-gate $_ = shift @dials; 11200Sstevel@tonic-gate s[(.)(.)]{ 11210Sstevel@tonic-gate local($from,$to) = ($1,$2); 11220Sstevel@tonic-gate $phone =~ s+(^|[^\\])$from+$1$to+gx; 11230Sstevel@tonic-gate $xphone =~ s+(^|[^\\])$from+$1$to+gx; 11240Sstevel@tonic-gate }ge; 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate # Translate escapes in dial specification. Chat has a \T, 11270Sstevel@tonic-gate # but uses \U instead of \D. 11280Sstevel@tonic-gate local($needt, $needu, $isexpect, @chats) = ("", "", 1); 11290Sstevel@tonic-gate foreach $str (@dials) { 11300Sstevel@tonic-gate push(@chats, "") if $str eq ""; 11310Sstevel@tonic-gate local ($ostr) = ""; 11320Sstevel@tonic-gate if ($isexpect) { 11330Sstevel@tonic-gate while ($str =~ s/([^\\]*)\\(.)//) { 11340Sstevel@tonic-gate local($lead, $_) = ($1, $2); 11350Sstevel@tonic-gate /[Mm]/ ? ($ostr .= $lead) : 11360Sstevel@tonic-gate /[Ee]/ ? ($sorrye = 1, $ostr .= $lead) : 11370Sstevel@tonic-gate ($ostr .= $lead . "\\" . $_); 11380Sstevel@tonic-gate } 11390Sstevel@tonic-gate } else { 11400Sstevel@tonic-gate while ($str =~ s/([^\\]*)\\(.)//) { 11410Sstevel@tonic-gate local($lead, $_) = ($1, $2); 11420Sstevel@tonic-gate /T/ ? ($needt = " -T '$xphone'", 11430Sstevel@tonic-gate $ostr .= $lead . "\\T") : 11440Sstevel@tonic-gate /D/ ? ($needu = " -U '$phone'", 11450Sstevel@tonic-gate $ostr .= $lead . "\\U") : 11460Sstevel@tonic-gate /M/ ? ($ostr .= $lead, 11470Sstevel@tonic-gate ($ostr ne "" ? push(@chats, $ostr, "\\c"):0), 11480Sstevel@tonic-gate push(@chats, "HANGUP", "OFF"), $ostr = "") : 11490Sstevel@tonic-gate /m/ ? ($ostr .= $lead, 11500Sstevel@tonic-gate ($ostr ne "" ? push(@chats, $ostr, "\\c"):0), 11510Sstevel@tonic-gate push(@chats, "HANGUP", "ON"), $ostr = "") : 11520Sstevel@tonic-gate /[Ee]/ ? ($sorrye = 1, $ostr .= $lead) : 11530Sstevel@tonic-gate /[dp]/ ? ($ostr .= $lead . "\\" . $_ . "\\" . $_) : 11540Sstevel@tonic-gate /c/ ? ($str eq "" ? ($ostr .= $lead . "\\c") : 0) : 11550Sstevel@tonic-gate ($ostr .= $lead . "\\" . $_); 11560Sstevel@tonic-gate } 11570Sstevel@tonic-gate } 11580Sstevel@tonic-gate $ostr .= $str; 11590Sstevel@tonic-gate push @chats, $ostr if $ostr ne ""; 11600Sstevel@tonic-gate $isexpect = !$isexpect; 11610Sstevel@tonic-gate } 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate # Pad out dial list if we're missing a "send" string and tack 11640Sstevel@tonic-gate # on the chat list from the Systems file. 11650Sstevel@tonic-gate if (defined $$sline[4]) { 11660Sstevel@tonic-gate push @chats, "\\c" if !$isexpect; 11670Sstevel@tonic-gate push @chats, (splice @$sline, 4); 11680Sstevel@tonic-gate } 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate $chatfile = $pppdir . "chat.$peer.$$dev[3]"; 11710Sstevel@tonic-gate if (-e $chatfile) { 11720Sstevel@tonic-gate print "$chatfile already exists.\n"; 11730Sstevel@tonic-gate if (!yesno("Should it be overwritten",$opt_y)) { 11740Sstevel@tonic-gate if (yesno("Should it be used as-is")) { 11750Sstevel@tonic-gate warn "Using $chatfile as-is; it may not be correct.\n"; 11760Sstevel@tonic-gate } else { 11770Sstevel@tonic-gate for ($n = 0; ; $n++) { 11780Sstevel@tonic-gate last if !(-e $chatfile . "." . $n); 11790Sstevel@tonic-gate } 11800Sstevel@tonic-gate $chatfile .= "." . $n; 11810Sstevel@tonic-gate print "Using $chatfile instead.\n"; 11820Sstevel@tonic-gate $chatfiles{$chatfile} = \@chats; 11830Sstevel@tonic-gate } 11840Sstevel@tonic-gate } else { 11850Sstevel@tonic-gate $overwrite{$chatfile} = 1; 11860Sstevel@tonic-gate $chatfiles{$chatfile} = \@chats; 11870Sstevel@tonic-gate } 11880Sstevel@tonic-gate } else { 11890Sstevel@tonic-gate $chatfiles{$chatfile} = \@chats; 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate push @pppdargs, $dname; 11930Sstevel@tonic-gate push @pppdargs, $class if $class =~ /^[0-9]+$/; 11940Sstevel@tonic-gate push @pppdargs, "demand"; 11950Sstevel@tonic-gate convert_options(\@pppdargs,$$paths{$peer}, 11960Sstevel@tonic-gate $chatfile . $needt . $needu, undef); 11970Sstevel@tonic-gate 11980Sstevel@tonic-gate $optname = $peersdir . $peer; 11990Sstevel@tonic-gate if (-e $optname) { 12000Sstevel@tonic-gate print "$optname already exists.\n"; 12010Sstevel@tonic-gate if (!yesno("Should it be overwritten", $opt_y)) { 12020Sstevel@tonic-gate if (yesno("Should it be used as-is")) { 12030Sstevel@tonic-gate warn "Using $optname as-is; it may not be correct.\n"; 12040Sstevel@tonic-gate } else { 12050Sstevel@tonic-gate for ($n = 0; ; $n++) { 12060Sstevel@tonic-gate last if !(-e $optname . "." . $n); 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate $optname .= "." . $n; 12090Sstevel@tonic-gate print "Using $optname instead.\n"; 12100Sstevel@tonic-gate $optfiles{$optname} = \@pppdargs; 12110Sstevel@tonic-gate } 12120Sstevel@tonic-gate } else { 12130Sstevel@tonic-gate $overwrite{$optname} = 1; 12140Sstevel@tonic-gate $optfiles{$optname} = \@pppdargs; 12150Sstevel@tonic-gate } 12160Sstevel@tonic-gate } else { 12170Sstevel@tonic-gate $optfiles{$optname} = \@pppdargs; 12180Sstevel@tonic-gate } 12190Sstevel@tonic-gate $scriptfiles{$pppdir . "demand"} .= "/usr/bin/pppd file $optname\n"; 12200Sstevel@tonic-gate last; 12210Sstevel@tonic-gate } 12220Sstevel@tonic-gate } elsif (${$$paths{$peer}}{$isdialin}) { 12230Sstevel@tonic-gate translatedialin($peer); 12240Sstevel@tonic-gate } else { 12250Sstevel@tonic-gate warn "Path $peer has no dial-in user nor Systems file entry.\n"; 12260Sstevel@tonic-gate delete $$paths{$peer}; 12270Sstevel@tonic-gate } 12280Sstevel@tonic-gate} 12290Sstevel@tonic-gate 12300Sstevel@tonic-gatewarn "Chat cannot do echo checking; requests for this removed.\n" if $sorrye; 12310Sstevel@tonic-gate 12320Sstevel@tonic-gateif (@bidirectional) { 12330Sstevel@tonic-gate print "\nWarning: The following paths are bidirectional:\n"; 12340Sstevel@tonic-gate print "\t@bidirectional\n\n"; 12350Sstevel@tonic-gate print "Bidirectional paths (with entries in both Systems and passwd) do not translate\n"; 12360Sstevel@tonic-gate print "into Solaris PPP 4.0 semantics in an exact manner. The dial-out portion will\n"; 12370Sstevel@tonic-gate print "use the designated interface, but the dial-in portion will use any available\n"; 12380Sstevel@tonic-gate print "interface.\n"; 12390Sstevel@tonic-gate while ($peer = pop @bidirectional) { 12400Sstevel@tonic-gate delete $ {$$paths{$peer}}{interface}; 12410Sstevel@tonic-gate translatedialin($peer); 12420Sstevel@tonic-gate } 12430Sstevel@tonic-gate} 12440Sstevel@tonic-gate 12450Sstevel@tonic-gatetranslateifconfig; 12460Sstevel@tonic-gate 12470Sstevel@tonic-gate# Create an /etc/ppp/options if we need to. 12480Sstevel@tonic-gateif (!defined($authoption) && $dialin_auth > 0) { 12490Sstevel@tonic-gate local (@pppdopts); 12500Sstevel@tonic-gate push @pppdopts, "lock"; 12510Sstevel@tonic-gate push @pppdopts, "auth" if $dialin_auth == 1; 12520Sstevel@tonic-gate push @pppdopts, "noauth" if $dialin_auth > 1; 12530Sstevel@tonic-gate $optfiles{$options} = \@pppdopts; 12540Sstevel@tonic-gate} 12550Sstevel@tonic-gate# Translate option files to plain text. 12560Sstevel@tonic-gateforeach $file (keys %optfiles) { 12570Sstevel@tonic-gate local ($opts) = $optfiles{$file}; 12580Sstevel@tonic-gate local ($cstr) = ""; 12590Sstevel@tonic-gate $cstr .= shift(@$opts) . "\n" while @$opts; 12600Sstevel@tonic-gate $optfiles{$file} = $cstr; 12610Sstevel@tonic-gate} 12620Sstevel@tonic-gate# Change "auth" to "noauth" or add "noauth" to /etc/ppp/options. 12630Sstevel@tonic-gateif (defined($authoption) && $authoption ne "noauth" && $dialin_auth == 3) { 12640Sstevel@tonic-gate local(@triplet, $cstr); 12650Sstevel@tonic-gate if ($authoption eq "unknown") { 12660Sstevel@tonic-gate warn "Adding 'noauth' to $options\n"; 12670Sstevel@tonic-gate } else { 12680Sstevel@tonic-gate warn "Changing 'auth' in $options to 'noauth'\n"; 12690Sstevel@tonic-gate } 12700Sstevel@tonic-gate open(OPTIONS,"<" . $options) || die "$options disappeared: $!\n"; 12710Sstevel@tonic-gate while (@{$words = uucpline(OPTIONS, $options, \@triplet)}) { 12720Sstevel@tonic-gate $cstr .= $triplet[0]; 12730Sstevel@tonic-gate if (grep(/auth/, @$words)) { 12740Sstevel@tonic-gate local(@newwords) = map { $_ = "noauth" if /auth/; $_ } @$words; 12750Sstevel@tonic-gate $cstr .= "@newwords"; 12760Sstevel@tonic-gate } else { 12770Sstevel@tonic-gate $cstr .= $triplet[1]; 12780Sstevel@tonic-gate } 12790Sstevel@tonic-gate while (pop @$words) { 12800Sstevel@tonic-gate $authoption = $_ if /auth/i; 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate $cstr .= $triplet[2]; 12830Sstevel@tonic-gate } 12840Sstevel@tonic-gate $cstr .= $triplet[0] . $triplet[2]; 12850Sstevel@tonic-gate close OPTIONS; 12860Sstevel@tonic-gate $cstr .= "\n" if $cstr !~ /\n$/; 12870Sstevel@tonic-gate $cstr .= "noauth\n" if $authoption eq "unknown"; 12880Sstevel@tonic-gate $optfiles{$options} = $cstr; 12890Sstevel@tonic-gate} 12900Sstevel@tonic-gate 12910Sstevel@tonic-gate# Create a sed script to fix the users' shell paths. 12920Sstevel@tonic-gateif (0+(keys %dialinshell) != 0) { 12930Sstevel@tonic-gate $cstr = ""; 12940Sstevel@tonic-gate foreach $peer (keys %dialinshell) { 12950Sstevel@tonic-gate $cstr .= "/^$peer:/s+[^:]*/aspppls\$+$dialinshell{$peer}+\n"; 12960Sstevel@tonic-gate } 12970Sstevel@tonic-gate $scriptfiles{$sedpasswd} = $cstr; 12980Sstevel@tonic-gate} 12990Sstevel@tonic-gate 13000Sstevel@tonic-gateprint "\nPreparing to write out translated configuration:\n"; 13010Sstevel@tonic-gate 13020Sstevel@tonic-gate# Enumerate the files we'll write. 13030Sstevel@tonic-gate$nfiles = 0; 13040Sstevel@tonic-gateif (0+(keys %chatfiles) != 0) { 13050Sstevel@tonic-gate print " "; 13060Sstevel@tonic-gate nof 0+(keys %chatfiles), "chat file", ":\n"; 13070Sstevel@tonic-gate foreach $file (keys %chatfiles) { 13080Sstevel@tonic-gate $nfiles++; 13090Sstevel@tonic-gate print "\t$nfiles. $file\n"; 13100Sstevel@tonic-gate local ($chats) = $chatfiles{$file}; 13110Sstevel@tonic-gate local ($cstr) = ""; 13120Sstevel@tonic-gate while (@$chats) { 13130Sstevel@tonic-gate $cstr .= requote(shift(@$chats)); 13140Sstevel@tonic-gate $cstr .= " " . requote(shift(@$chats)) if @$chats; 13150Sstevel@tonic-gate $cstr .= "\n"; 13160Sstevel@tonic-gate } 13170Sstevel@tonic-gate local (@filerec) = ( $file, $cstr ); 13180Sstevel@tonic-gate push @allfiles, \@filerec; 13190Sstevel@tonic-gate } 13200Sstevel@tonic-gate} 13210Sstevel@tonic-gateif (0+(keys %optfiles) != 0) { 13220Sstevel@tonic-gate print " "; 13230Sstevel@tonic-gate nof 0+(keys %optfiles), "option file", ":\n"; 13240Sstevel@tonic-gate foreach $file (keys %optfiles) { 13250Sstevel@tonic-gate $nfiles++; 13260Sstevel@tonic-gate print "\t$nfiles. $file\n"; 13270Sstevel@tonic-gate local (@filerec) = ( $file, $optfiles{$file} ); 13280Sstevel@tonic-gate push @allfiles, \@filerec; 13290Sstevel@tonic-gate } 13300Sstevel@tonic-gate} 13310Sstevel@tonic-gateif (0+(keys %scriptfiles) != 0) { 13320Sstevel@tonic-gate print " "; 13330Sstevel@tonic-gate nof 0+(keys %scriptfiles), "script file", ":\n"; 13340Sstevel@tonic-gate foreach $file (keys %scriptfiles) { 13350Sstevel@tonic-gate $nfiles++; 13360Sstevel@tonic-gate print "\t$nfiles. $file\n"; 13370Sstevel@tonic-gate local (@filerec) = ( $file, $scriptfiles{$file} ); 13380Sstevel@tonic-gate push @allfiles, \@filerec; 13390Sstevel@tonic-gate } 13400Sstevel@tonic-gate} 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate# Merge new secrets needed with existing ones, if any. 13430Sstevel@tonic-gatesub merge_secrets 13440Sstevel@tonic-gate{ 13450Sstevel@tonic-gate local ($addsecrets, $fname) = @_; 13460Sstevel@tonic-gate local ($file, $cstr, @triplet, $newsecret); 13470Sstevel@tonic-gate 13480Sstevel@tonic-gate $nfiles++; 13490Sstevel@tonic-gate $file = $pppdir . $fname; 13500Sstevel@tonic-gate print "\t$nfiles. $file\n"; 13510Sstevel@tonic-gate if (open(SECRETS, '<' . $pppdir . $fname)) { 13520Sstevel@tonic-gate while (@{$words = uucpline(SECRETS, $pppdir . $fname, \@triplet)}) { 13530Sstevel@tonic-gate $cstr .= $triplet[0]; 13540Sstevel@tonic-gate $newsecret = $ {$$addsecrets{$$words[0]}}{$$words[1]}; 13550Sstevel@tonic-gate if (defined $newsecret) { 13560Sstevel@tonic-gate $cstr .= requote($$words[0]) . " " . requote($$words[1]) . 13570Sstevel@tonic-gate " " . $newsecret; 13580Sstevel@tonic-gate delete $ {$$addsecrets{$$words[0]}}{$$words[1]}; 13590Sstevel@tonic-gate } else { 13600Sstevel@tonic-gate $cstr .= $triplet[1]; 13610Sstevel@tonic-gate } 13620Sstevel@tonic-gate $cstr .= $triplet[2]; 13630Sstevel@tonic-gate } 13640Sstevel@tonic-gate close SECRETS; 13650Sstevel@tonic-gate $cstr .= $triplet[0] . $triplet[2]; 13660Sstevel@tonic-gate } 13670Sstevel@tonic-gate foreach $key1 (keys (%$addsecrets)) { 13680Sstevel@tonic-gate foreach $key2 (keys (%{$$addsecrets{$key1}})) { 13690Sstevel@tonic-gate $cstr .= requote($key1) . " " . requote($key2) . " " . 13700Sstevel@tonic-gate $ {$$addsecrets{$key1}}{$key2} . "\n"; 13710Sstevel@tonic-gate } 13720Sstevel@tonic-gate } 13730Sstevel@tonic-gate local (@filerec) = ( $file, $cstr ); 13740Sstevel@tonic-gate push @allfiles, \@filerec; 13750Sstevel@tonic-gate} 13760Sstevel@tonic-gate 13770Sstevel@tonic-gate$nchap = 0+(keys %chapsecrets) != 0; 13780Sstevel@tonic-gate$npap = 0+(keys %papsecrets) != 0; 13790Sstevel@tonic-gateif ($nchap != 0 || $npap != 0) { 13800Sstevel@tonic-gate print " "; 13810Sstevel@tonic-gate nof $nchap + $npap, "secrets file", ":\n"; 13820Sstevel@tonic-gate merge_secrets(\%chapsecrets, "chap-secrets") if $nchap != 0; 13830Sstevel@tonic-gate merge_secrets(\%papsecrets, "pap-secrets") if $npap != 0; 13840Sstevel@tonic-gate} 13850Sstevel@tonic-gate 13860Sstevel@tonic-gatedie "Nothing to write back; I'm done.\n" if $nfiles == 0; 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate$PAGER = fixpath($ENV{PAGER}, "/usr/bin/less"); 13890Sstevel@tonic-gate$EDITOR = fixpath($ENV{EDITOR}, "/usr/bin/vi"); 13900Sstevel@tonic-gate$SHELL = fixpath($ENV{SHELL}, "/usr/bin/ksh"); 13910Sstevel@tonic-gate 13920Sstevel@tonic-gateEND { 13930Sstevel@tonic-gate if ($tempname) { 13940Sstevel@tonic-gate unlink($tempname) or 13950Sstevel@tonic-gate die "Cannot remove temporary file $tempname: $!\n"; 13960Sstevel@tonic-gate } 13970Sstevel@tonic-gate} 13980Sstevel@tonic-gate 13990Sstevel@tonic-gatesub show_file_options 14000Sstevel@tonic-gate{ 14010Sstevel@tonic-gate print "\nEnter option number:\n"; 14020Sstevel@tonic-gate print "\t1 - view contents of file on standard output\n"; 14030Sstevel@tonic-gate print "\t2 - view contents of file using $PAGER\n" if $PAGER ne ""; 14040Sstevel@tonic-gate print "\t3 - edit contents of file using $EDITOR\n" if $EDITOR ne ""; 14050Sstevel@tonic-gate print "\t4 - delete/undelete file from list\n"; 14060Sstevel@tonic-gate print "\t5 - rename file in list\n"; 14070Sstevel@tonic-gate print "\t6 - show file list again\n"; 14080Sstevel@tonic-gate print "\t7 - escape to shell (or \"!cmd\")\n"; 14090Sstevel@tonic-gate print "\t8 - abort without saving anything\n"; 14100Sstevel@tonic-gate print "\t9 - save all files and exit (default)\n"; 14110Sstevel@tonic-gate} 14120Sstevel@tonic-gate 14130Sstevel@tonic-gate# If interactive, then allow user to view and modify converted data. 14140Sstevel@tonic-gateif ((-t STDIN) && (-t STDOUT) && !$opt_n) { 14150Sstevel@tonic-gate show_file_options(); 14160Sstevel@tonic-gate while (1) { 14170Sstevel@tonic-gate print "Option: "; 14180Sstevel@tonic-gate chomp($ans = <STDIN>); 14190Sstevel@tonic-gate if ($ans eq "?" || $ans =~ /^h/i) { 14200Sstevel@tonic-gate show_file_options(); 14210Sstevel@tonic-gate next; 14220Sstevel@tonic-gate } 14230Sstevel@tonic-gate if ($ans eq "") { 14240Sstevel@tonic-gate last if yesno "Saving all files. Are you sure"; 14250Sstevel@tonic-gate next; 14260Sstevel@tonic-gate } 14270Sstevel@tonic-gate last if $ans == 9; 14280Sstevel@tonic-gate print("Aborted.\n"), exit if $ans == 8; 14290Sstevel@tonic-gate if ($ans =~ /^!/ || $ans == 7) { 14300Sstevel@tonic-gate if ($ans =~ /^!(.+)/) { 14310Sstevel@tonic-gate system($1); 14320Sstevel@tonic-gate } else { 14330Sstevel@tonic-gate print("Interactive shell access not permitted here.\n"), next 14340Sstevel@tonic-gate if $< != $>; 14350Sstevel@tonic-gate system($SHELL); 14360Sstevel@tonic-gate } 14370Sstevel@tonic-gate } elsif ($ans == 6) { 14380Sstevel@tonic-gate for ($i = 0; $i < $nfiles; $i++) { 14390Sstevel@tonic-gate print "\t", $i+1, ". $allfiles[$i][0]", 14400Sstevel@tonic-gate ($deleted[$i] ? " (deleted)" : ""), "\n"; 14410Sstevel@tonic-gate } 14420Sstevel@tonic-gate } elsif ($ans > 0 && $ans < 6) { 14430Sstevel@tonic-gate $fnum = 0; 14440Sstevel@tonic-gate if ($nfiles > 1) { 14450Sstevel@tonic-gate print "File number (1 .. $nfiles): "; 14460Sstevel@tonic-gate chomp($fnum = <STDIN>); 14470Sstevel@tonic-gate if ($fnum < 1 || $fnum > $nfiles) { 14480Sstevel@tonic-gate print "Unknown file (must be 1 to $nfiles).\n"; 14490Sstevel@tonic-gate next; 14500Sstevel@tonic-gate } 14510Sstevel@tonic-gate $fnum--; 14520Sstevel@tonic-gate } 14530Sstevel@tonic-gate if ($ans == 5) { 14540Sstevel@tonic-gate print "Current name is $allfiles[$fnum][0]\n"; 14550Sstevel@tonic-gate print "New name: "; 14560Sstevel@tonic-gate chomp($fname = <STDIN>); 14570Sstevel@tonic-gate print("Unchanged\n"), next if $fname eq ""; 14580Sstevel@tonic-gate $allfiles[$fnum][0] = $fname; 14590Sstevel@tonic-gate } 14600Sstevel@tonic-gate if ($deleted[$fnum]) { 14610Sstevel@tonic-gate if (yesno("File " . $fnum+1 . 14620Sstevel@tonic-gate " ($allfiles[$fnum][0]) is deleted; undelete",1)) { 14630Sstevel@tonic-gate undef $deleted[$fnum]; 14640Sstevel@tonic-gate } 14650Sstevel@tonic-gate next; 14660Sstevel@tonic-gate } 14670Sstevel@tonic-gate if ($ans == 1) { 14680Sstevel@tonic-gate print $allfiles[$fnum][1]; 14690Sstevel@tonic-gate } elsif ($ans == 2 && $PAGER ne "") { 14700Sstevel@tonic-gate $i = 0; 14710Sstevel@tonic-gate do { 14720Sstevel@tonic-gate if (++$i > 5) { 14730Sstevel@tonic-gate warn "Unable to open temporary file: $!"; 14740Sstevel@tonic-gate undef $tempname; 14750Sstevel@tonic-gate last; 14760Sstevel@tonic-gate } 14770Sstevel@tonic-gate $tempname = tmpnam(); 14780Sstevel@tonic-gate } until sysopen(FH, $tempname, O_RDWR|O_CREAT|O_EXCL); 14790Sstevel@tonic-gate next if !$tempname; 14800Sstevel@tonic-gate print FH $allfiles[$fnum][1]; 14810Sstevel@tonic-gate close FH; 14820Sstevel@tonic-gate system($PAGER, $tempname); 14830Sstevel@tonic-gate unlink($tempname) || 14840Sstevel@tonic-gate warn "Trouble removing temporary file: $!"; 14850Sstevel@tonic-gate undef $tempname; 14860Sstevel@tonic-gate } elsif ($ans == 3 && $EDITOR ne "") { 14870Sstevel@tonic-gate $i = 0; 14880Sstevel@tonic-gate do { 14890Sstevel@tonic-gate if (++$i > 5) { 14900Sstevel@tonic-gate warn "Unable to open temporary file: $!"; 14910Sstevel@tonic-gate undef $tempname; 14920Sstevel@tonic-gate last; 14930Sstevel@tonic-gate } 14940Sstevel@tonic-gate $tempname = tmpnam(); 14950Sstevel@tonic-gate } until sysopen(FH, $tempname, O_RDWR|O_CREAT|O_EXCL); 14960Sstevel@tonic-gate next if !$tempname; 14970Sstevel@tonic-gate chown $<, $(, $tempname; 14980Sstevel@tonic-gate print FH $allfiles[$fnum][1]; 14990Sstevel@tonic-gate close FH; 15000Sstevel@tonic-gate $i = system($EDITOR, $tempname); 15010Sstevel@tonic-gate if ($i == 0) { 15020Sstevel@tonic-gate if (open FH, "<" . $tempname) { 15030Sstevel@tonic-gate read FH, $allfiles[$fnum][1], (-s $tempname); 15040Sstevel@tonic-gate close FH; 15050Sstevel@tonic-gate } 15060Sstevel@tonic-gate } else { 15070Sstevel@tonic-gate print "Editor dropped core.\n" if $? & 128; 15080Sstevel@tonic-gate print "Editor terminated on signal ", $? & 127, "\n" 15090Sstevel@tonic-gate if $? & 127; 15100Sstevel@tonic-gate print "Editor returned error ", $? >> 8, "\n" 15110Sstevel@tonic-gate if $? >> 8; 15120Sstevel@tonic-gate } 15130Sstevel@tonic-gate unlink($tempname) || 15140Sstevel@tonic-gate warn "Trouble removing temporary file: $!"; 15150Sstevel@tonic-gate undef $tempname; 15160Sstevel@tonic-gate } elsif ($ans == 4) { 15170Sstevel@tonic-gate $deleted[$fnum] = 1; 15180Sstevel@tonic-gate } 15190Sstevel@tonic-gate } 15200Sstevel@tonic-gate } 15210Sstevel@tonic-gate} 15220Sstevel@tonic-gate 15230Sstevel@tonic-gateprint "\n"; 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate# Interactive part is over. Become real. 15260Sstevel@tonic-gate$( = $); 15270Sstevel@tonic-gate$< = $>; 15280Sstevel@tonic-gate 15290Sstevel@tonic-gateprint "Stopping aspppd\n" if $opt_v; 15300Sstevel@tonic-gatesystem($asctl, "stop") if -x $asctl; 15310Sstevel@tonic-gate 15320Sstevel@tonic-gateprint "Saving all files\n" if $opt_v; 15330Sstevel@tonic-gatefor ($i = 0; $i < $nfiles; $i++) { 15340Sstevel@tonic-gate $filerec = $allfiles[$i]; 15350Sstevel@tonic-gate if ($deleted[$i]) { 15360Sstevel@tonic-gate delete $scriptfiles{$$filerec[0]}; 15370Sstevel@tonic-gate next; 15380Sstevel@tonic-gate } 15390Sstevel@tonic-gate print "Saving $$filerec[0]\n" if $opt_v; 15400Sstevel@tonic-gate $$filerec[0] =~ m+(.*)/+; 15410Sstevel@tonic-gate if ($1 eq "") { 15420Sstevel@tonic-gate # this is ok; just a top level file 15430Sstevel@tonic-gate } elsif (!(-d $1)) { 15440Sstevel@tonic-gate local ($exdir) = $1; 15450Sstevel@tonic-gate while ($exdir && !(-d $exdir)) { 15460Sstevel@tonic-gate $exdir =~ m+(.*)/+; 15470Sstevel@tonic-gate $exdir = $1; 15480Sstevel@tonic-gate } 15490Sstevel@tonic-gate if ($exdir) { 15500Sstevel@tonic-gate local ($dir) = $1; 15510Sstevel@tonic-gate $dir =~ m+$exdir/([^/]*)(.*)+; 15520Sstevel@tonic-gate local ($tomake, $rest) = ($1, $2); 15530Sstevel@tonic-gate mkdir $exdir . "/" . $tomake, 0775; 15540Sstevel@tonic-gate if ($! == ENOSYS) { 15550Sstevel@tonic-gate warn "Unable to make directory $exdir/$tomake; automount point.\n"; 15560Sstevel@tonic-gate next; 15570Sstevel@tonic-gate } 15580Sstevel@tonic-gate if ($! != 0) { 15590Sstevel@tonic-gate warn "Unable to make directory $exdir/$tomake: $!\n"; 15600Sstevel@tonic-gate next; 15610Sstevel@tonic-gate } 15620Sstevel@tonic-gate if (system("mkdir", "-p", $dir) != 0) { 15630Sstevel@tonic-gate warn "Failed to make $dir\n"; 15640Sstevel@tonic-gate next; 15650Sstevel@tonic-gate } 15660Sstevel@tonic-gate } else { 15670Sstevel@tonic-gate warn "$1 doesn't appear to have a useful path.\n"; 15680Sstevel@tonic-gate next; 15690Sstevel@tonic-gate } 15700Sstevel@tonic-gate } 15710Sstevel@tonic-gate undef $fileerr; 15720Sstevel@tonic-gate local ($fname) = $$filerec[0]; 15730Sstevel@tonic-gate if (-e $fname && !$overwrite{$chatfile}) { 15740Sstevel@tonic-gate print "$fname already exists.\n" 15750Sstevel@tonic-gate if (-t STDIN) && (-t STDOUT) && !$opt_n; 15760Sstevel@tonic-gate if (!yesno("Should it be overwritten",$opt_y)) { 15770Sstevel@tonic-gate warn "Using $fname as-is; it may not be correct.\n"; 15780Sstevel@tonic-gate next; 15790Sstevel@tonic-gate } 15800Sstevel@tonic-gate } 15810Sstevel@tonic-gate if (sysopen(OUTFILE, $$filerec[0], O_WRONLY|O_CREAT|O_TRUNC, 0600)) { 15820Sstevel@tonic-gate print OUTFILE $$filerec[1] || ($fileerr = $!); 15830Sstevel@tonic-gate close OUTFILE || ($fileerr = $!); 15840Sstevel@tonic-gate } else { 15850Sstevel@tonic-gate $fileerr = $!; 15860Sstevel@tonic-gate } 15870Sstevel@tonic-gate warn "Unable to write $$filerec[0]: $fileerr\n" if $fileerr; 15880Sstevel@tonic-gate} 15890Sstevel@tonic-gate 15900Sstevel@tonic-gatelocal(@scripts) = keys %scriptfiles; 15910Sstevel@tonic-gateif (@scripts) { 15920Sstevel@tonic-gate print "Making scripts executable\n" if $opt_v; 15930Sstevel@tonic-gate system("chmod", "u+x", @scripts); 15940Sstevel@tonic-gate} 15950Sstevel@tonic-gate 15960Sstevel@tonic-gaterewrite_passwd if exists($scriptfiles{$sedpasswd}); 15970Sstevel@tonic-gate 15980Sstevel@tonic-gate# clean up after a previous translation. 15990Sstevel@tonic-gateunlink $pppdir . "ifconfig" if !$scriptfiles{$pppdir . "ifconfig"}; 16000Sstevel@tonic-gateunlink $pppdir . "demand" if !$scriptfiles{$pppdir . "demand"}; 16010Sstevel@tonic-gate 16020Sstevel@tonic-gate(rename($asfile, $asmoved) || warn "Cannot move $asfile: $!\n") 16030Sstevel@tonic-gate if $aspppcf ne $astemp; 16040Sstevel@tonic-gate 16050Sstevel@tonic-gatesystem($pppdctl, "start") if -x $pppdctl; 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate# use Dumpvalue; 16080Sstevel@tonic-gate# my $dumper = new Dumpvalue; 16090Sstevel@tonic-gate# $dumper->set(globPrint => 1); 16100Sstevel@tonic-gate# $dumper->dumpValue($ifconfig); 1611