/* 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 <config.h>

#include <pwd.h>
#include <sys/types.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif /* HAVE_STRINGS_H */
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif /* HAVE_PATHS_H */
#include <stdlib.h>
#include <ctype.h>

#include "finger.h"
#include "log.h"
#include "statusdb.h"
#include "local_user.h"

void gecos_realname(finger_userinfo *finfo, char *gecos);

/* return a list of possible passwd entries of the user
 *
 * Note: We do not make case insensitive compares 
 * this allows explicit search for a Real Name that happens to be 
 * the same as some login 
 *
 * logelvel:
 *    0: do not print errors (user for 'finger @host' and statusdb)
 *    1: log errors (like nofinger exists)
 */
finger_userinfo * pwd_search_login(char *username, int loglevel)
{
  struct passwd *pwd;
  static finger_userinfo finfo;

  /* rewind passwd file */
  setpwent();
  
  while ((pwd = getpwent())) {

    if (!strcmp(username, pwd->pw_name)) {

      /* don't check system logins */
      if (pwd->pw_uid < config.first_uid) {
	/* But report them */
	if (loglevel)
	  log(LOG_WARNING, "attempted to finger %s", username);
	continue;
      }

      finfo.pw_name = pwd->pw_name;
      finfo.homedir = pwd->pw_dir;

      /* check if user doesn't want to be fingered */
      if (findUserFile(&finfo, "nofinger")) {
	if (loglevel)
	  log(LOG_WARNING, 
	      "attempted to finger %s, but user has 'nofinger' file",
	      username);
	continue;
      }

      gecos_realname(&finfo, pwd->pw_gecos);
      return &finfo;
    }
  }
  return NULL;
}

finger_userinfo * pwd_search_realname(char *username)
{
  struct passwd *pwd;
  char *idx;
  char *sidx;
  static finger_userinfo finfo;

  while ((pwd = getpwent())) {

    /* don't check system logins */
    if (pwd->pw_uid < config.first_uid)
      continue;
	
    /* search beginning of realname */
    sidx = pwd->pw_gecos;
    while(*sidx && !isalnum(*sidx))
      sidx++;

    /* only check if  username is not larger than realname */
    if (strlen(sidx) < strlen(username))
      continue;
    
    /* store end of realname */
    idx = index(pwd->pw_gecos, ',');
    if (idx)
      *idx='\0';

    while (1) {
      if (!strncasecmp(sidx, username, strlen(username))) {
	finfo.pw_name = pwd->pw_name;
	finfo.homedir = pwd->pw_dir;
	gecos_realname(&finfo, pwd->pw_gecos);

	/* Permission checks */
	if (findUserFile(&finfo, "nofinger"))
	  return NULL;

	return &finfo;
      }
      sidx=index(sidx, ' ');
      if (!sidx)
	break;
      while(*sidx && !isalnum(*sidx))
	sidx++;
    }

    /* restore end of realname */
    if (idx)
      *idx=',';
  }
  return NULL;
}

#ifndef HAVE_STRSEP
char *strsep(char **stringp, const char *delim)
{
  /* Unfortunately Solaris does not have this... */

  char *s, *tmp;

  s = *stringp;

  while(*s && (*s != *delim))
    s++;

  if (*s) {
    *s = '\0';
    tmp = *stringp;
    *stringp = ++s;
    return tmp;
  }
  return NULL;
}
#endif /* HAVE_STRSEP */

/* Parse the gecos field and return the values in the 
 * finger_userinfo structure.
 *
 * Gecos = Realname [, Office [, Office Phone [, Home Phone [, system]]]]
 */
void gecos_realname(finger_userinfo *finfo, char *gecos)
{ 
  char *token = gecos;

  finfo->office = NULL;
  finfo->office_phone = NULL;
  finfo->home_phone = NULL;

  finfo->pw_realname = strsep(&token, ",");
  if (!finfo->pw_realname) {
    finfo->pw_realname = token;
    return;
  }
  if (!strlen(finfo->pw_realname))
    finfo->pw_realname = "";

  finfo->office = strsep(&token, ",");
  if (!finfo->office) {
    finfo->office = token;
    return;
  }
  if (!strlen(finfo->office))
    finfo->office = NULL;

  finfo->office_phone = strsep(&token, ",");
  if (!finfo->office_phone) {
    finfo->office_phone = token;
    return;
  }
  if (!strlen(finfo->office_phone))
    finfo->office_phone = NULL;

  finfo->home_phone = strsep(&token, ",");
  if (!finfo->home_phone) {
    finfo->home_phone = token;
    return;
  }
  if (!strlen(finfo->home_phone))
    finfo->home_phone = NULL;
}


syntax highlighted by Code2HTML, v. 0.9.1