1#!/usr/bin/env perl 2#- 3# Copyright (c) 2000 Mark Ovens 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer 11# in this position and unchanged. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# 27 28 29# Each port record in INDEX contains 10 fields, delimited by ``|'', some 30# of which may be empty. The fields are: 31# 32# distribution-name|port-path|installation-prefix|comment| \ 33# description-file|maintainer|categories|build deps|run deps|www site 34 35 36use strict; 37use Getopt::Std; 38use vars qw/ $key @list %fields %list %opts /; 39 40# 41# Global variables 42# 43 44my $osrel = `/usr/bin/uname -r`; 45$osrel =~ s/\..+$//s; 46 47my $portsdir = "/usr/mports"; 48$portsdir = $ENV{PORTSDIR} if ( defined $ENV{'PORTSDIR'} ); 49 50my $VERSION = "1.0"; 51my $file = "$portsdir/INDEX-$osrel"; 52my $match = 1; 53my $count = 0; 54my $fulldesc = 0; 55 56# We only need 7 of the 10 fields in a record; define which ones in a 57# hash slice to ignore the un-needed ones. This also makes it easy to 58# add or remove fields in the future. 59 60@fields{qw(n p i e m x b r)} = (0, 1, 3, 4, 5, 6, 7, 8); 61 62# 63# Print a basic help message 64# 65 66sub usage() { 67 print(STDERR " 68Usage: portsearch [-h] [-e] [-n name] [-p path] [-i info] [-m maint] [-x index] 69 [-b b_deps] [-r r_deps] [-d deps] [-f file] 70 71"); 72} # usage() 73 74# 75# Print a more verbose help message 76# 77 78sub help() { 79 print(STDERR "portsearch $VERSION - A utility for searching the ports tree. 80 81Options: 82 83 -n name Search for \"name\" in name of ports 84 -p path Search for \"path\" in location of ports 85 -i info Search for \"info\" in ports COMMENT 86 -m maint Search for \"maint\" in ports Maintainer 87 -x index Search for \"index\" in ports categories 88 -b b_deps Search for \"b_deps\" in build depends of ports 89 -r r_deps Search for \"r_deps\" in run depends of ports 90 -d deps Search for \"deps\" in both build & run depends of ports 91 -f file Use \"file\" instead of /usr/ports/INDEX 92 -e Show long description for all matching ports 93 -h Print this message and exit 94 95"); 96} # help() 97 98# 99# The program proper 100# 101 102MAIN: { 103 # No command-line args 104 if ($#ARGV == -1) { 105 usage(); 106 exit(1); 107 } 108 109 getopts('ehf:n:p:i:m:x:b:r:d:', \%opts); 110 # Process -e first, as it doesn't take 111 # arguments 112 if (defined($opts{"e"})) { 113 $fulldesc = 1; 114 delete $opts{"e"}; 115 } 116 # Command-line args, but without options 117 if (keys(%opts) == 0 ) { 118 # Default to name search if no constraints 119 # specified 120 if ($#ARGV == 0) { 121 $opts{"n"} = $ARGV[0]; 122 } else { 123 usage(); 124 exit(1); 125 } 126 } 127 # If ``-h'', ignore any other options 128 if (defined($opts{"h"})) { 129 help(); 130 exit(1); 131 } 132 # A different INDEX file 133 if (defined($opts{"f"})) { 134 $file = $opts{"f"}; 135 } 136 # If ``-d'' used we don't want ``-b'' & ``-r'' 137 if (defined($opts{"d"})) { 138 delete $opts{"b"}; 139 delete $opts{"r"}; 140 } 141 # Finished with it now so remove it from hash 142 delete $opts{"f"}; 143 144 open(INDEX, "$file") || die "Unable to open $file"; 145 146 while (<INDEX>) { 147 chomp; 148 @list = split(/\|/); 149 150 $match = 1; 151 # All searches are case-insensitive! 152 # For ``-d'' search both build & run depends. 153 # Only fail to match if not found in either. 154 foreach $key (keys (%opts)) { 155 if ($key eq "d") { 156 if ($list[$fields{"b"}] !~ m#$opts{$key}#i && 157 $list[$fields{"r"}] !~ m#$opts{$key}#i) { 158 $match = 0; 159 last; 160 } 161 } else { 162 if ($list[$fields{$key}] !~ m#$opts{$key}#i) { 163 $match = 0; 164 last; 165 } 166 } 167 } # foreach 168 169 if ($match == 1) { 170 $count++; 171 write; 172 if ($fulldesc) { 173 open my $pkgdescr, $list[$fields{"e"}] || next; 174 print while <$pkgdescr>; print "\n"; 175 close $pkgdescr; 176 } 177 } 178 179 } # while 180 181 close(INDEX); 182 183 print ("Number of matching ports = $count\n\n"); 184 185} # MAIN 186 187 188format STDOUT = 189 190Port: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 191$list[$fields{"n"}] 192Path: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 193$list[$fields{"p"}] 194Info: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 195$list[$fields{"i"}] 196~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 197$list[$fields{"i"}] 198Maint: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 199$list[$fields{"m"}] 200Index: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 201$list[$fields{"x"}] 202B-deps: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 203$list[$fields{"b"}] 204~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 205$list[$fields{"b"}] 206R-deps: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 207$list[$fields{"r"}] 208~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 209$list[$fields{"r"}] 210 211. 212