
/*
 *  PUTFILES.C
 *
 *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
 *
 *  Upload one or more files or directories to the remote host
 */

#include "defs.h"

char Buf[1024];

int putname ARGS((void *, char *));
int putfile ARGS((void *, char *, char *));
int writehdr ARGS((void *, ubyte, char *, long));

void main ARGS((int, char **));

int
brk()
{
    return(0);
}

void
main(ac,av)
char *av[];
{
    void *chan;
    short i;
    char fn = 0;
    char *host = NULL;
    char *dir = NULL;

    printf("PutFiles V%s%s\n", VERSION, PUTFILES_VERSION);
    ac = DoOption(ac, av, "N%sd%s", &host, &dir);

    onbreak(brk);
    if (ac <= 1) {
	puts("putfiles [-Nnetid] [-dremotedir] file/dir file/dir ....");
	exit(1);
    }
    chan = DOpen(host, PORT_FILECOPY, -80, 126);
    if (!chan) {
	puts("Unable to connect");
	exit(1);
    }
    DRead(chan, &fn, 1);
    if (fn == 'S') {
	puts("Remote Server Permission Denied");
	DClose(chan);
	exit(1);
    }
    if (fn != 'Y') {
	puts("Remote Server Software Error");
	DClose(chan);
	exit(1);
    }
    if (dir) {
	if (writehdr(chan, 'C', dir, 0) != 'Y') {
	    printf("Remote directory unavailable: %s\n", dir);
	    goto fail;
	}
    }
    for (i = 1; i < ac; ++i) {
	if (putname(chan, av[i]) < 0)
	    break;
    }
fail:
    printf("\nclosing... ");
    fflush(stdout);
    DClose(chan);
    puts("done");
}

int
putname(chan, file)
void *chan;
char *file;
{
    long lock = Lock(file, SHARED_LOCK);
    long dirl;
    int ret = 1;
    FIB *fib = (FIB *)malloc(sizeof(FIB));

    printf("%-20s ", file);
    if (lock == NULL || !Examine(lock, fib)) {
	if (lock)
	    UnLock(lock);
	free(fib);
	puts("NOT FOUND");
	return(1);
    }
    if (fib->fib_DirEntryType > 0) {
	char *dirname = (fib->fib_FileName[0]) ? fib->fib_FileName : "ram";
	puts("DIR");
	dirl = (long)CurrentDir(lock);
	if (writehdr(chan, 'X', dirname, 0) != 'Y') {
	    puts("Remote unable to make directory");
	    goto f1;
	}
	while (ExNext(lock, fib)) {
	    if (putname(chan, fib->fib_FileName) < 0) {
		ret = -1;
		goto f1;
	    }
	}
	writehdr(chan, 'Y', "?", 0);
f1:
	UnLock(CurrentDir(dirl));
    } else {
	UnLock(lock);
	ret = putfile(chan, file, fib->fib_FileName);
    }
    free(fib);
    return(ret);
}

int
putfile(chan, file, stripedname)
void *chan;
char *file;
char *stripedname;
{
    long fh = (long)Open(file, 1005);
    long n, r, len;
    long ttl = 0;
    char co;

    fflush(stdout);
    if (fh == NULL) {
	puts("FILE NOT FOUND");
	return(0);
    }
    Seek(fh, 0, 1);                 /*  get length */
    len = ttl = Seek(fh, 0, -1);
    if (writehdr(chan, 'W', stripedname, len) != 'Y') {
	puts("REMOTE UNABLE TO ACCEPT FILE");
	Close(fh);
	return(0);
    }
    printf("%6ld/%-6ld", ttl - len, ttl);
    while (len) {
	fflush(stdout);
	r = (len > sizeof(Buf)) ? sizeof(Buf) : len;
	n = Read(fh, Buf, r);
	if (n != r) {
	    puts("Local File error");
	    Close(fh);
	    return(-1);
	}
	if (DWrite(chan, Buf, n) != n) {
	    puts("Remote error");
	    Close(fh);
	    return(-1);
	}
	if (SetSignal(0,0) & (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) {
	    puts("\nBreak");
	    Close(fh);
	    return(-1);
	}
	len -= n;
	printf("\010\010\010\010\010\010\010\010\010\010\010\010\010");
	printf("%6ld/%-6ld", ttl - len, ttl);
    }
    Close(fh);
    printf("Queued, waiting...");
    fflush(stdout);
    DRead(chan, &co, 1);
    if (co != 'Y') {
	puts("Remote Server Software Error");
	return(-1);
    }
    puts("  OK");
    return(0);
}

int
writehdr(chan, c, name, len)
void *chan;
unsigned char c;
char *name;
long len;
{
    if (DWrite(chan, &c, 1) != 1)
	return(-1);
    c = strlen(name) + 1;
    if (DWrite(chan, &c, 1) != 1)
	return(-1);
    if (DWrite(chan, name, c) != c)
	return(-1);
    if (DWrite(chan, &len, 4) != 4)
	return(-1);
    if (DRead(chan, &c, 1) == 1)
	return((int)c);
    return(-1);
}

