Пример #1
0
void Help(void)
{
    do_quiet = FALSE;
    ProgName();

    ftnd_colour(LIGHTCYAN, BLACK);
    printf("Usage:	ftnfile [command] <options>\n\n");
    ftnd_colour(LIGHTBLUE, BLACK);
    printf("	Commands are:\n\n");
    ftnd_colour(CYAN, BLACK);
    printf("	a  adopt <area> <file> \"[desc]\"	Adopt file to area\n");
    printf("	c  check [area]			Check filebase\n");
    printf("	d  delete <area> \"<filemask>\"	Mark file(s) in area for deletion\n");
    printf("	im import <area>		Import files in current dir to area\n");
    printf("	in index			Create filerequest index\n");
    printf("	k  kill				Kill/move old files\n");
    printf("	l  list	[area]			List file areas or one area\n");
    printf("	m  move <from> <to> <file>	Move file from to area\n");
    printf("	p  pack				Pack filebase\n");
    printf("	r  rearc <area> \"<filemask>\"	Rearc file(s) in area to area archive type\n");
    printf("	s  sort <area>			Sort files in a file area\n");
    printf("	t  toberep			Show toberep database\n");
    printf("	u  undelete <area> \"<filemask>\"	Mark file(s) in area for undeletion\n");
    ftnd_colour(LIGHTBLUE, BLACK);
    printf("\n	Options are:\n\n");
    ftnd_colour(CYAN, BLACK);
    printf("	-a -announce			Suppress announce added files\n");
    printf("	-f -force			Force file overwrite\n");
    printf("	-q -quiet			Quiet mode\n");
    printf("	-v -virus			Suppress virus scanning, use with care\n");
    die(FTNERR_COMMANDLINE);
}
Пример #2
0
void ProgName(void)
{
    if (do_quiet)
	return;

    ftnd_colour(WHITE, BLACK);
    printf("\nFTNDAFF: FTNd %s Announce new files and FileFind\n", VERSION);
    ftnd_colour(YELLOW, BLACK);
    printf("       %s\n", COPYRIGHT);
}
Пример #3
0
void ProgName(void)
{
    if (do_quiet)
        return;

    ftnd_colour(WHITE, BLACK);
    printf("\nFTNFILE: FTNd %s File maintenance utility\n", VERSION);
    ftnd_colour(YELLOW, BLACK);
    printf("        %s\n", COPYRIGHT);
}
Пример #4
0
/*
 * Toss one packet.
 *
 *  0  - 
 *  1  - Cannot open packet
 *  2  - Bad packet header
 *  3  - Packet is not for us
 *  4  - Bad password
 */
