3 # This utility translates from aspppd configuration to Solaris PPP 4.0
4 # (or ANU ppp-2.4.0; aka pppd). It can also revert to previous aspppd
5 # configuration (discarding the pppd configuration), but does not
6 # translate new configuration files into old.
8 # This script provides only a suggested translation for your existing
9 # aspppd configuration. You will need to evaluate for yourself
10 # whether the translation is appropriate for your operating
13 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
14 # Use is subject to license terms.
17 # Steps in translation:
18 # - parse /etc/asppp.cf
19 # - check for aspppls in /etc/passwd (or NIS)
20 # - read in current /etc/ppp/options configuration file
21 # - read list of configured serial ports from pmadm
22 # - read in UUCP configuration files
23 # - create translated configuration
24 # - write files back out
27 # - translation with point-to-multipoint is incomplete
31 use POSIX
qw(tmpnam ENOSYS);
34 # Secure the path if we're running under RBAC.
35 $ENV{PATH
} = ( "/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/ucb" )
38 # General path names that can be configured.
39 local($rootetc) = "/etc/";
40 local($passwd) = $rootetc . "passwd";
41 local($passwdlck) = $rootetc . ".pwd.lock";
42 local($asfile) = $rootetc . "asppp.cf";
43 local($astemp) = $rootetc . "asppp.temp.cf";
44 local($asmoved) = $rootetc . "asppp.saved.cf";
45 local($uucpdir) = $rootetc . "uucp/";
46 local($Devices) = $uucpdir . "Devices";
47 local($Devconfig) = $uucpdir . "Devconfig";
48 local($Dialers) = $uucpdir . "Dialers";
49 local($Dialcodes) = $uucpdir . "Dialcodes";
50 local($Limits) = $uucpdir . "Limits";
51 local($Sysfiles) = $uucpdir . "Sysfiles";
52 local($Systems) = $uucpdir . "Systems";
53 local($pppdir) = $rootetc . "ppp/";
54 local($options) = $pppdir . "options";
55 local($ttyprefix) = $pppdir . "options.";
56 local($peersdir) = $pppdir . "peers/";
57 local($initd) = $rootetc . "init.d/";
58 local($asctl) = $initd . "asppp";
59 local($pppdctl) = $initd . "pppd";
60 local($sedpasswd) = "/tmp/sed-passwd";
62 # Fake asppp keyword used to keep track of dial-in paths.
63 local($isdialin) = "-is-dial-in";
65 # Limits and Sysfiles are keyed on "service=".
66 # Devconfig is keyed on "service=" and "device=".
67 # Dialcodes, Dialers, Systems, and Devices are single keyword files.
68 # Devices alone may have multiple entries for a given key.
70 # Internal data structures
71 local(@sysfiles,@limits,@devconfig);
72 local(@sysdefault) = ( "systems=" . $Systems, "dialers=" . $Dialers,
73 "devices=" . $Devices );
74 local(@limitdefault) = ( "max=-1" );
75 local(@devdefault) = ( "pop=", "push=", "connecttime=-1", "expecttime=-1",
78 # List of keywords for which ifconfig takes an additional parameter.
79 local($ifconfigtakes) = (
99 # These are keywords, but do not take an additional parameter.
131 # print number of something in English.
134 local($num, $item, @rest) = @_;
135 print "No ", $item, "s", @rest if $num == 0;
136 print "1 ", $item, @rest if $num == 1;
137 print $num, " ", $item, "s", @rest if $num > 1;
140 # ask a yes or no question.
143 local ($query, $default) = @_;
144 local ($ans, $defans);
146 return $default unless (-t STDIN
) && (-t STDOUT
) && !$opt_n;
147 $defans = $default ?
"Yn" : "yN";
149 print $query, " [", $defans, "]? ";
150 chomp($ans = <STDIN
>);
151 return $default unless $ans;
152 return 1 if $ans =~ /^[Yy1Tt]/;
153 return 0 if $ans =~ /^[Nn0Ff]/;
154 print "Please enter 'y' or 'n'.\n";
158 # Put quotes around a string, if necessary.
159 # The tests here aren't perfect -- they think that \\\' isn't an
160 # escaped quote -- but they're good enough.
166 } elsif (/^'/ || /[^\\]'/ || /\\\\'/) {
167 # Has unescaped quotes; must use " or redo quoting.
168 if (/^"/ || /[^\\]"/ || /\\\\"/) {
169 # Both kinds of quotes; redo the quoting.
171 s/([^\\]|\\\\)"/$1\\"/g;
174 } elsif (/^"/ || /[^\\]"/ || /\\\\"/) {
183 # Get a single line from a UUCP configuration file and return as a
184 # reference to an array of words. Removes comments and escapes.
185 # (This is a modified version of the standard Perl shellwords function
186 # that understands C escape sequences and continuation lines.)
187 # Optionally returns lead-in, source text, and trailing component
191 local($input, $file, $triplet) = @_;
192 local(@words,$snippet,$field,$havefield,$cont,@triparray,$maytrail);
197 # remove leading whitespace
202 if (s/^(\#(.|\n)*)$//) {
203 $triparray[0] .= $maytrail . $1;
207 if (s/^(\\?\n?)$//) {
208 $triparray[0] .= $maytrail . $1;
212 $triparray[0] .= $maytrail;
216 if (s/^(([^\#\\]|\\.)*)\\\n$//) {
217 $maytrail .= $snippet;
221 if (/^(([^\\\#]|\\[^\#])*)(\#?(.|\n)*)$/) {
224 if (s/((\s|\n)*)$//) {
225 $maytrail = $1 . $maytrail;
229 $_ = $cont . $snippet;
236 } elsif (s/^"(([^"\\]|\\.)*)"//) {
239 warn "Unmatched double quote in $file: \"$_\n";
240 } elsif (s/^'(([^'\\]|\\.)*)'//) {
243 warn "Unmatched single quote in $file: '$_\n";
245 # \s works in chat, but not in the pppd option files
247 } elsif (s/^(\\.)//) {
249 } elsif (s/^([^\s\\'"#]+)//) {
258 push(@words, $field) if $havefield;
264 $triparray[2] .= $maytrail;
265 @
$triplet = @triparray;
266 warn "Bad continuation line in $file: $cont\n" if $cont ne '';
270 # Given a logical UUCP file name, return a list of all of the files
271 # that should be read.
275 local (@flist, $value) = ();
277 for $value (@sysfiles, @sysdefault) {
278 if ($value =~ /^$file=/i) {
279 $value =~ s/^$file=//i;
280 for $file (split /:/, $value) {
281 $file = $uucpdir . $file if $file !~ /^\//;
290 # Given a file name and some key words, parse the contents of the file
291 # and return a reference to a hash constructed from this. All keys
292 # except the last must match exactly. The last is used to order the
296 local($file,@keylist) = @_;
297 local($lastkey,$keyval,$words,$i,$flag,%byservice);
299 open(SVCFILE
, '<' . $file) || return undef;
300 $lastkey = pop @keylist;
301 while (@
{$words = uucpline
(SVCFILE
, $file)}) {
303 foreach $keyval (@keylist) {
306 while ($i < @
$words) {
307 if ($$words[$i] eq $keyval) {
308 splice @
$words, $i, 1;
317 foreach $i (0 .. @
{$words}) {
318 if (@
{$words}[$i] =~ /^$lastkey(.*)/i) {
319 splice @
{$words}, $i, 1;
320 $byservice{$1} = $words;
329 # This reads a UUCP file that is keyed on the first token on each
330 # line. Duplicates are not permitted; the first encountered is used
331 # and the rest are silently discarded. A hash indexed on the first
332 # token and containing an array of tokens in each bucket is returned.
333 # Used for Dialcodes, Dialers, and Systems.
337 local($keyval,$words,%keyeddata);
339 foreach $file (@files) {
340 if (!open(POSFILE
, '<' . $file)) {
344 while (@
{$words = uucpline
(POSFILE
, $file)}) {
345 $keyval = shift @
{$words};
346 next if $keyeddata{$keyval};
347 $keyeddata{$keyval} = $words;
354 # This reads a UUCP file that is keyed on the first token on each line
355 # and may have duplicate entries. Each entry of the hash contains an
356 # array. Each entry of that array points to an array of tokens
357 # representing one parsed line. Used for the Devices file.
361 local($keyval,$words,%keyeddata);
363 foreach $file (@files) {
364 if (!open(POSFILE
, '<' . $file)) {
368 while (@
{$words = uucpline
(POSFILE
, $file)}) {
369 $keyval = shift @
{$words};
370 push @
{$keyeddata{$keyval}}, $words;
377 # For a path defined in asppp.cf, copy over defaults, validate the
378 # required options, and save in the hash to be returned.
381 local($paths, $options, $defref) = @_;
384 return if $options == $defref;
385 foreach $key (keys %$defref) {
386 $$options{$key} = $$defref{$key} unless defined($$options{$key});
388 $peer = $$options{"peer_system_name"};
389 warn("Discarded path with no peer system name.\n"), return
390 unless defined($peer);
391 $intf = $$options{"interface"};
392 warn("Missing interface on path to peer \"$peer\".\n"), return
393 unless defined($intf);
394 warn("Bad interface $intf on path to peer \"$peer\".\n"), return
395 unless $intf =~ /^ipd([0-9]+|ptp[0-9]+|ptp\*)$/;
396 warn("Missing peer IP address for point-to-multipoint path to \"",
397 $peer, "\".\n"), return
398 if $intf =~ /^ipd[0-9]+$/ && !defined($$options{"peer_ip_address"});
399 warn "Multiple definitions of path to peer \"$peer\".\n",
400 if defined($paths{$peer});
401 warn "Odd version number ", $$options{"version"},
402 " encountered in path to peer \"", $peer, "\" (ignored).\n"
403 if defined($$options{"version"}) && $$options{"version"} != 1;
404 $paths{$peer} = $options;
407 # Parse through asppp.cf. Unlike the UUCP files, lines don't matter
408 # here. The parsing is modal, with "path" introducing a PPP session
409 # description and "defaults" reverting back to global definitions.
412 local($aspppcf) = @_;
413 local(%aspppdkey) = (
415 chap_peer_secret
=> 1,
421 inactivity_timeout
=> 1,
423 # sic; aspppd is seriously confused! ACCM isn't in IPCP.
425 ipcp_compression
=> 1,
426 lcp_compression
=> 1,
428 negotiate_address
=> 1,
432 pap_peer_password
=> 1,
433 peer_ip_address
=> 1,
434 peer_system_name
=> 1,
435 require_authentication
=> 2,
437 will_do_authentication
=> 2
439 local($words,$word,$prevword,$i,$errors,%defaults,%ifconfig,%paths);
442 open ASPPPD
, "<" . $aspppcf || die "$aspppcf: $!\n";
443 print "Reading configuration from $aspppcf\n" if $opt_v;
444 $defaults{inactivity_timeout
} = 120;
445 $defaults{ipcp_compression
} = "vj";
446 $defaults{lcp_compression
} = "on";
447 $options = \
%defaults;
448 while (@
{$words = uucpline
(ASPPPD
, $aspppcf)}) {
449 if ($$words[0] =~ /^ifconfig$/i) {
450 warn "$prevword with missing argument ignored.\n"
451 if defined($prevword);
453 shift @
$words; # discard 'ifconfig' keyword
454 $word = shift @
$words;
455 warn("Bad interface on ifconfig $word.\n"), next
456 unless $word =~ /^ipd([0-9]+|ptp[0-9]+)$/;
457 $ifconfig{$word} = \@
$words;
460 unshift @
{$words}, $prevword if defined($prevword);
462 while ($word = lc(shift @
{$words})) {
465 savepath
(\
%paths, $options, \
%defaults);
466 $options = \
%defaults;
471 savepath
(\
%paths, $options, \
%defaults);
472 $options = \
%pathopts;
475 if (!defined($i = $aspppdkey{$word})) {
476 die "Too many errors in $aspppcf; aborting.\n"
478 warn "Ignoring unknown keyword $word in $aspppcf\n";
481 warn("$_ unexpected; remainder of line ignored.\n"),
483 warn("Duplicate $_ in path ignored.\n"), next
484 if $options != \
%defaults && defined($$options{$_});
485 $$options{$_} = 1 if $i == 0;
487 $prevword = $_, last unless defined($word = shift @
{$words});
488 $$options{$_} = $word if $i == 1;
490 undef $$options{$_}, next if $word =~ /^off$/;
491 $$options{$_} = $word;
492 if ($word = shift @
{$words}) {
493 if ($word =~ /^(p|ch)ap$/) {
494 $$options{$_} .= " " . $word;
496 unshift @
{$words}, $word;
502 warn "Odd trailing keyword \"$prevword\" ignored in $aspppcf\n"
504 savepath
(\
%paths, $options, \
%defaults);
505 die "No paths defined for aspppd.\n" if 0+(keys %paths) == 0;
506 die "No interfaces defined for aspppd.\n" if 0+(keys %ifconfig) == 0;
508 nof
0+(keys %paths), "path", " and ";
509 nof
0+(keys %ifconfig), "interface", " defined for aspppd.\n";
512 ( \
%ifconfig, \
%paths );
515 # Read /etc/passwd (or NIS) and return hash of users for whom
516 # the default shell is aspppls. Each hash entry contains the user's
517 # home directory path.
523 while (@pwe = getpwent()) {
524 $users{$pwe[0]} = $pwe[7] if $pwe[8] =~ /\/aspppls$/;
527 nof
0+(keys %users), "aspppd dial in user", " found.\n"
532 # Parse through pmadm output to find enabled serial ports.
533 # Field 9 has 'I' (modem dial-out only or initialize only), 'b'
534 # (bidirectional) or is blank (modem dial-in only or terminal-hardwired).
535 # For that latter case, field 18 (software-carrier) has 'y'.
536 # Field 3 has 'x' if disabled.
539 local(%dialin, %dialout);
541 open PMADM
, "pmadm -L|" || (warn "pmadm: $!\n", return undef);
545 $dialin{$_[2]} = $_[8] if $_[9] ne "I";
546 $dialout{$_[2]} = $_[8] if $_[9] ne "";
550 ( \
%dialin, \
%dialout );
553 # Convert an ifconfig statement into a local and remote address pair.
557 local($arg, $narg, $lcladdr, $remaddr);
559 shift @
$ifconf; # lose the interface name
562 $arg = shift @
$ifconf;
563 $narg = shift @
$ifconf if $ifconfigtakes{$arg};
564 if (exists($ifconfigtakes{$arg})) {
567 } elsif ($arg eq "destination") {
570 } elsif (!defined($lcladdr)) {
572 } elsif (!defined($remaddr)) {
576 ( $lcladdr, $remaddr );
579 # Convert a hash of aspppd options into an array of pppd options. The
580 # third argument ($chatpath) is undef for dial-in or a path to the
581 # chat script file otherwise.
584 local ($pppdargs, $opts, $chatpath, $user) = @_;
586 # Do the pppd option conversions.
587 push(@
$pppdargs, "defaultroute") if $$opts{default_route
};
588 push(@
$pppdargs, "idle " . $$opts{inactivity_timeout
})
589 if $$opts{inactivity_timeout
} != 0;
590 push(@
$pppdargs, "asyncmap " . $$opts{ipcp_async_map
})
591 if $$opts{ipcp_async_map
};
592 push(@
$pppdargs, "novj") if !$$opts{ipcp_compression
};
594 if ($$opts{require_authentication
}) {
596 if ($$opts{require_authentication
} =~ /chap/) {
597 push(@authopts, "require-chap");
598 $peer = $$opts{chap_peer_name
};
600 push(@authopts, "require-pap");
601 $peer = $$opts{pap_peer_id
};
603 push(@authopts, "remotename " . requote
($peer)) if $peer;
604 push(@authopts, "auth");
606 push(@
$pppdargs, @authopts);
607 } elsif ($dialin_auth == 3) {
608 # mixed authentication; must use wrapper script.
609 local($sfile) = $pppdir . "dial-in." . $user;
610 $scriptfiles{$sfile} = "#!/bin/sh\n";
611 $scriptfiles{$sfile} .= "exec /usr/bin/pppd @authopts\n";
612 $dialinshell{$user} = $sfile;
614 } elsif ($dialin_auth < 2) {
615 push(@
$pppdargs, "noauth");
617 push(@
$pppdargs, "noaccomp nopcomp") if !$$opts{lcp_compression
};
618 push(@
$pppdargs, "mru " . $$opts{lcp_mru
}) if $$opts{lcp_mru
};
619 push(@
$pppdargs, "noipdefault ipcp-accept-local")
620 if $$opts{negotiate_address
};
621 local($myname,$csecret,$psecret,$passopt);
622 if ($$opts{will_do_authentication
} =~ /chap/i) {
623 $myname = $$opts{chap_name
};
624 $csecret = $$opts{chap_secret
};
626 $myname = "" if !$myname;
627 if ($$opts{will_do_authentication
} =~ /pap/i) {
628 if ($myname ne "" && $$opts{pap_id
} ne "" &&
629 $myname ne $$opts{pap_id
}) {
630 warn "pppd cannot have separate local names for PAP and CHAP; using CHAP name:\n";
631 warn "\t\"$myname\"\n";
633 $myname = $$opts{pap_id
} if $$opts{pap_id
} ne "";
635 $psecret = $$opts{pap_password
};
637 if ($$opts{will_do_authentication
}) {
639 ($$opts{will_do_authentication
} !~ /chap/i ||
640 $$opts{will_do_authentication
} !~ /pap/i ||
641 $csecret eq $psecret)) {
643 "password " . requote
($csecret ?
$csecret : $psecret));
646 push @
$pppdargs, "user " . requote
($myname);
647 push(@
$pppdargs, "remotename " . requote
($peer))
648 if $peer && !$$opts{require_authentication
};
650 $myname = "NeverAuthenticate";
653 push(@
$pppdargs, "debug") if $$opts{debug_level
} >= 8;
654 push(@
$pppdargs, "kdebug 3") if $$opts{debug_level
} >= 9;
655 local($lcladdr, $remaddr) = ifconf_addr
($$ifconfig{$$opts{interface
}});
657 if ($$opts{debug_level
} >= 4) {
658 push(@pppdargs, "connect \"/usr/bin/chat -vf $chatpath\"");
660 push(@pppdargs, "connect \"/usr/bin/chat -f $chatpath\"");
662 push(@
$pppdargs, "user " . requote
($myname));
663 local($str) = $remaddr;
664 $str = $$opts{peer_ip_address
} if $$opts{peer_ip_address
};
665 push(@
$pppdargs, $lcladdr . ":" . $str)
666 if !$opt_s && ($lcladdr || $str);
668 push(@
$pppdargs, "user " . requote
($myname))
669 if $myname eq "NeverAuthenticate";
671 if ($$opts{interface
} && $opt_s) {
672 if ($$opts{interface
} =~ /^ipd[0-9]+$/) {
673 push(@
$pppdargs, $lcladdr . ":") if $lcladdr;
674 } elsif ($$opts{interface
} =~ /^ipd(|ptp)([0-9]+)$/) {
675 push(@pppdargs, "unit " . $2);
677 push(@pppdargs, "plumbed");
681 # Convert the secrets
684 } elsif ($$opts{peer_ip_address
}) {
685 $addsecret = " " . $$opts{peer_ip_address
};
689 if ($$opts{require_authentication
}) {
690 local($lclname, $secret, $authf);
691 $lclname = $$opts{will_do_authentication
} ?
$myname : hostname
();
692 if ($$opts{require_authentication
} =~ /chap/) {
693 $secret = $$opts{chap_peer_secret
};
694 $authf = \
%chapsecrets;
696 $secret = $$opts{pap_peer_password
};
697 $authf = \
%papsecrets;
699 ${$$authf{$peer}}{$lclname} = requote
($secret) . $addsecret;
701 if ($$opts{will_do_authentication
} && !$passopt) {
702 ${$chapsecrets{$myname}}{$peer} = requote
($csecret) if $csecret;
703 ${$papsecrets{$myname}}{$peer} = requote
($psecret) if $psecret;
707 # Translate options for a dial-in user.
712 $optname = $$dialinusers{$peer};
713 $optname .= "/" if $optname !~ /\
/$/;
714 $optname .= ".ppprc";
715 if (exists($optfiles{$optname})) {
716 warn "Home directories of $peer and $optuser{$optname} are the same ($optfiles{$optname}\n";
717 warn "Ignoring configuration for $peer.\n";
720 $optuser{$optname} = $peer;
721 $dialinshell{$peer} = "/usr/bin/pppd";
723 convert_options
(\
@pppdargs, $$paths{$peer}, undef, $peer);
724 push @pppdargs, "nologfd";
725 $optfiles{$optname} = \
@pppdargs;
728 # Translate ifconfig entries in asppp.cf into either an ifconfig
729 # script for strict translation or a set of per-port IP addresses
730 # for normal translation. Also translate ipdX interfaces into
731 # Ethernet aliases to make routing daemon happy.
732 sub translateifconfig
734 local (@ifconfiglist,$cstr,$etherif,$intf,$ifconf,$addstr,$port);
736 open IFLIST
, "/usr/sbin/ifconfig -au4|" || die "cannot run ifconfig: $!\n";
738 $etherif = $1 if !$etherif && /^([^:]*).*UP.*BROADCAST/;
741 $etherif = $1 if !$etherif && glob("/etc/hostname.*") =~ /[^\.]*.(.*)/;
742 $etherif = $1 if !$etherif && glob("/etc/dhcp.*") =~ /[^\.]*.(.*)/;
743 $etherif = "hme0" if !$etherif;
746 foreach $intf (keys %$ifconfig) {
747 $ifconf = $$ifconfig{$intf};
748 if ($intf =~ /ipd[0-9]+/) {
750 $cstr .= "ifconfig $etherif addif @$ifconf\n";
754 $ndialin = 0+(keys %$dialin);
756 foreach $intf (keys %downif) {
757 $ifconf = $downif{$intf};
758 if ($intf =~ /ipdptp([0-9]+)/ && --$ndialin >= 0) {
759 push @ifconfiglist, $ifconf;
760 $addstr .= "ifconfig sppp" . $1 . " @$ifconf\n";
765 print "Fewer ifconfigs (", $#ifconfiglist+1,
766 ") than dial-in lines (", $ndialin+$#ifconfiglist+1, ")\n";
768 print "No ifconfigs for ";
769 nof
$ndialin, "dial-in port", ".\n";
771 } elsif ($ndialin < 0) {
773 print "Ignoring ", -$ndialin, " of ";
774 nof
$#ifconfiglist-$ndialin+1, "ifconfig",
775 " (too few dial-in ports)\n";
777 print "Ignoring all ";
778 nof
-$ndialin, "ifconfig line", " (no dial-in ports)\n";
783 # Strict translation uses pre-plumbed interfaces.
786 foreach $port (values %$dialin) {
787 last if !@ifconfiglist;
790 $optfile = $ttyprefix . $port;
791 $ifconf = pop @ifconfiglist;
792 local ($lcladdr, $remaddr) = ifconf_addr
($ifconf);
793 next if !defined($lcladdr) || !defined($remaddr);
794 local (@pppdargs) = $lcladdr . ":" . $remaddr;
795 $optfiles{$optfile} = \
@pppdargs;
798 $scriptfiles{$pppdir . "ifconfig"} = $cstr if $cstr;
801 # Attempt to modify global passwd file using sed script stored in
802 # the $sedpasswd temporary file.
805 print "Updating local passwd file (if any).\n" if $opt_v;
806 if (!sysopen(PWDLCK
, $passwdlck, O_WRONLY
|O_CREAT
, 0600)) {
807 warn "Unable to lock password file: $!\n";
809 $lockstr = pack "ssLLiiLLLL", F_WRLCK
, 0, 0, 0, 0, 0, 0, 0, 0, 0;
811 local $SIG{ARLM
} = sub {
812 die "alarm while locking password file\n"
815 fcntl PWDLCK
, F_SETLKW
, $lockstr ||
816 die "cannot lock password file: $!\n";
822 warn "Password update failed.\n"
823 if (system("sed -f $sedpasswd < $passwd > ${passwd}.new") ||
824 !(rename "${passwd}.new", $passwd));
826 $lockstr = pack "ssLLiiLLLL", F_UNLCK
, 0, 0, 0, 0, 0, 0, 0, 0, 0;
827 fcntl PWDLCK
, F_SETLK
, $lockstr;
830 if (($ypmaster = `/usr/bin/ypwhich 2>/dev/null`) && $?
== 0) {
831 $ypmaster =~ /(.*)\n/;
832 ($ypmaster) = gethostbyname($1);
833 ($thishost) = gethostbyname(hostname
);
834 if ($ypmaster eq $thishost) {
835 system("cd /var/yp && make")
836 if yesno
("Rebuild NIS/YP maps", $opt_y);
838 warn "Not running on NIS/YP master $1; unable to update user shells\n";
839 print "Use 'sed -f $sedpasswd <$passwd >${passwd}.new' on the master\n";
840 print "and then remake the NIS/YP database.\n";
844 unlink $sedpasswd if $sedpasswd;
847 # Show usage message.
851 print "\t$0 [-rsvy]\n\n";
852 print " -n - non-interactive mode.\n";
853 print " -r - revert back to aspppd configuration.\n";
854 print " -s - use strict translation.\n";
855 print " -v - print more detail of the operations performed.\n";
856 print " -y - assume 'yes' as default answer where reasonable.\n";
860 # Correct an environment variable so that it points at either a useful
861 # executable program, or nothing at all.
864 local ($prog, $deflt) = @_;
866 $prog = $deflt if $prog eq "";
867 if ($prog !~ /^(\.\/|\
/)/) {
868 local ($_) = $ENV{PATH
};
869 $_ = "/bin:/usr/bin:/sbin:/usr/sbin" if $_ eq "";
872 $prog = $_ . "/" . $prog, last if -x
$_ . "/" . $prog;
875 $prog = "" if !(-x
$prog);
879 getopts
('nrsvy') || usage
;
881 die "Need permission to modify system files.\n"
882 unless ($> == 0 || yesno
"This script should be run as root. Continue");
887 # Revert to previous configuration. Just rename the aspppd file back
888 # and undo changes to the passwd file.
890 die "No saved aspppd configuration exists.\n" unless -f
$asmoved;
892 die "$astemp is not a file\n" unless -f
$asfile;
893 unlink $astemp || die "Cannot remove temporary $astemp: $!\n";
897 die "$asfile is not a file\n" unless -f
$asfile;
898 die "Not modifying configuration.\n"
899 unless yesno
"Remove existing $asfile", $opt_y;
900 rename $asfile, $astemp || die "Cannot rename existing $asfile: $!\n";
904 if (rename $asmoved, $asfile) {
905 unlink $astemp || warn "$astemp: $!\n" if $intemp;
907 $failure = "Cannot rename $asmoved to $asfile: $!\n";
908 rename $astemp, $asfile ||
909 die "$failure\nand cannot recover: $!\n" .
910 "Saved current asppp.cf in $astemp\n"
918 system($pppdctl, "stop") if -x
$pppdctl;
919 # remove pppd autostart files.
920 unlink $pppdir . "ifconfig";
921 unlink $pppdir . "demand";
923 system($asctl, "start") if -x
$asctl;
925 open SEDFILE
, ">$sedpasswd" || die "Cannot write $sedpasswd: $!\n";
926 local ($escdir) = $pppdir;
927 $escdir =~ s
+/+\\/+g
;
928 print SEDFILE
"/${escdir}dial-in\\./s+[^:]*\$+/usr/sbin/aspppls+\n";
929 print SEDFILE
"/\\/usr\\/bin\\/pppd/s+[^:]*\$+/usr/sbin/aspppls+\n";
939 die "No aspppd configuration exists; nothing to convert.\n"
941 die "No changes made.\n"
942 unless yesno
"Already converted; rerun anyway";
946 print "This script provides only a suggested translation for your existing aspppd\n";
947 print "configuration. You will need to evaluate for yourself whether the translation\n";
948 print "is appropriate for your operating environment.\n";
949 die "No changes made.\n"
950 unless yesno
"Continue", 1;
952 # Read in the asppp.cf file first; there's no reason to continue on to
953 # the UUCP files if this file isn't readable or has no paths defined.
954 local($ifconfig, $paths) = readaspppcf
($aspppcf);
956 # Loop over the ifconfigs and build a list of the down ones.
957 foreach $intf (keys %$ifconfig) {
958 local(@words) = @
{$$ifconfig{$intf}};
959 while ($word = shift @words) {
960 shift @words if $ifconfigtakes{$word};
961 if ($word =~ /^down$/) {
962 warn("Why is $intf declared down?\n"), last
963 if $intf =~ /^ipd[0-9]+$/;
964 $downif{$intf} = $$ifconfig{$intf};
965 delete $$ifconfig{$intf};
971 # Read /etc/passwd for dial-in users configured for aspppd.
972 local($dialinusers) = readpasswd
;
974 # Read in existing pppd configuration. All we really care about
975 # is the setting of the "auth" option.
977 if (open(OPTIONS
,"<" . $options)) {
978 while (@
{$words = uucpline
(OPTIONS
, $options)}) {
979 while ($_ = pop @
$words) {
980 $authoption = $_ if /auth/i;
984 $authoption = "unknown" if !defined($authoption);
988 if ($authoption =~ /^auth$/i) {
990 } elsif ($authoption =~ /^noauth$/i) {
992 } elsif (defined($authoption)) {
996 # Check that there's a path for each dial in user
997 foreach $user (keys %$dialinusers) {
998 if (!defined($$paths{$user})) {
999 warn "Dial-in user ", $user,
1000 " does not have a corresponding dial-in path.\n";
1001 delete $$dialinusers{$user};
1004 $intf = ${$$paths{$user}}{"interface"};
1005 if ($intf eq "ipdptp*") {
1006 if (0+keys(%downif) == 0) {
1007 warn "Dial-in user $path has no available \"down\" interfaces.\n";
1008 delete $$dialinusers{$user};
1012 if (!defined($downif{$intf}) && !defined($$ifconfig{$intf})) {
1013 warn "Dial-in path $user has undefined $intf; deleted.\n";
1014 delete $$dialinusers{$user};
1018 ${$$paths{$user}}{$isdialin} = 1;
1019 # 0 - no info (no options file, "noauth" on call)
1020 # 1 - all auth ("auth" in options, "noauth" on call)
1021 # 2 - all noauth ("noauth" in options)
1022 # 3 - mixed; use auth ("noauth" in options, wrapper script for "auth")
1023 if (${$$paths{$user}}{require_authentication
}) {
1024 if ($dialin_auth == 2) {
1026 } elsif ($dialin_auth == 0) {
1030 if ($dialin_auth == 1) {
1032 } elsif ($dialin_auth == 0) {
1038 # Get lists of usable dial-in and dial-out ports.
1039 local($dialin,$dialout) = getserialports
;
1041 # Read and parse the UUCP Sysfiles, Devconfig, and Limits files.
1042 # These are keyed with the "service=" string. The Sysfiles file can
1043 # augment or override the list of files read for a given service.
1044 print "Reading UUCP configuration.\n" if $opt_v;
1045 @sysfiles = @
{${uucpkeyfile
($Sysfiles,"service=")}{"ppp"}};
1046 @limits = @
{${uucpkeyfile
($Limits,"service=")}{"ppp"}};
1047 %devconfig = %{uucpkeyfile
($Devconfig,"service=ppp","device=")};
1049 # Now read in the UUCP files corresponding to this service.
1050 $systems = uucpposfiles
(uucpfiles
("systems"));
1051 $dialers = uucpposfiles
(uucpfiles
("dialers"));
1052 $dialcodes = uucpposfiles
($Dialcodes);
1053 $devices = uucpdevices
(uucpfiles
("devices"));
1056 $$dialcodes{""} = ();
1058 # Loop over paths. Dial-out only paths are translated into demand-dial
1059 # configurations. Dial-in only paths are translated into appropriate
1061 local (@bidirectional);
1062 foreach $peer (keys %$paths) {
1063 if (exists($$systems{$peer})) {
1064 $sline = $$systems{$peer};
1065 if ($$sline[0] eq "Never") {
1066 if (${$$paths{$peer}}{$isdialin}) {
1067 translatedialin
($peer);
1069 print "We never call $peer, and he never calls us.\n"
1072 delete $$paths{$peer};
1075 push @bidirectional, $peer if ${$$paths{$peer}}{$isdialin};
1076 print "Ignoring time restriction on $peer\n"
1077 if $$sline[0] ne "Any";
1078 $dlist = $$devices{$$sline[1]};
1079 $class = $$sline[2];
1081 while ($i < @
$dlist) {
1082 local($dev) = $$dlist[$i];
1083 if ($$dev[1] ne "-") {
1084 print "Ignoring device $$dev[0]; 801-type not supported.\n";
1085 splice @
$dlist, $i, 1;
1090 # Make sure that classes match.
1091 next if $$dev[2] ne "Any" && $class ne "Any" && $$dev[2] ne $class;
1092 # Prepend "/dev/" if it's not present in the device name.
1093 if (exists($$dialout{$$dev[0]})) {
1094 # This just seems odd.
1095 $dname = $$dialout{$$dev[0]};
1096 $dname =~ s
+/dev/term
/+/dev
/cua/+;
1098 $dname = ($$dev[0] =~ m
+^/+ ? $$dev[0] : ("/dev
/" . $$dev[0]));
1100 # Skip devices that aren't supposed to be used for dial-out.
1101 next if $dname =~ m+^/dev/term/+;
1102 next if $dname =~ m+^/dev/tty[a-z]$+;
1103 # Make sure this is a character device and we have access to it.
1104 next unless -w $dname && -c $dname;
1105 warn "Dialer
for $$dev[3] is missing
.\n"
1106 unless exists($warned{$$dev[3]}) ||
1107 exists($$dialers{$$dev[3]});
1108 $warned{$$dev[3]} = 1;
1110 # Expand keywords from Dialcodes file. Should have \T or \D.
1111 $phone = $$sline[3];
1112 $xphone = ($$dev[4] eq "\\T
" && $phone =~ /^([A-Za-z]*)(.*)$/ ?
1113 "@
{$$dialcodes{$1}}" . $2 : $phone);
1115 # Make a copy of the dialing script.
1116 local(@dials) = @{$$dialers{$$dev[3]}};
1118 # Translate dial tone and wait characters from Dialers file.
1121 local($from,$to) = ($1,$2);
1122 $phone =~ s+(^|[^\\])$from+$1$to+gx;
1123 $xphone =~ s+(^|[^\\])$from+$1$to+gx;
1126 # Translate escapes in dial specification. Chat has a \T,
1127 # but uses \U instead of \D.
1128 local($needt, $needu, $isexpect, @chats) = ("", "", 1);
1129 foreach $str (@dials) {
1130 push(@chats, "") if $str eq "";
1133 while ($str =~ s/([^\\]*)\\(.)//) {
1134 local($lead, $_) = ($1, $2);
1135 /[Mm]/ ? ($ostr .= $lead) :
1136 /[Ee]/ ? ($sorrye = 1, $ostr .= $lead) :
1137 ($ostr .= $lead . "\\" . $_);
1140 while ($str =~ s/([^\\]*)\\(.)//) {
1141 local($lead, $_) = ($1, $2);
1142 /T/ ? ($needt = " -T
'$xphone'",
1143 $ostr .= $lead . "\\T
") :
1144 /D/ ? ($needu = " -U
'$phone'",
1145 $ostr .= $lead . "\\U
") :
1146 /M/ ? ($ostr .= $lead,
1147 ($ostr ne "" ? push(@chats, $ostr, "\\c
"):0),
1148 push(@chats, "HANGUP
", "OFF
"), $ostr = "") :
1149 /m/ ? ($ostr .= $lead,
1150 ($ostr ne "" ? push(@chats, $ostr, "\\c
"):0),
1151 push(@chats, "HANGUP
", "ON
"), $ostr = "") :
1152 /[Ee]/ ? ($sorrye = 1, $ostr .= $lead) :
1153 /[dp]/ ? ($ostr .= $lead . "\\" . $_ . "\\" . $_) :
1154 /c/ ? ($str eq "" ? ($ostr .= $lead . "\\c
") : 0) :
1155 ($ostr .= $lead . "\\" . $_);
1159 push @chats, $ostr if $ostr ne "";
1160 $isexpect = !$isexpect;
1163 # Pad out dial list if we're missing a "send" string and tack
1164 # on the chat list from the Systems file.
1165 if (defined $$sline[4]) {
1166 push @chats, "\\c
" if !$isexpect;
1167 push @chats, (splice @$sline, 4);
1170 $chatfile = $pppdir . "chat
.$peer.$$dev[3]";
1172 print "$chatfile already
exists.\n";
1173 if (!yesno("Should it be overwritten
",$opt_y)) {
1174 if (yesno("Should it be used as
-is
")) {
1175 warn "Using
$chatfile as
-is
; it may
not be correct
.\n";
1177 for ($n = 0; ; $n++) {
1178 last if !(-e $chatfile . "." . $n);
1180 $chatfile .= "." . $n;
1181 print "Using
$chatfile instead
.\n";
1182 $chatfiles{$chatfile} = \@chats;
1185 $overwrite{$chatfile} = 1;
1186 $chatfiles{$chatfile} = \@chats;
1189 $chatfiles{$chatfile} = \@chats;
1192 push @pppdargs, $dname;
1193 push @pppdargs, $class if $class =~ /^[0-9]+$/;
1194 push @pppdargs, "demand
";
1195 convert_options(\@pppdargs,$$paths{$peer},
1196 $chatfile . $needt . $needu, undef);
1198 $optname = $peersdir . $peer;
1200 print "$optname already
exists.\n";
1201 if (!yesno("Should it be overwritten
", $opt_y)) {
1202 if (yesno("Should it be used as
-is
")) {
1203 warn "Using
$optname as
-is
; it may
not be correct
.\n";
1205 for ($n = 0; ; $n++) {
1206 last if !(-e $optname . "." . $n);
1208 $optname .= "." . $n;
1209 print "Using
$optname instead
.\n";
1210 $optfiles{$optname} = \@pppdargs;
1213 $overwrite{$optname} = 1;
1214 $optfiles{$optname} = \@pppdargs;
1217 $optfiles{$optname} = \@pppdargs;
1219 $scriptfiles{$pppdir . "demand
"} .= "/usr/bin
/pppd file
$optname\n";
1222 } elsif (${$$paths{$peer}}{$isdialin}) {
1223 translatedialin($peer);
1225 warn "Path
$peer has
no dial
-in user nor Systems file entry
.\n";
1226 delete $$paths{$peer};
1230 warn "Chat cannot
do echo checking
; requests
for this removed
.\n" if $sorrye;
1232 if (@bidirectional) {
1233 print "\nWarning
: The following paths are bidirectional
:\n";
1234 print "\t@bidirectional\n\n";
1235 print "Bidirectional paths
(with entries
in both Systems
and passwd
) do not translate
\n";
1236 print "into Solaris PPP
4.0 semantics
in an exact manner
. The dial
-out portion will
\n";
1237 print "use the designated interface
, but the dial
-in portion will
use any available
\n";
1238 print "interface
.\n";
1239 while ($peer = pop @bidirectional) {
1240 delete $ {$$paths{$peer}}{interface};
1241 translatedialin($peer);
1247 # Create an /etc/ppp/options if we need to.
1248 if (!defined($authoption) && $dialin_auth > 0) {
1250 push @pppdopts, "lock";
1251 push @pppdopts, "auth
" if $dialin_auth == 1;
1252 push @pppdopts, "noauth
" if $dialin_auth > 1;
1253 $optfiles{$options} = \@pppdopts;
1255 # Translate option files to plain text.
1256 foreach $file (keys %optfiles) {
1257 local ($opts) = $optfiles{$file};
1259 $cstr .= shift(@$opts) . "\n" while @$opts;
1260 $optfiles{$file} = $cstr;
1262 # Change "auth
" to "noauth
" or add "noauth
" to /etc/ppp/options.
1263 if (defined($authoption) && $authoption ne "noauth
" && $dialin_auth == 3) {
1264 local(@triplet, $cstr);
1265 if ($authoption eq "unknown
") {
1266 warn "Adding
'noauth' to
$options\n";
1268 warn "Changing
'auth' in $options to
'noauth'\n";
1270 open(OPTIONS,"<" . $options) || die "$options disappeared
: $!\n";
1271 while (@{$words = uucpline(OPTIONS, $options, \@triplet)}) {
1272 $cstr .= $triplet[0];
1273 if (grep(/auth/, @$words)) {
1274 local(@newwords) = map { $_ = "noauth
" if /auth/; $_ } @$words;
1275 $cstr .= "@newwords";
1277 $cstr .= $triplet[1];
1279 while (pop @$words) {
1280 $authoption = $_ if /auth/i;
1282 $cstr .= $triplet[2];
1284 $cstr .= $triplet[0] . $triplet[2];
1286 $cstr .= "\n" if $cstr !~ /\n$/;
1287 $cstr .= "noauth
\n" if $authoption eq "unknown
";
1288 $optfiles{$options} = $cstr;
1291 # Create a sed script to fix the users' shell paths.
1292 if (0+(keys %dialinshell) != 0) {
1294 foreach $peer (keys %dialinshell) {
1295 $cstr .= "/^$peer:/s+[^:]*/aspppls\
$+$dialinshell{$peer}+\n";
1297 $scriptfiles{$sedpasswd} = $cstr;
1300 print "\nPreparing to
write out translated configuration
:\n";
1302 # Enumerate the files we'll write.
1304 if (0+(keys %chatfiles) != 0) {
1306 nof 0+(keys %chatfiles), "chat file
", ":\n";
1307 foreach $file (keys %chatfiles) {
1309 print "\t$nfiles. $file\n";
1310 local ($chats) = $chatfiles{$file};
1313 $cstr .= requote(shift(@$chats));
1314 $cstr .= " " . requote(shift(@$chats)) if @$chats;
1317 local (@filerec) = ( $file, $cstr );
1318 push @allfiles, \@filerec;
1321 if (0+(keys %optfiles) != 0) {
1323 nof 0+(keys %optfiles), "option file
", ":\n";
1324 foreach $file (keys %optfiles) {
1326 print "\t$nfiles. $file\n";
1327 local (@filerec) = ( $file, $optfiles{$file} );
1328 push @allfiles, \@filerec;
1331 if (0+(keys %scriptfiles) != 0) {
1333 nof 0+(keys %scriptfiles), "script file
", ":\n";
1334 foreach $file (keys %scriptfiles) {
1336 print "\t$nfiles. $file\n";
1337 local (@filerec) = ( $file, $scriptfiles{$file} );
1338 push @allfiles, \@filerec;
1342 # Merge new secrets needed with existing ones, if any.
1345 local ($addsecrets, $fname) = @_;
1346 local ($file, $cstr, @triplet, $newsecret);
1349 $file = $pppdir . $fname;
1350 print "\t$nfiles. $file\n";
1351 if (open(SECRETS, '<' . $pppdir . $fname)) {
1352 while (@{$words = uucpline(SECRETS, $pppdir . $fname, \@triplet)}) {
1353 $cstr .= $triplet[0];
1354 $newsecret = $ {$$addsecrets{$$words[0]}}{$$words[1]};
1355 if (defined $newsecret) {
1356 $cstr .= requote($$words[0]) . " " . requote($$words[1]) .
1358 delete $ {$$addsecrets{$$words[0]}}{$$words[1]};
1360 $cstr .= $triplet[1];
1362 $cstr .= $triplet[2];
1365 $cstr .= $triplet[0] . $triplet[2];
1367 foreach $key1 (keys (%$addsecrets)) {
1368 foreach $key2 (keys (%{$$addsecrets{$key1}})) {
1369 $cstr .= requote($key1) . " " . requote($key2) . " " .
1370 $ {$$addsecrets{$key1}}{$key2} . "\n";
1373 local (@filerec) = ( $file, $cstr );
1374 push @allfiles, \@filerec;
1377 $nchap = 0+(keys %chapsecrets) != 0;
1378 $npap = 0+(keys %papsecrets) != 0;
1379 if ($nchap != 0 || $npap != 0) {
1381 nof $nchap + $npap, "secrets file
", ":\n";
1382 merge_secrets(\%chapsecrets, "chap
-secrets
") if $nchap != 0;
1383 merge_secrets(\%papsecrets, "pap
-secrets
") if $npap != 0;
1386 die "Nothing to
write back
; I
'm done.\n" if $nfiles == 0;
1388 $PAGER = fixpath($ENV{PAGER}, "/usr/bin/less");
1389 $EDITOR = fixpath($ENV{EDITOR}, "/usr/bin/vi");
1390 $SHELL = fixpath($ENV{SHELL}, "/usr/bin/ksh");
1394 unlink($tempname) or
1395 die "Cannot remove temporary file $tempname: $!\n";
1399 sub show_file_options
1401 print "\nEnter option number:\n";
1402 print "\t1 - view contents of file on standard output\n";
1403 print "\t2 - view contents of file using $PAGER\n" if $PAGER ne "";
1404 print "\t3 - edit contents of file using $EDITOR\n" if $EDITOR ne "";
1405 print "\t4 - delete/undelete file from list\n";
1406 print "\t5 - rename file in list\n";
1407 print "\t6 - show file list again\n";
1408 print "\t7 - escape to shell (or \"!cmd\")\n";
1409 print "\t8 - abort without saving anything\n";
1410 print "\t9 - save all files and exit (default)\n";
1413 # If interactive, then allow user to view and modify converted data.
1414 if ((-t STDIN) && (-t STDOUT) && !$opt_n) {
1415 show_file_options();
1418 chomp($ans = <STDIN>);
1419 if ($ans eq "?" || $ans =~ /^h/i) {
1420 show_file_options();
1424 last if yesno "Saving all files. Are you sure";
1428 print("Aborted.\n"), exit if $ans == 8;
1429 if ($ans =~ /^!/ || $ans == 7) {
1430 if ($ans =~ /^!(.+)/) {
1433 print("Interactive shell access not permitted here.\n"), next
1437 } elsif ($ans == 6) {
1438 for ($i = 0; $i < $nfiles; $i++) {
1439 print "\t", $i+1, ". $allfiles[$i][0]",
1440 ($deleted[$i] ? " (deleted)" : ""), "\n";
1442 } elsif ($ans > 0 && $ans < 6) {
1445 print "File number (1 .. $nfiles): ";
1446 chomp($fnum = <STDIN>);
1447 if ($fnum < 1 || $fnum > $nfiles) {
1448 print "Unknown file (must be 1 to $nfiles).\n";
1454 print "Current name is $allfiles[$fnum][0]\n";
1456 chomp($fname = <STDIN>);
1457 print("Unchanged\n"), next if $fname eq "";
1458 $allfiles[$fnum][0] = $fname;
1460 if ($deleted[$fnum]) {
1461 if (yesno("File " . $fnum+1 .
1462 " ($allfiles[$fnum][0]) is deleted; undelete",1)) {
1463 undef $deleted[$fnum];
1468 print $allfiles[$fnum][1];
1469 } elsif ($ans == 2 && $PAGER ne "") {
1473 warn "Unable to open temporary file: $!";
1477 $tempname = tmpnam();
1478 } until sysopen(FH, $tempname, O_RDWR|O_CREAT|O_EXCL);
1480 print FH $allfiles[$fnum][1];
1482 system($PAGER, $tempname);
1483 unlink($tempname) ||
1484 warn "Trouble removing temporary file: $!";
1486 } elsif ($ans == 3 && $EDITOR ne "") {
1490 warn "Unable to open temporary file: $!";
1494 $tempname = tmpnam();
1495 } until sysopen(FH, $tempname, O_RDWR|O_CREAT|O_EXCL);
1497 chown $<, $(, $tempname;
1498 print FH $allfiles[$fnum][1];
1500 $i = system($EDITOR, $tempname);
1502 if (open FH, "<" . $tempname) {
1503 read FH, $allfiles[$fnum][1], (-s $tempname);
1507 print "Editor dropped core.\n" if $? & 128;
1508 print "Editor terminated on signal ", $? & 127, "\n"
1510 print "Editor returned error ", $? >> 8, "\n"
1513 unlink($tempname) ||
1514 warn "Trouble removing temporary file: $!";
1516 } elsif ($ans == 4) {
1517 $deleted[$fnum] = 1;
1525 # Interactive part is over. Become real.
1529 print "Stopping aspppd\n" if $opt_v;
1530 system($asctl, "stop") if -x $asctl;
1532 print "Saving all files\n" if $opt_v;
1533 for ($i = 0; $i < $nfiles; $i++) {
1534 $filerec = $allfiles[$i];
1536 delete $scriptfiles{$$filerec[0]};
1539 print "Saving $$filerec[0]\n" if $opt_v;
1540 $$filerec[0] =~ m+(.*)/+;
1542 # this is ok; just a top level file
1543 } elsif (!(-d $1)) {
1544 local ($exdir) = $1;
1545 while ($exdir && !(-d $exdir)) {
1551 $dir =~ m+$exdir/([^/]*)(.*)+;
1552 local ($tomake, $rest) = ($1, $2);
1553 mkdir $exdir . "/" . $tomake, 0775;
1555 warn "Unable to make directory $exdir/$tomake; automount point.\n";
1559 warn "Unable to make directory $exdir/$tomake: $!\n";
1562 if (system("mkdir", "-p", $dir) != 0) {
1563 warn "Failed to make $dir\n";
1567 warn "$1 doesn't appear to have a useful path
.\n";
1572 local ($fname) = $$filerec[0];
1573 if (-e $fname && !$overwrite{$chatfile}) {
1574 print "$fname already
exists.\n"
1575 if (-t STDIN) && (-t STDOUT) && !$opt_n;
1576 if (!yesno("Should it be overwritten
",$opt_y)) {
1577 warn "Using
$fname as
-is
; it may
not be correct
.\n";
1581 if (sysopen(OUTFILE, $$filerec[0], O_WRONLY|O_CREAT|O_TRUNC, 0600)) {
1582 print OUTFILE $$filerec[1] || ($fileerr = $!);
1583 close OUTFILE || ($fileerr = $!);
1587 warn "Unable to
write $$filerec[0]: $fileerr\n" if $fileerr;
1590 local(@scripts) = keys %scriptfiles;
1592 print "Making scripts executable
\n" if $opt_v;
1593 system("chmod", "u
+x
", @scripts);
1596 rewrite_passwd if exists($scriptfiles{$sedpasswd});
1598 # clean up after a previous translation.
1599 unlink $pppdir . "ifconfig
" if !$scriptfiles{$pppdir . "ifconfig
"};
1600 unlink $pppdir . "demand
" if !$scriptfiles{$pppdir . "demand
"};
1602 (rename($asfile, $asmoved) || warn "Cannot move
$asfile: $!\n")
1603 if $aspppcf ne $astemp;
1605 system($pppdctl, "start
") if -x $pppdctl;
1608 # my $dumper = new Dumpvalue;
1609 # $dumper->set(globPrint => 1);
1610 # $dumper->dumpValue($ifconfig);