/*
    ldapdiff
    Copyright (C) 2000-2006 Thomas.Reith@rhoen.de

    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 <lber.h>
#include <ldap.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif

#include "ldapdiff.h"

/* global variables */
char *profile  = NULL;
char *logfile  = NULL;
int   facility = -1;
int   loglevel = 0;

static void printusage()
{
 printf("usage: ldapdiff [options] -p profile\n");
 printf("                 options: -c configfile\n");
 printf("                 options: -d loglevel 0|1|2\n");
 printf("                 options: -f ldiffile\n");
 printf("                 options: -l logfile\n");
 printf("                 options: -s local[0-7] (syslog facility)\n");
 printf("                 options: -v (print version and exit)\n");
}

int main(int argc,char* argv[])
{
 extern char     *optarg;
 extern int       optind;
 int              option;
 int              ldapoption;
 int              rc;
 int              ldapdiffrc  = EXITLDOK;
 int              errflag     = 0;
 char            *cfile       = NULL;
 char            *ifile       = NULL;
 char            *ldapuri     = NULL;
 LDAP            *ld;
 LDAPURLDesc      url;
 struct s_ldif   *sldif       = NULL;
 struct s_ldif   *sldifstart  = NULL;
 struct s_mod    *smod        = NULL;
 struct s_schema *sschema     = NULL;
 struct berval    passwd;
 struct berval   *spasswd;
 time_t           tstart;
 time_t           tend;

 time(&tstart);

 while ((option = getopt(argc, argv, "c:d:f:l:p:s:vh")) != EOF){
  switch(option){
   case 'c':
        cfile    = optarg;
        break;
   case 'd':
        loglevel = atoi(optarg);
        break;
   case 'f':
        ifile    = optarg;
        break;
   case 'h':
        printf("%s\n",VERSION);
        printf("%s\n",COPYING);
        printusage();
        exit(EXITLDOK);
        break;
   case 'l':
        logfile  = optarg;
        break;
   case 'p':
        profile  = optarg;
        break;
   case 's':
        if((facility = ldifgetfacility(optarg)) == -1){
         errflag++;
        }
        break;
   case 'v':
        printf("%s\n",VERSION);
        printf("%s\n",COPYING);
        exit(EXITLDOK);
        break;
   default:
        errflag++;
  }
 }

 if(errflag != 0 || profile == NULL){
  printusage();
  exit(EXITLDERROR);
 }

 /* log version information, always */
 ldiflog(LOG1,"%s",VERSION);
 ldiflog(LOG1,"%s",COPYING);
 ldiflog(LOG1,"profile:           [%s]",profile);

 if(cfile == NULL){
  cfile = LDAPCONF;
 }

 ldifinitconf(cfile); 

#ifndef USE_DEPRECATED_API
 memset(&url,0,sizeof(url));
 url.lud_scheme = "ldap";
 url.lud_host = ldifgetgconf(CONFLDAPHOST);
 url.lud_port = atoi(ldifgetgconf(CONFLDAPPORT));
 url.lud_scope = LDAP_SCOPE_DEFAULT;
 ldapuri = ldap_url_desc2str(&url);
 if((rc = ldap_initialize(&ld,ldapuri)) != LDAP_SUCCESS){
  ldiflog(LOG0,"ldap_initialize() failed: file: %s, line: %d",__FILE__,__LINE__);
  ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
  exit(EXITLDERROR);
 }
#else 
 if((ld = ldap_open(ldifgetgconf(CONFLDAPHOST),atoi(ldifgetgconf(CONFLDAPPORT)))) == NULL){
  ldiflog(LOG0,"ldap_open() failed: file: %s, line: %d",__FILE__,__LINE__);
  perror("perror(): ");
  exit(EXITLDERROR);
 }
#endif

 ldapoption = LDAP_NO_LIMIT;
 if(ldap_set_option(ld,LDAP_OPT_SIZELIMIT,&ldapoption) == -1){
  ldiflog(LOG0,"ldap_set_option() failed: file: %s, line: %d",__FILE__,__LINE__);
  exit(EXITLDERROR);
 }

 ldapoption = LDAP_VERSION3;
 if(ldap_set_option(ld,LDAP_OPT_PROTOCOL_VERSION,&ldapoption) == -1){
  ldiflog(LOG0,"ldap_set_option() failed: file: %s, line: %d",__FILE__,__LINE__);
  exit(EXITLDERROR);
 }

#ifndef USE_DEPRECATED_API
 passwd.bv_val = ldifgetgconf(CONFROOTPW);
 passwd.bv_len = strlen(passwd.bv_val);
 if((rc = ldap_sasl_bind_s(ld,ldifgetgconf(CONFROOTDN),NULL,&passwd,NULL,NULL,&spasswd)) != LDAP_SUCCESS){
  ldiflog(LOG0,"ldap_sasl_bind_s() failed: file: %s, line: %d",__FILE__,__LINE__);
#else 
 if((rc = ldap_bind_s(ld,ldifgetgconf(CONFROOTDN),ldifgetgconf(CONFROOTPW),LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS){
  ldiflog(LOG0,"ldap_bind_s() failed: file: %s, line: %d",__FILE__,__LINE__);
#endif
  ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
  exit(EXITLDERROR);
 }

 /* read ldif input */
 ldifread(&sldif,ifile);
 if(sldif == NULL){
  ldiflog(LOG1,"no ldif entries found, normal exit...");
  exit(EXITLDOK);
 }
 sldifstart = sldif; 

 /* build the schema cache */
 ldifschemacreate(ld,&sschema);

 /* replace all aliases with the real attribute names */
 ldifschemareplacealiases(sldif,sschema);

 /* compare ldif file against ldap server */
 ldifiterldif(ld,sldifstart,&smod,sschema);

 /* compare ldap server against ldif file */
 ldifiterldap(ld,sldifstart,&smod,sschema);

 ldiffree(&sldifstart);

 ldifstats(smod);

 if(strcmp(ldifgetgconf(CONFONLINEUPDATE),"yes") == 0){
  if(ldifmodify(ld,smod,sschema) != 0){
   ldapdiffrc = EXITLDWARNING;
  }
 }

 if(strcmp(ldifgetgconf(CONFOFFLINEUPDATE),"yes") == 0){
  ldifwrite(smod,sschema);
 }

 /* free the schema cache */
 ldifschemafree(&sschema);

#ifndef USE_DEPRECATED_API
 if((rc = ldap_set_option(ld,LDAP_OPT_SERVER_CONTROLS,NULL)) != LDAP_OPT_SUCCESS){
  ldiflog(LOG0,"ldap_set_option() failed: file: %s, line: %d",__FILE__,__LINE__);
  ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
  exit(EXITLDERROR);
 }
 if((rc = ldap_unbind_ext_s(ld,NULL,NULL)) != LDAP_OPT_SUCCESS){
  ldiflog(LOG0,"ldap_unbind_ext() failed: file: %s, line: %d",__FILE__,__LINE__);
  ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
  exit(EXITLDERROR);
 }
#else
 if(ldap_unbind(ld) == -1){
  ldiflog(LOG0,"ldap_unbind() failed: file: %s, line: %d",__FILE__,__LINE__);
  ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
  exit(EXITLDERROR);
 }
#endif

 /* calculate execution time */
 time(&tend);
 ldiflog(LOG1,"time:   %10d seconds",tend - tstart);

 exit(ldapdiffrc);
}


syntax highlighted by Code2HTML, v. 0.9.1