bin/dbupdate/dbupdate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. error_init
  2. lockfilestruct
  3. delete_key
  4. import_key
  5. get_keyowner_fingerpr
  6. deprecated_mail_from
  7. write_errors_to_ack
  8. set_default_source_data
  9. set_current_source_data
  10. process_object
  11. process_file
  12. generate_upd_file
  13. create_lock_file
  14. remove_lock_file
  15. write_checkpoint
  16. remove_checkpoint
  17. main

   1 /***************************************
   2   $Revision: 1.33 $
   3 
   4   DBupdate 
   5 
   6   Status: PARTIALLY REVIEWED, NOT TESTED
   7 
   8   Author(s):       Engin Gunduz
   9 
  10   ******************/ /******************
  11   Modification History:
  12         engin (01/03/2000) Created.
  13                 denis (31/08/2001) Modified for new API
  14   ******************/ /******************
  15   Copyright (c) 2001,2002                         RIPE NCC
  16 
  17   All Rights Reserved
  18 
  19   Permission to use, copy, modify, and distribute this software and its
  20   documentation for any purpose and without fee is hereby granted,
  21   provided that the above copyright notice appear in all copies and that
  22   both that copyright notice and this permission notice appear in
  23   supporting documentation, and that the name of the author not be
  24   used in advertising or publicity pertaining to distribution of the
  25   software without specific, written prior permission.
  26 
  27   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  28   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  29   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  30   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  31   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  32   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33  ***************************************/
  34 
  35 
  36 
  37 
  38 #include <config.h>
  39 #include "dbupdate.h"
  40 #include "UP_extrnl_syntax.h"
  41 #include "UP_subject.h"
  42 #include "er_yacc_helper.h"
  43 #include "erroutines.h"
  44 #include "ca_configFns.h"
  45 #include "ca_dictionary.h"
  46 #include "ca_macros.h"
  47 #include "ca_srcAttribs.h"
  48 #include "notification.h"
  49 #include "gpg.h"
  50 #include "mail_parser.h"
  51 #include "process.h"
  52 
  53 #ifdef HAVE_SYS_PARAM_H
  54 #include <sys/param.h>
  55 #endif
  56 
  57 extern int  num_sources;
  58 
  59 int tracing = 0;
  60 int test_mode = 0;
  61 int supress_ack_notif = 0;
  62 int print_out_ack = 0;
  63 
  64 /* do we process a mail */
  65 int reading_from_mail = 0;
  66 
  67 /* sync update flags */
  68 int webupdate = 0;
  69 int help_requested = 0;
  70 int enforced_new = 0;
  71 int origin_string = 0;
  72 
  73 /* are we processing networkupdate? */
  74 int networkupdate = 0;
  75 
  76 /* IP of the networkupdate client */
  77 char * netupdclientIP = NULL;
  78 
  79 /* two global variables to tally the processed objects */
  80 int count_successful = 0;
  81 int count_unsuccessful = 0;
  82 
  83 
  84 /* sender of the mail, in case of a mail update */
  85 char *update_mail_sender = NULL;
  86 char *update_mail_subject = NULL;
  87 char *update_mail_date = NULL;
  88 char *update_mail_ID = NULL;
  89 char *update_mail_cc = NULL;
  90 
  91 /* re-direct to humail message */
  92 char *header_type = NULL;
  93 char *text_type = NULL;
  94 
  95 /* required configuration variables */
  96 char *tmpdir = NULL;
  97 char *lockdir = NULL;
  98 char *mailcmd = NULL;
  99 char *notitxt = NULL;
 100 char *notihdr = NULL;
 101 char *successtxt = NULL;
 102 char *failuretxt = NULL;
 103 char *helpheader = NULL;
 104 char *notimailtxt = NULL;
 105 char *notinetworktxt = NULL;
 106 char *fwtxt   = NULL;
 107 char *fwhdr   = NULL;
 108 char *fwmailtxt = NULL;
 109 char *mtfwheader = NULL; 
 110 char *mtfwtxt = NULL;
 111 char *mailtxt = NULL;
 112 char *acksig = NULL;
 113 char *defmail = NULL;
 114 char *updlog = NULL;
 115 char *notiflog = NULL;
 116 char *crosslog = NULL;
 117 char *acklog = NULL;
 118 char *forwlog = NULL;
 119 char *humailbox = NULL;
 120 char *autobox = NULL;
 121 char *copyright_notice = NULL;
 122 char *overridecryptedpw = NULL;
 123 char *country = NULL;
 124 char *countries[400];
 125 char *authmethod = NULL;
 126 char *authmethods[20];
 127 char *nicsuffixes[7];
 128 char *current_source = NULL;
 129 char *pgppath = NULL;
 130 char *gpgcmd = NULL;
 131 char *pgp_public_key_ring = NULL;
 132 char *autodbmhelp = NULL; 
 133 char *update_host = NULL;
 134 int  update_port;
 135 char *query_host = NULL;
 136 int  query_port;
 137 char *cn_subject_add = NULL;
 138 char *cn_subject_del = NULL;
 139 char *cn_explain_add = NULL;
 140 char *cn_explain_del = NULL;
 141 char *cn_overlap_add = NULL;
 142 char *cn_overlap_del = NULL;
 143 char *cno_subject_add = NULL;
 144 char *cno_subject_del = NULL;
 145 char *cno_explain_add = NULL;
 146 char *cno_explain_del = NULL;
 147 char *cno_overlap_add = NULL;
 148 char *cno_overlap_del = NULL;
 149 char *allocmnt = NULL;
 150 char *mheader = NULL;
 151 char *DBhost = NULL;
 152 int  DBport;
 153 char *DBuser = NULL;
 154 char *DBname = NULL;
 155 char *DBpasswd = NULL;
 156 ca_updDbSource_t **upd_source_hdl;
 157 /* end of config variables */
 158 
 159 char * fingerprint = NULL;
 160 char * keyowner = NULL;
 161 
 162 /* result of subject line processing is kept in the following struct. */
 163 up_subject_struct subject_result;
 164 
 165 
 166 /* hostname and pid are used all over the program, so we save them into these variables */
 167 char hostname[MAXHOSTNAMELEN];
 168 /* char * hostname; */
 169 int pid;
 170 
 171 /* name of the lock file, which is used for the crash recovery mechanism */
 172 char * lock_file_name;
 173 
 174 void error_init(int argc, char ** argv) {
     /* [<][>][^][v][top][bottom][index][help] */
 175 
 176   ER_init("dbupdate", 1);
 177   
 178 
 179 } /* error_init() */
 180 
 181 
 182 
 183 
 184 
 185 
 186 /* 'lockfile' struct is for keeping both the name of the lock file and the file descriptor
 187     of it, which is open during the execution of dbupdate. We need the filedes to close it,
 188     when dbupdate finishes, and the name to delete the file. */
 189 typedef struct {
 190    char * lockname;
 191    int filedes;
 192 } lockfilestruct;
     /* [<][>][^][v][top][bottom][index][help] */
 193 
 194 
 195 lockfilestruct lockfile;
 196 
 197 
 198 
 199 /* Deletes the key defined in the incoming object (a key-cert object)
 200    from the public keyring. Returns NULL if there was no error,
 201    returns an error message if there is an error */
 202 char *delete_key(rpsl_object_t * obj)
     /* [<][>][^][v][top][bottom][index][help] */
 203 {
 204   struct ImportKeyObject iKO;
 205   char * obj_keyID;
 206   char * key_cert_attr;
 207   GList * templist;
 208   GList * certiflist, * next;
 209   u32 keyID;
 210   char * key_file_name;
 211   char ** lines;
 212   char *value;
 213   int i;
 214   FILE * key_file;
 215   char * temp, * temp2;
 216   char * error_string;
 217   rpsl_attr_t *attr;
 218 
 219 /*  templist = get_attr_list(obj, "key-cert"); */
 220    templist = rpsl_object_get_attr(obj, "key-cert");
 221  attr = (rpsl_attr_t *)(templist->data);
 222   key_cert_attr = strdup((char *)(attr->value));
 223 /*  key_cert_attr = strdup( (char *)( ((rpsl_attr_t *)(templist->data))->value ) );  */
 224   rpsl_attr_delete_list(templist);
 225 
 226   key_file_name = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
 227   sprintf(key_file_name, "%s/tmp-key.%i", tmpdir, pid);
 228 
 229   /* now we must write certif attribute(s) of this key-certif into the key_file_name */
 230   /* get the certif first */
 231 /*  certiflist = get_attr_list(obj, "certif"); */
 232   certiflist = rpsl_object_get_attr(obj, "certif");
 233   if (( key_file = fopen(key_file_name, "w")) == NULL)
 234   {
 235      ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temporary file, %s", key_file_name);
 236      exit(1);
 237   }
 238   for ( next = certiflist; next != NULL ; next = g_list_next(next) )
 239   {
 240     value = rpsl_attr_get_clean_lines( (rpsl_attr_t *)(next->data) );
 241         if (value == NULL)
 242         { /* if this was an empty attribute, just print an empty line */
 243       fprintf(key_file, "\n"); 
 244     }
 245         else
 246         {
 247           fprintf(key_file, "%s\n", value);
 248           free(value);
 249         }
 250   
 251 /*    attr = (rpsl_attr_t *)(next->data);
 252     lines = g_strsplit((char *)(attr->value), "\n", 0);
 253     if (lines[0] == NULL)
 254         { /* if this was an empty attribute, just print an empty line */
 255 /*      fprintf(key_file, "\n"); 
 256     }
 257     for (i = 0; lines[i] != NULL; i++)
 258         {
 259       temp = strdup(lines[i]);
 260       if (i != 0 && temp[0] == '+')
 261           { /* if it begins with a plus */
 262 /*        temp2 = strdup(temp + 1);
 263         g_strstrip(temp2);
 264         fprintf(key_file, "%s\n", temp2);
 265         free(temp);free(temp2);
 266       }
 267           else
 268           {
 269         g_strstrip(temp);
 270         fprintf(key_file, "%s\n", temp);
 271         free(temp); 
 272       }
 273     }
 274     g_strfreev(lines);
 275 */
 276   }
 277   fclose(key_file);
 278   rpsl_attr_delete_list(certiflist);
 279 
 280   strcpy(iKO.iFilename, key_file_name);
 281 
 282   if (tracing)
 283   {
 284     printf("TRACING: delete_key: key_cert_attr: [%s]\n", key_cert_attr);
 285   }
 286   
 287   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 288 
 289   if (tracing)
 290   {
 291     printf("TRACING: delete_key: obj_keyID: [%s]\n", obj_keyID);
 292   }
 293   
 294   keyID = strtoul(obj_keyID, NULL, 16);
 295 
 296   if (tracing)
 297   {
 298     printf("TRACING: delete_key: keyID is: %u, %X\n", keyID, keyID);
 299   }
 300   
 301   strcpy(iKO.keyRing, pgp_public_key_ring);
 302   PA_RemoveKey(&iKO);
 303 
 304   if (tracing)
 305   {
 306     printf("TRACING: importKeyObj status:\n");
 307     printf("TRACING: isValid: %d\n", iKO.rc);
 308   }
 309 
 310   /* clean-up: delete the file, free the char *    */
 311   unlink(key_file_name);
 312   free(key_file_name);
 313 
 314   if (iKO.rc == iKO_OK)
 315   { /* if PA_RemoveKey returned OK */
 316     return NULL;
 317   }
 318   else
 319   {  /* if PA_RemoveKey returned not OK */
 320       switch (iKO.rc)
 321           {
 322         case iKO_UNCHANGED:      error_string = strdup("the key is already in the keyring");break; 
 323         case iKO_NOUSERID:       error_string = strdup("no user ID could be extracted");break;
 324         case iKO_GENERAL:        error_string = strdup("general PGP error");break;
 325         case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
 326         case iKO_NOPUBLICKEY:    error_string = strdup("no public key in the object");break;
 327         case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
 328         case iKO_CRC_ERROR:      error_string = strdup("CRC error in the certificate");break;
 329         case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
 330         case iKO_NO_IN_FILES:    error_string = strdup("general PGP error");break;
 331         case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
 332         default:            error_string = strdup("general PGP error");
 333       }
 334       return error_string; 
 335   }
 336 }
 337 
 338 
 339 
 340 
 341 
 342 /* Takes a key-certif object, extracts its 'certif' attribute and adds
 343    the key into public keyring
 344    If there is no problem, it returns NULL
 345    If there is a problem, then it returns a string which contains an error
 346    message */
 347 char * import_key(rpsl_object_t *object)
     /* [<][>][^][v][top][bottom][index][help] */
 348 {
 349   char * key_file_name;
 350   char *value;
 351   struct ImportKeyObject iKO;
 352   GList * certiflist, * item, * templist;
 353   FILE * key_file;
 354   char keyID[9];
 355   char * obj_keyID, * key_cert_attr;
 356   char * error_string = NULL;
 357    
 358   key_file_name = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
 359   sprintf(key_file_name, "%s/tmp-key.%i", tmpdir, pid );
 360 
 361   /* now we must write certif attribute(s) of this key-certif into the key_file_name */
 362   /* get the certif first */
 363   certiflist = rpsl_object_get_attr(object, "certif");
 364   if (( key_file = fopen(key_file_name, "w")) == NULL)
 365   {
 366      ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temporary file, %s", key_file_name);
 367      exit(1);
 368   }
 369   for( item = certiflist; item != NULL ; item = g_list_next(item) )
 370   {
 371     value = rpsl_attr_get_clean_lines( (rpsl_attr_t *)(item->data) );
 372         if (value == NULL)
 373         { /* if this was an empty attribute, just print an empty line */
 374       fprintf(key_file, "\n"); 
 375     }
 376         else
 377         {
 378           fprintf(key_file, "%s\n", value);
 379           free(value);
 380         }
 381   }
 382   fclose(key_file);
 383   rpsl_attr_delete_list(certiflist);
 384 
 385   strcpy(iKO.iFilename, key_file_name);
 386   strcpy(iKO.keyRing, pgp_public_key_ring);
 387   PA_ImportKey(&iKO);
 388 
 389   if (tracing)
 390   {
 391     printf("importKeyObj status:\n");
 392     
 393     printf("isValid: %d\n", iKO.rc);
 394     printf("keyID: %08lX\n", (long)(iKO.keyID) );
 395   }
 396   snprintf(keyID, 9, "%08lX", iKO.keyID);
 397   
 398   if (tracing)
 399   {
 400     printf("keyID: [%s]\n", keyID);
 401   }
 402   
 403   templist = rpsl_object_get_attr(object, "key-cert");
 404   key_cert_attr = rpsl_attr_get_clean_value((rpsl_attr_t *)(templist->data));
 405   rpsl_attr_delete_list(templist);
 406 
 407   if (tracing)
 408   {
 409     printf("key_cert_attr: [%s]\n", key_cert_attr);
 410   }
 411   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 412   free(key_cert_attr);
 413   if (tracing)
 414   {
 415     printf("obj_keyID: [%s]\n", obj_keyID);
 416   }
 417 
 418   if (iKO.rc == iKO_OK && (strcasecmp(obj_keyID, keyID) == 0))
 419   { /* if PA_ImportKey returned OK 
 420     and the real keyID is equal to the
 421     keyID in the 'key-cert' attribute */
 422     fingerprint = strdup(iKO.fingerPrint); 
 423     keyowner    = strdup(iKO.keyOwner);
 424 
 425     /* clean-up: delete the file, free the variable */ 
 426     unlink(key_file_name);
 427     free(key_file_name);
 428     
 429     return NULL;
 430   }
 431   else
 432   {
 433     /* if PA_ImportKey returned not OK or obj_keyID, keyID didn't match */
 434     if  (iKO.rc != iKO_OK)
 435         {
 436       switch (iKO.rc)
 437           {
 438         case iKO_UNCHANGED:      error_string = strdup("the key is already in the keyring");break; 
 439         case iKO_NOUSERID:       error_string = strdup("no user ID could be extracted");break;
 440         case iKO_GENERAL:        error_string = strdup("general PGP error");break;
 441         case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
 442         case iKO_NOPUBLICKEY:    error_string = strdup("no public key in the object");break;
 443         case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
 444         case iKO_CRC_ERROR:      error_string = strdup("CRC error in the certificate");break;
 445         case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
 446         case iKO_NO_IN_FILES:    error_string = strdup("general PGP error");break;
 447         case iKO_INVALID_ARMOR_HEADER:  error_string = strdup("invalid armor header");break;
 448         case iKO_MULTIPLE_KEYS:  error_string = strdup("multiple keys in key-cert object");break;
 449         case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
 450         default:            error_string = strdup("general PGP error");
 451       }
 452 
 453       /* clean-up: delete the file, free the variable */ 
 454       unlink(key_file_name);
 455       free(key_file_name);
 456       return error_string; 
 457 
 458     }
 459         else
 460         {
 461       error_string = (char *)malloc(1024);/* this should be enough */
 462       sprintf(error_string, "Keyid for this certificate (%s) is not the same as the PGPKEY field (%s)", 
 463                  keyID, obj_keyID);
 464       /* roll-back: we encountered a problem, so we have to remove the key that
 465          we've added */
 466       PA_RemoveKey(&iKO);
 467 
 468       /* clean-up: delete the file, free the variable */ 
 469       unlink(key_file_name);
 470       free(key_file_name);
 471 
 472             free(obj_keyID);
 473       return error_string;
 474     }
 475   }
 476 }
 477 
 478 
 479 
 480 /* Gets the keyowner and fingerprint of a PGP key 
 481    from the keycert object. The keycert object must already
 482    be in the database (thus, in the keyring) 
 483    The fingerprint and keyowner will be saved in global variables */
 484    
 485 void get_keyowner_fingerpr(rpsl_object_t *obj)
     /* [<][>][^][v][top][bottom][index][help] */
 486 {
 487   GList * templist = NULL;
 488   char * obj_keyID = NULL;
 489   struct ImportKeyObject iKO;
 490   u32 keyID;
 491   char * key_cert_value;
 492    
 493   
 494   templist = rpsl_object_get_attr(obj, "key-cert");
 495   key_cert_value = rpsl_attr_get_clean_value((rpsl_attr_t *)(templist->data));
 496   rpsl_attr_delete_list(templist);
 497 
 498   if (tracing)
 499   {
 500     printf("get_keyowner_fingerpr: key_cert_attr is [%s]\n", key_cert_value);
 501   } 
 502   
 503   obj_keyID = strdup(key_cert_value + strlen("PGPKEY-"));
 504   if (tracing)
 505   {
 506     printf("get_keyowner_fingerpr: obj_keyID is [%s]\n", obj_keyID);
 507   }
 508  
 509   sscanf(obj_keyID, "%8X", &keyID); 
 510   if (tracing)
 511   {
 512     printf("get_keyowner_fingerpr: keyID is [%u]\n", keyID);
 513  }
 514   
 515   /* set appropriate fields of iKO */ 
 516   iKO.keyID = keyID;
 517   strcpy(iKO.keyRing, pgp_public_key_ring);
 518 
 519   GetFingerPrint(&iKO);
 520   fingerprint = strdup(iKO.fingerPrint);
 521   
 522   GetKeyOwner(&iKO);
 523   keyowner = strdup(iKO.keyOwner); 
 524 
 525   free(key_cert_value);
 526   free(obj_keyID);
 527 
 528   if(tracing)
 529   {
 530     if (fingerprint != NULL)
 531         {
 532       printf("get_keyowner_fingerpr: fingerprint is [%s]\n", fingerprint);
 533     }
 534     if (keyowner)
 535         {
 536       printf("get_keyowner_fingerpr: keyowner is [%s]\n", keyowner);
 537     }
 538   }
 539 }
 540 
 541 
 542 
 543 /* Adds an information message to the ack message if a deprecated MAIL-FROM was found in
 544    any of the mntner objects checked by the check_auth routine. */
 545 void deprecated_mail_from(char * ack_file_name, int result)
     /* [<][>][^][v][top][bottom][index][help] */
 546 {
 547   /* auth passed OK but a MAIL-FROM was still found */
 548 
 549   /* an early idea that was not implemented - so do nothing */
 550   
 551   /* remove completely during re-structuring */
 552 }
 553 
 554 
 555 /* writes the object and any attribute and object level error
 556    messages to the ack file.
 557 */
 558 
 559 void write_errors_to_ack(rpsl_object_t *object, char *arg, char * ack_file_name, char *errmsg)
     /* [<][>][^][v][top][bottom][index][help] */
 560 {
 561     const GList * attr_list = NULL;
 562     const GList * attr_list_item = NULL;
 563     const GList * error_list = NULL;
 564     const GList * error_list_item = NULL;
 565     const GList * attr_error_list = NULL;
 566     const GList * attr_error_list_item = NULL;
 567     char * arg2;
 568         const char * value = NULL;
 569         const char * name = NULL;
 570         char * attribute = NULL;
 571 
 572         /* syntax error AND not deletion */
 573 /*
 574         noclass = 0;
 575         for ( error_list_item = error_list; error_list_item != NULL; error_list_item = g_list_next(error_list_item) )
 576         {
 577           ecode = ((rpsl_error_t *)(error_list_item->data))->code;
 578       if ( ecode == RPSL_ERR_ONLYCOMMENTS || ecode == RPSL_ERR_BADCLASS
 579                     || ecode == RPSL_ERR_BADCLASS )
 580           {
 581                 noclass = 1;
 582                 break;
 583           }
 584         }
 585 */
 586     if ( UP_remove_override_attr(object) )
 587     {
 588       arg2 = rpsl_object_get_text(object,0);
 589       if ( ! arg2 )
 590       {
 591         /* if we are processing garbage with a : in the first line, arg2 may be null */
 592             arg2 = (char *)malloc(2);
 593             strcpy(arg2, "");   /* Don't include object in ack/notif msgs */
 594       }
 595     }
 596         else
 597         {
 598           /* there was an override attr in this object and it has not been removed */
 599           arg2 = (char *)malloc(2);
 600           strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
 601         }
 602 
 603 /*               if ( ! noclass )
 604         {
 605       type = rpsl_object_get_class(object);
 606           key = get_search_key(object, type);
 607       AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s \n***Error: Syntax error in object\n",
 608                          type, key ? key : "" );
 609         }
 610         else 
 611 */
 612       AK_add_to_ack(ack_file_name, "\nUpdate FAILED: Syntax error in object\n");
 613 
 614     if ( rpsl_object_has_error(object, RPSL_ERRLVL_CRIT) )
 615         {
 616           /* object not parsed so print out text version of object rather than attributes */
 617           AK_add_to_ack(ack_file_name, "%s\n", arg2);
 618     }
 619     else
 620         {
 621           /* add attributes along with any attribute error messages */
 622           attr_list = rpsl_object_get_all_attr(object);
 623           for ( attr_list_item = attr_list; attr_list_item != NULL; attr_list_item = g_list_next(attr_list_item) )
 624           {
 625                 name = rpsl_attr_get_name( (rpsl_attr_t *)(attr_list_item->data) );
 626                 if ( strcasecmp(name, "override") != 0 )
 627                 {
 628                   /* don't include the override attibute, but still include override error messages */
 629                   value = rpsl_attr_get_value( (rpsl_attr_t *)(attr_list_item->data) );
 630                   attribute = (char *)malloc( strlen(name) + strlen(value) + 3);
 631                   sprintf(attribute, "%s: %s", name, value);
 632           AK_add_to_ack(ack_file_name, "%s\n", attribute);
 633                   free(attribute);
 634                 }
 635                 attr_error_list = rpsl_attr_errors( (rpsl_attr_t *)(attr_list_item->data) );
 636                 for ( attr_error_list_item = attr_error_list; attr_error_list_item != NULL; attr_error_list_item = g_list_next(attr_error_list_item) )
 637                 {
 638                   if ( ((rpsl_error_t *)(attr_error_list_item->data))->level > RPSL_ERRLVL_DEBUG )
 639             AK_add_to_ack(ack_file_name, "***Error: %s\n", ((rpsl_error_t *)(attr_error_list_item->data))->descr);
 640                 }
 641           }
 642     }
 643 
 644     /* now add any object level error messages */
 645         error_list = rpsl_object_errors(object);
 646         for ( error_list_item = error_list; error_list_item != NULL; error_list_item = g_list_next(error_list_item) )
 647         {
 648           if ( ((rpsl_error_t *)(error_list_item->data))->level > RPSL_ERRLVL_DEBUG &&
 649                     ((rpsl_error_t *)(error_list_item->data))->code != RPSL_ERR_BADATTR )
 650           {
 651         AK_add_to_ack(ack_file_name, "***Error: %s\n", ((rpsl_error_t *)(error_list_item->data))->descr);
 652           }
 653         }
 654     
 655     if ( errmsg )
 656       AK_add_to_ack(ack_file_name, "\n%s\n", errmsg);
 657 
 658     AK_add_to_ack(ack_file_name, "\n");
 659     free(arg2);
 660 }
 661 
 662 
 663 /* sets up the current source data from the first entry in the
 664    list of config data for multiple sources.
 665    Needed for networkupdate.
 666 */
 667 
 668 void set_default_source_data()
     /* [<][>][^][v][top][bottom][index][help] */
 669 {
 670   if (tracing)
 671   {
 672     printf("TRACING: set_default_source_data running\n");
 673   }
 674   
 675   if ( current_source )
 676     free(current_source);
 677   current_source = strdup(upd_source_hdl[0]->name);
 678   update_host = upd_source_hdl[0]->whoisd_host;
 679   if ( query_host )
 680     free(query_host);
 681   query_host = strdup(update_host);
 682   update_port = upd_source_hdl[0]->updPort;
 683   query_port = upd_source_hdl[0]->qryPort;
 684   DBhost = upd_source_hdl[0]->updDb.host;
 685   DBport = upd_source_hdl[0]->updDb.port;
 686   DBname = upd_source_hdl[0]->updDb.dbName;
 687   DBuser = upd_source_hdl[0]->updDb.user;
 688   DBpasswd = upd_source_hdl[0]->updDb.password; 
 689 
 690   if (tracing)
 691   {
 692     /* print out the config variables for debugging */
 693     printf("CURRENT SOURCE is: [%s]\n", current_source);
 694     printf("UPDATE_HOST is: [%s]\n", update_host);
 695     printf("UPDATE_PORT is: [%i]\n", update_port);
 696     printf("QUERY_HOST is: [%s]\n",  query_host);
 697     printf("QUERY_PORT is: [%i]\n",  query_port);   
 698     printf("DBhost is: [%s]\n", DBhost);
 699     printf("DBport is: [%i]\n",  DBport);   
 700     printf("DBname is: [%s]\n", DBname);
 701     printf("DBuser is: [%s]\n", DBuser);
 702     printf("DBpasswd is: [%s]\n", DBpasswd);
 703   }
 704 }
 705 
 706 
 707 /* takes the source string from an object and sets up the current source
 708    data from the list of config data for multiple sources 
 709    
 710    returns 1 for success and 0 for source not found */
 711 
 712 int set_current_source_data(char *obj_source)
     /* [<][>][^][v][top][bottom][index][help] */
 713 {
 714   int i;
 715   int found = 0;
 716 
 717   if (tracing)
 718   {
 719     printf("TRACING: set_current_source_data running\n");
 720   }
 721   
 722   for ( i=0; i<num_sources; i++ )
 723   {
 724     if ( ! strcasecmp( obj_source, upd_source_hdl[i]->name) )
 725     {
 726       /* found the source in the list */
 727       found = 1;
 728       
 729       if ( current_source )
 730         free(current_source);
 731       current_source = strdup(upd_source_hdl[i]->name);
 732       update_host = upd_source_hdl[i]->whoisd_host;
 733       if ( query_host )
 734         free(query_host);
 735       query_host = strdup(update_host);
 736       update_port = upd_source_hdl[i]->updPort;
 737       query_port = upd_source_hdl[i]->qryPort;
 738       DBhost = upd_source_hdl[i]->updDb.host;
 739       DBport = upd_source_hdl[i]->updDb.port;
 740       DBname = upd_source_hdl[i]->updDb.dbName;
 741       DBuser = upd_source_hdl[i]->updDb.user;
 742       DBpasswd = upd_source_hdl[i]->updDb.password; 
 743 
 744       if (tracing)
 745       {
 746         /* print out the config variables for debugging */
 747         printf("CURRENT SOURCE is: [%s]\n", current_source);
 748         printf("UPDATE_HOST is: [%s]\n", update_host);
 749         printf("UPDATE_PORT is: [%i]\n", update_port);
 750         printf("QUERY_HOST is: [%s]\n",  query_host);
 751         printf("QUERY_PORT is: [%i]\n",  query_port);   
 752         printf("DBhost is: [%s]\n", DBhost);
 753         printf("DBport is: [%i]\n",  DBport);   
 754         printf("DBname is: [%s]\n", DBname);
 755         printf("DBuser is: [%s]\n", DBuser);
 756         printf("DBpasswd is: [%s]\n", DBpasswd);
 757       }
 758       
 759       break;
 760     }
 761   }
 762 
 763   if ( ! found  && tracing )
 764   {
 765     printf("TRACING: invalid source [%s]\n", obj_source);
 766   }
 767   
 768   return found;
 769 }
 770 
 771 
 772 
 773 /* Checks the object's syntax, retrives the old version of it from the db, 
 774    and checks auth2. If everything is OK, then sends it to RIPdb, where referential
 775    integrity is checked, and the object is really committed to the db.
 776    Also now determines which source to update for each object.
 777   
 778      Arguments:
 779         char * incoming: The object,
 780         credentials_struct credentials: The struct containing the credentials, such as 
 781           'From:' field of the e-mail update,
 782         GHashTable * NIC_hdl_hash: A hash containing 
 783         char * ack_file_name:  The file name, to be used to store ACK message 
 784         GHashTable * ntfy_hash, 
 785         GHashTable * forw_hash, 
 786         GHashTable * cross_hash: hashes that contain files that have notifications. 
 787 */
 788 
 789 
 790 
 791 int process_object(char * incoming, credentials_struct credentials, 
     /* [<][>][^][v][top][bottom][index][help] */
 792                    GHashTable * NIC_hdl_hash, char * ack_file_name,
 793                    GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash)
 794 {
 795     rpsl_object_t *object = NULL;
 796     rpsl_object_t *old_obj = NULL;
 797     rpsl_object_t *external_syntax_obj = NULL;
 798     rpsl_object_t *obj_with_AUTO_NIC_hdl = NULL;
 799     rpsl_object_t *formatted_object = NULL;
 800     rpsl_object_t *generated_obj = NULL;
 801     const GList * error_list = NULL;
 802     const GList * error_list_item = NULL;
 803     const GList * attr_list = NULL;
 804     const GList * attr_list_item = NULL;
 805     const GList * attr_error_list = NULL;
 806     const GList * attr_error_list_item = NULL;
 807     char * old_version = NULL;
 808     int result = 0;
 809     char * result_from_import_key = NULL;
 810     char * result_from_delete_key = NULL;
 811     char * auto_nic = NULL;
 812     char * changed_obj_str = NULL;
 813         char *obj_with_AUTO_NIC_hdl_str;
 814     char * assigned_NIC;
 815     char * formatted_object_str;
 816     const char * type;
 817         char *lctype;
 818     char * arg;
 819     char * arg2;
 820     char * generated_obj_str;
 821         const char * value = NULL;
 822         const char * name = NULL;
 823         char * attribute = NULL;
 824         char *key;
 825     char *obj_source = NULL;
 826     up_ripupd_result_struct * result_from_RIPupd;
 827     external_syntax_struct * external_syntax_results;
 828         gint elevel, ecode;
 829         gchar *edescr = NULL;
 830 
 831     arg = strdup(incoming);
 832         
 833         object = rpsl_object_init(arg);
 834         error_list = rpsl_object_errors(object);
 835         if (tracing && error_list)
 836         {
 837           printf("TRACING: errors found on initial object parse\n");
 838           for ( error_list_item = error_list; error_list_item != NULL; error_list_item = g_list_next(error_list_item) )
 839           {
 840             elevel = ((rpsl_error_t *)(error_list_item->data))->level;
 841                 ecode = ((rpsl_error_t *)(error_list_item->data))->code;
 842                 edescr = strdup(((rpsl_error_t *)(error_list_item->data))->descr);
 843                 
 844                 printf("TRACING: level [%d]  code [%d]  [%s]\n", elevel, ecode, edescr);
 845                 free(edescr);
 846           }
 847         }
 848         if ( error_list )
 849         {
 850           if ( ((rpsl_error_t *)(error_list->data))->code == RPSL_ERR_ONLYCOMMENTS )
 851             return UP_NOOBJECT;
 852         }
 853     
 854     /* find source from object and set current source data */
 855     attr_list = rpsl_object_get_attr(object, "source");
 856         if ( attr_list )
 857         {
 858       obj_source = rpsl_attr_get_clean_value((rpsl_attr_t *)(attr_list->data));
 859       result = set_current_source_data(obj_source);
 860       if ( ! result )
 861       {
 862         /* source in object not recognised */
 863         write_errors_to_ack(object, arg, ack_file_name, "***Error: No such source");
 864         rpsl_object_delete(object);
 865         free(arg);
 866         return UP_INT;  /* need a new return code here for object source not found in config list */
 867 /*        return UP_SNF;   */
 868       }
 869     }
 870     else
 871     {
 872       /* should only happen if the object has no source: attribute */
 873       write_errors_to_ack(object, arg, ack_file_name, NULL);
 874       rpsl_object_delete(object);
 875       free(arg);
 876       return UP_SYN;
 877     }
 878 
 879     if ( !rpsl_object_has_error(object, RPSL_ERRLVL_ERROR) 
 880                         && has_ref_to_AUTO_nic_hdl(object) )
 881         {  /* parsed with no systax errors */
 882           if (tracing)
 883           { 
 884         printf("TRACING: the object has ref to AUTO nic-hdl\n");
 885           }
 886 
 887           /* if this object has refs to AUTO NIC hdls*/
 888       /* then first replace AUTO NIC hdls with assigned NIC hdls (in NIC_hdl_hash) */
 889       if ((changed_obj_str = replace_refs_to_AUTO_NIC_hdl(object, NIC_hdl_hash, arg)) == NULL)
 890           {
 891                 type = rpsl_object_get_class(object);
 892 
 893                 free(arg);
 894         if ( UP_remove_override_attr(object) )
 895         {
 896           arg = rpsl_object_get_text(object,0);
 897           if ( ! arg )
 898           {
 899             /* if we are processing garbage with a : in the first line, arg will be null */
 900                 arg = (char *)malloc(2);
 901                 strcpy(arg, "");        /* Don't include object in ack/notif msgs */
 902           }
 903         }
 904                 else
 905                 {
 906                   /* there was an override attr in this object and it has not been removed */
 907                   arg = (char *)malloc(2);
 908                   strcpy(arg, "");      /* Don't include object in ack/notif msgs */
 909                 }
 910 
 911         AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] Unknown AUTO NIC handle referenced\n%s\n", 
 912                 type ? type : "unknown-type", arg);
 913 
 914         rpsl_object_delete(object);
 915         free(arg); 
 916         return UP_ANE; /* AUTO NIC hdl error */
 917       }
 918           else
 919           { /* in this case, we must use changed_obj_str instead of arg */
 920 
 921         free(arg); 
 922         arg = changed_obj_str; 
 923       };
 924     }
 925   
 926     
 927     if ( !rpsl_object_has_error(object, RPSL_ERRLVL_ERROR) )
 928         {
 929           /* parsed with no systax errors */
 930     
 931       /* find source from object and set current source data */
 932       attr_list = rpsl_object_get_attr(object, "source");
 933           if ( attr_list )
 934           {
 935         obj_source = rpsl_attr_get_clean_value((rpsl_attr_t *)(attr_list->data));
 936         result = set_current_source_data(obj_source);
 937         if ( ! result )
 938         {
 939           write_errors_to_ack(object, arg, ack_file_name, "***Error: No such source");
 940           rpsl_object_delete(object);
 941           free(arg);
 942           return UP_INT;  /* need a new return code here for object source not found in config list */
 943   /*        return UP_SNF;   */
 944         }
 945       }
 946       else
 947       {
 948         /* should only happen if the object has no source: attribute */
 949         write_errors_to_ack(object, arg, ack_file_name, NULL);
 950         rpsl_object_delete(object);
 951         free(arg);
 952         return UP_SYN;
 953       }
 954 
 955       type = rpsl_object_get_class(object);
 956       /* is the object to be deleted? */
 957       if ( rpsl_object_is_deleted(object) )
 958           {
 959         old_version = get_old_version(object, arg);
 960 
 961         if(old_version == NULL)
 962                 {  /* the object doesn't exist in the db! */
 963 
 964                   if (tracing)
 965                   { 
 966                 printf("TRACING: the object doesn't exist in the db\n");
 967                   }
 968 
 969                   free(arg);
 970           if ( UP_remove_override_attr(object) )
 971           {
 972                 arg = rpsl_object_get_text(object,0);
 973             if ( ! arg )
 974             {
 975               /* if we are processing garbage with a : in the first line, arg will be null */
 976                   arg = (char *)malloc(2);
 977                   strcpy(arg, "");      /* Don't include object in ack/notif msgs */
 978             }
 979           }
 980                   else
 981                   {
 982                         /* there was an override attr in this object and it has not been removed */
 983                         arg = (char *)malloc(2);
 984                         strcpy(arg, "");        /* Don't include object in ack/notif msgs */
 985                   }
 986 
 987           AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n***Error: Entry not found\n\n",
 988                         type, get_search_key(object, type), arg);
 989 
 990           rpsl_object_delete(object);
 991           free(arg); 
 992           return UP_NSO; /* no such object */
 993         }
 994                 else 
 995                 {  /* the object is in the db */
 996 
 997                   if (tracing)
 998                   { 
 999                 printf("TRACING: the object is in the db\n");
1000                   }
1001 
1002                   lctype = strdup(type);
1003                   g_strdown(lctype);
1004           if (    identical(old_version, object)      /* if the old & new versions are identical */
1005                || (strcmp(lctype, "key-cert") == 0)   /* or it is a key-cert object  */
1006                || (strcmp(lctype, "inet6num") == 0) ) /* or it is an inet6num object */
1007                   {  
1008             result = check_auth(NULL, object, type, credentials);
1009             if(result == UP_AUTH_OK || result == UP_OKM)
1010                         { 
1011               if (tracing)
1012                           {
1013                 printf("TRACING: Will send the obj to be deleted\n");
1014               }
1015               if(strcmp(type, "key-cert") == 0)
1016                           {
1017                 result_from_delete_key = delete_key(object);
1018               }
1019                           else
1020                           {
1021                 result_from_delete_key = NULL;
1022               }
1023               /* if there was no problem with key deletion from the key-ring */
1024               if (result_from_delete_key == NULL)
1025                           {
1026                 result_from_RIPupd = send_object_db(object, NULL, "DEL");
1027                 if (result_from_RIPupd->result == 0)
1028                                 {
1029                   AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n", 
1030                                 type, get_search_key(object, type));
1031                   deprecated_mail_from( ack_file_name, result );
1032                   NT_write_all_ntfs(old_version, NULL, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
1033                                     credentials.from);
1034 
1035                   rpsl_object_delete(object);
1036                                   free(result_from_RIPupd);
1037                   free(arg); 
1038                           free(old_version);
1039                   return UP_OK;
1040                 }
1041                                 else
1042                                 {
1043                   AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
1044                                 type, get_search_key(object, type),
1045                                 result_from_RIPupd->error_str);
1046                   deprecated_mail_from( ack_file_name, result );
1047 
1048                   rpsl_object_delete(object);
1049                                   free(result_from_RIPupd->error_str);
1050                                   free(result_from_RIPupd);
1051                   free(arg); 
1052                           free(old_version);
1053                   return UP_INT;
1054                 }
1055               }
1056                           else
1057                           {
1058                  AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
1059                                 type, get_search_key(object, type),
1060                                 result_from_delete_key);
1061                  deprecated_mail_from( ack_file_name, result );
1062 
1063                  rpsl_object_delete(object);
1064                  free(arg); 
1065                          free(old_version);
1066                  free(result_from_delete_key); 
1067                  return UP_INT;
1068               }
1069             }
1070                         else
1071                         { /* auth failed */
1072               if (tracing) 
1073                           {
1074                 printf("TRACING: Auth failed\n");
1075               }
1076 
1077                       free(arg);
1078                   if ( UP_remove_override_attr(object) )
1079               {
1080                         arg = rpsl_object_get_text(object,0);
1081                 if ( ! arg )
1082                 {
1083                   /* if we are processing garbage with a : in the first line, arg may be null */
1084                       arg = (char *)malloc(2);
1085                       strcpy(arg, "");  /* Don't include object in ack/notif msgs */
1086                 }
1087               }
1088                           else
1089                           {
1090                                 /* there was an override attr in this object and it has not been removed */
1091                                 arg = (char *)malloc(2);
1092                                 strcpy(arg, "");        /* Don't include object in ack/notif msgs */
1093                           }
1094 
1095               AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
1096                             type, get_search_key(object, type), arg);
1097               deprecated_mail_from( ack_file_name, result );
1098               NT_write_all_frwds(old_version, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
1099 
1100               rpsl_object_delete(object);
1101               free(arg); 
1102                       free(old_version);
1103               return UP_AUF; /* Auth failed */
1104             } 
1105           }  /* end of identical match */
1106                   else
1107                   {  /* the new & old versions do not match */
1108                     free(arg);
1109                 if ( UP_remove_override_attr(object) )
1110             {
1111                   arg = rpsl_object_get_text(object,0);
1112               if ( ! arg )
1113               {
1114                 /* if we are processing garbage with a : in the first line, arg may be null */
1115                     arg = (char *)malloc(2);
1116                     strcpy(arg, "");    /* Don't include object in ack/notif msgs */
1117               }
1118             }
1119                         else
1120                         {
1121                           /* there was an override attr in this object and it has not been removed */
1122                           arg = (char *)malloc(2);
1123                           strcpy(arg, "");      /* Don't include object in ack/notif msgs */
1124                         }
1125 
1126             AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n***Error: new & old versions do not match\n",
1127                  type, get_search_key(object, type), arg);
1128 
1129             rpsl_object_delete(object);
1130             free(arg); 
1131                     free(old_version);
1132             return UP_NOM; /* new & old versions do not match */
1133           }
1134         }  /* end of the object is in the db */
1135       } /* end of the object is to be deleted */
1136           else 
1137           { /* the object is _NOT_ to be deleted */
1138         
1139         if (has_AUTO_NIC_hdl(object))
1140                 { /* if the object has an AUTO NIC hdl */
1141                   external_syntax_obj = rpsl_object_copy(object);
1142           external_syntax_results = UP_check_external_syntax(external_syntax_obj);
1143           if (    external_syntax_results->result != UP_EXTSYN_ERR 
1144                && external_syntax_results->result != UP_EXTSYN_ERR_WARN)
1145                   { /* if there is no error */
1146             /* then its nic-hdl attribute must be modified so that RIPupdate
1147                would understand that it must assign a NIC handle to it */
1148             /* but first check the auth */
1149             result = check_auth(external_syntax_obj, NULL, type, credentials);
1150             if (result == UP_AUTH_OK || result == UP_OKM)
1151                         {
1152               if (tracing)
1153                           {                                
1154                   printf("TRACING: Will send the obj to be created with AUTO NIC hdl\n");
1155               }
1156               auto_nic = (char *)malloc(1024); /* should be enough for a NIC hdl */
1157               obj_with_AUTO_NIC_hdl = replace_AUTO_NIC_hdl(external_syntax_obj, auto_nic);
1158               if (tracing)
1159                           {  
1160                             obj_with_AUTO_NIC_hdl_str = rpsl_object_get_text(obj_with_AUTO_NIC_hdl,0);
1161                 printf("TRACING:  Called replace_AUTO_NIC_hdl, get [%s]\n", obj_with_AUTO_NIC_hdl_str);
1162                 printf("TRACING: Will send the obj to be added\n");
1163                                 free(obj_with_AUTO_NIC_hdl_str);
1164                                 obj_with_AUTO_NIC_hdl_str = NULL;
1165               }
1166               assigned_NIC = (char *)malloc(128); /* this should be enough for a NIC hdl */
1167               result_from_RIPupd = send_object_db(obj_with_AUTO_NIC_hdl, assigned_NIC, "ADD");
1168               if (result_from_RIPupd->result == 0)
1169                           {
1170                 AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n", type, assigned_NIC);
1171                 deprecated_mail_from( ack_file_name, result );
1172 
1173                 /* replace the AUTO nic hdl with the assigned one (for reporting purposes, in the notif mesg) */
1174                 formatted_object = UP_put_assigned_NIC(external_syntax_obj, assigned_NIC);
1175 
1176                 formatted_object_str = rpsl_object_get_text(formatted_object,0);
1177                 NT_write_all_ntfs(NULL, arg, formatted_object_str, tmpdir, ntfy_hash, forw_hash, cross_hash, 
1178                                   credentials.from);
1179                 
1180                 result_from_RIPupd->result = 0;
1181                 if (tracing && assigned_NIC != NULL)
1182                                 {  
1183                   printf("TRACING: send_object_db returned [%s] as assigned NIC hdl\n", assigned_NIC);
1184                 }
1185                 if (assigned_NIC != NULL)
1186                                 {
1187                   if (tracing)
1188                                   {
1189                     printf("TRACING: auto_nic=[%s], assigned_NIC=[%s]\n", auto_nic, assigned_NIC);
1190                   }
1191                   g_hash_table_insert(NIC_hdl_hash, auto_nic, assigned_NIC);
1192                   if (tracing)
1193                                   {
1194                     printf("TRACING: NIC_hdl_hash has %i pairs\n",g_hash_table_size(NIC_hdl_hash));
1195                   }
1196                 }
1197                 
1198                                 rpsl_object_delete(formatted_object);
1199                                 rpsl_object_delete(obj_with_AUTO_NIC_hdl);
1200                                 rpsl_object_delete(external_syntax_obj);
1201                 rpsl_object_delete(object);
1202                                 free(result_from_RIPupd);
1203                                 free(formatted_object_str);
1204                                 free(external_syntax_results->new_obj);
1205 /*                              free(external_syntax_results->error_str);*/
1206 /*                              free(external_syntax_results->warning_str);*/
1207                                 free(external_syntax_results);
1208                 free(arg); 
1209                 return UP_OK;
1210               }
1211                           else
1212                           {
1213                         if ( UP_remove_override_attr(object) )
1214                 {
1215                           arg2 = rpsl_object_get_text(object,0);
1216                   if ( ! arg2 )
1217                   {
1218                     /* if we are processing garbage with a : in the first line, arg2 may be null */
1219                         arg2 = (char *)malloc(2);
1220                         strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1221                   }
1222                 }
1223                                 else
1224                                 {
1225                                   /* there was an override attr in this object and it has not been removed */
1226                                   arg2 = (char *)malloc(2);
1227                                   strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1228                                 }
1229 
1230                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s]\n%s\n%s\n",
1231                               type, arg2, result_from_RIPupd->error_str);
1232                 deprecated_mail_from( ack_file_name, result );
1233 
1234                                 rpsl_object_delete(obj_with_AUTO_NIC_hdl);
1235                                 rpsl_object_delete(external_syntax_obj);
1236                 rpsl_object_delete(object);
1237                                 free(result_from_RIPupd);
1238                                 free(external_syntax_results->new_obj);
1239                                 free(external_syntax_results);
1240                                 free(arg2);
1241                 free(arg); 
1242                 return UP_INT;
1243               }
1244             }
1245                         else
1246                         {
1247               /* auth failed ! */
1248               if (tracing)
1249                           {
1250                 printf("TRACING: Auth failed\n");
1251               }
1252   
1253                   if ( UP_remove_override_attr(object) )
1254               {
1255                         arg2 = rpsl_object_get_text(object,0);
1256                 if ( ! arg2 )
1257                 {
1258                   /* if we are processing garbage with a : in the first line, arg2 may be null */
1259                       arg2= (char *)malloc(2);
1260                       strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
1261                 }
1262               }
1263                           else
1264                           {
1265                                 /* there was an override attr in this object and it has not been removed */
1266                                 arg2 = (char *)malloc(2);
1267                                 strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1268                           }
1269 
1270               AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
1271                             type, get_search_key(object, type), arg2);
1272               deprecated_mail_from( ack_file_name, result );
1273               NT_write_all_frwds(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
1274 
1275                       rpsl_object_delete(external_syntax_obj);
1276               rpsl_object_delete(object);
1277                           free(external_syntax_results->new_obj);
1278                       free(external_syntax_results);
1279                       free(arg2);
1280               free(arg); 
1281               return UP_AUF; /* Auth failed */
1282             }
1283           }
1284                   else
1285                   { /* external syntax check failed */
1286                 if ( UP_remove_override_attr(object) )
1287             {
1288                   arg2 = rpsl_object_get_text(object,0);
1289                 if ( ! arg2 )
1290                 {
1291                   /* if we are processing garbage with a : in the first line, arg2 may be null */
1292                       arg2= (char *)malloc(2);
1293                       strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
1294                 }
1295               }
1296                         else
1297                         {
1298                           /* there was an override attr in this object and it has not been removed */
1299                           arg2 = (char *)malloc(2);
1300                           strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1301                         }
1302 
1303             AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s%s\n",
1304                    type, get_search_key(object, type), 
1305                    arg2, external_syntax_results->error_str);
1306 
1307                     rpsl_object_delete(external_syntax_obj);
1308             rpsl_object_delete(object);
1309                         free(external_syntax_results->new_obj);
1310                         free(external_syntax_results);
1311                     free(arg2);
1312             free(arg); 
1313             return UP_SYN;
1314           }
1315         }  /* end of the object has an AUTO NIC hdl */
1316         else
1317                 { /* process object without an AUTO NIC hdl */
1318           old_version = get_old_version(object, arg);
1319           if (old_version != NULL)
1320                   { 
1321                     /* so, this is an update operation */
1322             if (tracing)
1323               printf("TRACING: this is an UPDATE\n");
1324 
1325             if ( (!reading_from_mail && !webupdate) || 
1326                 (subject_result.result != UP_SUBJ_NEW_ENFORCED))
1327                         { 
1328                           /* If the user didn't enforce creation in the subject line */
1329                       external_syntax_obj = rpsl_object_copy(object);
1330               external_syntax_results = UP_check_external_syntax(external_syntax_obj);
1331               if (    external_syntax_results->result != UP_EXTSYN_ERR 
1332                    && external_syntax_results->result != UP_EXTSYN_ERR_WARN)
1333                           { 
1334                             /* if there is no error */
1335                 if ( identical(old_version, external_syntax_obj) != 1 )
1336                                 {
1337                   /* if the old version & the new one are not identical */ 
1338                       old_obj = rpsl_object_init(old_version);
1339                       error_list = rpsl_object_errors(old_obj);
1340                       /***************************** DO SOME ERROR CHECKING / REPORTING HERE ***************/
1341 
1342                   result = check_auth(object, old_obj, type, credentials);    
1343                   if (result == UP_AUTH_OK || result == UP_OKM)
1344                                   {
1345                     if (tracing)
1346                                         {                                
1347                       printf("TRACING: Will send the obj to be updated\n");
1348                     }
1349 
1350                     generated_obj = rpsl_object_copy(external_syntax_obj);
1351                     if (strcasecmp(type, "key-cert") == 0)
1352                                         {
1353                       get_keyowner_fingerpr(object);/* get keyowner and fingerprint, 
1354                                                        save them into global vars  */
1355                       generated_obj_str = UP_generate_kc_attrs(generated_obj);
1356                                       free(external_syntax_results->new_obj);
1357                       external_syntax_results->new_obj = generated_obj_str;
1358                     }
1359                    
1360                     result_from_RIPupd = send_object_db(generated_obj, NULL, "UPD");
1361 
1362                                 if ( UP_remove_override_attr(object) )
1363                     {
1364                                   arg2 = rpsl_object_get_text(object,0);
1365                       if ( ! arg2 )
1366                       {
1367                         /* if we are processing garbage with a : in the first line, arg2 may be null */
1368                             arg2= (char *)malloc(2);
1369                             strcpy(arg2, "");   /* Don't include object in ack/notif msgs */
1370                       }
1371                     }
1372                                         else
1373                                         {
1374                                           /* there was an override attr in this object and it has not been removed */
1375                                           arg2 = (char *)malloc(2);
1376                                           strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1377                                         }
1378 
1379                     if (result_from_RIPupd->result == 0)
1380                                         {
1381                       AK_add_to_ack(ack_file_name, "\nUpdate OK: [%s] %s\n",
1382                                     type, get_search_key(object, type));
1383                       deprecated_mail_from( ack_file_name, result );
1384 
1385                       NT_write_all_ntfs(old_version, arg, external_syntax_results->new_obj, tmpdir, ntfy_hash, forw_hash, cross_hash, 
1386                                         credentials.from);
1387 
1388                                       rpsl_object_delete(generated_obj);
1389                                       rpsl_object_delete(old_obj);
1390                                       rpsl_object_delete(external_syntax_obj);
1391                       rpsl_object_delete(object);
1392                                       free(result_from_RIPupd);
1393                                           free(old_version);
1394                                       free(external_syntax_results->new_obj);
1395                                           free(external_syntax_results);
1396                                       free(arg2);
1397                       free(arg); 
1398                       return UP_OK;
1399                     }
1400                                         else
1401                                         {
1402                       AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s\n%s\n",
1403                                     type, get_search_key(object, type),
1404                                     arg2, result_from_RIPupd->error_str);
1405                       deprecated_mail_from( ack_file_name, result );
1406 
1407                                       rpsl_object_delete(generated_obj);
1408                                       rpsl_object_delete(old_obj);
1409                                       rpsl_object_delete(external_syntax_obj);
1410                       rpsl_object_delete(object);
1411                                       free(result_from_RIPupd->error_str);
1412                                       free(result_from_RIPupd);
1413                                           free(old_version);
1414                                       free(external_syntax_results->new_obj);
1415                                           free(external_syntax_results);
1416                                       free(arg2);
1417                       free(arg); 
1418                       return UP_INT;
1419                     }
1420                   }
1421                                   else if (result == UP_NAM)
1422                                   {
1423                     /* name of a person/role object cannot be changed */
1424                     if (tracing)
1425                                         {
1426                       printf("TRACING: name of a person/role object cannot be changed\n");
1427                     }
1428                     
1429                                 if ( UP_remove_override_attr(object) )
1430                     {
1431                                   arg2 = rpsl_object_get_text(object,0);
1432                       if ( ! arg2 )
1433                       {
1434                         /* if we are processing garbage with a : in the first line, arg2 may be null */
1435                             arg2= (char *)malloc(2);
1436                             strcpy(arg2, "");   /* Don't include object in ack/notif msgs */
1437                       }
1438                     }
1439                                         else
1440                                         {
1441                                           /* there was an override attr in this object and it has not been removed */
1442                                           arg2 = (char *)malloc(2);
1443                                           strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1444                                         }
1445 
1446                     AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s\n***Error: Name of a person or role object cannot be changed.\n",
1447                                   type, get_search_key(object, type), arg2);
1448 
1449                                     rpsl_object_delete(old_obj);
1450                                     rpsl_object_delete(external_syntax_obj);
1451                     rpsl_object_delete(object);
1452                                         free(old_version);
1453                                     free(external_syntax_results->new_obj);
1454                                         free(external_syntax_results);
1455                                     free(arg2);
1456                     free(arg); 
1457                     return UP_NAM; /* name of a person/role object cannot be changed */
1458 
1459 
1460                   }
1461                   else
1462                                   {
1463                     /* auth failed ! */
1464                     if (tracing)
1465                                         {
1466                       printf("TRACING: Auth failed\n");
1467                     }
1468       
1469                                 if ( UP_remove_override_attr(object) )
1470                     {
1471                                   arg2 = rpsl_object_get_text(object,0);
1472                       if ( ! arg2 )
1473                       {
1474                         /* if we are processing garbage with a : in the first line, arg2 may be null */
1475                             arg2= (char *)malloc(2);
1476                             strcpy(arg2, "");   /* Don't include object in ack/notif msgs */
1477                       }
1478                     }
1479                                         else
1480                                         {
1481                                           /* there was an override attr in this object and it has not been removed */
1482                                           arg2 = (char *)malloc(2);
1483                                           strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1484                                         }
1485 
1486                     /* we can now have a hierarchical authorisation failure in an update
1487                        if an inet6num status is set to ASSIGNED when there are more specific objects */
1488                     if (result == UP_HOF)
1489                       AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\nHierarchical Authorisation failed, request forwarded to maintainer.\n%s\n",
1490                                   type, get_search_key(object, type), arg2);
1491                     else
1492                       AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
1493                                   type, get_search_key(object, type), arg2);
1494                     deprecated_mail_from( ack_file_name, result );
1495 
1496                     NT_write_all_frwds(old_version, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
1497 
1498                                     rpsl_object_delete(old_obj);
1499                                     rpsl_object_delete(external_syntax_obj);
1500                     rpsl_object_delete(object);
1501                                         free(old_version);
1502                                     free(external_syntax_results->new_obj);
1503                                         free(external_syntax_results);
1504                                     free(arg2);
1505                     free(arg); 
1506                     return UP_AUF; /* Auth failed */
1507                   }
1508 
1509                 }
1510                                 else
1511                                 { /* if the old and new versions of the object are the same */
1512                   if (tracing)
1513                                   {                                
1514                       printf("TRACING: The obj sent is identical to the one in the DB (NOOP)\n");
1515                   }
1516 
1517                   AK_add_to_ack(ack_file_name, "\nUpdate NOOP: [%s] %s\n",
1518                                     type, get_search_key(object, type));
1519 
1520                                   rpsl_object_delete(external_syntax_obj);
1521                   rpsl_object_delete(object);
1522                               free(old_version);
1523                                   free(external_syntax_results->new_obj);
1524                               free(external_syntax_results);
1525                   free(arg); 
1526                   return UP_OK;
1527                 }
1528               }
1529                           else
1530                           { /* if there is an error in external syntax checks */
1531                         if ( UP_remove_override_attr(object) )
1532                 {
1533                   arg2 = rpsl_object_get_text(object,0);
1534                   if ( ! arg2 )
1535                   {
1536                     /* if we are processing garbage with a : in the first line, arg2 may be null */
1537                         arg2= (char *)malloc(2);
1538                         strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1539                   }
1540                 }
1541                                 else
1542                                 {
1543                                   /* there was an override attr in this object and it has not been removed */
1544                                   arg2 = (char *)malloc(2);
1545                                   strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1546                                 }
1547 
1548                 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s%s\n",
1549                      type, get_search_key(object, type), 
1550                      arg2, external_syntax_results->error_str);
1551 
1552                                 rpsl_object_delete(external_syntax_obj);
1553                 rpsl_object_delete(object);
1554                             free(old_version);
1555                                 free(external_syntax_results->new_obj);
1556                             free(external_syntax_results);
1557                 free(arg2); 
1558                 free(arg); 
1559                 return UP_SYN;
1560               }
1561             }
1562                         else
1563                         { /* if the user enforced creation (using NEW keyword) in the subject line */
1564                   if ( UP_remove_override_attr(object) )
1565               {
1566                         arg2 = rpsl_object_get_text(object,0);
1567                 if ( ! arg2 )
1568                 {
1569                   /* if we are processing garbage with a : in the first line, arg2 may be null */
1570                       arg2= (char *)malloc(2);
1571                       strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
1572                 }
1573               }
1574                           else
1575                           {
1576                                 /* there was an override attr in this object and it has not been removed */
1577                                 arg2 = (char *)malloc(2);
1578                                 strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1579                           }
1580 
1581               AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s\n"
1582                    "***Error:  Object already exists\n",
1583                    type, get_search_key(object, type), arg2),
1584 
1585               rpsl_object_delete(object);
1586                           free(old_version);
1587               free(arg2); 
1588               free(arg); 
1589               return UP_INT;
1590               
1591             }
1592           }  /* end of this is an update operation */
1593                   else
1594                   { /* old_version  == NULL, so, creation */
1595             if (tracing)
1596               printf("TRACING: this is a CREATION\n");
1597 
1598                     external_syntax_obj = rpsl_object_copy(object);
1599             external_syntax_results = UP_check_external_syntax(external_syntax_obj);
1600             if (    external_syntax_results->result != UP_EXTSYN_ERR 
1601                  && external_syntax_results->result != UP_EXTSYN_ERR_WARN)
1602                         {
1603                           /* if there is no error */
1604               result = check_auth(object, NULL, type, credentials);
1605               if (result == UP_AUTH_OK || result == UP_OKM)
1606                           { 
1607                 if (tracing)
1608                                 {                                
1609                   printf("TRACING: Will send the obj to be added\n");
1610                 }
1611                  /* if the object is a key-cert object, then we must import the PGP key */
1612                 if ( strcmp(type, "key-cert") == 0 )
1613                                 {
1614                   result_from_import_key = import_key(object);
1615                 }
1616                                 else
1617                                 {
1618                   result_from_import_key = NULL;
1619                 }
1620                 if (result_from_import_key == NULL)
1621                                 { 
1622                                   /* no PGP problem */
1623                                   generated_obj = rpsl_object_copy(external_syntax_obj);
1624                   if (strcasecmp(type, "key-cert") == 0)
1625                                   {
1626                                     /* if the object is a key-cert object */
1627                     generated_obj_str = UP_generate_kc_attrs(generated_obj);
1628                                     free(external_syntax_results->new_obj);
1629                     external_syntax_results->new_obj = generated_obj_str;
1630                   }
1631                   result_from_RIPupd = send_object_db(generated_obj, NULL, "ADD");                     
1632 
1633                   if (result_from_RIPupd->result == 0)
1634                                   { 
1635                                     /* if there was no problem */
1636                     AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n",
1637                                   type, get_search_key(object, type));
1638                     deprecated_mail_from( ack_file_name, result );
1639 
1640                     NT_write_all_ntfs(NULL, arg, external_syntax_results->new_obj, tmpdir, 
1641                                                            ntfy_hash, forw_hash, cross_hash, credentials.from);
1642 
1643                                     rpsl_object_delete(generated_obj);
1644                                     rpsl_object_delete(external_syntax_obj);
1645                     rpsl_object_delete(object);
1646                                     free(result_from_RIPupd);
1647                                     free(external_syntax_results->new_obj);
1648                                         free(external_syntax_results);
1649                     free(arg); 
1650                     return UP_OK;
1651 
1652                   }
1653                                   else
1654                                   {
1655                     AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n",
1656                                   type, get_search_key(object, type),
1657                                   result_from_RIPupd->error_str);
1658                     deprecated_mail_from( ack_file_name, result );
1659 
1660                                     rpsl_object_delete(generated_obj);
1661                                     rpsl_object_delete(external_syntax_obj);
1662                     rpsl_object_delete(object);
1663                                     free(result_from_RIPupd->error_str);
1664                                     free(result_from_RIPupd);
1665                                     free(external_syntax_results->new_obj);
1666                                         free(external_syntax_results);
1667                     free(arg); 
1668                     return UP_INT;
1669                   }
1670                 }
1671                                 else
1672                                 {
1673                                   /* there was a problem with PGP key import */
1674                   AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n",
1675                                   type, get_search_key(object, type),
1676                                   result_from_import_key);
1677 
1678                                   rpsl_object_delete(external_syntax_obj);
1679                   rpsl_object_delete(object);
1680                   free(result_from_import_key);
1681                                   free(external_syntax_results->new_obj);
1682                                   free(external_syntax_results);
1683                   free(arg); 
1684                   return UP_INT;
1685                 }
1686               }
1687                           else if (result == UP_FWD)
1688                           { 
1689                             /* this was a maintainer or as-block creation request, so
1690                    forward it to <HUMAILBOX> */
1691                 if (tracing)
1692                                 {
1693                   printf("TRACING: Maintainer or as-block or irt request will be forwarded to <HUMAILBOX>\n");
1694                 }
1695 
1696                         if ( UP_remove_override_attr(object) )
1697                 {
1698                           arg2 = rpsl_object_get_text(object,0);
1699                   if ( ! arg2 )
1700                   {
1701                     /* if we are processing garbage with a : in the first line, arg2 may be null */
1702                         arg2= (char *)malloc(2);
1703                         strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1704                   }
1705                 }
1706                                 else
1707                                 {
1708                                   /* there was an override attr in this object and it has not been removed */
1709                                   arg2 = (char *)malloc(2);
1710                                   strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1711                                 }
1712 
1713                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n"
1714                               "***Error:     %s objects cannot be created automatically\n"
1715                               "***Error:     This object has been forwarded to %s\n"
1716                               "***Error:     for authorisation.\n"
1717                               "***Error:     No further action from your part is required\n",
1718                               type, get_search_key(object, type),
1719                               arg2, type, humailbox);
1720 
1721                 if ( ! strcmp(type, "mntner") )
1722                 {
1723                   header_type = strdup("Maintainer");
1724                   text_type = strdup("maintainer");
1725                 }
1726                 else if ( ! strcmp(type, "as-block") )
1727                 {
1728                   header_type = strdup("as-block");
1729                   text_type = strdup("as-block");
1730                 }
1731                 else if ( ! strcmp(type, "irt") )
1732                 {
1733                   header_type = strdup("irt");
1734                   text_type = strdup("irt");
1735                 }
1736                 else
1737                 {
1738                   header_type = strdup("");
1739                   text_type = strdup("");
1740                 }
1741 
1742                 /* and forward this creation request to <HUMAILBOX> */
1743                 NT_forw_create_req(external_syntax_results->new_obj);
1744 
1745                                 rpsl_object_delete(external_syntax_obj);
1746                 rpsl_object_delete(object);
1747                                 free(external_syntax_results->new_obj);
1748                                 free(external_syntax_results);
1749                                 free(arg2);
1750                 free(arg); 
1751                 free(header_type);
1752                 free(text_type);
1753                 return UP_AUF;
1754               }
1755                           else if (result == UP_HOF)
1756                           {
1757                             /* hierarchical authorisation failed */
1758                 if (tracing)
1759                                 {
1760                   printf("TRACING: Auth failed\n");
1761                 }
1762 
1763                         if ( UP_remove_override_attr(object) )
1764                 {
1765                           arg2 = rpsl_object_get_text(object,0);
1766                   if ( ! arg2 )
1767                   {
1768                     /* if we are processing garbage with a : in the first line, arg2 may be null */
1769                         arg2= (char *)malloc(2);
1770                         strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1771                   }
1772                 }
1773                                 else
1774                                 {
1775                                   /* there was an override attr in this object and it has not been removed */
1776                                   arg2 = (char *)malloc(2);
1777                                   strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1778                                 }
1779 
1780                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nHierarchical authorisation failed, request forwarded to maintainer.\n%s\n",
1781                               type, get_search_key(object, type), arg2);
1782 
1783                 NT_write_all_frwds(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
1784 
1785                                 rpsl_object_delete(external_syntax_obj);
1786                 rpsl_object_delete(object);
1787                                 free(external_syntax_results->new_obj);
1788                                 free(external_syntax_results);
1789                                 free(arg2);
1790                 free(arg); 
1791                 return UP_AUF;
1792               }
1793                           else
1794                           {
1795                 /* auth failed ! */
1796                 if (tracing)
1797                                 {
1798                   printf("TRACING: Auth failed\n");
1799                 }
1800 
1801                         if ( UP_remove_override_attr(object) )
1802                 {
1803                           arg2 = rpsl_object_get_text(object,0);
1804                   if ( ! arg2 )
1805                   {
1806                     /* if we are processing garbage with a : in the first line, arg2 may be null */
1807                         arg2= (char *)malloc(2);
1808                         strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1809                   }
1810                 }
1811                                 else
1812                                 {
1813                                   /* there was an override attr in this object and it has not been removed */
1814                                   arg2 = (char *)malloc(2);
1815                                   strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
1816                                 }
1817 
1818                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
1819                               type, get_search_key(object, type), arg2);
1820                 deprecated_mail_from( ack_file_name, result );
1821 
1822                 NT_write_all_frwds(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
1823 
1824                                 rpsl_object_delete(external_syntax_obj);
1825                 rpsl_object_delete(object);
1826                                 free(external_syntax_results->new_obj);
1827                                 free(external_syntax_results);
1828                                 free(arg2);
1829                 free(arg); 
1830                 return UP_AUF; /* Auth failed */
1831               }
1832             }
1833                         else
1834                         {
1835                   if ( UP_remove_override_attr(object) )
1836               {
1837                         arg2 = rpsl_object_get_text(object,0);
1838                 if ( ! arg2 )
1839                 {
1840                   /* if we are processing garbage with a : in the first line, arg2 may be null */
1841                       arg2= (char *)malloc(2);
1842                       strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
1843                 }
1844               }
1845                           else
1846                           {
1847                                 /* there was an override attr in this object and it has not been removed */
1848                                 arg2 = (char *)malloc(2);
1849                                 strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
1850                           }
1851 
1852               AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s%s\n",
1853                               type, get_search_key(object, type), 
1854                               arg2, external_syntax_results->error_str);
1855 
1856                           rpsl_object_delete(external_syntax_obj);
1857               rpsl_object_delete(object);
1858                           free(external_syntax_results->new_obj);
1859                           free(external_syntax_results);
1860                           free(arg2);
1861               free(arg); 
1862               return UP_SYN;
1863             }
1864           }  /* end of creation */
1865         }  /* end of process object without an AUTO NIC hdl */
1866       }  /* end of the object is _not_ to be deleted */
1867     }  /* end of parsed with no systax errors */
1868         else
1869         {
1870             /* even if obj doesn't parse properly, it may be a legacy object
1871             which the user wants to delete... */
1872        if (tracing)
1873            {   
1874          printf("TRACING: Object didn't parse, check for legacy object deletion\n");   
1875        }
1876        /* if it is for deletion */
1877        if (rpsl_object_is_deleted(object))
1878            {
1879          /* here delete it */
1880          type = rpsl_object_get_class(object);
1881          old_version = get_old_version(object, arg);
1882 
1883                  if (tracing)
1884                  { 
1885            printf("TRACING: old_version: [\n%s]\n arg: [\n%s]\n", old_version, arg);
1886                  }
1887 
1888          if (old_version == NULL)
1889                  { 
1890                    /* the object doesn't exist in the db! */
1891                    free(arg);
1892            if ( UP_remove_override_attr(object) )
1893            {
1894                  arg = rpsl_object_get_text(object,0);
1895              if ( ! arg )
1896              {
1897                /* if we are processing garbage with a : in the first line, arg may be null */
1898                    arg = (char *)malloc(2);
1899                    strcpy(arg, "");     /* Don't include object in ack/notif msgs */
1900              }
1901            }
1902                    else
1903                    {
1904                          /* there was an override attr in this object and it has not been removed */
1905                          arg = (char *)malloc(2);
1906                          strcpy(arg, "");       /* Don't include object in ack/notif msgs */
1907                    }
1908 
1909            AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n***Error: Entry not found\n\n%s\n", 
1910                           type, get_search_key(object, type), arg);
1911 
1912            rpsl_object_delete(object);
1913            free(arg); 
1914            return UP_NSO; /* no such object */
1915          }
1916                  else
1917                  {
1918 
1919                         if (tracing)
1920                         { 
1921                   printf("TRACING: legacy object is in the database\n");
1922                         }
1923 
1924                     /* the object is in the db */
1925             if ( identical(old_version, object) )
1926                         {
1927                           /* if the old & new versions are identical */
1928 
1929                           if (tracing)
1930                           { 
1931                         printf("TRACING: old & new versions are identical\n");
1932                           }
1933               result = check_auth(NULL, object, type, credentials);
1934               if (result == UP_AUTH_OK || result == UP_OKM)
1935                           { 
1936                 if (tracing)
1937                                 {
1938                   printf("TRACING: Will send the obj to be deleted\n");
1939                 }
1940                 if (strcmp(type, "key-cert") == 0)
1941                                 {
1942                   result_from_delete_key = delete_key(object);
1943                 }
1944                                 else
1945                                 {
1946                   result_from_delete_key = NULL;
1947                 }
1948                 /* if there was no problem with key deletion from the key-ring */
1949                 if (result_from_delete_key == NULL)
1950                                 {
1951                   result_from_RIPupd = send_object_db(object, NULL, "DEL");
1952                   if (result_from_RIPupd->result == 0)
1953                                   {
1954                     AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n", 
1955                                   type, get_search_key(object, type));
1956                     deprecated_mail_from( ack_file_name, result );
1957                     NT_write_all_ntfs(old_version, NULL, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
1958                                       credentials.from);
1959 
1960                         rpsl_object_delete(object);
1961                                         free(result_from_RIPupd);
1962                         free(arg); 
1963                                 free(old_version);
1964                     return UP_OK;
1965                   }
1966                                   else
1967                                   {
1968                     AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
1969                                   type, get_search_key(object, type),
1970                                   result_from_RIPupd->error_str);
1971                     deprecated_mail_from( ack_file_name, result );
1972 
1973                         rpsl_object_delete(object);
1974                                     free(result_from_RIPupd->error_str);
1975                                         free(result_from_RIPupd);
1976                         free(arg); 
1977                                 free(old_version);
1978                     return UP_INT;
1979                   }
1980                 }
1981                                 else
1982                                 {
1983                    AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
1984                                   type, get_search_key(object, type), result_from_delete_key);
1985 
1986                    rpsl_object_delete(object);
1987                    free(arg); 
1988                            free(old_version);
1989                    free(result_from_delete_key); 
1990                    return UP_INT;
1991                 }
1992               }
1993                           else
1994                           { /* auth failed */
1995                 if (tracing)
1996                                 {
1997                   printf("TRACING: Auth failed\n");
1998                 }
1999 
2000                         if ( UP_remove_override_attr(object) )
2001                 {
2002                           arg2 = rpsl_object_get_text(object,0);
2003                   if ( ! arg2 )
2004                   {
2005                     /* if we are processing garbage with a : in the first line, arg2 may be null */
2006                         arg2= (char *)malloc(2);
2007                         strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
2008                   }
2009                 }
2010                                 else
2011                                 {
2012                                   /* there was an override attr in this object and it has not been removed */
2013                                   arg2 = (char *)malloc(2);
2014                                   strcpy(arg2, "");     /* Don't include object in ack/notif msgs */
2015                                 }
2016 
2017                 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
2018                               type, get_search_key(object, type), arg2);
2019                 deprecated_mail_from( ack_file_name, result );
2020                 NT_write_all_frwds(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
2021 
2022                 rpsl_object_delete(object);
2023                 free(arg2); 
2024                 free(arg); 
2025                         free(old_version);
2026                 return UP_AUF; /* Auth failed */
2027               } 
2028             }  /* end of identical match */
2029                         else
2030                         {
2031                           /* the new & old versions do not match */
2032                   if ( UP_remove_override_attr(object) )
2033               {
2034                         arg2 = rpsl_object_get_text(object,0);
2035                 if ( ! arg2 )
2036                 {
2037                   /* if we are processing garbage with a : in the first line, arg2 may be null */
2038                       arg2= (char *)malloc(2);
2039                       strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
2040                 }
2041               }
2042                           else
2043                           {
2044                                 /* there was an override attr in this object and it has not been removed */
2045                                 arg2 = (char *)malloc(2);
2046                                 strcpy(arg2, "");       /* Don't include object in ack/notif msgs */
2047                           }
2048 
2049               AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s \n***Error: new & old versions do not match\n%s\n",
2050                               type, get_search_key(object, type), arg2);
2051 
2052               rpsl_object_delete(object);
2053               free(arg2); 
2054                       free(arg);
2055                       free(old_version);
2056               return UP_NOM; /* new & old versions do not match */
2057             }
2058           }  /* end of the object is in the db */
2059        } /* end of the object is to be deleted */
2060            else
2061            {
2062              /* syntax error AND not deletion */
2063        
2064          write_errors_to_ack(object, arg, ack_file_name, NULL);
2065          rpsl_object_delete(object);
2066                  free(arg);
2067          return UP_SYN; /* syntax error */
2068        }
2069     }
2070 }
2071 
2072 
2073 
2074 
2075 
2076 /* processes the objects in the given file */
2077 void process_file(char * filename, credentials_struct credentials, 
     /* [<][>][^][v][top][bottom][index][help] */
2078                   GHashTable * AUTO_NIC_hdl_hash, char * ack_file_name, 
2079                   GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash)
2080 {
2081 FILE * input_file;
2082 GSList *list_of_objects = NULL, *list_of_objects2 = NULL;   
2083 GSList *next = NULL;
2084 int object_count = 0;
2085 char *object = NULL;
2086 char * line;
2087 char * lwrcase_line;
2088 int result = 0;
2089 rpsl_object_t *obj = NULL;
2090 const GList * error_list = NULL;
2091 
2092     if (tracing)
2093     {
2094       printf("TRACING: process_file running\n");
2095     }
2096   
2097     line = (char *)malloc(1024);
2098 
2099     if ((input_file = fopen(filename, "r")) == NULL)
2100         {
2101         if (tracing)
2102         {
2103           printf("TRACING: Couldn't open the file %s: %s\n", filename, strerror(errno));
2104         }
2105          ER_perror(FAC_UP, UP_CANTOPEN, "Couldn't open the file %s: %s\n", filename, strerror(errno));
2106         exit(1);  
2107     }
2108   
2109     while (fgets(line, 1024, input_file) != NULL)
2110         {
2111       /* first, if it is a pasword, save it, but do not regard it as an attrib */ 
2112       lwrcase_line = strdup(line);
2113       g_strdown(lwrcase_line);
2114       if (strstr(lwrcase_line, "password:") == lwrcase_line)
2115           {
2116         if (tracing)
2117                 {
2118           printf("TRACING: This is a password\n");
2119         }
2120         credentials.password_list = g_slist_append(credentials.password_list, 
2121                                       g_strstrip(strdup(line + strlen("password:"))));
2122         free(lwrcase_line);
2123         continue;
2124       }
2125       free(lwrcase_line);
2126       
2127       line = UP_remove_EOLs(line); /* remove '\n's and '\r' first */
2128       /* remove trailing white space */
2129       line = g_strchomp(line); 
2130       if (strlen(line) == 0)
2131           {
2132             /* then, this was an empty line */
2133         if (object != NULL)
2134                 {
2135            list_of_objects = g_slist_append(list_of_objects, object);
2136            if (tracing)
2137                    {
2138              printf("TRACING: added an object: [%s]\n", object);
2139            }
2140            object = NULL;
2141         }
2142       }
2143           else
2144           {
2145         if (object == NULL && strlen(line) != 0)
2146                 {
2147           object = (char *)malloc(strlen(line) + 2);
2148           object = strcpy(object, line);
2149           object = strcat(object, "\n"); /* add EOL again (we removed it before) */
2150         }
2151         else
2152                 {
2153           object = (char *)realloc(object, strlen(object) + strlen(line) + 2);
2154           object = strcat(object, line);
2155           object = strcat(object, "\n");
2156         }
2157       }
2158       
2159     }
2160     fclose(input_file);
2161         free(line);
2162 
2163     /* now, if at the very and of the input file there wasn't an 
2164        empty line, we have to add the remaining object in the 'object'
2165        variable */
2166     if (object != NULL)
2167         {
2168        list_of_objects = g_slist_append(list_of_objects, object);
2169        object = NULL;
2170     }
2171 
2172 
2173     if (tracing)
2174         {
2175        printf("TRACING: Will process the objects in the list\n");
2176     }
2177     next = list_of_objects;
2178     object_count = 0;
2179     for ( next = list_of_objects; next != NULL ; next = g_slist_next(next) )
2180         {
2181       if (UP_is_object((char *)next->data))
2182           {
2183             /* if this looks like an object */
2184       
2185         object_count++;
2186         if(tracing)
2187                 {
2188           printf("TRACING: Got an object from the list\n");
2189           printf("[%s]\n", (char *)next->data );
2190         }
2191         
2192             obj = rpsl_object_init( (char *)next->data );
2193             error_list = rpsl_object_errors(obj);
2194 
2195         if ( ! rpsl_object_has_error(obj, RPSL_ERRLVL_ERROR) && has_ref_to_AUTO_nic_hdl(obj) )
2196                 {
2197                   /* if object has a reference to an auto- nichdl and no syntax errors
2198                      then defer the processing to allow the auto- nichdl to be created first */
2199           if(tracing)
2200                   {
2201             printf("TRACING: this object has a ref to an AUTO NIC hdl\n");
2202           }
2203           list_of_objects2 = g_slist_append(list_of_objects2, strdup((char *)next->data));
2204         }
2205                 else
2206                 {
2207           result = 0;
2208           result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name, 
2209                                    ntfy_hash, forw_hash, cross_hash);
2210           /* keep a tally */
2211           if (result == UP_NOOBJECT)
2212                   {
2213                     /* do nothing and don't increment any counts */
2214                   }
2215           else if (result == UP_OK)
2216                   {
2217             count_successful++;
2218           }
2219                   else
2220                   {
2221             count_unsuccessful++;
2222           }
2223          }
2224                 
2225         rpsl_object_delete(obj);
2226       }
2227           else
2228           {
2229             /* this does not look like an object (a signature? some other text?) */
2230         
2231         AK_add_to_ack(ack_file_name, "\nThe following paragraph does not look like an object,\n"
2232                                      "so ignoring it:\n%s\n", (char *)next->data);
2233       }
2234     }
2235 
2236 
2237     if (tracing)
2238         {
2239       printf("TRACING: list_of_objects2 has %d entries\n", g_slist_length(list_of_objects2));
2240       printf("TRACING: will start to process the second list\n");
2241     }
2242   
2243     for ( next = list_of_objects2; next != NULL ; next = g_slist_next(next) )
2244         {
2245       if (tracing)
2246           {
2247         printf("TRACING: Will process object: %s\n", (char *)next->data);
2248       }
2249       result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name, 
2250                                ntfy_hash, forw_hash, cross_hash);
2251       /* keep a tally */
2252       if (result == UP_NOOBJECT)
2253           {
2254                 /* do nothing and don't increment any counts */
2255           }
2256       else if (result == UP_OK)
2257           {
2258         count_successful++;
2259       }
2260           else
2261           {
2262         count_unsuccessful++;
2263       }
2264     }
2265 }/* process_file */
2266 
2267 
2268 
2269 
2270 /*  Generates a unique file name and returns the full path of the filename 
2271     for storing notification message.  */
2272       
2273 char * generate_upd_file()
     /* [<][>][^][v][top][bottom][index][help] */
