/* ------------------------------------------------------------------------ */
/* --- vuserset: Programm zum Setzen der User Counts bei ACUCOBOL-GT®   --- */
/* --- Vision-Dateien im laufenden Betrieb                              --- */
/* ---                                                                  --- */
/* --- Author : Lothar Krauss vuserset@lkrauss.de                       --- */
/* ---                                                                  --- */
/* --- Lizenz : Dieses Programm darf frei verwendet, geändert  und      --- */
/* ---          weitergegeben werden, solange die folgenden Bedingungen --- */
/* ---          eingehalten werden:                                     --- */
/* ---          - Die Weitergabe einer compilierten Version darf nur    --- */
/* ---            zusammen mit dieser Source-Datei erfolen              --- */
/* ---          - Die Nennung des Authors, dieser Lizenzbedingungen     --- */
/* ---            und die folgenden Warnunge dürfen nicht verändert     --- */
/* ---            oder entfernt werden                                  --- */
/* ---          - Veränderungen am Sourcecode müssen mit Nennung des    --- */
/* ---            jeweiligen Authors und einer gültigen ihm zugehörigen --- */
/* ---            Emailadresse dokumentiert und unter dieser Lizenz     --- */
/* ---            freigegeben werden.                                   --- */
/* ---                                                                  --- */
/* --- Compilieren: Das Programm sollte unter gängigen UNIX- und LINUX- --- */
/* ---              Systemen mit folgendem Befehl compilierbar sein:    --- */
/* ---              cc -o vuserset vuserset.c                           --- */
/* ---                                                                  --- */
/* --- Aufruf : vuserset dateiname anzahl                               --- */
/* ---          Dateiname ist der Name der Vision-Datei. Bei Version    --- */
/* ---          4 und 5 ist hier die Hauptdatei anzugeben, also         --- */
/* ---          diejenige ohne Endung .vix, .dnn, .vnn                  --- */
/* ---          anzahl ist der gewünschte neue Wert des User Counts     --- */
/* ---          Er sollte auf keinen Fall kleiner sein als die Anzahl   --- */
/* ---          der Prozesse sein, die diese Datei aktuell geöffnet     --- */
/* ---          haben!                                                  --- */
/* ---                                                                  --- */
/* --- Warnung: Die Verwendung dieses Programmes erfolgt auf eigene     --- */
/* --- Gefahr! Ein Datenverlust ist nicht auszuschliessen!              --- */
/* --- Dieses Programm sollte auf keinen Fall auf Dateien angewendet    --- */
/* --- werden, die kein Problem aufweisen. Vor dem Programmlauf ist     --- */
/* --- unbedingt eine Sicherungskopie der betreffenden Datei            --- */
/* --- anzufertigen!                                                    --- */
/* ---                                                                  --- */
/* --- Historie:                                                        --- */
/* --- 04.07.2006 Lothar Krauss  vuserset@lkrauss.de                    --- */
/* ---            neu erstellt                                          --- */
/* ---                                                                  --- */
/* ------------------------------------------------------------------------ */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/file.h>

int main (int argc, char **argv)
{
  unsigned char buf[2],ubuf[2];
  int      u,u_alt,f,p,flag_bigend;
  char     *f_name;

  if (argc<3)
  {
     printf("Setzen des Usercounts in einer Vision-Datei\n");
     printf("Aufruf: %s <Dateiname> <Useranzahl>\n",argv[0]);
     exit(1);
  }

  u=atoi(argv[2]);
  f_name=argv[1];

  /* --- Datei oeffnen und 0. Byte locken als Zugriffsschutz--- */
  if ((f=open(f_name,O_RDWR)) <0)
  {
    perror(f_name);
    exit(1);
  }
  if (lseek(f,0,SEEK_SET)!=0)
  {
    perror("lseek");
    close(f);
    exit(1);
  }
  if (lockf(f,F_LOCK,1)!=0)
  {
    perror("lockf");
    close(f);
    exit(1);
  }

  /* --- Vision Versionsnummer und little/big-endian ermitteln --- */
  /* --- wird anhand der Bytes 4 und 5 im Header durchgefuehrt --- */
  if (lseek(f,4,SEEK_SET)!=4)
  {
    perror("lseek");
    lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1); close(f);
    exit(1);
  }
  if (read(f,buf,2)!=2)
  {
    perror("read");
    lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1); close(f);
    exit(1);
  }

  if (buf[0]==5 && buf[1]==0)
  {
    p=94; flag_bigend=0;
    printf("%s: Vision Version 5 little endian\n",f_name);
  }
  else if (buf[0]==0 && buf[1]==5)
  {
    p=94; flag_bigend=1;
    printf("%s: Vision Version 5 big endian\n",f_name);
  }
  else if (buf[0]==4 && buf[1]==0)
  {
    p=78; flag_bigend=0;
    printf("%s: Vision Version 4 little endian\n",f_name);
  }
  else if (buf[0]==0 && buf[1]==4)
  {
    p=78; flag_bigend=1;
    printf("%s: Vision Version 4 big endian\n",f_name);
  }
  else if (buf[0]==3 && buf[1]==0)
  {
    p=66; flag_bigend=0;
    printf("%s: Vision Version 3 little endian\n",f_name);
  }
  else if (buf[0]==0 && buf[1]==3)
  {
    p=66; flag_bigend=1;
    printf("%s: Vision Version 3 big endian\n",f_name);
  }
  else if (buf[0]==2 && buf[1]==0)
  {
    p=126; flag_bigend=0;
    printf("%s: Vision Version 2 little endian\n",f_name);
  }
  else if (buf[0]==0 && buf[1]==2)
  {
    p=126; flag_bigend=1;
    printf("%s: Vision Version 2 big endian\n",f_name);
  }
  else
  {
    printf("%s: Unbekanntes Format!\n",f_name);
    lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1); close(f);
    exit(1);
  }

  /* --- Alten Usercount lesen --- */
  if (lseek(f,p,SEEK_SET)!=p)
  {
    perror("lseek");
    lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1); close(f);
    exit(1);
  }
  if (read(f,buf,2)!=2)
  {
    perror("read");
    lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1); close(f);
    exit(1);
  }
  if (flag_bigend)
  {
    u_alt=256*buf[0]+buf[1];
    ubuf[0]=u/256;
    ubuf[1]=u%256;
  }
  else
  {
    u_alt=256*buf[1]+buf[0];
    ubuf[1]=u/256;
    ubuf[0]=u%256;
  }

  /* --- neuen Usercount schreiben --- */
  if (lseek(f,p,SEEK_SET)!=p)
  {
    perror("lseek");
    lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1); close(f);
    exit(1);
  }
  if (write(f,ubuf,2)!=2)
  {
    perror("write");
    lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1); close(f);
    exit(1);
  }
  printf("User Count von %i auf %i gesetzt.\n",u_alt,u);

  /* --- Datei schliessen und fertig --- */
  lseek(f,0,SEEK_SET); lockf(f,F_ULOCK,1);
  close(f);
  exit(0);
}
