Esempio n. 1
1
File: file.c Progetto: bbs-io/mbse
/*
 * Show filelist from current area, called from the menu.
 */
void Copy_Home()
{
    char    *File, *temp1, *temp2;
    int	    err, Found = FALSE;
    struct _fdbarea *fdb_area = NULL;

    File  = calloc(81, sizeof(char));
    temp1 = calloc(PATH_MAX, sizeof(char));
    temp2 = calloc(PATH_MAX, sizeof(char));
	
    Enter(1);
    /* Please enter filename: */
    pout(YELLOW, BLACK, (char *) Language(245));
    colour(CFG.InputColourF, CFG.InputColourB);
    GetstrC(File, 80);
    Enter(2);

    if ((strcmp(File, "")) == 0) {
	/* No filename entered, Aborting. */
	pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(246));
	Enter(2);
	Pause();
	free(File);
	free(temp1);
	free(temp2);
	return;
    }

    if (*(File) == '/' || *(File) == ' ') {
	/* Illegal Filename! */
	pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(247));
	Enter(2);
	Pause();
        free(File);
        free(temp1);
        free(temp2);
	return;
    }

    if (Access(exitinfo.Security, area.DLSec) == FALSE) {
	pout(YELLOW, BLACK, (char *) Language(236));
	Enter(2);
	Pause();
        free(File);
        free(temp1);
        free(temp2);
	return;
    }

    if ((fdb_area = mbsedb_OpenFDB(iAreaNumber, 30)) == NULL) {
	free(File);
        free(temp1);
        free(temp2);
	return;
    }

    while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
	if ((strcasecmp(File, fdb.Name) == 0) || (strcasecmp(File, fdb.LName) == 0)) {

	    Found = TRUE;
	    if (((fdb.Size + Quota()) > (CFG.iQuota * 1048576))) {
		/* You have not enough diskspace free to copy this file */
		pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(279));
		Enter(1);
		Syslog('+', "Copy homedir, not enough quota");
	    } else {
		snprintf(temp1, PATH_MAX, "%s/%s", area.Path, fdb.LName); /* Use real longname here */
		snprintf(temp2, PATH_MAX, "%s/%s/wrk/%s", CFG.bbs_usersdir, exitinfo.Name, File);
		colour(CFG.TextColourF, CFG.TextColourB);
		/* Start copy: */
		pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(289));
		PUTSTR(File);
		PUTCHAR(' ');

		Syslog('b', "Copy from : %s", temp1);
		Syslog('b', "Copy to   : %s", temp2);

		if ((err = file_cp(temp1, temp2))) {
		    /* Failed! */
		    pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(353));
		    WriteError("Copy %s to homedir failed, code %d", File, err);
		} else {
		    /* Ok */
		    PUTSTR((char *) Language(200));
		    Syslog('+', "Copied %s from area %d to homedir", File, iAreaNumber);
		}
		Enter(1);
	    }
	}
    }
    mbsedb_CloseFDB(fdb_area);

    if (!Found) {
	/* File does not exist, please try again ... */
	pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(296));
	Enter(1);
    }

    Pause();
    free(File);
    free(temp1);
    free(temp2);
}
Esempio n. 2
0
void *thread_fun(void *arg)
{
	struct sigaction act,oact;//设置信号
	act.sa_handler = sig_alrm;//
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
//	sigaction(SIGALRM, &act, &oact);
	while(1)
	{
		printf("pid=%lu tid=%lu\n", getpid(), pthread_self());
		unsigned long  ret;
		ret=get_file_size("2.cpp");
		
		//sleep(3);
     	struct itimerval itv;
    	itv.it_interval.tv_sec = 5;
        itv.it_interval.tv_usec = 0;
    	itv.it_value.tv_sec = 5;
    	itv.it_value.tv_usec = 0;
    	setitimer(ITIMER_REAL, &itv, &oldtv);

		if(ret>0)
		{
			printf("file  is  too big.....\n");
			get_local_time();
			file_cp("1","2");
		//	sleep(3);
		}
	//	sleep(3);
	}
}
Esempio n. 3
0
/*
 * from_client_commit
 * Handle an incoming commit message from a client.
 * XXX: If commit succeeds and snapshot/startup fails, we have strange state:
 *   the commit has succeeded but an error message is returned.
 */
int
from_client_commit(clicon_handle h,
		   int s, 
		   struct clicon_msg *msg, 
		   const char *label)
{
    char *candidate, *running;
    uint32_t snapshot, startup;
    int retval = -1;
    char *snapshot_0;

    if (clicon_msg_commit_decode(msg, &candidate, &running, 
				&snapshot, &startup, label) < 0)
	goto err;

    if (candidate_commit(h, candidate, running) < 0){
	clicon_debug(1, "Commit %s failed",  candidate);
	retval = 0; /* We ignore errors from commit, but maybe
		       we should fail on fatal errors? */
	goto err;
    }
    clicon_debug(1, "Commit %s",  candidate);

    if (snapshot && config_snapshot(clicon_dbspec_key(h), running, clicon_archive_dir(h)) < 0)
	goto err;

    if (startup){
	snapshot_0 = chunk_sprintf(__FUNCTION__, "%s/0", 
				   clicon_archive_dir(h));
	if (file_cp(snapshot_0, clicon_startup_config(h)) < 0){
	    clicon_err(OE_PROTO, errno, "%s: Error when creating startup", 
		    __FUNCTION__);
		goto err;
	}
    }
    retval = 0;
    if (send_msg_ok(s) < 0)
	goto done;
    goto done;
  err:
    /* XXX: more elaborate errstring? */
    if (send_msg_err(s, clicon_errno, clicon_suberrno, "%s", clicon_err_reason) < 0)
	retval = -1;
  done:
    unchunk_group(__FUNCTION__);
    return retval; /* may be zero if we ignoring errors from commit */
} /* from_client_commit */
Esempio n. 4
0
File: mbfile.c Progetto: bbs-io/mbse
/*
 * Move or rename a file. Not fullproof if using NFS, see
 * man 2 rename. If we are trying to move a file accross
 * filesystems, which is not allowed,  we fall back to simple
 * copy the file and then delete the old file.
 */
