/* 
 * Thomas Pantzer: mkhead.cc, Version: v0.1b  31.07.1998 17:11 
 * Thomas Pantzer: mkhead.cc, Version: v0.1c  11.02.2000 03:15 
 * 
 * 
 * Copyright 1998 by Thomas Pantzer
 * 
 * Permission to use, copy, modify, and distribute this software for noncommercial 
 * use and without fee is hereby granted, provided that the above copyright notice 
 * appear in all copies and that both that copyright notice and this permission 
 * notice appear in supporting documentation, and that the name of the Author not be 
 * used in advertising or publicity pertaining to distribution of the software 
 * without specific, written prior permission. The Author makes no representations about
 * the suitability of this software for any purpose.  It is provided "as is" 
 * without expressed or implied warranty. 
 * 
 * 
 * pantec@aix520.informatik.uni-leipzig.de   (Thomas Pantzer) 
 * 
 */


/*  
 * %ORGANISATION%: %FILE%, %VERSION%  %DATE% %TIME% 
 *
 * 
 * Copyright %YEAR% by %ORGANISATION%
 *
 * Permission to use, copy, modify, and distribute this software for noncommercial 
 * use and without fee is hereby granted, provided * that the above copyright notice 
 * appear in all copies and that both that copyright notice and this permission notice 
 * appear in supporting documentation, and that the name of the %SHORT_ORG% not be 
 * used in advertising or publicity pertaining to distribution of the software without 
 * specific, written prior permission. The %SHORT_ORG% makes no representations about the 
 * suitability of this software for any purpose.  It is provided "as is" without expressed 
 * or implied warranty.  
 * 
 * %CREATOR% 
 * %MAIL_ADDR%
 */


#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <dirent.h>
#include <string.h>


#define MAIN_G
#include "copyright.h"


#include "mkopts.h"
#include "readln.h"


// extern int gethostname(char *name, int namelen);

const char DISCLAIM_TEMPLATE[] =  
"/* \n" 
" * %s: %s, Version: %s  %s %s \n"
" * \n"
" * \n"
" * Copyright %s by %s\n"
" * \n"
" * Permission to use, copy, modify, and distribute this software for noncommercial \n"
" * use and without fee is hereby granted, provided that the above copyright notice \n"
" * appear in all copies and that both that copyright notice and this permission \n"
" * notice appear in supporting documentation, and that the name of the %s not be \n"
" * used in advertising or publicity pertaining to distribution of the software \n"
" * without specific, written prior permission. The %s makes no representations about\n"
" * the suitability of this software for any purpose.  It is provided \"as is\" \n"
" * without expressed or implied warranty. \n"
" * \n"
" * \n"
" * %s   (%s) \n"
" * \n"
" */\n\n";

const char SECOND_HEADING[] =  
"/* \n" 
" * %s: %s, Version: %s  %s %s \n"
" * \n"
" */\n\n";


#ifndef ORGANIZATION
#define ORGANIZATION "Thomas Pantzer"
#endif

#ifndef SHORT_ORG
#define SHORT_ORG "Author"
#endif



t_opts opts[] = {
	{empty_func,e_integer,'j',"major" ,"major version number",false,0,0.0,"\0"},
#define major opts[0].i

	{empty_func,e_integer,'i',"minor" ,"minor version number",false,1,0.0,"\0"},
#define minor opts[1].i

	{empty_func,e_integer,'p',"patch" ,"patch level\t",false,0,0.0,"\0"},
#define patchlevel opts[2].i

	{empty_func,e_string ,'o',"org", "name of organization",false,0,0.0,ORGANIZATION"\0                                                                                                                           \0"},
#define Organization opts[3].s

	{empty_func,e_string ,'s',"short", "abbreviation of org.",false,0,0.0,SHORT_ORG"\0                                                                                                                           \0"},
#define S_ORG opts[4].s

	{empty_func,e_string ,'m',"mail", "your mail address",false,0,0.0,"\0                                                                                                                           \0"},
#define mail opts[5].s

	{empty_func,e_string ,'h',"host", "your primary host",false,0,0.0,"\0                                                                                                                           \0"},
#define host opts[6].s

//	{empty_func,e_boolean,'s',"short_org", "abbreviation of org.",false,0,0.0,"\0"},
//#define S_ORG opts[7].b

	{empty_func,e_unknown,'\0',"\0","\0",0,0,0.0,"\0"}
	};
 



// #ifdef SunOS
// extern int gethostname(char *name, int namelen);
// #endif

char Version[64];  //  = "v0.1b";

int DirError = 0;


char date[64],time_[64],year[64],creator[128],domain[128];

#define MASK_NUM 6          
char mask[MASK_NUM][5] = {".c",".cc",".h",".C",".cpp",".H"};         


struct passwd *Get_pwent(uid_t uid)
{
   struct passwd *P;
   
