2001-08-17 05:46:24 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
2001-11-25 12:18:18 +00:00
|
|
|
* $Id$
|
2001-08-17 05:46:24 +00:00
|
|
|
* Purpose ...............: Process 1 .tic file
|
|
|
|
*
|
|
|
|
*****************************************************************************
|
2008-02-17 17:50:13 +00:00
|
|
|
* Copyright (C) 1997-2008
|
2001-08-17 05:46:24 +00:00
|
|
|
*
|
|
|
|
* Michiel Broek FIDO: 2:280/2802
|
|
|
|
* Beekmansbos 10
|
|
|
|
* 1971 BV IJmuiden
|
|
|
|
* the Netherlands
|
|
|
|
*
|
|
|
|
* This file is part of MBSE BBS.
|
|
|
|
*
|
|
|
|
* This BBS is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
* later version.
|
|
|
|
*
|
|
|
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
2003-08-15 20:05:34 +00:00
|
|
|
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
2001-08-17 05:46:24 +00:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2002-06-30 12:48:44 +00:00
|
|
|
#include "../config.h"
|
2004-02-21 17:22:00 +00:00
|
|
|
#include "../lib/mbselib.h"
|
2002-01-07 19:16:03 +00:00
|
|
|
#include "../lib/users.h"
|
2004-02-21 17:22:00 +00:00
|
|
|
#include "../lib/mbsedb.h"
|
2002-08-05 13:30:44 +00:00
|
|
|
#include "unpack.h"
|
2001-08-17 05:46:24 +00:00
|
|
|
#include "mover.h"
|
|
|
|
#include "toberep.h"
|
2005-11-12 12:52:30 +00:00
|
|
|
#include "orphans.h"
|
2001-08-17 05:46:24 +00:00
|
|
|
#include "tic.h"
|
|
|
|
#include "utic.h"
|
|
|
|
#include "magic.h"
|
|
|
|
#include "forward.h"
|
|
|
|
#include "rollover.h"
|
|
|
|
#include "ptic.h"
|
|
|
|
#include "magic.h"
|
2002-04-18 19:39:23 +00:00
|
|
|
#include "createf.h"
|
2002-11-20 21:13:02 +00:00
|
|
|
#include "qualify.h"
|
2004-07-16 20:21:23 +00:00
|
|
|
#include "addbbs.h"
|
|
|
|
|
2001-08-17 05:46:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define UNPACK_FACTOR 300
|
|
|
|
|
|
|
|
extern int tic_bad;
|
|
|
|
extern int tic_dup;
|
|
|
|
extern int tic_out;
|
|
|
|
extern int do_quiet;
|
|
|
|
extern int check_crc;
|
|
|
|
extern int check_dupe;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return values:
|
|
|
|
* 0 - Success
|
|
|
|
* 1 - Some error
|
|
|
|
* 2 - Orphaned tic
|
|
|
|
*/
|
2005-11-12 12:52:30 +00:00
|
|
|
int ProcessTic(fa_list **sbl, orphans **opl)
|
2001-08-17 05:46:24 +00:00
|
|
|
{
|
2005-11-13 20:45:25 +00:00
|
|
|
time_t Now;
|
|
|
|
int First, Listed = FALSE, DownLinks = 0, MustRearc = FALSE;
|
2002-10-28 12:21:06 +00:00
|
|
|
int UnPacked = FALSE, IsArchive = FALSE, rc, i, j, k, File_Id = FALSE;
|
|
|
|
char *Temp, *unarc = NULL, *cmd = NULL;
|
2008-03-14 20:09:37 +00:00
|
|
|
char temp1[PATH_MAX], temp2[PATH_MAX], sbe[24], TDesc[1024];
|
2005-10-11 20:49:41 +00:00
|
|
|
unsigned int crc, crc2, Kb;
|
2002-10-28 12:21:06 +00:00
|
|
|
sysconnect Link;
|
|
|
|
FILE *fp;
|
|
|
|
struct utimbuf ut;
|
|
|
|
int BBS_Imp = FALSE, DidBanner = FALSE;
|
|
|
|
faddr *p_from;
|
2002-11-20 21:13:02 +00:00
|
|
|
qualify *qal = NULL, *tmpq;
|
2005-11-13 20:45:25 +00:00
|
|
|
orphans *topl;
|
2002-10-28 12:21:06 +00:00
|
|
|
|
|
|
|
Now = time(NULL);
|
|
|
|
|
|
|
|
if (TIC.TicIn.PathError) {
|
|
|
|
WriteError("Our Aka is in the path");
|
|
|
|
tic_bad++;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Temp = calloc(PATH_MAX, sizeof(char));
|
|
|
|
|
|
|
|
if (!do_quiet) {
|
2005-08-19 20:48:54 +00:00
|
|
|
mbse_colour(LIGHTGREEN, BLACK);
|
2002-10-28 12:21:06 +00:00
|
|
|
printf("Checking \b\b\b\b\b\b\b\b\b\b");
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2002-11-26 20:35:50 +00:00
|
|
|
if (TIC.Orphaned) {
|
2005-11-13 20:45:25 +00:00
|
|
|
fill_orphans(opl, TIC.TicName, TIC.TicIn.Area, TIC.TicIn.File, TRUE, FALSE);
|
|
|
|
Syslog('+', "File not in inbound: %s", TIC.TicIn.File);
|
2002-10-28 12:21:06 +00:00
|
|
|
free(Temp);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(Temp, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File);
|
2002-10-28 12:21:06 +00:00
|
|
|
crc = file_crc(Temp, CFG.slow_util && do_quiet);
|
|
|
|
TIC.FileSize = file_size(Temp);
|
|
|
|
TIC.FileDate = file_time(Temp);
|
|
|
|
|
|
|
|
if (TIC.TicIn.Size) {
|
|
|
|
if (TIC.TicIn.Size != TIC.FileSize)
|
|
|
|
WriteError("Size is %ld, expected %ld", TIC.FileSize, TIC.TicIn.Size);
|
|
|
|
} else {
|
2001-08-17 05:46:24 +00:00
|
|
|
/*
|
2002-10-28 12:21:06 +00:00
|
|
|
* No filesize in TIC file, add filesize.
|
2001-08-17 05:46:24 +00:00
|
|
|
*/
|
2002-10-28 12:21:06 +00:00
|
|
|
TIC.TicIn.Size = TIC.FileSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TIC.Crc_Int) {
|
|
|
|
if (crc != TIC.Crc_Int) {
|
|
|
|
Syslog('!', "CRC: expected %08lX, the file is %08lX", TIC.Crc_Int, crc);
|
2005-11-13 20:45:25 +00:00
|
|
|
fill_orphans(opl, TIC.TicName, TIC.TicIn.Area, TIC.TicIn.File, FALSE, TRUE);
|
2002-10-28 12:21:06 +00:00
|
|
|
if (check_crc) {
|
2005-11-13 20:45:25 +00:00
|
|
|
Syslog('+', "Bad CRC, will check this ticfile later");
|
2001-08-17 05:46:24 +00:00
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2002-10-28 12:21:06 +00:00
|
|
|
} else {
|
|
|
|
Syslog('!', "CRC: error, recalculating crc");
|
|
|
|
ReCalcCrc(Temp);
|
2002-04-18 19:39:23 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Syslog('+', "CRC: missing, calculating CRC");
|
|
|
|
ReCalcCrc(Temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load and check the .TIC area.
|
|
|
|
*/
|
|
|
|
if (!SearchTic(TIC.TicIn.Area)) {
|
|
|
|
UpdateNode();
|
|
|
|
Syslog('f', "Unknown file area %s", TIC.TicIn.Area);
|
|
|
|
p_from = fido2faddr(TIC.Aka);
|
|
|
|
if (!create_ticarea(TIC.TicIn.Area, p_from)) {
|
|
|
|
Bad((char *)"Unknown file area %s", TIC.TicIn.Area);
|
|
|
|
free(Temp);
|
2002-04-18 19:39:23 +00:00
|
|
|
tidy_faddr(p_from);
|
2002-10-28 12:21:06 +00:00
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
tidy_faddr(p_from);
|
|
|
|
/*
|
|
|
|
* Try to load the .TIC area again.
|
|
|
|
*/
|
|
|
|
if (!SearchTic(TIC.TicIn.Area)) {
|
|
|
|
Bad((char *)"Reload of new created file area %s failed", TIC.TicIn.Area);
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if ((tic.Secure) && (!TIC.TicIn.Hatch)) {
|
|
|
|
First = TRUE;
|
|
|
|
while (GetTicSystem(&Link, First)) {
|
|
|
|
First = FALSE;
|
|
|
|
if (Link.aka.zone) {
|
|
|
|
if ((Link.aka.zone == TIC.Aka.zone) && (Link.aka.net == TIC.Aka.net) &&
|
|
|
|
(Link.aka.node == TIC.Aka.node) && (Link.aka.point== TIC.Aka.point) && (Link.receivefrom))
|
|
|
|
Listed = TRUE;
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
if (!Listed) {
|
|
|
|
Bad((char *)"%s NOT connected to %s", aka2str(TIC.Aka), TIC.TicIn.Area);
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if ((!SearchNode(TIC.Aka)) && (!TIC.TicIn.Hatch)) {
|
|
|
|
Bad((char *)"%s NOT known", aka2str(TIC.Aka));
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TIC.TicIn.Hatch) {
|
|
|
|
if (strcasecmp(TIC.TicIn.Pw, nodes.Fpasswd)) {
|
|
|
|
Bad((char *)"Pwd error, got %s, expected %s", TIC.TicIn.Pw, nodes.Fpasswd);
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
} else {
|
|
|
|
if (strcasecmp(TIC.TicIn.Pw, CFG.hatchpasswd)) {
|
|
|
|
Bad((char *)"Password error in local Hatch");
|
|
|
|
WriteError("WARNING: it might be a Trojan in your inbound");
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (Magic_DeleteFile()) {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicName);
|
2002-10-28 12:21:06 +00:00
|
|
|
file_rm(temp1);
|
|
|
|
Syslog('+', "Deleted file %s", temp1);
|
|
|
|
file_rm(Temp);
|
|
|
|
free(Temp);
|
|
|
|
return 0;
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (Magic_MoveFile()) {
|
|
|
|
if (!SearchTic(TIC.TicIn.Area)) {
|
|
|
|
Bad((char *)"Unknown Area: %s", TIC.TicIn.Area);
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(T_File.Echo, tic.Name, 20);
|
|
|
|
strncpy(T_File.Group, tic.Group, 12);
|
|
|
|
TIC.KeepNum = tic.KeepLatest;
|
|
|
|
|
|
|
|
Magic_Keepnum();
|
|
|
|
|
|
|
|
if (!tic.FileArea) {
|
|
|
|
Syslog('+', "Passthru TIC area!");
|
|
|
|
strcpy(TIC.BBSpath, CFG.ticout);
|
|
|
|
strcpy(TIC.BBSdesc, tic.Comment);
|
|
|
|
} else {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(Temp, PATH_MAX, "%s/etc/fareas.data", getenv("MBSE_ROOT"));
|
2002-10-28 12:21:06 +00:00
|
|
|
if ((fp = fopen(Temp, "r")) == NULL) {
|
|
|
|
WriteError("Can't access fareas.data area: %ld", tic.FileArea);
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
fread(&areahdr, sizeof(areahdr), 1, fp);
|
|
|
|
if (fseek(fp, ((tic.FileArea -1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET)) {
|
|
|
|
fclose(fp);
|
|
|
|
WriteError("Can't seek area %ld in fareas.data", tic.FileArea);
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (fread(&area, areahdr.recsize, 1, fp) != 1) {
|
|
|
|
fclose(fp);
|
|
|
|
WriteError("Can't read area %ld in fareas.data", tic.FileArea);
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
fclose(fp);
|
|
|
|
strcpy(TIC.BBSpath, area.Path);
|
|
|
|
strcpy(TIC.BBSdesc, area.Name);
|
2001-08-17 05:46:24 +00:00
|
|
|
|
|
|
|
/*
|
2002-10-28 12:21:06 +00:00
|
|
|
* If the File area has a special announce group, change
|
|
|
|
* the group to that name.
|
2001-08-17 05:46:24 +00:00
|
|
|
*/
|
2002-10-28 12:21:06 +00:00
|
|
|
if (strlen(area.NewGroup))
|
|
|
|
strncpy(T_File.Group, area.NewGroup, 12);
|
|
|
|
}
|
|
|
|
strncpy(T_File.Comment, tic.Comment, 55);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if the destination area really exists, it may be that
|
|
|
|
* the area is not linked to an existing BBS area.
|
|
|
|
*/
|
|
|
|
if (tic.FileArea && access(TIC.BBSpath, W_OK)) {
|
|
|
|
WriteError("No write access to \"%s\"", TIC.BBSpath);
|
|
|
|
Bad((char *)"Dest directory not available");
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tic.DupCheck) && (check_dupe)) {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(Temp, PATH_MAX, "%s%s", TIC.TicIn.Area, TIC.TicIn.Crc);
|
2002-10-28 12:21:06 +00:00
|
|
|
crc2 = 0xffffffff;
|
|
|
|
crc2 = upd_crc32(Temp, crc2, strlen(Temp));
|
|
|
|
if (CheckDupe(crc2, D_FILEECHO, CFG.tic_dupes)) {
|
|
|
|
Bad((char *)"Duplicate file");
|
|
|
|
tic_dup++;
|
|
|
|
free(Temp);
|
|
|
|
return 1;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2002-11-20 21:13:02 +00:00
|
|
|
* Count the actual downlinks for this area and build the list of
|
|
|
|
* systems qualified to receive this file.
|
2002-10-28 12:21:06 +00:00
|
|
|
*/
|
|
|
|
First = TRUE;
|
|
|
|
while (GetTicSystem(&Link, First)) {
|
|
|
|
First = FALSE;
|
2002-11-20 21:13:02 +00:00
|
|
|
if ((Link.aka.zone) && (Link.sendto) && (!Link.pause)) {
|
2002-10-28 12:21:06 +00:00
|
|
|
DownLinks++;
|
2002-11-20 21:13:02 +00:00
|
|
|
p_from = fido2faddr(Link.aka);
|
|
|
|
if (TIC.TicIn.Hatch) {
|
2005-08-15 17:44:10 +00:00
|
|
|
fill_qualify(&qal, Link.aka, FALSE, in_list(p_from, sbl, TRUE));
|
2002-11-20 21:13:02 +00:00
|
|
|
} else {
|
|
|
|
fill_qualify(&qal, Link.aka, ((TIC.Aka.zone == Link.aka.zone) &&
|
|
|
|
(TIC.Aka.net == Link.aka.net) && (TIC.Aka.node == Link.aka.node) &&
|
2005-08-15 17:44:10 +00:00
|
|
|
(TIC.Aka.point == Link.aka.point)), in_list(p_from, sbl, TRUE));
|
2002-11-20 21:13:02 +00:00
|
|
|
}
|
|
|
|
tidy_faddr(p_from);
|
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
T_File.Size = TIC.FileSize;
|
|
|
|
T_File.SizeKb = TIC.FileSize / 1024;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the uplink's counters.
|
|
|
|
*/
|
|
|
|
Kb = TIC.FileSize / 1024;
|
|
|
|
if (SearchNode(TIC.Aka)) {
|
|
|
|
StatAdd(&nodes.FilesRcvd, 1L);
|
|
|
|
StatAdd(&nodes.F_KbRcvd, Kb);
|
|
|
|
UpdateNode();
|
|
|
|
SearchNode(TIC.Aka);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the fileecho and group counters.
|
|
|
|
*/
|
|
|
|
StatAdd(&fgroup.Files, 1L);
|
|
|
|
StatAdd(&fgroup.KBytes, Kb);
|
|
|
|
fgroup.LastDate = time(NULL);
|
|
|
|
StatAdd(&tic.Files, 1L);
|
|
|
|
StatAdd(&tic.KBytes, Kb);
|
|
|
|
tic.LastAction = time(NULL);
|
|
|
|
UpdateTic();
|
|
|
|
|
|
|
|
if (!do_quiet) {
|
|
|
|
printf("Unpacking \b\b\b\b\b\b\b\b\b\b");
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if this is an archive, and if so, which compression method
|
|
|
|
* is used for this file.
|
|
|
|
*/
|
2008-02-17 17:50:13 +00:00
|
|
|
if (strlen(tic.Convert) || tic.FileId || tic.ConvertAll || strlen(tic.Banner)) {
|
2005-12-04 11:46:07 +00:00
|
|
|
/*
|
|
|
|
* Create tmp workdir
|
|
|
|
*/
|
|
|
|
if (create_tmpwork()) {
|
|
|
|
free(Temp);
|
|
|
|
tidy_qualify(&qal);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-11-26 20:35:50 +00:00
|
|
|
if ((unarc = unpacker(TIC.TicIn.File)) == NULL)
|
|
|
|
Syslog('+', "Unknown archive format %s", TIC.TicIn.File);
|
2002-10-28 12:21:06 +00:00
|
|
|
else {
|
|
|
|
IsArchive = TRUE;
|
|
|
|
if ((strlen(tic.Convert) && (strcmp(unarc, tic.Convert) == 0)) || (tic.ConvertAll))
|
|
|
|
MustRearc = TRUE;
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the file if there are downlinks and we send the
|
|
|
|
* original file, but want to rearc it for ourself, or if
|
|
|
|
* it's a passthru area.
|
|
|
|
*/
|
|
|
|
if (((tic.SendOrg) && (MustRearc || strlen(tic.Banner))) || (!tic.FileArea)) {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File);
|
|
|
|
snprintf(temp2, PATH_MAX, "%s/%s", CFG.ticout, TIC.TicIn.File);
|
2002-10-28 12:21:06 +00:00
|
|
|
if ((rc = file_cp(temp1, temp2) == 0)) {
|
|
|
|
TIC.SendOrg = TRUE;
|
|
|
|
} else {
|
|
|
|
WriteError("Copy %s to %s failed: %s", temp1, temp2, strerror(rc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-17 17:50:13 +00:00
|
|
|
if (MustRearc && IsArchive) {
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2005-12-03 14:52:34 +00:00
|
|
|
snprintf(temp2, PATH_MAX, "%s/tmp/arc%d", getenv("MBSE_ROOT"), (int)getpid());
|
2002-11-26 20:35:50 +00:00
|
|
|
if (!checkspace(temp2, TIC.TicIn.File, UNPACK_FACTOR)) {
|
2002-10-28 12:21:06 +00:00
|
|
|
Bad((char *)"Not enough free diskspace left");
|
|
|
|
free(Temp);
|
2002-11-20 21:13:02 +00:00
|
|
|
tidy_qualify(&qal);
|
2005-12-04 11:46:07 +00:00
|
|
|
clean_tmpwork();
|
2002-10-28 12:21:06 +00:00
|
|
|
return 1;
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (chdir(temp2) != 0) {
|
|
|
|
WriteError("$Can't change to %s", temp2);
|
|
|
|
free(Temp);
|
2002-11-20 21:13:02 +00:00
|
|
|
tidy_qualify(&qal);
|
2005-12-04 11:46:07 +00:00
|
|
|
clean_tmpwork();
|
2002-10-28 12:21:06 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (!getarchiver(unarc)) {
|
|
|
|
WriteError("Can't get archiver for %s", unarc);
|
|
|
|
chdir(TIC.Inbound);
|
|
|
|
free(Temp);
|
2002-11-20 21:13:02 +00:00
|
|
|
tidy_qualify(&qal);
|
2005-12-04 11:46:07 +00:00
|
|
|
clean_tmpwork();
|
2002-10-28 12:21:06 +00:00
|
|
|
return 1;
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
cmd = xstrcpy(archiver.funarc);
|
2001-12-09 15:20:51 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if ((cmd == NULL) || (cmd == "")) {
|
|
|
|
Syslog('!', "No unarc command available");
|
|
|
|
} else {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File);
|
2004-03-02 20:47:23 +00:00
|
|
|
if (execute_str(cmd, temp1, (char *)NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null") == 0) {
|
2002-10-28 12:21:06 +00:00
|
|
|
UnPacked = TRUE;
|
|
|
|
} else {
|
|
|
|
chdir(TIC.Inbound);
|
|
|
|
Bad((char *)"Archive maybe corrupt");
|
2001-12-09 15:20:51 +00:00
|
|
|
free(Temp);
|
2005-12-03 14:52:34 +00:00
|
|
|
clean_tmpwork();
|
2001-12-09 15:20:51 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
free(cmd);
|
|
|
|
}
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2008-02-17 17:50:13 +00:00
|
|
|
/*
|
|
|
|
* Scan file for viri.
|
|
|
|
*/
|
2002-10-28 12:21:06 +00:00
|
|
|
if (tic.VirScan) {
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2008-02-17 17:50:13 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File);
|
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (!do_quiet) {
|
|
|
|
printf("Virscan \b\b\b\b\b\b\b\b\b\b");
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2008-02-17 17:50:13 +00:00
|
|
|
if (VirScanFile(temp1)) {
|
2002-10-28 12:21:06 +00:00
|
|
|
chdir(TIC.Inbound);
|
|
|
|
Bad((char *)"Possible virus found!");
|
|
|
|
free(Temp);
|
2002-11-20 21:13:02 +00:00
|
|
|
tidy_qualify(&qal);
|
2005-12-04 11:46:07 +00:00
|
|
|
clean_tmpwork();
|
2002-10-28 12:21:06 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (!do_quiet) {
|
|
|
|
printf("Checking \b\b\b\b\b\b\b\b\b\b");
|
|
|
|
fflush(stdout);
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-12-09 15:20:51 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (tic.FileId && tic.FileArea && IsArchive) {
|
|
|
|
if (UnPacked) {
|
2006-01-06 20:06:57 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/tmp/arc%d", getenv("MBSE_ROOT"), (int)getpid());
|
|
|
|
snprintf(Temp, PATH_MAX, "FILE_ID.DIZ");
|
|
|
|
if (getfilecase(temp1, Temp)) {
|
|
|
|
Syslog('f', "Found %s", Temp);
|
|
|
|
snprintf(temp1, PATH_MAX, "%s/tmp/arc%d/%s", getenv("MBSE_ROOT"), (int)getpid(), Temp);
|
|
|
|
snprintf(temp2, PATH_MAX, "%s/tmp/FILE_ID.DIZ", getenv("MBSE_ROOT"));
|
2002-10-28 12:21:06 +00:00
|
|
|
if (file_cp(temp1, temp2) == 0) {
|
|
|
|
File_Id = TRUE;
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
2006-01-06 20:06:57 +00:00
|
|
|
} else {
|
|
|
|
Syslog('f', "Didn't find a FILE_ID.DIZ");
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!getarchiver(unarc)) {
|
|
|
|
chdir(TIC.Inbound);
|
|
|
|
} else {
|
|
|
|
cmd = xstrcpy(archiver.iunarc);
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (cmd == NULL) {
|
|
|
|
WriteError("No unarc command available");
|
2001-12-09 15:20:51 +00:00
|
|
|
} else {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/tmp", getenv("MBSE_ROOT"));
|
2002-10-28 12:21:06 +00:00
|
|
|
chdir(temp1);
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s FILE_ID.DIZ", TIC.Inbound, TIC.TicIn.File);
|
2004-03-02 20:47:23 +00:00
|
|
|
if (execute_str(cmd, temp1, (char *)NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null") == 0) {
|
2002-10-28 12:21:06 +00:00
|
|
|
File_Id = TRUE;
|
|
|
|
} else {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s file_id.diz", TIC.Inbound, TIC.TicIn.File);
|
2004-03-02 20:47:23 +00:00
|
|
|
if (execute_str(cmd, temp1, (char *)NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null") == 0) {
|
2002-10-28 12:21:06 +00:00
|
|
|
File_Id = TRUE;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
free(cmd);
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
} /* if getarchiver */
|
|
|
|
} /* if not unpacked */
|
|
|
|
} /* if need FILE_ID.DIZ and not passthru */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create internal file description, priority is FILE_ID.DIZ,
|
|
|
|
* 2nd LDesc, and finally the standard description.
|
|
|
|
*/
|
|
|
|
if (!Get_File_Id()) {
|
|
|
|
if (TIC.TicIn.TotLDesc > 2) {
|
|
|
|
for (i = 0; i < TIC.TicIn.TotLDesc; i++) {
|
|
|
|
strncpy(TIC.File_Id[i], TIC.TicIn.LDesc[i], 48);
|
|
|
|
}
|
|
|
|
TIC.File_Id_Ct = TIC.TicIn.TotLDesc;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Format the description line (max 255 chars) in parts of 48 characters.
|
|
|
|
*/
|
|
|
|
if (strlen(TIC.TicIn.Desc) <= 48) {
|
|
|
|
strcpy(TIC.File_Id[0], TIC.TicIn.Desc);
|
|
|
|
TIC.File_Id_Ct++;
|
|
|
|
} else {
|
|
|
|
memset(&TDesc, 0, sizeof(TDesc));
|
|
|
|
strcpy(TDesc, TIC.TicIn.Desc);
|
|
|
|
while (strlen(TDesc) > 48) {
|
|
|
|
j = 48;
|
|
|
|
while ((TDesc[j] != ' ') && (j > 0))
|
|
|
|
j--;
|
|
|
|
if (j == 0) {
|
|
|
|
Syslog('f', "Panic, no spaces");
|
|
|
|
j = 47;
|
|
|
|
}
|
|
|
|
strncpy(TIC.File_Id[TIC.File_Id_Ct], TDesc, j);
|
|
|
|
Syslog('f', "%2d/%2d: \"%s\"", TIC.File_Id_Ct, j, TIC.File_Id[TIC.File_Id_Ct]);
|
|
|
|
TIC.File_Id_Ct++;
|
|
|
|
k = strlen(TDesc);
|
|
|
|
j++; /* Correct space */
|
|
|
|
for (i = 0; i <= k; i++, j++)
|
|
|
|
TDesc[i] = TDesc[j];
|
|
|
|
if (TIC.File_Id_Ct == 23)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
strncpy(TIC.File_Id[TIC.File_Id_Ct], TDesc, 48);
|
|
|
|
Syslog('f', "%2d/%2d: \"%s\"", TIC.File_Id_Ct, strlen(TIC.File_Id[TIC.File_Id_Ct]), TIC.File_Id[TIC.File_Id_Ct]);
|
|
|
|
TIC.File_Id_Ct++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} /* not get FILE_ID.DIZ */
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2005-11-13 20:45:25 +00:00
|
|
|
/*
|
2005-12-31 12:18:31 +00:00
|
|
|
* Now check if other (older) ticfiles point to this file,
|
|
|
|
* if found mark it to purge later.
|
2005-11-13 20:45:25 +00:00
|
|
|
*/
|
|
|
|
for (topl = *opl; topl; topl = topl->next) {
|
|
|
|
if ((strcmp(topl->Area, TIC.TicIn.Area) == 0) && (strcmp(topl->FileName, TIC.TicIn.File) == 0)) {
|
2005-11-19 19:43:03 +00:00
|
|
|
topl->Purged = TRUE;
|
2005-11-13 20:45:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-26 20:35:50 +00:00
|
|
|
/*
|
|
|
|
* Rearc file if it is an unpacked archive.
|
|
|
|
*/
|
2002-10-28 12:21:06 +00:00
|
|
|
if ((MustRearc) && (UnPacked) && (tic.FileArea)) {
|
|
|
|
if (Rearc(tic.Convert)) {
|
|
|
|
/*
|
|
|
|
* Get new filesize for import and announce
|
|
|
|
*/
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile);
|
2002-10-28 12:21:06 +00:00
|
|
|
TIC.FileSize = file_size(temp1);
|
|
|
|
T_File.Size = TIC.FileSize;
|
|
|
|
T_File.SizeKb = TIC.FileSize / 1024;
|
|
|
|
/*
|
|
|
|
* Calculate the CRC if we must send the new archived file.
|
|
|
|
*/
|
|
|
|
if (!TIC.SendOrg) {
|
|
|
|
ReCalcCrc(temp1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
WriteError("Rearc failed");
|
|
|
|
} /* if Rearc() */
|
2002-11-26 20:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change banner if needed.
|
|
|
|
*/
|
|
|
|
if ((strlen(tic.Banner)) && IsArchive) {
|
|
|
|
cmd = xstrcpy(archiver.barc);
|
|
|
|
if ((cmd == NULL) || (!strlen(cmd))) {
|
2005-11-19 20:22:40 +00:00
|
|
|
Syslog('+', "No banner command for %s", archiver.name);
|
2002-11-26 20:35:50 +00:00
|
|
|
} else {
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile);
|
|
|
|
snprintf(Temp, PATH_MAX, "%s/etc/%s", getenv("MBSE_ROOT"), tic.Banner);
|
2004-03-02 20:47:23 +00:00
|
|
|
if (execute_str(cmd, temp1, (char *)NULL, Temp, (char *)"/dev/null", (char *)"/dev/null")) {
|
2005-08-19 19:07:24 +00:00
|
|
|
WriteError("Changing the banner failed");
|
2002-10-28 12:21:06 +00:00
|
|
|
} else {
|
2002-11-26 20:35:50 +00:00
|
|
|
Syslog('+', "New banner %s", tic.Banner);
|
|
|
|
TIC.FileSize = file_size(temp1);
|
|
|
|
T_File.Size = TIC.FileSize;
|
|
|
|
T_File.SizeKb = TIC.FileSize / 1024;
|
|
|
|
ReCalcCrc(temp1);
|
|
|
|
DidBanner = TRUE;
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
2002-11-26 20:35:50 +00:00
|
|
|
}
|
2005-12-03 14:52:34 +00:00
|
|
|
clean_tmpwork();
|
2002-10-28 12:21:06 +00:00
|
|
|
chdir(TIC.Inbound);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the file is converted, we set the date of the original
|
|
|
|
* received file as the file creation date.
|
|
|
|
*/
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(Temp, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile);
|
2002-10-28 13:57:38 +00:00
|
|
|
if ((MustRearc || DidBanner) && CFG.ct_KeepDate) {
|
2002-10-28 12:21:06 +00:00
|
|
|
if ((tic.Touch) && (tic.FileArea)) {
|
|
|
|
ut.actime = mktime(localtime(&TIC.FileDate));
|
|
|
|
ut.modtime = mktime(localtime(&TIC.FileDate));
|
|
|
|
utime(Temp, &ut);
|
2002-11-22 21:51:15 +00:00
|
|
|
Syslog('-', "Restamp filedate %s to %s", Temp, rfcdate(ut.modtime));
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
}
|
2002-11-23 16:48:54 +00:00
|
|
|
/*
|
|
|
|
* Now make sure the file timestamp is updated. The file may be restamped,
|
|
|
|
* altered by banners etc.
|
|
|
|
*/
|
|
|
|
TIC.FileDate = file_time(Temp);
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-11-23 16:48:54 +00:00
|
|
|
/*
|
|
|
|
* If not passthru, import in the BBS.
|
|
|
|
*/
|
2002-10-28 12:21:06 +00:00
|
|
|
if (tic.FileArea) {
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-11-30 13:07:47 +00:00
|
|
|
Syslog('+', "Import: %s (%s) Area: %s", TIC.NewFile, TIC.NewFullName, TIC.TicIn.Area);
|
2004-07-16 20:21:23 +00:00
|
|
|
BBS_Imp = Add_BBS(&qal);
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (!BBS_Imp) {
|
|
|
|
Bad((char *)"File Import Error");
|
|
|
|
free(Temp);
|
2002-11-20 21:13:02 +00:00
|
|
|
tidy_qualify(&qal);
|
2005-12-04 11:46:07 +00:00
|
|
|
clean_tmpwork();
|
2002-10-28 12:21:06 +00:00
|
|
|
return 1;
|
2001-12-09 15:20:51 +00:00
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
chdir(TIC.Inbound);
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-11-26 20:35:50 +00:00
|
|
|
/*
|
|
|
|
* Create file announce record
|
|
|
|
*/
|
2002-10-28 12:21:06 +00:00
|
|
|
if (tic.FileArea) {
|
|
|
|
if (strlen(TIC.TicIn.Magic))
|
2004-03-09 21:42:29 +00:00
|
|
|
magic_update(TIC.TicIn.Magic, TIC.NewFile);
|
2002-10-28 12:21:06 +00:00
|
|
|
else
|
|
|
|
Magic_UpDateAlias();
|
|
|
|
|
2007-10-12 19:19:00 +00:00
|
|
|
for (i = 0; i < TIC.File_Id_Ct; i++)
|
2002-10-28 12:21:06 +00:00
|
|
|
strncpy(T_File.LDesc[i], TIC.File_Id[i], 48);
|
|
|
|
T_File.TotLdesc = TIC.File_Id_Ct;
|
|
|
|
T_File.Announce = tic.Announce;
|
2002-11-26 20:35:50 +00:00
|
|
|
strncpy(T_File.Name, TIC.NewFile, 12);
|
|
|
|
strncpy(T_File.LName, TIC.NewFullName, 80);
|
2002-10-28 12:21:06 +00:00
|
|
|
T_File.Fdate = TIC.FileDate;
|
2004-03-11 18:58:51 +00:00
|
|
|
Add_ToBeRep(T_File);
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (TIC.SendOrg && !tic.FileArea) {
|
|
|
|
/*
|
|
|
|
* If it's a passthru area we don't need the
|
|
|
|
* file in the inbound anymore so it can be
|
|
|
|
* deleted.
|
|
|
|
*/
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File);
|
2002-10-28 12:21:06 +00:00
|
|
|
if (file_rm(temp1) == 0)
|
|
|
|
Syslog('f', "Deleted %s", temp1);
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
if (DownLinks) {
|
|
|
|
First = TRUE;
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
/*
|
2002-11-21 22:15:01 +00:00
|
|
|
* Add all our system aka's to the seenby lines in the same zone,
|
|
|
|
* omit aka's already in the seenby list.
|
2002-10-28 12:21:06 +00:00
|
|
|
*/
|
|
|
|
for (i = 0; i < 40; i++) {
|
2002-11-21 22:15:01 +00:00
|
|
|
if (CFG.akavalid[i] && (tic.Aka.zone == CFG.aka[i].zone)) {
|
|
|
|
p_from = fido2faddr(CFG.aka[i]);
|
2005-08-15 17:44:10 +00:00
|
|
|
if (! in_list(p_from, sbl, TRUE)) {
|
2006-03-29 18:36:35 +00:00
|
|
|
if (CFG.aka[i].point)
|
|
|
|
snprintf(sbe, 24, "%u:%u/%u.%u", CFG.aka[i].zone, CFG.aka[i].net, CFG.aka[i].node, CFG.aka[i].point);
|
|
|
|
else
|
|
|
|
snprintf(sbe, 24, "%u:%u/%u", CFG.aka[i].zone, CFG.aka[i].net, CFG.aka[i].node);
|
2005-08-15 17:44:10 +00:00
|
|
|
fill_list(sbl, sbe, NULL);
|
2002-11-13 21:34:28 +00:00
|
|
|
}
|
2002-11-21 22:15:01 +00:00
|
|
|
tidy_faddr(p_from);
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2002-11-26 20:35:50 +00:00
|
|
|
* Add seen-by lines for all systems that will receive this file.
|
2002-10-28 12:21:06 +00:00
|
|
|
*/
|
2002-11-21 22:15:01 +00:00
|
|
|
for (tmpq = qal; tmpq; tmpq = tmpq->next) {
|
|
|
|
if (tmpq->send) {
|
2006-03-29 18:36:35 +00:00
|
|
|
if (CFG.aka[i].point)
|
|
|
|
snprintf(sbe, 24, "%u:%u/%u.%u", tmpq->aka.zone, tmpq->aka.net, tmpq->aka.node, tmpq->aka.point);
|
|
|
|
else
|
|
|
|
snprintf(sbe, 24, "%u:%u/%u", tmpq->aka.zone, tmpq->aka.net, tmpq->aka.node);
|
2005-08-15 17:44:10 +00:00
|
|
|
fill_list(sbl, sbe, NULL);
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2005-08-15 17:44:10 +00:00
|
|
|
uniq_list(sbl);
|
|
|
|
sort_list(sbl);
|
2002-11-21 22:15:01 +00:00
|
|
|
|
2002-11-20 21:13:02 +00:00
|
|
|
/*
|
2002-11-21 22:15:01 +00:00
|
|
|
* Now forward this file to the qualified downlinks.
|
2002-11-20 21:13:02 +00:00
|
|
|
*/
|
|
|
|
for (tmpq = qal; tmpq; tmpq = tmpq->next) {
|
|
|
|
if (tmpq->send) {
|
2005-08-15 17:44:10 +00:00
|
|
|
ForwardFile(tmpq->aka, *sbl);
|
2002-11-21 22:15:01 +00:00
|
|
|
tic_out++;
|
2002-11-20 21:13:02 +00:00
|
|
|
}
|
|
|
|
}
|
2002-10-28 12:21:06 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
Magic_ExecCommand();
|
|
|
|
Magic_CopyFile();
|
|
|
|
Magic_UnpackFile();
|
|
|
|
Magic_AdoptFile();
|
2002-05-11 15:30:34 +00:00
|
|
|
|
2005-08-12 14:20:33 +00:00
|
|
|
|
2005-08-28 14:10:06 +00:00
|
|
|
snprintf(Temp, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicName);
|
2007-10-12 19:19:00 +00:00
|
|
|
if (unlink(Temp)) {
|
|
|
|
WriteError("$Can't delete %s", Temp);
|
|
|
|
}
|
2002-11-23 16:48:54 +00:00
|
|
|
|
2002-10-28 12:21:06 +00:00
|
|
|
free(Temp);
|
2002-11-20 21:13:02 +00:00
|
|
|
tidy_qualify(&qal);
|
2002-10-28 12:21:06 +00:00
|
|
|
return 0;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|