int file_mv(char *oldpath, char *newpath)
{
	static	int error;

	if (rename(oldpath, newpath) != 0) {
		error = errno;
		if (error != EXDEV)
			return error;
		/*
		 * We tried cross-device link, now the slow way :-)
		 */
		error = file_cp(oldpath, newpath);
		if (error != 0)
			return error;
		error = file_rm(oldpath);
		return 0;
	}

	return 0;
}
static int copy_default_file (const char *srcfile, const char *dstfile)
{
	char *local_path, *default_path, *target_dir;

	target_dir = stringf_dup ("%s/FastTrack", platform_local_dir());
	local_path = stringf_dup ("%s/FastTrack/%s", platform_local_dir(), dstfile);
	default_path = stringf_dup ("%s/FastTrack/%s", platform_data_dir(), srcfile);

	if (!file_exists (local_path))
	{
		FST_WARN_2 ("Local file \"%s\" does not exist, copying default from \"%s\"",
					local_path, default_path);

		/* make sure the target directory exists */
		if (!file_mkdir (target_dir, 0777))
		{
			FST_ERR_1 ("Unable to create directory \"%s\"", target_dir);

			free (target_dir);
			free (local_path);
			free (default_path);
			return FALSE;
		}


		if (!file_cp (default_path, local_path))
		{		
			FST_ERR_1 ("Unable to copy default file \"%s\"", default_path);

			free (target_dir);
			free (local_path);
			free (default_path);
			return FALSE;
		}
	}

	free (target_dir);
	free (local_path);
	free (default_path);
	return TRUE;
}
Esempio n. 6
0
File: magic.c Progetto: bbs-io/mbse
void Magic_CopyFile(void)
{
    int	    First = TRUE, rc;
    char    *From, *To;

    From = calloc(PATH_MAX, sizeof(char));
    To   = calloc(PATH_MAX, sizeof(char));

    while (GetMagicRec(MG_COPY, First)) {
	First = FALSE;
	snprintf(From, PATH_MAX, "%s/%s", TIC.BBSpath, TIC.NewFile);
	snprintf(To, PATH_MAX, "%s/%s", magic.Path, TIC.NewFile);

	if ((rc = file_cp(From, To) == 0)) {
	    MagicResult((char *)"%s copied to %s", From, To);
	    Magic_CheckCompile();
	} else
	    WriteError("Magic: copy: %s to %s failed, %s", strerror(rc));
    }

    free(From);
    free(To);
}
Esempio n. 7
0
/*
 * Add file to the BBS. The file is in the current directory.
 * The f_db record already has all needed information.
 */
int AddFile(struct FILE_record f_db, int Area, char *DestPath, char *FromPath, char *LinkPath)
{
    int	    	    rc;
    struct _fdbarea *fdb_area = NULL;
    char	    *temp, *dest, *lnk;

    Syslog('f', "AddFile Area    : %d", Area);
    Syslog('f', "AddFile DestPath: %s", FTND_SS(DestPath));
    Syslog('f', "AddFile FromPath: %s", FTND_SS(FromPath));
    Syslog('f', "AddFile LinkPath: %s", FTND_SS(LinkPath));

    /*
     * Copy file to the final destination and make a hard link with the
     * 8.3 filename to the long filename.
     */
    mkdirs(DestPath, 0775);

    if ((file_exist(DestPath, F_OK) == 0) || (file_exist(LinkPath, F_OK) == 0)) {
        if (do_force) {
            Syslog('+', "File %s (%s) already exists in area %d, forced overwrite", f_db.Name, f_db.LName, Area);
        } else {
            WriteError("File %s (%s) already exists in area %d", f_db.Name, f_db.LName, Area);
            if (!do_quiet)
                printf("\nFile %s (%s) already exists in area %d\n", f_db.Name, f_db.LName, Area);
            return FALSE;
        }
    }

    if ((rc = file_cp(FromPath, DestPath))) {
        WriteError("Can't copy file to %s, %s", DestPath, strerror(rc));
        if (!do_quiet)
            printf("\nCan't copy file to %s, %s\n", DestPath, strerror(rc));
        return FALSE;
    }

    chmod(DestPath, 0644);
    if (LinkPath) {
        temp = calloc(PATH_MAX, sizeof(char));
        if (getcwd(temp, PATH_MAX-1)) {
            if (chdir(area.Path)) {
                WriteError("$Can't chdir to %s", area.Path);
                free(temp);
                return FALSE;
            }
            unlink(LinkPath);
            dest = xstrcpy(basename(DestPath));
            lnk = xstrcpy(basename(LinkPath));
            if ((rc = symlink(dest, lnk))) {
                WriteError("Can't create symbolic link %s", lnk);
                if (!do_quiet)
                    printf("\nCan't create symbolic link %s, %s\n", lnk, strerror(rc));
                unlink(DestPath);
                return FALSE;
            }
            free(dest);
            free(lnk);
            chdir(temp);
        }
        free(temp);
    }

    if ((fdb_area = ftnddb_OpenFDB(Area, 30))) {
        rc = ftnddb_InsertFDB(fdb_area, f_db, TRUE);
        ftnddb_CloseFDB(fdb_area);
        return rc;
    } else {
        return FALSE;
    }
}
Esempio n. 8
0
File: ptic.c Progetto: bbs-io/mbse
/*
 * 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;
}
Esempio n. 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);
    }
}
Esempio n. 10
0
File: addbbs.c Progetto: bbs-io/mbse
/*
 *  Add file to the BBS file database and place it in the download
 *  directory. If it is replacing a file, a file with a matching name
 *  will be deleted. If there is a limit on the number of files with
 *  the  same name pattern, the oldest files will be deleted. The
 *  files database will be packed if necessary. All modifications are
 *  done on temp files first.
 */
