17c478bd9Sstevel@tonic-gate#!/usr/bin/perl
27c478bd9Sstevel@tonic-gate
37c478bd9Sstevel@tonic-gate# This utility translates from aspppd configuration to Solaris PPP 4.0
47c478bd9Sstevel@tonic-gate# (or ANU ppp-2.4.0; aka pppd).  It can also revert to previous aspppd
57c478bd9Sstevel@tonic-gate# configuration (discarding the pppd configuration), but does not
67c478bd9Sstevel@tonic-gate# translate new configuration files into old.
77c478bd9Sstevel@tonic-gate#
87c478bd9Sstevel@tonic-gate# This script provides only a suggested translation for your existing
97c478bd9Sstevel@tonic-gate# aspppd configuration.  You will need to evaluate for yourself
107c478bd9Sstevel@tonic-gate# whether the translation is appropriate for your operating
117c478bd9Sstevel@tonic-gate# environment.
127c478bd9Sstevel@tonic-gate
13*36e852a1SRaja Andra# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
14*36e852a1SRaja Andra# Use is subject to license terms.
157c478bd9Sstevel@tonic-gate#
167c478bd9Sstevel@tonic-gate
177c478bd9Sstevel@tonic-gate# Steps in translation:
187c478bd9Sstevel@tonic-gate#	- parse /etc/asppp.cf
19*36e852a1SRaja Andra#	- check for aspppls in /etc/passwd (or NIS)
207c478bd9Sstevel@tonic-gate#	- read in current /etc/ppp/options configuration file
217c478bd9Sstevel@tonic-gate#	- read list of configured serial ports from pmadm
227c478bd9Sstevel@tonic-gate#	- read in UUCP configuration files
237c478bd9Sstevel@tonic-gate#	- create translated configuration
247c478bd9Sstevel@tonic-gate#	- write files back out
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate# Known issues:
277c478bd9Sstevel@tonic-gate#	- translation with point-to-multipoint is incomplete
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gateuse Getopt::Std;
307c478bd9Sstevel@tonic-gateuse Fcntl;
317c478bd9Sstevel@tonic-gateuse POSIX qw(tmpnam ENOSYS);
327c478bd9Sstevel@tonic-gateuse Sys::Hostname;
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate# Secure the path if we're running under RBAC.
357c478bd9Sstevel@tonic-gate$ENV{PATH} = ( "/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/ucb" )
367c478bd9Sstevel@tonic-gate    if $< != $>;
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate# General path names that can be configured.
397c478bd9Sstevel@tonic-gatelocal($rootetc) =	"/etc/";
407c478bd9Sstevel@tonic-gatelocal($passwd) =	$rootetc . "passwd";
417c478bd9Sstevel@tonic-gatelocal($passwdlck) =	$rootetc . ".pwd.lock";
427c478bd9Sstevel@tonic-gatelocal($asfile) =	$rootetc . "asppp.cf";
437c478bd9Sstevel@tonic-gatelocal($astemp) =	$rootetc . "asppp.temp.cf";
447c478bd9Sstevel@tonic-gatelocal($asmoved) =	$rootetc . "asppp.saved.cf";
457c478bd9Sstevel@tonic-gatelocal($uucpdir) =	$rootetc . "uucp/";
467c478bd9Sstevel@tonic-gatelocal($Devices) =	$uucpdir . "Devices";
477c478bd9Sstevel@tonic-gatelocal($Devconfig) =	$uucpdir . "Devconfig";
487c478bd9Sstevel@tonic-gatelocal($Dialers) =	$uucpdir . "Dialers";
497c478bd9Sstevel@tonic-gatelocal($Dialcodes) =	$uucpdir . "Dialcodes";
507c478bd9Sstevel@tonic-gatelocal($Limits) =	$uucpdir . "Limits";
517c478bd9Sstevel@tonic-gatelocal($Sysfiles) =	$uucpdir . "Sysfiles";
527c478bd9Sstevel@tonic-gatelocal($Systems) =	$uucpdir . "Systems";
537c478bd9Sstevel@tonic-gatelocal($pppdir) =	$rootetc . "ppp/";
547c478bd9Sstevel@tonic-gatelocal($options) =	$pppdir . "options";
557c478bd9Sstevel@tonic-gatelocal($ttyprefix) =	$pppdir . "options.";
567c478bd9Sstevel@tonic-gatelocal($peersdir) =	$pppdir . "peers/";
577c478bd9Sstevel@tonic-gatelocal($initd) =		$rootetc . "init.d/";
587c478bd9Sstevel@tonic-gatelocal($asctl) =		$initd . "asppp";
597c478bd9Sstevel@tonic-gatelocal($pppdctl) =	$initd . "pppd";
607c478bd9Sstevel@tonic-gatelocal($sedpasswd) =	"/tmp/sed-passwd";
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate# Fake asppp keyword used to keep track of dial-in paths.
637c478bd9Sstevel@tonic-gatelocal($isdialin) = "-is-dial-in";
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate# Limits and Sysfiles are keyed on "service=".
667c478bd9Sstevel@tonic-gate# Devconfig is keyed on "service=" and "device=".
677c478bd9Sstevel@tonic-gate# Dialcodes, Dialers, Systems, and Devices are single keyword files.
687c478bd9Sstevel@tonic-gate# Devices alone may have multiple entries for a given key.
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate# Internal data structures
717c478bd9Sstevel@tonic-gatelocal(@sysfiles,@limits,@devconfig);
727c478bd9Sstevel@tonic-gatelocal(@sysdefault) = ( "systems=" . $Systems, "dialers=" . $Dialers,
737c478bd9Sstevel@tonic-gate		       "devices=" . $Devices );
747c478bd9Sstevel@tonic-gatelocal(@limitdefault) = ( "max=-1" );
757c478bd9Sstevel@tonic-gatelocal(@devdefault) = ( "pop=", "push=", "connecttime=-1", "expecttime=-1",
767c478bd9Sstevel@tonic-gate		       "msgtime=-1" );
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate# List of keywords for which ifconfig takes an additional parameter.
797c478bd9Sstevel@tonic-gatelocal($ifconfigtakes) = (
807c478bd9Sstevel@tonic-gate	addif => 1,
817c478bd9Sstevel@tonic-gate	removeif => 1,
827c478bd9Sstevel@tonic-gate	auth_algs => 1,
837c478bd9Sstevel@tonic-gate	encr_algs => 1,
847c478bd9Sstevel@tonic-gate	encr_auth_algs => 1,
857c478bd9Sstevel@tonic-gate	broadcast => 1,
867c478bd9Sstevel@tonic-gate	destination => 1,
877c478bd9Sstevel@tonic-gate	index => 1,
887c478bd9Sstevel@tonic-gate	metric => 1,
897c478bd9Sstevel@tonic-gate	modinsert => 1,
907c478bd9Sstevel@tonic-gate	modremove => 1,
917c478bd9Sstevel@tonic-gate	mtu => 1,
927c478bd9Sstevel@tonic-gate	netmask => 1,
937c478bd9Sstevel@tonic-gate	set => 1,
947c478bd9Sstevel@tonic-gate	subnet => 1,
957c478bd9Sstevel@tonic-gate	tdst => 1,
967c478bd9Sstevel@tonic-gate	tsrc => 1,
977c478bd9Sstevel@tonic-gate	wait => 1,
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate# These are keywords, but do not take an additional parameter.
1007c478bd9Sstevel@tonic-gate	ether => 0,
1017c478bd9Sstevel@tonic-gate	inet => 0,
1027c478bd9Sstevel@tonic-gate	inet6 => 0,
1037c478bd9Sstevel@tonic-gate	arp => 0,
1047c478bd9Sstevel@tonic-gate	-arp => 0,
1057c478bd9Sstevel@tonic-gate	auto-revarp => 0,
1067c478bd9Sstevel@tonic-gate	modlist => 0,
1077c478bd9Sstevel@tonic-gate	plumb => 0,
1087c478bd9Sstevel@tonic-gate	unplumb => 0,
1097c478bd9Sstevel@tonic-gate	private => 0,
1107c478bd9Sstevel@tonic-gate	-private => 0,
1117c478bd9Sstevel@tonic-gate	nud => 0,
1127c478bd9Sstevel@tonic-gate	-nud => 0,
1137c478bd9Sstevel@tonic-gate	trailers => 0,
1147c478bd9Sstevel@tonic-gate	-trailers => 0,
1157c478bd9Sstevel@tonic-gate	up => 0,
1167c478bd9Sstevel@tonic-gate	down => 0,
1177c478bd9Sstevel@tonic-gate	xmit => 0,
1187c478bd9Sstevel@tonic-gate	-xmit => 0,
1197c478bd9Sstevel@tonic-gate	auto-dhcp => 0,
1207c478bd9Sstevel@tonic-gate	dhcp => 0,
1217c478bd9Sstevel@tonic-gate	primary => 0,
1227c478bd9Sstevel@tonic-gate	drop => 0,
1237c478bd9Sstevel@tonic-gate	extend => 0,
1247c478bd9Sstevel@tonic-gate	inform => 0,
1257c478bd9Sstevel@tonic-gate	ping => 0,
1267c478bd9Sstevel@tonic-gate	release => 0,
1277c478bd9Sstevel@tonic-gate	start => 0,
1287c478bd9Sstevel@tonic-gate	status => 0
1297c478bd9Sstevel@tonic-gate);
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate# print number of something in English.
1327c478bd9Sstevel@tonic-gatesub nof
1337c478bd9Sstevel@tonic-gate{
1347c478bd9Sstevel@tonic-gate    local($num, $item, @rest) = @_;
1357c478bd9Sstevel@tonic-gate    print "No ", $item, "s", @rest if $num == 0;
1367c478bd9Sstevel@tonic-gate    print "1 ", $item, @rest if $num == 1;
1377c478bd9Sstevel@tonic-gate    print $num, " ", $item, "s", @rest if $num > 1;
1387c478bd9Sstevel@tonic-gate}
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate# ask a yes or no question.
1417c478bd9Sstevel@tonic-gatesub yesno
1427c478bd9Sstevel@tonic-gate{
1437c478bd9Sstevel@tonic-gate    local ($query, $default) = @_;
1447c478bd9Sstevel@tonic-gate    local ($ans, $defans);
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate    return $default unless (-t STDIN) && (-t STDOUT) && !$opt_n;
1477c478bd9Sstevel@tonic-gate    $defans = $default ? "Yn" : "yN";
1487c478bd9Sstevel@tonic-gate    while (1) {
1497c478bd9Sstevel@tonic-gate	print $query, " [", $defans, "]? ";
1507c478bd9Sstevel@tonic-gate	chomp($ans = <STDIN>);
1517c478bd9Sstevel@tonic-gate	return $default unless $ans;
1527c478bd9Sstevel@tonic-gate	return 1 if $ans =~ /^[Yy1Tt]/;
1537c478bd9Sstevel@tonic-gate	return 0 if $ans =~ /^[Nn0Ff]/;
1547c478bd9Sstevel@tonic-gate	print "Please enter 'y' or 'n'.\n";
1557c478bd9Sstevel@tonic-gate    }
1567c478bd9Sstevel@tonic-gate}
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate# Put quotes around a string, if necessary.
1597c478bd9Sstevel@tonic-gate# The tests here aren't perfect -- they think that \\\' isn't an
1607c478bd9Sstevel@tonic-gate# escaped quote -- but they're good enough.
1617c478bd9Sstevel@tonic-gatesub requote
1627c478bd9Sstevel@tonic-gate{
1637c478bd9Sstevel@tonic-gate    local($_) = @_;
1647c478bd9Sstevel@tonic-gate    if (/^$/) {
1657c478bd9Sstevel@tonic-gate	"\"\"";
1667c478bd9Sstevel@tonic-gate    } elsif (/^'/ || /[^\\]'/ || /\\\\'/) {
1677c478bd9Sstevel@tonic-gate# Has unescaped quotes; must use " or redo quoting.
1687c478bd9Sstevel@tonic-gate	if (/^"/ || /[^\\]"/ || /\\\\"/) {
1697c478bd9Sstevel@tonic-gate# Both kinds of quotes; redo the quoting.
1707c478bd9Sstevel@tonic-gate	    s/^"/\\"/;
1717c478bd9Sstevel@tonic-gate	    s/([^\\]|\\\\)"/$1\\"/g;
1727c478bd9Sstevel@tonic-gate	}
1737c478bd9Sstevel@tonic-gate	"\"" . $_ . "\"";
1747c478bd9Sstevel@tonic-gate    } elsif (/^"/ || /[^\\]"/ || /\\\\"/) {
1757c478bd9Sstevel@tonic-gate	"'" . $_ . "'";
1767c478bd9Sstevel@tonic-gate    } elsif (/\s/) {
1777c478bd9Sstevel@tonic-gate	"\"" . $_ . "\"";
1787c478bd9Sstevel@tonic-gate    } else {
1797c478bd9Sstevel@tonic-gate	$_;
1807c478bd9Sstevel@tonic-gate    }
1817c478bd9Sstevel@tonic-gate}
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate# Get a single line from a UUCP configuration file and return as a
1847c478bd9Sstevel@tonic-gate# reference to an array of words.  Removes comments and escapes.
1857c478bd9Sstevel@tonic-gate# (This is a modified version of the standard Perl shellwords function
1867c478bd9Sstevel@tonic-gate# that understands C escape sequences and continuation lines.)
1877c478bd9Sstevel@tonic-gate# Optionally returns lead-in, source text, and trailing component
1887c478bd9Sstevel@tonic-gate# for editing.
1897c478bd9Sstevel@tonic-gatesub uucpline
1907c478bd9Sstevel@tonic-gate{
1917c478bd9Sstevel@tonic-gate    local($input, $file, $triplet) = @_;
1927c478bd9Sstevel@tonic-gate    local(@words,$snippet,$field,$havefield,$cont,@triparray,$maytrail);
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate    $cont = "";
1957c478bd9Sstevel@tonic-gate    $maytrail = "";
1967c478bd9Sstevel@tonic-gate    while (<$input>) {
1977c478bd9Sstevel@tonic-gate	# remove leading whitespace
1987c478bd9Sstevel@tonic-gate	if (s/^(\s+)//) {
1997c478bd9Sstevel@tonic-gate	    $maytrail .= $1;
2007c478bd9Sstevel@tonic-gate	}
2017c478bd9Sstevel@tonic-gate	if ($cont eq "") {
2027c478bd9Sstevel@tonic-gate	    if (s/^(\#(.|\n)*)$//) {
2037c478bd9Sstevel@tonic-gate		$triparray[0] .= $maytrail . $1;
2047c478bd9Sstevel@tonic-gate		$maytrail = "";
2057c478bd9Sstevel@tonic-gate		next;
2067c478bd9Sstevel@tonic-gate	    }
2077c478bd9Sstevel@tonic-gate	    if (s/^(\\?\n?)$//) {
2087c478bd9Sstevel@tonic-gate		$triparray[0] .= $maytrail . $1;
2097c478bd9Sstevel@tonic-gate		$maytrail = "";
2107c478bd9Sstevel@tonic-gate		next;
2117c478bd9Sstevel@tonic-gate	    }
2127c478bd9Sstevel@tonic-gate	    $triparray[0] .= $maytrail;
2137c478bd9Sstevel@tonic-gate	    $maytrail = "";
2147c478bd9Sstevel@tonic-gate	}
2157c478bd9Sstevel@tonic-gate	$snippet = $_;
2167c478bd9Sstevel@tonic-gate	if (s/^(([^\#\\]|\\.)*)\\\n$//) {
2177c478bd9Sstevel@tonic-gate	    $maytrail .= $snippet;
2187c478bd9Sstevel@tonic-gate	    $cont .= $1;
2197c478bd9Sstevel@tonic-gate	    next;
2207c478bd9Sstevel@tonic-gate	}
2217c478bd9Sstevel@tonic-gate	if (/^(([^\\\#]|\\[^\#])*)(\#?(.|\n)*)$/) {
2227c478bd9Sstevel@tonic-gate	    $_ = $maytrail . $1;
2237c478bd9Sstevel@tonic-gate	    $maytrail = $3;
2247c478bd9Sstevel@tonic-gate	    if (s/((\s|\n)*)$//) {
2257c478bd9Sstevel@tonic-gate		$maytrail = $1 . $maytrail;
2267c478bd9Sstevel@tonic-gate	    }
2277c478bd9Sstevel@tonic-gate	    $triparray[1] = $_;
2287c478bd9Sstevel@tonic-gate	}
2297c478bd9Sstevel@tonic-gate	$_ = $cont . $snippet;
2307c478bd9Sstevel@tonic-gate	$cont = "";
2317c478bd9Sstevel@tonic-gate	s/\n$//;
2327c478bd9Sstevel@tonic-gate	while ($_ ne '') {
2337c478bd9Sstevel@tonic-gate	    for (;;) {
2347c478bd9Sstevel@tonic-gate		if (s/^#.*//) {
2357c478bd9Sstevel@tonic-gate		    last;
2367c478bd9Sstevel@tonic-gate		} elsif (s/^"(([^"\\]|\\.)*)"//) {
2377c478bd9Sstevel@tonic-gate		    $snippet = $1;
2387c478bd9Sstevel@tonic-gate		} elsif (s/^"//) {
2397c478bd9Sstevel@tonic-gate		    warn "Unmatched double quote in $file: \"$_\n";
2407c478bd9Sstevel@tonic-gate		} elsif (s/^'(([^'\\]|\\.)*)'//) {
2417c478bd9Sstevel@tonic-gate		    $snippet = $1;
2427c478bd9Sstevel@tonic-gate		} elsif (s/^'//) {
2437c478bd9Sstevel@tonic-gate		    warn "Unmatched single quote in $file: '$_\n";
2447c478bd9Sstevel@tonic-gate		} elsif (s/^\\s//) {
2457c478bd9Sstevel@tonic-gate# \s works in chat, but not in the pppd option files
2467c478bd9Sstevel@tonic-gate		    $snippet = " ";
2477c478bd9Sstevel@tonic-gate		} elsif (s/^(\\.)//) {
2487c478bd9Sstevel@tonic-gate		    $snippet = $1;
2497c478bd9Sstevel@tonic-gate		} elsif (s/^([^\s\\'"#]+)//) {
2507c478bd9Sstevel@tonic-gate		    $snippet = $1;
2517c478bd9Sstevel@tonic-gate		} else {
2527c478bd9Sstevel@tonic-gate		    s/^\s+//;
2537c478bd9Sstevel@tonic-gate		    last;
2547c478bd9Sstevel@tonic-gate		}
2557c478bd9Sstevel@tonic-gate		$havefield = 1;
2567c478bd9Sstevel@tonic-gate		$field .= $snippet;
2577c478bd9Sstevel@tonic-gate	    }
2587c478bd9Sstevel@tonic-gate	    push(@words, $field) if $havefield;
2597c478bd9Sstevel@tonic-gate	    $havefield = 0;
2607c478bd9Sstevel@tonic-gate	    $field = '';
2617c478bd9Sstevel@tonic-gate	}
2627c478bd9Sstevel@tonic-gate	last;
2637c478bd9Sstevel@tonic-gate    }
2647c478bd9Sstevel@tonic-gate    $triparray[2] .= $maytrail;
2657c478bd9Sstevel@tonic-gate    @$triplet = @triparray;
2667c478bd9Sstevel@tonic-gate    warn "Bad continuation line in $file: $cont\n" if $cont ne '';
2677c478bd9Sstevel@tonic-gate    \@words;
2687c478bd9Sstevel@tonic-gate}
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate# Given a logical UUCP file name, return a list of all of the files
2717c478bd9Sstevel@tonic-gate# that should be read.
2727c478bd9Sstevel@tonic-gatesub uucpfiles
2737c478bd9Sstevel@tonic-gate{
2747c478bd9Sstevel@tonic-gate    local ($file) = @_;
2757c478bd9Sstevel@tonic-gate    local (@flist, $value) = ();
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate    for $value (@sysfiles, @sysdefault) {
2787c478bd9Sstevel@tonic-gate	if ($value =~ /^$file=/i) {
2797c478bd9Sstevel@tonic-gate	    $value =~ s/^$file=//i;
2807c478bd9Sstevel@tonic-gate	    for $file (split /:/, $value) {
2817c478bd9Sstevel@tonic-gate		$file = $uucpdir . $file if $file !~ /^\//;
2827c478bd9Sstevel@tonic-gate		push @flist, $file;
2837c478bd9Sstevel@tonic-gate	    }
2847c478bd9Sstevel@tonic-gate	    last;
2857c478bd9Sstevel@tonic-gate	}
2867c478bd9Sstevel@tonic-gate    }
2877c478bd9Sstevel@tonic-gate    @flist;
2887c478bd9Sstevel@tonic-gate}
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate# Given a file name and some key words, parse the contents of the file
2917c478bd9Sstevel@tonic-gate# and return a reference to a hash constructed from this.  All keys
2927c478bd9Sstevel@tonic-gate# except the last must match exactly.  The last is used to order the
2937c478bd9Sstevel@tonic-gate# hash.
2947c478bd9Sstevel@tonic-gatesub uucpkeyfile
2957c478bd9Sstevel@tonic-gate{
2967c478bd9Sstevel@tonic-gate    local($file,@keylist) = @_;
2977c478bd9Sstevel@tonic-gate    local($lastkey,$keyval,$words,$i,$flag,%byservice);
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate    open(SVCFILE, '<' . $file) || return undef;
3007c478bd9Sstevel@tonic-gate    $lastkey = pop @keylist;
3017c478bd9Sstevel@tonic-gate    while (@{$words = uucpline(SVCFILE, $file)}) {
3027c478bd9Sstevel@tonic-gate	$flag = 1;
3037c478bd9Sstevel@tonic-gate	foreach $keyval (@keylist) {
3047c478bd9Sstevel@tonic-gate	    $flag = 0;
3057c478bd9Sstevel@tonic-gate	    $i = 0;
3067c478bd9Sstevel@tonic-gate	    while ($i < @$words) {
3077c478bd9Sstevel@tonic-gate		if ($$words[$i] eq $keyval) {
3087c478bd9Sstevel@tonic-gate		    splice @$words, $i, 1;
3097c478bd9Sstevel@tonic-gate		    $flag = 1;
3107c478bd9Sstevel@tonic-gate		    last;
3117c478bd9Sstevel@tonic-gate		}
3127c478bd9Sstevel@tonic-gate		$i++;
3137c478bd9Sstevel@tonic-gate	    }
3147c478bd9Sstevel@tonic-gate	    last unless $flag;
3157c478bd9Sstevel@tonic-gate	}
3167c478bd9Sstevel@tonic-gate	next unless $flag;
3177c478bd9Sstevel@tonic-gate	foreach $i (0 .. @{$words}) {
3187c478bd9Sstevel@tonic-gate	    if (@{$words}[$i] =~ /^$lastkey(.*)/i) {
3197c478bd9Sstevel@tonic-gate		splice @{$words}, $i, 1;
3207c478bd9Sstevel@tonic-gate		$byservice{$1} = $words;
3217c478bd9Sstevel@tonic-gate		last;
3227c478bd9Sstevel@tonic-gate	    }
3237c478bd9Sstevel@tonic-gate	}
3247c478bd9Sstevel@tonic-gate    }
3257c478bd9Sstevel@tonic-gate    close SVCFILE;
3267c478bd9Sstevel@tonic-gate    \%byservice;
3277c478bd9Sstevel@tonic-gate}
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate# This reads a UUCP file that is keyed on the first token on each
3307c478bd9Sstevel@tonic-gate# line.  Duplicates are not permitted; the first encountered is used
3317c478bd9Sstevel@tonic-gate# and the rest are silently discarded.  A hash indexed on the first
3327c478bd9Sstevel@tonic-gate# token and containing an array of tokens in each bucket is returned.
3337c478bd9Sstevel@tonic-gate# Used for Dialcodes, Dialers, and Systems.
3347c478bd9Sstevel@tonic-gatesub uucpposfiles
3357c478bd9Sstevel@tonic-gate{
3367c478bd9Sstevel@tonic-gate    local(@files) = @_;
3377c478bd9Sstevel@tonic-gate    local($keyval,$words,%keyeddata);
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate    foreach $file (@files) {
3407c478bd9Sstevel@tonic-gate	if (!open(POSFILE, '<' . $file)) {
3417c478bd9Sstevel@tonic-gate	    warn "$file: $!\n";
3427c478bd9Sstevel@tonic-gate	    next;
3437c478bd9Sstevel@tonic-gate	}
3447c478bd9Sstevel@tonic-gate	while (@{$words = uucpline(POSFILE, $file)}) {
3457c478bd9Sstevel@tonic-gate	    $keyval = shift @{$words};
3467c478bd9Sstevel@tonic-gate	    next if $keyeddata{$keyval};
3477c478bd9Sstevel@tonic-gate	    $keyeddata{$keyval} = $words;
3487c478bd9Sstevel@tonic-gate	}
3497c478bd9Sstevel@tonic-gate	close POSFILE;
3507c478bd9Sstevel@tonic-gate    }
3517c478bd9Sstevel@tonic-gate    \%keyeddata;
3527c478bd9Sstevel@tonic-gate}
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate# This reads a UUCP file that is keyed on the first token on each line
3557c478bd9Sstevel@tonic-gate# and may have duplicate entries.  Each entry of the hash contains an
3567c478bd9Sstevel@tonic-gate# array.  Each entry of that array points to an array of tokens
3577c478bd9Sstevel@tonic-gate# representing one parsed line.  Used for the Devices file.
3587c478bd9Sstevel@tonic-gatesub uucpdevices
3597c478bd9Sstevel@tonic-gate{
3607c478bd9Sstevel@tonic-gate    local(@files) = @_;
3617c478bd9Sstevel@tonic-gate    local($keyval,$words,%keyeddata);
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate    foreach $file (@files) {
3647c478bd9Sstevel@tonic-gate	if (!open(POSFILE, '<' . $file)) {
3657c478bd9Sstevel@tonic-gate	    warn "$file: $!\n";
3667c478bd9Sstevel@tonic-gate	    next;
3677c478bd9Sstevel@tonic-gate	}
3687c478bd9Sstevel@tonic-gate	while (@{$words = uucpline(POSFILE, $file)}) {
3697c478bd9Sstevel@tonic-gate	    $keyval = shift @{$words};
3707c478bd9Sstevel@tonic-gate	    push @{$keyeddata{$keyval}}, $words;
3717c478bd9Sstevel@tonic-gate	}
3727c478bd9Sstevel@tonic-gate	close POSFILE;
3737c478bd9Sstevel@tonic-gate    }
3747c478bd9Sstevel@tonic-gate    \%keyeddata;
3757c478bd9Sstevel@tonic-gate}
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate# For a path defined in asppp.cf, copy over defaults, validate the
3787c478bd9Sstevel@tonic-gate# required options, and save in the hash to be returned.
3797c478bd9Sstevel@tonic-gatesub savepath
3807c478bd9Sstevel@tonic-gate{
3817c478bd9Sstevel@tonic-gate    local($paths, $options, $defref) = @_;
3827c478bd9Sstevel@tonic-gate    local($peer,$intf);
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate    return if $options == $defref;
3857c478bd9Sstevel@tonic-gate    foreach $key (keys %$defref) {
3867c478bd9Sstevel@tonic-gate	$$options{$key} = $$defref{$key} unless defined($$options{$key});
3877c478bd9Sstevel@tonic-gate    }
3887c478bd9Sstevel@tonic-gate    $peer = $$options{"peer_system_name"};
3897c478bd9Sstevel@tonic-gate    warn("Discarded path with no peer system name.\n"), return
3907c478bd9Sstevel@tonic-gate	unless defined($peer);
3917c478bd9Sstevel@tonic-gate    $intf = $$options{"interface"};
3927c478bd9Sstevel@tonic-gate    warn("Missing interface on path to peer \"$peer\".\n"), return
3937c478bd9Sstevel@tonic-gate	unless defined($intf);
3947c478bd9Sstevel@tonic-gate    warn("Bad interface $intf on path to peer \"$peer\".\n"), return
3957c478bd9Sstevel@tonic-gate	unless $intf =~ /^ipd([0-9]+|ptp[0-9]+|ptp\*)$/;
3967c478bd9Sstevel@tonic-gate    warn("Missing peer IP address for point-to-multipoint path to \"",
3977c478bd9Sstevel@tonic-gate	$peer, "\".\n"), return
3987c478bd9Sstevel@tonic-gate	if $intf =~ /^ipd[0-9]+$/ && !defined($$options{"peer_ip_address"});
3997c478bd9Sstevel@tonic-gate    warn "Multiple definitions of path to peer \"$peer\".\n",
4007c478bd9Sstevel@tonic-gate	if defined($paths{$peer});
4017c478bd9Sstevel@tonic-gate    warn "Odd version number ", $$options{"version"},
4027c478bd9Sstevel@tonic-gate	" encountered in path to peer \"", $peer, "\" (ignored).\n"
4037c478bd9Sstevel@tonic-gate	if defined($$options{"version"}) && $$options{"version"} != 1;
4047c478bd9Sstevel@tonic-gate    $paths{$peer} = $options;
4057c478bd9Sstevel@tonic-gate}
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate# Parse through asppp.cf. Unlike the UUCP files, lines don't matter
4087c478bd9Sstevel@tonic-gate# here.  The parsing is modal, with "path" introducing a PPP session
4097c478bd9Sstevel@tonic-gate# description and "defaults" reverting back to global definitions.
4107c478bd9Sstevel@tonic-gatesub readaspppcf
4117c478bd9Sstevel@tonic-gate{
4127c478bd9Sstevel@tonic-gate    local($aspppcf) = @_;
4137c478bd9Sstevel@tonic-gate    local(%aspppdkey) = (
4147c478bd9Sstevel@tonic-gate	chap_name		=> 1,
4157c478bd9Sstevel@tonic-gate	chap_peer_secret	=> 1,
4167c478bd9Sstevel@tonic-gate	chap_peer_name		=> 1,
4177c478bd9Sstevel@tonic-gate	chap_secret		=> 1,
4187c478bd9Sstevel@tonic-gate	debug_level		=> 1,
4197c478bd9Sstevel@tonic-gate	default_route		=> 0,
4207c478bd9Sstevel@tonic-gate	ifconfig		=> -1,
4217c478bd9Sstevel@tonic-gate	inactivity_timeout	=> 1,
4227c478bd9Sstevel@tonic-gate	interface		=> 1,
4237c478bd9Sstevel@tonic-gate# sic; aspppd is seriously confused!  ACCM isn't in IPCP.
4247c478bd9Sstevel@tonic-gate	ipcp_async_map		=> 1,
4257c478bd9Sstevel@tonic-gate	ipcp_compression	=> 1,
4267c478bd9Sstevel@tonic-gate	lcp_compression		=> 1,
4277c478bd9Sstevel@tonic-gate	lcp_mru			=> 1,
4287c478bd9Sstevel@tonic-gate	negotiate_address	=> 1,
4297c478bd9Sstevel@tonic-gate	pap_id			=> 1,
4307c478bd9Sstevel@tonic-gate	pap_password		=> 1,
4317c478bd9Sstevel@tonic-gate	pap_peer_id		=> 1,
4327c478bd9Sstevel@tonic-gate	pap_peer_password	=> 1,
4337c478bd9Sstevel@tonic-gate	peer_ip_address		=> 1,
4347c478bd9Sstevel@tonic-gate	peer_system_name	=> 1,
4357c478bd9Sstevel@tonic-gate	require_authentication	=> 2,
4367c478bd9Sstevel@tonic-gate	version			=> 1,
4377c478bd9Sstevel@tonic-gate	will_do_authentication	=> 2
4387c478bd9Sstevel@tonic-gate    );
4397c478bd9Sstevel@tonic-gate    local($words,$word,$prevword,$i,$errors,%defaults,%ifconfig,%paths);
4407c478bd9Sstevel@tonic-gate    local($options);
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate    open ASPPPD, "<" . $aspppcf || die "$aspppcf: $!\n";
4437c478bd9Sstevel@tonic-gate    print "Reading configuration from $aspppcf\n" if $opt_v;
4447c478bd9Sstevel@tonic-gate    $defaults{inactivity_timeout} = 120;
4457c478bd9Sstevel@tonic-gate    $defaults{ipcp_compression} = "vj";
4467c478bd9Sstevel@tonic-gate    $defaults{lcp_compression} = "on";
4477c478bd9Sstevel@tonic-gate    $options = \%defaults;
4487c478bd9Sstevel@tonic-gate    while (@{$words = uucpline(ASPPPD, $aspppcf)}) {
4497c478bd9Sstevel@tonic-gate	if ($$words[0] =~ /^ifconfig$/i) {
4507c478bd9Sstevel@tonic-gate	    warn "$prevword with missing argument ignored.\n"
4517c478bd9Sstevel@tonic-gate		if defined($prevword);
4527c478bd9Sstevel@tonic-gate	    undef $prevword;
4537c478bd9Sstevel@tonic-gate	    shift @$words;	# discard 'ifconfig' keyword
4547c478bd9Sstevel@tonic-gate	    $word = shift @$words;
4557c478bd9Sstevel@tonic-gate	    warn("Bad interface on ifconfig $word.\n"), next
4567c478bd9Sstevel@tonic-gate		unless $word =~ /^ipd([0-9]+|ptp[0-9]+)$/;
4577c478bd9Sstevel@tonic-gate	    $ifconfig{$word} = \@$words;
4587c478bd9Sstevel@tonic-gate	    next;
4597c478bd9Sstevel@tonic-gate	}
4607c478bd9Sstevel@tonic-gate	unshift @{$words}, $prevword if defined($prevword);
4617c478bd9Sstevel@tonic-gate	undef $prevword;
4627c478bd9Sstevel@tonic-gate	while ($word = lc(shift @{$words})) {
4637c478bd9Sstevel@tonic-gate	    $_ = $word;
4647c478bd9Sstevel@tonic-gate	    if (/^defaults$/i) {
4657c478bd9Sstevel@tonic-gate		savepath(\%paths, $options, \%defaults);
4667c478bd9Sstevel@tonic-gate		$options = \%defaults;
4677c478bd9Sstevel@tonic-gate		next ;
4687c478bd9Sstevel@tonic-gate	    }
4697c478bd9Sstevel@tonic-gate	    if (/^path$/i) {
4707c478bd9Sstevel@tonic-gate		local(%pathopts);
4717c478bd9Sstevel@tonic-gate		savepath(\%paths, $options, \%defaults);
4727c478bd9Sstevel@tonic-gate		$options = \%pathopts;
4737c478bd9Sstevel@tonic-gate		next;
4747c478bd9Sstevel@tonic-gate	    }
4757c478bd9Sstevel@tonic-gate	    if (!defined($i = $aspppdkey{$word})) {
4767c478bd9Sstevel@tonic-gate		die "Too many errors in $aspppcf; aborting.\n"
4777c478bd9Sstevel@tonic-gate		    if ++$errors > 5;
4787c478bd9Sstevel@tonic-gate		warn "Ignoring unknown keyword $word in $aspppcf\n";
4797c478bd9Sstevel@tonic-gate		next;
4807c478bd9Sstevel@tonic-gate	    }
4817c478bd9Sstevel@tonic-gate	    warn("$_ unexpected; remainder of line ignored.\n"),
4827c478bd9Sstevel@tonic-gate		last if $i == -1;
4837c478bd9Sstevel@tonic-gate	    warn("Duplicate $_ in path ignored.\n"), next
4847c478bd9Sstevel@tonic-gate		if $options != \%defaults && defined($$options{$_});
4857c478bd9Sstevel@tonic-gate	    $$options{$_} = 1 if $i == 0;
4867c478bd9Sstevel@tonic-gate	    next if $i == 0;
4877c478bd9Sstevel@tonic-gate	    $prevword = $_, last unless defined($word = shift @{$words});
4887c478bd9Sstevel@tonic-gate	    $$options{$_} = $word if $i == 1;
4897c478bd9Sstevel@tonic-gate	    if ($i == 2) {
4907c478bd9Sstevel@tonic-gate		undef $$options{$_}, next if $word =~ /^off$/;
4917c478bd9Sstevel@tonic-gate		$$options{$_} = $word;
4927c478bd9Sstevel@tonic-gate		if ($word = shift @{$words}) {
4937c478bd9Sstevel@tonic-gate		    if ($word =~ /^(p|ch)ap$/) {
4947c478bd9Sstevel@tonic-gate			$$options{$_} .= " " . $word;
4957c478bd9Sstevel@tonic-gate		    } else {
4967c478bd9Sstevel@tonic-gate			unshift @{$words}, $word;
4977c478bd9Sstevel@tonic-gate		    }
4987c478bd9Sstevel@tonic-gate		}
4997c478bd9Sstevel@tonic-gate	    }
5007c478bd9Sstevel@tonic-gate	}
5017c478bd9Sstevel@tonic-gate    }
5027c478bd9Sstevel@tonic-gate    warn "Odd trailing keyword \"$prevword\" ignored in $aspppcf\n"
5037c478bd9Sstevel@tonic-gate	if $prevword;
5047c478bd9Sstevel@tonic-gate    savepath(\%paths, $options, \%defaults);
5057c478bd9Sstevel@tonic-gate    die "No paths defined for aspppd.\n" if 0+(keys %paths) == 0;
5067c478bd9Sstevel@tonic-gate    die "No interfaces defined for aspppd.\n" if 0+(keys %ifconfig) == 0;
5077c478bd9Sstevel@tonic-gate    if ($opt_v) {
5087c478bd9Sstevel@tonic-gate	nof 0+(keys %paths), "path", " and ";
5097c478bd9Sstevel@tonic-gate	nof 0+(keys %ifconfig), "interface", " defined for aspppd.\n";
5107c478bd9Sstevel@tonic-gate    }
5117c478bd9Sstevel@tonic-gate    close ASPPPD;
5127c478bd9Sstevel@tonic-gate    ( \%ifconfig, \%paths );
5137c478bd9Sstevel@tonic-gate}
5147c478bd9Sstevel@tonic-gate
515*36e852a1SRaja Andra# Read /etc/passwd (or NIS) and return hash of users for whom
5167c478bd9Sstevel@tonic-gate# the default shell is aspppls.  Each hash entry contains the user's
5177c478bd9Sstevel@tonic-gate# home directory path.
5187c478bd9Sstevel@tonic-gatesub readpasswd
5197c478bd9Sstevel@tonic-gate{
5207c478bd9Sstevel@tonic-gate    local(%users,@pwe);
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate    setpwent();
5237c478bd9Sstevel@tonic-gate    while (@pwe = getpwent()) {
5247c478bd9Sstevel@tonic-gate	$users{$pwe[0]} = $pwe[7] if $pwe[8] =~ /\/aspppls$/;
5257c478bd9Sstevel@tonic-gate    }
5267c478bd9Sstevel@tonic-gate    endpwent();
5277c478bd9Sstevel@tonic-gate    nof 0+(keys %users), "aspppd dial in user", " found.\n"
5287c478bd9Sstevel@tonic-gate	if $opt_v;
5297c478bd9Sstevel@tonic-gate    \%users;
5307c478bd9Sstevel@tonic-gate}
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate# Parse through pmadm output to find enabled serial ports.
5337c478bd9Sstevel@tonic-gate# Field 9 has 'I' (modem dial-out only or initialize only), 'b'
5347c478bd9Sstevel@tonic-gate# (bidirectional) or is blank (modem dial-in only or terminal-hardwired).
5357c478bd9Sstevel@tonic-gate# For that latter case, field 18 (software-carrier) has 'y'.
5367c478bd9Sstevel@tonic-gate# Field 3 has 'x' if disabled.
5377c478bd9Sstevel@tonic-gatesub getserialports
5387c478bd9Sstevel@tonic-gate{
5397c478bd9Sstevel@tonic-gate    local(%dialin, %dialout);
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate    open PMADM, "pmadm -L|" || (warn "pmadm: $!\n", return undef);
5427c478bd9Sstevel@tonic-gate    while (<PMADM>) {
5437c478bd9Sstevel@tonic-gate	split /:/;
5447c478bd9Sstevel@tonic-gate	if ($_[3] !~ /x/) {
5457c478bd9Sstevel@tonic-gate	    $dialin{$_[2]} = $_[8] if $_[9] ne "I";
5467c478bd9Sstevel@tonic-gate	    $dialout{$_[2]} = $_[8] if $_[9] ne "";
5477c478bd9Sstevel@tonic-gate	}
5487c478bd9Sstevel@tonic-gate    }
5497c478bd9Sstevel@tonic-gate    close PMADM;
5507c478bd9Sstevel@tonic-gate    ( \%dialin, \%dialout );
5517c478bd9Sstevel@tonic-gate}
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate# Convert an ifconfig statement into a local and remote address pair.
5547c478bd9Sstevel@tonic-gatesub ifconf_addr
5557c478bd9Sstevel@tonic-gate{
5567c478bd9Sstevel@tonic-gate    local($ifconf) = @_;
5577c478bd9Sstevel@tonic-gate    local($arg, $narg, $lcladdr, $remaddr);
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate    shift @$ifconf;	# lose the interface name
5607c478bd9Sstevel@tonic-gate    while (@$ifconf) {
5617c478bd9Sstevel@tonic-gate	local($arg, $narg);
5627c478bd9Sstevel@tonic-gate	$arg = shift @$ifconf;
5637c478bd9Sstevel@tonic-gate	$narg = shift @$ifconf if $ifconfigtakes{$arg};
5647c478bd9Sstevel@tonic-gate	if (exists($ifconfigtakes{$arg})) {
5657c478bd9Sstevel@tonic-gate	    if ($arg eq "set") {
5667c478bd9Sstevel@tonic-gate		$lcladdr = $narg;
5677c478bd9Sstevel@tonic-gate	    } elsif ($arg eq "destination") {
5687c478bd9Sstevel@tonic-gate		$remaddr = $narg;
5697c478bd9Sstevel@tonic-gate	    }
5707c478bd9Sstevel@tonic-gate	} elsif (!defined($lcladdr)) {
5717c478bd9Sstevel@tonic-gate	    $lcladdr = $arg;
5727c478bd9Sstevel@tonic-gate	} elsif (!defined($remaddr)) {
5737c478bd9Sstevel@tonic-gate	    $remaddr = $arg;
5747c478bd9Sstevel@tonic-gate	}
5757c478bd9Sstevel@tonic-gate    }
5767c478bd9Sstevel@tonic-gate    ( $lcladdr, $remaddr );
5777c478bd9Sstevel@tonic-gate}
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate# Convert a hash of aspppd options into an array of pppd options.  The
5807c478bd9Sstevel@tonic-gate# third argument ($chatpath) is undef for dial-in or a path to the
5817c478bd9Sstevel@tonic-gate# chat script file otherwise.
5827c478bd9Sstevel@tonic-gatesub convert_options
5837c478bd9Sstevel@tonic-gate{
5847c478bd9Sstevel@tonic-gate    local ($pppdargs, $opts, $chatpath, $user) = @_;
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate# Do the pppd option conversions.
5877c478bd9Sstevel@tonic-gate    push(@$pppdargs, "defaultroute") if $$opts{default_route};
5887c478bd9Sstevel@tonic-gate    push(@$pppdargs, "idle " . $$opts{inactivity_timeout})
5897c478bd9Sstevel@tonic-gate	if $$opts{inactivity_timeout} != 0;
5907c478bd9Sstevel@tonic-gate    push(@$pppdargs, "asyncmap " . $$opts{ipcp_async_map})
5917c478bd9Sstevel@tonic-gate	if $$opts{ipcp_async_map};
5927c478bd9Sstevel@tonic-gate    push(@$pppdargs, "novj") if !$$opts{ipcp_compression};
5937c478bd9Sstevel@tonic-gate    local($peer);
5947c478bd9Sstevel@tonic-gate    if ($$opts{require_authentication}) {
5957c478bd9Sstevel@tonic-gate	local (@authopts);
5967c478bd9Sstevel@tonic-gate	if ($$opts{require_authentication} =~ /chap/) {
5977c478bd9Sstevel@tonic-gate	    push(@authopts, "require-chap");
5987c478bd9Sstevel@tonic-gate	    $peer = $$opts{chap_peer_name};
5997c478bd9Sstevel@tonic-gate	} else {
6007c478bd9Sstevel@tonic-gate	    push(@authopts, "require-pap");
6017c478bd9Sstevel@tonic-gate	    $peer = $$opts{pap_peer_id};
6027c478bd9Sstevel@tonic-gate	}
6037c478bd9Sstevel@tonic-gate	push(@authopts, "remotename " . requote($peer)) if $peer;
6047c478bd9Sstevel@tonic-gate	push(@authopts, "auth");
6057c478bd9Sstevel@tonic-gate	if ($chatpath) {
6067c478bd9Sstevel@tonic-gate	    push(@$pppdargs, @authopts);
6077c478bd9Sstevel@tonic-gate	} elsif ($dialin_auth == 3) {
6087c478bd9Sstevel@tonic-gate# mixed authentication; must use wrapper script.
6097c478bd9Sstevel@tonic-gate	    local($sfile) = $pppdir . "dial-in." . $user;
6107c478bd9Sstevel@tonic-gate	    $scriptfiles{$sfile}  = "#!/bin/sh\n";
6117c478bd9Sstevel@tonic-gate	    $scriptfiles{$sfile} .= "exec /usr/bin/pppd @authopts\n";
6127c478bd9Sstevel@tonic-gate	    $dialinshell{$user} = $sfile;
6137c478bd9Sstevel@tonic-gate	}
6147c478bd9Sstevel@tonic-gate    } elsif ($dialin_auth < 2) {
6157c478bd9Sstevel@tonic-gate	push(@$pppdargs, "noauth");
6167c478bd9Sstevel@tonic-gate    }
6177c478bd9Sstevel@tonic-gate    push(@$pppdargs, "noaccomp nopcomp") if !$$opts{lcp_compression};
6187c478bd9Sstevel@tonic-gate    push(@$pppdargs, "mru " . $$opts{lcp_mru}) if $$opts{lcp_mru};
6197c478bd9Sstevel@tonic-gate    push(@$pppdargs, "noipdefault ipcp-accept-local")
6207c478bd9Sstevel@tonic-gate	if $$opts{negotiate_address};
6217c478bd9Sstevel@tonic-gate    local($myname,$csecret,$psecret,$passopt);
6227c478bd9Sstevel@tonic-gate    if ($$opts{will_do_authentication} =~ /chap/i) {
6237c478bd9Sstevel@tonic-gate	$myname = $$opts{chap_name};
6247c478bd9Sstevel@tonic-gate	$csecret = $$opts{chap_secret};
6257c478bd9Sstevel@tonic-gate    }
6267c478bd9Sstevel@tonic-gate    $myname = "" if !$myname;
6277c478bd9Sstevel@tonic-gate    if ($$opts{will_do_authentication} =~ /pap/i) {
6287c478bd9Sstevel@tonic-gate	if ($myname ne "" && $$opts{pap_id} ne "" &&
6297c478bd9Sstevel@tonic-gate	    $myname ne $$opts{pap_id}) {
6307c478bd9Sstevel@tonic-gate	    warn "pppd cannot have separate local names for PAP and CHAP; using CHAP name:\n";
6317c478bd9Sstevel@tonic-gate	    warn "\t\"$myname\"\n";
6327c478bd9Sstevel@tonic-gate	} else {
6337c478bd9Sstevel@tonic-gate	    $myname = $$opts{pap_id} if $$opts{pap_id} ne "";
6347c478bd9Sstevel@tonic-gate	}
6357c478bd9Sstevel@tonic-gate	$psecret = $$opts{pap_password};
6367c478bd9Sstevel@tonic-gate    }
6377c478bd9Sstevel@tonic-gate    if ($$opts{will_do_authentication}) {
6387c478bd9Sstevel@tonic-gate	if ($chatpath &&
6397c478bd9Sstevel@tonic-gate	    ($$opts{will_do_authentication} !~ /chap/i ||
6407c478bd9Sstevel@tonic-gate	     $$opts{will_do_authentication} !~ /pap/i ||
6417c478bd9Sstevel@tonic-gate	     $csecret eq $psecret)) {
6427c478bd9Sstevel@tonic-gate	    push(@$pppdargs,
6437c478bd9Sstevel@tonic-gate		"password " . requote($csecret ? $csecret : $psecret));
6447c478bd9Sstevel@tonic-gate	    $passopt = 1;
6457c478bd9Sstevel@tonic-gate	}
6467c478bd9Sstevel@tonic-gate	push @$pppdargs, "user " . requote($myname);
6477c478bd9Sstevel@tonic-gate	push(@$pppdargs, "remotename " . requote($peer))
6487c478bd9Sstevel@tonic-gate	  if $peer && !$$opts{require_authentication};
6497c478bd9Sstevel@tonic-gate    } else {
6507c478bd9Sstevel@tonic-gate	$myname = "NeverAuthenticate";
6517c478bd9Sstevel@tonic-gate    }
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate    push(@$pppdargs, "debug") if $$opts{debug_level} >= 8;
6547c478bd9Sstevel@tonic-gate    push(@$pppdargs, "kdebug 3") if $$opts{debug_level} >= 9;
6557c478bd9Sstevel@tonic-gate    local($lcladdr, $remaddr) = ifconf_addr($$ifconfig{$$opts{interface}});
6567c478bd9Sstevel@tonic-gate    if ($chatpath) {
6577c478bd9Sstevel@tonic-gate	if ($$opts{debug_level} >= 4) {
6587c478bd9Sstevel@tonic-gate	    push(@pppdargs, "connect \"/usr/bin/chat -vf $chatpath\"");
6597c478bd9Sstevel@tonic-gate	} else {
6607c478bd9Sstevel@tonic-gate	    push(@pppdargs, "connect \"/usr/bin/chat -f $chatpath\"");
6617c478bd9Sstevel@tonic-gate	}
6627c478bd9Sstevel@tonic-gate	push(@$pppdargs, "user " . requote($myname));
6637c478bd9Sstevel@tonic-gate	local($str) = $remaddr;
6647c478bd9Sstevel@tonic-gate	$str = $$opts{peer_ip_address} if $$opts{peer_ip_address};
6657c478bd9Sstevel@tonic-gate	push(@$pppdargs, $lcladdr . ":" . $str)
6667c478bd9Sstevel@tonic-gate	    if !$opt_s && ($lcladdr || $str);
6677c478bd9Sstevel@tonic-gate    } else {
6687c478bd9Sstevel@tonic-gate	push(@$pppdargs, "user " . requote($myname))
6697c478bd9Sstevel@tonic-gate	    if $myname eq "NeverAuthenticate";
6707c478bd9Sstevel@tonic-gate    }
6717c478bd9Sstevel@tonic-gate    if ($$opts{interface} && $opt_s) {
6727c478bd9Sstevel@tonic-gate	if ($$opts{interface} =~ /^ipd[0-9]+$/) {
6737c478bd9Sstevel@tonic-gate	    push(@$pppdargs, $lcladdr . ":") if $lcladdr;
6747c478bd9Sstevel@tonic-gate	} elsif ($$opts{interface} =~ /^ipd(|ptp)([0-9]+)$/) {
6757c478bd9Sstevel@tonic-gate	    push(@pppdargs, "unit " . $2);
6767c478bd9Sstevel@tonic-gate	} else {
6777c478bd9Sstevel@tonic-gate	    push(@pppdargs, "plumbed");
6787c478bd9Sstevel@tonic-gate	}
6797c478bd9Sstevel@tonic-gate    }
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate# Convert the secrets
6827c478bd9Sstevel@tonic-gate    if ($chatpath) {
6837c478bd9Sstevel@tonic-gate	$addsecret = "";
6847c478bd9Sstevel@tonic-gate    } elsif ($$opts{peer_ip_address}) {
6857c478bd9Sstevel@tonic-gate	$addsecret = " " . $$opts{peer_ip_address};
6867c478bd9Sstevel@tonic-gate    } else {
6877c478bd9Sstevel@tonic-gate	$addsecret = " *";
6887c478bd9Sstevel@tonic-gate    }
6897c478bd9Sstevel@tonic-gate    if ($$opts{require_authentication}) {
6907c478bd9Sstevel@tonic-gate	local($lclname, $secret, $authf);
6917c478bd9Sstevel@tonic-gate	$lclname = $$opts{will_do_authentication} ? $myname : hostname();
6927c478bd9Sstevel@tonic-gate	if ($$opts{require_authentication} =~ /chap/) {
6937c478bd9Sstevel@tonic-gate	    $secret = $$opts{chap_peer_secret};
6947c478bd9Sstevel@tonic-gate	    $authf = \%chapsecrets;
6957c478bd9Sstevel@tonic-gate	} else {
6967c478bd9Sstevel@tonic-gate	    $secret = $$opts{pap_peer_password};
6977c478bd9Sstevel@tonic-gate	    $authf = \%papsecrets;
6987c478bd9Sstevel@tonic-gate	}
6997c478bd9Sstevel@tonic-gate	${$$authf{$peer}}{$lclname} = requote($secret) . $addsecret;
7007c478bd9Sstevel@tonic-gate    }
7017c478bd9Sstevel@tonic-gate    if ($$opts{will_do_authentication} && !$passopt) {
7027c478bd9Sstevel@tonic-gate	${$chapsecrets{$myname}}{$peer} = requote($csecret) if $csecret;
7037c478bd9Sstevel@tonic-gate	${$papsecrets{$myname}}{$peer} = requote($psecret) if $psecret;
7047c478bd9Sstevel@tonic-gate    }
7057c478bd9Sstevel@tonic-gate}
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate# Translate options for a dial-in user.
7087c478bd9Sstevel@tonic-gatesub translatedialin
7097c478bd9Sstevel@tonic-gate{
7107c478bd9Sstevel@tonic-gate    local($peer) = @_;
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate    $optname = $$dialinusers{$peer};
7137c478bd9Sstevel@tonic-gate    $optname .= "/" if $optname !~ /\/$/;
7147c478bd9Sstevel@tonic-gate    $optname .= ".ppprc";
7157c478bd9Sstevel@tonic-gate    if (exists($optfiles{$optname})) {
7167c478bd9Sstevel@tonic-gate	warn "Home directories of $peer and $optuser{$optname} are the same ($optfiles{$optname}\n";
7177c478bd9Sstevel@tonic-gate	warn "Ignoring configuration for $peer.\n";
7187c478bd9Sstevel@tonic-gate	return;
7197c478bd9Sstevel@tonic-gate    }
7207c478bd9Sstevel@tonic-gate    $optuser{$optname} = $peer;
7217c478bd9Sstevel@tonic-gate    $dialinshell{$peer} = "/usr/bin/pppd";
7227c478bd9Sstevel@tonic-gate    local (@pppdargs);
7237c478bd9Sstevel@tonic-gate    convert_options(\@pppdargs, $$paths{$peer}, undef, $peer);
7247c478bd9Sstevel@tonic-gate    push @pppdargs, "nologfd";
7257c478bd9Sstevel@tonic-gate    $optfiles{$optname} = \@pppdargs;
7267c478bd9Sstevel@tonic-gate}
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate# Translate ifconfig entries in asppp.cf into either an ifconfig
7297c478bd9Sstevel@tonic-gate# script for strict translation or a set of per-port IP addresses
7307c478bd9Sstevel@tonic-gate# for normal translation.  Also translate ipdX interfaces into
7317c478bd9Sstevel@tonic-gate# Ethernet aliases to make routing daemon happy.
7327c478bd9Sstevel@tonic-gatesub translateifconfig
7337c478bd9Sstevel@tonic-gate{
7347c478bd9Sstevel@tonic-gate    local (@ifconfiglist,$cstr,$etherif,$intf,$ifconf,$addstr,$port);
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate    open IFLIST, "/usr/sbin/ifconfig -au4|" || die "cannot run ifconfig: $!\n";
7377c478bd9Sstevel@tonic-gate    while (<IFLIST>) {
7387c478bd9Sstevel@tonic-gate	$etherif = $1 if !$etherif && /^([^:]*).*UP.*BROADCAST/;
7397c478bd9Sstevel@tonic-gate    }
7407c478bd9Sstevel@tonic-gate    close IFLIST;
7417c478bd9Sstevel@tonic-gate    $etherif = $1 if !$etherif && glob("/etc/hostname.*") =~ /[^\.]*.(.*)/;
7427c478bd9Sstevel@tonic-gate    $etherif = $1 if !$etherif && glob("/etc/dhcp.*") =~ /[^\.]*.(.*)/;
7437c478bd9Sstevel@tonic-gate    $etherif = "hme0" if !$etherif;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate    $cstr = "";
7467c478bd9Sstevel@tonic-gate    foreach $intf (keys %$ifconfig) {
7477c478bd9Sstevel@tonic-gate	$ifconf = $$ifconfig{$intf};
7487c478bd9Sstevel@tonic-gate	if ($intf =~ /ipd[0-9]+/) {
7497c478bd9Sstevel@tonic-gate	    shift @$ifconf;
7507c478bd9Sstevel@tonic-gate	    $cstr .= "ifconfig $etherif addif @$ifconf\n";
7517c478bd9Sstevel@tonic-gate	}
7527c478bd9Sstevel@tonic-gate    }
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate    $ndialin = 0+(keys %$dialin);
7557c478bd9Sstevel@tonic-gate    $addstr = "";
7567c478bd9Sstevel@tonic-gate    foreach $intf (keys %downif) {
7577c478bd9Sstevel@tonic-gate	$ifconf = $downif{$intf};
7587c478bd9Sstevel@tonic-gate	if ($intf =~ /ipdptp([0-9]+)/ && --$ndialin >= 0) {
7597c478bd9Sstevel@tonic-gate	    push @ifconfiglist, $ifconf;
7607c478bd9Sstevel@tonic-gate	    $addstr .= "ifconfig sppp" . $1 . " @$ifconf\n";
7617c478bd9Sstevel@tonic-gate	}
7627c478bd9Sstevel@tonic-gate    }
7637c478bd9Sstevel@tonic-gate    if ($ndialin > 0) {
7647c478bd9Sstevel@tonic-gate	if (@ifconfiglist) {
7657c478bd9Sstevel@tonic-gate	    print "Fewer ifconfigs (", $#ifconfiglist+1,
7667c478bd9Sstevel@tonic-gate	    ") than dial-in lines (", $ndialin+$#ifconfiglist+1, ")\n";
7677c478bd9Sstevel@tonic-gate	} else {
7687c478bd9Sstevel@tonic-gate	    print "No ifconfigs for ";
7697c478bd9Sstevel@tonic-gate	    nof $ndialin, "dial-in port", ".\n";
7707c478bd9Sstevel@tonic-gate	}
7717c478bd9Sstevel@tonic-gate    } elsif ($ndialin < 0) {
7727c478bd9Sstevel@tonic-gate	if (@ifconfiglist) {
7737c478bd9Sstevel@tonic-gate	    print "Ignoring ", -$ndialin, " of ";
7747c478bd9Sstevel@tonic-gate	    nof $#ifconfiglist-$ndialin+1, "ifconfig",
7757c478bd9Sstevel@tonic-gate	    " (too few dial-in ports)\n";
7767c478bd9Sstevel@tonic-gate	} else {
7777c478bd9Sstevel@tonic-gate	    print "Ignoring all ";
7787c478bd9Sstevel@tonic-gate	    nof -$ndialin, "ifconfig line", " (no dial-in ports)\n";
7797c478bd9Sstevel@tonic-gate	}
7807c478bd9Sstevel@tonic-gate    }
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate    if ($opt_s) {
7837c478bd9Sstevel@tonic-gate	# Strict translation uses pre-plumbed interfaces.
7847c478bd9Sstevel@tonic-gate	$cstr .= $addstr;
7857c478bd9Sstevel@tonic-gate    } else {
7867c478bd9Sstevel@tonic-gate	foreach $port (values %$dialin) {
7877c478bd9Sstevel@tonic-gate	    last if !@ifconfiglist;
7887c478bd9Sstevel@tonic-gate	    $port =~ s+/dev/++;
7897c478bd9Sstevel@tonic-gate	    $port =~ s+/+.+g;
7907c478bd9Sstevel@tonic-gate	    $optfile = $ttyprefix . $port;
7917c478bd9Sstevel@tonic-gate	    $ifconf = pop @ifconfiglist;
7927c478bd9Sstevel@tonic-gate	    local ($lcladdr, $remaddr) = ifconf_addr($ifconf);
7937c478bd9Sstevel@tonic-gate	    next if !defined($lcladdr) || !defined($remaddr);
7947c478bd9Sstevel@tonic-gate	    local (@pppdargs) = $lcladdr . ":" . $remaddr;
7957c478bd9Sstevel@tonic-gate	    $optfiles{$optfile} = \@pppdargs;
7967c478bd9Sstevel@tonic-gate	}
7977c478bd9Sstevel@tonic-gate    }
7987c478bd9Sstevel@tonic-gate    $scriptfiles{$pppdir . "ifconfig"} = $cstr if $cstr;
7997c478bd9Sstevel@tonic-gate}
8007c478bd9Sstevel@tonic-gate
8017c478bd9Sstevel@tonic-gate# Attempt to modify global passwd file using sed script stored in
8027c478bd9Sstevel@tonic-gate# the $sedpasswd temporary file.
8037c478bd9Sstevel@tonic-gatesub rewrite_passwd
8047c478bd9Sstevel@tonic-gate{
8057c478bd9Sstevel@tonic-gate    print "Updating local passwd file (if any).\n" if $opt_v;
8067c478bd9Sstevel@tonic-gate    if (!sysopen(PWDLCK, $passwdlck, O_WRONLY|O_CREAT, 0600)) {
8077c478bd9Sstevel@tonic-gate	warn "Unable to lock password file: $!\n";
8087c478bd9Sstevel@tonic-gate    } else {
8097c478bd9Sstevel@tonic-gate	$lockstr = pack "ssLLiiLLLL", F_WRLCK, 0, 0, 0, 0, 0, 0, 0, 0, 0;
8107c478bd9Sstevel@tonic-gate	eval {
8117c478bd9Sstevel@tonic-gate	    local $SIG{ARLM} = sub {
8127c478bd9Sstevel@tonic-gate		die "alarm while locking password file\n"
8137c478bd9Sstevel@tonic-gate	    };
8147c478bd9Sstevel@tonic-gate	    alarm 15;
8157c478bd9Sstevel@tonic-gate	    fcntl PWDLCK, F_SETLKW, $lockstr ||
8167c478bd9Sstevel@tonic-gate	      die "cannot lock password file: $!\n";
8177c478bd9Sstevel@tonic-gate	    alarm 0;
8187c478bd9Sstevel@tonic-gate	};
8197c478bd9Sstevel@tonic-gate	if ($@) {
8207c478bd9Sstevel@tonic-gate	    warn $@;
8217c478bd9Sstevel@tonic-gate	} else {
8227c478bd9Sstevel@tonic-gate	    warn "Password update failed.\n"
8237c478bd9Sstevel@tonic-gate	      if (system("sed -f $sedpasswd < $passwd > ${passwd}.new") ||
8247c478bd9Sstevel@tonic-gate		  !(rename "${passwd}.new", $passwd));
8257c478bd9Sstevel@tonic-gate	}
8267c478bd9Sstevel@tonic-gate	$lockstr = pack "ssLLiiLLLL", F_UNLCK, 0, 0, 0, 0, 0, 0, 0, 0, 0;
8277c478bd9Sstevel@tonic-gate	fcntl PWDLCK, F_SETLK, $lockstr;
8287c478bd9Sstevel@tonic-gate	close PWDLCK;
8297c478bd9Sstevel@tonic-gate    }
830*36e852a1SRaja Andra    if (($ypmaster = `/usr/bin/ypwhich 2>/dev/null`) && $? == 0) {
8317c478bd9Sstevel@tonic-gate	$ypmaster =~ /(.*)\n/;
8327c478bd9Sstevel@tonic-gate	($ypmaster) = gethostbyname($1);
8337c478bd9Sstevel@tonic-gate	($thishost) = gethostbyname(hostname);
8347c478bd9Sstevel@tonic-gate	if ($ypmaster eq $thishost) {
8357c478bd9Sstevel@tonic-gate	    system("cd /var/yp && make")
8367c478bd9Sstevel@tonic-gate	      if yesno("Rebuild NIS/YP maps", $opt_y);
8377c478bd9Sstevel@tonic-gate	} else {
8387c478bd9Sstevel@tonic-gate	    warn "Not running on NIS/YP master $1; unable to update user shells\n";
8397c478bd9Sstevel@tonic-gate	    print "Use 'sed -f $sedpasswd <$passwd >${passwd}.new' on the master\n";
8407c478bd9Sstevel@tonic-gate	    print "and then remake the NIS/YP database.\n";
8417c478bd9Sstevel@tonic-gate	    undef $sedpasswd;
8427c478bd9Sstevel@tonic-gate	}
8437c478bd9Sstevel@tonic-gate    }
8447c478bd9Sstevel@tonic-gate    unlink $sedpasswd if $sedpasswd;
8457c478bd9Sstevel@tonic-gate}
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate# Show usage message.
8487c478bd9Sstevel@tonic-gatesub usage
8497c478bd9Sstevel@tonic-gate{
8507c478bd9Sstevel@tonic-gate    print "Usage:\n\n";
8517c478bd9Sstevel@tonic-gate    print "\t$0 [-rsvy]\n\n";
8527c478bd9Sstevel@tonic-gate    print "    -n - non-interactive mode.\n";
8537c478bd9Sstevel@tonic-gate    print "    -r - revert back to aspppd configuration.\n";
8547c478bd9Sstevel@tonic-gate    print "    -s - use strict translation.\n";
8557c478bd9Sstevel@tonic-gate    print "    -v - print more detail of the operations performed.\n";
8567c478bd9Sstevel@tonic-gate    print "    -y - assume 'yes' as default answer where reasonable.\n";
8577c478bd9Sstevel@tonic-gate    exit;
8587c478bd9Sstevel@tonic-gate}
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate# Correct an environment variable so that it points at either a useful
8617c478bd9Sstevel@tonic-gate# executable program, or nothing at all.
8627c478bd9Sstevel@tonic-gatesub fixpath
8637c478bd9Sstevel@tonic-gate{
8647c478bd9Sstevel@tonic-gate    local ($prog, $deflt) = @_;
8657c478bd9Sstevel@tonic-gate
8667c478bd9Sstevel@tonic-gate    $prog = $deflt if $prog eq "";
8677c478bd9Sstevel@tonic-gate    if ($prog !~ /^(\.\/|\/)/) {
8687c478bd9Sstevel@tonic-gate	local ($_) = $ENV{PATH};
8697c478bd9Sstevel@tonic-gate	$_ = "/bin:/usr/bin:/sbin:/usr/sbin" if $_ eq "";
8707c478bd9Sstevel@tonic-gate	split /:/;
8717c478bd9Sstevel@tonic-gate	foreach (@_) {
8727c478bd9Sstevel@tonic-gate	    $prog = $_ . "/" . $prog, last if -x $_ . "/" . $prog;
8737c478bd9Sstevel@tonic-gate	}
8747c478bd9Sstevel@tonic-gate    }
8757c478bd9Sstevel@tonic-gate    $prog = "" if !(-x $prog);
8767c478bd9Sstevel@tonic-gate    $prog;
8777c478bd9Sstevel@tonic-gate}
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gategetopts('nrsvy') || usage;
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gatedie "Need permission to modify system files.\n"
8827c478bd9Sstevel@tonic-gate    unless ($> == 0 || yesno "This script should be run as root.  Continue");
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gateif ($opt_r) {
8857c478bd9Sstevel@tonic-gate    local ($intemp);
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate# Revert to previous configuration.  Just rename the aspppd file back
8887c478bd9Sstevel@tonic-gate# and undo changes to the passwd file.
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate    die "No saved aspppd configuration exists.\n" unless -f $asmoved;
8917c478bd9Sstevel@tonic-gate    if (-e $astemp) {
8927c478bd9Sstevel@tonic-gate	die "$astemp is not a file\n" unless -f $asfile;
8937c478bd9Sstevel@tonic-gate	unlink $astemp || die "Cannot remove temporary $astemp: $!\n";
8947c478bd9Sstevel@tonic-gate    }
8957c478bd9Sstevel@tonic-gate    $intemp = 0;
8967c478bd9Sstevel@tonic-gate    if (-e $asfile) {
8977c478bd9Sstevel@tonic-gate	die "$asfile is not a file\n" unless -f $asfile;
8987c478bd9Sstevel@tonic-gate	die "Not modifying configuration.\n"
8997c478bd9Sstevel@tonic-gate	    unless yesno "Remove existing $asfile", $opt_y;
9007c478bd9Sstevel@tonic-gate	rename $asfile, $astemp || die "Cannot rename existing $asfile: $!\n";
9017c478bd9Sstevel@tonic-gate	$intemp = 1;
9027c478bd9Sstevel@tonic-gate    }
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate    if (rename $asmoved, $asfile) {
9057c478bd9Sstevel@tonic-gate	unlink $astemp || warn "$astemp: $!\n" if $intemp;
9067c478bd9Sstevel@tonic-gate    } else {
9077c478bd9Sstevel@tonic-gate	$failure = "Cannot rename $asmoved to $asfile: $!\n";
9087c478bd9Sstevel@tonic-gate	rename $astemp, $asfile ||
9097c478bd9Sstevel@tonic-gate	    die "$failure\nand cannot recover: $!\n" .
9107c478bd9Sstevel@tonic-gate		"Saved current asppp.cf in $astemp\n"
9117c478bd9Sstevel@tonic-gate		    if $intemp;
9127c478bd9Sstevel@tonic-gate	die $failure;
9137c478bd9Sstevel@tonic-gate    }
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate    $( = $);
9167c478bd9Sstevel@tonic-gate    $< = $>;
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate    system($pppdctl, "stop") if -x $pppdctl;
9197c478bd9Sstevel@tonic-gate    # remove pppd autostart files.
9207c478bd9Sstevel@tonic-gate    unlink $pppdir . "ifconfig";
9217c478bd9Sstevel@tonic-gate    unlink $pppdir . "demand";
9227c478bd9Sstevel@tonic-gate
9237c478bd9Sstevel@tonic-gate    system($asctl, "start") if -x $asctl;
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate    open SEDFILE, ">$sedpasswd" || die "Cannot write $sedpasswd: $!\n";
9267c478bd9Sstevel@tonic-gate    local ($escdir) = $pppdir;
9277c478bd9Sstevel@tonic-gate    $escdir =~ s+/+\\/+g;
9287c478bd9Sstevel@tonic-gate    print SEDFILE "/${escdir}dial-in\\./s+[^:]*\$+/usr/sbin/aspppls+\n";
9297c478bd9Sstevel@tonic-gate    print SEDFILE "/\\/usr\\/bin\\/pppd/s+[^:]*\$+/usr/sbin/aspppls+\n";
9307c478bd9Sstevel@tonic-gate    close SEDFILE;
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate    rewrite_passwd;
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate    exit 0;
9357c478bd9Sstevel@tonic-gate}
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate$aspppcf = $asfile;
9387c478bd9Sstevel@tonic-gateif (!(-f $asfile)) {
9397c478bd9Sstevel@tonic-gate    die "No aspppd configuration exists; nothing to convert.\n"
9407c478bd9Sstevel@tonic-gate	unless -f $asmoved;
9417c478bd9Sstevel@tonic-gate    die "No changes made.\n"
9427c478bd9Sstevel@tonic-gate	unless yesno "Already converted; rerun anyway";
9437c478bd9Sstevel@tonic-gate    $aspppcf = $asmoved;
9447c478bd9Sstevel@tonic-gate}
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gateprint "This script provides only a suggested translation for your existing aspppd\n";
9477c478bd9Sstevel@tonic-gateprint "configuration.  You will need to evaluate for yourself whether the translation\n";
9487c478bd9Sstevel@tonic-gateprint "is appropriate for your operating environment.\n";
9497c478bd9Sstevel@tonic-gatedie "No changes made.\n"
9507c478bd9Sstevel@tonic-gate  unless yesno "Continue", 1;
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate# Read in the asppp.cf file first; there's no reason to continue on to
9537c478bd9Sstevel@tonic-gate# the UUCP files if this file isn't readable or has no paths defined.
9547c478bd9Sstevel@tonic-gatelocal($ifconfig, $paths) = readaspppcf($aspppcf);
9557c478bd9Sstevel@tonic-gate
9567c478bd9Sstevel@tonic-gate# Loop over the ifconfigs and build a list of the down ones.
9577c478bd9Sstevel@tonic-gateforeach $intf (keys %$ifconfig) {
9587c478bd9Sstevel@tonic-gate    local(@words) = @{$$ifconfig{$intf}};
9597c478bd9Sstevel@tonic-gate    while ($word = shift @words) {
9607c478bd9Sstevel@tonic-gate	shift @words if $ifconfigtakes{$word};
9617c478bd9Sstevel@tonic-gate	if ($word =~ /^down$/) {
9627c478bd9Sstevel@tonic-gate	    warn("Why is $intf declared down?\n"), last
9637c478bd9Sstevel@tonic-gate		if $intf =~ /^ipd[0-9]+$/;
9647c478bd9Sstevel@tonic-gate	    $downif{$intf} = $$ifconfig{$intf};
9657c478bd9Sstevel@tonic-gate	    delete $$ifconfig{$intf};
9667c478bd9Sstevel@tonic-gate	    last;
9677c478bd9Sstevel@tonic-gate	}
9687c478bd9Sstevel@tonic-gate    }
9697c478bd9Sstevel@tonic-gate}
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate# Read /etc/passwd for dial-in users configured for aspppd.
9727c478bd9Sstevel@tonic-gatelocal($dialinusers) = readpasswd;
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate# Read in existing pppd configuration.  All we really care about
9757c478bd9Sstevel@tonic-gate# is the setting of the "auth" option.
9767c478bd9Sstevel@tonic-gateundef $authoption;
9777c478bd9Sstevel@tonic-gateif (open(OPTIONS,"<" . $options)) {
9787c478bd9Sstevel@tonic-gate    while (@{$words = uucpline(OPTIONS, $options)}) {
9797c478bd9Sstevel@tonic-gate	while ($_ = pop @$words) {
9807c478bd9Sstevel@tonic-gate	    $authoption = $_ if /auth/i;
9817c478bd9Sstevel@tonic-gate	}
9827c478bd9Sstevel@tonic-gate    }
9837c478bd9Sstevel@tonic-gate    close OPTIONS;
9847c478bd9Sstevel@tonic-gate    $authoption = "unknown" if !defined($authoption);
9857c478bd9Sstevel@tonic-gate}
9867c478bd9Sstevel@tonic-gate
9877c478bd9Sstevel@tonic-gate$dialin_auth = 0;
9887c478bd9Sstevel@tonic-gateif ($authoption =~ /^auth$/i) {
9897c478bd9Sstevel@tonic-gate    $dialin_auth = 1;
9907c478bd9Sstevel@tonic-gate} elsif ($authoption =~ /^noauth$/i) {
9917c478bd9Sstevel@tonic-gate    $dialin_auth = 2;
9927c478bd9Sstevel@tonic-gate} elsif (defined($authoption)) {
9937c478bd9Sstevel@tonic-gate    $dialin_auth = 3;
9947c478bd9Sstevel@tonic-gate}
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate# Check that there's a path for each dial in user
9977c478bd9Sstevel@tonic-gateforeach $user (keys %$dialinusers) {
9987c478bd9Sstevel@tonic-gate    if (!defined($$paths{$user})) {
9997c478bd9Sstevel@tonic-gate	warn "Dial-in user ", $user,
10007c478bd9Sstevel@tonic-gate	    " does not have a corresponding dial-in path.\n";
10017c478bd9Sstevel@tonic-gate	delete $$dialinusers{$user};
10027c478bd9Sstevel@tonic-gate	next;
10037c478bd9Sstevel@tonic-gate    }
10047c478bd9Sstevel@tonic-gate    $intf = ${$$paths{$user}}{"interface"};
10057c478bd9Sstevel@tonic-gate    if ($intf eq "ipdptp*") {
10067c478bd9Sstevel@tonic-gate	if (0+keys(%downif) == 0) {
10077c478bd9Sstevel@tonic-gate	    warn "Dial-in user $path has no available \"down\" interfaces.\n";
10087c478bd9Sstevel@tonic-gate	    delete $$dialinusers{$user};
10097c478bd9Sstevel@tonic-gate	    next;
10107c478bd9Sstevel@tonic-gate	}
10117c478bd9Sstevel@tonic-gate    } else {
10127c478bd9Sstevel@tonic-gate	if (!defined($downif{$intf}) && !defined($$ifconfig{$intf})) {
10137c478bd9Sstevel@tonic-gate	    warn "Dial-in path $user has undefined $intf; deleted.\n";
10147c478bd9Sstevel@tonic-gate	    delete $$dialinusers{$user};
10157c478bd9Sstevel@tonic-gate	    next;
10167c478bd9Sstevel@tonic-gate	}
10177c478bd9Sstevel@tonic-gate    }
10187c478bd9Sstevel@tonic-gate    ${$$paths{$user}}{$isdialin} = 1;
10197c478bd9Sstevel@tonic-gate# 0 - no info (no options file, "noauth" on call)
10207c478bd9Sstevel@tonic-gate# 1 - all auth ("auth" in options, "noauth" on call)
10217c478bd9Sstevel@tonic-gate# 2 - all noauth ("noauth" in options)
10227c478bd9Sstevel@tonic-gate# 3 - mixed; use auth ("noauth" in options, wrapper script for "auth")
10237c478bd9Sstevel@tonic-gate    if (${$$paths{$user}}{require_authentication}) {
10247c478bd9Sstevel@tonic-gate	if ($dialin_auth == 2) {
10257c478bd9Sstevel@tonic-gate	    $dialin_auth = 3;
10267c478bd9Sstevel@tonic-gate	} elsif ($dialin_auth == 0) {
10277c478bd9Sstevel@tonic-gate	    $dialin_auth = 1;
10287c478bd9Sstevel@tonic-gate	}
10297c478bd9Sstevel@tonic-gate    } else {
10307c478bd9Sstevel@tonic-gate	if ($dialin_auth == 1) {
10317c478bd9Sstevel@tonic-gate	    $dialin_auth = 3;
10327c478bd9Sstevel@tonic-gate	} elsif ($dialin_auth == 0) {
10337c478bd9Sstevel@tonic-gate	    $dialin_auth = 2;
10347c478bd9Sstevel@tonic-gate	}
10357c478bd9Sstevel@tonic-gate    }
10367c478bd9Sstevel@tonic-gate}
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate# Get lists of usable dial-in and dial-out ports.
10397c478bd9Sstevel@tonic-gatelocal($dialin,$dialout) = getserialports;
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate# Read and parse the UUCP Sysfiles, Devconfig, and Limits files.
10427c478bd9Sstevel@tonic-gate# These are keyed with the "service=" string.  The Sysfiles file can
10437c478bd9Sstevel@tonic-gate# augment or override the list of files read for a given service.
10447c478bd9Sstevel@tonic-gateprint "Reading UUCP configuration.\n" if $opt_v;
10457c478bd9Sstevel@tonic-gate@sysfiles = @{${uucpkeyfile($Sysfiles,"service=")}{"ppp"}};
10467c478bd9Sstevel@tonic-gate@limits = @{${uucpkeyfile($Limits,"service=")}{"ppp"}};
10477c478bd9Sstevel@tonic-gate%devconfig = %{uucpkeyfile($Devconfig,"service=ppp","device=")};
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate# Now read in the UUCP files corresponding to this service.
10507c478bd9Sstevel@tonic-gate$systems = uucpposfiles(uucpfiles("systems"));
10517c478bd9Sstevel@tonic-gate$dialers = uucpposfiles(uucpfiles("dialers"));
10527c478bd9Sstevel@tonic-gate$dialcodes = uucpposfiles($Dialcodes);
10537c478bd9Sstevel@tonic-gate$devices = uucpdevices(uucpfiles("devices"));
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate# just to make sure
10567c478bd9Sstevel@tonic-gate$$dialcodes{""} = ();
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate# Loop over paths.  Dial-out only paths are translated into demand-dial
10597c478bd9Sstevel@tonic-gate# configurations.  Dial-in only paths are translated into appropriate
10607c478bd9Sstevel@tonic-gate# log-in entries.
10617c478bd9Sstevel@tonic-gatelocal (@bidirectional);
10627c478bd9Sstevel@tonic-gateforeach $peer (keys %$paths) {
10637c478bd9Sstevel@tonic-gate    if (exists($$systems{$peer})) {
10647c478bd9Sstevel@tonic-gate	$sline = $$systems{$peer};
10657c478bd9Sstevel@tonic-gate	if ($$sline[0] eq "Never") {
10667c478bd9Sstevel@tonic-gate	    if (${$$paths{$peer}}{$isdialin}) {
10677c478bd9Sstevel@tonic-gate		translatedialin($peer);
10687c478bd9Sstevel@tonic-gate	    } else {
10697c478bd9Sstevel@tonic-gate		print "We never call $peer, and he never calls us.\n"
10707c478bd9Sstevel@tonic-gate		    if $opt_v;
10717c478bd9Sstevel@tonic-gate	    }
10727c478bd9Sstevel@tonic-gate	    delete $$paths{$peer};
10737c478bd9Sstevel@tonic-gate	    next;
10747c478bd9Sstevel@tonic-gate	}
10757c478bd9Sstevel@tonic-gate	push @bidirectional, $peer if ${$$paths{$peer}}{$isdialin};
10767c478bd9Sstevel@tonic-gate	print "Ignoring time restriction on $peer\n"
10777c478bd9Sstevel@tonic-gate	    if $$sline[0] ne "Any";
10787c478bd9Sstevel@tonic-gate	$dlist = $$devices{$$sline[1]};
10797c478bd9Sstevel@tonic-gate	$class = $$sline[2];
10807c478bd9Sstevel@tonic-gate	$i = 0;
10817c478bd9Sstevel@tonic-gate	while ($i < @$dlist) {
10827c478bd9Sstevel@tonic-gate	    local($dev) = $$dlist[$i];
10837c478bd9Sstevel@tonic-gate	    if ($$dev[1] ne "-") {
10847c478bd9Sstevel@tonic-gate		print "Ignoring device $$dev[0]; 801-type not supported.\n";
10857c478bd9Sstevel@tonic-gate		splice @$dlist, $i, 1;
10867c478bd9Sstevel@tonic-gate		next;
10877c478bd9Sstevel@tonic-gate	    }
10887c478bd9Sstevel@tonic-gate	    $i++;
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate	    # Make sure that classes match.
10917c478bd9Sstevel@tonic-gate	    next if $$dev[2] ne "Any" && $class ne "Any" && $$dev[2] ne $class;
10927c478bd9Sstevel@tonic-gate	    # Prepend "/dev/" if it's not present in the device name.
10937c478bd9Sstevel@tonic-gate	    if (exists($$dialout{$$dev[0]})) {
10947c478bd9Sstevel@tonic-gate		# This just seems odd.
10957c478bd9Sstevel@tonic-gate		$dname = $$dialout{$$dev[0]};
10967c478bd9Sstevel@tonic-gate		$dname =~ s+/dev/term/+/dev/cua/+;
10977c478bd9Sstevel@tonic-gate	    } else {
10987c478bd9Sstevel@tonic-gate		$dname = ($$dev[0] =~ m+^/+ ? $$dev[0] : ("/dev/" . $$dev[0]));
10997c478bd9Sstevel@tonic-gate	    }
11007c478bd9Sstevel@tonic-gate	    # Skip devices that aren't supposed to be used for dial-out.
11017c478bd9Sstevel@tonic-gate	    next if $dname =~ m+^/dev/term/+;
11027c478bd9Sstevel@tonic-gate	    next if $dname =~ m+^/dev/tty[a-z]$+;
11037c478bd9Sstevel@tonic-gate	    # Make sure this is a character device and we have access to it.
11047c478bd9Sstevel@tonic-gate	    next unless -w $dname && -c $dname;
11057c478bd9Sstevel@tonic-gate	    warn "Dialer for $$dev[3] is missing.\n"
11067c478bd9Sstevel@tonic-gate		unless exists($warned{$$dev[3]}) ||
11077c478bd9Sstevel@tonic-gate		    exists($$dialers{$$dev[3]});
11087c478bd9Sstevel@tonic-gate	    $warned{$$dev[3]} = 1;
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate	    # Expand keywords from Dialcodes file.  Should have \T or \D.
11117c478bd9Sstevel@tonic-gate	    $phone = $$sline[3];
11127c478bd9Sstevel@tonic-gate	    $xphone = ($$dev[4] eq "\\T" && $phone =~ /^([A-Za-z]*)(.*)$/ ?
11137c478bd9Sstevel@tonic-gate	        "@{$$dialcodes{$1}}" . $2 : $phone);
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate	    # Make a copy of the dialing script.
11167c478bd9Sstevel@tonic-gate	    local(@dials) = @{$$dialers{$$dev[3]}};
11177c478bd9Sstevel@tonic-gate
11187c478bd9Sstevel@tonic-gate	    # Translate dial tone and wait characters from Dialers file.
11197c478bd9Sstevel@tonic-gate	    $_ = shift @dials;
11207c478bd9Sstevel@tonic-gate	    s[(.)(.)]{
11217c478bd9Sstevel@tonic-gate		local($from,$to) = ($1,$2);
11227c478bd9Sstevel@tonic-gate		$phone =~ s+(^|[^\\])$from+$1$to+gx;
11237c478bd9Sstevel@tonic-gate		$xphone =~ s+(^|[^\\])$from+$1$to+gx;
11247c478bd9Sstevel@tonic-gate	    }ge;
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate	    # Translate escapes in dial specification.  Chat has a \T,
11277c478bd9Sstevel@tonic-gate	    # but uses \U instead of \D.
11287c478bd9Sstevel@tonic-gate	    local($needt, $needu, $isexpect, @chats) = ("", "", 1);
11297c478bd9Sstevel@tonic-gate	    foreach $str (@dials) {
11307c478bd9Sstevel@tonic-gate		push(@chats, "") if $str eq "";
11317c478bd9Sstevel@tonic-gate		local ($ostr) = "";
11327c478bd9Sstevel@tonic-gate		if ($isexpect) {
11337c478bd9Sstevel@tonic-gate		    while ($str =~ s/([^\\]*)\\(.)//) {
11347c478bd9Sstevel@tonic-gate			local($lead, $_) = ($1, $2);
11357c478bd9Sstevel@tonic-gate			/[Mm]/ ? ($ostr .= $lead) :
11367c478bd9Sstevel@tonic-gate			/[Ee]/ ? ($sorrye = 1, $ostr .= $lead) :
11377c478bd9Sstevel@tonic-gate			($ostr .= $lead . "\\" . $_);
11387c478bd9Sstevel@tonic-gate		    }
11397c478bd9Sstevel@tonic-gate		} else {
11407c478bd9Sstevel@tonic-gate		    while ($str =~ s/([^\\]*)\\(.)//) {
11417c478bd9Sstevel@tonic-gate			local($lead, $_) = ($1, $2);
11427c478bd9Sstevel@tonic-gate			/T/ ? ($needt = " -T '$xphone'",
11437c478bd9Sstevel@tonic-gate			       $ostr .= $lead . "\\T") :
11447c478bd9Sstevel@tonic-gate			/D/ ? ($needu = " -U '$phone'",
11457c478bd9Sstevel@tonic-gate			       $ostr .= $lead . "\\U") :
11467c478bd9Sstevel@tonic-gate			/M/ ? ($ostr .= $lead,
11477c478bd9Sstevel@tonic-gate			       ($ostr ne "" ? push(@chats, $ostr, "\\c"):0),
11487c478bd9Sstevel@tonic-gate			       push(@chats, "HANGUP", "OFF"), $ostr = "") :
11497c478bd9Sstevel@tonic-gate			/m/ ? ($ostr .= $lead,
11507c478bd9Sstevel@tonic-gate			       ($ostr ne "" ? push(@chats, $ostr, "\\c"):0),
11517c478bd9Sstevel@tonic-gate			       push(@chats, "HANGUP", "ON"), $ostr = "") :
11527c478bd9Sstevel@tonic-gate			/[Ee]/ ? ($sorrye = 1, $ostr .= $lead) :
11537c478bd9Sstevel@tonic-gate			/[dp]/ ? ($ostr .= $lead . "\\" . $_ . "\\" . $_) :
11547c478bd9Sstevel@tonic-gate			/c/ ? ($str eq "" ? ($ostr .= $lead . "\\c") : 0) :
11557c478bd9Sstevel@tonic-gate			($ostr .= $lead . "\\" . $_);
11567c478bd9Sstevel@tonic-gate		    }
11577c478bd9Sstevel@tonic-gate		}
11587c478bd9Sstevel@tonic-gate		$ostr .= $str;
11597c478bd9Sstevel@tonic-gate		push @chats, $ostr if $ostr ne "";
11607c478bd9Sstevel@tonic-gate		$isexpect = !$isexpect;
11617c478bd9Sstevel@tonic-gate	    }
11627c478bd9Sstevel@tonic-gate
11637c478bd9Sstevel@tonic-gate	    # Pad out dial list if we're missing a "send" string and tack
11647c478bd9Sstevel@tonic-gate	    # on the chat list from the Systems file.
11657c478bd9Sstevel@tonic-gate	    if (defined $$sline[4]) {
11667c478bd9Sstevel@tonic-gate		push @chats, "\\c" if !$isexpect;
11677c478bd9Sstevel@tonic-gate		push @chats, (splice @$sline, 4);
11687c478bd9Sstevel@tonic-gate	    }
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate	    $chatfile = $pppdir . "chat.$peer.$$dev[3]";
11717c478bd9Sstevel@tonic-gate	    if (-e $chatfile) {
11727c478bd9Sstevel@tonic-gate		print "$chatfile already exists.\n";
11737c478bd9Sstevel@tonic-gate		if (!yesno("Should it be overwritten",$opt_y)) {
11747c478bd9Sstevel@tonic-gate		    if (yesno("Should it be used as-is")) {
11757c478bd9Sstevel@tonic-gate			warn "Using $chatfile as-is; it may not be correct.\n";
11767c478bd9Sstevel@tonic-gate		    } else {
11777c478bd9Sstevel@tonic-gate			for ($n = 0; ; $n++) {
11787c478bd9Sstevel@tonic-gate			    last if !(-e $chatfile . "." . $n);
11797c478bd9Sstevel@tonic-gate			}
11807c478bd9Sstevel@tonic-gate			$chatfile .= "." . $n;
11817c478bd9Sstevel@tonic-gate			print "Using $chatfile instead.\n";
11827c478bd9Sstevel@tonic-gate			$chatfiles{$chatfile} = \@chats;
11837c478bd9Sstevel@tonic-gate		    }
11847c478bd9Sstevel@tonic-gate		} else {
11857c478bd9Sstevel@tonic-gate		    $overwrite{$chatfile} = 1;
11867c478bd9Sstevel@tonic-gate		    $chatfiles{$chatfile} = \@chats;
11877c478bd9Sstevel@tonic-gate		}
11887c478bd9Sstevel@tonic-gate	    } else {
11897c478bd9Sstevel@tonic-gate		$chatfiles{$chatfile} = \@chats;
11907c478bd9Sstevel@tonic-gate	    }
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate	    push @pppdargs, $dname;
11937c478bd9Sstevel@tonic-gate	    push @pppdargs, $class if $class =~ /^[0-9]+$/;
11947c478bd9Sstevel@tonic-gate	    push @pppdargs, "demand";
11957c478bd9Sstevel@tonic-gate	    convert_options(\@pppdargs,$$paths{$peer},
11967c478bd9Sstevel@tonic-gate		$chatfile . $needt . $needu, undef);
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate	    $optname = $peersdir . $peer;
11997c478bd9Sstevel@tonic-gate	    if (-e $optname) {
12007c478bd9Sstevel@tonic-gate		print "$optname already exists.\n";
12017c478bd9Sstevel@tonic-gate		if (!yesno("Should it be overwritten", $opt_y)) {
12027c478bd9Sstevel@tonic-gate		    if (yesno("Should it be used as-is")) {
12037c478bd9Sstevel@tonic-gate			warn "Using $optname as-is; it may not be correct.\n";
12047c478bd9Sstevel@tonic-gate		    } else {
12057c478bd9Sstevel@tonic-gate			for ($n = 0; ; $n++) {
12067c478bd9Sstevel@tonic-gate			    last if !(-e $optname . "." . $n);
12077c478bd9Sstevel@tonic-gate			}
12087c478bd9Sstevel@tonic-gate			$optname .= "." . $n;
12097c478bd9Sstevel@tonic-gate			print "Using $optname instead.\n";
12107c478bd9Sstevel@tonic-gate			$optfiles{$optname} = \@pppdargs;
12117c478bd9Sstevel@tonic-gate		    }
12127c478bd9Sstevel@tonic-gate		} else {
12137c478bd9Sstevel@tonic-gate		    $overwrite{$optname} = 1;
12147c478bd9Sstevel@tonic-gate		    $optfiles{$optname} = \@pppdargs;
12157c478bd9Sstevel@tonic-gate		}
12167c478bd9Sstevel@tonic-gate	    } else {
12177c478bd9Sstevel@tonic-gate		$optfiles{$optname} = \@pppdargs;
12187c478bd9Sstevel@tonic-gate	    }
12197c478bd9Sstevel@tonic-gate	    $scriptfiles{$pppdir . "demand"} .= "/usr/bin/pppd file $optname\n";
12207c478bd9Sstevel@tonic-gate	    last;
12217c478bd9Sstevel@tonic-gate	}
12227c478bd9Sstevel@tonic-gate    } elsif (${$$paths{$peer}}{$isdialin}) {
12237c478bd9Sstevel@tonic-gate    	translatedialin($peer);
12247c478bd9Sstevel@tonic-gate    } else {
12257c478bd9Sstevel@tonic-gate	warn "Path $peer has no dial-in user nor Systems file entry.\n";
12267c478bd9Sstevel@tonic-gate	delete $$paths{$peer};
12277c478bd9Sstevel@tonic-gate    }
12287c478bd9Sstevel@tonic-gate}
12297c478bd9Sstevel@tonic-gate
12307c478bd9Sstevel@tonic-gatewarn "Chat cannot do echo checking; requests for this removed.\n" if $sorrye;
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gateif (@bidirectional) {
12337c478bd9Sstevel@tonic-gate    print "\nWarning:  The following paths are bidirectional:\n";
12347c478bd9Sstevel@tonic-gate    print "\t@bidirectional\n\n";
12357c478bd9Sstevel@tonic-gate    print "Bidirectional paths (with entries in both Systems and passwd) do not translate\n";
12367c478bd9Sstevel@tonic-gate    print "into Solaris PPP 4.0 semantics in an exact manner.  The dial-out portion will\n";
12377c478bd9Sstevel@tonic-gate    print "use the designated interface, but the dial-in portion will use any available\n";
12387c478bd9Sstevel@tonic-gate    print "interface.\n";
12397c478bd9Sstevel@tonic-gate    while ($peer = pop @bidirectional) {
12407c478bd9Sstevel@tonic-gate	delete $ {$$paths{$peer}}{interface};
12417c478bd9Sstevel@tonic-gate	translatedialin($peer);
12427c478bd9Sstevel@tonic-gate    }
12437c478bd9Sstevel@tonic-gate}
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gatetranslateifconfig;
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate# Create an /etc/ppp/options if we need to.
12487c478bd9Sstevel@tonic-gateif (!defined($authoption) && $dialin_auth > 0) {
12497c478bd9Sstevel@tonic-gate    local (@pppdopts);
12507c478bd9Sstevel@tonic-gate    push @pppdopts, "lock";
12517c478bd9Sstevel@tonic-gate    push @pppdopts, "auth" if $dialin_auth == 1;
12527c478bd9Sstevel@tonic-gate    push @pppdopts, "noauth" if $dialin_auth > 1;
12537c478bd9Sstevel@tonic-gate    $optfiles{$options} = \@pppdopts;
12547c478bd9Sstevel@tonic-gate}
12557c478bd9Sstevel@tonic-gate# Translate option files to plain text.
12567c478bd9Sstevel@tonic-gateforeach $file (keys %optfiles) {
12577c478bd9Sstevel@tonic-gate    local ($opts) = $optfiles{$file};
12587c478bd9Sstevel@tonic-gate    local ($cstr) = "";
12597c478bd9Sstevel@tonic-gate    $cstr .= shift(@$opts) . "\n" while @$opts;
12607c478bd9Sstevel@tonic-gate    $optfiles{$file} = $cstr;
12617c478bd9Sstevel@tonic-gate}
12627c478bd9Sstevel@tonic-gate# Change "auth" to "noauth" or add "noauth" to /etc/ppp/options.
12637c478bd9Sstevel@tonic-gateif (defined($authoption) && $authoption ne "noauth" && $dialin_auth == 3) {
12647c478bd9Sstevel@tonic-gate    local(@triplet, $cstr);
12657c478bd9Sstevel@tonic-gate    if ($authoption eq "unknown") {
12667c478bd9Sstevel@tonic-gate	warn "Adding 'noauth' to $options\n";
12677c478bd9Sstevel@tonic-gate    } else {
12687c478bd9Sstevel@tonic-gate	warn "Changing 'auth' in $options to 'noauth'\n";
12697c478bd9Sstevel@tonic-gate    }
12707c478bd9Sstevel@tonic-gate    open(OPTIONS,"<" . $options) || die "$options disappeared: $!\n";
12717c478bd9Sstevel@tonic-gate    while (@{$words = uucpline(OPTIONS, $options, \@triplet)}) {
12727c478bd9Sstevel@tonic-gate	$cstr .= $triplet[0];
12737c478bd9Sstevel@tonic-gate	if (grep(/auth/, @$words)) {
12747c478bd9Sstevel@tonic-gate	    local(@newwords) = map { $_ = "noauth" if /auth/; $_ } @$words;
12757c478bd9Sstevel@tonic-gate	    $cstr .= "@newwords";
12767c478bd9Sstevel@tonic-gate	} else {
12777c478bd9Sstevel@tonic-gate	    $cstr .= $triplet[1];
12787c478bd9Sstevel@tonic-gate	}
12797c478bd9Sstevel@tonic-gate	while (pop @$words) {
12807c478bd9Sstevel@tonic-gate	    $authoption = $_ if /auth/i;
12817c478bd9Sstevel@tonic-gate	}
12827c478bd9Sstevel@tonic-gate	$cstr .= $triplet[2];
12837c478bd9Sstevel@tonic-gate    }
12847c478bd9Sstevel@tonic-gate    $cstr .= $triplet[0] . $triplet[2];
12857c478bd9Sstevel@tonic-gate    close OPTIONS;
12867c478bd9Sstevel@tonic-gate    $cstr .= "\n" if $cstr !~ /\n$/;
12877c478bd9Sstevel@tonic-gate    $cstr .= "noauth\n" if $authoption eq "unknown";
12887c478bd9Sstevel@tonic-gate    $optfiles{$options} = $cstr;
12897c478bd9Sstevel@tonic-gate}
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate# Create a sed script to fix the users' shell paths.
12927c478bd9Sstevel@tonic-gateif (0+(keys %dialinshell) != 0) {
12937c478bd9Sstevel@tonic-gate    $cstr = "";
12947c478bd9Sstevel@tonic-gate    foreach $peer (keys %dialinshell) {
12957c478bd9Sstevel@tonic-gate	$cstr .= "/^$peer:/s+[^:]*/aspppls\$+$dialinshell{$peer}+\n";
12967c478bd9Sstevel@tonic-gate    }
12977c478bd9Sstevel@tonic-gate    $scriptfiles{$sedpasswd} = $cstr;
12987c478bd9Sstevel@tonic-gate}
12997c478bd9Sstevel@tonic-gate
13007c478bd9Sstevel@tonic-gateprint "\nPreparing to write out translated configuration:\n";
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate# Enumerate the files we'll write.
13037c478bd9Sstevel@tonic-gate$nfiles = 0;
13047c478bd9Sstevel@tonic-gateif (0+(keys %chatfiles) != 0) {
13057c478bd9Sstevel@tonic-gate    print "    ";
13067c478bd9Sstevel@tonic-gate    nof 0+(keys %chatfiles), "chat file", ":\n";
13077c478bd9Sstevel@tonic-gate    foreach $file (keys %chatfiles) {
13087c478bd9Sstevel@tonic-gate	$nfiles++;
13097c478bd9Sstevel@tonic-gate	print "\t$nfiles.  $file\n";
13107c478bd9Sstevel@tonic-gate	local ($chats) = $chatfiles{$file};
13117c478bd9Sstevel@tonic-gate	local ($cstr) = "";
13127c478bd9Sstevel@tonic-gate	while (@$chats) {
13137c478bd9Sstevel@tonic-gate	    $cstr .= requote(shift(@$chats));
13147c478bd9Sstevel@tonic-gate	    $cstr .= " " . requote(shift(@$chats)) if @$chats;
13157c478bd9Sstevel@tonic-gate	    $cstr .= "\n";
13167c478bd9Sstevel@tonic-gate	}
13177c478bd9Sstevel@tonic-gate	local (@filerec) = ( $file, $cstr );
13187c478bd9Sstevel@tonic-gate	push @allfiles, \@filerec;
13197c478bd9Sstevel@tonic-gate    }
13207c478bd9Sstevel@tonic-gate}
13217c478bd9Sstevel@tonic-gateif (0+(keys %optfiles) != 0) {
13227c478bd9Sstevel@tonic-gate    print "    ";
13237c478bd9Sstevel@tonic-gate    nof 0+(keys %optfiles), "option file", ":\n";
13247c478bd9Sstevel@tonic-gate    foreach $file (keys %optfiles) {
13257c478bd9Sstevel@tonic-gate	$nfiles++;
13267c478bd9Sstevel@tonic-gate	print "\t$nfiles.  $file\n";
13277c478bd9Sstevel@tonic-gate	local (@filerec) = ( $file, $optfiles{$file} );
13287c478bd9Sstevel@tonic-gate	push @allfiles, \@filerec;
13297c478bd9Sstevel@tonic-gate    }
13307c478bd9Sstevel@tonic-gate}
13317c478bd9Sstevel@tonic-gateif (0+(keys %scriptfiles) != 0) {
13327c478bd9Sstevel@tonic-gate    print "    ";
13337c478bd9Sstevel@tonic-gate    nof 0+(keys %scriptfiles), "script file", ":\n";
13347c478bd9Sstevel@tonic-gate    foreach $file (keys %scriptfiles) {
13357c478bd9Sstevel@tonic-gate	$nfiles++;
13367c478bd9Sstevel@tonic-gate	print "\t$nfiles.  $file\n";
13377c478bd9Sstevel@tonic-gate	local (@filerec) = ( $file, $scriptfiles{$file} );
13387c478bd9Sstevel@tonic-gate	push @allfiles, \@filerec;
13397c478bd9Sstevel@tonic-gate    }
13407c478bd9Sstevel@tonic-gate}
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate# Merge new secrets needed with existing ones, if any.
13437c478bd9Sstevel@tonic-gatesub merge_secrets
13447c478bd9Sstevel@tonic-gate{
13457c478bd9Sstevel@tonic-gate    local ($addsecrets, $fname) = @_;
13467c478bd9Sstevel@tonic-gate    local ($file, $cstr, @triplet, $newsecret);
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate    $nfiles++;
13497c478bd9Sstevel@tonic-gate    $file = $pppdir . $fname;
13507c478bd9Sstevel@tonic-gate    print "\t$nfiles.  $file\n";
13517c478bd9Sstevel@tonic-gate    if (open(SECRETS, '<' . $pppdir . $fname)) {
13527c478bd9Sstevel@tonic-gate	while (@{$words = uucpline(SECRETS, $pppdir . $fname, \@triplet)}) {
13537c478bd9Sstevel@tonic-gate	    $cstr .= $triplet[0];
13547c478bd9Sstevel@tonic-gate	    $newsecret = $ {$$addsecrets{$$words[0]}}{$$words[1]};
13557c478bd9Sstevel@tonic-gate	    if (defined $newsecret) {
13567c478bd9Sstevel@tonic-gate		$cstr .= requote($$words[0]) . " " . requote($$words[1]) .
13577c478bd9Sstevel@tonic-gate		  " " . $newsecret;
13587c478bd9Sstevel@tonic-gate		delete $ {$$addsecrets{$$words[0]}}{$$words[1]};
13597c478bd9Sstevel@tonic-gate	    } else {
13607c478bd9Sstevel@tonic-gate		$cstr .= $triplet[1];
13617c478bd9Sstevel@tonic-gate	    }
13627c478bd9Sstevel@tonic-gate	    $cstr .= $triplet[2];
13637c478bd9Sstevel@tonic-gate	}
13647c478bd9Sstevel@tonic-gate	close SECRETS;
13657c478bd9Sstevel@tonic-gate	$cstr .= $triplet[0] . $triplet[2];
13667c478bd9Sstevel@tonic-gate    }
13677c478bd9Sstevel@tonic-gate    foreach $key1 (keys (%$addsecrets)) {
13687c478bd9Sstevel@tonic-gate	foreach $key2 (keys (%{$$addsecrets{$key1}})) {
13697c478bd9Sstevel@tonic-gate	    $cstr .= requote($key1) . " " . requote($key2) . " " .
13707c478bd9Sstevel@tonic-gate	      $ {$$addsecrets{$key1}}{$key2} . "\n";
13717c478bd9Sstevel@tonic-gate	}
13727c478bd9Sstevel@tonic-gate    }
13737c478bd9Sstevel@tonic-gate    local (@filerec) = ( $file, $cstr );
13747c478bd9Sstevel@tonic-gate    push @allfiles, \@filerec;
13757c478bd9Sstevel@tonic-gate}
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate$nchap = 0+(keys %chapsecrets) != 0;
13787c478bd9Sstevel@tonic-gate$npap = 0+(keys %papsecrets) != 0;
13797c478bd9Sstevel@tonic-gateif ($nchap != 0 || $npap != 0) {
13807c478bd9Sstevel@tonic-gate    print "    ";
13817c478bd9Sstevel@tonic-gate    nof $nchap + $npap, "secrets file", ":\n";
13827c478bd9Sstevel@tonic-gate    merge_secrets(\%chapsecrets, "chap-secrets") if $nchap != 0;
13837c478bd9Sstevel@tonic-gate    merge_secrets(\%papsecrets, "pap-secrets") if $npap != 0;
13847c478bd9Sstevel@tonic-gate}
13857c478bd9Sstevel@tonic-gate
13867c478bd9Sstevel@tonic-gatedie "Nothing to write back; I'm done.\n" if $nfiles == 0;
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate$PAGER = fixpath($ENV{PAGER}, "/usr/bin/less");
13897c478bd9Sstevel@tonic-gate$EDITOR = fixpath($ENV{EDITOR}, "/usr/bin/vi");
13907c478bd9Sstevel@tonic-gate$SHELL = fixpath($ENV{SHELL}, "/usr/bin/ksh");
13917c478bd9Sstevel@tonic-gate
13927c478bd9Sstevel@tonic-gateEND {
13937c478bd9Sstevel@tonic-gate    if ($tempname) {
13947c478bd9Sstevel@tonic-gate	unlink($tempname) or
13957c478bd9Sstevel@tonic-gate	    die "Cannot remove temporary file $tempname: $!\n";
13967c478bd9Sstevel@tonic-gate    }
13977c478bd9Sstevel@tonic-gate}
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gatesub show_file_options
14007c478bd9Sstevel@tonic-gate{
14017c478bd9Sstevel@tonic-gate    print "\nEnter option number:\n";
14027c478bd9Sstevel@tonic-gate    print "\t1 - view contents of file on standard output\n";
14037c478bd9Sstevel@tonic-gate    print "\t2 - view contents of file using $PAGER\n" if $PAGER ne "";
14047c478bd9Sstevel@tonic-gate    print "\t3 - edit contents of file using $EDITOR\n" if $EDITOR ne "";
14057c478bd9Sstevel@tonic-gate    print "\t4 - delete/undelete file from list\n";
14067c478bd9Sstevel@tonic-gate    print "\t5 - rename file in list\n";
14077c478bd9Sstevel@tonic-gate    print "\t6 - show file list again\n";
14087c478bd9Sstevel@tonic-gate    print "\t7 - escape to shell (or \"!cmd\")\n";
14097c478bd9Sstevel@tonic-gate    print "\t8 - abort without saving anything\n";
14107c478bd9Sstevel@tonic-gate    print "\t9 - save all files and exit (default)\n";
14117c478bd9Sstevel@tonic-gate}
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate# If interactive, then allow user to view and modify converted data.
14147c478bd9Sstevel@tonic-gateif ((-t STDIN) && (-t STDOUT) && !$opt_n) {
14157c478bd9Sstevel@tonic-gate    show_file_options();
14167c478bd9Sstevel@tonic-gate    while (1) {
14177c478bd9Sstevel@tonic-gate	print "Option:  ";
14187c478bd9Sstevel@tonic-gate	chomp($ans = <STDIN>);
14197c478bd9Sstevel@tonic-gate	if ($ans eq "?" || $ans =~ /^h/i) {
14207c478bd9Sstevel@tonic-gate	    show_file_options();
14217c478bd9Sstevel@tonic-gate	    next;
14227c478bd9Sstevel@tonic-gate	}
14237c478bd9Sstevel@tonic-gate	if ($ans eq "") {
14247c478bd9Sstevel@tonic-gate	    last if yesno "Saving all files.  Are you sure";
14257c478bd9Sstevel@tonic-gate	    next;
14267c478bd9Sstevel@tonic-gate	}
14277c478bd9Sstevel@tonic-gate	last if $ans == 9;
14287c478bd9Sstevel@tonic-gate	print("Aborted.\n"), exit if $ans == 8;
14297c478bd9Sstevel@tonic-gate	if ($ans =~ /^!/ || $ans == 7) {
14307c478bd9Sstevel@tonic-gate	    if ($ans =~ /^!(.+)/) {
14317c478bd9Sstevel@tonic-gate		system($1);
14327c478bd9Sstevel@tonic-gate	    } else {
14337c478bd9Sstevel@tonic-gate		print("Interactive shell access not permitted here.\n"), next
14347c478bd9Sstevel@tonic-gate		    if $< != $>;
14357c478bd9Sstevel@tonic-gate		system($SHELL);
14367c478bd9Sstevel@tonic-gate	    }
14377c478bd9Sstevel@tonic-gate	} elsif ($ans == 6) {
14387c478bd9Sstevel@tonic-gate	    for ($i = 0; $i < $nfiles; $i++) {
14397c478bd9Sstevel@tonic-gate		print "\t", $i+1, ".  $allfiles[$i][0]",
14407c478bd9Sstevel@tonic-gate		    ($deleted[$i] ? "   (deleted)" : ""), "\n";
14417c478bd9Sstevel@tonic-gate	    }
14427c478bd9Sstevel@tonic-gate	} elsif ($ans > 0 && $ans < 6) {
14437c478bd9Sstevel@tonic-gate	    $fnum = 0;
14447c478bd9Sstevel@tonic-gate	    if ($nfiles > 1) {
14457c478bd9Sstevel@tonic-gate		print "File number (1 .. $nfiles):  ";
14467c478bd9Sstevel@tonic-gate		chomp($fnum = <STDIN>);
14477c478bd9Sstevel@tonic-gate		if ($fnum < 1 || $fnum > $nfiles) {
14487c478bd9Sstevel@tonic-gate		    print "Unknown file (must be 1 to $nfiles).\n";
14497c478bd9Sstevel@tonic-gate		    next;
14507c478bd9Sstevel@tonic-gate		}
14517c478bd9Sstevel@tonic-gate		$fnum--;
14527c478bd9Sstevel@tonic-gate	    }
14537c478bd9Sstevel@tonic-gate	    if ($ans == 5) {
14547c478bd9Sstevel@tonic-gate		print "Current name is $allfiles[$fnum][0]\n";
14557c478bd9Sstevel@tonic-gate		print "New name:  ";
14567c478bd9Sstevel@tonic-gate		chomp($fname = <STDIN>);
14577c478bd9Sstevel@tonic-gate		print("Unchanged\n"), next if $fname eq "";
14587c478bd9Sstevel@tonic-gate		$allfiles[$fnum][0] = $fname;
14597c478bd9Sstevel@tonic-gate	    }
14607c478bd9Sstevel@tonic-gate	    if ($deleted[$fnum]) {
14617c478bd9Sstevel@tonic-gate		if (yesno("File " . $fnum+1 .
14627c478bd9Sstevel@tonic-gate		   " ($allfiles[$fnum][0]) is deleted; undelete",1)) {
14637c478bd9Sstevel@tonic-gate		    undef $deleted[$fnum];
14647c478bd9Sstevel@tonic-gate		}
14657c478bd9Sstevel@tonic-gate		next;
14667c478bd9Sstevel@tonic-gate	    }
14677c478bd9Sstevel@tonic-gate	    if ($ans == 1) {
14687c478bd9Sstevel@tonic-gate		print $allfiles[$fnum][1];
14697c478bd9Sstevel@tonic-gate	    } elsif ($ans == 2 && $PAGER ne "") {
14707c478bd9Sstevel@tonic-gate		$i = 0;
14717c478bd9Sstevel@tonic-gate		do {
14727c478bd9Sstevel@tonic-gate		    if (++$i > 5) {
14737c478bd9Sstevel@tonic-gate			warn "Unable to open temporary file: $!";
14747c478bd9Sstevel@tonic-gate			undef $tempname;
14757c478bd9Sstevel@tonic-gate			last;
14767c478bd9Sstevel@tonic-gate		    }
14777c478bd9Sstevel@tonic-gate		    $tempname = tmpnam();
14787c478bd9Sstevel@tonic-gate		} until sysopen(FH, $tempname, O_RDWR|O_CREAT|O_EXCL);
14797c478bd9Sstevel@tonic-gate		next if !$tempname;
14807c478bd9Sstevel@tonic-gate		print FH $allfiles[$fnum][1];
14817c478bd9Sstevel@tonic-gate		close FH;
14827c478bd9Sstevel@tonic-gate		system($PAGER, $tempname);
14837c478bd9Sstevel@tonic-gate		unlink($tempname) ||
14847c478bd9Sstevel@tonic-gate		    warn "Trouble removing temporary file: $!";
14857c478bd9Sstevel@tonic-gate		undef $tempname;
14867c478bd9Sstevel@tonic-gate	    } elsif ($ans == 3 && $EDITOR ne "") {
14877c478bd9Sstevel@tonic-gate		$i = 0;
14887c478bd9Sstevel@tonic-gate		do {
14897c478bd9Sstevel@tonic-gate		    if (++$i > 5) {
14907c478bd9Sstevel@tonic-gate			warn "Unable to open temporary file: $!";
14917c478bd9Sstevel@tonic-gate			undef $tempname;
14927c478bd9Sstevel@tonic-gate			last;
14937c478bd9Sstevel@tonic-gate		    }
14947c478bd9Sstevel@tonic-gate		    $tempname = tmpnam();
14957c478bd9Sstevel@tonic-gate		} until sysopen(FH, $tempname, O_RDWR|O_CREAT|O_EXCL);
14967c478bd9Sstevel@tonic-gate		next if !$tempname;
14977c478bd9Sstevel@tonic-gate		chown $<, $(, $tempname;
14987c478bd9Sstevel@tonic-gate		print FH $allfiles[$fnum][1];
14997c478bd9Sstevel@tonic-gate		close FH;
15007c478bd9Sstevel@tonic-gate		$i = system($EDITOR, $tempname);
15017c478bd9Sstevel@tonic-gate		if ($i == 0) {
15027c478bd9Sstevel@tonic-gate		    if (open FH, "<" . $tempname) {
15037c478bd9Sstevel@tonic-gate			read FH, $allfiles[$fnum][1], (-s $tempname);
15047c478bd9Sstevel@tonic-gate			close FH;
15057c478bd9Sstevel@tonic-gate		    }
15067c478bd9Sstevel@tonic-gate		} else {
15077c478bd9Sstevel@tonic-gate		    print "Editor dropped core.\n" if $? & 128;
15087c478bd9Sstevel@tonic-gate		    print "Editor terminated on signal ", $? & 127, "\n"
15097c478bd9Sstevel@tonic-gate			if $? & 127;
15107c478bd9Sstevel@tonic-gate		    print "Editor returned error ", $? >> 8, "\n"
15117c478bd9Sstevel@tonic-gate			if $? >> 8;
15127c478bd9Sstevel@tonic-gate		}
15137c478bd9Sstevel@tonic-gate		unlink($tempname) ||
15147c478bd9Sstevel@tonic-gate		    warn "Trouble removing temporary file: $!";
15157c478bd9Sstevel@tonic-gate		undef $tempname;
15167c478bd9Sstevel@tonic-gate	    } elsif ($ans == 4) {
15177c478bd9Sstevel@tonic-gate		$deleted[$fnum] = 1;
15187c478bd9Sstevel@tonic-gate	    }
15197c478bd9Sstevel@tonic-gate	}
15207c478bd9Sstevel@tonic-gate    }
15217c478bd9Sstevel@tonic-gate}
15227c478bd9Sstevel@tonic-gate
15237c478bd9Sstevel@tonic-gateprint "\n";
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate# Interactive part is over.  Become real.
15267c478bd9Sstevel@tonic-gate$( = $);
15277c478bd9Sstevel@tonic-gate$< = $>;
15287c478bd9Sstevel@tonic-gate
15297c478bd9Sstevel@tonic-gateprint "Stopping aspppd\n" if $opt_v;
15307c478bd9Sstevel@tonic-gatesystem($asctl, "stop") if -x $asctl;
15317c478bd9Sstevel@tonic-gate
15327c478bd9Sstevel@tonic-gateprint "Saving all files\n" if $opt_v;
15337c478bd9Sstevel@tonic-gatefor ($i = 0; $i < $nfiles; $i++) {
15347c478bd9Sstevel@tonic-gate    $filerec = $allfiles[$i];
15357c478bd9Sstevel@tonic-gate    if ($deleted[$i]) {
15367c478bd9Sstevel@tonic-gate	delete $scriptfiles{$$filerec[0]};
15377c478bd9Sstevel@tonic-gate	next;
15387c478bd9Sstevel@tonic-gate    }
15397c478bd9Sstevel@tonic-gate    print "Saving $$filerec[0]\n" if $opt_v;
15407c478bd9Sstevel@tonic-gate    $$filerec[0] =~ m+(.*)/+;
15417c478bd9Sstevel@tonic-gate    if ($1 eq "") {
15427c478bd9Sstevel@tonic-gate	# this is ok; just a top level file
15437c478bd9Sstevel@tonic-gate    } elsif (!(-d $1)) {
15447c478bd9Sstevel@tonic-gate	local ($exdir) = $1;
15457c478bd9Sstevel@tonic-gate	while ($exdir && !(-d $exdir)) {
15467c478bd9Sstevel@tonic-gate	    $exdir =~ m+(.*)/+;
15477c478bd9Sstevel@tonic-gate	    $exdir = $1;
15487c478bd9Sstevel@tonic-gate	}
15497c478bd9Sstevel@tonic-gate	if ($exdir) {
15507c478bd9Sstevel@tonic-gate	    local ($dir) = $1;
15517c478bd9Sstevel@tonic-gate	    $dir =~ m+$exdir/([^/]*)(.*)+;
15527c478bd9Sstevel@tonic-gate	    local ($tomake, $rest) = ($1, $2);
15537c478bd9Sstevel@tonic-gate	    mkdir $exdir . "/" . $tomake, 0775;
15547c478bd9Sstevel@tonic-gate	    if ($! == ENOSYS) {
15557c478bd9Sstevel@tonic-gate		warn "Unable to make directory $exdir/$tomake; automount point.\n";
15567c478bd9Sstevel@tonic-gate		next;
15577c478bd9Sstevel@tonic-gate	    }
15587c478bd9Sstevel@tonic-gate	    if ($! != 0) {
15597c478bd9Sstevel@tonic-gate		warn "Unable to make directory $exdir/$tomake: $!\n";
15607c478bd9Sstevel@tonic-gate		next;
15617c478bd9Sstevel@tonic-gate	    }
15627c478bd9Sstevel@tonic-gate	    if (system("mkdir", "-p", $dir) != 0) {
15637c478bd9Sstevel@tonic-gate		warn "Failed to make $dir\n";
15647c478bd9Sstevel@tonic-gate		next;
15657c478bd9Sstevel@tonic-gate	    }
15667c478bd9Sstevel@tonic-gate	} else {
15677c478bd9Sstevel@tonic-gate	    warn "$1 doesn't appear to have a useful path.\n";
15687c478bd9Sstevel@tonic-gate	    next;
15697c478bd9Sstevel@tonic-gate	}
15707c478bd9Sstevel@tonic-gate    }
15717c478bd9Sstevel@tonic-gate    undef $fileerr;
15727c478bd9Sstevel@tonic-gate    local ($fname) = $$filerec[0];
15737c478bd9Sstevel@tonic-gate    if (-e $fname && !$overwrite{$chatfile}) {
15747c478bd9Sstevel@tonic-gate	print "$fname already exists.\n"
15757c478bd9Sstevel@tonic-gate	  if (-t STDIN) && (-t STDOUT) && !$opt_n;
15767c478bd9Sstevel@tonic-gate	if (!yesno("Should it be overwritten",$opt_y)) {
15777c478bd9Sstevel@tonic-gate	    warn "Using $fname as-is; it may not be correct.\n";
15787c478bd9Sstevel@tonic-gate	    next;
15797c478bd9Sstevel@tonic-gate	}
15807c478bd9Sstevel@tonic-gate    }
15817c478bd9Sstevel@tonic-gate    if (sysopen(OUTFILE, $$filerec[0], O_WRONLY|O_CREAT|O_TRUNC, 0600)) {
15827c478bd9Sstevel@tonic-gate	print OUTFILE $$filerec[1] || ($fileerr = $!);
15837c478bd9Sstevel@tonic-gate	close OUTFILE || ($fileerr = $!);
15847c478bd9Sstevel@tonic-gate    } else {
15857c478bd9Sstevel@tonic-gate	$fileerr = $!;
15867c478bd9Sstevel@tonic-gate    }
15877c478bd9Sstevel@tonic-gate    warn "Unable to write $$filerec[0]: $fileerr\n" if $fileerr;
15887c478bd9Sstevel@tonic-gate}
15897c478bd9Sstevel@tonic-gate
15907c478bd9Sstevel@tonic-gatelocal(@scripts) = keys %scriptfiles;
15917c478bd9Sstevel@tonic-gateif (@scripts) {
15927c478bd9Sstevel@tonic-gate    print "Making scripts executable\n" if $opt_v;
15937c478bd9Sstevel@tonic-gate    system("chmod", "u+x", @scripts);
15947c478bd9Sstevel@tonic-gate}
15957c478bd9Sstevel@tonic-gate
15967c478bd9Sstevel@tonic-gaterewrite_passwd if exists($scriptfiles{$sedpasswd});
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate# clean up after a previous translation.
15997c478bd9Sstevel@tonic-gateunlink $pppdir . "ifconfig" if !$scriptfiles{$pppdir . "ifconfig"};
16007c478bd9Sstevel@tonic-gateunlink $pppdir . "demand" if !$scriptfiles{$pppdir . "demand"};
16017c478bd9Sstevel@tonic-gate
16027c478bd9Sstevel@tonic-gate(rename($asfile, $asmoved) || warn "Cannot move $asfile: $!\n")
16037c478bd9Sstevel@tonic-gate  if $aspppcf ne $astemp;
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gatesystem($pppdctl, "start") if -x $pppdctl;
16067c478bd9Sstevel@tonic-gate
16077c478bd9Sstevel@tonic-gate# use Dumpvalue;
16087c478bd9Sstevel@tonic-gate# my $dumper = new Dumpvalue;
16097c478bd9Sstevel@tonic-gate# $dumper->set(globPrint => 1);
16107c478bd9Sstevel@tonic-gate# $dumper->dumpValue($ifconfig);
1611