#!/usr/bin/tclsh8.5
#
# $Id: bd840f95f8fa19fd2c4fe328cd312e9db1ce6b7b $
#
#
# Usage: nbspinsert -i [-f nbspinfifo] finfo < file
#	 nbspinsert [-f nbspinfifo] finfo
#	 nbspinsert [-f nbspinfifo] < file_with_finfolist
# where
#
# finfo = seq type cat code npchidx fname fpath
#
# In the first form, it will save the data in fpath, and then process the
# file. In the second form, it assumes that the data is already in fpath.
# The third form is like the second one, but it takes a list of finfo
# on stdin (like a filter does). In all cases, the fpath should be a
# "spool file" path, that is, a path to a file in the spool directory with
# the usual convention used by nbsp.
#
# If [-f] is not given to specify the location of the nbspd.infifo file,
# then the nbsp configuration files are read.
#
# NOTE:  In this mode the Nbsp processor is not invoked and the files
#        that are saved in the spool directory by the caller of this script,
#        or by this script itself, are not inserted by the spooldb that
#        handles the deletion of the spooled files. Therefore the files
#        that are sent to Nbsp by this script must be deleted from the spool
#        by the caller of this script, or by the cleanup scheduler.
#        The latter is set automaticaly by the default hourly-cleanup.conf,
#        but the files written by this script must be writable by the
#        nbsp user (noaaport:noaaport) so that they can be deleted by the
#        default cleanup process.
#
#        For more general instructions see the file "nbspinsert.README".
#        For an example of how to use this script see the "craftinsert" script
#        and "craftinsert.README".
#
package require cmdline;

set usage {
nbspinsert -i [-f nbspinfifo] seq type cat code npchidx fname fpath < file
nbspinsert [-f nbspinfifo] seq type cat code npchidx fname fpath
nbspinsert [-f nbspinfifo] < finfolist
};

set optlist {i {f.arg ""}};
array set option [::cmdline::getoptions argv $optlist $usage];
set argc [llength $argv];

if {$option(f) ne ""} {
    set nbspinfifo $option(f);
} else {
    ## The common defaults
    set _defaultsfile "/usr/local/etc/nbsp/filters.conf";
    if {[file exists ${_defaultsfile}] == 0} {
	puts "${_defaultsfile} not found.";
	return 1;
    }
    source ${_defaultsfile};
    unset _defaultsfile;

    # nbspd.init is needed to get the fifo
    set nbspd_init_file [file join $common(libdir) nbspd.init];
    if {[file exists $nbspd_init_file] == 0} {
	puts "$nbspd_init_file not found.";
	return 1;
    }
    source $nbspd_init_file;
    unset nbspd_init_file;

    set nbspinfifo $nbspd(infeedfifo);
}

proc err_msg {s} {

    global argv0;

    set name [file tail $argv0];

    puts stderr "$name: $s";
    exec logger -t $name $s;
}

proc err {s} {

    err_msg $s;

    exit 1;
}

proc process {finfo nbspinfifo} {

    global option;

   if {[llength [split $finfo]] != 7} {
	return -code error "Not enough arguments: $finfo.";
   }

    if {$option(i) == 1} {
        save_fpath $finfo;
    }

    set status [catch {
	sendtof $finfo $nbspinfifo;
    } errmsg];
    
    if {($status != 0) && ($option(i) == 1)} {
	delete_fpath $finfo;
    }

    if {$status != 0} {
       return -code error $errmsg;
    }
}

proc save_fpath {finfo} {

    scan $finfo "%u %d %d %d %d %s %s" seq type cat code npchidx fname fpath;
    set fbasename [file tail $fpath];
    set fdirname [file dirname $fpath];
    set spooldir [file dirname $fdirname];

    if {[file isdirectory $spooldir] == 0} {
	return -code error "Directory $spooldir does not exist.";
    }

    set status [catch {
	if {[file isdirectory $fdirname] == 0} {
	    file mkdir $fdirname;
	}
	fconfigure stdin -translation binary -encoding binary;
	set fout [open $fpath w];
	fconfigure $fout -translation binary -encoding binary;
	puts -nonewline $fout [read stdin];
    } errmsg];

    if {[info exists fout]} {
	catch {close $fout};
    }

    if {$status != 0} {
	file delete $fpath;
	return -code error $errmsg;
    }
}

proc delete_fpath {finfo} {

    scan $finfo "%u %d %d %d %d %s %s" seq type cat code npchidx fname fpath;

    file delete $fpath;
}

proc sendtof {finfo nbspinfifo} {

   set status [catch {
       set FIFO [open $nbspinfifo {WRONLY NONBLOCK}]
       fconfigure $FIFO -translation binary -encoding binary;
       set finfo_size [string length $finfo];
       puts -nonewline $FIFO [binary format "I" $finfo_size];
       puts $FIFO $finfo;
   } errmsg];

   if {[info exists FIFO]} {
       catch {close $FIFO};
   }

   if {$status != 0} {
       return -code error $errmsg;
   }
}

proc process_finfo_list {nbspinfifo} {

    set status 0;

    while {[gets stdin finfo] >= 0} {
        if {$finfo eq ""} {
	    continue;
        }

	process $finfo $nbspinfifo;
    }
}

#
# main
#
if {$argc == 0} {
    set status [catch {
	process_finfo_list $nbspinfifo;
    } errmsg];

    if {$status != 0} {
	err $errmsg;
    }
}

set finfo [join $argv " "];

set status [catch {process $finfo $nbspinfifo} errmsg];

if {$status != 0} {
    err $errmsg;
}