int Add_BBS(qualify **qal)
{
    struct FILE_record	    frec;
    int			    rc, i, Found = FALSE, Keep = 0, DidDelete = FALSE;
    char		    temp1[PATH_MAX], temp2[PATH_MAX], *fname, *lname, *p;
    fd_list		    *fdl = NULL;
    struct _fdbarea	    *fdb_area = NULL;
    qualify		    *tmpq;
    faddr		    *taka;

    /*
     * First check for an existing record with the same filename,
     * if it exists, update the record and we are ready. This will
     * prevent for example allfiles.zip to get a new record everytime
     * and thus the download counters will be reset after a new update.
     */
    if ((fdb_area = mbsedb_OpenFDB(tic.FileArea, 30))) {
	while (fread(&frec, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
	    if (strcmp(frec.Name, TIC.NewFile) == 0) {
		snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile);
		snprintf(temp2, PATH_MAX, "%s/%s", TIC.BBSpath, TIC.NewFile);
		mkdirs(temp2, 0755);
		if ((rc = file_cp(temp1, temp2))) {
		    WriteError("Copy to %s failed: %s", temp2, strerror(rc));
		    mbsedb_CloseFDB(fdb_area);
		    return FALSE;
		}
		chmod(temp2, 0644);
		strncpy(frec.TicArea, TIC.TicIn.Area, sizeof(frec.TicArea) -1);
		frec.Size = TIC.FileSize;
		frec.Crc32 = TIC.Crc_Int;
		frec.Announced = TRUE;
		frec.FileDate = TIC.FileDate;
		frec.UploadDate = time(NULL);
		for (i = 0; i <= TIC.File_Id_Ct; i++) {
		    strcpy(frec.Desc[i], TIC.File_Id[i]);
		    if (i == 24)
			break;
		}
		if (mbsedb_LockFDB(fdb_area, 30)) {
		    fseek(fdb_area->fp, 0 - fdbhdr.recsize, SEEK_CUR);
		    fwrite(&frec, fdbhdr.recsize, 1, fdb_area->fp);
		    mbsedb_UnlockFDB(fdb_area);
		}
		mbsedb_CloseFDB(fdb_area);
		tic_imp++;
		if ((i = file_rm(temp1)))
		    WriteError("file_rm(%s): %s", temp1, strerror(i));
		return TRUE;
	    }
	}
	mbsedb_CloseFDB(fdb_area);
    }


    /*
     * Create filedatabase record.
     */
    memset(&frec, 0, sizeof(frec));
    strncpy(frec.Name, TIC.NewFile, sizeof(frec.Name) -1);
    if (strlen(TIC.NewFullName)) {
	strncpy(frec.LName, TIC.NewFullName, sizeof(frec.LName) -1);
    } else {
	/*
	 * No LFN, fake it with a lowercase copy of the 8.3 filename.
	 */
	strncpy(frec.LName, TIC.NewFile, sizeof(frec.LName) -1);
	for (i = 0; i < strlen(frec.LName); i++)
	    frec.LName[i] = tolower(frec.LName[i]);
    }
    strncpy(frec.TicArea, TIC.TicIn.Area, 20);
    frec.Size = TIC.FileSize;
    frec.Crc32 = TIC.Crc_Int;
    frec.Announced = TRUE;
    snprintf(frec.Uploader, 36, "Filemgr");
    frec.UploadDate = time(NULL);
    frec.FileDate = TIC.FileDate;
    for (i = 0; i <= TIC.File_Id_Ct; i++) {
	strcpy(frec.Desc[i], TIC.File_Id[i]);
	if (i == 24)
	    break;
    }
    if (strlen(TIC.TicIn.Magic)) {
	strncpy(frec.Magic, TIC.TicIn.Magic, sizeof(frec.Magic) -1);
    }

    snprintf(temp1, PATH_MAX, "%s/%s", TIC.Inbound, TIC.NewFile);
    snprintf(temp2, PATH_MAX, "%s/%s", TIC.BBSpath, frec.Name);
    mkdirs(temp2, 0755);

    if ((rc = file_cp(temp1, temp2))) {
	WriteError("Copy to %s failed: %s", temp2, strerror(rc));
	return FALSE;
    }
    chmod(temp2, 0644);

    /*
     * If LFN = 8.3 name and is DOS 8.3 format, change the LFN to lowercase.
     */
    if (strcmp(frec.Name, frec.LName) == 0) {
	p = frec.LName;
	while (*p) {
	    if (islower(*p))
		Found = TRUE;
	    p++;
	}
	if (!Found) {
	    /*
	     * All uppercase, change to lowercase.
	     */
	    tl(frec.LName);
	    Syslog('f', "Converted LFN to lowercase: \"%s\"", frec.LName);
	}
    }
    Found = FALSE;
    lname = calloc(PATH_MAX, sizeof(char));
    if (getcwd(lname, PATH_MAX -1)) {
	if (chdir(TIC.BBSpath)) {
	    WriteError("$Can't chdir %s", TIC.BBSpath);
	} else {
	    // snprintf(lname, PATH_MAX, "%s/%s", TIC.BBSpath, frec.LName);
	    if (symlink(frec.Name, frec.LName)) {
		WriteError("$Create link %s to %s failed", frec.Name, frec.LName);
	    }
	}
    }
    free(lname);

    if ((fdb_area = mbsedb_OpenFDB(tic.FileArea, 30)) == NULL)
	return FALSE;
    mbsedb_InsertFDB(fdb_area, frec, area.AddAlpha);
    mbsedb_CloseFDB(fdb_area);

    /*
     * Delete file from the inbound
     */
    if ((i = file_rm(temp1)))
	WriteError("file_rm(%s): %s", temp1, strerror(i));

    /*
     * Handle the replace option.
     */
    if ((strlen(TIC.TicIn.Replace)) && (tic.Replace)) {
	Syslog('f', "Must Replace: %s", TIC.TicIn.Replace);

	if ((fdb_area = mbsedb_OpenFDB(tic.FileArea, 30))) {
	    while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
		if (strlen(fdb.LName) == strlen(frec.LName)) {
		    // FIXME: Search must be based on a reg_exp search
		    if (strcasecmp(fdb.LName, frec.LName) != 0) {
			Found = TRUE;
			for (i = 0; i < strlen(frec.LName); i++) {
			    if ((TIC.TicIn.Replace[i] != '?') && (toupper(TIC.TicIn.Replace[i]) != toupper(fdb.LName[i])))
				Found = FALSE;
			}
			if (Found) {
			    Syslog('+', "Replace: Deleting: %s", fdb.LName);
			    fdb.Deleted = TRUE;
			    if (mbsedb_LockFDB(fdb_area, 30)) {
				fseek(fdb_area->fp , - fdbhdr.recsize, SEEK_CUR);
				fwrite(&fdb, fdbhdr.recsize, 1, fdb_area->fp);
				mbsedb_UnlockFDB(fdb_area);
			    }
			    DidDelete = TRUE;
			}
		    }
		}
	    }
	    mbsedb_CloseFDB(fdb_area);
	}
    }

    /*
     * Handle the Keep number of files option
     */
    if (TIC.KeepNum) {
	if ((fdb_area = mbsedb_OpenFDB(tic.FileArea, 30))) {
	    while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
		if ((strlen(fdb.LName) == strlen(frec.LName)) && (!fdb.Deleted)) {
		    Found = TRUE;

		    for (i = 0; i < strlen(fdb.LName); i++) {
			if ((frec.LName[i] < '0') || (frec.LName[i] > '9')) {
			    if (frec.LName[i] != fdb.LName[i]) {
				Found = FALSE;
			    }
			}
		    }
		    if (Found) {
			Keep++;
			fill_fdlist(&fdl, fdb.LName, fdb.UploadDate);
		    }
		}
	    }
	    mbsedb_CloseFDB(fdb_area);
	}

	/*
	 * If there are files to delete, mark them.
	 */
	if (Keep > TIC.KeepNum) {
	    sort_fdlist(&fdl);

	    if ((fdb_area = mbsedb_OpenFDB(tic.FileArea, 30))) {
		for (i = 0; i < (Keep - TIC.KeepNum); i++) {
		    fname = pull_fdlist(&fdl);
		    fseek(fdb_area->fp, fdbhdr.hdrsize, SEEK_SET);
		    while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
			if (strcmp(fdb.LName, fname) == 0) {
			    Syslog('+', "Keep %d files, deleting: %s", TIC.KeepNum, fdb.LName);
			    fdb.Deleted = TRUE;
			    if (mbsedb_LockFDB(fdb_area, 30)) {
				fseek(fdb_area->fp , - fdbhdr.recsize, SEEK_CUR);
				fwrite(&fdb, fdbhdr.recsize, 1, fdb_area->fp);
				mbsedb_UnlockFDB(fdb_area);
			    }
			    DidDelete = TRUE;
			}
		    }
		}
		mbsedb_CloseFDB(fdb_area);
    		}
	}
	tidy_fdlist(&fdl);
    }

    /*
     *  Now realy delete the marked files and clean the file
     *  database.
     */
    if (DidDelete) {
	if ((fdb_area = mbsedb_OpenFDB(tic.FileArea, 30))) {
	    while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
		if (fdb.Deleted) {
		    snprintf(temp2, PATH_MAX, "%s/%s", area.Path, fdb.LName);
		    if (unlink(temp2) != 0)
		        WriteError("$Can't unlink file %s", temp2);
		    snprintf(temp2, PATH_MAX, "%s/%s", area.Path, fdb.Name);

		    /*
		     * With the path to the 8.3 name, we can check if this file
		     * is attached for any possible downlink. We use the qualify
		     * list created by the ptic function to check connected nodes
		     * only.
		     */
		    for (tmpq = *qal; tmpq; tmpq = tmpq->next) {
			if (tmpq->send) {
			    taka = fido2faddr(tmpq->aka);
			    un_attach(taka, temp2);
			    tidy_faddr(taka);
			}
		    }

		    if (unlink(temp2) != 0)
		        WriteError("$Can't unlink file %s", temp2);
		    snprintf(temp2, PATH_MAX, "%s/.%s", area.Path, fdb.Name);
		    unlink(temp2); /* Thumbnail, no logging if there is an error */
		}
	    }
	    mbsedb_PackFDB(fdb_area);
	    mbsedb_CloseFDB(fdb_area);
	    DidDelete = FALSE;
	}
    }

    tic_imp++;
    return TRUE;
}
Esempio n. 11
0
/*
 * candidate_commit
 * Do a diff between candidate and running, and then call plugins to
 * commit the changes. 
 * The code reverts changes if the commit fails. But if the revert
 * fails, we just ignore the errors and proceed. Maybe we should
 * do something more drastic?
 * Arguments:
 * running:   The current database. The state of the router corresponds
 *            to these values. Also called db1.
 * candidate: The candidate database. We are aiming to put the router in this 
 *            state.   Also called db2.

                      (_dp) [op, callback] (dpe_)
                      +---------------+    +---------------+
                      |    dbdep_t    |--> |  dbdep_ent_t  | [key, var] 
                      +---------------+    +---------------+
                      ^ Database dependency description
from dbdep_commit()   |
+---------------+*    |dd_dep
|  dbdep_dd_t   |-----+
+---------------+     |dd_dbdiff
(dd_)                 |
                      v
+---------------+     +---------------+  
|   dbdiff      |---->|    dbdiff_ent |  [key1, key2, add/change/rm] (dfe_)
+---------------+     +---------------+  
(df_) from dbdiff(),   (dfe_)
                     
 */