2274 {
2275    char * name;
2276      
2277    /* allocate space for name.  32 should be enough for PID */
2278    name = (char*)malloc(strlen(tmpdir) + strlen("/dbupdate-tmp.") + 34 ); 
2279    
2280    sprintf(name, "%s/dbupdate-tmp.%i", tmpdir, pid /*getpid()*/);
2281      
2282    return name;      
2283 }
2284 
2285 
2286 /* create_lock_file: creates a lock file in lockdir and locks it. This is a 
2287    part of crash recovery. Must be called in the beginning of the run. At the
2288    end, the file must be removed. */
2289 /* The idea: Create the "lock" file, and lock it. When another process starts
2290    running, it checks the existing lock files. If some exists, then it checks
2291    if it is locked or not. It not locked, then assumes that the corresponding
2292    dbupdate is alredy running. If not locked, assumes that it has crashed. 
2293    (note: when a process crashes, the kernel releases all the files locked by
2294    this process [by the OS]) 
2295    Problem: locking doesn't work properly on some NFS implementations. */
2296 
2297 lockfilestruct create_lock_file(){
     /* [<][>][^][v][top][bottom][index][help] */
2298   
2299   lockfilestruct lock;
2300   int file;
2301   int length;
2302 
2303   /* allocate space for file name */
2304   length = strlen(lockdir) +  strlen(hostname) + 32;
2305   lock.lockname = (char *)malloc(length + 1);
2306 
2307   snprintf(lock.lockname, length, "%s/dbupdate.%s.%ld", lockdir, hostname, pid /*getpid()*/);
2308 
2309   /* we will lock the file, so we have to use open(), but not fopen() (see man 
2310      page of lockf(3C)) */
2311   if(( file = open(lock.lockname, O_RDWR|O_CREAT)) == -1){
2312     ER_perror(FAC_UP, UP_CANTOPEN, "Can't open lock file, %s", lock.lockname);
2313     exit(1);
2314   }
2315  
2316   if(lockf(file, F_LOCK, 0) == -1){
2317     ER_perror(FAC_UP, UP_CANTLOCK, "Can't lock the file, %s", lock.lockname);
2318     exit(1);
2319   }; 
2320 
2321   lock.filedes = file;
2322 
2323   return lock;
2324 
2325 }
2326 
2327 
2328 
2329 
2330 
2331 /* remove_lock_file(): unlocks and removes the file  */
2332 void remove_lock_file(lockfilestruct lockfile){
     /* [<][>][^][v][top][bottom][index][help] */
2333 
2334   close(lockfile.filedes); /* this will remove the lock at the same time */ 
2335   unlink(lockfile.lockname);
2336 
2337 }
2338 
2339 
2340 
2341 /* writes the checkpoint file with the specified state */
2342 void write_checkpoint(int state){
     /* [<][>][^][v][top][bottom][index][help] */
2343 
2344   char * filename;
2345   char * tmpfilename;
2346   int length;
2347   FILE * file;
2348 
2349   if(tracing){
2350     printf("TRACING: write_checkpoint, state=[%i]\n", state); 
2351   }
2352   length = strlen(lockdir) +  strlen(hostname) + 64;
2353   filename    = (char *)malloc(length + 1);
2354   tmpfilename = (char *)malloc(length + 5);
2355  
2356   snprintf(filename,    length, "%s/dbupdate.checkpoint.%s.%ld",     lockdir, hostname, pid );
2357   snprintf(tmpfilename, length, "%s/dbupdate.checkpoint.%s.%ld.tmp", lockdir, hostname, pid );
2358 
2359   if(( file = fopen(tmpfilename, "w")) == NULL){
2360     /* fprintf(stderr, "Can't open temp checkpoint file, %s", tmpfilename); */
2361     ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temp checkpoint file, %s", tmpfilename);
2362     exit(1);
2363   }
2364 
2365   fprintf(file, "[STATE]\n%i\n", state);
2366 
2367   fprintf(file, "[FLAGS]\n");
2368   /* should print the flags here */
2369   
2370   fprintf(file, "[PARTS]\n");
2371   /* should print the parts (filenames) here */
2372 
2373   fprintf(file, "[OBJECTS1]\n");
2374 
2375   fprintf(file, "[OBJECTS2]\n");
2376 
2377   fprintf(file, "[ACKFILE]\n");
2378   
2379   fprintf(file, "[NOTIFFILES]\n");
2380 
2381   fprintf(file, "[TIDS1]\n");
2382   
2383   fprintf(file, "[TIDS2]\n");
2384 
2385   fprintf(file, "[NICHDLHASH]\n");
2386 
2387   fprintf(file, "[CURRENTOBJECT]\n");
2388 
2389   fprintf(file, "[CURRENTPART]\n");
2390 
2391   
2392   fclose(file);
2393 
2394   rename(tmpfilename, filename);
2395 
2396   /* free the char *'s */
2397   free(tmpfilename);
2398   free(filename);
2399 
2400 }
2401 
2402 
2403 
2404 
2405 /* removes check point file */
2406 void remove_checkpoint(){
     /* [<][>][^][v][top][bottom][index][help] */
2407 
2408   char * filename;
2409   int length;
2410 
2411   if(tracing){
2412     printf("TRACING: remove_checkpoint\n"); 
2413   }
2414   
2415   length = strlen(lockdir) +  strlen(hostname) + 64;
2416   filename    = (char *)malloc(length + 1);
2417  
2418   snprintf(filename,    length, "%s/dbupdate.checkpoint.%s.%ld",     lockdir, hostname, pid );
2419 
2420   unlink(filename);
2421  
2422   /* free the char * */
2423   free(filename);
2424 
2425 }
2426 
2427 
2428 
2429 
2430 /* main */
2431 int main(int argc, char **argv, char **envp){
     /* [<][>][^][v][top][bottom][index][help] */
2432   /* init_and_set_options(argc, argv, envp); */
2433 
2434   int i,j;
2435   char ** temp_vector;
2436   char * temp;
2437   char * temp_upd_file = NULL;
2438   char *input_file_name = NULL;
2439   GHashTable *AUTO_NIC_hdl_hash;
2440   credentials_struct credentials;
2441   FILE * upd_file;
2442   char c;
2443   char * mheader_replaced = NULL;
2444   char * mailtxt_replaced = NULL;
2445 
2446   GHashTable *ntfy_hash, *forw_hash, *cross_hash;
2447   
2448 
2449   char * ack_file_name;
2450   char *config_file_name = NULL;
2451 
2452 
2453   /* to use EP module */
2454   EP_Mail_DescrPtr p; 
2455   EPTokenPtr pt;
2456   EPTokenPtr list_item;
2457   EPTokenKeysPtr ptk;
2458 
2459   char * temp_keyid;
2460   char * dummy_keyid;
2461 
2462   /* a variable to be used to know if the part is pgp_signed or not */
2463   int pgp_signed = 0;
2464 
2465   int ch;
2466   char * to_address = NULL;
2467   char * subject = NULL;
2468   char * reply_to = NULL;
2469     
2470 
2471   /* create notification hashes */
2472   ntfy_hash = g_hash_table_new(g_str_hash, g_str_equal);
2473   forw_hash = g_hash_table_new(g_str_hash, g_str_equal);
2474   cross_hash = g_hash_table_new(g_str_hash, g_str_equal);
2475       
2476   credentials.password_list = NULL;
2477   credentials.from = NULL;
2478 
2479   AUTO_NIC_hdl_hash = g_hash_table_new(g_str_hash, g_str_equal);       
2480   
2481   /* initialise the rpsl dictionary */
2482   rpsl_load_dictionary(RPSL_DICT_FRONT_END);
2483 
2484   while ((ch = getopt(argc, argv, "MtSTf:c:snwheo:")) != -1){
2485           switch(ch) {
2486           case 'M':
2487                   reading_from_mail = 1;
2488                   break;
2489           case 'f':
2490                   input_file_name = strdup(optarg);
2491                   break;
2492           case 'c':
2493                   config_file_name = strdup(optarg);
2494                   break;
2495           case 't': 
2496                   tracing = 1;
2497                   break;
2498           /* Test mode? In test mode, creation of mntners and as-blocks is possible, without overriding */        
2499           case 'T':
2500                   test_mode = 1; 
2501                   break;
2502           /* Supress acks and notifications? If yes, the acks and notifs will go to DEFMAIL config var */        
2503           case 'S': 
2504                   supress_ack_notif = 1;
2505                   break;
2506           /* Print out the ack to stdout? */        
2507           case 's':
2508                   print_out_ack = 1;
2509                   break;
2510           /* are we processing networkupdate? (invoked via inetd) */        
2511           case 'n':
2512                   networkupdate = 1;
2513                   break;
2514           case 'w':
2515                   webupdate = 1;
2516                   break;
2517           case 'h':
2518           /* help request from sync updates */
2519                   help_requested = 1;
2520                   break;
2521           case 'e':
2522           /* enforced new from sync updates */
2523                   enforced_new = 1;
2524                   break;
2525           case 'o':
2526           /* log a string from sync updates containing the origin IP address*/
2527                   netupdclientIP = strdup(optarg);
2528                   break;
2529           case '?':
2530           default:
2531                   printf("Unknown option\n"); exit(1);
2532           }
2533   }
2534 
2535   if (tracing)
2536   {
2537     printf("TRACING: options set\n");
2538     printf("TRACING: reading_from_mail [%d]\n", reading_from_mail);
2539     printf("TRACING: networkupdate [%d]\n", networkupdate);
2540     printf("TRACING: webupdate [%d]\n", webupdate);
2541     printf("TRACING: help_requested [%d]\n", help_requested);
2542     printf("TRACING: enforced_new [%d]\n", enforced_new);
2543     printf("TRACING: netupdclientIP [%s]\n", netupdclientIP ? netupdclientIP : "NULL");
2544   }
2545 
2546   /* config stuff */
2547   /* if -c flag is given, use the named file as config file, otherwise use
2548      default filename */ 
2549   if ( config_file_name != NULL)
2550   {
2551     /*ca_readConfig(config_file_name, confVars, VARS);*/
2552     ca_init(config_file_name);
2553         free(config_file_name);
2554   }
2555   else
2556   {
2557     /*ca_readConfig("dbupdate.conf", confVars, VARS);*/
2558     ca_init("dbupdate.conf");
2559   }
2560 
2561   error_init(argc, argv);
2562 
2563 
2564   tmpdir = ca_get_tmpdir;
2565   PA_SetTmpDir(tmpdir);
2566   tmpdir = g_strstrip(tmpdir);
2567   lockdir = ca_get_lockdir;
2568   mailcmd = ca_get_mailcmd;
2569   mailcmd = g_strstrip(mailcmd);
2570   notitxt = ca_get_notitxt;
2571   notihdr = ca_get_nheader;
2572   mailtxt = ca_get_mailtxt; 
2573   successtxt = ca_get_successtxt;
2574   failuretxt = ca_get_failuretxt;
2575   helpheader = ca_get_helpheader;
2576   defmail = ca_get_defmail; defmail = UP_remove_EOLs(defmail);
2577   crosslog = ca_get_crosslog;
2578   fwtxt = ca_get_fwtxt;
2579   fwhdr = ca_get_fwheader;
2580   acksig = ca_get_acksig;
2581   humailbox = ca_get_humailbox;
2582   humailbox = g_strstrip(humailbox);
2583   autobox = ca_get_autobox;
2584   overridecryptedpw = ca_get_overridecryptedpw;
2585   overridecryptedpw = g_strstrip(overridecryptedpw);
2586   updlog = ca_get_updlog;
2587   acklog = ca_get_acklog;
2588   notiflog = ca_get_notiflog;
2589   notimailtxt = ca_get_notimailtxt;  
2590   notinetworktxt = ca_get_notinetworktxt;
2591   forwlog = ca_get_forwlog;
2592   fwmailtxt = ca_get_fwmailtxt;
2593   mtfwheader = ca_get_mtfwheader;
2594   mtfwtxt = ca_get_mtfwtxt;
2595   country = ca_get_country;
2596   authmethod = ca_get_authmethod;
2597   pgppath = ca_get_pgppath;
2598   gpgcmd = ca_get_gpgcmd;
2599   PA_SetGPGCmd(gpgcmd);
2600   autodbmhelp = ca_get_autodbmhelp;
2601   allocmnt = ca_get_allocmnt; allocmnt = UP_remove_EOLs(allocmnt);
2602   /* convert all '\t's, '\n's and '\r's in allocmnt to white spaces */
2603   for(i=0;i<strlen(allocmnt);i++){
2604     if(allocmnt[i] == '\r' || allocmnt[i] == '\n' || allocmnt[i] == '\t'){
2605       allocmnt[i] = ' ';
2606     }
2607   }
2608   cn_subject_add = ca_get_cn_subject_add; cn_subject_add = UP_remove_EOLs(cn_subject_add);
2609   cn_subject_del = ca_get_cn_subject_del; cn_subject_del = UP_remove_EOLs(cn_subject_del);
2610   cn_explain_add = ca_get_cn_explain_add;
2611   cn_explain_del = ca_get_cn_explain_del;
2612   cn_overlap_add = ca_get_cn_overlap_add;
2613   cn_overlap_del = ca_get_cn_overlap_del;
2614   cno_subject_add = ca_get_cno_subject_add; cno_subject_add = UP_remove_EOLs(cno_subject_add); 
2615   cno_subject_del = ca_get_cno_subject_del; cno_subject_del = UP_remove_EOLs(cno_subject_del);
2616   cno_explain_add = ca_get_cno_explain_add;
2617   cno_explain_del = ca_get_cno_explain_del;
2618   cno_overlap_add = ca_get_cno_overlap_add;
2619   cno_overlap_del = ca_get_cno_overlap_del;
2620   copyright_notice = ca_get_pw_resp_header;
2621   mheader = ca_get_mheader;
2622   pgp_public_key_ring = (char *)malloc(strlen(pgppath) + strlen("/pubring.gpg") + 2);
2623   sprintf(pgp_public_key_ring ,"%s/pubring.gpg", pgppath);
2624   PA_SetKeyRing(pgp_public_key_ring);
2625   if(test_mode != 1){/* if it is not already set to 1 (from command line), read from config */
2626     
2627     test_mode = ca_get_testmode;
2628   }
2629   /* retrieve source variables */
2630   /* we now allow multiple sources */
2631   /* upd_source_hdl is a pointer to an array of pointers to source data */
2632   upd_source_hdl = ca_get_UpdSourceHandle(CA_UPDSOURCE);
2633 
2634   if (upd_source_hdl[0] == NULL)
2635   {
2636     printf("There must be at least one updateable source in the config file. Exiting.\n");
2637     ER_perror(FAC_UP, UP_CONFERR, "There must be at least one updateable source in"
2638                                   " the config file. Exiting.");
2639     exit(1);
2640   }
2641 /*  now using multiple sources, 
2642     this data set up for each object in update message
2643   else{
2644     if(tracing){
2645       printf("\nTRACING: The upd_source_hdl is: %s\n", upd_source_hdl->name);
2646     }
2647     sources[0] = strdup(upd_source_hdl->name);
2648     update_host = upd_source_hdl->whoisd_host;
2649     query_host = strdup(update_host);
2650     update_port = upd_source_hdl->updPort;
2651     query_port = upd_source_hdl->qryPort;
2652     DBhost = upd_source_hdl->updDb.host;
2653     DBport = upd_source_hdl->updDb.port;
2654     DBname = upd_source_hdl->updDb.dbName;
2655     DBuser = upd_source_hdl->updDb.user;
2656     DBpasswd = upd_source_hdl->updDb.password; 
2657   }
2658 */
2659 
2660   /* construct country array from country string variable */
2661   
2662   temp_vector = g_strsplit(country, "\n", 0);
2663   for (i=0, j=0; temp_vector[i] != NULL; i++)
2664   {
2665     temp_vector[i] == g_strstrip(temp_vector[i]);
2666     if (strlen(temp_vector[i]) > 0)
2667         {
2668       countries[j] = strdup(temp_vector[i]);
2669       g_strup(countries[j++]);
2670     }
2671   }
2672   countries[j] = NULL; /* mark the end of array */
2673   g_strfreev(temp_vector);
2674   if (tracing)
2675   {
2676     printf("TRACING: number of countries [%i]\n", j);
2677   }
2678 
2679   /* construct authmethods array from authmethod string variable */
2680   
2681   temp_vector = g_strsplit(authmethod, "\n", 0);
2682   for (i=0, j=0; temp_vector[i] != NULL; i++)
2683   {
2684     temp_vector[i] == g_strstrip(temp_vector[i]);
2685     if (strlen(temp_vector[i]) > 0)
2686         {
2687       authmethods[j] = strdup(temp_vector[i]);
2688       g_strup(authmethods[j++]);
2689     }
2690   }
2691   authmethods[j] = NULL; /* mark the end of array */
2692   g_strfreev(temp_vector);
2693 
2694   /* hard code the nicsuffixes for now, but should be a configurable variable */
2695 
2696   nicsuffixes[0] = strdup("RIPE");
2697   nicsuffixes[1] = strdup("ORG");
2698   nicsuffixes[2] = strdup("ARIN");
2699   nicsuffixes[3] = strdup("RADB");
2700   nicsuffixes[4] = strdup("APNIC");
2701   nicsuffixes[5] = strdup("RIPN");
2702   nicsuffixes[6] = NULL;
2703   
2704   if (tracing)
2705   {
2706     /* print out the config variables for debugging */
2707     printf("TMPDIR is: [%s]\n", tmpdir);
2708     printf("MAILCMD is: [%s]\n", mailcmd);
2709     printf("NOTITXT is: [%s]\n", notitxt);
2710     printf("NOTIHDR is: [%s]\n", notihdr);
2711     printf("CROSSLOG is: [%s]\n", crosslog);
2712     printf("FWTXT is: [%s]\n", fwtxt);
2713     printf("FWHDR is: [%s]\n", fwhdr);
2714     printf("HUMAILBOX is: [%s]\n", humailbox);
2715     printf("AUTOBOX is: [%s]\n", autobox);
2716     printf("OVERRIDECRYPTEDPW is: [%s]\n", overridecryptedpw);
2717     printf("ACKLOG is: [%s]\n", acklog);
2718     printf("NOTIFLOG is: [%s]\n", notiflog);
2719     printf("FORWLOG is: [%s]\n", forwlog);
2720     printf("NOTIMAILTXT is: [%s]\n", notimailtxt);
2721     printf("FWMAILTXT is: [%s]\n", fwmailtxt);
2722 /*   printf("COUNTRY is: [%s]\n", country); */
2723     printf("PGPPATH is: [%s]\n", pgppath);
2724     printf("LOCKDIR is: [%s]\n", lockdir); 
2725     printf("TESTMODE is: [%i]\n", test_mode);
2726     printf("CNO_SUBJECT_ADD is: [%s]\n", cno_subject_add);
2727     printf("CNO_SUBJECT_DEL is: [%s]\n", cno_subject_del);
2728   }
2729   /* end of config stuff */
2730 
2731 
2732   /* set hostname global variable */
2733   gethostname(hostname, MAXHOSTNAMELEN);
2734 
2735   /* set pid global variable */
2736   pid = getpid(); 
2737 
2738   /* create the lock file and lock it */
2739   /* lockfile = create_lock_file(); */
2740 
2741   /* Generate a name for temporary file for storing acks (AK_ack_file_name_generate
2742       also creates it) */
2743   ack_file_name = AK_ack_file_name_generate(tmpdir, ACK_FILE_PREFIX);
2744 
2745   /* initialize credentials.pgp_key_list */
2746   credentials.pgp_key_list = NULL;
2747 
2748 
2749  
2750   if (reading_from_mail || networkupdate || webupdate)
2751   {
2752     if (networkupdate)
2753     {
2754       set_default_source_data();
2755       process_networkupdate(credentials, AUTO_NIC_hdl_hash, ack_file_name, 
2756                             ntfy_hash, forw_hash, cross_hash); 
2757     }
2758     if (input_file_name != NULL)
2759     {
2760       temp_upd_file = generate_upd_file();
2761       if (tracing)
2762       {
2763         printf("TRACING: temp_upd_file is [%s]\n", temp_upd_file);
2764       }
2765 
2766       /* first log the input in the upd log file */
2767       UP_add_to_upd_log(input_file_name);
2768  
2769       
2770       MM_store(input_file_name, temp_upd_file, 0, networkupdate | webupdate);
2771       /*
2772       PA_SetGPGCmd(gpgcmd);
2773       PA_SetKeyRing(pgp_public_key_ring);
2774       */
2775       p = EP_ParseMail(temp_upd_file, tmpdir);
2776       
2777     }
2778     else
2779     { /* input_file_name == NULL */
2780       temp_upd_file = generate_upd_file();
2781       MM_store("-", temp_upd_file, 0, networkupdate | webupdate);
2782 
2783       /* first log the input in the upd log file */
2784       UP_add_to_upd_log(temp_upd_file);
2785       
2786       /*
2787       PA_SetGPGCmd(gpgcmd);
2788       PA_SetKeyRing(pgp_public_key_ring);
2789       */
2790       p = EP_ParseMail(temp_upd_file, tmpdir);
2791 
2792     }
2793 
2794     /* write off the checkpoint file */
2795     write_checkpoint(1);
2796 
2797     /* the new stuff using the EP module's interface */
2798 
2799     if(p->from != NULL && p->from->field != NULL)
2800     {
2801       credentials.from = (char *)malloc(strlen(p->from->field) + strlen("From:") + 1);
2802       sprintf(credentials.from, "From:%s", p->from->field);
2803       credentials.from_email = strdup(p->from->field); /* This doesn't contain "From:" */
2804       /* cut off the '\n's and '\r's at the end */
2805       UP_remove_EOLs(credentials.from);
2806       UP_remove_EOLs(credentials.from_email);
2807 
2808       /* now, there is a problem with EP module (or c-client): the p->from->field
2809          would contain only the first line if the "From" field has multiple lines.
2810          As a temp solution, we will add the second line (if it exists) explicitely */
2811       /* This is not a problem, it is the way the imap is written.
2812          It returns multiple lines as a linked list, so loop for all the lines */
2813       while ( (p->from = p->from->next) != NULL && p->from->field != NULL)
2814       { /* there is another line */
2815         credentials.from = (char *)realloc(credentials.from, strlen(credentials.from) + strlen(p->from->field) + 1);
2816         strcat(credentials.from, p->from->field);
2817         credentials.from_email = (char *)realloc(credentials.from_email, strlen(credentials.from_email) + strlen(p->from->field) + 1);
2818         strcat(credentials.from_email, p->from->field);
2819         UP_remove_EOLs(credentials.from);
2820         UP_remove_EOLs(credentials.from_email);
2821       }
2822     }
2823     else
2824     {
2825       credentials.from = strdup("");
2826       credentials.from_email = strdup("");
2827     }
2828     
2829     update_mail_sender = strdup(credentials.from_email); 
2830     
2831     if (tracing)
2832     {
2833       printf("TRACING: From field is: [%s]\n", credentials.from);
2834       printf("TRACING: update_mail_sender is: [%s]\n", update_mail_sender);
2835     }
2836     
2837 
2838     if(p->cc != NULL && p->cc->field != NULL)
2839     {
2840       update_mail_cc = strdup(p->cc->field);
2841       /* cut off the '\n's and '\r's at the end */
2842       UP_remove_EOLs(update_mail_cc);
2843 
2844       /* loop for all multiple lines */
2845       while ( (p->cc = p->cc->next) != NULL && p->cc->field != NULL)
2846       { /* there is another line */
2847         update_mail_cc = (char *)realloc(update_mail_cc, strlen(update_mail_cc) + strlen(p->cc->field) + 1);
2848         strcat(update_mail_cc, p->cc->field);
2849         UP_remove_EOLs(update_mail_cc);
2850       }
2851     }
2852     else
2853       update_mail_cc = strdup("");
2854     
2855     if (tracing)
2856     {
2857       printf("TRACING: Cc field is: [%s]\n", update_mail_cc);
2858     }
2859     
2860                
2861     if(p->subject != NULL && p->subject->field != NULL)
2862     {
2863       subject = strdup(p->subject->field);
2864       /* cut off the '\n' and '\r' from the end */
2865       UP_remove_EOLs(subject);
2866 
2867       /* loop for all multiple lines */
2868       while ( (p->subject = p->subject->next) != NULL && p->subject->field != NULL)
2869       { /* there is another line */
2870         subject = (char *)realloc(subject, strlen(subject) + strlen(p->subject->field) + 1);
2871         strcat(subject, p->subject->field);
2872         UP_remove_EOLs(subject);
2873       }
2874     }
2875     else
2876       subject = strdup("");
2877     
2878     update_mail_subject = strdup(subject);
2879 
2880     if (reading_from_mail)
2881     {
2882       /* parse the subject line */ 
2883       subject_result = UP_subject_process(update_mail_subject); 
2884       if (tracing)
2885         printf("TRACING: subject processing result [%d]\n", subject_result.result);
2886     }
2887     else
2888     {
2889       /* web update (or networkupdate) */
2890       /* process the flags */
2891       subject_result = UP_subject_flags();
2892       if (tracing)
2893         printf("TRACING: subject flags result [%d]\n", subject_result.result);
2894     }
2895 
2896     if(p->reply_to != NULL && p->reply_to->field != NULL)
2897     {
2898       reply_to = strdup(p->reply_to->field);
2899       /* cut off the '\n' and '\r' from the end */                    
2900       UP_remove_EOLs(reply_to);
2901 
2902       /* loop for all multiple lines */
2903       while ( (p->reply_to = p->reply_to->next) != NULL && p->reply_to->field != NULL)
2904       { /* there is another line */
2905         reply_to = (char *)realloc(reply_to, strlen(reply_to) + strlen(p->reply_to->field) + 1);
2906         strcat(reply_to, p->reply_to->field);
2907         UP_remove_EOLs(reply_to);
2908       }
2909     }
2910     else
2911       reply_to = strdup("");
2912 
2913     
2914     to_address = find_email_address(credentials.from);
2915 
2916     /* if Reply_To was available in the incoming header, then use it */
2917     if (strlen(reply_to) > 0)
2918     {
2919       to_address = (char *)realloc(to_address, strlen(reply_to) + 1);
2920       to_address = strcpy(to_address, reply_to);
2921       to_address = find_email_address(to_address); /* so that we take only the email address */
2922     }
2923 
2924     if (p->message_id != NULL && p->message_id->field != NULL)
2925     {
2926       update_mail_ID = strdup(p->message_id->field);
2927       /* cut off the '\n' and '\r' from the end */
2928       UP_remove_EOLs(update_mail_ID);
2929 
2930       /* loop for all multiple lines */
2931       while ( (p->message_id = p->message_id->next) != NULL && p->message_id->field != NULL)
2932       { /* there is another line */
2933         update_mail_ID = (char *)realloc(update_mail_ID, strlen(update_mail_ID) + strlen(p->message_id->field) + 1);
2934         strcat(update_mail_ID, p->message_id->field);
2935         UP_remove_EOLs(update_mail_ID);
2936       }
2937     }
2938     else
2939       update_mail_ID = strdup("");
2940     
2941 
2942     if(p->date != NULL && p->date->field != NULL)
2943     {
2944       update_mail_date = strdup(p->date->field);
2945       /* cut off the '\n' and '\r' from the end  */
2946       UP_remove_EOLs(update_mail_date);
2947 
2948       /* loop for all multiple lines */
2949       while ( (p->date = p->date->next) != NULL && p->date->field != NULL)
2950       { /* there is another line */
2951         update_mail_date = (char *)realloc(update_mail_date, strlen(update_mail_date) + strlen(p->date->field) + 1);
2952         strcat(update_mail_date, p->date->field);
2953         UP_remove_EOLs(update_mail_date);
2954       }
2955     }
2956     else
2957       update_mail_date = strdup("");
2958     
2959     if (tracing)
2960     {
2961       printf("\nEP_ShowTree outputs:\n");
2962       EP_ShowTree(p->tree);
2963     }
2964     
2965     pt = EP_GetTokens(p->tree, NULL, NULL, NULL);
2966 
2967     if(tracing)
2968     {
2969      /* Print the list out (debugging) */
2970       printf("\nEP_PrintTokens outputs:\n");
2971       EP_PrintTokens(pt);
2972     }
2973 
2974     /* replace the global variables in mheader */
2975     mheader_replaced = UP_replace_globals(mheader);
2976     /* replace the global variables in mailtxt */
2977     mailtxt_replaced = UP_replace_globals(mailtxt);
2978 
2979     /* If this wasn't only a help request, then we need to process the input */
2980     if(subject_result.result != UP_SUBJ_HELP_REQ)
2981     {
2982       /* ... and now process the items in the list */
2983       list_item = pt;
2984       while (list_item != NULL) 
2985       {
2986         if(tracing)
2987         {
2988           printf("\n\nWill process: %s, MIMEtype: %d\n", list_item->file, list_item->MIMEContentType);
2989         }
2990 
2991             /* Start with passwords from pieces of mail up in the structure*/
2992             credentials.password_list = list_item->passwords;
2993         /* initialize pgp_key_list (XXX This should be a proper freeing of the list) */
2994         credentials.pgp_key_list = NULL;
2995         ptk = list_item->keys;
2996         if(ptk != NULL)
2997         {
2998           AK_add_to_ack(ack_file_name, "==== BEGIN PGP SIGNED PART (keyID(s):");
2999           pgp_signed = 1; 
3000           while (ptk != NULL) 
3001           {
3002             if(tracing)
3003             {
3004               printf("TRACING:     key: %.8X, isValid: %i\n", 
3005                    ptk->keyID, ptk->isValidPGPSignature);
3006             }
3007             temp_keyid = (char *)malloc(10);
3008             sprintf(temp_keyid, "%.8X", ptk->keyID);
3009             dummy_keyid = strdup("00000000");
3010             if(tracing)
3011             {
3012               printf("TRACING: This key will be added to the list: [%s]\n", temp_keyid);
3013             }
3014 
3015             if((ptk->isValidPGPSignature) == vS_IS_VALID)
3016             {
3017 
3018               AK_add_to_ack(ack_file_name, " %s", temp_keyid);
3019               credentials.pgp_key_list = g_slist_append (credentials.pgp_key_list, temp_keyid);
3020             }
3021             else
3022             {
3023               /* if the signature was bad, just add a dummy key ID, '00000000' */
3024               if(tracing)
3025               {
3026                 printf("TRACING: bad signature, adding a dummy key ID\n");
3027               }
3028 
3029               AK_add_to_ack(ack_file_name, " %s", dummy_keyid);
3030               credentials.pgp_key_list = g_slist_append (credentials.pgp_key_list, dummy_keyid);
3031             }
3032 
3033             free(dummy_keyid);
3034             ptk = ptk->next;
3035             if(ptk != NULL)
3036             {
3037               AK_add_to_ack(ack_file_name, ",");
3038             }
3039             else
3040             {
3041               AK_add_to_ack(ack_file_name, ") ====\n");
3042             }
3043           }
3044         }
3045         process_file(list_item->file, credentials, 
3046                      AUTO_NIC_hdl_hash, ack_file_name, 
3047                      ntfy_hash, forw_hash, cross_hash);
3048         if(pgp_signed)
3049         {
3050           AK_add_to_ack(ack_file_name, "==== END PGP SIGNED PART ====\n\n");
3051           pgp_signed = 0;
3052         }
3053         list_item = list_item->next;
3054       }
3055 
3056     }
3057     else
3058     {
3059       /* this was only a help request (inferred from the "Subject" line of the upd message) */
3060 
3061       /* Print out the header of the acknowledgement */
3062 /*      AK_add_to_ack(ack_file_name, "To: %s\n%s\n\nHelp file requested so body of message ignored.\n\n\n"
3063           "============================================================\n\n", 
3064           to_address, mheader_replaced);  */
3065       AK_add_to_ack(ack_file_name, "\n============================================================\n\n");
3066 
3067       AK_add_file_to_ack(ack_file_name, autodbmhelp);
3068       AK_add_to_ack(ack_file_name, "\n============================================================\n\n");
3069     }
3070     
3071     EP_CleanTokens(pt);
3072 
3073     EP_MailDescrCleanUp(p);
3074 
3075     /* if we have created a temporary file for update, delete it */
3076     if (temp_upd_file != NULL)
3077     {
3078       unlink(temp_upd_file);
3079     }
3080 
3081   }
3082   else
3083   { /* not reading from the mail message or from network */
3084     if (input_file_name != NULL)
3085     {
3086       /* first log the input in the upd log file */
3087       UP_add_to_upd_log(input_file_name);
3088       
3089       write_checkpoint(1);
3090       process_file(input_file_name, credentials, 
3091                   AUTO_NIC_hdl_hash, ack_file_name, 
3092                   ntfy_hash, forw_hash, cross_hash);
3093     }
3094     else
3095     { /* the filename is not given, so we have to write 
3096              stdin to a temp file, and give it to process_file */
3097       temp_upd_file = generate_upd_file();
3098       if (tracing)
3099       {
3100         printf("TRACING: main: temp_upd_file=%s\n", temp_upd_file);
3101       }
3102       if (( upd_file = fopen(temp_upd_file, "a")) == NULL)
3103       {
3104         ER_perror(FAC_UP, UP_CANTOPENW, "Can't open ack file, %s", temp_upd_file);
3105       }
3106 
3107       while ((c = getchar()) != EOF)
3108       {
3109         fprintf(upd_file, "%c",c);
3110       }
3111       fclose(upd_file);
3112 
3113       /* now log the input in the upd log file */
3114       UP_add_to_upd_log(temp_upd_file);
3115 
3116       write_checkpoint(1);
3117       process_file(temp_upd_file, credentials, 
3118                  AUTO_NIC_hdl_hash, ack_file_name, 
3119                  ntfy_hash, forw_hash, cross_hash);
3120       unlink(temp_upd_file);
3121     }
3122   }  
3123 
3124 
3125   /* post-process and send the ack */
3126   if(reading_from_mail && to_address != NULL){
3127     AK_send_ack(ack_file_name, to_address, mailcmd);
3128   }
3129 
3130   /* if our update wasn't a mail update OR we have been asked explicitely
3131      to print out the ack to the stdout, print it */
3132   if((!reading_from_mail && !networkupdate)|| print_out_ack){
3133     AK_print_ack(ack_file_name);
3134   }
3135   
3136   AK_log_ack(ack_file_name, acklog);
3137   AK_delete_ack(ack_file_name);
3138 
3139   NT_send_ntfy_list(ntfy_hash, mailcmd);
3140   NT_log_ntfy_list(ntfy_hash, notiflog); 
3141   NT_delete_ntfy_list(ntfy_hash);
3142 
3143   NT_send_ntfy_list(forw_hash, mailcmd);
3144   NT_log_ntfy_list(forw_hash, forwlog); 
3145   NT_delete_ntfy_list(forw_hash);
3146 
3147 
3148   NT_send_ntfy_list(cross_hash, mailcmd);
3149   NT_log_ntfy_list(cross_hash, crosslog); 
3150   NT_delete_ntfy_list(cross_hash);
3151       
3152   /* remove the lock file */
3153   /* remove_lock_file(lockfile); */
3154   
3155  
3156   /* remove checkpoint file */
3157   remove_checkpoint();
3158 
3159   free(ack_file_name);
3160 
3161   if (tracing)
3162   {
3163     printf("TRACING: END\n");
3164   }
3165   
3166   return 0 ;
3167 }

/* [<][>][^][v][top][bottom][index][help] */