int TossPkt(char *fn)
{
	int		rc, count = 0; 
	static int	maxrc = 0;
	static faddr	from, to;
	FILE		*pkt;

	if (!do_quiet) {
		ftnd_colour(LIGHTGREEN, BLACK);
		printf("Tossing packet %s\n", fn);
	}

	if ((pkt = fopen(fn, "r")) == 0) {
		WriteError("$Cannot open %s", fn);
		return 1;
	}

	memset(&from, 0, sizeof(faddr));
	memset(&to,   0, sizeof(faddr));

	if (((rc = getheader(&from, &to, pkt, fn, FALSE)) != 0)) {
		WriteError("%s, aborting",
				(rc == 1)?"wrong header type":
				(rc == 2)?"bad packet header":
				(rc == 3)?"packet is not for us":
				(rc == 4)?"bad password":
				"******");
		fclose(pkt);
		return(rc);
	}

	while ((rc = getmessage(pkt, &from, &to)) == 1) {
		count++;
	}
	Syslog('+', "Messages : %d", count);

	maxrc = rc;
	if (!do_quiet)
		printf("\r                                                    \r");

	if (rc)
		Syslog('+', "End, rc=%d", maxrc);

	fclose(pkt);
	return maxrc;
}
Пример #5
0
void die(int onsig)
{
    /*
     * First check if a child is running, if so, kill it.
     */
    if (e_pid) {
        if ((kill(e_pid, SIGTERM)) == 0)
            Syslog('+', "SIGTERM to pid %d succeeded", e_pid);
        else {
            if ((kill(e_pid, SIGKILL)) == 0)
                Syslog('+', "SIGKILL to pid %d succeded", e_pid);
            else
                WriteError("$Failed to kill pid %d", e_pid);
        }

        /*
         * In case the child had the tty in raw mode...
         */
        if (!do_quiet)
            execute_pth((char *)"stty", (char *)"sane", (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null");
    }

    signal(onsig, SIG_IGN);

    if (onsig) {
        if (onsig <= NSIG)
            WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]);
        else
            WriteError("Terminated with error %d", onsig);
    }

    clean_tmpwork();
    ulockprogram((char *)"ftnfile");
    t_end = time(NULL);
    Syslog(' ', "FTNFILE finished in %s", t_elapsed(t_start, t_end));

    if (!do_quiet) {
        ftnd_colour(LIGHTGRAY, BLACK);
        fflush(stdout);
    }
    ExitClient(onsig);
}
Пример #6
0
void die(int onsig)
{
    signal(onsig, SIG_IGN);

    if (onsig) {
	if (onsig <= NSIG)
	    WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]);
	else
	    WriteError("Terminated with error %d", onsig);
    }

    ulockprogram((char *)"ftnaff");
    t_end = time(NULL);
    Syslog(' ', "FTNDAFF finished in %s", t_elapsed(t_start, t_end));

    if (!do_quiet) {
	ftnd_colour(LIGHTGRAY, BLACK);
	printf("\n");
    }
    ExitClient(onsig);
}
Пример #7
0
void Help(void)
{
	do_quiet = FALSE;
	ProgName();

	ftnd_colour(LIGHTMAGENTA, BLACK);
	printf("\nUsage:	ftnaff [command] <options>\n\n");
	ftnd_colour(LIGHTBLUE, BLACK);
	printf("	Commands are:\n\n");
	ftnd_colour(CYAN, BLACK);
	printf("	a  announce	Announce new files\n");
	printf("	f  filefind	FileFind service\n");
	ftnd_colour(LIGHTBLUE, BLACK);
	printf("\n	Options are:\n\n");
	ftnd_colour(CYAN, BLACK);
	printf("	-q -quiet	Quiet mode\n");
	ftnd_colour(LIGHTGRAY, BLACK);
	printf("\n");
	die(FTNERR_COMMANDLINE);
}
Пример #8
0
/*
 * Delete a file
 */
void Delete(int UnDel, int Area, char *File)
{
    char		mask[256];
    int			rc = FALSE;
    struct _fdbarea	*fdb_area = NULL;

    if (UnDel)
	IsDoing("Undelete file");
    else
	IsDoing("Delete file");
    ftnd_colour(LIGHTRED, BLACK);

    /*
     * Check area
     */
    if (LoadAreaRec(Area) == FALSE) {
	WriteError("Can't load record %d", Area);
	die(FTNERR_INIT_ERROR);
    }
    if (!area.Available) {
	WriteError("Area %d not available", Area);
	if (!do_quiet)
	    printf("Area %d not available\n", Area);
	die(FTNERR_CONFIG_ERROR);
    }

    if ((fdb_area = ftnddb_OpenFDB(Area, 30)) == NULL)
	die(FTNERR_GENERAL);


    ftnd_colour(CYAN, BLACK);
    strcpy(mask, re_mask(File, FALSE));
    if (re_comp(mask))
	die(FTNERR_GENERAL);

    while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
	if (re_exec(fdb.LName) || re_exec(fdb.Name)) {
	    if (UnDel && fdb.Deleted) {
		fdb.Deleted = FALSE;
		Syslog('+', "Marked file %s in area %d for undeletion", fdb.Name, Area);
		if (!do_quiet)
		    printf("Marked file %s in area %d for undeletion\n", fdb.Name, Area);
		rc = TRUE;
	    }
	    if (!UnDel && !fdb.Deleted) {
		fdb.Deleted = TRUE;
		Syslog('+', "Marked file %s in area %d for deletion", fdb.Name, Area);
		if (!do_quiet)
		    printf("Marked file %s in area %d for deletion\n", fdb.Name, Area);
		rc = TRUE;
	    }
	    if (rc) {
		if (ftnddb_LockFDB(fdb_area, 30)) {
		    fseek(fdb_area->fp, - fdbhdr.recsize, SEEK_CUR);
		    fwrite(&fdb, fdbhdr.recsize, 1, fdb_area->fp);
		    ftnddb_UnlockFDB(fdb_area);
		} else {
		    rc = FALSE;
		}
	    }
	}
    }
    ftnddb_CloseFDB(fdb_area);

    if (!rc) {
	Syslog('+', "%selete %s in area %d failed", UnDel?"Und":"D", File, Area);
	if (!do_quiet)
	    printf("%selete %s in area %d failed\n", UnDel?"Und":"D", File, Area);
    }
}
Пример #9
0
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);
    }
}
Пример #10
0
/*
 *  Scan for new news available at the nntp server.
 */
