/* PIPServer - A deamon for finger protocol v2
*
* Copyright (C) 1999 Michael Baumer <baumi@vis.ethz.ch>
*
* This program 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 this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <pwd.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "in.fingerd.h"
#include "local_user.h"
#include "parser.h"
#include "finger.h"
#include "file.h"
#include "configfile.h"
typedef struct finger_options {
int plan;
int mailinfo;
int project;
int tty;
int login;
} finger_options;
/* Show answer to finger */
void finger_show(finger_options *opt, finger_userinfo *uinfo)
{
char *filename;
Node *node, *cur;
int i;
fprintf(stdout, "<userinfo>\n");
fprintf(stdout, "<login>%s</login>\n", uinfo->pw_name);
filename = findUserFile(uinfo, "fingerconf");
if (filename && (node = readFingerconf(filename))) {
cur = node->child;
/* Print all info like it is in the config file
* Ugly but it works
*/
while(cur) {
if (!strcmp(cur->id, "userinfo")) {
cur = cur->child;
while (cur) {
if (!cur->child) {
fprintf(stdout, "<%s>%s</%s>\n", cur->id, cur->value, cur->id);
while (!cur->next) {
if (!cur->parent->parent->parent)
break;
cur = cur->parent;
fprintf(stdout, "</%s>\n", cur->id);
}
cur = cur->next;
}
else {
fprintf(stdout, "<%s>%s", cur->id, cur->value);
cur = cur->child;
}
}
}
else
cur = cur->next;
}
}
else {
/* No information available, use the GECOS field */
fprintf(stdout, "<realname>%s</realname>\n", uinfo->pw_realname);
}
/* print .plan file
*
* Note: GNU Finger 1.x allows the plan file to be parsed by cpp
* for replacing some strings (e.g. Date, Time).
* I don't think that is absolutely necessary and is non-standard.
*/
if (opt->plan)
if ((filename = findUserFile(uinfo, "plan"))) {
/* send the file */
fprintf(stdout, "<plan>\r\n");
print_file(filename, 1);
fprintf(stdout, "</plan>\n");
}
i = 0;
while(config.validfile[i]) {
if (strcmp(config.validfile[i], "plan") &&
(filename = findUserFile(uinfo, config.validfile[i]))) {
/* report the file */
fprintf(stdout, "<file>%s\r\n", config.validfile[i]);
if (config.filedesc[i])
fprintf(stdout, "<desc>%s</desc>\r\n", config.filedesc[i]);
fprintf(stdout, "</file>\r\n");
}
i++;
}
fprintf(stdout, "</userinfo>\n");
}
/* answer to a finger request
*
*/
void finger_handler(Node *node)
{
finger_options opt;
Node *subnode;
char *username = NULL;
char *tmp;
finger_userinfo *uinfo;
/* set default options */
opt.plan = TRUE;
opt.mailinfo = TRUE;
opt.tty = 0;
opt.login = TRUE;
opt.project = 0;
/* parse finger packets */
subnode = node->child;
while(subnode) {
switch (subnode->type) {
case OPTION:
break;
case NOOPTION:
break;
default:
if (!strcmp(subnode->id, "user")) {
username = subnode->value;
}
}
subnode = subnode->next;
}
fprintf(stdout, "<finger_reply>\n");
if (username) {
/* entspace it */
while (*username && isspace(*username))
username++;
tmp = username + strlen(username) - 1;
while((tmp >= username) && (isspace(*tmp))) {
*tmp = '\0';
tmp--;
}
/*
* 1. match login, if found print output and exit
* 2. match remote logins, if found print output and exit
* 3. match local users and their realnames
* 4. match remote users and their realnames
*
* That way we are able to provide on/offline information for matching
* Users and are able to search for non-matching users.
* The problem is that we can't provide a useful search that way,
* if the login name exists. Abbreviations must be used in that case.
*/
/* search for local users by login name */
uinfo = pwd_search_login(username, 1);
if (uinfo) {
finger_show(&opt, uinfo);
} else {
/* search for local users by real name */
/* rewind passwd file */
setpwent();
while ((uinfo = pwd_search_realname(username)))
finger_show(&opt, uinfo);
}
}
fprintf(stdout, "</finger_reply>\n");
/* free subtree */
/* todo: */
/* parstree_free(node); */
}
syntax highlighted by Code2HTML, v. 0.9.1