   P = getpwent();
   while (P != NULL)
     {
      if (P->pw_uid == uid)
         return P;
         
      P = getpwent(); 
     }
     
   return NULL;  
} 


struct dirent *ReadDir(struct DIR *dir, char *mask)
{
   struct dirent *e;
   int i,j,k;


   do {   
   e = readdir(dir);
   
   if (e == NULL)
      return NULL;
      
   if (e->d_name == NULL)
      return NULL;
   
   i = strlen(e->d_name);
   j = strlen(mask);
       
   if (i>=j)
      {
//     use this for-loop if "mask" contains stars '*' at begin AND end   
//       for (k=0; k< i-j+1; k++)
//         {
//          fprintf(stderr,"name=%s, mask=%s\n",(char *)(e->d_name + k),mask);
//     this should be true only if "mask" contains a star '*' at the beginning
       k = i - j;
       if (strncmp((char *)(e->d_name + k),mask,j) == 0)
             return e;
//         } // for    
      }
   } while (true);   

   return NULL;   
}

char *FindFirst(char *msk, struct DIR **dir)
{
  struct dirent *entry;

  if (*dir != NULL) 
     	closedir(*dir);
  
  *dir = opendir(".");
  if (*dir == NULL)
     {
      DirError=-1;
      return NULL;
     } 
      
        
  entry = ReadDir(*dir,msk);
  if (entry==NULL)
     { 
      DirError=-2;
      return NULL;
     } 
        
  return entry->d_name;      
}

char *FindNext(char *msk,struct DIR *dir)
{
  struct dirent *entry;


  if (dir == NULL)
     {
      DirError=-3;
      return NULL;
     } 
        
  entry = ReadDir(dir,msk);
  if (entry == NULL)
     {
      DirError=-2;
      return NULL;
     } 

  return entry->d_name;      
}




void Abort(const char *s)
{
   fprintf(stderr,"\b%s\n",s);
   exit(1);
}


void GetTime(char *date,char *time_, char *year)
{
   time_t T;
   struct tm *P;
   
   T = time(NULL);  
   P = localtime(&T);
   
   sprintf(date,"%02d.%02d.%4d",P->tm_mday,P->tm_mon+1,P->tm_year+1900);
   sprintf(time_,"%02d:%02d",P->tm_hour,P->tm_min);
   sprintf(year,"%4d",P->tm_year+1900);
}

#ifdef SunOS
char getdomainname(char *name, int len)
{
   strcpy(name,"informatik.uni-leipzig.de");    // FIX THIS !!  
   return false;
}   
#endif

void init_header(void)
{
   struct passwd *P;

   P = Get_pwent(getuid());

   if (P != NULL)       
      strcpy(creator,P->pw_gecos);     
    else
      Abort("cannot get user name");
 
   sprintf(Version,"v%d.%d%c",major,minor,patchlevel+97);

   char *mailadress = getenv("MAIL_ADDRESS");
   
   if (mailadress != NULL)
      strcpy(mail,mailadress);
    else   
      {
       if (!(gethostname(&host[0],128) == 0))
          Abort("cannot get hostname");

       if (!(getdomainname(&domain[0],128) == 0))
          Abort("cannot get domainname");


       if (strlen(mail) == 0)
          sprintf(mail,"%s@%s.%s",P->pw_name,host,domain);
      }
    
   GetTime(&date[0],&time_[0],&year[0]);        
}

void add_header(char *file)
{
   char s[4096],t_file[256];     
   int nfd,ofd,r;
   
   sprintf(&s[0],DISCLAIM_TEMPLATE,Organization,file,Version,
              date,time_,year,Organization,S_ORG,S_ORG,mail,creator);
              
   sprintf(t_file,".hc~%s~",file);
   printf("processing file: %s\n",file);

   if (rename(file,t_file) == 0)
      {
       nfd = creat(file,6*64);
       if (nfd > 0)
          {
           if ( write(nfd,&s[0],strlen(s)) == ((int)strlen(s)) )
              {
               ofd = open(t_file,O_RDONLY);
               
               if (ofd > 0)
                  {  
                   r = read(ofd,&s[0],3072); 
                   while (r > 0)
                     {
                      write(nfd,&s[0],r);
                      r = read(ofd,&s[0],3072);
                     }
                     
                   close(ofd);  
                  }   
              }
           close(nfd);   
          } 
      } 
}


int main(int argc, char *argv[])
{
    struct DIR *dir = NULL;
    char *filename;
    char s[256];


    strcpy(mail,"\0");

    init_header();
  
    scan_args(argc,argv,opts);

    for (int i=0; i<MASK_NUM; i++)
      {    
       filename = FindFirst(&mask[i][0],&dir);
       while (filename != NULL)
         {
          add_header(filename); 
          filename = FindNext(&mask[i][0],dir);
         }
      }   
}

