/***************************************************************************
 *                         tmpfile_mod.c -  description
 *                            -------------------
 *   begin                : Thu 29 Dec 2005 04:39:30 PM EST
 *   copyright            : (C) 2005 by Terry D. Boldt
 *   email                : fastsnip-wm1@yahoo.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
/*
 *
 *   QTAwk plugin function to create temporary file name for use
 */

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "QTAwk_plugins.h"
/* define some useful constants
 */
#define TRUE  1
#define FALSE 0

/* define End Of String marker
 */
#define EOS '\x000'

typedef struct t_files *t_files_ptr;

/* define the linked list structure for temporary files created
 */
typedef struct t_files {
    unsigned char *tfile_name;
    t_files_ptr    nxt_file;
} t_files;

static t_files_ptr created_files = NULL;
static t_files_ptr last_file = NULL;

/* define initialization function
 */
unsigned QTAwk_init_load_module(
void)
{
    /* array of pointers to string with argument names for loaded functions
     * Here both functions take a single string function
     */
    unsigned char *arguments[] = {
                    "file_pattern",
                    NULL
                    };

    /* declare error return variable
     */
    unsigned char *reg_err;

    /* call function to initialize for installing dynamic function(s)
     */
    QTAwk_register_function_count(2);

    /* now call function to register each dynamic function to load
     *
     * Note that 'QTAwk_register_function' returns a pointer to a string or NULL
     * if no error in registering function. Here we are ignoring the return value
     * until returning from the call.
     * We "should" examine the return value for every call to 'QTAwk_register_function'
     * and report any errors.
     */
    reg_err = QTAwk_register_function("tmpfile_mod_version",NULL,FALSE);
    reg_err = QTAwk_register_function("tempfile",arguments,FALSE);

    QTAwk_set_module_exit_function("tmpfile_shutdown");
    QTAwk_set_module_shutdown_function("tmpfile_shutdown");

    return reg_err ? -1 : 0;
} /* QTAwk_init_load_module */

/* function registered to accomplish actual work.
 *
 * All dynamically loaded functions have the following prototype form:
 *
 *      Variable_ptr loaded_function(unsigned argument_count);
 *
 * Where 'Variable_ptr' is a QTAwk variable defined in the QTAwk plugin
 *  header file "QTAwk_plugins.h"
 *  Do NOT manipulate the fields in the structure directly. Use the function
 *  calls defined in "QTAwk_plugins.h" for that purpose.
 *
 *
 *
 */

/* version string
 */
static unsigned char tmpfile_mod_version_string[] = "Create temporary file name: Version 1.00";

/* function to return module version string
 */
Variable_ptr  tmpfile_mod_version(
void)
{
    Variable_ptr   retval;

    retval = QTAwk_get_variable_set((void *)tmpfile_mod_version_string,STRING_VAL);

    return retval;
} /* time_mod_version */

/*
 * Return name to a temporary file - the file will be be deleted/removed
 * if the module is not unloaded before program termination.
 * The filename pattern passed to 'mkstemp' MUST HAVE last six characetrs
 * equal to "XXXXXX" - do that here to ensure it is done.
 *
 */
Variable_ptr tempfile(
unsigned     arg_cnt)
{
    Variable_ptr   retval = NULL;
    Variable_ptr   filename_pattern;
    unsigned char *tmp_string;
    unsigned char *fp_string;
    size_t         tlen;
    unsigned       type;
    int            mkst;
    t_files_ptr    crnt_file;

    filename_pattern = QTAwk_get_argument(1,NULL);

    type = STRING_VAL;
    tmp_string = (unsigned char *)QTAwk_get_value(filename_pattern,&type);
    tlen = strlen(tmp_string);
    fp_string = QTGrep_getmem(tlen + 7,sizeof(unsigned char));
    strcpy(fp_string,tmp_string);

    /* concatenate suffix
     */
    strcat(fp_string,"XXXXXX");

    /* Now get temporary name
     */
    if ( (mkst = mkstemp(fp_string) ) != -1 ) {
        /* get and set return value
         */
        retval = QTAwk_get_variable_set((void *)fp_string,STRING_VAL);

        crnt_file = (t_files_ptr)QTGrep_getmem(1,sizeof(t_files));
        crnt_file->tfile_name = fp_string;

        if ( created_files == NULL ) {
            created_files = crnt_file;
          } else {
            last_file->nxt_file = crnt_file;
        } /* endif */
        last_file = crnt_file;
    } /* endif */

    return retval;
} /* tempfile */

#if defined( EXIT_FUNCTION )
/* exit function - executed before unloading module. Cannot remove temporary files here
 * but should free memory used in linked list.
 *
 */
unsigned tmpfile_mod_exit(
void)
{
    t_files_ptr b_file;

    printf("Unloading tempfile name module.\n");
    for ( last_file = created_files ; last_file ; last_file = b_file->nxt_file ) {
        /* free memory
         */
        b_file = last_file;
        QTGrep_free_mem(last_file->tfile_name);
        QTGrep_free_mem(last_file);
    } /* endfor */
} /* tmpfile_mod_exit */
#endif // EXIT_FUNCTION

/* exit and shut down function - attempt to remove the temporary files created
 * During shutdown, all open files have been closed before executing module shutdown
 * functions so can safely remove here. Cycle through and execute 'remove' function.
 * since there is nothing to do if there is an error, ignore errors. If the utility
 * had already executed a system function to remove the file, then will get an error
 * here, but that can be safely ignored anyway.
 *
 * If executed during 'unload' function, then must rely that the user has closed
 * any open temporary files and will not be using them any further.
 */
void  tmpfile_shutdown(
void)
{
    t_files_ptr b_file;

    for ( last_file = created_files ; last_file ; last_file = b_file->nxt_file ) {
        /* remove file  and free memory
         * NOTE: ignoring errors
         */
        (void)remove(last_file->tfile_name);
        b_file = last_file;
        QTGrep_free_mem(last_file->tfile_name);
        QTGrep_free_mem(last_file);
    } /* endfor */
} /* tmpfile_shutdown */