void ScanNews(void)
{
    List		*art = NULL;
    POverview		tmp, old;
    FILE		*pAreas;
    char		*sAreas;
    struct msgareashdr	Msgshdr;
    struct msgareas	Msgs;

    IsDoing((char *)"Scan News");
    if (nntp_connect() == -1) {
        WriteError("Can't connect to newsserver");
        return;
    }
    if (get_xoverview()) {
        return;
    }

    if (!do_quiet) {
        ftnd_colour(LIGHTGREEN, BLACK);
        printf("Scan for new news articles\n");
    }

    sAreas = calloc(PATH_MAX, sizeof(char));
    snprintf(sAreas, PATH_MAX, "%s/etc/mareas.data", getenv("FTND_ROOT"));
    if(( pAreas = fopen (sAreas, "r")) == NULL) {
        WriteError("$Can't open Messages Areas File.");
        return;
    }
    fread(&Msgshdr, sizeof(Msgshdr), 1, pAreas);

    while (fread(&Msgs, Msgshdr.recsize, 1, pAreas) == 1) {
        fseek(pAreas, Msgshdr.syssize, SEEK_CUR);
#ifdef USE_NEWSGATE
        if ((Msgs.Active) && strlen(Msgs.Newsgroup)) {
#else
        if ((Msgs.Active) && strlen(Msgs.Newsgroup) && (Msgs.Type == NEWS)) {
#endif
            if (IsSema((char *)"upsalarm")) {
                Syslog('+', "Detected upsalarm semafore, aborting newsscan");
                break;
            }
            Syslog('m', "Scan newsgroup: %s", Msgs.Newsgroup);
            if (!do_quiet) {
                ftnd_colour(CYAN, BLACK);
                printf("\r%-40s", Msgs.Newsgroup);
                fflush(stdout);
            }
            Nopper();
            if (do_one_group(&art, Msgs.Newsgroup, Msgs.Tag, Msgs.MaxArticles) == RETVAL_ERROR)
                break;
            /*
             * To be safe, update the dupes database after each area.
             */
            CloseDupes();
        }
    }
    fclose(pAreas);
    free(sAreas);

    for (tmp = xoverview; tmp; tmp = old) {
        old = tmp->next;
        if (tmp->header)
            free(tmp->header);
        if (tmp->field)
            free(tmp->field);
        free(tmp);
    }

    nntp_close();

    do_flush = TRUE;
    if (!do_quiet)
        printf("\r                                                    \r");
}



int do_one_group(List **art, char *grpname, char *ftntag, int maxarticles)
{
    List    *tmp;
    char    temp[128], *resp;
    int	    retval, fetched = 0;
    int	    total, start, end;

    Syslog('m', "do_one_group(%s, %s)", grpname, ftntag);
    IsDoing((char *)"Scan %s", grpname);
    snprintf(temp, 128, "GROUP %s\r\n", grpname);
    nntp_send(temp);
    resp = nntp_receive();
    retval = atoi(strtok(resp, " "));
    if (retval == 480) {
        /*
         * We must login
         */
        if (nntp_auth() == FALSE) {
            WriteError("Authorisation failure");
            nntp_close();
            return RETVAL_NOAUTH;
        }
        nntp_send(temp);
        resp = nntp_receive();
        retval = atoi(strtok(resp, " "));
    }
    if (retval != 211) {
        if (retval == 411) {
            WriteError("No such newsgroup: %s", grpname);
            return RETVAL_UNEXPECTEDANS;
        }
        WriteError("Unknown response %d to GROUP command", retval);
        return RETVAL_ERROR;
    }

    total = atol(strtok(NULL, " "));
    start = atol(strtok(NULL, " "));
    end   = atol(strtok(NULL, " '\0'"));
    Syslog('m', "GROUP total %d, start %d, end %d, max %d", total, start, end, maxarticles);
    if ((maxarticles) && (total > maxarticles)) {
        start = end - maxarticles;
        total = maxarticles;
        Syslog('m', "NEW:  total %d, start %d, end %d", total, start, end);
    }
    if (!total) {
        Syslog('+', "Fetched 0 articles from %s", grpname);
        return RETVAL_NOARTICLES;
    }

    retval = get_xover(grpname, start, end, art);
    if (retval != RETVAL_OK) {
        tidy_artlist(art);
        return retval;
    }

    if (!do_learn) {
        for (tmp = *art; tmp; tmp = tmp->next) {
            if (!tmp->isdupe) {
                /*
                 *  If the message isn't a dupe, it must be new for us.
                 */
                get_article(tmp->msgid, ftntag);
                fetched++;
            }
        }
    }

    tidy_artlist(art);

    if ((maxarticles) && (fetched == maxarticles))
        Syslog('!', "Warning: the max. articles value in newsgroup %s might be to low", grpname);

    Syslog('+', "Fetched %d article%s from %s", fetched, (fetched == 1) ? "":"s", grpname);
    return RETVAL_OK;
}
Пример #11
0
Файл: tic.c Проект: ftnapps/FTNd
/*
 * 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;
}
Пример #12
0
/*
 *  Sort files database
 */
void SortFileBase(int Area)
{
    FILE    *pAreas;
    int	    iAreas;
    char    *sAreas;
    struct _fdbarea *fdb_area = NULL;
    
    sAreas = calloc(PATH_MAX, sizeof(char));

    IsDoing("Sort filebase");
    if (!do_quiet) {
	ftnd_colour(CYAN, BLACK);
    }

    snprintf(sAreas, PATH_MAX, "%s/etc/fareas.data", getenv("FTND_ROOT"));

    if ((pAreas = fopen (sAreas, "r")) == NULL) {
	WriteError("Can't open %s", sAreas);
	die(FTNERR_INIT_ERROR);
    }

    fread(&areahdr, sizeof(areahdr), 1, pAreas);
    fseek(pAreas, 0, SEEK_END);
    iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize;

    if ((Area < 1) || (Area > iAreas)) {
	if (!do_quiet) {
	    printf("Area must be between 1 and %d\n", iAreas);
	}
    } else {
	fseek(pAreas, ((Area - 1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET);
	fread(&area, areahdr.recsize, 1, pAreas);

	if (area.Available) {

	    if (enoughspace(CFG.freespace) == 0)
		die(FTNERR_DISK_FULL);

	    if (!do_quiet) {
		printf("Sorting area %d: %-44s", Area, area.Name);
		fflush(stdout);
	    }

	    if ((fdb_area = ftnddb_OpenFDB(Area, 30))) {
		ftnddb_SortFDB(fdb_area);
		ftnddb_CloseFDB(fdb_area);
	    }
	    Syslog('+', "Sorted file area %d: %s", Area, area.Name);
	    do_index = TRUE;

	} else {
	    printf("You cannot sort area %d\n", Area);
	}
    }

    fclose(pAreas);

    if (!do_quiet) {
	printf("\r                                                              \r");
	fflush(stdout);
    }

    free(sAreas);
}
Пример #13
0
/*
 * Move a file
 */
void Move(int From, int To, char *File)
{
    char		    *frompath, *topath, *temp1, *fromlink, *tolink, *fromthumb, *tothumb;
    struct FILE_record	    f_db;
    int			    rc = FALSE, Found = FALSE;
    struct _fdbarea	    *src_area = NULL;

    IsDoing("Move file");
    ftnd_colour(LIGHTRED, BLACK);

    if (From == To) {
	WriteError("Area numbers are the same");
	if (!do_quiet)
	    printf("Can't move to the same area\n");
	die(FTNERR_COMMANDLINE);
    }

    /*
     * Check From area
     */
    if (LoadAreaRec(From) == FALSE) {
	WriteError("Can't load record %d", From);
	die(FTNERR_INIT_ERROR);
    }
    if (!area.Available) {
	WriteError("Area %d not available", From);
	if (!do_quiet)
	    printf("Area %d not available\n", From);
	die(FTNERR_COMMANDLINE);
    }
    if (CheckFDB(From, area.Path))
	die(FTNERR_GENERAL);

    /*
     * Find the file in the "from" area, check LFN and 8.3 names.
     */
    if ((src_area = ftnddb_OpenFDB(From, 30)) == NULL)
	die(FTNERR_GENERAL);

    while (fread(&f_db, fdbhdr.recsize, 1, src_area->fp) == 1) {
	if ((strcmp(f_db.LName, File) == 0) || strcmp(f_db.Name, File) == 0) {
	    Found = TRUE;
	    break;
	}
    }
    temp1 = calloc(PATH_MAX, sizeof(char)); // not serious
    if (!Found) {
	WriteError("File %s not found in area %d", File, From);
	if (!do_quiet)
	    printf("File %s not found in area %d\n", File, From);
	free(temp1);
	die(FTNERR_GENERAL);
    }

    frompath = xstrcpy(area.Path);
    frompath = xstrcat(frompath, (char *)"/");
    frompath = xstrcat(frompath, f_db.Name);
    fromlink = xstrcpy(area.Path);
    fromlink = xstrcat(fromlink, (char *)"/");
    fromlink = xstrcat(fromlink, f_db.LName);
    fromthumb = xstrcpy(area.Path);
    fromthumb = xstrcat(fromthumb, (char *)"/.");
    fromthumb = xstrcat(fromthumb, f_db.Name);

    /*
     * Check Destination area
     */
    if (LoadAreaRec(To) == FALSE) {
	WriteError("Can't load record %d", To);
	die(FTNERR_GENERAL);
    }
    if (!area.Available) {
	WriteError("Area %d not available", To);
	if (!do_quiet)
	    printf("Area %d not available\n", To);
	die(FTNERR_GENERAL);
    }
    if (CheckFDB(To, area.Path))
	die(FTNERR_GENERAL);

    topath = xstrcpy(area.Path);
    topath = xstrcat(topath, (char *)"/");
    topath = xstrcat(topath, f_db.Name);
    tolink = xstrcpy(area.Path);
    tolink = xstrcat(tolink, (char *)"/");
    tolink = xstrcat(tolink, f_db.LName);
    tothumb = xstrcpy(area.Path);
    tothumb = xstrcat(tothumb, (char *)"/.");
    tothumb = xstrcat(tothumb, f_db.Name);

    if (file_exist(topath, F_OK) == 0) {
	WriteError("File %s already exists in area %d", File, To);
	if (!do_quiet)
	    printf("File %s already exists in area %d\n", File, To);
	die(FTNERR_COMMANDLINE);
    }

    rc = AddFile(f_db, To, topath, frompath, tolink);
    if (rc) {
	unlink(fromlink);
	unlink(frompath);
	/*
	 * Try to move thumbnail if it exists
	 */
	if (file_exist(fromthumb, R_OK) == 0) {
	    file_mv(fromthumb, tothumb);
	}
    }
    if (ftnddb_LockFDB(src_area, 30)) {
	f_db.Deleted = TRUE;
	fseek(src_area->fp, - fdbhdr.recsize, SEEK_CUR);
	fwrite(&f_db, fdbhdr.recsize, 1, src_area->fp);
	ftnddb_UnlockFDB(src_area);
    }
    ftnddb_PackFDB(src_area);
    ftnddb_CloseFDB(src_area);
    ftnd_colour(CYAN, BLACK);

    Syslog('+', "Move %s from %d to %d %s", File, From, To, rc ? "successfull":"failed");
    if (!do_quiet)
	printf("Move %s from %d to %d %s\n", File, From, To, rc ? "successfull":"failed");

    free(temp1);
    free(frompath);
    free(fromlink);
    free(fromthumb);
    free(topath);
    free(tolink);
    free(tothumb);
}
Пример #14
0
/*
 * 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) {
	ftnd_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("FTND_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("FTND_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("FTND_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("FTND_ROOT"), (int)getpid(), Temp);
		snprintf(temp2, PATH_MAX, "%s/tmp/FILE_ID.DIZ", getenv("FTND_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("FTND_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("FTND_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;
}
Пример #15
0
int Post(char *To, int Area, char *Subj, char *File, char *Flavor)
{
    int		    i, rc = FALSE, has_tear = FALSE, has_origin = FALSE;
    char	    *aka, *temp, *sAreas;
    FILE	    *fp, *tp;
    unsigned int    crc = -1;
    time_t	    tt;
    struct tm	    *t;

    ftnd_CleanSubject(Subj);

    if (!do_quiet) {
	ftnd_colour(CYAN, BLACK);
	printf("Post \"%s\" to \"%s\" in area %d\n", File, To, Area);
    }

    IsDoing("Posting");
    Syslog('+', "Post \"%s\" area %d to \"%s\" flavor %s", File, Area, To, Flavor);
    Syslog('+', "Subject: \"%s\"", Subj);

    if ((tp = fopen(File, "r")) == NULL) {
	WriteError("$Can't open %s", File);
	if (!do_quiet)
	    printf("Can't open \"%s\"\n", File);
	return -1;
    }

    sAreas = calloc(PATH_MAX, sizeof(char));
    snprintf(sAreas, PATH_MAX, "%s/etc/mareas.data", getenv("FTND_ROOT"));
    if ((fp = fopen(sAreas, "r")) == NULL) {
	WriteError("$Can't open %s", sAreas);
	free(sAreas);
	fclose(tp);
	return -1;
    }

    fread(&msgshdr, sizeof(msgshdr), 1, fp);
    if (fseek(fp, (msgshdr.recsize + msgshdr.syssize) * (Area - 1), SEEK_CUR) == 0) {
	if (fread(&msgs, msgshdr.recsize, 1, fp) == 1) {
	    rc = TRUE;
	} else {
	    WriteError("$Can't read area %ld", Area);
	}
    } else {
	WriteError("$Can't seek area %ld", Area);
    }

    free(sAreas);
    if (rc == FALSE) {
	fclose(fp);
	fclose(tp);
	return -1;
    }

    if (!msgs.Active) {
	WriteError("Area %s not active", msgs.Name);
	fclose(fp);
	fclose(tp);
	return -1;
    }

    /*
     * Check the proper syntax in the To parameter, in netmail areas
     * it must have a destination address, in all other areas just a
     * full name.
     */
    if (msgs.Type == NETMAIL) {
	if ((strchr(To, '@') == NULL) || (strstr(To, (char *)".n") == NULL) || (strstr(To, (char *)".z") == NULL)) {
	    WriteError("No address in \"%s\" and area is netmail", To);
	    if (!do_quiet)
		printf("No address in \"%s\" and area is netmail\n", To);
	    fclose(fp);
	    fclose(tp);
	    return -1;
	}
    } else {
	if ((strchr(To, '@')) || (strstr(To, (char *)".n")) || (strstr(To, (char *)".z"))) {
	    WriteError("Address present in \"%s\" and area is not netmail", To);
	    if (!do_quiet)
		printf("Address present in \"%s\" and area is not netmail\n", To);
	    fclose(fp);
	    fclose(tp);
	    return -1;
	}
    }

    if (!Msg_Open(msgs.Base)) {
	WriteError("Can't open %s", msgs.Base);
	fclose(fp);
	fclose(tp);
	return -1;
    }

    if (!Msg_Lock(30L)) {
	WriteError("Can't lock %s", msgs.Base);
	Msg_Close();
	fclose(fp);
	fclose(tp);
	return -1;
    }

    tt = time(NULL);
    t = localtime(&tt);
    Diw = t->tm_wday;
    Miy = t->tm_mon;
    memset(&Msg, 0, sizeof(Msg));
    Msg_New();

    /*
     * Update statistic counter for message area
     */
    fseek(fp, - msgshdr.recsize, SEEK_CUR);
    msgs.Posted.total++;
    msgs.Posted.tweek++;
    msgs.Posted.tdow[Diw]++;
    msgs.Posted.month[Miy]++;
    fwrite(&msgs, msgshdr.recsize, 1, fp);
    fclose(fp);

    /*
     * Start writing the message
     */
    snprintf(Msg.From, 101, CFG.sysop_name);
    snprintf(Msg.To, 101, To);

    /*
     * If netmail, clean the To field.
     */
    if ((msgs.Type == NETMAIL) && strchr(To, '@')) {
	for (i = 0; i < strlen(Msg.To); i++) {
	    if (Msg.To[i] == '_')
		Msg.To[i] = ' ';
	    if (Msg.To[i] == '@') {
		Msg.To[i] = '\0';
		break;
	    }
	}
    }

    snprintf(Msg.Subject, 101, "%s", Subj);
    snprintf(Msg.FromAddress, 101, "%s", aka2str(msgs.Aka));
    Msg.Written = Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60);
    Msg.Local = TRUE;

    if (strchr(Flavor, 'c'))
	Msg.Crash = TRUE;
    if (strchr(Flavor, 'p'))
	Msg.Private = TRUE;
    if (strchr(Flavor, 'h'))
	Msg.Hold = TRUE;

    switch (msgs.Type) {
	case LOCALMAIL:	
			Msg.Localmail = TRUE;
			break;

	case NETMAIL:
			Msg.Netmail = TRUE;
			snprintf(Msg.ToAddress, 101, "%s", ascfnode(parsefaddr(To), 0xff));
			break;

	case ECHOMAIL:
			Msg.Echomail = TRUE;
			break;

	case NEWS:
			Msg.News = TRUE;
			break;
    }

    temp = calloc(PATH_MAX, sizeof(char));
    snprintf(temp, PATH_MAX, "\001MSGID: %s %08x", aka2str(msgs.Aka), sequencer());
    MsgText_Add2(temp);
    Msg.MsgIdCRC = upd_crc32(temp, crc, strlen(temp));
    Msg.ReplyCRC = 0xffffffff;
    snprintf(temp, PATH_MAX, "\001PID: FTND-FIDO %s (%s-%s)", VERSION, OsName(), OsCPU());
    MsgText_Add2(temp);
    if (msgs.Charset != FTNC_NONE) {
	snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(msgs.Charset));
    } else {
	snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(FTNC_LATIN_1));
    }
    MsgText_Add2(temp);
    snprintf(temp, PATH_MAX, "\001TZUTC: %s", gmtoffset(tt));
    MsgText_Add2(temp);

    while ((Fgets(temp, PATH_MAX, tp)) != NULL) {
	if (strncmp(temp, "--- ", 4) == 0)
	    has_tear = TRUE;
	if (strncmp(temp, " * Origin: ", 11) == 0)
	    has_origin = TRUE;
    }
    rewind(tp);
    Syslog('m', "has tearline=%s, has origin=%s", has_tear?"True":"False", has_origin?"True":"False");

    /*
     * Add the file as text
     */
    Msg_Write(tp);
    fclose(tp);

    /*
     * Finish the message
     */
    if ((! has_tear) && (! has_origin)) {
	MsgText_Add2((char *)"");
	MsgText_Add2(TearLine());
    }

    if (! has_origin) {
	aka = calloc(40, sizeof(char));

	if (msgs.Aka.point)
	    snprintf(aka, 40, "(%d:%d/%d.%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node, msgs.Aka.point);
	else
	    snprintf(aka, 40, "(%d:%d/%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node);

	if (strlen(msgs.Origin))
	    snprintf(temp, 81, " * Origin: %s %s", msgs.Origin, aka);
	else
	    snprintf(temp, 81, " * Origin: %s %s", CFG.origin, aka);

	MsgText_Add2(temp);
	free(aka);
    }

    Msg_AddMsg();
    Msg_UnLock();
    Syslog('+', "Posted message %ld", Msg.Id);

    if (msgs.Type != LOCALMAIL) {
	snprintf(temp, PATH_MAX, "%s/tmp/%smail.jam", getenv("FTND_ROOT"), (msgs.Type == ECHOMAIL) ? "echo" : "net");
	if ((fp = fopen(temp, "a")) != NULL) {
	    fprintf(fp, "%s %u\n", msgs.Base, Msg.Id);
	    fclose(fp);
	}
	CreateSema((char *)"mailout");
    }

    free(temp);
    Msg_Close();

    return 0;
}