Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/p/daemon/finger.c b/p/daemon/finger.c
new file mode 100644
index 0000000..d4b602a
--- /dev/null
+++ b/p/daemon/finger.c
@@ -0,0 +1,443 @@
+/* a finger
+ * Original (c) 14.03.1993 by Taube @Nightfall
+ * Umsetzung fuer Morgengrauen 09.08.1993 by Loco
+
+   Verwendung ausserhalb von Morgengrauen ist gestattet unter folgenden
+   Bedingungen:
+   - Benutzung erfolgt auf eigene Gefahr. Jegliche Verantwortung wird
+     abgelehnt.
+   - Auch in veraenderten oder abgeleiteten Objekten muss ein Hinweis auf
+     die Herkunft erhalten bleiben.
+   Ein Update-Service besteht nicht.
+
+ * 29.Okt 1993 Seherversion.
+ * spaeter auch fuer externen Aufruf verwendbar gemacht
+ * 13.Okt .plan und .project koennen auch in ~loco/plans sein.
+ * 15.Jan 1994 angepasst an neues Speicherformat
+ * 02-05.Dez94 -n, -p
+ *
+ * Gelegentlich minor changes, zuletzt 04.Okt.95
+ */
+
+#pragma strong_types,save_types
+#pragma no_clone, no_shadow
+
+#include <config.h>
+#include <properties.h>
+#include <wizlevels.h>
+#include <new_skills.h>
+#include <userinfo.h>
+#include <config.h>
+
+#define HBINT    2   /* interval between two heart_beats in seconds */
+#define MINIDLE 60   /* minimum idle time in seconds to be stated idle */
+#define TBANISH_EXTRACT 71..  /* Der benoetigte Teil des TBanish-strings */
+
+#define TP this_player()
+#define wiz (local && IS_LEARNER(TP))
+#define seer (local && IS_SEER(TP))
+#define IN ((properties[P_GENDER]==2)?"in":"")
+
+
+#define FLAG_NOPLAN 1
+#define FLAG_LONG 2
+#define FLAG_SPONSOR 4
+#define FLAG_VIS_LOGOUT 8
+#define FLAG_AVATAR 16
+
+
+mapping properties;
+int age,invis,hc_play;
+int filetime;
+mapping relatives;
+
+
+void create()
+{
+  seteuid(getuid());
+  filetime=0;
+}
+
+
+string timediff(int time)
+{
+  string ret;
+
+  ret="";
+  if ( time >= 86400*365 ) {
+    ret+=time/(86400*365)+"a ";
+    time%=(86400*365);
+  }
+  if(time>=86400) {
+    ret+=time/86400+"d ";
+    time%=86400;
+  }
+  if(time<36000) ret+="0";
+  ret+=time/3600+":";
+  time%=3600;
+  if(time<600) ret+="0";
+  ret+=time/60+":";
+  time%=60;
+  if(time<10) ret+="0";
+  ret+=time+"";
+  return ret;
+}
+
+string sponsoring(string name)
+{
+  int i,w;
+  string *s,s2,s3,s4;
+  // Daten einlesen, wenn die daten aelter als 1 Tag sind oder sich
+  // /log/SPONSORS geaendert hat.
+  if ((time() > filetime+86400) ||
+      filetime!=file_time("/log/SPONSOR")) 
+  {
+      relatives=m_allocate(0,2);
+      filetime=file_time("/log/SPONSOR");
+      s=explode(read_file("/log/SPONSOR"),"\n");
+      foreach(string str: s) { 
+	  sscanf(str,"%s: %s macht %s zum Learner.",s2,s3,s4);
+	  if (IS_LEARNER(lower_case(s3)) && IS_LEARNER(lower_case(s4)))
+          {
+             relatives[lower_case(s4),0]=s3;
+             s3=lower_case(s3);
+             s4+=" ("+query_wiz_level(lower_case(s4))+")";
+             if (!relatives[s3,1]) relatives[s3,1]=({s4});
+             else relatives[s3,1]+=({s4});
+          }
+      }  
+  }
+  s2="";
+  if (relatives[name,0])
+    s2+="Vorfahre:     "+relatives[name,0]+"\n";
+  if (relatives[name,1])
+    s2+="Nachfahre(n): "+break_string(implode(relatives[name,1],", "),78,14)[14..];
+  return s2;
+}
+
+varargs string finger_single(string str,int local)
+{
+  mixed  *userinfo;
+  string ip,text,ipnum,filename,away;
+  int wizlevel,playerlevel,idle,pos,flags,last;
+  mixed h,data,tmp;
+  object player,ob;
+
+  /*DEBUG###  tell_object((find_player("loco")||this_object()),"Finger request: '"+str+"'("+local+")\n");/**/
+  str=lower_case(str);
+  text="";
+  away="";
+  hc_play=0;
+  
+  h=explode(str," ");
+  if (sizeof(h)==1) h=explode(str,"+");
+  if (member(h,"-n")>=0) flags=FLAG_NOPLAN;
+  if (member(h,"-p")>=0) flags=0;
+  if (member(h,"-l")>=0) flags|=FLAG_LONG;
+  if (member(h,"-s")>=0) flags|=FLAG_SPONSOR;
+  if (member(h,"-v")>=0) flags|=FLAG_VIS_LOGOUT;
+  if (member(h,"-a")>=0) flags|=FLAG_AVATAR;
+
+  h=(h-({"-n","-p","-l","-s", "-v","-a"}));
+  if (!sizeof(h)) {
+    text="Du solltest schon sagen, wer Dich interessiert!\n";
+    if (local) return write(text),0;
+    else return text;
+  }
+  str=h[0];
+  if (!sizeof(str) || str[0]<'a' || str[0]>'z') {
+    text="Also, so ("+str+") heisst bestimmt kein Spieler hier!\n";
+    if (local) return write(text),0;
+    else return text;
+  }
+
+  /* does this player exist? */
+  str=old_explode(str,".")[0];
+  userinfo=MASTER->get_userinfo(str);
+  player=find_player(str)||find_netdead(str);
+
+  if( (!pointerp(userinfo) || userinfo[USER_LEVEL+1]==-1)
+	&& !player) {
+    text="Hmm... diesen Namen gibt es im "MUDNAME" nicht.\n";
+    if (tmp="/secure/master"->QueryBanished(str)){
+      text="Hoppla - dieser Name ist reserviert oder gesperrt (\"gebanisht\")!\n";
+      if ( tmp != "Dieser Name ist gesperrt." )
+          text += "Grund fuer die Sperrung: " + tmp +
+              (member( ({'!','?','.'}), tmp[<1] ) != -1 ? "" : ".") + "\n";
+    }
+    if (local) return write(text),0;
+    else return text;
+  }
+
+  if (player) {
+    hc_play=player->query_hc_play();
+    properties=player->QueryProperties();
+    properties[P_RACE]=player->QueryProp(P_RACE);
+    properties[P_VISIBLE_GUILD]=player->QueryProp(P_VISIBLE_GUILD);
+    properties[P_TITLE]=player->QueryProp(P_TITLE);
+    tmp = player->QueryProp(P_PRESAY);
+    properties[P_PRESAY]=(stringp(tmp) && sizeof(tmp)>1) ? tmp[0..<2] : 0;
+  }
+  else
+    restore_object("/save/"+str[0..0]+"/"+str);
+  if (!properties)
+  {
+    text+="Mist!!! Das Einlesen der Daten klappt nicht wie es soll :-(\n";
+    properties=0;
+    if (!local)
+      return text;
+    write(text);
+    return "";
+  }
+  if ( player && interactive(player) )
+      ipnum = query_ip_number(player);
+  else
+      ipnum = properties[P_CALLED_FROM_IP];
+  // frueher stand in P_CALLED_FROM_IP evtl. auch der Name direkt drin
+  // anstelle der numerischen IP
+  ip=query_ip_name(ipnum)||properties[P_CALLED_FROM_IP];
+  if(player) {
+      if (!interactive(player) || (idle=query_idle(player))<MINIDLE)
+          idle=0;
+      if (!(invis=age=player->QueryProp(P_INVIS)))
+          age=player->QueryProp(P_AGE);
+  } else {
+    if (properties[P_INVIS]) age=properties[P_INVIS];
+    idle=properties[P_LAST_LOGOUT];
+  }
+
+   wizlevel=query_wiz_level(str);
+   if ( (tmp = file_time("/save/"+str[0..0]+"/"+str+".o")) <= 0 )
+       // Hack, um bei ganz "frischen" Spielern (noch kein Savefile vorhanden)
+       // die Ausgabe von 1.1.1970 zu verhindern
+       tmp = time();
+   last=properties[P_LAST_LOGOUT];
+   if ( last <= 0 || (!(flags&FLAG_VIS_LOGOUT) && wiz && wizlevel > 10
+                  && properties[P_INVIS] && tmp - last > 300) )
+       last = tmp;
+
+  /* output routine for all */
+  if(player) {
+    h=player->QueryProp(P_RACE);
+    if(interactive(player) && (wiz || !invis)) {
+      text+=capitalize(str)+" ist anwesend,\n"+
+        "und zwar von: "+
+          (wiz ? (ip+(ipnum?" ("+ipnum+")":"")):"")+
+          (stringp(properties[P_LOCATION]) ? (wiz ? "\n              [" : "")
+           +capitalize(properties[P_LOCATION])+
+           ((properties[P_LOCATION] != country(ip, ipnum))
+            ? " (ueber "+country(ip, ipnum)+")" : "" )
+           : (wiz?" [":"")+country(ip, ipnum))+(wiz ? "]":"")+".\n";
+      if(idle)
+        text+="Passiv seit: "+timediff(idle)+"\n";
+     if (local)
+      text+="Eingeloggt seit: "+dtime(properties[P_LAST_LOGIN])+"\n";
+     if (properties[P_AWAY])
+       away="z.Z. abwesend, Grund  : "+properties[P_AWAY]+"\n";
+    } else
+      text+=capitalize(str)+" ist nicht anwesend.\nZuletzt eingeloggt von: "+
+        (wiz ? (ip+(ipnum&&ipnum!=ip?" ("+ipnum+")":"")):"")+
+        (stringp(properties[P_LOCATION]) ?
+         (wiz ? "\n                        [": "")
+         +capitalize(properties[P_LOCATION])+" (ueber "+country(ip, ipnum)+")":
+         (wiz?" [":"")+country(ip, ipnum))+(wiz ? "]":"")+".\n"+
+        "Zuletzt ausgeloggt: "+dtime(last)+" ("+timediff(time()-last)+").\n";
+  }
+  else {
+    text+=capitalize(str)+" ist nicht anwesend.\nZuletzt eingeloggt von: "+
+        (wiz ? (ip+(ipnum&&ipnum!=ip?" ("+ipnum+")":"")):"")+
+        (stringp(properties[P_LOCATION]) ?
+         (wiz ? "\n                        [": "")
+         +capitalize(properties[P_LOCATION])+" (ueber "+country(ip, ipnum)+")":
+         (wiz?" [":"")+country(ip, ipnum))+(wiz ? "]":"")+".\n"+
+        "Zuletzt ausgeloggt: "+dtime(last)+" ("+timediff(time()-last)+").\n";
+  }
+  text+="Voller Name: "+(((h=properties[P_PRESAY]) && h!="") ? h+" " : "")+
+    capitalize((h=properties[P_NAME]) ? h : str)+" "+
+     ((h=properties[P_TITLE]) ? h :
+    ((mappingp(h=properties["guild_title"]) && (h=(h[properties[P_GUILD]?properties[P_GUILD]:"abenteurer"])) ) ? h : "") )
+       +"\n";
+
+  if (properties[P_GHOST]) text+="Hoppla, ein Geist!\n";
+  if ((flags&FLAG_LONG)&&properties[P_LONG])
+    text+="Beschreibung: \n"+break_string(properties[P_LONG],78,2);
+
+  if(wiz ||
+     (properties[P_SHOWEMAIL]=="alle") ||
+     ( (properties[P_SHOWEMAIL]=="freunde") &&
+       objectp(player) &&
+       this_player() &&
+       (ob=present("\n\bfband",player)) &&
+       pointerp(tmp=ob->QueryProp(P_AUTOLOADOBJ)) &&
+       pointerp(tmp=tmp[1]) &&
+       (member(tmp,getuid(this_player()))!=-1))) tmp = 1;
+  else tmp=0;
+
+
+  if (!(h=properties[P_RACE]) && userinfo && pointerp(userinfo) && sizeof(userinfo)>4 &&
+      stringp(userinfo[4]) && sizeof(h=old_explode(userinfo[4],"/"))>2) {
+    h=capitalize(h[2]);
+    h=(["Human":"Mensch","Dwarf":"Zwerg","Darkelf":"Dunkelelf","Orc":"Ork"])[h] || h;
+  }
+
+  if (!stringp(h)) h="<keine>";
+
+  text+="Rasse: "+h+",  Gilde: "+
+                     ((h=properties[P_VISIBLE_GUILD])?capitalize(h):((h=properties[P_GUILD])?capitalize(h):"Abenteurer"))+
+                     ((h=properties[P_VISIBLE_SUBGUILD_TITLE])?" ("+capitalize(h)+")":((h=properties[P_SUBGUILD_TITLE])?" ("+capitalize(h)+")":""))+
+                     ",  Geschlecht: "+({"neutral ?!","maennlich","weiblich","<verdammt seltsam>"})[properties[P_GENDER]]+"\n"+
+                      (seer ? "Alter: "+timediff(age*HBINT)+",   " : "")+
+                      (wizlevel>=10?"Magierlevel: "+wizlevel+
+          (wizlevel>=GOD_LVL?" (Mudgott)":str=="boing"?" (Mudgott a.D.)":str=="muadib"?" (Apostolischer Visitator)":wizlevel>=ARCH_LVL?" (Erzmagier)":IS_DEPUTY(str)?" (Hilfssheriff)":wizlevel>=ELDER_LVL?" (Weiser)":wizlevel>=LORD_LVL?" (Regionsmagier)":wizlevel>=SPECIAL_LVL?" (Hilfsmagier)":wizlevel>=DOMAINMEMBER_LVL?" (Regionsmitarbeiter)":wizlevel>WIZARD_LVL?" (Vollmagier)":" (Lehrling)"):
+                       ("Spielerlevel: "+properties[P_LEVEL]+( wizlevel ? " (Seher"+IN+")" : "" )+
+                        (((h=properties[P_GUILD_LEVEL]) && h=h[properties[P_GUILD]]) ?
+                         (",   Gildenlevel: "+h) : "" )
+                        ))+((userinfo&&pointerp(userinfo))?
+                        (sprintf("\nDatum des ersten Login: %s",
+                                 (userinfo[5] > 0) ? dtime(userinfo[5]) : "vor dem 10. Nov 1995")):"")+
+                         (tmp ? ("\nE-Mail-Adresse: "+((h=properties[P_MAILADDR]) ? h : "keine")+"\n") : "\n");
+
+  if (properties[P_HOMEPAGE])
+    text+="Homepage: "+properties[P_HOMEPAGE]+"\n";
+
+  if (stringp(data=properties[P_MESSENGER])) {
+    text+=sprintf("Messenger: %s", data);
+    if (intp(data=properties[P_ICQ])) {
+      if (data<0 && IS_WIZARD(this_player())) data*=-1;
+      if (data>0) text += sprintf(", ICQ: %d", data);
+    }
+    text+="\n";
+  } else 
+    if (intp(data=properties[P_ICQ])) {
+      if (data<0 && IS_WIZARD(this_player()))
+        data*=-1;
+      if (data>0)
+        text+=sprintf("ICQ: %d\n",data);
+    }
+
+  if (properties[P_MARRIED])
+    text+="Verheiratet mit: "+capitalize(properties[P_MARRIED])+"\n";
+
+  if ( pointerp(properties[P_SIBLINGS]) )
+      text += ({ "Es", "Er", "Sie" })[properties[P_GENDER]] + " ist Bluts" +
+          ({ "verwandt mit ", "bruder von ", "schwester von " })
+          [properties[P_GENDER]] +
+          CountUp(properties[P_SIBLINGS]) + ".\n";
+
+  text+=away;
+  
+  if(MASTER->check_late_player(str))
+  {
+    text+=capitalize(str)+" hat uns leider fuer immer verlassen.\n";
+  }
+  else
+  {
+    if (h=MASTER->QueryTBanished(str))
+      text+=capitalize(str)+" will fruehestens "+h[TBANISH_EXTRACT];
+  }
+  
+  if (h=properties[P_TESTPLAYER])
+  {
+    text+=capitalize(str)+" ist Testspieler"+IN;
+    if (stringp(h)) text+=" ("+h+")";
+    text+=".\n";
+  }
+  if ( h=properties[P_SECOND])
+  {
+    if (IS_WIZARD(this_player())) {
+       text+=capitalize(str)+" ist";
+       switch((int)properties[P_SECOND_MARK]) {
+         case -1: text+=" unsichtbar markierte"
+                       +((int)properties[P_GENDER]!=FEMALE ? "r": "");
+                  break;
+         case  0: text+=" nicht namentlich markierte"
+                       +((int)properties[P_GENDER]!=FEMALE ? "r": "");
+                  break;
+         default:
+       }
+       text+=" Zweitspieler"+IN;
+       if (stringp(h))
+         text+=" ("+capitalize(h)+")";
+       text+=".\n";
+    }
+    else if ((int)properties[P_SECOND_MARK]>0)
+    {
+      text+=capitalize(str)+" ist Zweitspieler"+IN;
+      if (stringp(h))
+        text+=" ("+capitalize(h)+")";
+      text+=".\n";
+    }
+    else if ((int)properties[P_SECOND_MARK]>-1)
+      text+=capitalize(str)+" ist Zweitspieler"+IN+".\n";
+  }
+  if (properties[P_DEADS])
+  {
+    text+="Bisher bereits "+properties[P_DEADS]+" mal gestorben\n";
+    // Bezieht sich nur auf den Zeitraum ab dem 30.11.'94
+  }
+  if(hc_play==1)
+  {
+    text+=capitalize(str)+" ist sehr mutig.\n";
+  }
+  if(hc_play>1)
+  {
+    text+=capitalize(str)+" ist am "+dtime(hc_play)+" in das Nirvana eingegangen.\n";
+  }
+
+  if (/*wiz && */userinfo) {
+    data=userinfo[3];
+    if (sizeof(data))
+      text+="Regionsmagier"+IN+" von     : "+implode(map(data,#'capitalize),", ")+".\n";
+    data="/secure/master"->get_domain_homes(str);
+data=filter(data-({"erzmagier"}),#'stringp); 
+    if ((wizlevel>=DOMAINMEMBER_LVL) && (sizeof(data)))
+      text+="Regionsmitarbeiter"+IN+" von: "+implode(map(data,#'capitalize),", ")+".\n";  /* #' */ 
+    }
+
+  if (userinfo) {
+    data=userinfo[8];
+    if (sizeof(data))
+      text += "Gildenmagier"+IN+" von      : "+implode(map(data, #'capitalize), ", ")+".\n";   /* #' */
+  }
+
+  // ggf. Avatar-URI mit ausgeben.
+  if (flags & FLAG_AVATAR
+      && stringp(properties[P_AVATAR_URI]))
+    text += "Avatar-URI: " + properties[P_AVATAR_URI] + "\n";
+
+  if (flags & FLAG_SPONSOR)
+    text+=sponsoring(str);
+
+  filename="/players/"+str+"/.project";
+  if(file_size(filename)>=0)
+    text+="Projekt: "+explode(read_file(filename), "\n")[0]+"\n";
+  else {
+    filename="/p/service/loco/plans/"+str+".project";
+    if(file_size(filename)>=0)
+      text+="Projekt: "+explode(read_file(filename), "\n")[0]+"\n";
+  }
+  if (seer && !(flags&FLAG_NOPLAN)) {
+    filename="/players/"+str+"/.plan";
+    if(file_size(filename)>=0)
+      text+="Plan:\n"+read_file(filename);
+    else {
+      filename="/p/service/loco/plans/"+str+".plan";
+      if(file_size(filename)>=0)
+        text+="Plan:\n"+read_file(filename);
+//      else
+//      text+="Keine .plan-Datei.\n";
+    }
+  }
+  properties=0;
+  if (!local)
+    return text;
+  this_player()->More(text);
+  return "";
+}
+
+string Finger(string str)
+{
+  if(!str || str=="") { notify_fail("Wen denn?\n"); return 0; }
+  else
+    return finger_single(str,1);
+}