void AdoptFile(int Area, char *File, char *Description) { FILE *fp; char *temp, *temp2, *tmpdir, *unarc, *pwd, *lname, *fileid; char Desc[256], TDesc[256]; int MustRearc = FALSE, UnPacked = FALSE; int IsVirus = FALSE, File_Id = FALSE; int i, j, k, lines = 0, File_id_cnt = 0; struct FILE_record f_db; Syslog('f', "Adopt(%d, %s, %s)", Area, FTND_SS(File), FTND_SS(Description)); if (!do_quiet) ftnd_colour(CYAN, BLACK); if (LoadAreaRec(Area) == FALSE) die(FTNERR_INIT_ERROR); if (area.Available) { temp = calloc(PATH_MAX, sizeof(char)); temp2 = calloc(PATH_MAX, sizeof(char)); pwd = calloc(PATH_MAX, sizeof(char)); tmpdir = calloc(PATH_MAX, sizeof(char)); if (CheckFDB(Area, area.Path)) die(FTNERR_INIT_ERROR); getcwd(pwd, PATH_MAX); if (!do_quiet) { printf("Adopt file: %s ", File); printf("Unpacking \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } snprintf(tmpdir, PATH_MAX, "%s/tmp/arc%d", getenv("FTND_ROOT"), (int)getpid()); if (create_tmpwork()) { WriteError("Can't create %s", tmpdir); if (!do_quiet) printf("\nCan't create dir %s\n", tmpdir); die(FTNERR_INIT_ERROR); } snprintf(temp, PATH_MAX, "%s/%s", pwd, File); if (do_novir == FALSE) { if (!do_quiet) { printf("Virscan \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } IsVirus = VirScanFile(temp); } if (IsVirus) { WriteError("Virus found"); if (!do_quiet) printf("\nVirus found\n"); die(FTNERR_VIRUS_FOUND); } if ((unarc = unpacker(File))) { if (strlen(area.Archiver) && (strcmp(unarc, area.Archiver) == 0)) MustRearc = TRUE; UnPacked = UnpackFile(temp); if (!UnPacked) die(FTNERR_INIT_ERROR); } if (!do_quiet) { printf("Checking \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } memset(&f_db, 0, sizeof(f_db)); strcpy(f_db.Uploader, CFG.sysop_name); f_db.UploadDate = time(NULL); if (do_annon) f_db.Announced = TRUE; if (UnPacked) { /* * Try to get a FILE_ID.DIZ */ fileid = calloc(PATH_MAX, sizeof(char)); snprintf(temp, PATH_MAX, "%s/tmp/arc%d", getenv("FTND_ROOT"), (int)getpid()); snprintf(fileid, PATH_MAX, "FILE_ID.DIZ"); if (getfilecase(temp, fileid)) { snprintf(temp, PATH_MAX, "%s/tmp/arc%d/%s", getenv("FTND_ROOT"), (int)getpid(), fileid); snprintf(temp2, PATH_MAX, "%s/tmp/FILE_ID.DIZ", getenv("FTND_ROOT")); if (file_cp(temp, temp2) == 0) { File_Id = TRUE; } } free(fileid); if (File_Id) { Syslog('f', "FILE_ID.DIZ found"); if ((fp = fopen(temp2, "r"))) { /* * Read no more then 25 lines */ while (((fgets(Desc, 255, fp)) != NULL) && (File_id_cnt < 25)) { lines++; /* * Check if the FILE_ID.DIZ is in a normal layout. * This should be max. 10 lines of max. 48 characters. * We check at 51 characters and if the lines are longer, * we discard the FILE_ID.DIZ file. */ if (strlen(Desc) > 51) { File_id_cnt = 0; File_Id = FALSE; Syslog('!', "Discarding illegal formated FILE_ID.DIZ"); break; } if (strlen(Desc)) { if (strlen(Desc) > 48) Desc[48] = '\0'; j = 0; for (i = 0; i < strlen(Desc); i++) { if ((Desc[i] >= ' ') || (Desc[i] < 0)) { f_db.Desc[File_id_cnt][j] = Desc[i]; j++; } } File_id_cnt++; } } fclose(fp); unlink(temp2); /* * Strip empty lines at end of FILE_ID.DIZ */ while ((strlen(f_db.Desc[File_id_cnt-1]) == 0) && (File_id_cnt)) File_id_cnt--; Syslog('f', "Got %d FILE_ID.DIZ lines", File_id_cnt); for (i = 0; i < File_id_cnt; i++) Syslog('f', "\"%s\"", f_db.Desc[i]); } } } if (!File_id_cnt) { if (Description == NULL) { WriteError("No FILE_ID.DIZ and no description on the commandline"); if (!do_quiet) printf("\nNo FILE_ID.DIZ and no description on the commandline\n"); clean_tmpwork(); die(FTNERR_COMMANDLINE); } else { /* * Create description from the commandline. */ if (strlen(Description) < 48) { /* * Less then 48 chars, copy and ready. */ strcpy(f_db.Desc[0], Description); File_id_cnt++; } else { /* * More then 48 characters, break into multiple * lines not longer then 48 characters. */ memset(&TDesc, 0, sizeof(TDesc)); strcpy(TDesc, Description); while (strlen(TDesc) > 48) { j = 48; while (TDesc[j] != ' ') j--; strncat(f_db.Desc[File_id_cnt], TDesc, j); File_id_cnt++; k = strlen(TDesc); j++; /* Correct space */ for (i = 0; i <= k; i++, j++) TDesc[i] = TDesc[j]; } strcpy(f_db.Desc[File_id_cnt], TDesc); File_id_cnt++; } } } /* * Import the file. */ chdir(pwd); clean_tmpwork(); /* * Work out the kind of filename, is it a long filename * or a 8.3 DOS filename. The file on disk must become * 8.3 for import. */ if (is_real_8_3(File)) { Syslog('f', "Adopt, file is 8.3"); strcpy(f_db.Name, File); strcpy(f_db.LName, File); for (i = 0; i < strlen(File); i++) if (isupper(f_db.LName[i])) f_db.LName[i] = tolower(f_db.LName[i]); } else { Syslog('f', "Adopt, file is LFN"); strcpy(temp2, File); name_mangle(temp2); if (rename(File, temp2)) { Syslog('+', "Can't rename %s to %s", File, temp2); if (!do_quiet) printf("\nCan't rename %s to %s\n", File, temp2); die(FTNERR_GENERAL); } strcpy(f_db.Name, temp2); strcpy(f_db.LName, File); } f_db.Size = file_size(f_db.Name); f_db.Crc32 = file_crc(f_db.Name, TRUE); f_db.FileDate = file_time(f_db.Name); snprintf(temp2, PATH_MAX, "%s/%s", area.Path, f_db.Name); if (!do_quiet) { printf("Adding \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } if (strcmp(f_db.Name, f_db.LName)) { lname = calloc(PATH_MAX, sizeof(char)); snprintf(lname, PATH_MAX, "%s/%s", area.Path, f_db.LName); if (AddFile(f_db, Area, temp2, f_db.Name, lname) == FALSE) { die(FTNERR_GENERAL); } free(lname); } else { if (AddFile(f_db, Area, temp2, File, NULL) == FALSE) { die(FTNERR_GENERAL); } } Syslog('+', "File %s added to area %d", File, Area); if (MustRearc) { /* Here we should call the rearc function */ } free(pwd); free(temp2); free(temp); free(tmpdir); } else { WriteError("Area %d is not available", Area); if (!do_quiet) printf("\nArea %d is not available\n", Area); } if (!do_quiet) { printf("\r \r"); fflush(stdout); } }
/* * Return values: * 0 - Success * 1 - Some error * 2 - Orphaned tic */ int ProcessTic(fa_list **sbl, orphans **opl) { int First, Listed = FALSE, DownLinks = 0, MustRearc = FALSE; int UnPacked = FALSE, IsArchive = FALSE, rc, i, j, k; char *Temp, *unarc = NULL, *cmd = NULL; char temp1[PATH_MAX], temp2[PATH_MAX], sbe[24], TDesc[1024]; unsigned int crc, crc2, Kb; sysconnect Link; FILE *fp; struct utimbuf ut; int BBS_Imp = FALSE, DidBanner = FALSE; faddr *p_from; qualify *qal = NULL, *tmpq; orphans *topl; if (TIC.TicIn.PathError) { WriteError("Our Aka is in the path"); tic_bad++; return 1; } Temp = calloc(PATH_MAX, sizeof(char)); if (!do_quiet) { mbse_colour(LIGHTGREEN, BLACK); printf("Checking \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } if (TIC.Orphaned) { fill_orphans(opl, TIC.TicName, TIC.TicIn.Area, TIC.TicIn.File, TRUE, FALSE); Syslog('+', "File not in inbound: %s", TIC.TicIn.File); free(Temp); return 2; } snprintf(Temp, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File); 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 { /* * No filesize in TIC file, add filesize. */ 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); fill_orphans(opl, TIC.TicName, TIC.TicIn.Area, TIC.TicIn.File, FALSE, TRUE); if (check_crc) { Syslog('+', "Bad CRC, will check this ticfile later"); free(Temp); return 1; } else { Syslog('!', "CRC: error, recalculating crc"); ReCalcCrc(Temp); } } } 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); tidy_faddr(p_from); return 1; } 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; } } 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; } } if (!Listed) { Bad((char *)"%s NOT connected to %s", aka2str(TIC.Aka), TIC.TicIn.Area); free(Temp); return 1; } } 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; } } 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; } } if (Magic_DeleteFile()) { snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicName); file_rm(temp1); Syslog('+', "Deleted file %s", temp1); file_rm(Temp); free(Temp); return 0; } if (Magic_MoveFile()) { if (!SearchTic(TIC.TicIn.Area)) { Bad((char *)"Unknown Area: %s", TIC.TicIn.Area); free(Temp); return 1; } } 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 { snprintf(Temp, PATH_MAX, "%s/etc/fareas.data", getenv("MBSE_ROOT")); if ((fp = fopen(Temp, "r")) == NULL) { WriteError("Can't access fareas.data area: %ld", tic.FileArea); free(Temp); return 1; } 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; } fclose(fp); strcpy(TIC.BBSpath, area.Path); strcpy(TIC.BBSdesc, area.Name); /* * If the File area has a special announce group, change * the group to that name. */ 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)) { snprintf(Temp, PATH_MAX, "%s%s", TIC.TicIn.Area, TIC.TicIn.Crc); 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; } } /* * Count the actual downlinks for this area and build the list of * systems qualified to receive this file. */ First = TRUE; while (GetTicSystem(&Link, First)) { First = FALSE; if ((Link.aka.zone) && (Link.sendto) && (!Link.pause)) { DownLinks++; p_from = fido2faddr(Link.aka); if (TIC.TicIn.Hatch) { fill_qualify(&qal, Link.aka, FALSE, in_list(p_from, sbl, TRUE)); } else { fill_qualify(&qal, Link.aka, ((TIC.Aka.zone == Link.aka.zone) && (TIC.Aka.net == Link.aka.net) && (TIC.Aka.node == Link.aka.node) && (TIC.Aka.point == Link.aka.point)), in_list(p_from, sbl, TRUE)); } tidy_faddr(p_from); } } 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. */ if (strlen(tic.Convert) || tic.FileId || tic.ConvertAll || strlen(tic.Banner)) { /* * Create tmp workdir */ if (create_tmpwork()) { free(Temp); tidy_qualify(&qal); return 1; } if ((unarc = unpacker(TIC.TicIn.File)) == NULL) Syslog('+', "Unknown archive format %s", TIC.TicIn.File); else { IsArchive = TRUE; if ((strlen(tic.Convert) && (strcmp(unarc, tic.Convert) == 0)) || (tic.ConvertAll)) MustRearc = TRUE; } } /* * 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)) { snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File); snprintf(temp2, PATH_MAX, "%s/%s", CFG.ticout, TIC.TicIn.File); if ((rc = file_cp(temp1, temp2) == 0)) { TIC.SendOrg = TRUE; } else { WriteError("Copy %s to %s failed: %s", temp1, temp2, strerror(rc)); } } if (MustRearc && IsArchive) { snprintf(temp2, PATH_MAX, "%s/tmp/arc%d", getenv("MBSE_ROOT"), (int)getpid()); if (!checkspace(temp2, TIC.TicIn.File, UNPACK_FACTOR)) { Bad((char *)"Not enough free diskspace left"); free(Temp); tidy_qualify(&qal); clean_tmpwork(); return 1; } if (chdir(temp2) != 0) { WriteError("$Can't change to %s", temp2); free(Temp); tidy_qualify(&qal); clean_tmpwork(); return 1; } if (!getarchiver(unarc)) { WriteError("Can't get archiver for %s", unarc); chdir(TIC.Inbound); free(Temp); tidy_qualify(&qal); clean_tmpwork(); return 1; } if (strlen(archiver.funarc) == 0) { Syslog('!', "No unarc command available"); } else { cmd = xstrcpy(archiver.funarc); snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File); if (execute_str(cmd, temp1, (char *)NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null") == 0) { UnPacked = TRUE; } else { chdir(TIC.Inbound); Bad((char *)"Archive maybe corrupt"); free(Temp); clean_tmpwork(); return 1; } free(cmd); } } /* * Scan file for viri. */ if (tic.VirScan) { snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File); if (!do_quiet) { printf("Virscan \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } if (VirScanFile(temp1)) { chdir(TIC.Inbound); Bad((char *)"Possible virus found!"); free(Temp); tidy_qualify(&qal); clean_tmpwork(); return 1; } if (!do_quiet) { printf("Checking \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } } if (tic.FileId && tic.FileArea && IsArchive) { if (UnPacked) { 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")); } else { Syslog('f', "Didn't find a FILE_ID.DIZ"); } } else { if (!getarchiver(unarc)) { chdir(TIC.Inbound); } else { cmd = xstrcpy(archiver.iunarc); if (cmd == NULL) { WriteError("No unarc command available"); } else { snprintf(temp1, PATH_MAX, "%s/tmp", getenv("MBSE_ROOT")); chdir(temp1); snprintf(temp1, PATH_MAX, "%s/%s FILE_ID.DIZ", TIC.Inbound, TIC.TicIn.File); if (execute_str(cmd, temp1, (char *)NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null")) { snprintf(temp1, PATH_MAX, "%s/%s file_id.diz", TIC.Inbound, TIC.TicIn.File); execute_str(cmd, temp1, (char *)NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null"); } free(cmd); } } /* 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 */ /* * Now check if other (older) ticfiles point to this file, * if found mark it to purge later. */ for (topl = *opl; topl; topl = topl->next) { if ((strcmp(topl->Area, TIC.TicIn.Area) == 0) && (strcmp(topl->FileName, TIC.TicIn.File) == 0)) { topl->Purged = TRUE; } } /* * Rearc file if it is an unpacked archive. */ if ((MustRearc) && (UnPacked) && (tic.FileArea)) { if (Rearc(tic.Convert)) { /* * Get new filesize for import and announce */ snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile); 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() */ } /* * Change banner if needed. */ if ((strlen(tic.Banner)) && IsArchive) { cmd = xstrcpy(archiver.barc); if ((cmd == NULL) || (!strlen(cmd))) { Syslog('+', "No banner command for %s", archiver.name); } else { snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile); snprintf(Temp, PATH_MAX, "%s/etc/%s", getenv("MBSE_ROOT"), tic.Banner); if (execute_str(cmd, temp1, (char *)NULL, Temp, (char *)"/dev/null", (char *)"/dev/null")) { WriteError("Changing the banner failed"); } else { 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; } } } clean_tmpwork(); chdir(TIC.Inbound); /* * If the file is converted, we set the date of the original * received file as the file creation date. */ snprintf(Temp, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile); if ((MustRearc || DidBanner) && CFG.ct_KeepDate) { if ((tic.Touch) && (tic.FileArea)) { ut.actime = mktime(localtime(&TIC.FileDate)); ut.modtime = mktime(localtime(&TIC.FileDate)); utime(Temp, &ut); Syslog('-', "Restamp filedate %s to %s", Temp, rfcdate(ut.modtime)); } } /* * Now make sure the file timestamp is updated. The file may be restamped, * altered by banners etc. */ TIC.FileDate = file_time(Temp); /* * If not passthru, import in the BBS. */ if (tic.FileArea) { Syslog('+', "Import: %s (%s) Area: %s", TIC.NewFile, TIC.NewFullName, TIC.TicIn.Area); BBS_Imp = Add_BBS(&qal); if (!BBS_Imp) { Bad((char *)"File Import Error"); free(Temp); tidy_qualify(&qal); clean_tmpwork(); return 1; } } chdir(TIC.Inbound); /* * Create file announce record */ if (tic.FileArea) { if (strlen(TIC.TicIn.Magic)) magic_update(TIC.TicIn.Magic, TIC.NewFile); else Magic_UpDateAlias(); for (i = 0; i < TIC.File_Id_Ct; i++) strncpy(T_File.LDesc[i], TIC.File_Id[i], 48); T_File.TotLdesc = TIC.File_Id_Ct; T_File.Announce = tic.Announce; strncpy(T_File.Name, TIC.NewFile, 12); strncpy(T_File.LName, TIC.NewFullName, 80); T_File.Fdate = TIC.FileDate; Add_ToBeRep(T_File); } 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. */ snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File); if (file_rm(temp1) == 0) Syslog('f', "Deleted %s", temp1); } if (DownLinks) { First = TRUE; /* * Add all our system aka's to the seenby lines in the same zone, * omit aka's already in the seenby list. */ for (i = 0; i < 39; i++) { if (CFG.akavalid[i] && (tic.Aka.zone == CFG.aka[i].zone)) { p_from = fido2faddr(CFG.aka[i]); if (! in_list(p_from, sbl, TRUE)) { 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); fill_list(sbl, sbe, NULL); } tidy_faddr(p_from); } } /* * Add seen-by lines for all systems that will receive this file. */ for (tmpq = qal; tmpq; tmpq = tmpq->next) { if (tmpq->send) { 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); fill_list(sbl, sbe, NULL); } } uniq_list(sbl); sort_list(sbl); /* * Now forward this file to the qualified downlinks. */ for (tmpq = qal; tmpq; tmpq = tmpq->next) { if (tmpq->send) { ForwardFile(tmpq->aka, *sbl); tic_out++; } } } Magic_ExecCommand(); Magic_CopyFile(); Magic_UnpackFile(); Magic_AdoptFile(); snprintf(Temp, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicName); if (unlink(Temp)) { WriteError("$Can't delete %s", Temp); } free(Temp); tidy_qualify(&qal); return 0; }
/* * Returns > 0 if error, 0 if ok. */ int LoadTic(char *inb, char *tfn, orphans **opl) { FILE *tfp; char *Temp, *Temp2, *Buf, *Log = NULL, RealName[256]; int i, j, rc, bufsize, DescCnt = FALSE; fa_list *sbl = NULL; if (CFG.slow_util && do_quiet) msleep(1); memset(&RealName, 0, sizeof(RealName)); memset(&TIC, 0, sizeof(TIC)); memset(&T_File, 0, sizeof(T_File)); snprintf(TIC.Inbound, PATH_MAX, "%s", inb); strncpy(TIC.TicName, tfn, 12); chdir(inb); if ((tfp = fopen(tfn, "r")) == NULL) { WriteError("$Cannot open %s", tfn); return 1; } /* * Although a TIC line may only be 255 characters long, * nobody seems to care and lines are up to 1024 characters * long. */ if (PATH_MAX > 1024) bufsize = PATH_MAX; else bufsize = 1024; Temp = calloc(bufsize+1, sizeof(char)); Buf = calloc(bufsize+1, sizeof(char)); while ((fgets(Buf, bufsize, tfp)) != NULL) { if (strlen(Buf) == bufsize) Syslog('!', "Detected a TIC file line of %d characters long", bufsize); /* * Remove all garbage from this tic line. */ Temp[0] = '\0'; j = 0; for (i = 0; i < strlen(Buf); i++) { if (isprint(Buf[i] & 0x7f)) { Temp[j] = Buf[i] & 0x7f; j++; } } Temp[j] = '\0'; if (strncasecmp(Temp, "hatch", 5) == 0) { TIC.TicIn.Hatch = TRUE; } else if (TIC.TicIn.Hatch && (strncasecmp(Temp, "pth ", 4) == 0)) { strncpy(TIC.TicIn.Pth, Temp+4, PATH_MAX); } else if (strncasecmp(Temp, "area ", 5) == 0) { strncpy(TIC.TicIn.Area, Temp+5, 20); strncpy(T_File.Echo, Temp+5, 20); } else if (strncasecmp(Temp, "origin ", 7) == 0) { strncpy(TIC.TicIn.Origin, Temp+7, 80); strncpy(T_File.Origin, Temp+7, 23); } else if (strncasecmp(Temp, "from ", 5) == 0) { strncpy(TIC.TicIn.From, Temp+5, 80); strncpy(T_File.From, Temp+5, 23); } else if (strncasecmp(Temp, "file ", 5) == 0) { strncpy(TIC.TicIn.File, Temp+5, 80); for (i = 0; i < strlen(TIC.TicIn.File); i++) TIC.TicIn.File[i] = toupper(TIC.TicIn.File[i]); } else if (strncasecmp(Temp, "fullname ", 9) == 0) { strncpy(TIC.TicIn.FullName, Temp+9, 80); } else if (strncasecmp(Temp, "created ", 8) == 0) { strncpy(TIC.TicIn.Created, Temp+8, 80); } else if (strncasecmp(Temp, "magic ", 6) == 0) { strncpy(TIC.TicIn.Magic, Temp+6, 20); strncpy(T_File.Magic, Temp+6, 20); } else if (strncasecmp(Temp, "crc ", 4) == 0) { TIC.Crc_Int = strtoul(Temp+4, (char **)NULL, 16); snprintf(TIC.TicIn.Crc, 9, "%08X", TIC.Crc_Int); strncpy(T_File.Crc, TIC.TicIn.Crc, 8); } else if (strncasecmp(Temp, "pw ", 3) == 0) { strncpy(TIC.TicIn.Pw, Temp+3, 20); } else if (strncasecmp(Temp, "replaces ", 9) == 0) { strncpy(TIC.TicIn.Replace, Temp+9, 80); strncpy(T_File.Replace, Temp+9, 80); } else if (strncasecmp(Temp, "desc ", 5) == 0) { if (!DescCnt) { strncpy(TIC.TicIn.Desc, Temp+5, 1023); strncpy(T_File.Desc, TIC.TicIn.Desc, 255); DescCnt = TRUE; } else { Syslog('!', "More than one \"Desc\" line"); } } else if (strncasecmp(Temp, "path ", 5) == 0) { if (strchr(Temp+5, ':') && strchr(Temp+5, '/')) { strncpy(TIC.TicIn.Path[TIC.TicIn.TotPath], Temp+5, 80); TIC.TicIn.TotPath++; TIC.Aka.zone = atoi(strtok(Temp+5, ":")); TIC.Aka.net = atoi(strtok(NULL, "/")); TIC.Aka.node = atoi(strtok(NULL, "\0")); for (i = 0; i < 40; i++) if ((CFG.akavalid[i]) && (CFG.aka[i].zone == TIC.Aka.zone) && (CFG.aka[i].net == TIC.Aka.net) && (CFG.aka[i].node == TIC.Aka.node) && (!CFG.aka[i].point)) { TIC.TicIn.PathError = TRUE; Syslog('+', "Aka %d: %s in path", i + 1, aka2str(CFG.aka[i])); } } else { WriteError("No valid AKA in Path line: \"%s\"", printable(Temp, 0)); WriteError("Report this to author of that program"); } } else if (strncasecmp(Temp, "seenby ", 7) == 0) { if (strchr(Temp+7, ':') && strchr(Temp+7, '/')) { fill_list(&sbl, Temp+7, NULL); } else { WriteError("No valid AKA in Seenby line: \"%s\"", printable(Temp, 0)); } } else if (strncasecmp(Temp, "areadesc ", 9) == 0) { strncpy(TIC.TicIn.AreaDesc, Temp+9, 60); } else if (strncasecmp(Temp, "to ", 3) == 0) { /* * Drop this one * FIXME: should check if this is for us. */ } else if (strncasecmp(Temp, "size ", 5) == 0) { TIC.TicIn.Size = atoi(Temp+5); } else if (strncasecmp(Temp, "date ", 5) == 0) { /* * Drop this one (HTick writes these) */ } else if (strncasecmp(Temp, "cost ", 5) == 0) { TIC.TicIn.Cost = atoi(Temp+5); } else if (strncasecmp(Temp, "ldesc ", 6) == 0) { if (TIC.TicIn.TotLDesc < 25) { strncpy(TIC.TicIn.LDesc[TIC.TicIn.TotLDesc], Temp+6, 80); TIC.TicIn.TotLDesc++; } else { Syslog('f', "Too many LDesc lines in TIC file"); } } else if (strncasecmp(Temp, "destination ", 12) == 0) { /* * Drop this one */ } else { /* * If we didn't find a matching keyword it is a line we * will just remember and forward if there are downlinks. */ if (strlen(Temp) > 127) { Syslog('+', "Unknown too long TIC line dropped"); } else if (TIC.TicIn.Unknowns < 25) { strncpy(TIC.TicIn.Unknown[TIC.TicIn.Unknowns], Temp, 127); TIC.TicIn.Unknowns++; } } } fclose(tfp); /* * Do some basic checks on the loaded ticfile. */ if ( (strlen(TIC.TicIn.File) == 0) || (strlen(TIC.TicIn.Area) == 0) || (strlen(TIC.TicIn.From) == 0) || (strlen(TIC.TicIn.Origin) == 0)) { WriteError("TIC file %s misses important information", TIC.TicName); tidy_falist(&sbl); mover(TIC.TicName); tic_in++; tic_bad++; return 1; } if (TIC.TicIn.TotLDesc) { /* * First check for a bug in Harald Harms Allfix program that * lets Allfix forward dummy Ldesc lines with the contents: * "Long description not available" */ if (strstr(TIC.TicIn.LDesc[0], "ion not avail") != NULL) { Syslog('!', "Killing invalid Ldesc line(s)"); TIC.TicIn.TotLDesc = 0; } } if (TIC.TicIn.TotLDesc) { T_File.TotLdesc = TIC.TicIn.TotLDesc; for (i = 0; i < TIC.TicIn.TotLDesc; i++) { strncpy(T_File.LDesc[i], TIC.TicIn.LDesc[i], 48); } } /* * Show on screen what we are doing */ if (!do_quiet) { ftnd_colour(CYAN, BLACK); printf("\r"); for (i = 0; i < 79; i++) printf(" "); printf("\rTic: %12s File: %-14s Area: %-12s ", TIC.TicName, TIC.TicIn.File, TIC.TicIn.Area); fflush(stdout); } /* * Show in logfile what we are doing */ Syslog('+', "Processing %s, %s area %s from %s", TIC.TicName, TIC.TicIn.File, TIC.TicIn.Area, TIC.TicIn.From); Syslog('+', "+- %s", TIC.TicIn.Created); Log = NULL; if (strlen(TIC.TicIn.Replace)) { Log = xstrcpy((char *)"Replace "); Log = xstrcat(Log, TIC.TicIn.Replace); } if (strlen(TIC.TicIn.Magic)) { if (Log != NULL) Log = xstrcat(Log, (char *)", Magic "); else Log = xstrcpy((char *)"Magic "); Log = xstrcat(Log, TIC.TicIn.Magic); } if (Log != NULL) { Syslog('+', "%s", Log); free(Log); Log = NULL; } strcpy(Temp, TIC.TicIn.From); TIC.Aka.zone = atoi(strtok(Temp, ":")); TIC.Aka.net = atoi(strtok(NULL, "/")); TIC.Aka.node = atoi(strtok(NULL, "@\0")); if (SearchFidonet(TIC.Aka.zone)) strcpy(TIC.Aka.domain, fidonet.domain); strcpy(Temp, TIC.TicIn.Origin); TIC.OrgAka.zone = atoi(strtok(Temp, ":")); TIC.OrgAka.net = atoi(strtok(NULL, "/")); TIC.OrgAka.node = atoi(strtok(NULL, "@\0")); if (SearchFidonet(TIC.OrgAka.zone)) strcpy(TIC.OrgAka.domain, fidonet.domain); Temp2 = calloc(PATH_MAX, sizeof(char)); if (TIC.TicIn.Hatch) { /* * Try to move the hatched file to the inbound */ snprintf(Temp, bufsize, "%s/%s", TIC.TicIn.Pth, TIC.TicIn.FullName); if (file_exist(Temp, R_OK) == 0) { strcpy(RealName, TIC.TicIn.FullName); } else { WriteError("Can't find %s", Temp); tidy_falist(&sbl); return 2; } snprintf(Temp2, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.FullName); if ((rc = file_mv(Temp, Temp2))) { WriteError("Can't move %s to inbound: %s", Temp, strerror(rc)); tidy_falist(&sbl); return 1; } if (!strlen(TIC.TicIn.File)) { strcpy(Temp, TIC.TicIn.FullName); name_mangle(Temp); strncpy(TIC.TicIn.File, Temp, 12); Syslog('f', "Local hatch created 8.3 name %s", Temp); } } else { /* * Find out what the real name of the file is, * most likely this is a 8.3 filename. */ strncpy(RealName, TIC.TicIn.File, 255); Syslog('f', "getfilecase(%s, %s)", TIC.Inbound, RealName); if (! getfilecase(TIC.Inbound, RealName)) { strncpy(RealName, TIC.TicIn.FullName, 255); Syslog('f', "getfilecase(%s, %s)", TIC.Inbound, RealName); if (! getfilecase(TIC.Inbound, RealName)) { memset(&RealName, 0, sizeof(RealName)); } } } if (strlen(RealName) == 0) { /* * We leave RealName empty, the ProcessTic function * will handle this orphaned tic file. */ TIC.Orphaned = TRUE; Syslog('+', "Can't find file in inbound, will check later"); } else { /* * If no LFN received in the ticfile and the file in the inbound is the same as the 8.3 name * but only the case is different, then treat the real filename as LFN. */ if ((strlen(TIC.TicIn.FullName) == 0) && strcmp(TIC.TicIn.File, RealName) && (strcasecmp(TIC.TicIn.File, RealName) == 0)) { Syslog('f', "Real filename possible LFN, faking it"); strcpy(TIC.TicIn.FullName, RealName); } Syslog('f', "Real filename in inbound is \"%s\"", RealName); if ((strlen(TIC.TicIn.FullName)) == 0) { Syslog('f', "LFN is empty, create lowercase one"); strncpy(TIC.TicIn.FullName, RealName, 255); for (i = 0; i < strlen(TIC.TicIn.FullName); i++) TIC.TicIn.FullName[i] = tolower(TIC.TicIn.FullName[i]); } Syslog('+', "8.3 name \"%s\", LFN \"%s\"", TIC.TicIn.File, TIC.TicIn.FullName); if (strcmp(RealName, TIC.TicIn.File)) { /* * File in inbound has not the same name as the name on disk. * It may be a LFN but also a case difference. The whole tic * processing is based on 8.3 filenames. */ snprintf(Temp, bufsize, "%s/%s", TIC.Inbound, RealName); snprintf(Temp2, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File); if (rename(Temp, Temp2)) WriteError("$Can't rename %s to %s", Temp, Temp2); else Syslog('f', "Renamed %s to %s", Temp, Temp2); } } strncpy(TIC.NewFile, TIC.TicIn.File, 80); strncpy(TIC.NewFullName, TIC.TicIn.FullName, 255); free(Temp2); free(Temp); free(Buf); tic_in++; rc = ProcessTic(&sbl, opl); tidy_falist(&sbl); return rc; }