summaryrefslogtreecommitdiff
path: root/finger
diff options
context:
space:
mode:
authorian <ian>2000-05-20 20:04:03 +0000
committerian <ian>2000-05-20 20:04:03 +0000
commit5f9b76752f5213b26c47be57a6733ead09cfdff3 (patch)
treef5b16dceb822834abc8bded89bdc941de79571f0 /finger
parente1e9b27fa939d2a3fa5ac7567bb0bf70085e04c8 (diff)
downloaduserv-utils-5f9b76752f5213b26c47be57a6733ead09cfdff3.tar.gz
@@ -1,3 +1,9 @@
+userv (0.2) unstable; urgency=low + + * Embryonic new finger program. + + -- + userv (0.1) experimental; urgency=low * Initial release.
Diffstat (limited to 'finger')
-rw-r--r--finger/.cvsignore6
-rw-r--r--finger/Makefile64
-rw-r--r--finger/config.in40
-rw-r--r--finger/finger-finger.in10
-rw-r--r--finger/finger-getprefs.in13
-rw-r--r--finger/finger-notmyself.in10
-rw-r--r--finger/finger-setprefs.in11
-rwxr-xr-xfinger/in.fingerd256
-rwxr-xr-xfinger/install-confs11
-rw-r--r--finger/services.in18
-rwxr-xr-xfinger/setprefs29
11 files changed, 468 insertions, 0 deletions
diff --git a/finger/.cvsignore b/finger/.cvsignore
new file mode 100644
index 0000000..157bb59
--- /dev/null
+++ b/finger/.cvsignore
@@ -0,0 +1,6 @@
+config
+services
+finger-finger
+finger-notmyself
+finger-getprefs
+finger-setprefs
diff --git a/finger/Makefile b/finger/Makefile
new file mode 100644
index 0000000..f818c7e
--- /dev/null
+++ b/finger/Makefile
@@ -0,0 +1,64 @@
+# Copyright (C) 2000 Ian Jackson
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with userv-utils; if not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+etcdir= /etc
+var= /var
+varlib= $(var)/lib
+prefix= /usr/local
+bindir= $(prefix)/bin
+sbindir= $(prefix)/sbin
+
+libdir= $(prefix)/lib
+libuserv= $(libdir)/userv
+libfinger= $(libuserv)/finger
+
+varuserv= $(varlib)/userv
+varfinger= $(varuserv)/finger
+
+etcuserv= $(etcdir)/userv
+etcfinger= $(etcuserv)/finger
+uservicesd= $(etcuserv)/services.d
+
+user= daemon
+
+ROOTMKDIRS= $(etcfinger) $(uservicesd) $(libfinger) $(varuserv)
+USERVICES= finger-notmyself finger-finger finger-getprefs finger-setprefs
+FINGERCONFS= config services
+TARGETS= $(FINGERCONFS) $(USERVICES)
+
+SUBSTVARS= user etcfinger varfinger libfinger
+SEDSCRIPT= '$(foreach f, $(SUBSTVARS), s,@$f@,$($f),g; )'
+
+all: $(TARGETS)
+
+%: %.in
+ sed -e $(SEDSCRIPT) <$< >$@.new && mv -f $@.new $@
+
+install: all
+ install -d -m 755 -o root $(ROOTMKDIRS)
+ install -d -m 700 -o $(user) $(varfinger)
+ install -m 755 in.fingerd $(sbindir)
+ install -m 755 setprefs $(libfinger)
+ ./install-confs $(etcfinger) $(FINGERCONFS)
+ ./install-confs $(uservicesd) $(USERVICES)
+
+fresh-install: erase-configs install
+
+erase-configs:
+ cd $(etcfinger); rm -f $(FINGERCONFS)
+ cd $(uservicesd); rm -f $(USERVICES)
diff --git a/finger/config.in b/finger/config.in
new file mode 100644
index 0000000..db21cd3
--- /dev/null
+++ b/finger/config.in
@@ -0,0 +1,40 @@
+# This configuration file controls the userv finger daemon
+# The possible directives in it are:
+# default-pref <logged-on-list-preference> <search-preference>
+# hostname <hostname>
+# prefs-file <per-user-preferences-file>
+# services-file <extended-services-file>
+# Blank lines and #-comments are allowed.
+#
+# The per-user prefs file has a list of
+# <username> <logged-on-list-preference> <search-preference>
+# and may NOT contain blank lines or comments. It is supposed
+# to be edited only by the finger-pref userv service.
+#
+# The logged-on-list preference controls how, if at all, a user
+# appears in the list of logged on users. It may be is either `-', or
+# `+' followed by a possibly-empty list of fields to show. `-' means
+# that the user will not appear, whether they are logged on or not.
+# `+' means that they will appear. It may be followed by one or more
+# of the following letters:
+# i Show the idle time
+# m Show whether the session is accepting messages (`mesg')
+# t Show why tty the session is on
+# l Show when the session started (ie, when the user logged on)
+# f Show where the user is logged on from
+# n Show the user's name (from the passwd file GCOS field)
+#
+# The search-preference controls how, if at all, a user's details will
+# be used and their information returned, in response to a search request.
+# n The user will never be returned for a search request
+# u Only matches against their username will count, and only their
+# username will be displayed.
+# y Matching is performed against username or full name and both
+# are displayed.
+#
+# The extended services file is usually the file `services' in
+# this directory.
+
+default-pref +m y
+services-file @etcfinger@/services
+prefs-file @varfinger@/prefs
diff --git a/finger/finger-finger.in b/finger/finger-finger.in
new file mode 100644
index 0000000..4e09226
--- /dev/null
+++ b/finger/finger-finger.in
@@ -0,0 +1,10 @@
+#
+if ( glob calling-user @user@
+ & grep service-user-shell /etc/shells
+ )
+ reset
+ no-set-environment
+ suppress-args
+ disconnect-hup
+ execute userv @user@ finger-notmyself
+fi
diff --git a/finger/finger-getprefs.in b/finger/finger-getprefs.in
new file mode 100644
index 0000000..2f91f47
--- /dev/null
+++ b/finger/finger-getprefs.in
@@ -0,0 +1,13 @@
+#
+if ( grep calling-user-shell /etc/shells
+ & glob service-user daemon
+ )
+ reset
+ no-set-environment
+ suppress-args
+ disconnect-hup
+ execute sh -c " \
+ if test -f @varfinger@/prefs; then \
+ grep '^$USERV_USER ' @varfinger/prefs || test $? = 1; fi \
+ "
+fi
diff --git a/finger/finger-notmyself.in b/finger/finger-notmyself.in
new file mode 100644
index 0000000..33353e6
--- /dev/null
+++ b/finger/finger-notmyself.in
@@ -0,0 +1,10 @@
+#
+if ( grep calling-user-shell /etc/shells
+ & glob service-user @user@
+ )
+ reset
+ no-set-environment
+ suppress-args
+ disconnect-hup
+ execute sh -c "finger -m $USERV_USER"
+fi
diff --git a/finger/finger-setprefs.in b/finger/finger-setprefs.in
new file mode 100644
index 0000000..6602fce
--- /dev/null
+++ b/finger/finger-setprefs.in
@@ -0,0 +1,11 @@
+#
+if ( grep calling-user-shell /etc/shells
+ & glob service-user daemon
+ )
+ reset
+ no-set-environment
+ no-suppress-args
+ no-disconnect-hup
+ execute with-lock-ex -w @varfinger@/lock \
+ @libfinger@/setprefs @varfinger@/prefs
+fi
diff --git a/finger/in.fingerd b/finger/in.fingerd
new file mode 100755
index 0000000..58d4c93
--- /dev/null
+++ b/finger/in.fingerd
@@ -0,0 +1,256 @@
+#!/usr/bin/perl --
+
+use POSIX;
+
+setup();
+read_config();
+read_services();
+parse_query();
+process_query();
+
+sub process_query () {
+ if (exists $services{$query}) {
+
+ exec ($verbose && length $services{$query}->{'verbose'} ?
+ $services{$query}->{'verbose'} :
+ $services{$query}->{'command'});
+ die $!;
+
+ }
+
+ if ($query eq '/') {
+
+ print ("userv fingerd on $hostname\r\n".
+ "queries supported:\r\n".
+ "\r\n".
+ " <nothing> list of logged on users and available services\r\n".
+ " / this help text\r\n".
+ " <service> separately advertised special finger service\r\n".
+ " <user> user (logged in or otherwise)\r\n".
+ " <user>+<xtra> user-provided extended/special finger service\r\n".
+ " /<substring> search for user matching substring\r\n")
+ or die $!;
+
+ return;
+
+ }
+
+ if (!length $query) {
+
+ read_per_user();
+
+ if ($verbose) {
+ print "Username Idle Msg,tty Login at From\r\n" or die $!;
+ }
+
+ open W,"who -iw|" or die $!;
+ while (<W>) {
+
+ m/^(\w+) +(\S) +(\S+) +(\w+ +\d+ \d\d\:\d\d) +(\S+) +(.*)$/ or die;
+ ($user, $mesg, $tty, $login, $idle, $from) = ($1,$2,$3,$4,$5,$6);
+ $mesg = $mesg =~ m/[-+]/ ? $& : '?';
+
+ if ($tty =~ m/\./) {
+ $from =~ s/.$/$& /;
+ $from.= $tty;
+ $tty= '';
+ }
+
+ $pref= exists $user_pref_list{$user}
+ ? $user_pref_list{$user} : $def_pref_list;
+ next unless $pref =~ m/^\+/;
+
+ $idle= '' unless $pref =~ m/i/;
+ $mesg= ' ' unless $pref =~ m/m/;
+ $tty= '' unless $pref =~ m/t/;
+ $login= '' unless $pref =~ m/l/;
+ $from= '' unless $pref =~ m/t/;
+
+ if ($verbose) {
+
+ printf "%-8s %-5s %s%-8s %-12s %s\r\n",
+ $user, $idle, $mesg, $tty, $login, $from
+ or die $!;
+ } else {
+ $users{$user}->{'pref'} = $pref;
+ $users{$user}->{'mesg'}->{$mesg} = 1;
+ $users{$user}->{'idle'} = min_idle($users{$user}->{'idle'}, $idle);
+ }
+
+ }
+ $!=0; close W; $? and die "$! $?";
+
+ if (!$verbose) {
+ print "Username Idle Msg Name\r\n" or die $!;
+
+ for $user (sort keys %users) {
+ $pref= $users{$user}->{'pref'};
+ $name= $pref =~ m/n/ ? (getpwnam($user))[6] : '';
+ $name =~ s/,.*//;
+ $mesg= join('', sort keys %{ $users{$user}->{'mesg'} });
+ $mesg= '+' if $mesg =~ m,\+,;
+ printf "%-8s %-5s %s %s\r\n",
+ $user, $users{$user}->{'idle'}, $mesg, $name
+ or die $!;
+ }
+ }
+
+ foreach $service (sort keys %services) {
+ $desc= $services{$service}->{'desc'};
+ next unless length $desc;
+
+ if (!$anyservice) {
+ print "\r\nService Description\r\n" or die $!;
+ $anyservice= 1;
+ }
+
+ printf "%-12s %s\r\n", $service, $desc or die $!;
+ }
+
+ print "\r\nFor help, finger /\@$hostname\r\n";
+ return;
+
+ }
+
+ if ($query =~ s,^/,,) {
+ $query =~ s/\W/\\$&/g;
+ read_per_user();
+
+ while (($user,$passwd,$uid,$gid,$quota,$comment,$name) = getpwent) {
+ $name =~ s/,.*//;
+
+ $pref= exists $user_pref_search{$user}
+ ? $user_pref_search{$user}
+ : $def_pref_search;
+ next unless $pref =~ m/[uy]/;
+ $name= '' unless $pref =~ m/y/;
+ next unless query_match($user) || query_match($name);
+
+ if (!$found) {
+ print "Username Name\r\n" or die $!;
+ $found= 1;
+ }
+ printf "%-9s %s\r\n", $user,$name or die $!;
+
+ }
+
+ if (!$found) {
+ print "No matches. finger /\@$hostname for help.\r\n" or die $!;
+ }
+
+ return;
+ }
+
+ if ($query =~ s/\+.*$//) { $qsuffix= $&; }
+
+ if (!(($user)= getpwnam($query))) {
+ print "No user named \`$query'. finger /\@$hostname for help.\r\n" or die $!;
+ return;
+ }
+
+ @servcmd= length $qsuffix
+ ? ('finger-finger')
+ : ('finger-extended',$qsuffix);
+ exec 'userv','-t',300,$user,@list;
+ die $!;
+
+}
+
+sub query_match ($) {
+ my ($data) = @_;
+ return $data =~ m/\b$query\b/io;
+}
+
+sub setup () {
+ $progname= $0; $progname =~ s,.*/,,;
+ alarm(300);
+
+ $config= '/etc/finger-userv/config';
+
+ if (@ARGV) { @ARGV == 1 or die; $config= $ARGV[1]; }
+ $services= '/etc/userv/finger/services';
+ $peruser= '/var/lib/userv/finger/prefs';
+ $def_pref_list= '+m'; $list_fields= 'imtlfn';
+ $def_pref_search= 'y'; $search_opts= 'nuy';
+}
+
+sub parse_query () {
+ $query= <STDIN>;
+ $query =~ s/\r?\n$// or die "$0: no query\n";
+
+ $verbose = $query =~ s,^/[wW],,;
+ $query =~ s/^ *//;
+}
+
+sub min_idle ($$) {
+ my ($a,$b) = @_;
+ return '.' if $a eq '.' || $b eq '.';
+ return $b if $a eq 'old' || $a eq '';
+ return $a if $b eq 'old' || $b eq '';;
+ return $a le $b ? $a : $b;
+}
+
+sub read_config () {
+ if (open C, "$config") {
+ while (<C>) {
+ chomp; s/\s+$//; s/^\s+//;
+ if (m/^default\-pref\s+([-+][$list_fields]+)\s+([$search_opts])$/) {
+ $def_pref_list= $1;
+ $def_pref_search= $2;
+ } elsif (m/^hostname\s+(\S+)$/) {
+ $hostname= $1;
+ } elsif (m/^prefs\-file\s+(\S.*)$/) {
+ $peruser= $1;
+ } elsif (m/^services\-file\s+(\S.*)$/) {
+ $services= $1;
+ } elsif (m/\S/ && !m/^\#/) {
+ die;
+ }
+ }
+ close C or die $!;
+ } elsif ($! != &ENOENT) {
+ die $!;
+ }
+
+ if (!defined $hostname) {
+ chomp($hostname= `hostname -f`);
+ length $hostname or die $?;
+ }
+}
+
+sub read_services () {
+ if (open C, "$services") {
+ while (<C>) {
+ chomp; s/\s+$//; s/^\s+//;
+ next if m/^\#/ || !m/\S/;
+ if (m/^service\s+(\S.*)$/) {
+ $sname= $1;
+ die if exists $services{$sname};
+ } elsif (m/^(desc|command|verbose)\s+(\S.*)$/) {
+ die if exists $services{$sname}->{$1};
+ $services{$sname}->{$1}= $2;
+ } else {
+ die;
+ }
+ }
+ close C;
+ foreach $sname (keys %services) {
+ die unless exists $services{$sname}->{'command'};
+ }
+ } elsif ($! != &ENOENT) {
+ die $!;
+ }
+}
+
+sub read_per_user () {
+ if (open DL, "$peruser") {
+ while (<DL>) {
+ m/^(\w+) ([-+][$list_fields]+) ([$search_opts])$/ or die;
+ $user_pref_list{$1}= $2;
+ $user_pref_search{$1}= $3;
+ }
+ close DL;
+ } elsif ($! != &ENOENT) {
+ die $!;
+ }
+}
diff --git a/finger/install-confs b/finger/install-confs
new file mode 100755
index 0000000..68044a9
--- /dev/null
+++ b/finger/install-confs
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+destdir="$1"; shift
+for f in "$@"; do install -m 644 -o root "$f" "$destdir/$f:new"; done
+cd "$destdir"
+for f in "$@"; do
+ if ! test -f "$f"; then
+ echo installing new "$destdir/$f"
+ mv -f "$f:new" "$f"
+ fi
+done
diff --git a/finger/services.in b/finger/services.in
new file mode 100644
index 0000000..4bc7cfd
--- /dev/null
+++ b/finger/services.in
@@ -0,0 +1,18 @@
+# This file contains the special advertised or unadvertised services
+# The result is that finger <service>@<hostname> will run some
+# command.
+#
+# Each service is listed like this:
+# service <service-name>
+# command <command>
+# [ verbose <command-if-verbose> ]
+# [ desc <description> ]
+# Blank lines and #-comments are allowed.
+#
+# If a description is provided it will be printed in the normal
+# finger @host output. If the verbose command is provided it
+# will be run instead of the usual command if a verbose request
+# (from `finger -l' on UN*X) is made; otherwise verbose requests
+# will run the normal command.
+#
+# You can override anything usually displayed by this fingerd here.
diff --git a/finger/setprefs b/finger/setprefs
new file mode 100755
index 0000000..53de506
--- /dev/null
+++ b/finger/setprefs
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use POSIX;
+
+@ARGV==3 or die;
+($prefs_file, $new_list, $new_search) = @ARGV;
+
+$new_list =~ m/^(\-|\+[imtlfn]+)$/ or die; $new_list= $1;
+$new_search =~ m/^([nuy])$/ or die; $new_search= $1;
+
+$user= $ENV{'USERV_USER'}; length $user or die;
+
+open N, ">$prefs_file.new" or die $!;
+
+if (open P, $prefs_file) {
+ while (<P>) {
+ die unless m/^(\w+) /;
+ next if $1 eq $user;
+ print N or die $!;
+ }
+ close P or die $!;
+} elsif ($! != &ENOENT) {
+ die $!;
+}
+
+print N "$user $new_list $new_search\n" or die $!;
+close N or die $!;
+
+rename "$prefs_file.new", $prefs_file or die $!;