File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / mkdep.pl
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:53 2014 UTC (10 years ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

    1: #!/usr/bin/env perl
    2: #
    3: # Copyright (c) 2011-2014 Todd C. Miller <Todd.Miller@courtesan.com>
    4: #
    5: # Permission to use, copy, modify, and distribute this software for any
    6: # purpose with or without fee is hereby granted, provided that the above
    7: # copyright notice and this permission notice appear in all copies.
    8: #
    9: # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10: # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11: # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12: # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13: # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14: # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15: # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16: #
   17: 
   18: use File::Temp qw/ :mktemp  /;
   19: use Fcntl;
   20: use warnings;
   21: 
   22: die "usage: $0 Makefile ...\n" unless $#ARGV >= 0;
   23: 
   24: my @incpaths;
   25: my %dir_vars;
   26: my %implicit;
   27: my %generated;
   28: 
   29: # Read in MANIFEST fail if present
   30: my %manifest;
   31: if (open(MANIFEST, "<MANIFEST")) {
   32:     while (<MANIFEST>) {
   33: 	chomp;
   34: 	next unless /([^\/]+\.[cly])$/;
   35: 	$manifest{$1} = $_;
   36:     }
   37: }
   38: 
   39: foreach (@ARGV) {
   40:     mkdep($_);
   41: }
   42: 
   43: sub mkdep {
   44:     my $file = $_[0];
   45:     $file =~ s:^\./+::;		# strip off leading ./
   46: 
   47:     my $makefile;
   48:     if (open(MF, "<$file")) {
   49: 	local $/;		# enable "slurp" mode
   50: 	$makefile = <MF>;
   51:     } else {
   52: 	warn "$0: $file: $!\n";
   53: 	return undef;
   54:     }
   55:     close(MF);
   56: 
   57:     # New makefile, minus the autogenerated dependencies
   58:     my $separator = "# Autogenerated dependencies, do not modify";
   59:     my $new_makefile = $makefile;
   60:     $new_makefile =~ s/${separator}.*$//s;
   61:     $new_makefile .= "$separator\n";
   62: 
   63:     # Old makefile, join lines with continuation characters
   64:     $makefile =~ s/\\\n//mg;
   65: 
   66:     # Expand some configure bits
   67:     $makefile =~ s:\@DEV\@::g;
   68:     $makefile =~ s:\@COMMON_OBJS\@:aix.lo event_poll.lo event_select.lo:;
   69:     $makefile =~ s:\@SUDO_OBJS\@:openbsd.o preload.o selinux.o sesh.o solaris.o sudo_noexec.lo:;
   70:     $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo sssd.lo:;
   71:     # XXX - fill in AUTH_OBJS from contents of the auth dir instead
   72:     $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
   73:     $makefile =~ s:\@LTLIBOBJS\@:clock_gettime.lo closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getgrouplist.lo getline.lo getopt_long.lo glob.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo pw_dup.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo strtonum.lo utimes.lo globtest.o fnm_test.o inet_pton:;
   74: 
   75:     # Parse OBJS lines
   76:     my %objs;
   77:     while ($makefile =~ /^[A-Z0-9_]*OBJS\s*=\s*(.*)/mg) {
   78: 	foreach (split/\s+/, $1) {
   79: 	    next if /^\$[\(\{].*[\)\}]$/; # skip included vars for now
   80: 	    $objs{$_} = 1;
   81: 	}
   82:     }
   83: 
   84:     # Find include paths
   85:     @incpaths = ();
   86:     while ($makefile =~ /-I(\S+)/mg) {
   87: 	push(@incpaths, $1) unless $1 eq ".";
   88:     }
   89: 
   90:     # Check for generated files
   91:     if ($makefile =~ /GENERATED\s*=\s*(.+)$/m) {
   92: 	foreach (split(/\s+/, $1)) {
   93: 	    $generated{$_} = 1;
   94: 	}
   95:     }
   96: 
   97:     # Values of srcdir, top_srcdir, top_builddir, incdir
   98:     %dir_vars = ();
   99:     $file =~ m:^(.*)/+[^/]+:;
  100:     $dir_vars{'srcdir'} = $1 || '.';
  101:     $dir_vars{'devdir'} = $dir_vars{'srcdir'};
  102:     $dir_vars{'authdir'} = $dir_vars{'srcdir'} . "/auth";
  103:     $dir_vars{'top_srcdir'} = '.';
  104:     #$dir_vars{'top_builddir'} = '.';
  105:     $dir_vars{'incdir'} = 'include';
  106: 
  107:     # Find implicit rules for generated .o and .lo files
  108:     %implicit = ();
  109:     while ($makefile =~ /^\.c\.(l?o):\s*\n\t+(.*)$/mg) {
  110: 	$implicit{$1} = $2;
  111:     }
  112: 
  113:     # Find existing .o and .lo dependencies
  114:     my %old_deps;
  115:     while ($makefile =~ /^(\w+\.l?o):\s*(\S+\.c)/mg) {
  116: 	$old_deps{$1} = $2;
  117:     }
  118: 
  119:     # Sort files so we do .lo files first
  120:     foreach my $obj (sort keys %objs) {
  121: 	next unless $obj =~ /(\S+)\.(l?o)$/;
  122: 	if ($2 eq "o" && exists($objs{"$1.lo"})) {
  123: 	    # If we have both .lo and .o files, make the .o depend on the .lo
  124: 	    $new_makefile .= sprintf("%s: %s.lo\n", $obj, $1);
  125: 	} else {
  126: 	    # Use old depenencies when mapping objects to their source.
  127: 	    # If no old depenency, use the MANIFEST file to find the source.
  128: 	    my $src = $1 . '.c';
  129: 	    my $ext = $2;
  130: 	    if (exists $old_deps{$obj}) {
  131: 		$src = $old_deps{$obj};
  132: 	    } elsif (exists $manifest{$src}) {
  133: 		$src = $manifest{$src};
  134: 		foreach (sort { length($b) <=> length($a) } keys %dir_vars) {
  135: 		    next if $_ eq "devdir";
  136: 		    last if $src =~ s:^\Q$dir_vars{$_}/\E:\$\($_\)/:;
  137: 		}
  138: 	    } else {
  139: 		warn "$file: unable to find source for $obj\n";
  140: 	    }
  141: 	    my $imp = $implicit{$ext};
  142: 	    $imp =~ s/\$</$src/g;
  143: 
  144: 	    my $deps = sprintf("%s: %s %s", $obj, $src,
  145: 		join(' ', find_depends($src)));
  146: 	    if (length($deps) > 80) {
  147: 		my $off = 0;
  148: 		my $indent = length($obj) + 2;
  149: 		while (length($deps) - $off > 80 - $indent) {
  150: 		    my $pos;
  151: 		    if ($off != 0) {
  152: 			$new_makefile .= ' ' x $indent;
  153: 			$pos = rindex($deps, ' ', $off + 80 - $indent - 2);
  154: 		    } else {
  155: 			$pos = rindex($deps, ' ', $off + 78);
  156: 		    }
  157: 		    $new_makefile .= substr($deps, $off, $pos - $off) . " \\\n";
  158: 		    $off = $pos + 1;
  159: 		}
  160: 		$new_makefile .= ' ' x $indent;
  161: 		$new_makefile .= substr($deps, $off) . "\n";
  162: 	    } else {
  163: 		$new_makefile .= "$deps\n";
  164: 	    }
  165: 	    $new_makefile .= "\t$imp\n";
  166: 	}
  167:     }
  168: 
  169:     my $newfile = $file . ".new";
  170:     if (!open(MF, ">$newfile")) {
  171: 	warn("cannot open $newfile: $!\n");
  172:     } else {
  173: 	print MF $new_makefile || warn("cannot write $newfile: $!\n");
  174: 	close(MF) || warn("cannot close $newfile: $!\n");;
  175: 	rename($newfile, $file);
  176:     }
  177: }
  178: 
  179: exit(0);
  180: 
  181: sub find_depends {
  182:     my $src = $_[0];
  183:     my ($deps, $code, %headers);
  184: 
  185:     if ($src !~ /\//) {
  186: 	# XXX - want build dir not src dir
  187: 	$src = "$dir_vars{'srcdir'}/$src";
  188:     }
  189: 
  190:     # resolve $(srcdir) etc.
  191:     foreach (keys %dir_vars) {
  192: 	$src =~ s/\$[\(\{]$_[\)\}]/$dir_vars{$_}/g;
  193:     }
  194: 
  195:     # find open source file and find headers used by it
  196:     if (!open(FILE, "<$src")) {
  197: 	warn "unable to open $src\n";
  198: 	return "";
  199:     }
  200:     local $/;		# enable "slurp" mode
  201:     $code = <FILE>;
  202:     close(FILE);
  203: 
  204:     # find all headers
  205:     while ($code =~ /^#\s*include\s+["<](\S+)[">]/mg) {
  206: 	my ($hdr, $hdr_path) = find_header($1);
  207: 	if (defined($hdr)) {
  208: 	    $headers{$hdr} = 1;
  209: 	    # Look for other includes in the .h file
  210: 	    foreach (find_depends($hdr_path)) {
  211: 		$headers{$_} = 1;
  212: 	    }
  213: 	}
  214:     }
  215: 
  216:     sort keys %headers;
  217: }
  218: 
  219: # find the path to a header file
  220: # returns path or undef if not found
  221: sub find_header {
  222:     my $hdr = $_[0];
  223: 
  224:     # Look for .h.in files in top_builddir and build dir
  225:     return ("\$(top_builddir\)/$hdr", "./${hdr}.in") if -r "./${hdr}.in";
  226:     return ("./$hdr", "$dir_vars{'srcdir'}/${hdr}.in") if -r "$dir_vars{'srcdir'}/${hdr}.in";
  227: 
  228:     if (exists $generated{$hdr}) {
  229: 	my $hdr_path = $dir_vars{'devdir'} . '/' . $hdr;
  230: 	return ('$(devdir)/' . $hdr, $hdr_path) if -r $hdr_path;
  231:     }
  232:     foreach my $inc (@incpaths) {
  233: 	my $hdr_path = "$inc/$hdr";
  234: 	# resolve variables in include path
  235: 	foreach (keys %dir_vars) {
  236: 	    next if $_ eq "devdir";
  237: 	    $hdr_path =~ s/\$[\(\{]$_[\)\}]/$dir_vars{$_}/g;
  238: 	}
  239: 	return ("$inc/$hdr", $hdr_path) if -r $hdr_path;
  240:     }
  241: 
  242:     undef;
  243: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>