1#!/usr/bin/perl -w
2##
3# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4#
5# @APPLE_LICENSE_HEADER_START@
6#
7# This file contains Original Code and/or Modifications of Original Code
8# as defined in and that are subject to the Apple Public Source License
9# Version 2.0 (the 'License'). You may not use this file except in
10# compliance with the License. Please obtain a copy of the License at
11# http://www.opensource.apple.com/apsl/ and read it before using this
12# file.
13#
14# The Original Code and all software distributed under the License are
15# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19# Please see the License for the specific language governing rights and
20# limitations under the License.
21#
22# @APPLE_LICENSE_HEADER_END@
23##
24
25use strict;
26use Getopt::Long qw(GetOptions);
27
28sub usage {
29  print "fuser: [-cfu] file ...\n",
30    "\t-c\tfile is treated as mount point\n",
31    "\t-f\tthe report is only for the named files\n",
32    "\t-u\tprint username of pid in parenthesis\n";
33}
34
35Getopt::Long::config('bundling');
36my %o;
37unless (GetOptions(\%o, qw(c f u)) && scalar (@ARGV) > 0) {
38  usage();
39  exit(1);
40}
41
42use IO::Handle;
43STDERR->autoflush(1);
44STDOUT->autoflush(1);
45
46my $exit_value = 0;
47
48my $space = "";
49while (scalar (@ARGV)) {
50  my $file =  shift @ARGV;
51  if (-e $file) {
52    my @command;
53    push(@command, q(/usr/sbin/lsof));
54    push(@command, q(-F));
55    if ($o{u}) {		# Add user name
56      push(@command, q(pfL));
57    } else {
58      push(@command, q(pf));
59    }
60    push(@command, q(-f)) if ($o{f});
61    push(@command, q(--));
62    push(@command, $file);
63    # This cryptic statement will cause exec(@command) to run in the child,
64    # with the output set up correctl and LSOF's input set up correctly.
65    open (LSOF, "-|") or exec(@command);
66    my @results = <LSOF>;
67    chomp(@results);
68    # fuser man page is very explicit about stdout/stderr output
69    print STDERR $file, qq(: );
70    my $username = "";
71    foreach (@results) {
72      if (/^p(\d+)$/) {
73	if ($username) {
74	  print STDERR $username;
75	  $username = "";
76	}
77	print $space, $1;
78	$space = q( );
79      }
80      if (/^f(c|r)[wt]d$/) {
81	print STDERR "$1" . $username;
82	$username = "";
83      }
84      $username = "(" . $1 . ")" if (/^L(.+)$/);
85    }
86    print STDERR $username . qq(\n);
87  } else {
88    print STDERR "$0: '$file' does not exist\n";
89    $exit_value = 1;
90  }
91}
92exit($exit_value);
93