int
candidate_commit(clicon_handle h, char *candidate, char *running)
{
    struct dbdiff      df;
    dbdep_t           *dp;
    struct dbdiff_ent *dfe;
    dbdep_dd_t        *ddvec = NULL;
    dbdep_dd_t        *dd;
    int                nvec;
    int                retval = -1;
    int                i, j;
    int                failed = 0;
    struct stat        sb;
    void              *firsterr = NULL;

    /* Sanity checks that databases exists. */
    if (stat(running, &sb) < 0){
	clicon_err(OE_DB, errno, "%s", running);
	goto done;
    }
    if (stat(candidate, &sb) < 0){
	clicon_err(OE_DB, errno, "%s", candidate);
	goto done;
    }
    memset(&df, 0, sizeof(df));

    /* Find the differences between the two databases and store it in dd vector. */
    if (db_diff(running, candidate,
		__FUNCTION__,
		clicon_dbspec_key(h),
		&df
	    ) < 0)
	goto done;
    /* 1. Get commit processing dbdiff vector: one entry per key that changed.
          changes are registered as if they exist in the 1st(candidate) or
	  2nd(running) dbs.
     */
    if (dbdep_commitvec(h, &df, &nvec, &ddvec) < 0)
	goto done;
    
    /* 2. Call plugin pre-commit hooks */
    if (plugin_begin_hooks(h, candidate) < 0)
	goto done;

    /* call generic cv_validate() on all new or changed keys. */
    if (generic_validate(h, candidate, &df) < 0)
	goto done;

    /* user-defined callbacks */
    if (validate_db(h, nvec, ddvec, candidate) < 0)
	goto done;

    /* Call plugin post-commit hooks */
    if (plugin_complete_hooks(h, candidate) < 0)
	goto done;

    /* Now follows commit rules in order.
    * 4. For all keys that are in candidate, delete key (from running). 
    */
    for (i = nvec-1; i >= 0; i--){
	dd = &ddvec[i];
	dfe = dd->dd_dbdiff; /* key1/key2/op */
	dp = dd->dd_dep;     /* op, callback, arg */
	if (dp->dp_type & TRANS_CB_COMMIT &&
	    dfe->dfe_op & DBDIFF_OP_FIRST &&
	    plugin_modify_key_value(h, running,        /* db */
				    dfe->dfe_key1,     /* key */
				    TRANS_CB_COMMIT, /* commit|validate */
				    LV_DELETE,         /* operation */
				    dp                 /* callback(arg) */
		) < 0){
	    firsterr = clicon_err_save(); /* save this error */
	    break;
	}
    }
    /* 5. Failed deletion of running, add the key value back (from running) */
    if (i >= 0){ /* failed */
	for (j=i+1; j<nvec; j++){ /* revert in opposite order */
	    dd = &ddvec[j];
	    dfe = dd->dd_dbdiff; /* key1/key2/op */
	    dp = dd->dd_dep;     /* op, callback, arg */
	    if (dp->dp_type & TRANS_CB_COMMIT &&
		dfe->dfe_op & DBDIFF_OP_FIRST &&
		plugin_modify_key_value(h, running,       /* db */
					dfe->dfe_key1,    /* key */
					TRANS_CB_COMMIT,  /* commit|validate */
					LV_SET,           /* operation */
					dp                 /* callback(arg) */
		    ) < 0)
		continue; /* ignore errors or signal major setback ? */
	}
	goto done;
    }

    /* 6. Set keys (from candidate) */
    for (i=0; i < nvec; i++){
	dd = &ddvec[i];
	dfe = dd->dd_dbdiff; /* key1/key2/op */
	dp = dd->dd_dep;     /* op, callback, arg */
	if (dp->dp_type & TRANS_CB_COMMIT &&
	    dfe->dfe_op & DBDIFF_OP_SECOND &&
	    plugin_modify_key_value(h, candidate,        /* db */
				    dfe->dfe_key2,     /* key */
				    TRANS_CB_COMMIT, /* commit|validate */
				    LV_SET,         /* operation */
				    dp                 /* callback(arg) */
		) < 0){
	    firsterr = clicon_err_save(); /* save this error */
	    failed++;
	    break;
	}
    }
    if (!failed)
	if (file_cp(candidate, running) < 0){
	    clicon_err(OE_UNIX, errno, "file_cp");
	    failed++;
	}
    /* 7. Failed setting keys in running, first remove the keys set */
    if (failed){ /* failed */
	for (j=i-1; j>=0; j--){ /* revert in opposite order */
	    dd = &ddvec[j];
	    dfe = dd->dd_dbdiff; /* key1/key2/op */
	    dp = dd->dd_dep;     /* op, callback, arg */
	    if (dp->dp_type & TRANS_CB_COMMIT &&
		dfe->dfe_op & DBDIFF_OP_SECOND &&
		plugin_modify_key_value(h, candidate,    /* db */
					dfe->dfe_key2,   /* key */
					TRANS_CB_COMMIT, /* commit|validate */
					LV_DELETE,       /* operation */
					dp               /* callback(arg) */
		    ) < 0)
		continue; /* ignore errors or signal major setback ? */
	}
	/* 7. Set back original running values */
	for (j=0; j < nvec; j++){ /* revert in opposite order */
	    dd = &ddvec[j];
	    dfe = dd->dd_dbdiff; /* key1/key2/op */
	    dp = dd->dd_dep;     /* op, callback, arg */
	    if (dp->dp_type & TRANS_CB_COMMIT &&
		dfe->dfe_op & DBDIFF_OP_FIRST &&
		plugin_modify_key_value(h, running,        /* db */
					dfe->dfe_key1,     /* key */
					TRANS_CB_COMMIT, /* commit|validate */
					LV_SET,         /* operation */
					dp                 /* callback(arg) */
		    ) < 0)
		continue; /* ignore errors or signal major setback ? */
	}
	goto done;
    }


    /* Copy running back to candidate in case end functions triggered 
       updates in running */
    /* XXX: check for errors */
    file_cp(running, candidate);

    /* Call plugin post-commit hooks */
    plugin_end_hooks(h, candidate);

    retval = 0;
  done:
    if (retval < 0) /* Call plugin fail-commit hooks */
	plugin_abort_hooks(h, candidate);
    if (ddvec)
	free(ddvec);
    unchunk_group(__FUNCTION__); 
    if (firsterr)
	clicon_err_restore(firsterr);
    return retval;
}
Esempio n. 12
0
File: queue.c Progetto: bbs-io/mbse
void flush_dir(char *ndir)
{
    struct dirent   *de;
    DIR		    *dp;
    FILE	    *fp, *inf, *ouf;
    faddr	    noden, *bestaka;
    fidoaddr	    nodenr;
    int		    flavor, mode, Attach, fage, first, bread, rc;
    int		    fsize;
    char	    *p, *temp, *fname, *arcfile, *pktfile, *ext, maxnr, nr, oldnr, *buf;
    time_t	    Now;
    struct tm	    *ptm;
    struct stat	    sbuf;
    fd_list	    *fdl = NULL;

    temp = calloc(PATH_MAX, sizeof(char));
    snprintf(temp, PATH_MAX, "%s/%s", CFG.out_queue, ndir);
    if (chdir(temp) == -1) {
	WriteError("$Error chdir to %s", temp);
	free(temp);
	return;
    }

    /*
     * Get the nodenumber from the filename
     */
    noden.domain = NULL;
    noden.name   = NULL;
    noden.zone   = atoi(strtok(ndir, "."));
    noden.net    = atoi(strtok(NULL, "."));
    noden.node   = atoi(strtok(NULL, "."));
    noden.point  = atoi(strtok(NULL, "\0"));
    if (SearchFidonet(noden.zone))
	noden.domain = xstrcpy(fidonet.domain);

    memset(&nodenr, 0, sizeof(nodenr));
    nodenr.zone  = noden.zone;
    nodenr.net   = noden.net;
    nodenr.node  = noden.node;
    nodenr.point = noden.point;
    snprintf(nodenr.domain, 13, "%s", noden.domain);

    if (!SearchNode(nodenr)) {
	/*
	 * Node not in setup, blank noderecord and fill in some details
	 * so that we are able to send mail crash or immediate.
	 */
	Syslog('+', "Node %s not in setup, using default settings", aka2str(nodenr));
	memset(&nodes, 0, sizeof(nodes));
	nodes.Aka[0].zone  = noden.zone;
	nodes.Aka[0].net   = noden.net;
	nodes.Aka[0].node  = noden.node;
	nodes.Aka[0].point = noden.point;
	snprintf(nodes.Archiver, 6, (char *)"ZIP");
    }

    /*
     * If we route via another aka, change everything.
     */
    if (nodes.RouteVia.zone) {
	p = xstrcpy(aka2str(nodenr));
	Syslog('+', "Route to %s via %s", p, aka2str(nodes.RouteVia));
	free(p);
	noden.zone   = nodes.RouteVia.zone;
	noden.net    = nodes.RouteVia.net;
	noden.node   = nodes.RouteVia.node;
	noden.point  = nodes.RouteVia.point;
	if (noden.domain)
	    free(noden.domain);
	noden.domain = xstrcpy(nodes.RouteVia.domain);
	/*
	 * Load routevia noderecord to get the correct flavor.
	 * If there is no noderecord, reload the old one.
	 */
	if (!SearchNode(nodes.RouteVia))
	    SearchNode(nodenr);
    }

    /*
     * At this point we are ready to add everything to the real outbound.
     * Lock the node, if this fails because the node is busy we abort
     * and try to add at a later time.
     */
    if (nodes.Session_out == S_DIR) {
	if (islocked(nodes.Dir_out_clock, nodes.Dir_out_chklck, nodes.Dir_out_waitclr, 'p')) {
	    Syslog('+', "Mail and files stay in queue, will be added later");
	    if (noden.domain)
		free(noden.domain);
	    free(temp);
	    return;
	} else {
	    if (! setlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p')) {
		Syslog('+', "Mail and files stay in queue, will be added later");
		if (noden.domain)
		    free(noden.domain);
		free(temp);
		return;
	    }
	}
    } else {
	if (nodelock(&noden, mypid)) {
	    Syslog('+', "Mail and files stay in queue, will be added later");
	    if (noden.domain)
		free(noden.domain);
	    free(temp);
	    return;
	}
    }

    /*
     * Create arcmail filename for this node.
     */
    Now = time(NULL);
    arcfile = calloc(PATH_MAX, sizeof(char));
    if (nodes.Session_out == S_DIR) {

	ptm = localtime(&Now);
	ext = dow[ptm->tm_wday];

	if (!nodes.ARCmailCompat && (nodes.Aka[0].zone != noden.zone)) {
	    /*
	     * Generate ARCfile name from the CRC of the ASCII string of the node address.
	     */
	    snprintf(arcfile, PATH_MAX, "%s/%08x.%s0", nodes.Dir_out_path, StringCRC32(ascfnode(&noden, 0x1f)), ext);
	} else {
	    bestaka = bestaka_s(&noden);

	    if (noden.point) {
		snprintf(arcfile, PATH_MAX, "%s/%04x%04x.%s0", nodes.Dir_out_path, ((bestaka->net) - (noden.net)) & 0xffff,
			((bestaka->node) - (noden.node) + (noden.point)) & 0xffff, ext);
	    } else if (bestaka->point) {
		/*
		 * Inserted the next code for if we are a point,
		 * I hope this is ARCmail 0.60 compliant. 21-May-1999
		 */
		snprintf(arcfile, PATH_MAX, "%s/%04x%04x.%s0", nodes.Dir_out_path, ((bestaka->net) - (noden.net)) & 0xffff,
			((bestaka->node) - (noden.node) - (bestaka->point)) & 0xffff, ext);
	    } else {
		snprintf(arcfile, PATH_MAX, "%s/%04x%04x.%s0", nodes.Dir_out_path, ((bestaka->net) - (noden.net)) & 0xffff,
			((bestaka->node) - (noden.node)) &0xffff, ext);
	    }
	}
    } else {
	snprintf(arcfile, PATH_MAX, "%s", arcname(&noden, nodes.Aka[0].zone, nodes.ARCmailCompat));
    }

    /*
     * If there is a mailpkt.qqq file, close it and rename it.
     */
    pktfile = calloc(PATH_MAX, sizeof(char));
    fname   = calloc(PATH_MAX, sizeof(char));
    snprintf(fname, PATH_MAX, "%s/mailpkt.qqq", temp);
    if (access(fname, W_OK) == 0) {
	snprintf(pktfile, PATH_MAX, "%s/%08x.pkt", temp, sequencer());
	if (rename(fname, pktfile)) {
	    WriteError("$Can't rename %s to %s", fname, pktfile);
	} else {
	    /*
	     * Add zero word to end of .pkt file
	     */
	    if ((fp = fopen(pktfile, "a+")) == NULL) {
		WriteError("$Can't open %s", pktfile);
	    }
	    putc('\0', fp);
	    putc('\0', fp);
	    fsync(fileno(fp));
	    fclose(fp);
	}
    }
    free(fname);

    /*
     * Now all mail pkts are ready to archive
     */
    if ((dp = opendir(temp)) == NULL) {
	WriteError("$Can't open %s", temp);
	free(temp);
	free(arcfile);
	if (nodes.Session_out == S_DIR)
	    remlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p');
	else
	    nodeulock(&noden, mypid);
	if (noden.domain)
	    free(noden.domain);
	return;
    }

    /*
     * Read all .pkt filenames, get the timestamp and add them
     * to the memory array for later sort on filedate.
     */ 
    while ((de = readdir(dp)))
	if ((strlen(de->d_name) == 12) && (strncasecmp(de->d_name+8,".pkt",4) == 0)) {
	    stat(de->d_name, &sbuf);
	    Syslog('p', "Adding %s to filelist", de->d_name);
	    fill_fdlist(&fdl, de->d_name, sbuf.st_mtime);
	}

    closedir(dp);
    sort_fdlist(&fdl);

    if (getarchiver(nodes.Archiver)) {
	flavor = 'f';
	if (nodes.Crash)
	    flavor = 'c';
	if (nodes.Hold)
	    flavor = 'h';
    } else {
	WriteError("Archiver %s not found", nodes.Archiver);
	if (noden.domain)
	    free(noden.domain);
	free(temp);
	free(arcfile);
	return;
    }

    first = TRUE;
    while ((fname = pull_fdlist(&fdl)) != NULL) {
	/*
	 *  Check the size of the existing archive if there is a size limit.
	 *  Change to new archive names if the existing is too large.
	 *  If the archive size is zero, it's an already sent archive, the
	 *  number will be bumped also.
	 *  If the archive is older then 6 days, the name is also bumped.
	 *  Do this until we find a new name or if the last digit is a '9' or 'z'.
	 *  Purge archives older then toss_days.
	 */
	nr = oldnr = '0';
	if (nodes.ARCmailAlpha)
	    maxnr = 'z';
	else
	    maxnr = '9';
	Attach = FALSE;

	for (;;) {
	    fsize = file_size(arcfile);
	    fage  = (int)((Now - file_time(arcfile)) / 86400);

	    if (fsize == -1L) {
		Attach = TRUE;
		break;
	    }

	    if (fsize == 0L) {
		if ((fage > 6) && (nr < maxnr)) {
		    /*
		     * Remove truncated ARCmail files older then 6 days.
		     */
		    unlink(arcfile);
		    fsize = -1L;
		    Attach = TRUE;
		    break;
		}

		/*
		 * Increase filename extension if there is a truncated file of today.
		 */
		if (nr < maxnr) {
		    nr++;
		    if (nr == ('9' +1))
			nr = 'a';
		    arcfile[strlen(arcfile) -1] = nr;
		} else {
		    Syslog('!', "Warning: archive filename extensions exhausted for today");
		    break;
		}
	    } else if (CFG.maxarcsize && (fsize > (CFG.maxarcsize * 1024)) && (nr < maxnr)) {
		/*
		 * Use a new ARCmail file if the last one is too big.
		 */
		nr++;
		if (nr == ('9' +1))
		    nr = 'a';
		arcfile[strlen(arcfile) -1] = nr;
	    }

	    fsize = file_size(arcfile);
	    fage  = (int)((Now - file_time(arcfile)) / 86400);

	    if ((fsize > 0L) && (fage > 6) && (nr < maxnr)) {
		/*
		 * If there is ARCmail of a week old or older, add mail
		 * to a new ARCmail bundle.
		 */
		nr++;
		if (nr == ('9' +1))
		    nr = 'a';
		arcfile[strlen(arcfile) -1] = nr;
	    }

	    if (oldnr == nr)
		break;
	    else
		oldnr = nr;
	}

	fsize = file_size(arcfile);

	/*
	 * If arcfile names were exhausted then the file ending on a z could still
	 * be in the outbound but truncated if it has been sent. Since we are
	 * reusing that filename (not a good solution) we must erase it or the
	 * archiver program will complain.
	 */
	if (fsize == 0L) {
	    unlink(arcfile);
	    Attach = TRUE;
	}

	if (first) {
	    Syslog('+', "Pack ARCmail for %s via %s with %s", aka2str(nodenr), ascfnode(&noden, 0x1f), nodes.Archiver);
	    if (!do_quiet) {
		printf("\rAdding ARCmail for %s                      ", ascfnode(&noden, 0x1f));
		fflush(stdout);
	    }
	    first = FALSE;
	    flushed = TRUE;
	}

	if (execute_str(archiver.marc, arcfile, fname, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null") == 0) {
	    unlink(fname);
	} else {
	    WriteError("Can't add %s to ARCmail archive", fname);
	    Attach = FALSE;
	}

	/*
	 * Change filemode so downlink has rights to the file.
	 */
	if (nodes.Session_out == S_DIR)
	    chmod(arcfile, 0660);
	
	/*
	 * Attach file to .flo, not for FTP or Directory sessions.
	 */
	if (Attach && nodes.Session_out == S_DIRECT)
	    attach(noden, arcfile, TFS, flavor);
    }

    /*
     * Open directory again.
     */
    if ((dp = opendir(temp)) == NULL) {
	WriteError("$Can't open %s", temp);
	free(temp);
	free(arcfile);
	if (nodes.Session_out == S_DIR)
	    remlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p');
	else
	    nodeulock(&noden, mypid);
	if (noden.domain)
	    free(noden.domain);
	return;
    }

    /*
     * Read all other mail filenames, get the timestamp and add them
     * to the memory array for later sort on filedate.
     */ 
    while ((de = readdir(dp)))
	if ((strlen(de->d_name) == 11) && (strncasecmp(de->d_name,"mailpkt.",8) == 0)) {
	    stat(de->d_name, &sbuf);
	    Syslog('p', "Adding %s to filelist", de->d_name);
	    fill_fdlist(&fdl, de->d_name, sbuf.st_mtime);
	}

    closedir(dp);
    sort_fdlist(&fdl);

    first = TRUE;
    while ((fname = pull_fdlist(&fdl)) != NULL) {
	if (first) {
	    Syslog('+', "Pack unpacked mail for %s via %s", aka2str(nodenr), ascfnode(&noden, 0x1f));
	    if (!do_quiet) {
		printf("\rAdding netmail for %s                      ", ascfnode(&noden, 0x1f));
		fflush(stdout);
	    }
	    first = FALSE;
	    flushed = TRUE;
	}

	snprintf(pktfile, PATH_MAX, "%s/%s", temp, fname);

	if (strstr(fname, ".ddd"))
	    flavor = 'd';
	else if (strstr(fname, ".ccc"))
	    flavor = 'c';
	else if (strstr(fname, ".hhh"))
	    flavor = 'h';
	else
	    flavor = 'o';

	if (nodes.Session_out == S_DIR) {
	    snprintf(arcfile, PATH_MAX, "%s/%08x.pkt", nodes.Dir_out_path, sequencer());
	} else {
	    snprintf(arcfile, PATH_MAX, "%s", pktname(&noden, flavor));
	}

	/*
	 *  Now we must see if there is already mail in the outbound.
	 *  If that's the case, we must skip the .pkt header from the queue
	 *  because there is already a .pkt header also, append to the
	 *  outbound 2 bytes before the end of file, this is the zero word.
	 */
	if ((inf = fopen(pktfile, "r")) != NULL) {
	    if (access(arcfile, R_OK) == -1) {
		ouf = fopen(arcfile, "w");  /* create new  */
		Syslog('p', "Create new %s", arcfile);
	    } else {
		ouf = fopen(arcfile, "r+"); /* open R/W    */
		fseek(ouf, -2, SEEK_END);   /* b4 0 word   */
		fseek(inf, 58, SEEK_SET);   /* skip header */
		Syslog('p', "Append to %s", arcfile);
	    }

	    if (ouf != NULL) {
		buf = malloc(16384);

		do {
		    bread = fread(buf, 1, 16384, inf);
		    fwrite(buf, 1, bread, ouf);
		} while (bread);

		free(buf);
		putc('\0', ouf);
		putc('\0', ouf);
		fsync(fileno(ouf));
		fclose(ouf);
		fclose(inf);
		unlink(pktfile);
	    } else {
		WriteError("$Can't open %s", arcfile);
		fclose(inf);
	    }
	}

	/*
	 * Change filemode so downlink has rights to the file.
	 */
	if (nodes.Session_out == S_DIR)
	    chmod(arcfile, 0660);
    }

    /*
     * Now add the files for the node, information is in the .filelist
     * file, this tells the location of the file and what to do with
     * it after it is sent.
     */
    snprintf(pktfile, PATH_MAX, "%s/.filelist", temp);
    if ((fp = fopen(pktfile, "r")) != NULL) {

	Syslog('+', "Adding files for %s via %s", aka2str(nodenr), ascfnode(&noden, 0x1f));
	if (!do_quiet) {
	    printf("\rAdding files for %s                        ", ascfnode(&noden, 0x1f));
	    fflush(stdout);
	    flushed = TRUE;
	}

	buf = calloc(PATH_MAX + 1, sizeof(char));

	while (fgets(buf, PATH_MAX, fp)) {
	    Striplf(buf);
	    Syslog('p', ".filelist: %s", buf);
	    flavor = buf[0];
	    p = strchr(buf, ' ');
	    p++;
	    if (strncmp(p, "LEAVE ", 6) == 0)
		mode = LEAVE;
	    else if (strncmp(p, "KFS ", 4) == 0)
		mode = KFS;
	    else if (strncmp(p, "TFS ", 4) == 0)
		mode = TFS;
	    else {
		WriteError("Syntax error in filelist \"%s\"", buf);
		mode = LEAVE;
	    }
	    p = strchr(p, ' ');
	    p++;
	    // Here is a extra now unused keyword.
	    p = strchr(p, ' ');
	    p++;

	    Syslog('p', "File attach %s to %s", p, ascfnode(&noden, 0x1f));
	    if (nodes.Session_out == S_DIRECT) {
		attach(noden, p, mode, flavor);
	    } else if (nodes.Session_out == S_DIR) {
		snprintf(arcfile, PATH_MAX, "%s/%s", nodes.Dir_out_path, Basename(p));
		if (mode == LEAVE) {
		    /*
		     * LEAVE file, so we copy this one.
		     */
		    rc = file_cp(p, arcfile);
		    Syslog('p', "file_cp(%s, %s) rc=%d", p, arcfile, rc);
		} else {
		    /*
		     * KFS or TFS, move file to node directory
		     */
		    rc = file_mv(p, arcfile);
		    Syslog('p', "file_mv(%s, %s) rc=%d", p, arcfile, rc);
		}
		chmod(arcfile, 0660);
	    }
	}

	free(buf);
	fclose(fp);
	unlink(pktfile);
    }

    /*
     * We are done, the queue is flushed, unlock the node.
     */
    if (nodes.Session_out == S_DIR)
	remlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p');
    else
	nodeulock(&noden, mypid);

    if (noden.domain)
	free(noden.domain);
    free(temp);
    free(arcfile);
    free(pktfile);
    return;
}