chiark / gitweb /
@@ -1,3 +1,9 @@
authorian <ian>
Sat, 20 May 2000 20:04:03 +0000 (20:04 +0000)
committerian <ian>
Sat, 20 May 2000 20:04:03 +0000 (20:04 +0000)
+userv (0.2) unstable; urgency=low
+
+  * Embryonic new finger program.
+
+ --
+
 userv (0.1) experimental; urgency=low

   * Initial release.

13 files changed:
changelog
debian/changelog
finger/.cvsignore [new file with mode: 0644]
finger/Makefile [new file with mode: 0644]
finger/config.in [new file with mode: 0644]
finger/finger-finger.in [new file with mode: 0644]
finger/finger-getprefs.in [new file with mode: 0644]
finger/finger-notmyself.in [new file with mode: 0644]
finger/finger-setprefs.in [new file with mode: 0644]
finger/in.fingerd [new file with mode: 0755]
finger/install-confs [new file with mode: 0755]
finger/services.in [new file with mode: 0644]
finger/setprefs [new file with mode: 0755]

index c0f6a31..80a0170 100644 (file)
--- a/changelog
+++ b/changelog
@@ -1,3 +1,9 @@
+userv (0.2) unstable; urgency=low
+
+  * Embryonic new finger program.
+
+ --
+
 userv (0.1) experimental; urgency=low
 
   * Initial release.
index c0f6a31..80a0170 100644 (file)
@@ -1,3 +1,9 @@
+userv (0.2) unstable; urgency=low
+
+  * Embryonic new finger program.
+
+ --
+
 userv (0.1) experimental; urgency=low
 
   * Initial release.
diff --git a/finger/.cvsignore b/finger/.cvsignore
new file mode 100644 (file)
index 0000000..157bb59
--- /dev/null
@@ -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 (file)
index 0000000..f818c7e
--- /dev/null
@@ -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 (file)
index 0000000..db21cd3
--- /dev/null
@@ -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 (file)
index 0000000..4e09226
--- /dev/null
@@ -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 (file)
index 0000000..2f91f47
--- /dev/null
@@ -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 (file)
index 0000000..33353e6
--- /dev/null
@@ -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 (file)
index 0000000..6602fce
--- /dev/null
@@ -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 (executable)
index 0000000..58d4c93
--- /dev/null
@@ -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 (executable)
index 0000000..68044a9
--- /dev/null
@@ -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 (file)
index 0000000..4bc7cfd
--- /dev/null
@@ -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 (executable)
index 0000000..53de506
--- /dev/null
@@ -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 $!;