bin/dbupdate/dbupdate.cc

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

FUNCTIONS

This source file includes following functions.
  1. error_init
  2. delete_key
  3. import_key
  4. get_keyowner_fingerpr
  5. process_object
  6. process_file
  7. generate_upd_file
  8. create_lock_file
  9. remove_lock_file
  10. write_checkpoint
  11. remove_checkpoint
  12. main

   1 /***************************************
   2   $Revision: 1.89 $
   3 
   4   DBupdate 
   5 
   6   Status: NOT REVIEWED, TESTED
   7 
   8   Author(s):       Engin Gunduz
   9 
  10   ******************/ /******************
  11   Modification History:
  12         engin (01/03/2000) Created.
  13   ******************/ /******************
  14   Copyright (c) 2001                              RIPE NCC
  15 
  16   All Rights Reserved
  17 
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25 
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32  ***************************************/
  33 
  34 
  35 
  36 
  37 #include <config.h>
  38 #include "dbupdate.h"
  39 #include "UP_extrnl_syntax.h"
  40 #include "UP_subject.h"
  41 #include "er_yacc_helper.h"
  42 #include "erroutines.h"
  43 #include "ca_configFns.h"
  44 #include "ca_dictionary.h"
  45 #include "ca_macros.h"
  46 #include "ca_srcAttribs.h"
  47 #include "notification.h"
  48 #include "gpg.h"
  49 #include "mail_parser.h"
  50 #include "process.h"
  51 
  52 #ifdef HAVE_SYS_PARAM_H
  53 #include <sys/param.h>
  54 #endif
  55 
  56 
  57 int tracing = 0;
  58 int test_mode = 0;
  59 int supress_ack_notif = 0;
  60 int print_out_ack = 0;
  61 
  62 /* do we process a mail */
  63 int reading_from_mail = 0;
  64 
  65 /* are we processing networkupdate? */
  66 int networkupdate = 0;
  67 
  68 /* IP of the networkupdate client */
  69 char * netupdclientIP = NULL;
  70 
  71 /* two global variables to tally the processed objects */
  72 int count_successful = 0;
  73 int count_unsuccessful = 0;
  74 
  75 
  76 /* sender of the mail, in case of a mail update */
  77 char *update_mail_sender = NULL;
  78 char *update_mail_subject = NULL;
  79 char *update_mail_date = NULL;
  80 char *update_mail_ID = NULL;
  81 char *update_mail_cc = NULL;
  82 
  83 /* required configuration variables */
  84 char *tmpdir = NULL;
  85 char *lockdir = NULL;
  86 char *mailcmd = NULL;
  87 char *notitxt = NULL;
  88 char *successtxt = NULL;
  89 char *failuretxt = NULL;
  90 char *notimailtxt = NULL;
  91 char *notinetworktxt = NULL;
  92 char *fwtxt   = NULL;
  93 char *fwmailtxt = NULL;
  94 char *mtfwheader = NULL; 
  95 char *mtfwtxt = NULL;
  96 char *mailtxt = NULL;
  97 char *acksig = NULL;
  98 char *defmail = NULL;
  99 char *updlog = NULL;
 100 char *notiflog = NULL;
 101 char *crosslog = NULL;
 102 char *acklog = NULL;
 103 char *forwlog = NULL;
 104 char *humailbox = NULL;
 105 char *autobox = NULL;
 106 char *copyright_notice = NULL;
 107 char *overridecryptedpw = NULL;
 108 char *country = NULL;
 109 char *countries[400];
 110 char *sources[100];
 111 char *pgppath = NULL;
 112 char *gpgcmd = NULL;
 113 char *pgp_public_key_ring = NULL;
 114 char *autodbmhelp = NULL; 
 115 char *update_host = NULL;
 116 int  update_port;
 117 char *query_host = NULL;
 118 int  query_port;
 119 char *cn_subject_add = NULL;
 120 char *cn_subject_del = NULL;
 121 char *cn_explain_add = NULL;
 122 char *cn_explain_del = NULL;
 123 char *cn_overlap_add = NULL;
 124 char *cn_overlap_del = NULL;
 125 char *cno_subject_add = NULL;
 126 char *cno_subject_del = NULL;
 127 char *cno_explain_add = NULL;
 128 char *cno_explain_del = NULL;
 129 char *cno_overlap_add = NULL;
 130 char *cno_overlap_del = NULL;
 131 char *allocmnt = NULL;
 132 char *mheader = NULL;
 133 char *DBhost = NULL;
 134 int  DBport;
 135 char *DBuser = NULL;
 136 char *DBname = NULL;
 137 char *DBpasswd = NULL;
 138 /* end of config variables */
 139 
 140 char * fingerprint = NULL;
 141 char * keyowner = NULL;
 142 
 143 /* result of subject line processing is kept in the following struct. */
 144 up_subject_struct subject_result;
 145 
 146 
 147 /* hostname and pid are used all over the program, so we save them into these variables */
 148 char hostname[MAXHOSTNAMELEN];
 149 //char * hostname;
 150 int pid;
 151 
 152 /* name of the lock file, which is used for the crash recovery mechanism */
 153 char * lock_file_name;
 154 
 155 void error_init(int argc, char ** argv) {
     /* [<][>][^][v][top][bottom][index][help] */
 156 
 157   ER_init("dbupdate", 1);
 158   
 159 
 160 } /* error_init() */
 161 
 162 
 163 
 164 
 165 
 166 
 167 /* 'lockfile' struct is for keeping both the name of the lock file and the file descriptor
 168     of it, which is open during the execution of dbupdate. We need the filedes to close it,
 169     when dbupdate finishes, and the name to delete the file. */
 170 typedef struct {
 171    char * lockname;
 172    int filedes;
 173 } lockfilestruct;
 174 
 175 
 176 lockfilestruct lockfile;
 177 
 178 
 179 
 180 /* Deletes the key defined in the incoming object (a key-cert object)
 181    from the public keyring. Returns NULL if there was no error,
 182    returns an error message if there is an error */
 183 char * delete_key(char * obj){
     /* [<][>][^][v][top][bottom][index][help] */
 184 
 185   struct ImportKeyObject iKO;
 186   char * obj_keyID;
 187   char * key_cert_attr;
 188   GSList * templist, * certiflist, * next;
 189   u32 keyID;
 190   char * tempfile;
 191   char ** lines;
 192   int i;
 193   FILE * key_file;
 194   char * temp, * temp2;
 195   char * error_string;
 196 
 197   templist = get_attr_list(obj, "key-cert");
 198   key_cert_attr = strdup((char *)templist->data);
 199   g_slist_free(templist);
 200 
 201   tempfile = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
 202   sprintf(tempfile, "%s/tmp-key.%i", tmpdir, pid /*getpid()*/);
 203 
 204   /* now we must write certif attribute(s) of this key-certif into the tempfile */
 205   /* get the certif first */
 206   certiflist = get_attr_list(obj, "certif");
 207   if(( key_file = fopen(tempfile, "w")) == NULL){
 208      ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temporary file, %s", tempfile);
 209      exit(1);
 210   }
 211   for( next = certiflist; next != NULL ; next = g_slist_next(next) ){
 212     lines = g_strsplit((char *)next->data, "\n", 0);
 213     if(lines[0] == NULL){/* if this was an empty attribute, just print an empty line */
 214       fprintf(key_file, "\n"); 
 215     }
 216     for(i = 0; lines[i] != NULL; i++){
 217       temp = strdup(lines[i]);
 218       if(i != 0 && temp[0] == '+'){/* if it begins with a plus */
 219         temp2 = strdup(temp + 1);
 220         g_strstrip(temp2);
 221         fprintf(key_file, "%s\n", temp2);
 222         free(temp);free(temp2);
 223       }else{
 224         g_strstrip(temp);
 225         fprintf(key_file, "%s\n", temp);
 226         free(temp); 
 227       }
 228     }
 229     g_strfreev(lines);
 230   }
 231   fclose(key_file);
 232   g_slist_free(certiflist);
 233 
 234   strcpy(iKO.iFilename, tempfile);
 235 
 236   if(tracing){
 237     printf("TRACING: delete_key: key_cert_attr: [%s]\n", key_cert_attr);
 238   }
 239   
 240   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 241 
 242   if(tracing){
 243     printf("TRACING: delete_key: obj_keyID: [%s]\n", obj_keyID);
 244   }
 245   
 246   keyID = strtoul(obj_keyID, NULL, 16);
 247 
 248   if(tracing){
 249     printf("TRACING: delete_key: keyID is: %u, %X\n", keyID, keyID);
 250   }
 251   
 252   
 253   
 254   strcpy(iKO.keyRing, pgp_public_key_ring);
 255   PA_RemoveKey(&iKO);
 256 
 257   if(tracing){
 258     printf("TRACING: importKeyObj status:\n");
 259     printf("TRACING: isValid: %d\n", iKO.rc);
 260   }
 261   
 262 
 263 
 264   unlink(tempfile);
 265   if(iKO.rc == iKO_OK){/* if PA_RemoveKey returned OK */
 266     return NULL;
 267   }else{/* if PA_RemoveKey returned not OK */
 268       switch(iKO.rc){
 269         case iKO_UNCHANGED:      error_string = strdup("the key is already in the keyring");break; 
 270         case iKO_NOUSERID:       error_string = strdup("no user ID could be extracted");break;
 271         case iKO_GENERAL:        error_string = strdup("general PGP error");break;
 272         case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
 273         case iKO_NOPUBLICKEY:    error_string = strdup("no public key in the object");break;
 274         case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
 275         case iKO_CRC_ERROR:      error_string = strdup("CRC error in the certificate");break;
 276         case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
 277         case iKO_NO_IN_FILES:    error_string = strdup("general PGP error");break;
 278         case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
 279         default:            error_string = strdup("general PGP error");
 280       }
 281       return error_string; 
 282   }
 283 
 284   return NULL;
 285 }
 286 
 287 
 288 /* Takes a key-certif object, extracts its 'certif' attribute and adds
 289    the key into public keyring
 290    If there is no problem, it returns NULL
 291    If there is a problem, then it returns a string which contains an error
 292    message */
 293 char * import_key(char *obj){
     /* [<][>][^][v][top][bottom][index][help] */
 294 
 295   char * tempfile;
 296   struct ImportKeyObject iKO;
 297   GSList * certiflist, * next, * templist;
 298   FILE * key_file;
 299   char keyID[9];
 300   char * obj_keyID, * key_cert_attr;
 301   char * error_string = NULL;
 302   char ** lines;
 303   int i;
 304   char * temp, * temp2;
 305    
 306   tempfile = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
 307   sprintf(tempfile, "%s/tmp-key.%i", tmpdir, pid );
 308 
 309   /* now we must write certif attribute(s) of this key-certif into the tempfile */
 310   /* get the certif first */
 311   certiflist = get_attr_list(obj, "certif");
 312   if(( key_file = fopen(tempfile, "w")) == NULL){
 313      ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temporary file, %s", tempfile);
 314      exit(1);
 315   }
 316   for( next = certiflist; next != NULL ; next = g_slist_next(next) ){
 317     lines = g_strsplit((char *)next->data, "\n", 0);
 318     if(lines[0] == NULL){/* if this was an empty attribute, just print an empty line */
 319       fprintf(key_file, "\n"); 
 320     }
 321     for(i = 0; lines[i] != NULL; i++){
 322       temp = strdup(lines[i]);
 323       if(i != 0 && temp[0] == '+'){/* if it begins with a plus */
 324         temp2 = strdup(temp + 1);
 325         g_strstrip(temp2);
 326         fprintf(key_file, "%s\n", temp2);
 327         free(temp);free(temp2);
 328       }else{
 329         g_strstrip(temp);
 330         fprintf(key_file, "%s\n", temp);
 331         free(temp); 
 332       }
 333     }
 334     g_strfreev(lines);
 335   }
 336   fclose(key_file);
 337   g_slist_free(certiflist);
 338 
 339   strcpy(iKO.iFilename, tempfile);
 340   strcpy(iKO.keyRing, pgp_public_key_ring);
 341   PA_ImportKey(&iKO);
 342 
 343   if(tracing){
 344     printf("importKeyObj status:\n");
 345     
 346     printf("isValid: %d\n", iKO.rc);
 347     printf("keyID: %08lX\n", iKO.keyID);
 348   }
 349   snprintf(keyID, 9, "%08lX", iKO.keyID);
 350   
 351   if(tracing){
 352     printf("keyID: [%s]\n", keyID);
 353   }
 354   
 355   unlink(tempfile);
 356   free(tempfile);
 357 
 358   
 359   templist = get_attr_list(obj, "key-cert");
 360   key_cert_attr = strdup((char *)templist->data);
 361   g_slist_free(templist);
 362 
 363   if(tracing){
 364     printf("key_cert_attr: [%s]\n", key_cert_attr);
 365   }
 366   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 367   if(tracing){
 368     printf("obj_keyID: [%s]\n", obj_keyID);
 369   }
 370   if(iKO.rc == iKO_OK && (strcasecmp(obj_keyID, keyID) == 0)){/* if PA_ImportKey returned OK 
 371                                                             and the real keyID is equal to the
 372                                                             keyID in the 'key-cert' attribute */
 373     fingerprint = strdup(iKO.fingerPrint); 
 374     keyowner    = strdup(iKO.keyOwner);                                                           
 375     return NULL;
 376   }else{/* if PA_ImportKey returned not OK or obj_keyID, keyID didn't match */
 377     if(iKO.rc != iKO_OK){
 378       switch(iKO.rc){
 379         case iKO_UNCHANGED:      error_string = strdup("the key is already in the keyring");break; 
 380         case iKO_NOUSERID:       error_string = strdup("no user ID could be extracted");break;
 381         case iKO_GENERAL:        error_string = strdup("general PGP error");break;
 382         case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
 383         case iKO_NOPUBLICKEY:    error_string = strdup("no public key in the object");break;
 384         case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
 385         case iKO_CRC_ERROR:      error_string = strdup("CRC error in the certificate");break;
 386         case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
 387         case iKO_NO_IN_FILES:    error_string = strdup("general PGP error");break;
 388         case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
 389         default:            error_string = strdup("general PGP error");
 390       }
 391       return error_string; 
 392     }else{
 393       error_string = (char *)malloc(1024);/* this should be enough */
 394       sprintf(error_string, "Keyid for this certificate (%s) is not the same as the PGPKEY field (%s)", 
 395                  keyID, obj_keyID);
 396       return error_string;
 397     }
 398   }
 399       
 400 }
 401 
 402 
 403 
 404 
 405 
 406 /* Gets the keyowner and fingerprint of a PGP key 
 407    from the keycert object. The keycert object must already
 408    be in the database (thus, in the keyring) 
 409    The fingerprint and keyowner will be saved in global variables */
 410    
 411 void get_keyowner_fingerpr(char *obj){
     /* [<][>][^][v][top][bottom][index][help] */
 412 
 413   GSList * templist = NULL;
 414   char * obj_keyID = NULL;
 415   struct ImportKeyObject iKO;
 416   u32 keyID;
 417   char * key_cert_attr;
 418    
 419   
 420   templist = get_attr_list(obj, "key-cert");
 421   key_cert_attr = strdup((char *)templist->data);
 422   g_slist_free(templist);
 423 
 424   if(tracing){
 425     printf("get_keyowner_fingerpr: key_cert_attr is [%s]\n", key_cert_attr);
 426   } 
 427   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 428   if(tracing){
 429     printf("get_keyowner_fingerpr: obj_keyID is [%s]\n", obj_keyID);
 430   }
 431  
 432   sscanf(obj_keyID, "%8X", &keyID); 
 433   if(tracing){
 434     printf("get_keyowner_fingerpr: keyID is [%s]\n", keyID);
 435   }
 436   
 437   /* set appropriate fields of iKO */ 
 438   iKO.keyID = keyID;
 439   strcpy(iKO.keyRing, pgp_public_key_ring);
 440 
 441   GetFingerPrint(&iKO);
 442   fingerprint = strdup(iKO.fingerPrint);
 443   
 444   GetKeyOwner(&iKO);
 445   keyowner = strdup(iKO.keyOwner); 
 446 
 447 
 448   if(tracing){
 449     if(fingerprint != NULL){
 450       printf("get_keyowner_fingerpr: fingerprint is [%s]\n", fingerprint);
 451     }
 452     if(keyowner){
 453       printf("get_keyowner_fingerpr: keyowner is [%s]\n", keyowner);
 454     }
 455   }
 456 }
 457 
 458 
 459 
 460 
 461 
 462 
 463 /* Checks the object's syntax, retrives the old version of it from the db, 
 464    and checks auth2. If everything is OK, then sends it to RIPdb, where referential
 465    integrity is checked, and the object is really committed to the db.
 466   
 467      Arguments:
 468         char * arg: The object,
 469         credentials_struct credentials: The struct containing the credentials, such as 
 470           'From:' field of the e-mail update,
 471         GHashTable * NIC_hdl_hash: A hash containing 
 472         char * ack_file_name:  The file name, to be used to store ACK message 
 473 */
 474 
 475 
 476 
 477 int process_object(char * incoming, credentials_struct credentials, 
     /* [<][>][^][v][top][bottom][index][help] */
 478                    GHashTable * NIC_hdl_hash, char * ack_file_name,
 479                    GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
 480   
 481     bool code = true;
 482     Object *o;
 483     char * old_version = NULL;
 484     o = new Object;
 485     int result = 0;
 486     up_ripupd_result_struct * result_from_RIPupd;
 487     char * result_from_import_key = NULL;
 488     char * result_from_delete_key = NULL;
 489     char * auto_nic = NULL;
 490     char * changed_obj = NULL;
 491     char * obj_with_AUTO_NIC_hdl;
 492     char * assigned_NIC;
 493     char * formatted_object;
 494     char * type;
 495     char * arg;
 496     char * arg2;
 497     char * generated_object;
 498         char *search_key = NULL;
 499     external_syntax_struct * external_syntax_results;
 500 
 501 
 502     char * value = NULL;/* these two are for */
 503     Attr * attr;        /* ack messages only */ 
 504 
 505     arg = strdup(incoming);
 506     
 507     if(has_ref_to_AUTO_nic_hdl(arg)){/* if this object has refs to AUTO NIC hdls*/
 508        /* then first replace AUTO NIC hdls with assigned NIC hdls (in NIC_hdl_hash) */
 509        if((changed_obj = replace_refs_to_AUTO_NIC_hdl(changed_obj, arg, NIC_hdl_hash)) == NULL){
 510          /* try to parse the object only for reporting purposes */
 511          o->scan_silent(arg,strlen(arg));
 512          AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] Unknown AUTO NIC handle referenced\n%s\n", 
 513                  (o && o->type) ? o->type->getName() : "unknown-type", delete_override(arg));
 514          delete(o);
 515          return UP_ANE; /* AUTO NIC hdl error */
 516          
 517        }else{ /* in this case, we must use changed_obj instead of arg */
 518 
 519          free(arg); 
 520          arg = changed_obj; 
 521 
 522        };
 523     }
 524   
 525     
 526     code = o->scan_silent(arg,strlen(arg));
 527     if(code){
 528       type = get_class_type(o);
 529       /* is the object to be deleted? */
 530       if(o->isDeleted){
 531         old_version = get_old_version(arg);
 532         if(old_version == NULL){ /* the object doesn't exist in the db! */
 533                     search_key = get_search_key(o, o->type->getName(), arg);
 534                         if ( search_key == NULL )
 535                           search_key = "";
 536           AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n***Error: Entry not found\n\n",
 537                         o->type->getName(), search_key, delete_override(arg));
 538           return UP_NSO; /* no such object */
 539         }else {/* the object is in the db */
 540           if(identical(old_version, arg) /* if the old & new versions are identical */
 541              || (strcmp(o->type->getName(), "key-cert") == 0)  /* or it is a key-cert object  */
 542              || (strcmp(o->type->getName(), "inet6num") == 0)){/* or it is an inet6num object */
 543             result = check_auth(NULL, arg, o->type->getName(), credentials);
 544             if(result == UP_AUTH_OK){ 
 545               if(tracing) {
 546                 printf("TRACING: Will send the obj to be deleted\n");
 547               }
 548               if(strcmp(type, "key-cert") == 0){
 549                 result_from_delete_key = delete_key(arg);
 550               }else{
 551                 result_from_delete_key = NULL;
 552               }
 553               /* if there was no problem with key deletion from the key-ring */
 554               if(result_from_delete_key == NULL){
 555                 result_from_RIPupd = send_object_db(arg, NULL, "DEL");
 556                 if(result_from_RIPupd->result == 0){
 557                   AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n", 
 558                                 o->type->getName(), get_search_key(o, o->type->getName(), arg));
 559                   NT_write_all_ntfs(old_version, NULL, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 560                                     credentials.from);
 561                   return UP_OK;
 562                 }else{
 563                   AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 564                                 o->type->getName(), get_search_key(o, o->type->getName(), arg),
 565                                 result_from_RIPupd->error_str);
 566                   return UP_INT;
 567                 }
 568                 result_from_RIPupd->result = 0;
 569               }else{
 570                  AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 571                                 o->type->getName(), get_search_key(o, o->type->getName(), delete_override(arg)),
 572                                 result_from_delete_key);
 573                  return UP_INT;
 574               }
 575             }else{ /* auth failed */
 576               if(tracing) {
 577                 printf("TRACING: Auth failed\n");
 578               }
 579 
 580               AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 581                             o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 582               NT_write_all_frwds(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 583               return UP_AUF; /* Auth failed */
 584             } 
 585           }else{/* the new & old versions do not match */
 586             AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n***Error: new & old versions do not match\n",
 587                  o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 588             return UP_NOM; /* new & old versions do not match */
 589           }
 590         }
 591       }else {/* the object is _not_ to be deleted */
 592         
 593         if(has_AUTO_NIC_hdl(arg)){/* if the object has an AUTO NIC hdl */
 594           external_syntax_results = UP_check_external_syntax(o, arg);
 595           if(     external_syntax_results->result != UP_EXTSYN_ERR 
 596                && external_syntax_results->result != UP_EXTSYN_ERR_WARN){/* if there is no error */
 597             /* then its nic-hdl attribute must be modified so that RIPupdate
 598                would understand that it must assign a NIC handle to it */
 599             /* but first check the auth */
 600             result = check_auth(arg, NULL, o->type->getName(), credentials);
 601             if(result == UP_AUTH_OK){
 602               if(tracing) {                                
 603                   printf("TRACING: Will send the obj to be created with AUTO NIC hdl\n");
 604               }
 605               auto_nic = (char *)malloc(1024); /* should be enough for a NIC hdl */
 606               obj_with_AUTO_NIC_hdl = replace_AUTO_NIC_hdl(external_syntax_results->new_obj, auto_nic);
 607               if(tracing) {  
 608                 printf("TRACING:  Called replace_AUTO_NIC_hdl, get [%s]\n", obj_with_AUTO_NIC_hdl);
 609                 printf("TRACING: Will send the obj to be added\n");
 610               }
 611               assigned_NIC = (char *)malloc(128); /* this should be enough for a NIC hdl */
 612               result_from_RIPupd = send_object_db(obj_with_AUTO_NIC_hdl, assigned_NIC, "ADD");
 613               if(result_from_RIPupd->result == 0){
 614                 AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n", 
 615                               o->type->getName(), assigned_NIC);
 616                 /* replace the AUTO nic hdl with the assigned one (for reporting purposes, in the notif mesg) */
 617                 formatted_object = UP_put_assigned_NIC(external_syntax_results->new_obj, assigned_NIC);
 618                 formatted_object = delete_override(formatted_object);
 619                 arg2 = delete_override(arg);
 620                 NT_write_all_ntfs(NULL, arg2, formatted_object, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 621                                   credentials.from);
 622                 
 623                 result_from_RIPupd->result = 0;
 624                 if(tracing && assigned_NIC != NULL) {  
 625                   printf("TRACING: send_object_db returned [%s] as assigned NIC hdl\n", assigned_NIC);
 626                 }
 627                 if(assigned_NIC != NULL){
 628                   if(tracing){
 629                     printf("TRACING: auto_nic=[%s], assigned_NIC=[%s]\n", auto_nic, assigned_NIC);
 630                   }
 631                   g_hash_table_insert(NIC_hdl_hash, auto_nic, assigned_NIC);
 632                   if(tracing){
 633                     printf("TRACING: NIC_hdl_hash has %i pairs\n",g_hash_table_size(NIC_hdl_hash));
 634                   }
 635                 }
 636                 
 637                 return UP_OK;
 638               }else{
 639                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s]\n%s\n%s\n",
 640                               o->type->getName(), delete_override(arg),
 641                               result_from_RIPupd->error_str);
 642                 return UP_INT;
 643               }
 644               
 645             }else{
 646               /* auth failed ! */
 647               if(tracing) {
 648                 printf("TRACING: Auth failed\n");
 649               }
 650   
 651               AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 652                             o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 653               arg2 = delete_override(arg);
 654               NT_write_all_frwds(NULL, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 655               return UP_AUF; /* Auth failed */
 656             }
 657           }else{/* external syntax check failed */
 658             AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s%s\n",
 659                    o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 660                    delete_override(arg), external_syntax_results->error_str);
 661             return UP_SYN;
 662           }
 663         }
 664         else{ 
 665           old_version = get_old_version(arg);
 666           if(old_version != NULL){/* so, this is an update operation */
 667             if( (!reading_from_mail) || 
 668                 (subject_result.result != UP_SUBJ_NEW_ENFORCED)){/* If the user didn't enforce 
 669                                                                     creation in the subject line */
 670               external_syntax_results = UP_check_external_syntax(o, arg);
 671               if(    external_syntax_results->result != UP_EXTSYN_ERR 
 672                   && external_syntax_results->result != UP_EXTSYN_ERR_WARN){/* if there is no error */
 673                 /* if the old version & the new one are not identical */ 
 674                 if(identical(old_version, arg) != 1){
 675                   result = check_auth(arg, old_version, o->type->getName(), credentials);    
 676                   if(result == UP_AUTH_OK){
 677                     if(tracing) {                                
 678                       printf("TRACING: Will send the obj to be updated\n");
 679                     }
 680 
 681                     if(strcasecmp(o->type->getName(), "key-cert") == 0){
 682                       get_keyowner_fingerpr(arg);
 683                       generated_object = UP_generate_kc_attrs(o, arg);
 684                       external_syntax_results->new_obj = generated_object;
 685                     }
 686                     
 687                     result_from_RIPupd = send_object_db(external_syntax_results->new_obj, NULL, "UPD");
 688                     if(result_from_RIPupd->result == 0){
 689                       AK_add_to_ack(ack_file_name, "\nUpdate OK: [%s] %s\n",
 690                                     o->type->getName(), get_search_key(o, o->type->getName(), arg));
 691                       arg2 = delete_override(arg);
 692                       NT_write_all_ntfs(old_version, arg2, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 693                                         credentials.from);
 694                       return UP_OK;
 695                     }else{
 696                       AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s\n%s\n",
 697                                     o->type->getName(), get_search_key(o, o->type->getName(), arg),
 698                                     delete_override(arg), result_from_RIPupd->error_str);
 699                       return UP_INT;
 700                     }
 701                     result_from_RIPupd->result = 0;
 702                   }else if(result == UP_NAM){
 703                     /* name of a person/role object cannot be changed */
 704                     if(tracing) {
 705                       printf("TRACING: name of a person/role object cannot be changed\n");
 706                     }
 707                     
 708                     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",
 709                                   o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 710                     arg2 = delete_override(arg);
 711                     return UP_NAM; /* name of a person/role object cannot be changed */
 712 
 713 
 714                   }
 715                   else{
 716                     /* auth failed ! */
 717                     if(tracing) {
 718                       printf("TRACING: Auth failed\n");
 719                     }
 720       
 721                     AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 722                                   o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 723                     arg2 = delete_override(arg);
 724                     NT_write_all_frwds(old_version, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 725                     return UP_AUF; /* Auth failed */
 726                   }
 727 
 728                 }else{/* if the old and new versions of the object are the same */
 729                   if(tracing) {                                
 730                       printf("TRACING: The obj sent is identical to the one in the DB (NOOP)\n");
 731                   }
 732                   AK_add_to_ack(ack_file_name, "\nUpdate NOOP: [%s] %s\n",
 733                                     o->type->getName(), get_search_key(o, o->type->getName(), arg));
 734                   return UP_OK;
 735    
 736                 }
 737               }else{/* if there is an error in external syntax checks */
 738                 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s%s\n",
 739                      o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 740                      delete_override(arg), external_syntax_results->error_str);
 741                 return UP_SYN;
 742               }
 743 
 744             }else{/* if the user enforced creation (using NEW keyword) in the subject line */
 745 
 746               AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s\n"
 747                    "***Error:  Object already exists\n",
 748                    o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 749                    delete_override(arg));
 750               return UP_INT;
 751               
 752             }
 753           }else { /* old_version  == NULL, so, creation */
 754             external_syntax_results = UP_check_external_syntax(o, arg);
 755             if(    external_syntax_results->result != UP_EXTSYN_ERR 
 756                 && external_syntax_results->result != UP_EXTSYN_ERR_WARN){/* if there is no error */
 757               result = check_auth(arg, NULL, o->type->getName(), credentials);
 758               if(result == UP_AUTH_OK){ 
 759                 if(tracing) {                                
 760                   printf("TRACING: Will send the obj to be added\n");
 761                 }
 762                  /* if the object is a key-cert object, then we must import the PGP key */
 763                 if(strcmp(type, "key-cert") == 0){
 764                   result_from_import_key = import_key(arg);
 765                 }else{
 766                   result_from_import_key = NULL;
 767                 }
 768                 if(result_from_import_key == NULL){/* no PGP problem */
 769                   if(strcmp(type, "key-cert") == 0){/* if the object is a key-cert object */
 770 
 771                     generated_object = UP_generate_kc_attrs(o, arg);
 772                     result_from_RIPupd = send_object_db(generated_object, NULL, "ADD");                     
 773                   }else{
 774                     
 775                     result_from_RIPupd = send_object_db(external_syntax_results->new_obj, NULL, "ADD");
 776 
 777                   }
 778                   if(result_from_RIPupd->result == 0){/* if there was no problem */
 779                     AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n",
 780                                   o->type->getName(), get_search_key(o, o->type->getName(), arg));
 781                     arg2 = delete_override(arg);
 782                     NT_write_all_ntfs(NULL, arg2, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 783                                       credentials.from);
 784                     return UP_OK;
 785 
 786                   }else{
 787                     AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n",
 788                                   o->type->getName(), get_search_key(o, o->type->getName(), arg),
 789                                   result_from_RIPupd->error_str);
 790                     return UP_INT;
 791                   }
 792                   result_from_RIPupd = 0;
 793                 }else{/* there was a problem with PGP key import */
 794                   AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n",
 795                                   o->type->getName(), get_search_key(o, o->type->getName(), arg),
 796                                   result_from_import_key);
 797                   return UP_INT;
 798                 }
 799               }else if(result == UP_FWD){ /* this was a maintainer or as-block creation request, so
 800                                              forward it to <HUMAILBOX> */
 801 
 802                 if(tracing){
 803 
 804                   printf("TRACING: Maintainer or as-block request will be forwarded to <HUMAILBOX>\n");
 805                   
 806                 }
 807 
 808                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n"
 809                               "***Error:     %s objects cannot be created automatically\n"
 810                               "***Error:     This object has been forwarded to %s\n"
 811                               "***Error:     for authorisation.\n"
 812                               "***Error:     No further action from your part is required\n",
 813                               o->type->getName(), get_search_key(o, o->type->getName(), arg),
 814                               delete_override(external_syntax_results->new_obj), o->type->getName(), humailbox);
 815 
 816                 /* and forward this creation request to <HUMAILBOX> */
 817                 NT_forw_create_req(external_syntax_results->new_obj);
 818 
 819                 return UP_AUF;
 820 
 821                 
 822               }else if(result == UP_HOF){/* hierarchical authorisation failed */
 823                 if(tracing) {
 824                   printf("TRACING: Auth failed\n");
 825                 }
 826 
 827                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n***Error: Hierarchical authorisation"
 828                               " failed, request forwarded to maintainer.\n",
 829                               o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 830                 arg2 = delete_override(arg);
 831                 NT_write_all_frwds(NULL, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 832                 return UP_AUF;
 833                 
 834                 
 835               }else{
 836                 /* auth failed ! */
 837                 if(tracing) {
 838                   printf("TRACING: Auth failed\n");
 839                 }
 840 
 841                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 842                               o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 843                 arg2 = delete_override(arg);
 844                 NT_write_all_frwds(NULL, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 845                 return UP_AUF; /* Auth failed */
 846               }
 847             }else{
 848               AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s%s\n",
 849                               o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 850                               delete_override(arg), external_syntax_results->error_str);
 851               return UP_SYN;
 852             }
 853           } 
 854         }
 855 
 856       }
 857     }else{/* even if obj doesn't parse properly, it may be a legacy object
 858             which the user wants to delete... */
 859        if(tracing){   
 860          printf("TRACING: Object didn't parse\n");   
 861        }
 862        /* if it is for deletion */
 863        if(o->isDeleted){
 864          /* here delete it */
 865          old_version = get_old_version(arg);
 866          if(old_version == NULL){ /* the object doesn't exist in the db! */
 867                     search_key = get_search_key(o, o->type->getName(), arg);
 868                         if ( search_key == NULL )
 869                           search_key = "";
 870             AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n***Entry not found\n\n", 
 871                           o->type->getName(), search_key, delete_override(arg));
 872             return UP_NSO; /* no such object */
 873           }else {/* the object is in the db */
 874             if(identical(old_version, arg)){/* if the old & new versions are identical */
 875               result = check_auth(NULL, old_version, o->type->getName(), credentials);
 876               if(result == UP_AUTH_OK){ 
 877                 if(tracing) {
 878                   printf("TRACING: Will send the obj to be deleted\n");
 879                 }
 880                 if(strcmp(type, "key-cert") == 0){
 881                   result_from_delete_key = delete_key(arg);
 882                 }else{
 883                   result_from_delete_key = NULL;
 884                 }
 885                 /* if there was no problem with key deletion from the key-ring */
 886                 if(result_from_delete_key == NULL){
 887                   result_from_RIPupd = send_object_db(arg, NULL, "DEL");
 888                   if(result_from_RIPupd->result == 0){
 889                     AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n", 
 890                                   o->type->getName(), get_search_key(o, o->type->getName(), arg));
 891                     NT_write_all_ntfs(arg, NULL, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 892                                       credentials.from);
 893                     return UP_OK;
 894                   }else{
 895                     AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 896                                   o->type->getName(), get_search_key(o, o->type->getName(), arg),
 897                                   result_from_RIPupd->error_str);
 898                     return UP_INT;
 899                   }
 900                   result_from_RIPupd = 0;
 901                 }else{
 902                    AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 903                                   o->type->getName(), get_search_key(o, o->type->getName(), arg), result_from_delete_key);
 904                    return UP_INT;
 905                 }
 906               }else{ /* auth failed */
 907                 if(tracing) {
 908                   printf("TRACING: Auth failed\n");
 909                 }
 910 
 911                 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 912                               o->type->getName(), get_search_key(o, o->type->getName(), arg), delete_override(arg));
 913                 NT_write_all_frwds(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 914                 return UP_AUF; /* Auth failed */
 915               } 
 916             }else{/* the new & old versions do not match */
 917               AK_add_to_ack(ack_file_name, "\nDelete FAILED: new & old versions do not match\n%s\n", delete_override(arg));
 918               return UP_NOM; /* new & old versions do not match */
 919             }
 920           }
 921                
 922        }else{/* syntax error AND not deletion */
 923          AK_add_to_ack(ack_file_name, "\nUpdate FAILED: Syntax error in object\n");
 924        
 925          if(o->attrs.head() != NULL){
 926            for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
 927              if(attr->len > 0 && 
 928                 ( attr->type == NULL || (attr->type != NULL && strcasecmp(attr->type->name(), "override") != 0)) ){
 929                  value = (char*)malloc(attr->len);
 930                  strncpy(value, (char *)(arg+attr->offset) ,
 931                    attr->len - 1);
 932                  value[attr->len - 1] = '\0';
 933                  AK_add_to_ack(ack_file_name, "%s\n", value);
 934                  if(!attr->errors.empty()){
 935                    AK_add_to_ack_string(ack_file_name, attr->errors);
 936                  }
 937                  free(value);
 938              }else{
 939                if(!attr->errors.empty()){
 940                  AK_add_to_ack_string(ack_file_name, attr->errors);
 941                }
 942              }
 943            }
 944          }
 945          if(o->has_error){
 946            AK_add_to_ack_string(ack_file_name, o->errors);
 947          }
 948          AK_add_to_ack(ack_file_name, "\n");
 949        
 950          return UP_SYN; /* syntax error */
 951        }
 952     }
 953 }
 954 
 955 
 956 
 957 
 958 
 959 /* processes the objects in the given file */
 960 void process_file(char * filename, credentials_struct credentials, 
     /* [<][>][^][v][top][bottom][index][help] */
 961                   GHashTable * AUTO_NIC_hdl_hash, char * ack_file_name, 
 962                   GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
 963 
 964 FILE * input_file;
 965 GSList *list_of_objects = NULL, *list_of_objects2 = NULL;   
 966 GSList *next = NULL;
 967 int object_count = 0;
 968 char *object = NULL;
 969 char * line;
 970 char * lwrcase_line;
 971 int result = 0;
 972 struct VerifySignObject vSO, *pvSO;
 973 
 974 
 975   
 976     line = (char *)malloc(1024);
 977 
 978     if((input_file = fopen(filename, "r")) == NULL){
 979         ER_perror(FAC_UP, UP_CANTOPEN, "Couldn't open the file %s: %s\n", filename, strerror(errno));
 980         exit(1);  
 981     }
 982 
 983   
 984     while(fgets(line, 1023, input_file) != NULL){
 985       /* first, if it is a pasword, save it, but do not regard it as an attrib */ 
 986       lwrcase_line = strdup(line);
 987       g_strdown(lwrcase_line);
 988       if(strstr(lwrcase_line, "password:") == lwrcase_line){
 989         if(tracing){
 990           printf("TRACING: This is a password\n");
 991         }
 992         credentials.password_list = g_slist_append(credentials.password_list, 
 993                                       g_strstrip(strdup(line + strlen("password:"))));
 994         continue;
 995       }
 996       free(lwrcase_line);
 997       
 998       line = UP_remove_EOLs(line); /* remove '\n's and '\r' first */
 999       /* remove trailing white space */
1000       line = g_strchomp(line); 
1001       if(strlen(line) == 0){/* then, this was an empty line */
1002         if(object != NULL){
1003            list_of_objects = g_slist_append(list_of_objects, object);
1004            if(tracing){
1005              printf("TRACING: added an object: [%s]\n", object);
1006            }
1007            object = NULL;
1008         }
1009       }else{
1010         if(object == NULL && strlen(line) != 0){
1011           object = (char *)malloc(strlen(line) + 2);
1012           object = strcpy(object, line);
1013           object = strcat(object, "\n"); /* add EOL again (we removed it before) */
1014         }
1015         else{
1016           object = (char *)realloc(object, strlen(object) + strlen(line) + 2);
1017           object = strcat(object, line);
1018           object = strcat(object, "\n");
1019         }
1020       }
1021       
1022     }
1023     fclose(input_file);
1024 
1025     /* now, if at the very and of the input file there wasn't an 
1026        empty line, we have to add the remaining object in the 'object'
1027        variable */
1028     if(object != NULL){
1029        list_of_objects = g_slist_append(list_of_objects, object);
1030        object = NULL;
1031     }
1032 
1033 
1034 
1035     if(tracing) {
1036        printf("TRACING: Will process the objects in the list\n");
1037     }
1038     next = list_of_objects;
1039     object_count = 0;
1040     for( next = list_of_objects; next != NULL ; next = g_slist_next(next) ){
1041       
1042       if(UP_is_object((char *)next->data)){/* if this looks like an object */
1043       
1044         object_count++;
1045 
1046         if(tracing) {
1047           cout << "TRACING: Got an object from the list" << endl;
1048           cout << (char *)next->data << endl;
1049         }
1050         
1051         if(has_ref_to_AUTO_nic_hdl((char *)next->data)){/* defer the processing */
1052           if(tracing) {
1053             printf("TRACING: this object has a ref to an AUTO NIC hdl\n");
1054           }
1055           list_of_objects2 = g_slist_append(list_of_objects2, strdup((char *)next->data));
1056         }else{
1057           result = 0;
1058           result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name, 
1059                                    ntfy_hash, forw_hash, cross_hash);
1060           /* keep a tally */
1061           if(result == UP_OK){
1062             count_successful++;
1063           }else{
1064             count_unsuccessful++;
1065           }
1066         
1067         }
1068       }else{/* this does not look like an object (a signature? some other text?) */
1069         
1070         AK_add_to_ack(ack_file_name, "\nThe following paragraph does not look like an object,\n"
1071                                      "so ignoring it:\n%s\n", (char *)next->data);
1072         
1073       }
1074     }
1075 
1076 
1077     if(tracing) {
1078       printf("TRACING: list_of_objects2 has %d entries\n", g_slist_length(list_of_objects2));
1079     }
1080   
1081     if(tracing) {
1082       printf("TRACING: will start to process the second list\n");
1083     }
1084   
1085     for( next = list_of_objects2; next != NULL ; next = g_slist_next(next) ){
1086       if(tracing) {
1087         printf("TRACING: Will process object: %s\n", (char *)next->data);
1088       }
1089       result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name, 
1090                                ntfy_hash, forw_hash, cross_hash);
1091         /* keep a tally */
1092         if(result == UP_OK){
1093           count_successful++;
1094         }else{
1095           count_unsuccessful++;
1096         }
1097       
1098     }
1099   
1100 }/* process_file */
1101 
1102 
1103 
1104 
1105 
1106 
1107 /*  Generates a unique file name and returns the full path of the filename 
1108     for storing notification message.  */
1109       
1110 char * generate_upd_file(){
     /* [<][>][^][v][top][bottom][index][help] */
1111 
1112    char * name;
1113      
1114    /* allocate space for name.  32 should be enough for PID */
1115    name = (char*)malloc(strlen(tmpdir) + strlen("/dbupdate-tmp.") + 32 ); 
1116    
1117    sprintf(name, "%s/dbupdate-tmp.%i", tmpdir, pid /*getpid()*/);
1118 
1119      
1120    return name;
1121       
1122 }
1123 
1124 
1125 /* create_lock_file: creates a lock file in lockdir and locks it. This is a 
1126    part of crash recovery. Must be called in the beginning of the run. At the
1127    end, the file must be removed. */
1128 /* The idea: Create the "lock" file, and lock it. When another process starts
1129    running, it checks the existing lock files. If some exists, then it checks
1130    if it is locked or not. It not locked, then assumes that the corresponding
1131    dbupdate is alredy running. If not locked, assumes that it has crashed. 
1132    (note: when a process crashes, the kernel releases all the files locked by
1133    this process [by the OS]) 
1134    Problem: locking doesn't work properly on some NFS implementations. */
1135 
1136 lockfilestruct create_lock_file(){
     /* [<][>][^][v][top][bottom][index][help] */
1137   
1138   lockfilestruct lock;
1139   int file;
1140   int length;
1141 
1142   /* allocate space for file name */
1143   length = strlen(lockdir) +  strlen(hostname) + 32;
1144   lock.lockname = (char *)malloc(length + 1);
1145 
1146   snprintf(lock.lockname, length, "%s/dbupdate.%s.%ld", lockdir, hostname, pid /*getpid()*/);
1147 
1148   /* we will lock the file, so we have to use open(), but not fopen() (see man 
1149      page of lockf(3C)) */
1150   if(( file = open(lock.lockname, O_RDWR|O_CREAT)) == -1){
1151     ER_perror(FAC_UP, UP_CANTOPEN, "Can't open lock file, %s", lock.lockname);
1152     exit(1);
1153   }
1154  
1155   if(lockf(file, F_LOCK, 0) == -1){
1156     ER_perror(FAC_UP, UP_CANTLOCK, "Can't lock the file, %s", lock.lockname);
1157     exit(1);
1158   }; 
1159 
1160   lock.filedes = file;
1161 
1162   return lock;
1163 
1164 }
1165 
1166 
1167 
1168 
1169 
1170 /* remove_lock_file(): unlocks and removes the file  */
1171 void remove_lock_file(lockfilestruct lockfile){
     /* [<][>][^][v][top][bottom][index][help] */
1172 
1173   close(lockfile.filedes); /* this will remove the lock at the same time */ 
1174   unlink(lockfile.lockname);
1175 
1176 }
1177 
1178 
1179 
1180 /* writes the checkpoint file with the specified state */
1181 void write_checkpoint(int state){
     /* [<][>][^][v][top][bottom][index][help] */
1182 
1183   char * filename;
1184   char * tmpfilename;
1185   int length;
1186   FILE * file;
1187 
1188   if(tracing){
1189     printf("TRACING: write_checkpoint, state=[%i]\n", state); 
1190   }
1191   length = strlen(lockdir) +  strlen(hostname) + 64;
1192   filename    = (char *)malloc(length + 1);
1193   tmpfilename = (char *)malloc(length + 5);
1194  
1195   snprintf(filename,    length, "%s/dbupdate.checkpoint.%s.%ld",     lockdir, hostname, pid );
1196   snprintf(tmpfilename, length, "%s/dbupdate.checkpoint.%s.%ld.tmp", lockdir, hostname, pid );
1197 
1198   if(( file = fopen(tmpfilename, "w")) == NULL){
1199     //fprintf(stderr, "Can't open temp checkpoint file, %s", tmpfilename);
1200     ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temp checkpoint file, %s", tmpfilename);
1201     exit(1);
1202   }
1203 
1204   fprintf(file, "[STATE]\n%i\n", state);
1205 
1206   fprintf(file, "[FLAGS]\n");
1207   /* should print the flags here */
1208   
1209   fprintf(file, "[PARTS]\n");
1210   /* should print the parts (filenames) here */
1211 
1212   fprintf(file, "[OBJECTS1]\n");
1213 
1214   fprintf(file, "[OBJECTS2]\n");
1215 
1216   fprintf(file, "[ACKFILE]\n");
1217   
1218   fprintf(file, "[NOTIFFILES]\n");
1219 
1220   fprintf(file, "[TIDS1]\n");
1221   
1222   fprintf(file, "[TIDS2]\n");
1223 
1224   fprintf(file, "[NICHDLHASH]\n");
1225 
1226   fprintf(file, "[CURRENTOBJECT]\n");
1227 
1228   fprintf(file, "[CURRENTPART]\n");
1229 
1230   
1231   fclose(file);
1232 
1233   rename(tmpfilename, filename);
1234 
1235   /* free the char *'s */
1236   free(tmpfilename);
1237   free(filename);
1238 
1239 }
1240 
1241 
1242 
1243 
1244 /* removes check point file */
1245 void remove_checkpoint(){
     /* [<][>][^][v][top][bottom][index][help] */
1246 
1247   char * filename;
1248   int length;
1249   FILE * file;
1250 
1251   if(tracing){
1252     printf("TRACING: remove_checkpoint\n"); 
1253   }
1254   
1255   length = strlen(lockdir) +  strlen(hostname) + 64;
1256   filename    = (char *)malloc(length + 1);
1257  
1258   snprintf(filename,    length, "%s/dbupdate.checkpoint.%s.%ld",     lockdir, hostname, pid );
1259 
1260   unlink(filename);
1261  
1262   /* free the char * */
1263   free(filename);
1264 
1265 }
1266 
1267 
1268 
1269 
1270 
1271 
1272 
1273 /* main */
1274 void main(int argc, char **argv, char **envp){
     /* [<][>][^][v][top][bottom][index][help] */
1275   //init_and_set_options(argc, argv, envp);
1276 
1277   int count = 0;
1278   int i,j;
1279   int no_of_updateables = 0;
1280   char ** temp_vector;
1281   char * temp;
1282   char * temp_upd_file = NULL;
1283   char *input_file_name = NULL;
1284   GHashTable *AUTO_NIC_hdl_hash;
1285   credentials_struct credentials;
1286   FILE * upd_file;
1287   char c;
1288   char * mheader_replaced = NULL;
1289   char * mailtxt_replaced = NULL;
1290 
1291   /* temp variables to read from conf */
1292   char * source = NULL, * canupd = NULL;
1293   ca_dbSource_t *source_hdl;
1294   ca_updDbSource_t *upd_source_hdl;
1295 
1296   GHashTable *ntfy_hash, *forw_hash, *cross_hash;
1297   
1298 
1299   char *mail_command_line, * ack_file_name;
1300   char *config_file_name = NULL;
1301   
1302 
1303 
1304   /* to use EP module */
1305   EP_Mail_DescrPtr p; 
1306   EPTokenPtr pt;
1307   EPTokenPtr list_item;
1308   EPTokenKeysPtr ptk;
1309 
1310   char * temp_keyid;
1311 
1312   /* a variable to be used to know if the part is pgp_signed or not */
1313   int pgp_signed = 0;
1314 
1315   long debug = 0;
1316     
1317 
1318   /* create notification hashes */
1319   ntfy_hash = g_hash_table_new(g_str_hash, g_str_equal);
1320   forw_hash = g_hash_table_new(g_str_hash, g_str_equal);
1321   cross_hash = g_hash_table_new(g_str_hash, g_str_equal);
1322       
1323   credentials.password_list = NULL;
1324   credentials.from = NULL;
1325   int ch;
1326   char * to_address = NULL;
1327   char * subject = NULL;
1328   char * reply_to = NULL;
1329 
1330   AUTO_NIC_hdl_hash = g_hash_table_new(g_str_hash, g_str_equal);       
1331   
1332       
1333               
1334 
1335   while ((ch = getopt(argc, argv, "MtSTf:c:sn")) != -1){
1336           switch(ch) {
1337           case 'M':
1338                   reading_from_mail = 1;
1339                   break;
1340           case 'f':
1341                   input_file_name = strdup(optarg);
1342                   break;
1343           case 'c':
1344                   config_file_name = strdup(optarg);
1345                   break;
1346           case 't': 
1347                   tracing = 1;
1348                   break;
1349           /* Test mode? In test mode, creation of mntners and as-blocks is possible, without overriding */        
1350           case 'T':
1351                   test_mode = 1; 
1352                   break;
1353           /* Supress acks and notifications? If yes, the acks and notifs will go to DEFMAIL config var */        
1354           case 'S': 
1355                   supress_ack_notif = 1;
1356                   break;
1357           /* Print out the ack to stdout? */        
1358           case 's':
1359                   print_out_ack = 1;
1360                   break;
1361           /* are we processing networkupdate? (invoked via inetd) */        
1362           case 'n':
1363                   networkupdate = 1;
1364                   break;
1365           case '?':
1366           default:
1367                   printf("Unknown option\n"); exit(1);
1368           }
1369   }
1370 
1371 
1372   /* config stuff */
1373   /* if -c flag is given, use the named file as config file, otherwise use
1374      default filename */ 
1375   if( config_file_name != NULL){
1376     /*ca_readConfig(config_file_name, confVars, VARS);*/
1377     ca_init(config_file_name);
1378   }else{
1379     /*ca_readConfig("dbupdate.conf", confVars, VARS);*/
1380     ca_init("dbupdate.conf");
1381   }
1382 
1383   error_init(argc, argv);
1384 
1385 
1386   tmpdir = ca_get_tmpdir;
1387   tmpdir = g_strstrip(tmpdir);
1388   lockdir = ca_get_lockdir;
1389   mailcmd = ca_get_mailcmd;
1390   mailcmd = g_strstrip(mailcmd);
1391   notitxt = ca_get_notitxt;
1392   mailtxt = ca_get_mailtxt; 
1393   successtxt = ca_get_successtxt;
1394   failuretxt = ca_get_failuretxt;
1395   defmail = ca_get_defmail; defmail = UP_remove_EOLs(defmail);
1396   crosslog = ca_get_crosslog;
1397   fwtxt = ca_get_fwtxt;
1398   acksig = ca_get_acksig;
1399   humailbox = ca_get_humailbox;
1400   humailbox = g_strstrip(humailbox);
1401   autobox = ca_get_autobox;
1402   overridecryptedpw = ca_get_overridecryptedpw;
1403   overridecryptedpw = g_strstrip(overridecryptedpw);
1404   updlog = ca_get_updlog;
1405   acklog = ca_get_acklog;
1406   notiflog = ca_get_notiflog;
1407   notimailtxt = ca_get_notimailtxt;  
1408   notinetworktxt = ca_get_notinetworktxt;
1409   forwlog = ca_get_forwlog;
1410   fwmailtxt = ca_get_fwmailtxt;
1411   mtfwheader = ca_get_mtfwheader;
1412   mtfwtxt = ca_get_mtfwtxt;
1413   country = ca_get_country;
1414   pgppath = ca_get_pgppath;
1415   gpgcmd = ca_get_gpgcmd;
1416   autodbmhelp = ca_get_autodbmhelp;
1417   allocmnt = ca_get_allocmnt; allocmnt = UP_remove_EOLs(allocmnt);
1418   /* convert all '\t's, '\n's and '\r's in allocmnt to white spaces */
1419   for(i=0;i<strlen(allocmnt);i++){
1420     if(allocmnt[i] == '\r' || allocmnt[i] == '\n' || allocmnt[i] == '\t'){
1421       allocmnt[i] = ' ';
1422     }
1423   }
1424   cn_subject_add = ca_get_cn_subject_add; cn_subject_add = UP_remove_EOLs(cn_subject_add);
1425   cn_subject_del = ca_get_cn_subject_del; cn_subject_del = UP_remove_EOLs(cn_subject_del);
1426   cn_explain_add = ca_get_cn_explain_add;
1427   cn_explain_del = ca_get_cn_explain_del;
1428   cn_overlap_add = ca_get_cn_overlap_add;
1429   cn_overlap_del = ca_get_cn_overlap_del;
1430   cno_subject_add = ca_get_cno_subject_add; cno_subject_add = UP_remove_EOLs(cno_subject_add); 
1431   cno_subject_del = ca_get_cno_subject_del; cno_subject_del = UP_remove_EOLs(cno_subject_del);
1432   cno_explain_add = ca_get_cno_explain_add;
1433   cno_explain_del = ca_get_cno_explain_del;
1434   cno_overlap_add = ca_get_cno_overlap_add;
1435   cno_overlap_del = ca_get_cno_overlap_del;
1436   copyright_notice = ca_get_pw_resp_header;
1437   mheader = ca_get_mheader;
1438   pgp_public_key_ring = (char *)malloc(strlen(pgppath) + strlen("/pubring.gpg") + 2);
1439   sprintf(pgp_public_key_ring ,"%s/pubring.gpg", pgppath);
1440   if(test_mode != 1){/* if it is not already set to 1 (from command line), read from config */
1441     
1442     test_mode = ca_get_testmode;
1443   }
1444   /* retrieve source variables */
1445   upd_source_hdl = ca_get_UpdSourceHandle(CA_UPDSOURCE);
1446 
1447   if(upd_source_hdl == NULL){
1448     printf("There must be one updateable source in the config file. Exiting.\n");
1449     ER_perror(FAC_UP, UP_CONFERR, "There must be one updateable source in"
1450                                   " the config file. Exiting.");
1451     exit(1);
1452   }else{
1453     if(tracing){
1454       printf("\nTRACING: The upd_source_hdl is: %s\n", upd_source_hdl->name);
1455     }
1456     sources[0] = strdup(upd_source_hdl->name);
1457     update_host = upd_source_hdl->whoisd_host;
1458     query_host = strdup(update_host);
1459     update_port = upd_source_hdl->updPort;
1460     query_port = upd_source_hdl->qryPort;
1461     DBhost = upd_source_hdl->updDb.host;
1462     DBport = upd_source_hdl->updDb.port;
1463     DBname = upd_source_hdl->updDb.dbName;
1464     DBuser = upd_source_hdl->updDb.user;
1465     DBpasswd = upd_source_hdl->updDb.password; 
1466   }
1467 
1468   
1469 
1470   /* construct country array from country string variable */
1471   
1472   temp_vector = g_strsplit(country, "\n", 0);
1473   for(i=0, j=0; temp_vector[i] != NULL; i++){
1474     temp_vector[i] == g_strstrip(temp_vector[i]);
1475     if(strlen(temp_vector[i]) > 0){
1476       countries[j] = strdup(temp_vector[i]);
1477       g_strup(countries[j]);
1478       j++;
1479     }
1480   }
1481   countries[j] = NULL; /* mark the end of array */
1482   
1483   if(tracing){
1484     /* print out the config variables for debugging */
1485     printf("TRACING: countries[%i] = NULL\n", j);
1486  
1487     printf("TMPDIR is: [%s]\n", tmpdir);
1488     printf("MAILCMD is: [%s]\n", mailcmd);
1489     printf("NOTITXT is: [%s]\n", notitxt);
1490     printf("CROSSLOG is: [%s]\n", crosslog);
1491     printf("FWTXT is: [%s]\n", fwtxt);
1492     printf("HUMAILBOX is: [%s]\n", humailbox);
1493     printf("AUTOBOX is: [%s]\n", autobox);
1494     printf("OVERRIDECRYPTEDPW is: [%s]\n", overridecryptedpw);
1495     printf("ACKLOG is: [%s]\n", acklog);
1496     printf("NOTIFLOG is: [%s]\n", notiflog);
1497     printf("FORWLOG is: [%s]\n", forwlog);
1498     printf("NOTIMAILTXT is: [%s]\n", notimailtxt);
1499     printf("FWMAILTXT is: [%s]\n", fwmailtxt);
1500     printf("COUNTRY is: [%s]\n", country);
1501     printf("PGPPATH is: [%s]\n", pgppath);
1502     printf("UPDATE_HOST is: [%s]\n", update_host);
1503     printf("UPDATE_PORT is: [%i]\n", update_port);
1504     printf("QUERY_HOST is: [%s]\n",  query_host);
1505     printf("QUERY_PORT is: [%i]\n",  query_port);   
1506     printf("LOCKDIR is: [%s]\n", lockdir); 
1507     printf("TESTMODE is: [%i]\n", test_mode);
1508     printf("CNO_SUBJECT_ADD is: [%s]\n", cno_subject_add);
1509     printf("CNO_SUBJECT_DEL is: [%s]\n", cno_subject_del);
1510   }
1511   /* end of config stuff */
1512 
1513 
1514   /* set hostname global variable */
1515   gethostname(hostname, MAXHOSTNAMELEN);
1516 
1517   /* set pid global variable */
1518   pid = getpid(); 
1519 
1520   /* create the lock file and lock it */
1521   //lockfile = create_lock_file();
1522 
1523     
1524   /* initialize the parser */
1525   schema.initialize();
1526 
1527 
1528   /* Generate a name for temporary file for storing acks (AK_ack_file_name_generate
1529       also creates it) */
1530   ack_file_name = AK_ack_file_name_generate(tmpdir, ACK_FILE_PREFIX);
1531 
1532   /* initialize credentials.pgp_key_list */
1533   credentials.pgp_key_list = NULL;
1534 
1535 
1536   
1537  
1538   if(reading_from_mail){
1539     if(input_file_name != NULL){
1540       temp_upd_file = generate_upd_file();
1541       if(tracing){
1542         printf("TRACING: temp_upd_file is [%s]\n", temp_upd_file);
1543       }
1544 
1545       /* first log the input in the upd log file */
1546       UP_add_to_upd_log(input_file_name);
1547  
1548       
1549       MM_store(input_file_name, temp_upd_file, 0);
1550       p = EP_ParseMail(input_file_name, tmpdir, pgp_public_key_ring, gpgcmd);
1551       
1552     }else{/* input_file_name == NULL */
1553       temp_upd_file = generate_upd_file();
1554       MM_store("-", temp_upd_file, 0);
1555 
1556       /* first log the input in the upd log file */
1557       UP_add_to_upd_log(temp_upd_file);
1558       
1559       p = EP_ParseMail(temp_upd_file, tmpdir, pgp_public_key_ring, gpgcmd);
1560 
1561     }
1562 
1563     /* write off the checkpoint file */
1564     write_checkpoint(1);
1565 
1566     /* the new stuff using the EP module's interface */
1567     if(tracing){
1568       printf("\nTRACING: From field is: [%s]\n", p->from->field);
1569       if(p->from->next != NULL){
1570         printf("TRACING: From field (second line) is: [%s]\n", p->from->next->field);
1571       }
1572     }
1573 
1574     temp = (char *)malloc(strlen(p->from->field) + strlen("From: ") + 1);
1575     sprintf(temp, "From: %s", p->from->field);
1576     /* cut off the '\n's and '\r's at the end of temp */
1577     UP_remove_EOLs(temp);
1578 
1579     /* now, there is a problem with EP module (or c-client): the p->from->field
1580        would contain only the first line if the "From" field has multiple lines.
1581        As a temp solution, we will add the second line (if it exists) explicitely */
1582     if(p->from->next != NULL){/* if the second line exists */
1583       temp = (char *)realloc(temp, strlen(temp) + strlen(p->from->next->field) + 2);
1584       snprintf(temp, strlen(temp) + strlen(p->from->next->field) + 2, 
1585         "%s %s", temp, p->from->next->field);
1586     }
1587     UP_remove_EOLs(temp);
1588     
1589     
1590     credentials.from = temp;
1591     credentials.from_email = strdup(p->from->field); /* This doesn't contain "From:" */
1592     if(p->from->next != NULL){ /* if the second line exists */
1593       credentials.from_email = (char *)realloc(credentials.from_email, strlen(credentials.from_email) +
1594              strlen(p->from->next->field) + 2);
1595       snprintf(credentials.from_email, strlen(credentials.from_email) + 
1596              strlen(p->from->next->field) + 2, 
1597         "%s %s", credentials.from_email, p->from->next->field);
1598     }
1599     UP_remove_EOLs(credentials.from_email);
1600 
1601 
1602     update_mail_sender = strdup(credentials.from_email); 
1603     update_mail_sender = UP_remove_EOLs(update_mail_sender);
1604     
1605     if(tracing){
1606       printf("\nTRACING: update_mail_sender is: [%s]\n", update_mail_sender);
1607     }
1608     
1609                
1610     if(p->subject != NULL && p->subject->field != NULL){
1611       subject = strdup(p->subject->field);
1612     }else{
1613       subject = strdup("");
1614     }
1615     
1616     /* cut off the '\n' and '\r' from the end */
1617     UP_remove_EOLs(subject);
1618     
1619     update_mail_subject = strdup(subject);
1620 
1621     /* parse the subject line */ 
1622     subject_result = UP_subject_process(update_mail_subject); 
1623 
1624 
1625     if(p->reply_to != NULL && p->reply_to->field != NULL){
1626       reply_to = strdup(p->reply_to->field);
1627     }else{
1628       reply_to = strdup("");
1629     }
1630 
1631     
1632     /* cut off the '\n' and '\r' from the end */                    
1633     UP_remove_EOLs(reply_to);
1634 
1635     
1636     to_address = find_email_address(credentials.from);
1637 
1638     /* if Reply_To was available in the incoming header, then use it */
1639     if(strlen(reply_to) > 0){
1640       to_address = (char *)realloc(to_address, strlen(reply_to) + 1);
1641       to_address = strcpy(to_address, reply_to);
1642       to_address = find_email_address(to_address); /* so that we take only the email address */
1643     }
1644 
1645     if(p->message_id != NULL && p->message_id->field != NULL){
1646       update_mail_ID = strdup(p->message_id->field);
1647     }else{
1648       update_mail_ID = strdup("");
1649     }
1650 
1651     /* cut off the '\n' and '\r' from the end */
1652     UP_remove_EOLs(update_mail_ID);
1653     
1654 
1655     if(p->date != NULL && p->date->field != NULL){
1656       update_mail_date = strdup(p->date->field);
1657     }else{
1658       update_mail_date = strdup("");
1659     }
1660 
1661     /* cut off the '\n' and '\r' from the end  */
1662     UP_remove_EOLs(update_mail_date);
1663 
1664     
1665     if(tracing){
1666       printf("\nEP_ShowTree outputs:\n");
1667       EP_ShowTree(p->tree);
1668     }
1669     
1670     pt = EP_GetTokens(p->tree, NULL, NULL);
1671 
1672     if(tracing){
1673       /* Print the list out (debugging) */
1674       printf("\nEP_PrintTokens outputs:\n");
1675       EP_PrintTokens(pt);
1676     }
1677 
1678     /* replace the global variables in mheader */
1679     mheader_replaced = UP_replace_globals(mheader);
1680     /* replace the global variables in mailtxt */
1681     mailtxt_replaced = UP_replace_globals(mailtxt);
1682 
1683     /* If this wasn't only a help request, then we need to process the input */
1684     if(subject_result.result != UP_SUBJ_HELP_REQ){
1685       
1686       /* ... and now process the items in the list */
1687       list_item = pt;
1688       while (list_item != NULL) {
1689         if(tracing){
1690           printf("\n\nWill process: %s, MIMEtype: %d\n", list_item->file, list_item->MIMEContentType);
1691         }
1692         /* initialize pgp_key_list (XXX This should be a proper freeing of the list) */
1693         credentials.pgp_key_list = NULL;
1694         ptk = list_item->keys;
1695         if(ptk != NULL){
1696           AK_add_to_ack(ack_file_name, "==== BEGIN PGP SIGNED PART (keyID(s):");
1697           pgp_signed = 1; 
1698           while (ptk != NULL) {
1699             if(tracing){
1700               printf("TRACING:     key: %.8X, isValid: %i\n", 
1701                    ptk->keyID, ptk->isValidPGPSignature);
1702             }
1703             temp_keyid = (char *)malloc(10);
1704             sprintf(temp_keyid, "%.8X", ptk->keyID);
1705             if(tracing){
1706               printf("TRACING: This key will be added to the list: [%s]\n", temp_keyid);
1707             }
1708             AK_add_to_ack(ack_file_name, " %s", temp_keyid);
1709             credentials.pgp_key_list = g_slist_append (credentials.pgp_key_list, temp_keyid);
1710             ptk = ptk->next;
1711             if(ptk != NULL){
1712               AK_add_to_ack(ack_file_name, ",");
1713             }else{
1714               AK_add_to_ack(ack_file_name, ") ====\n");
1715             }
1716           }
1717         }
1718         process_file(list_item->file, credentials, 
1719                      AUTO_NIC_hdl_hash, ack_file_name, 
1720                      ntfy_hash, forw_hash, cross_hash);
1721         if(pgp_signed){
1722           AK_add_to_ack(ack_file_name, "==== END PGP SIGNED PART ====\n\n");
1723           pgp_signed = 0;
1724         }
1725         list_item = list_item->next;
1726       }
1727 
1728     }else{/* this was only a help request (inferred from the "Subject" line of the upd message) */
1729 
1730       /* Print out the header of the acknowledgement */
1731       AK_add_to_ack(ack_file_name, "To: %s\n%s\n\nHelp file requested so body of message ignored.\n\n\n"
1732           "============================================================\n\n", 
1733           to_address, mheader_replaced);
1734 
1735       AK_add_file_to_ack(ack_file_name, autodbmhelp);
1736       AK_add_to_ack(ack_file_name, "\n============================================================");
1737        
1738     }
1739     
1740     EP_CleanTokens(pt);
1741 
1742     EP_MailDescrCleanUp(p);
1743 
1744     /* if we have created a temporary file for update, delete it */
1745     if(temp_upd_file != NULL){
1746 
1747       unlink(temp_upd_file);
1748       
1749     }
1750 
1751   }else if(networkupdate){
1752 
1753     /* process networkupdate. Since we use inetd, we just process stdin */
1754     process_networkupdate(credentials, AUTO_NIC_hdl_hash, ack_file_name, 
1755                           ntfy_hash, forw_hash, cross_hash); 
1756 
1757   }else{/* not reading from the mail message or from network */
1758     if(input_file_name != NULL){
1759 
1760       /* first log the input in the upd log file */
1761       UP_add_to_upd_log(input_file_name);
1762 
1763       
1764       write_checkpoint(1);
1765       process_file(input_file_name, credentials, 
1766                   AUTO_NIC_hdl_hash, ack_file_name, 
1767                   ntfy_hash, forw_hash, cross_hash);
1768     }else{/* the filename is not given, so we have to write 
1769              stdin to a temp file, and give it to process_file */
1770        temp_upd_file = generate_upd_file();
1771        if(tracing){
1772          printf("TRACING: main: temp_upd_file=%s\n", temp_upd_file);
1773        }
1774        if(( upd_file = fopen(temp_upd_file, "a")) == NULL){
1775          ER_perror(FAC_UP, UP_CANTOPENW, "Can't open ack file, %s", temp_upd_file);
1776        }
1777 
1778        while((c = getchar()) != EOF){
1779          fprintf(upd_file, "%c",c);
1780        }
1781        fclose(upd_file);
1782 
1783        write_checkpoint(1);
1784        process_file(temp_upd_file, credentials, 
1785                   AUTO_NIC_hdl_hash, ack_file_name, 
1786                   ntfy_hash, forw_hash, cross_hash);
1787        unlink(temp_upd_file);
1788         
1789     }
1790       
1791   }  
1792 
1793 
1794   /* post-process and send the ack */
1795   if(reading_from_mail && to_address != NULL){
1796     AK_send_ack(ack_file_name, to_address, mailcmd);
1797   }
1798 
1799   /* if our update wasn't a mail update OR we have been asked explicitely
1800      to print out the ack to the stdout, print it */
1801   if(!reading_from_mail || print_out_ack){
1802     AK_print_ack(ack_file_name);
1803   }
1804   
1805   AK_log_ack(ack_file_name, acklog);
1806   AK_delete_ack(ack_file_name);
1807 
1808   NT_send_ntfy_list(ntfy_hash, mailcmd);
1809   NT_log_ntfy_list(ntfy_hash, notiflog); 
1810   NT_delete_ntfy_list(ntfy_hash);
1811 
1812   NT_send_ntfy_list(forw_hash, mailcmd);
1813   NT_log_ntfy_list(forw_hash, forwlog); 
1814   NT_delete_ntfy_list(forw_hash);
1815 
1816 
1817   NT_send_ntfy_list(cross_hash, mailcmd);
1818   NT_log_ntfy_list(cross_hash, crosslog); 
1819   NT_delete_ntfy_list(cross_hash);
1820       
1821   /* remove the lock file */
1822   //remove_lock_file(lockfile);
1823   
1824  
1825   /* remove checkpoint file */
1826   remove_checkpoint();
1827 
1828 
1829 
1830   if(tracing) {
1831     printf("TRACING: END\n");
1832   }
1833 
1834 
1835 }

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