home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PCBOARD
/
PCBM102.ZIP
/
SOURCES.ZIP
/
POSTMSG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-22
|
18KB
|
532 lines
/*
┌────────────────────────────────────────────────────────────────────────┐
│ │
│ ▒▒▒▒▒▒▄ ▒▒▒▒▒▒▄ ▒▒▒▒▒▒▒▄ ▒▒▒▒▒▒▒▒▄ ▒▒▒▒▒▒▄ ▒▒▄ ▒▒▄ ▒▒▒▒▒▒▄ │
│ ▒▒█▀▒▒█ ▒▒█▀▀▀▀ ▒▒█▀▒▒█ ▒▒█▒▒█▒▒█ ▒▒█▀▒▒█ ▒▒█ ▒▒█▀ ▒▒█▀▀▀▀ │
│ ▒▒▒▒▒▒█ ▒▒█ ▒▒▒▒▒█▀ ▒▒█▒▒█▒▒█ ▒▒█ ▒▒█ ▒▒█ ▒▒█▀ ▒▒▒▒▄ │
│ ▒▒█▀▀▀▀ ▒▒█ ▒▒█▀▒▒█ ▒▒█ ▀▀▒▒█ ▒▒█ ▒▒█ ▒▒█▒▒█▀ ▒▒█▀▀ │
│ ▒▒█ ▒▒▒▒▒▒▄ ▒▒▒▒▒▒▒█ ▒▒█ ▒▒█ ▒▒▒▒▒▒█ ▒▒▒█▀ ▒▒▒▒▒▒▄ │
│ ▀▀ ▀▀▀▀▀▀ ▀▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀▀ ▀▀▀▀▀▀ │
│ │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Module : Postmsg.c : Postage de messages directement dans une │
│ base de message PcBoard - par René Cougnenc (ANALIST) │
│ │
│ Remis au gout du jour par Vincent Gillet pour supporter │
│ l'utilisation de variables. │
│ │
╘════════════════════════════════════════════════════════════════════════╛
Compilation: modèle mémoire large.
*/
#include <stdio.h>
#include <share.h>
#include <string.h>
#include <time.h>
#include <malloc.h>
#include <sys/locking.h>
#include "postmsg.h"
#include "pcbmove.h"
#include "strings.h"
#define IDX_EXT ".IDX" /* Extension du fichier index.... */
char index_file[80] ; /* Fichier index base message */
char basehead[128] ; /* Header de la base messages */
long HighMsg, /* Numéro message plus élevé */
LowMsg , /* Numéro message le plus bas */
ActiveMsgs; /* Nombre de messages actifs */
indextype Index;
/*-------------------------------------------------------------------------*/
/*
* PostFile: Poste le fichier fname à FromField, en private.
*
* Retourne 1 en cas d'erreur, 0 si succès.
*
*/
PostFile( char *fname)
{
int test ;
char *txtbuf ;
/* Allocation buffers */
if( (txtbuf = (char *) calloc(1,MAXMSG)) == NULL )
{
puterrorlog(_Strings[L_MallocMessageError], MAXMSG);
return ERROR ;
}
if( readtxt(fname,txtbuf) ) /* Lecture du texte */
{ /* avec remplacement des */
free(txtbuf); /* variables */
return ERROR ;
}
sprintf (tampon, "PCBMOVE (%s) ERROR", __Version__);
test = PostMessage(PRIVATE, LOCAL, /* Postage du message */
Config.ToField,FromField, tampon,
txtbuf, Config.MessageBase);
free(txtbuf);
return test ;
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------
*
* PostMessage: Fonction à appeler pour poster un message.
*
* status : Status du message PUBLIC, PRIVATE ou COMMENT
* echo : ECHO ou NOECHO
* From : Pointeur sur le nom de l'auteur
* To : Pointeur sur le nom du destinataire
* Subject : Pointeur sur la chaine du sujet
* text: Pointeur sur le texte du message.
* MessageBase: Pointeur sur le nom du fichier de la base
* des messages.
*
*
* La fonction retourne 0 si le message a pu être posté.
* 1 en cas d'erreur.
*/
int
PostMessage( char status, char echo, char *From, char *To, char *Subject,
char *text, char *MessageBase )
{
FILE *fmsg,*fidx;
char msghead[128];
char offset_val[4];
long val;
char *msgbuf ;
memset(msghead,0x20,128 ); /* Resette le header des messages */
mkPCBnames( ); /* Retrouve le nom du fichier index */
if(( fmsg = _fsopen(MessageBase,"r+b", SH_DENYNO)) == NULL )
{
puterrorlog(_Strings[L_CanNotAccesMessage], MessageBase);
return ERROR ;
}
if(( fidx = _fsopen(index_file,"r+b", SH_DENYNO)) == NULL )
{
puterrorlog(_Strings[L_CanNotOpenIndexFile], index_file );
fclose( fmsg);
return ERROR ;
}
/* Alloue un buffer pour le message codé */
if( (msgbuf = (char *) calloc(1,MAXMSG)) == NULL )
{
puterrorlog(_Strings[L_MallocMessageError], MAXMSG);
fclose(fmsg);
fclose(fidx);
return ERROR ;
}
locking (fileno(fmsg), LK_LOCK, filelength (fileno(fmsg)));
locking (fileno(fidx), LK_LOCK, filelength (fileno(fidx)));
/* verouille tout pour l'ajout d'un message */
fread(basehead, 128, 1, fmsg ); /* lecture header base message */
HighMsg = BasNum ( basehead) ;
LowMsg = BasNum ( basehead + 4 );
ActiveMsgs = BasNum ( basehead + 8 );
/* Remplissage du header individuel */
msghead[0] = status ;
sprintf(msghead + 23, "%-25s", To );
sprintf(msghead + 58, "%-25s", From );
sprintf(msghead + 83, "%-25s", Subject );
msghead[120] = 225 ; /* Active Message */
msghead[121] = echo ;
DateMessage( msghead );
msghead[9] = CodeMessage( text , msgbuf );
HighMsg ++ ; /* On aura un message de plus, donc. */
ActiveMsgs ++ ;
ToBas ((SingleBasic *) (msghead +1),(double) HighMsg ); /* Numéro message */
ToBas ((SingleBasic *) (msghead +5),(double) 0L ); /* Pas de réf. */
/* ecrit l'offset du prochain message dans */
/* le fichier index. C'est la fin actuelle */
/* de la base messages bien entendu. */
if( fseek (fidx, 0L, SEEK_END ) != 0 )
{
puterrorlog("Erreur, base de messages pleine ?\n");
fclose(fidx);
fclose(fmsg);
free(msgbuf);
return ERROR ;
}
fseek(fmsg, 0L, SEEK_END ) ;
Index.Offset = ftell( fmsg) ; /* fill index structure */
Index.Num = HighMsg;
sprintf(Index.To , "%-25s", To );
sprintf(Index.From, "%-25s", From );
Index.Status = status;
/* Index.Date updated in DateMessage() (see up) */
memset (Index.Reserved, 0, sizeof (Index.Reserved));
fwrite (&Index.Offset, sizeof (Index), 1, fidx ) ; /* write index structure */
/* Ecrit le header du message */
/* puis le message lui même... */
fwrite(msghead, 128, 1, fmsg );
fwrite(msgbuf,128, (int) msghead[9] -1, fmsg );
/* Update le header de la base de messages*/
ToBas ((SingleBasic *) basehead, (double) HighMsg );
ToBas ((SingleBasic *) (basehead +4), (double) LowMsg );
ToBas ((SingleBasic *) (basehead +8), (double) ActiveMsgs );
fseek(fmsg, 0L, SEEK_SET ) ;
fwrite(basehead, 128, 1, fmsg );
fclose(fidx );
fclose(fmsg );
free(msgbuf) ;
return OK ;
}
/*-------------------------------------------------------------------------
*
* mkPCBnames:Recrée le nom du fichier index (.ndx) à partir du nom de la
* base de messages, qu'elle ait une extension ou pas.
* Fonctionne quelque soit le path (/pcb/toto.zob/machin/msgs.msg
* par exemple...)
*
* Remplit la variable globale avec le noms du fichier.
*/
void
mkPCBnames(void)
{
int i ;
strcpy( index_file, Config.MessageBase);
i = strlen( Config.MessageBase);
while (--i)
{
if( index_file[i] == '/' || index_file[i] == '\\' )
break ;
if( index_file[i] == '.' )
{
index_file[i] = '\0' ;
break ;
}
}
strcat( index_file, IDX_EXT);
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------
*
* readtxt: Lit le fichier contenant le message à poster.
* retourne 1 en cas de problème en affichant l'erreur
* retourne 0 si tout va bien.
* remplace aussi les variables de la forme %VARIABLES%
*
* VARIABLES :
* ===========
* FILE_TO_MOVE : Nom du fichier à déplacer
* GOOD_AREA : Area où a été trouvé le fichier lorsque il y a eu
* recherche
* AREA_ORI : Area spécifié en origine
* AREA_TAR : Area spécifié en destination
* AREA_ORI_DESC : Description de l'area en origine
* AREA_TAR_DESC : Description de l'area en destination
* DATE_MESSAGE : Date du message envoyé à PCBMOVE
* HEURE_MESSAGE : Heure du message envoyé à PCBMOVE
*/
int
readtxt( char *fname, char *txtbuf)
{
FILE *fp ;
char *ptr = txtbuf ;
char *debut_var;
int i = 0 ;
int len = 0;
if(( fp = fopen (fname,"rt") ) == NULL )
{
printf(_Strings[L_CanNotOpenReadMode], fname);
return ERROR ;
}
setvbuf(fp, NULL, _IOFBF, 5280 );
while( fread (ptr++,1,1,fp ) )
{
i++;
if (*(ptr-1) == '%')
{ /* si y'a un % */
debut_var = ptr; /* on cherche le % suivant */
while( fread (ptr++,1,1,fp ) && *(ptr-1) != '%');
*(ptr-1) = 0;
/* une fois délimité la variable, regarde compare */
if (!strcmp (debut_var, "FILE_TO_MOVE")){
strcpy (debut_var-1, file_to_move);
len = strlen(file_to_move);
} /* fin if */
if (!strcmp (debut_var, "GOOD_AREA")){
sprintf (tampon,"%02d", AreaFound);
strcpy (debut_var-1, tampon);
len = strlen(tampon);
} /* fin if */
if (!strcmp (debut_var, "AREA_ORI")){
sprintf (tampon,"%02d", area_ori);
strcpy (debut_var-1, tampon);
len = strlen(tampon);
} /* fin if */
if (!strcmp (debut_var, "AREA_TAR")){
sprintf(tampon,"%02d", area_tar);
strcpy (debut_var-1, tampon);
len = strlen(tampon);
} /* fin if */
if (!strcmp (debut_var, "AREA_ORI_DESC")){
getareaname (area_ori);
strcpy (debut_var-1, tampon);
len = strlen(tampon);
} /* fin if */
if (!strcmp (debut_var, "AREA_TAR_DESC")){
getareaname (area_tar);
strcpy (debut_var-1, tampon);
len = strlen(tampon);
} /* fin if */
if (!strcmp (debut_var, "GOOD_AREA_DESC")){
getareaname (AreaFound);
strcpy (debut_var-1, tampon);
len = strlen(tampon);
} /* fin if */
if (!strcmp (debut_var, "DATE_MESSAGE")){
strcpy (debut_var-1, DateField);
len = strlen(DateField);
} /* fin if */
if (!strcmp (debut_var, "HEURE_MESSAGE")){
strcpy (debut_var-1, HeureField);
len = strlen(HeureField);
} /* fin if */
if (!strcmp (debut_var, "SECURITY_MIN")){
strcpy (debut_var-1, Config.Security);
len = strlen(Config.Security);
} /* fin if */
if (!strcmp (debut_var, "FORWARD_USER")){
strcpy (debut_var-1, Config.ForwardUser);
len = strlen(Config.ForwardUser);
} /* fin if */
ptr = debut_var + len - 1;
i += len - 1; /* on remet le pointeur pour lire la suite */
} /* fin if */
if (i > MAXMSG)
{
puterrorlog(_Strings[L_MessageTooLong]);
fclose(fp);
return ERROR ;
}
}
fclose(fp);
return OK ;
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------
*
* CodeMessage: Code, dans le buffer msgbuf , le texte du message
* au format PcBoard.
*
* Retourne le nombre de blocs de 128 bytes + le header,
* à inscrire dans le header du message.
*/
int
CodeMessage( char *text, char *msgbuf)
{
unsigned char ch;
unsigned char *tamp = msgbuf ;
int CountSize = 0, /* Sera la taille totale du texte codé sans Header */
CountChar = 0,
CountBlocks = 2; /* Le premier bloc de 128 chars est tjrs le Header */
while(ch = *text++)
{
if(ch == 0x0A) ch = 227;
if(ch == 0x0D) continue ;
*tamp = ch; tamp ++;
CountChar++; CountSize ++;
if(CountChar > 127)
{
CountBlocks++;
CountChar = 0;
}
}
/* Ajuste la taille du dernier bloc à 128 chars */
/*----------------------------------------------*/
while(CountChar < 128)
{
*tamp = 0x20; tamp ++;
CountChar++; CountSize++;
}
/* printf("Nb blocs = %d\n", CountBlocks ); */
return CountBlocks ; /* retourne nombre de blocs + header */
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------
*
* DateMessage: Positionne la date et l'heure système dans le header
* du message.
*/
void
DateMessage( char *header)
{
long Time;
struct tm *tm ;
char buf[20] ;
time(&Time);
tm = localtime(&Time);
sprintf(buf,"%02d-%02d-%02d%02d:%02d",
tm->tm_mon +1 ,tm->tm_mday, tm->tm_year,
tm->tm_hour,tm->tm_min);
Index.Date = (unsigned) /* fill date Field in index structure */
(date_julien (tm->tm_mday, tm->tm_mon +1, tm->tm_year + 1900) - 2415020L);
/* date_julien retourne 2415020 au 01.01.80) */
strncpy(( char *) (header + 10), buf, 13 );
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/*
Conversions des nombres Basic en IEEE
Fonctions adaptées de 'realcnvt', par David Terry
Information collected and written by
David W. Terry
2/4/88
DONATED TO PUBLIC DOMAIN
*/
/*---------------------------------------------------------------------------
*
* Lecture d'un nombre Basic 4 bytes Réel Simple précision
*
* Retourne un double, le nombre Basic est un pointeur sur un tableau
* de 4 caracteres.
*/
double BasNum(SingleBasic OldNum)
{
IEEEdouble NewNum;
char Sign;
int Exp;
int X;
for(X = 0; X < 4; X++)
NewNum.byte[X] = 0x00;
Sign = OldNum[2] & 0x80;
Exp = OldNum[3] - 0x81 + 0x3FF;
NewNum.byte[6] = (Exp << 4);
NewNum.byte[7] = (Exp >> 4) | Sign;
for(X = 2; X > 0; X--)
{
OldNum[X] <<= 1;
OldNum[X] |= OldNum[X-1] >> 7;
}
OldNum[0] <<= 1;
for(X = 6; X >= 4; X--)
{
NewNum.byte[X] |= OldNum[X-4] >> 4;
NewNum.byte[X-1] = OldNum[X-4] << 4;
}
return(NewNum.value);
}
/*---------------------------------------------------------------------------
*
* Conversion d'un double en nombre Basic 4 octets double précision
*
* Remplit un tableau de 4 caracteres correspondant au double passé.
*/
void ToBas(SingleBasic *New, double Old)
{
char Sign;
int Exp;
int X;
unsigned char *NewNum, *OldNum;
NewNum = (char *) New;
OldNum = (char *) &Old;
Sign = OldNum[7] & 0x80;
Exp = ((OldNum[7] & 0x7F) << 4) + (OldNum[6] >> 4);
if (Exp)
Exp += 0x81 - 0x3FF;
for (X = 2; X >= 0; X--)
{
NewNum[X] = OldNum[X+4] << 4;
NewNum[X] |= OldNum[X+3] >> 4;
}
for (X = 0; X < 2; X++)
{
NewNum[X] >>= 1;
NewNum[X] |= NewNum[X+1] << 7;
}
NewNum[2] >>= 1;
NewNum[2] |= Sign;
NewNum[3] = Exp;
}
/*----------------------------------------------------------------------------*/
long date_julien(int jour, int mois, int annee) /* algorythme de calcul */
{ /* by Jean-Claude Ambroise */
int valeur_mois;
int valeur_annee;
float valeur_jour;
long jour_julien;
valeur_jour = (float) jour + 0.5;
valeur_mois = mois + 13;
valeur_annee = ((annee + 1) / 100) - 6;
if (mois < 3 && annee > 0) annee --;
if (valeur_mois > 15) valeur_mois = valeur_mois - 12;
jour_julien = (long)( 365.25 * annee) + (long)( 30.6001 * valeur_mois);
jour_julien = (long)(jour_julien + valeur_jour - valeur_annee + 1720994.5);
if (valeur_annee < 10 && jour_julien > 2299160) jour_julien --;
if (jour_julien < 2299161) jour_julien = jour_julien + valeur_annee;
return jour_julien;
}
/*----------------------------------------------------------------------------*/