/*
 * @(#) $Header: /tmp/cvs/mysql-admutils/common.c,v 1.7 2006-08-15 10:32:42 geirha Exp $
 *
 * functions used by mysql-dbadm.c and mysql-useradm.c
 *
 */

#include <config.h>
#include <stdio.h>
#include <stdarg.h>
#include <mysql.h>
#include <assert.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <grp.h>
#include "mysql-admutils.h"

char *program_name;

static char *rcsheader = "@(#) " PACKAGE " " VERSION " orakel@ntnu.no $Header: /tmp/cvs/mysql-admutils/common.c,v 1.7 2006-08-15 10:32:42 geirha Exp $";


int
version()
{
  printf("%s %s\n", program_name, rcsheader);
  exit(0);
}


int
wrong_use(char *format, ...)
{
  va_list ap;

  if (format)
    {
      fprintf(stderr, "%s: ", program_name);
      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);
      putchar('\n');
    }

  fprintf(stderr, "Try `%s --help' for more information.\n", program_name);

  return 1;
}


/* always returns 1. */
int
dberror(MYSQL *pmysql, char *format, ...)
{
  char *errmsg;
  va_list ap;

  fprintf(stderr, "%s: ", program_name);
  va_start(ap, format);
  vfprintf(stderr, format, ap);
  va_end(ap);
  fprintf(stderr, "\n");

  if (pmysql)
    {
      errmsg = mysql_error(pmysql);
      if ((errmsg) && (strcmp(errmsg, "") != 0))
	fprintf(stderr, "mysql: %s\n", errmsg);
  
      mysql_close(pmysql);
    }

  return 1;
}


/* always returns 1. */
int
fatal_error(char *format, ...)
{
  va_list ap;

  fprintf(stderr, "%s: ", program_name);
  va_start(ap, format);
  vfprintf(stderr, format, ap);
  va_end(ap);
  fprintf(stderr, "\n");

  return 1;
}


/* decides if the UNIX user is entitled to the MySQL database or MySQL user. */
int
owner(char *name)
{
  struct passwd *p;
  
  p = getpwuid(getuid());
  if (!p)
    {
      dberror(NULL, "Failed to look up your UNIX username.");
      exit(1);
    }

  if (strcmp(name, p->pw_name) == 0)
    return 1; /* OK */

  if ((strncmp(name, p->pw_name, strlen(p->pw_name)) == 0) &&
      (*(name + strlen(p->pw_name)) == '_'))
    return 1; /* OK */

  return 0; /* not owner if we get as far as this */
}

/**
 * Decides if the user is member of a group. The Unix group can't contain any
 * '_'. i.e 'fidi_s' won't be accepted.
 */
int 
member(char *gr) {
  char *username;

  char *group;
  struct group *g;

  struct passwd *p;
  char *foo;

  /*  size_t i = 0; */
  
  /* Get username */
  p = getpwuid(getuid());
  if (!p) {
    fprintf(stderr, "Failed to look up your UNIX username.");
    return 0;
  }
  username = p->pw_name;
 
  /* Copy string, but cut at '_' */
  group = strdup(gr);
  if (group == NULL) {
    fprintf(stderr, "Couldn't allocate memory. Terminating."); 
    exit(1);
  }

  // ettersom man kan f� inn gruppenavn med underscore i, m� man rett og
  // slett pr�ve seg fram for � sjekke om det er en gruppe personen er med
  // i.
  // eksempel: www_esb_test_users, hvor personen ikke er med i www_est_test
  // (som kanskje finnes), men er med i www_esb.
  // group er databasenavnet som brukeren ville ha. Vi m� finne gruppenavnet
  // ut av den, og stripper av en og en underscore til vi finner noe som
  // passer.
  while ( 1 ) {

#if DEBUG
//     printf("gr = %s, group = %s, foo = %s\n", gr, group, foo);
#endif
    g = getgrnam(group);
#if DEBUG
    printf("tror gruppenavnet er: %s\n", group);
#endif 

    // hvis gruppen ikke finnes, m� vi i allefall pr�ve � se om
    // det er noe lengre inn.
    if (g) { 
      /* Check if user is member of group */
      while(*g->gr_mem != NULL) {
        char * member = *g->gr_mem; 
#if DEBUG
        printf("Medlem: %s\n", *g->gr_mem);
#endif

        if (strcmp(member,username) == 0) {
#if DEBUG      
          printf("You have access to '%s'\n", gr);
#endif
          return 1;              /* OK */
        } else
          *g->gr_mem++;
      } 
#if DEBUG
      printf("You have no access to '%s'\n", gr);
#endif
    } // if
  // brukeren var ikke med i gruppen, s� vi m� pr�ve neste.

  // finner den siste _-en i navnet.
  foo = strrchr(group, '_');
  if (foo == NULL) {
    // hvis vi har kommet helt til bunn, og fremdeles
    // ikke har blitt avbrutt, fantes det ingen slik gruppe.
    return 0;
  }
  // det som n� er bak siste underscore er passe uinteressant, s�
  // vi flytter slutten av strengen litt framover.
  *foo = '\0'; 

  } // while
}

/* return a list of the user's groupnames */
/* numgroups is the total number of groups found */
char **get_group_names(int *numgroups)
{
        char **grouplist;
        gid_t gids[33];
        int real_nr_groups, nr_groups, i;
        struct group *g;

        nr_groups = 0;

        nr_groups = getgroups(32, &gids[0]); /* Allow a max of 32 groups */

        if (nr_groups == -1) {
                dberror(NULL, "Error while trying to fetch group info");
                return NULL;
        }

	grouplist = malloc(sizeof(char *));
	real_nr_groups = 0;

	for (i = 0; i < nr_groups; i++) {
		g = getgrgid(gids[i]);

		/* Go to next grp if it doesn't have a name */
		if (g != NULL) {
			grouplist = (char **) realloc(grouplist, (real_nr_groups+2) * sizeof(char *));
			grouplist[real_nr_groups] = strdup(g->gr_name);
			real_nr_groups++;
		} else {
			fprintf(stderr, "Omitting gid %d, no entry in group-file.\n", gids[i]);
		}
	}
	grouplist[real_nr_groups] = NULL;

	*numgroups = real_nr_groups;

        return grouplist;
}


int
reload(MYSQL *pmysql)
{
  return mysql_reload(pmysql);
}