#!/usr/bin/perl -s # # mkpeople - rebuild the Web People Directory for IU Computer Science # Steve Kinzler, kinzler@cs.indiana.edu, Sep 94/Jul 95/Nov 95/May 97 # # comments added for sanity -- schisham 19971007 # converted to new web structure -- robh Oct 2001 # added exceptgroups to limit the display (and web harvesting of email addrs) - robh May 2004 # # $Id: mkpeople,v 1.25 2007/05/03 16:23:18 root Exp root $ umask 002; # head/tail files $headfile="/l/www/People/headonly.html"; $tailfile="/l/www/People/tailonly.html"; # base url $base="/People/auto/"; # location of mkpeople $cwd = '/l/www/People/auto'; # root of WWW tree $root = '../..'; # usernames to exclude $except = '/usr/local/lib/userlist/nonusers'; @except = ('^[A-Z]'); # groups to exclude @exceptgroups = ( 'other', 'classes', 'csother', 'cssystem', 'guests', 'projects', 'students', 'xfaculty', 'alumni', 'xstaff'); # file that, if existing in the homedir of a user, excludes them from the listing $excludefile = ".web.exclude"; # machines serving as password hosts @pwhost = ('moose', 'whale', 'silo'); # where to find the password file on the passwd hosts %pwfile = ('whale', '/nfs/whale/etc/passwd', 'moose', '/nfs/moose/etc/passwd', 'silo', '/nfs/silo/etc/passwd'); $maxname = 50; # lower UID limit $minuid = 100; $primary = 'PRIMARY'; # default group if none match $dfltgrp = 'other'; # shells for skipped accounts @deactiv = ('deactivated'); $foto = "$root/foto"; # hyplan link for personal WWW pages $hyplan = "$root/hyplan"; # via filesystem $hyplanroot = "/hyplan"; # via web # resume forwarding filename $resufwd = 'resume.forward'; # filenames for actual resume @resume = ('resume.html', 'resume.txt'); # Address and fax override filenames. If these exist in the # users moose home directory, use them instead of the defaults # for the mailing address and fax number. $addressfile=".web.address"; $faxfile=".web.fax"; $emailfile=".web.email"; # no longer used #$facls = "$root/dept/faclist"; # part of page title $title = 'IU Computer Science'; $bgcolor = '#FFFFFF'; $montage = 'bin/usermontage'; $maxcols = 10; $swapgif = 1; # do we need to byte-order swap for correct GIF sizes? $montpad = 0; # does $montage pad out to $maxcols columns? $type2c = 's'; $domain = 'cs.indiana.edu'; $areacod = '812'; $prefix = '85'; $deptadd = 'Lindley Hall 215; Bloomington, IN 47405 USA'; @deptadd = ('admin', 'faculty', 'research', 'staff'); $deptfax = "$areacod-${prefix}5-4829"; @deptfax = ('admin', 'faculty', 'research', 'staff'); # student groups and file locations %subgrp = ('grads', 'students /usr/local/lib/userlist/phdgrads /usr/local/lib/userlist/msgrads', 'majors', 'students /usr/local/lib/userlist/csmajors'); %supgrp = ('supstaff', 'research staff admin wkstudy'); # Group order ? @gorder = ('faculty', 'supstaff', 'grads', 'majors', 'students', 'alumni', 'other'); # Group long names in assoc array %gname = ('admin', 'Admin Staff', 'alumni', 'Alumni', 'faculty', 'Faculty', 'grads', 'Graduate Student', 'other', 'Guest', 'research', 'Research Staff', 'staff', 'Systems Staff', 'students', 'Other Student', 'supstaff', 'Staff', 'majors', 'Undergraduate Major', 'wkstudy', 'Work-study'); # Group long names plural %gname2 = ('admin', 'Admin Staff', 'alumni', 'Alumni', 'faculty', 'Faculty', 'grads', 'Graduate Students', 'other', 'Guests', 'research', 'Research Staff', 'staff', 'Systems Staff', 'students', 'Other Students', 'supstaff', 'Staff', 'majors', 'Undergraduate Majors', 'wkstudy', 'Work-studies'); chdir $cwd || die "$0: cannot chdir $cwd ($!)\n"; ## Collect User Data ########################################################## while (@grent = getgrent) { $primary{$grent[2] + 0} = $grent[0] if $grent[3] =~ /(^|[ ,])$primary([ ,]|$)/; } endgrent; # build exceptions array open(EXCEPT, $except) || die "$0: cannot open $cwd/$except ($!)\n"; while () { chop; s/^\s*//; s/\s.*//; next if /^$|^#/; $except{$_} = 1; } close EXCEPT; # parse the password hosts's passwd files # grab everyone, but exceptions, deactivated, lowUIDs foreach $pwhost (@pwhost) { # open the passwd file on hosts ($pwfile = $pwfile{$pwhost}) || die "$0: undefined password file for $pwhost\n"; open(PASSWD, $pwfile) || die "$0: cannot open $pwfile ($!)\n"; while () { # get passwd entries @pwent = split(/:/); # username is first entry $user = $pwent[0]; # skip if no username or UID is below $minuid # or this is an exception person or this person's # account has been disabled next if ! $user || $pwent[2] < $minuid || $except{$user} || grep($user =~ /$_/, @except) || grep($pwent[6] =~ /$_/, @deactiv); # Skip if the user has a $excludefile in any CS homedir next if ( -e "/nfs/moose/u/$user/$excludefile" || -e "/nfs/whale/u/$user/$excludefile" || -e "/nfs/silo/u/$user/$excludefile" ); # grab userinfo from host only once unless ($host{$user}) { $host{$user} = $pwhost; $group{$user} = $primary{$pwent[3] + 0} || $dfltgrp; # grab the GECOS info and canonicalize it split(/,/, $pwent[4], 4); $name{$user} = &canon($_[0], 'name'); $office{$user} = &canon($_[1]); $wphone{$user} = &canon($_[2], 'phone'); $hphone{$user} = &canon($_[3], 'phone'); $members{$group{$user}} .= (($members{$group{$user}}) ? ':' : '') . $user; } } close PASSWD; } foreach $subgrp (keys %subgrp) { ($group, @files) = split(/\s+/, $subgrp{$subgrp}); foreach (@files) { open(FILE, $_) || die "$0: cannot open $_ ($!)\n"; grep(s/^\s*([^\s@]+).*\n/$1/ && ($subusers{$_} = 1) && 0, ); close FILE; } foreach (split(/:/, $members{$group})) { if ($subusers{$_}) { $group{$_} = $subgrp; push(@submembers, $_); } else { push(@members, $_); } } $members{$subgrp} = join(':', @submembers); $members{$group} = join(':', @members); %subusers = @submembers = @members = (); } opendir(DIR, $foto) || die "$0: cannot opendir $foto ($!)\n"; foreach (readdir DIR) { next if /^\./; # look for a foto in the foto dir of that person ($user = $_) =~ s/\.[^.]*$//; $foto{$user} = $_; } closedir DIR; # look for username/index.[s]html and username.html files in hyplan directory opendir(HYPLAN, $hyplan) || die "$0: cannot opendir $hyplan ($!)\n"; foreach $f (readdir HYPLAN) { # If we have an index.[s]html in a hyplan directory, # we use the ~user form. if (-f "$hyplan/$f/index.html" || -f "$hyplan/$f/index.shtml" ) { $hyplan{$f} = "/~$f"; } # Otherwise, we look for a .html file else { # We only care about .html files at this point next unless ($f =~ /^(\w+)\.html$/); # Get the user and initialize href ($user, $href) = ($1, ''); # If we already have something for this user, skip it next if $hyplan{$user}; # If the .html file is a link, use the hyplan/user.html form if (-l "$hyplan/$f") { $href = $f; } # If the .html file is a real file, see if it is a hyplan forward elsif (-f _) { warn("$0: cannot open $hyplan/$f ($!)\n"), next unless open(HYFWD, "$hyplan/$f"); ($href = (grep(s/.*href="?//i, ))[0]) =~ s/"?[\s>].*//; close HYFWD; $href =~ s/[\s"<>].*//; } # build the url $hyplan{$user} = (($href =~ m,^(\w+:|/),) ? '' : "$hyplanroot/") . $href if $href; } } #rewinddir HYPLAN || die "$0: cannot rewinddir $hyplan ($!)\n"; close HYPLAN; # build the /hyplan/username/ links opendir(HYPLAN, $hyplan) || die "$0: cannot opendir $hyplan ($!)\n"; foreach $user (readdir HYPLAN) { next unless $user =~ /^\w+$/ && -l "$hyplan/$user"; # look for a resume forwarder if (-s "$hyplan/$user/$resufwd" && open(RESFWD, "$hyplan/$user/$resufwd")) { $href = (grep(s/^\s*(\S+).*(\n|$)/$1/, ))[0]; close RESFWD; $href =~ s/[\s"<>].*//; $resume{$user} = (($href =~ m,^(\w+:|/),) ? '' : "$hyplan/$user/") . $href if $href; # look for local resume files } elsif ($resume = (grep(-s "$hyplan/$user/$_", @resume))[0]) { $resume{$user} = "$hyplanroot/$user/$resume"; } # skip if we already have this person from another host # host order is important next if $hyplan{$user}; $hyplan{$user} = (-e "$hyplan/$user/index.html") ? "$hyplan/$user/index.html" : "$hyplan/$user/"; } close HYPLAN; #opendir(DIR, $facls) || die "$0: cannot opendir $facls ($!)\n"; #foreach (readdir DIR) { # next unless /^(\w+)\.html$/; # $facls{$1} = $facls . '/' . $_; #} #closedir DIR; ## Delete Extra Pages and Prepare Page Segments ############################### $proot = ($root =~ /^\//) ? '' : '../'; $pfoto = ($foto =~ /^\//) ? '' : '../'; $phyplan = ($hyplan =~ /^\//) ? '' : '../'; #$pfacls = ($facls =~ /^\//) ? '' : '../'; # scroll through the 1 char length dir names foreach $dir () { opendir(DIR, $dir) || die "$0: cannot opendir $cwd/$dir ($!)\n"; foreach (readdir DIR) { next if /^\.\.?$/; unlink "$dir/$_" || die "$0: cannot unlink $cwd/$dir/$_ ($!)\n" unless ($user = $_) =~ s/\.html$// && $host{$user}; } closedir DIR; rmdir $dir; } %tmp = %members; foreach $group (@gorder) { @supgrp = grep(delete $tmp{$_}, split(/\s+/, $supgrp{$group})); # We exclude certain groups next if grep $group =~ /^$_$/, @exceptgroups; push(@groups, $group) if delete $tmp{$group} || @supgrp; } foreach $group (sort keys %tmp) { # We exclude certain groups next if grep $group =~ /^$_$/, @exceptgroups; push(@groups, $group) if delete $tmp{$group}; } foreach $file (<*.html>) { next if $file eq 'index.html'; ($group = $file) =~ s/T?\.[^.]*$//; unlink $file || die "$0: cannot unlink $cwd/$file ($!)\n" unless grep($_ eq $group, @groups); } foreach $file (<*.gif>) { ($group = $file) =~ s/\.[^.]*$//; unlink $file || die "$0: cannot unlink $cwd/$file ($!)\n" unless $members{$group}; } # build arrays from trailing data in script while () { last if /__DONTEDIT__/; push(@head, $_); } while () { last if /__TITLE__/; push(@dontedit, $_); } while () { last if /__INTRO__/; push(@title, $_); } while () { last if /__SEARCH__/; push(@intro, $_); } while () { last if /__FOOTNOTE__/; push(@search, $_); } while () { last if /__TAIL__/; push(@footnote, $_); } while () { push(@tail, $_); } # add a bit to the menu push(@menu, "\n", <<'EOF');
\n
EOF push(@menu, "Text Listings
\n[ "); foreach $group (@groups) { $gname2 = $gname2{$group} || $group; push(@menu, ($n++) ? '| ' : '', "$gname2\n"); } $n = 0; push(@menu, "]
\n"); push(@menu, "
\n"); push(@menu, "Icon Listings
\n[ "); foreach $group (@groups) { $gname2 = $gname2{$group} || $group; push(@menu, ($n++) ? '| ' : '', "$gname2\n"); } push(@menu, "]\n"); push(@menu, "
\n"); ## Write Main Index ########################################################### open(INDEX, '> index.html') || die "$0: cannot open $cwd/index.html ($!)\n"; printhead(INDEX); print INDEX @head, @dontedit, @title, "

Main Index

\n", @intro, @search, @menu, @tail; printtail(INDEX); close INDEX; exit if $exitindex; ## Write Text Listings ######################################################## @tmp = @groups; $prevgroup = ''; while ($group = shift @tmp) { $nextgroup = $tmp[0]; $gname2 = $gname2{$group} || $group; open(GROUP, "> ${group}T.html") || die "$0: cannot open $cwd/${group}T.html ($!)\n"; print GROUP @dontedit; printhead(GROUP); print GROUP @title, "

Text Listing - $gname2

\n", @intro; $prevhtml = ($prevgroup) ? "Previous Text Listing" : 'Previous Text Listing'; $nexthtml = ($nextgroup) ? "Next Text Listing" : 'Next Text Listing'; print GROUP "\n", <

[ Main Index | Icon Listing ]
$prevhtml <--> $nexthtml

EOF @supgrp = &supgrps($group); foreach $supgrp (@supgrp) { $gname2 = $gname2{$supgrp} || $supgrp; $supgrp2 = ($supgrp eq $group) ? "${supgrp}2" : $supgrp; print GROUP "\n

$gname2

\n" if $#supgrp > 0; @members = sort split(/:/, $members{$supgrp}); push(@users, @members); $supergroup{$supgrp} = $group; print GROUP "\n
\n"; foreach $user (@members) { print GROUP &userline($user), "
\n"; } print GROUP "
\n"; } print GROUP @footnote, @tail; printtail(GROUP); close GROUP; $prevgroup = $group; } exit if $exittext; ## Write Icon Listings ######################################################## $prevgroup = ''; while ($group = shift @groups) { $nextgroup = $groups[0]; $gname2 = $gname2{$group} || $group; open(GROUP, "> $group.html") || die "$0: cannot open $cwd/$group.html ($!)\n"; print GROUP @dontedit; printhead(GROUP); print GROUP @title, "

Icon Listing - $gname2

\n", @intro; $prevhtml = ($prevgroup) ? "Previous Icon Listing" : 'Previous Icon Listing'; $nexthtml = ($nextgroup) ? "Next Icon Listing" : 'Next Icon Listing'; print GROUP "\n", <

[ Main Index | Text Listing ]
$prevhtml <--> $nexthtml

EOF @supgrp = &supgrps($group); foreach (@supgrp) { &groupmontage($_); } print GROUP @tail; printtail(GROUP); close GROUP; $prevgroup = $group; } sub groupmontage { local($group) = @_; @members = sort split(/:/, $members{$group}); warn("$0: cannot run $montage ($!)\n"), return unless open(MONTAGE, "| $montage $maxcols $group.gif"); print MONTAGE join("\n", @members), "\n"; close MONTAGE; return if $? >> 8; warn("$0: cannot open $cwd/$group.gif ($!)\n"), return unless open(MONTAGE, "< $group.gif"); # grab the magic info to determine if file is a GIF read(MONTAGE, $magic, 10); @magic = (unpack('c10', $magic))[6 .. 9];; close MONTAGE; @magic = @magic[1, 0, 3, 2] if $swapgif; # this is pretty cool stuph # read the header to determine width and height settings # Steve never ceases to amaze me --schisham $width = unpack($type2c, pack('cc', @magic[0, 1])); $height = unpack($type2c, pack('cc', @magic[2, 3])); $columns = (! $montpad && $#members + 1 < $maxcols) ? $#members + 1 : $maxcols; $rows = int(($#members + 1) / $columns + .9999); $twidth = int($width / $columns) - 2; $theight = int($height / $rows) - 2; $gname2 = $gname2{$group} || $group; print GROUP "\n

$gname2

\n" if $#supgrp > 0; $size = ($#members == 0) ? "1 multiple" : ($#members < 5) ? $#members + 1 : 5; # a little javascript action print GROUP "\n", <
\n"; print GROUP "\n\n"; $row = $col = 0; foreach (@members) { $x = int($col * ($width / $columns) + .9999); $y = int($row * ($height / $rows) + .9999); print GROUP "\n"; $col = 0, $row++ if ++$col >= $columns; } print GROUP "\n", "\n\n", < Text Listing EOF } exit if $exiticon; ## Write User Pages ########################################################### while ($user = shift @users) { $nextuser = $users[0]; $name = $name{$user} || $user; $group = $group{$user}; $gname = $gname{$group} || $group; $dir = substr($user, 0, 1); mkdir($dir, 0777 & (0777 ^ umask)) || die "$0: cannot mkdir $cwd/$dir ($!)\n" unless -e $dir; open(FILE, "> $dir/$user.html") || die "$0: cannot open $cwd/$dir/$user ($!)\n"; print FILE @dontedit; printhead(FILE); print FILE "\n", < Indiana University Computer Science Personnel Directory
[ Main Index | Text Listing | Icon Listing ]
EOF print FILE &userseq($prevuser, $user, 'Previous Page'), " <-->\n", &userseq($nextuser, $user, 'Next Page'), "\n\n"; print FILE "\n
\n"; print FILE "\n

\n"; print FILE "\"\"\n" if $foto{$user}; print FILE "$name\n

\n"; print FILE "\n\n"; @out = ("
Position: $gname"); push(@out, "Office: $office{$user}") if $office{$user}; # Print the address if in one of the deptadd groups, looking # for an addressfile override. if (grep($group eq $_, @deptadd)) { if ( -r "/nfs/moose/u/$user/$addressfile") { $addrtmp=`cat /nfs/moose/u/$user/$addressfile`; push(@out, "Address: $addrtmp"); } else { push(@out, "Address: $deptadd"); } } push(@out, "Office phone: $wphone{$user}") if $wphone{$user}; # Print the fax number if in one of the deptadd groups, looking # for a faxfile override. if (grep($group eq $_, @deptadd)) { if ( -r "/nfs/moose/u/$user/$faxfile") { $faxtmp=`cat /nfs/moose/u/$user/$faxfile`; push(@out, "Fax phone: $faxtmp"); } else { push(@out, "Fax phone: $deptfax"); } } push(@out, "Home phone: $hphone{$user}") if $hphone{$user}; # Print the email address, looking for a emailfile override. if ( -r "/nfs/moose/u/$user/$emailfile") { chomp($emailtmp=`cat /nfs/moose/u/$user/$emailfile`); } elsif ( -r "/nfs/whale/u/$user/$emailfile") { chomp($emailtmp=`cat /nfs/whale/u/$user/$emailfile`); } elsif ( -r "/nfs/silo/u/$user/$emailfile") { chomp($emailtmp=`cat /nfs/silo/u/$user/$emailfile`); } else { $emailtmp="$user\@$domain"; } push(@out, "E-mail:\n" . &maillink($emailtmp)); print FILE "\n", join("
\n", @out), "\n"; print FILE "


See the "; print FILE "associated FAQ Entry if you want to change the contents of this page
\n"; printtail(FILE); close FILE; $prevuser = $user; } exit 0; ## General Subroutines ######################################################## # canonicalize GECOS info from passwd file sub canon { local($_) = shift; s/\s+/ /g; s/^ //; s/ $//; s/[^ -~]//g; # [<>&] go bye-bye s/&/&/g; s//>/g; foreach $key (@_) { if ($key eq 'name') { $_ = substr($_, 0, $maxname) if length > $maxname; } # the following looks like sendmail rules ;) # parse a phone number if ($key eq 'phone') { s/^\( ?(\d{3}) ?\) ?-* ?/$1-/; s/^(\d{3})[- .\/]?(\d{3})[- .\/]?(\d{4})$/$1-$2-$3/; s/^(\d{3})[- .\/]?(\d{4})$/$areacod-$1-$2/; s/^(\d)[- .\/]?(\d{4})$/$areacod-$prefix$1-$2/; } } return $_; } sub supgrps { local($group) = @_; @_ = ($members{$group}) ? ($group) : (); push(@_, grep($_ =~ /\S/ && $members{$_}, split(/\s+/, $supgrp{$group}))) if $supgrp{$group}; return @_; } sub userline { local($user) = @_; return '$user " . '...' . '.' x ((8 - length($user)) % 8) . (($hyplan{$user}) ? " hyplan" : '.......') . (($hyplan{$user} && $resume{$user}) ? ',' : ($hyplan{$user} && ! $resume{$user}) ? ' ' : '.') . (($resume{$user}) ? " résumé " : '........') . "... " . $name{$user} . (($foto{$user}) ? ' *' : ''); } sub userseq { local($ref, $rel, $txt) = @_; local($dir); return $txt unless $ref; return '$txt"; } # Printer the html header sub printhead { local($f) = @_; if (open(HEADF, "<$headfile")) { while() { print $f $_; } close(HEADF); } else { print $f "

HEADER NOT AVAILABLE

\n" } } # Printer the html footer sub printtail { local($f) = @_; if (open(TAILF, "<$tailfile")) { while() { print $f $_; } close(TAILF); } else { print $f "

FOOTER NOT AVAILABLE

\n" } } sub maillink { my ($addr) = @_; if ($addr =~ /^(.*)\@cs.indiana.edu$/) { return("$1"); } elsif ($addr =~ /^(.*)\@(.*)$/) { return("$1"); } elsif ($addr =~ /unlisted/i ) { return("Unlisted"); } else { return("Invalid User-Supplied Email Address"); } } ## Page Segments ############################################################## __END__ __DONTEDIT__ __TITLE__

Personnel Directory

__INTRO__

The information in this directory is garnered nightly from accounts on the CS systems. Persons listed in this directory can change their full name, office, and office and home phone using the account management system. You can also create a personal web page (a hyplan) and résumé (resume), and create and submit a departmental photo. The icons in this directory are from the Picons Archive, and may be rendered poorly by some browsers due to dithering.

PLEASE NOTE: This directory includes only people with current accounts on the CS systems. This listing does not include people who do not have CS accounts so some of the lists may not include everyone in the specified group.

__SEARCH__

__FOOTNOTE__


* An image of this person is available. __TAIL__

This directory is generated with mkpeople, greppeople and usermontage.

written by <kinzler@cs.indiana.edu>