コード例 #1
0
ファイル: environ.c プロジェクト: viashen07/Minishell_final
int		search_paths(t_env *e)
{
	t_search	env;

	env.paths = ft_strsplit(ft_getenv("PATH", e), ':');
	env.y = 0;
	while (env.y > -1 && env.paths[env.y] != 0)
	{
		env.dirp = opendir(env.paths[env.y]);
		while ((env.entry = readdir(env.dirp)) != NULL)
		{
			if (strcmp(env.entry->d_name, e->args[0]) == 0)
			{
				env.str = ft_strjoin(env.paths[env.y], "/");
				run_exec(ft_strjoin(env.str, env.entry->d_name), e);
				free(env.str);
				env.str = NULL;
				env.y = -2;
			}
		}
		closedir(env.dirp);
		env.y++;
	}
	free_tab(env.paths);
	free(env.paths);
	env.paths = NULL;
	return (env.y);
}
コード例 #2
0
ファイル: jsregexp.c プロジェクト: RareHare/reactos
static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
        jsval_t *r)
{
    match_state_t *match;
    heap_pool_t *mark;
    BOOL b;
    jsstr_t *string;
    HRESULT hres;

    TRACE("\n");

    mark = heap_pool_mark(&ctx->tmp_heap);

    hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &b);
    if(FAILED(hres)) {
        heap_pool_clear(mark);
        return hres;
    }

    if(r) {
        if(b) {
            IDispatch *ret;

            hres = create_match_array(ctx, string, match, &ret);
            if(SUCCEEDED(hres))
                *r = jsval_disp(ret);
        }else {
            *r = jsval_null();
        }
    }

    heap_pool_clear(mark);
    jsstr_release(string);
    return hres;
}
コード例 #3
0
ファイル: zrip2Utf8.c プロジェクト: jamesyan84/zbase
/*
*****************************************************************************
** FUNCTION NAME: charset_detect
**
** FUNCTION INPUTS:
**   @char *buf: The buffer will be detect
**   @int len: buffer size.
**
** FUNCTION DESCRIPTION
**   This function will detect buffer charset by zchardet.
**
** FUNCTION OUTPUTS:
**   Returns NULL when failed or Utf-8 format. Return format.
**
** HISTORY:
** 2008-7-15	Steven Leong	Created
*****************************************************************************
*/
static char* charset_detect(char *buf, int len)
{
	int wfd, rfd, pid;
	fd_set rdfds;
	struct timeval tv;
	char bufArray[BUF_256_BITS] = {0};
	FILE * ptrPipe = NULL;
	char cmdArray[BUF_512_BITS] = {0};
	int n, nRet = -1;

	dprintf("ZChartDet Request(%d) -> %s\n", len, buf);
	/* start the zdev bin */
	if( (pid = run_exec(ZCHAR_DETECT, &wfd, &rfd)) <= 0 ) {
		return NULL;
	}
	/* send cmd */
	if( write_pipe (wfd, buf, len, 5) <= 0 ) {
		goto errOut;
	}

	FD_ZERO (&rdfds);
	FD_SET (rfd, &rdfds);
	tv.tv_sec = ZCHAR_DETECT_TIMEOUT;
	tv.tv_usec = 0;
	select (rfd+1, &rdfds, NULL, NULL, &tv);
	if(FD_ISSET (rfd, &rdfds)){
		n = read(rfd, bufArray, BUF_256_BITS);
		bufArray[n] = '\0';
		if(n < 0){
			/* error or EAGAIN */
			goto errOut;
		}
	}
	else{
		/* timeout */
		goto errOut;
	}

	nRet = 0;
	dprintf("ZChartDet Response -> %s\n", bufArray);

errOut:
	/* kill pid */
	/* 080129, JC, force kill bin */
	sprintf(cmdArray, "kill -9 %d", pid);
	ptrPipe = popen(cmdArray, "r");
	if (ptrPipe) {
		pclose(ptrPipe);
	}
	//kill(pid, SIGKILL);
	/* end force kill */
	if (waitpid(pid, NULL, 0) != pid)
		fprintf(stderr, "Waitpid child error");

	close(wfd);
	close(rfd);
	if(nRet == 0 || strlen(bufArray) > 0)
		return strdup(bufArray);
	return NULL;
}
コード例 #4
0
ファイル: quash.c プロジェクト: ddreilin/Quash
//**************************************************************************
// function to parse/manage/execute commands
//**************************************************************************
void manager(command_t* cmd ){
	 char* temp [MAX_COMMAND_LENGTH];
	 strcpy(temp, cmd->cmdstr);
	 char* tokens = strtok(temp, " ");

	 //cd if the first two chars are cd
	 if (!strcmp(tokens, "cd")){
	 	run_cd( tokens );
	 }
	 //set
	 else if (!strcmp(tokens, "set")){
	 	run_set( tokens);
	 }
	 //echo
	 else if (!strcmp(tokens, "echo")){
	 	run_echo( tokens );
	 }
	 //pwd
	 else if (!strcmp(tokens, "pwd")){
	 	run_pwd( tokens );
	 }
	 //jobs
	 else if (!strcmp(tokens, "jobs")){
	 	run_jobs( cmd, tokens );
	 }
	 //exit command
	 else if (!strcmp(tokens, "exit") || !strcmp(tokens, "quit") )
      terminate(); // Exit Quash
  //run an executable
  else{
    	run_exec(cmd, tokens);
    }
}
コード例 #5
0
static int gencontrol(struct source_control *c)
{
    struct source_control_bin *sb;
    char *out_control;
    char *argv[] = { "gencontrol", "-v", version, "-o", NULL, control_path,
        NULL, NULL, };

    if (out_dir == NULL) {
        fprintf(stderr, "gencontrol: out dir must be set\n");
        return -1;
    }

    for (sb = c->bins; sb != NULL; sb = sb->next) {
        if (asprintf(&out_control, "%s/%s/packages/%s/%s/control", work_dir,
                    out_dir, sb->package, version) == -1)
        {
            perror("gencontrol: asprintf failed");
            return -1;
        }

        argv[6] = sb->package;
        argv[4] = out_control;

        if (run_exec(argv) != 0) {
            fprintf(stderr, "gencontrol: running for %s failed\n", sb->package);
            free(out_control);
            return -1;
        }

        free(out_control);
    }

    return 0;
}
コード例 #6
0
static int unpack(struct source_control *c)
{
    struct control_source *cs;
    int distd_fd, workd_fd;
    int ret = 0, r;
    char *unpack_argv[] = { "./unpack.sh", NULL };

    if (dist_dir == NULL) {
        fprintf(stderr, "unpack: dist dir must be set\n");
        return -1;
    }

    if ((distd_fd = open(dist_dir, O_RDONLY | O_DIRECTORY)) == -1) {
        perror("unpack: open distdir failed");
        return -1;
    }
    if ((workd_fd = open(work_dir, O_RDONLY | O_DIRECTORY)) == -1) {
        perror("unpack: open workdir failed");
        ret = -1;
        goto error_close_dist;
    }

    /* copying distfiles */
    for (cs = c->sources; cs != NULL; cs = cs->next) {


        if (copy_file(distd_fd, cs->source, workd_fd, cs->source) != 0) {
            fprintf(stderr, "unpack: copying source %s failed\n", cs->source);
            ret = -1;
            goto error_close_work;
        }
    }

    /* run unpack script */
    if (pkg_dir == NULL) {
        r = run_exec(unpack_argv);
    } else {
        r = run_exec_env(unpack_argv, c->unpack_depend);
    }
    if (r != 0) {
        fprintf(stderr, "unpack: running unpack script failed\n");
        ret = -1;
        goto error_close_work;
    }

error_close_work:
    close(workd_fd);
error_close_dist:
    close(distd_fd);
    return ret;
}
コード例 #7
0
static int build(struct source_control *c)
{
    int ret;
    char *outdir;
    char *build_argv[] = { "./build.sh", NULL };

    (void) c;

    if (out_dir == NULL) {
        fprintf(stderr, "build: out dir must be set\n");
        return -1;
    }

    /* run build script */
    if (pkg_dir == NULL) {
        if (asprintf(&outdir, "%s/%s", work_dir, out_dir) == -1) {
            perror("build: asprintf failed");
            return -1;
        }
        ret = setenv("PKG_INSTDIR", outdir, 1);
        free(outdir);
        if (ret != 0) {
            perror("build: setting PKG_INSTDIR failed");
            return -1;
        }

        ret = run_exec(build_argv);
    } else {
        if (asprintf(&outdir, "/work/%s", out_dir) == -1) {
            perror("build: asprintf failed");
            return -1;
        }
        ret = setenv("PKG_INSTDIR", outdir, 1);
        free(outdir);
        if (ret != 0) {
            perror("build: setting PKG_INSTDIR failed");
            return -1;
        }

        ret = run_exec_env(build_argv, c->build_depend);
    }

    if (ret != 0) {
        fprintf(stderr, "build: running build script failed\n");
        return -1;
    }

    return 0;
}
コード例 #8
0
ファイル: admin.c プロジェクト: gosudream/netbsd-src
/*
 * callback proc to run a script when admin finishes.
 */
static int
postadmin_proc (const char *repository, const char *filter, void *closure)
{
    char *cmdline;
    const char *srepos = Short_Repository (repository);

    TRACE (TRACE_FUNCTION, "postadmin_proc (%s, %s)", repository, filter);

    /* %c = cvs_cmd_name
     * %R = referrer
     * %p = shortrepos
     * %r = repository
     */
    /*
     * Cast any NULL arguments as appropriate pointers as this is an
     * stdarg function and we need to be certain the caller gets what
     * is expected.
     */
    cmdline = format_cmdline (
#ifdef SUPPORT_OLD_INFO_FMT_STRINGS
	                      false, srepos,
#endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
	                      filter,
	                      "c", "s", cvs_cmd_name,
#ifdef SERVER_SUPPORT
	                      "R", "s", referrer ? referrer->original : "NONE",
#endif /* SERVER_SUPPORT */
	                      "p", "s", srepos,
	                      "r", "s", current_parsed_root->directory,
	                      (char *) NULL);

    if (!cmdline || !strlen (cmdline))
    {
	if (cmdline) free (cmdline);
	error (0, 0, "postadmin proc resolved to the empty string!");
	return 1;
    }

    run_setup (cmdline);

    free (cmdline);

    /* FIXME - read the comment in verifymsg_proc() about why we use abs()
     * below() and shouldn't.
     */
    return abs (run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
			  RUN_NORMAL | RUN_SIGIGNORE));
}
コード例 #9
0
static int run_exec_env(char *script[], struct control_dependency *deps)
{
    struct control_dependency *cd;
    int n, k, r;
    char **argv;

    /* count args */
    for (k = 0; script[k] != NULL; k++);

    /* counting dependencies */
    for (n = 0, cd = deps; cd != NULL; cd = cd->next, n++);

    /* newns withpkgs + -d DIR + n * (-d PKG) + -w WORK -c /work
     * -- k + NULL */
    if ((argv = calloc(2 + 2 + 2 * n + 2 + 5 + k + 1, sizeof(*argv)))
           == NULL)
    {
        perror("run_exec_env: malloc failed");
        return -1;
    }

    n = 0;
    argv[n++] = "newns";
    argv[n++] = "withpkgs";
    argv[n++] = "-d";
    argv[n++] = pkg_dir;
    for (cd = deps; cd != NULL; cd = cd->next) {
        argv[n++] = "-p";
        argv[n++] = cd->package;
    }
    argv[n++] = "-w";
    argv[n++] = work_dir;
    argv[n++] = "-c";
    argv[n++] = "/work";

    for (k = 0; script[k] != NULL; k++)
        argv[n++] = script[k];

    argv[n++] = NULL;

    r = run_exec(argv);
    free(argv);

    return r;
}
コード例 #10
0
ファイル: jsregexp.c プロジェクト: RareHare/reactos
static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
        jsval_t *r)
{
    match_state_t *match;
    jsstr_t *undef_str;
    heap_pool_t *mark;
    BOOL b;
    HRESULT hres;

    TRACE("\n");

    mark = heap_pool_mark(&ctx->tmp_heap);
    hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str = jsstr_undefined()), NULL, &match, &b);
    heap_pool_clear(mark);
    if(!argc)
        jsstr_release(undef_str);
    if(FAILED(hres))
        return hres;

    if(r)
        *r = jsval_bool(b);
    return S_OK;
}
コード例 #11
0
ファイル: logmsg.c プロジェクト: ryo/netbsd-src
/*
 * Builds a temporary file using setup_tmpfile() and invokes the user's
 * editor on the file.  The header garbage in the resultant file is then
 * stripped and the log message is stored in the "message" argument.
 *
 * If REPOSITORY is non-NULL, process rcsinfo for that repository; if it
 * is NULL, use the CVSADM_TEMPLATE file instead.  REPOSITORY should be
 * NULL when running in client mode.
 *
 * GLOBALS
 *   Editor     Set to a default value by configure and overridable using the
 *              -e option to the CVS executable.
 */
void
do_editor (const char *dir, char **messagep, const char *repository,
           List *changes)
{
    static int reuse_log_message = 0;
    char *line;
    int line_length;
    size_t line_chars_allocated;
    char *fname;
    struct stat pre_stbuf, post_stbuf;
    int retcode = 0;

    assert (!current_parsed_root->isremote != !repository);

    if (noexec || reuse_log_message)
        return;

    /* Abort before creation of the temp file if no editor is defined. */
    if (strcmp (Editor, "") == 0)
        error(1, 0, "no editor defined, must use -e or -m");

again:
    /* Create a temporary file.  */
    if( ( fp = cvs_temp_file( &fname ) ) == NULL )
        error( 1, errno, "cannot create temporary file" );

    if (*messagep)
    {
        (void) fputs (*messagep, fp);

        if ((*messagep)[0] == '\0' ||
                (*messagep)[strlen (*messagep) - 1] != '\n')
            (void) fprintf (fp, "\n");
    }
    else
        (void) fprintf (fp, "\n");

    if (repository != NULL)
        /* tack templates on if necessary */
        (void) Parse_Info (CVSROOTADM_RCSINFO, repository, rcsinfo_proc,
                           PIOPT_ALL, NULL);
    else
    {
        FILE *tfp;
        char buf[1024];
        size_t n;
        size_t nwrite;

        /* Why "b"?  */
        tfp = CVS_FOPEN (CVSADM_TEMPLATE, "rb");
        if (tfp == NULL)
        {
            if (!existence_error (errno))
                error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
        }
        else
        {
            while (!feof (tfp))
            {
                char *p = buf;
                n = fread (buf, 1, sizeof buf, tfp);
                nwrite = n;
                while (nwrite > 0)
                {
                    n = fwrite (p, 1, nwrite, fp);
                    nwrite -= n;
                    p += n;
                }
                if (ferror (tfp))
                    error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
            }
            if (fclose (tfp) < 0)
                error (0, errno, "cannot close %s", CVSADM_TEMPLATE);
        }
    }

    (void) fprintf (fp,
                    "%s----------------------------------------------------------------------\n",
                    CVSEDITPREFIX);
    (void) fprintf (fp,
                    "%sEnter Log.  Lines beginning with `%.*s' are removed automatically\n%s\n",
                    CVSEDITPREFIX, CVSEDITPREFIXLEN, CVSEDITPREFIX,
                    CVSEDITPREFIX);
    if (dir != NULL && *dir)
        (void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,
                        dir, CVSEDITPREFIX);
    if (changes != NULL)
        setup_tmpfile (fp, CVSEDITPREFIX, changes);
    (void) fprintf (fp,
                    "%s----------------------------------------------------------------------\n",
                    CVSEDITPREFIX);

    /* finish off the temp file */
    if (fclose (fp) == EOF)
        error (1, errno, "%s", fname);
    if (stat (fname, &pre_stbuf) == -1)
        pre_stbuf.st_mtime = 0;

    /* run the editor */
    run_setup (Editor);
    run_add_arg (fname);
    if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
                             RUN_NORMAL | RUN_SIGIGNORE | RUN_UNSETXID)) != 0)
        error (0, retcode == -1 ? errno : 0, "warning: editor session failed");

    /* put the entire message back into the *messagep variable */

    fp = xfopen (fname, "r");

    if (*messagep)
        free (*messagep);

    if (stat (fname, &post_stbuf) != 0)
        error (1, errno, "cannot find size of temp file %s", fname);

    if (post_stbuf.st_size == 0)
        *messagep = NULL;
    else
    {
        /* On NT, we might read less than st_size bytes, but we won't
           read more.  So this works.  */
        *messagep = (char *) xmalloc (post_stbuf.st_size + 1);
        (*messagep)[0] = '\0';
    }

    line = NULL;
    line_chars_allocated = 0;

    if (*messagep)
    {
        size_t message_len = post_stbuf.st_size + 1;
        size_t offset = 0;
        while (1)
        {
            line_length = getline (&line, &line_chars_allocated, fp);
            if (line_length == -1)
            {
                if (ferror (fp))
                    error (0, errno, "warning: cannot read %s", fname);
                break;
            }
            if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
                continue;
            if (offset + line_length >= message_len)
                expand_string (messagep, &message_len,
                               offset + line_length + 1);
            (void) strcpy (*messagep + offset, line);
            offset += line_length;
        }
    }
    if (fclose (fp) < 0)
        error (0, errno, "warning: cannot close %s", fname);

    /* canonicalize emply messages */
    if (*messagep != NULL &&
            (**messagep == '\0' || strcmp (*messagep, "\n") == 0))
    {
        free (*messagep);
        *messagep = NULL;
    }

    if (pre_stbuf.st_mtime == post_stbuf.st_mtime || *messagep == NULL)
    {
        for (;;)
        {
            (void) printf ("\nLog message unchanged or not specified\n");
            (void) printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n");
            (void) printf ("Action: (abort) ");
            (void) fflush (stdout);
            line_length = getline (&line, &line_chars_allocated, stdin);
            if (line_length < 0)
            {
                error (0, errno, "cannot read from stdin");
                if (unlink_file (fname) < 0)
                    error (0, errno,
                           "warning: cannot remove temp file %s", fname);
                error (1, 0, "aborting");
            }
            else if (line_length == 0
                     || *line == '\n' || *line == 'a' || *line == 'A')
            {
                if (unlink_file (fname) < 0)
                    error (0, errno, "warning: cannot remove temp file %s", fname);
                error (1, 0, "aborted by user");
            }
            if (*line == 'c' || *line == 'C')
                break;
            if (*line == 'e' || *line == 'E')
                goto again;
            if (*line == '!')
            {
                reuse_log_message = 1;
                break;
            }
            (void) printf ("Unknown input\n");
        }
    }
    if (line)
        free (line);
    if (unlink_file (fname) < 0)
        error (0, errno, "warning: cannot remove temp file %s", fname);
    free (fname);
}
コード例 #12
0
ファイル: chansrv.c プロジェクト: eric011/xrdp
int DEFAULT_CC
main(int argc, char **argv)
{
    tbus waiters[4];
    int pid = 0;
    char text[256];
    char *home_text;
    char *display_text;
    char log_file[256];
    enum logReturns error;
    struct log_config logconfig;

    g_init("xrdp-chansrv"); /* os_calls */

    home_text = g_getenv("HOME");

    if (home_text == 0)
    {
        g_writeln("error reading HOME environment variable");
        g_deinit();
        return 1;
    }

    read_ini();
    pid = g_getpid();

    /* starting logging subsystem */
    g_memset(&logconfig, 0, sizeof(struct log_config));
    logconfig.program_name = "XRDP-Chansrv";
    g_snprintf(log_file, 255, "%s/xrdp-chansrv.log", home_text);
    g_writeln("chansrv::main: using log file [%s]", log_file);

    if (g_file_exist(log_file))
    {
        g_file_delete(log_file);
    }

    logconfig.log_file = log_file;
    logconfig.fd = -1;
    logconfig.log_level = LOG_LEVEL_ERROR;
    logconfig.enable_syslog = 0;
    logconfig.syslog_level = 0;
    error = log_start_from_param(&logconfig);

    if (error != LOG_STARTUP_OK)
    {
        switch (error)
        {
            case LOG_ERROR_MALLOC:
                g_writeln("error on malloc. cannot start logging. quitting.");
                break;
            case LOG_ERROR_FILE_OPEN:
                g_writeln("error opening log file [%s]. quitting.",
                          getLogFile(text, 255));
                break;
            default:
                g_writeln("log_start error");
                break;
        }

        g_deinit();
        return 1;
    }

    LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid));
    /*  set up signal handler  */
    g_signal_kill(term_signal_handler); /* SIGKILL */
    g_signal_terminate(term_signal_handler); /* SIGTERM */
    g_signal_user_interrupt(term_signal_handler); /* SIGINT */
    g_signal_pipe(nil_signal_handler); /* SIGPIPE */
    g_signal_child_stop(child_signal_handler); /* SIGCHLD */
    display_text = g_getenv("DISPLAY");
    LOGM((LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text));
    get_display_num_from_display(display_text);

    if (g_display_num == 0)
    {
        LOGM((LOG_LEVEL_ERROR, "main: error, display is zero"));
        g_deinit();
        return 1;
    }

    LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num));
    g_snprintf(text, 255, "xrdp_chansrv_%8.8x_main_term", pid);
    g_term_event = g_create_wait_obj(text);
    g_snprintf(text, 255, "xrdp_chansrv_%8.8x_thread_done", pid);
    g_thread_done_event = g_create_wait_obj(text);
    g_snprintf(text, 255, "xrdp_chansrv_%8.8x_exec", pid);
    g_exec_event = g_create_wait_obj(text);
    g_exec_mutex = tc_mutex_create();
    g_exec_sem = tc_sem_create(0);
    tc_thread_create(channel_thread_loop, 0);

    while (g_term_event > 0 && !g_is_wait_obj_set(g_term_event))
    {
        waiters[0] = g_term_event;
        waiters[1] = g_exec_event;

        if (g_obj_wait(waiters, 2, 0, 0, 0) != 0)
        {
            LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed"));
            break;
        }

        if (g_is_wait_obj_set(g_term_event))
        {
            break;
        }

        if (g_is_wait_obj_set(g_exec_event))
        {
            g_reset_wait_obj(g_exec_event);
            run_exec();
        }
    }

    while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event))
    {
        /* wait for thread to exit */
        if (g_obj_wait(&g_thread_done_event, 1, 0, 0, 0) != 0)
        {
            LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed"));
            break;
        }
    }

    /* cleanup */
    main_cleanup();
    LOGM((LOG_LEVEL_INFO, "main: app exiting pid %d(0x%8.8x)", pid, pid));
    g_deinit();
    return 0;
}
コード例 #13
0
ファイル: logmsg.cpp プロジェクト: acml/cvsnt
/*
 * Builds a temporary file using setup_tmpfile() and invokes the user's
 * editor on the file.  The header garbage in the resultant file is then
 * stripped and the log message is stored in the "message" argument.
 * 
 * If REPOSITORY is non-NULL, process rcsinfo for that repository; if it
 * is NULL, use the CVSADM_TEMPLATE file instead.
 */
void do_editor (const char *dir, char **messagep, const char *repository, List *changes)
{
    static int reuse_log_message = 0;
    char *line;
    int line_length;
    size_t line_chars_allocated;
    char *fname;
    struct stat pre_stbuf, post_stbuf;
    int retcode = 0;

    if (noexec || reuse_log_message)
		return;

    /* Abort creation of temp file if no editor is defined */
    if (strcmp (Editor, "") == 0)
		error(1, 0, "no editor defined, must use -e or -m");

	/* Create a temporary file */
	/* FIXME - It's possible we should be relying on cvs_temp_file to open
	* the file here - we get race conditions otherwise.
	*/
	fname = cvs_temp_name ();
again:
	if ((fp = CVS_FOPEN (fname, "w+")) == NULL)
		error (1, 0, "cannot create temporary file %s", fname);

	if (*messagep)
	{
		fprintf (fp, "%s", *messagep);

		if ((*messagep)[0] == '\0' ||
			(*messagep)[strlen (*messagep) - 1] != '\n')
			fprintf (fp, "\n");
	}

    if (repository != NULL)
	{
		rcsinfo_param_t args;
		args.directory = Short_Repository(repository);
		args.message=NULL;
		/* tack templates on if necessary */
		TRACE(3,"run rcsinfo trigger");
		if(!run_trigger(&args,rcsinfo_proc) && args.message)
		{
			fprintf(fp,"%s",args.message);
			if (args.message[0] == '\0' || args.message[strlen(args.message) - 1] != '\n')
				fprintf (fp, "\n");
		}
	}
    else
    {
		FILE *tfp;
		char buf[1024];
		size_t n;
		size_t nwrite;

		/* Why "b"?  */
		tfp = CVS_FOPEN (CVSADM_TEMPLATE, "rb");
		if (tfp == NULL)
		{
			if (!existence_error (errno))
			error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
		}
		else
		{
			while (!feof (tfp))
			{
				char *p = buf;
				n = fread (buf, 1, sizeof buf, tfp);
				nwrite = n;
				while (nwrite > 0)
				{
					n = fwrite (p, 1, nwrite, fp);
					nwrite -= n;
					p += n;
				}
				if (ferror (tfp))
					error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
			}
			if (fclose (tfp) < 0)
				error (0, errno, "cannot close %s", CVSADM_TEMPLATE);
		}
	}

	fprintf (fp,"%s----------------------------------------------------------------------\n",CVSEDITPREFIX);
#ifdef _WIN32
#if (CVSNT_SPECIAL_BUILD_FLAG != 0)
	if (strcasecmp(CVSNT_SPECIAL_BUILD,"Suite")!=0)
#endif
	{
	fprintf (fp,"%s     Committed on the Free edition of March Hare Software CVSNT Server\n",CVSEDITPREFIX);
	fprintf (fp,"%s     Upgrade to CVS Suite for more features and support:\n",CVSEDITPREFIX);
	fprintf (fp,"%s           http://march-hare.com/cvsnt/\n",CVSEDITPREFIX);
	fprintf (fp,"%s----------------------------------------------------------------------\n",CVSEDITPREFIX);
    }
#endif
	fprintf (fp,"%sEnter Log.  Lines beginning with `%.*s' are removed automatically\n%s\n",
				CVSEDITPREFIX, CVSEDITPREFIXLEN, CVSEDITPREFIX,CVSEDITPREFIX);
	if (dir != NULL && *dir)
		fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,	dir, CVSEDITPREFIX);
	if (changes != NULL)
		setup_tmpfile (fp, CVSEDITPREFIX, changes);
	fprintf (fp,"%s----------------------------------------------------------------------\n",
				CVSEDITPREFIX);

	/* finish off the temp file */
	if (fclose (fp) == EOF)
		error (1, errno, "%s", fname);
	if ( CVS_STAT (fname, &pre_stbuf) == -1)
		pre_stbuf.st_mtime = 0;

	/* run the editor */
	run_setup (Editor);
	run_arg (fname);
	if ((retcode = run_exec (true)) != 0)
		error (0, retcode == -1 ? errno : 0, "warning: editor session failed");

	/* put the entire message back into the *messagep variable */
	fp = open_file (fname, "r");

	if (*messagep)
		xfree (*messagep);

	if ( CVS_STAT (fname, &post_stbuf) != 0)
		error (1, errno, "cannot find size of temp file %s", fname);

	if (post_stbuf.st_size == 0)
		*messagep = NULL;
	else
	{
		/* On NT, we might read less than st_size bytes, but we won't
		read more.  So this works.  */
		*messagep = (char *) xmalloc (post_stbuf.st_size + 1);
 		*messagep[0] = '\0';
	}

	line = NULL;
	line_chars_allocated = 0;

	if (*messagep)
	{
		size_t message_len = post_stbuf.st_size + 1;
		size_t offset = 0;
		while (1)
		{
			line_length = getline (&line, &line_chars_allocated, fp);
			if (line_length == -1)
			{
				if (ferror (fp))
					error (0, errno, "warning: cannot read %s", fname);
				break;
			}
			if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
				continue;
			if (offset + line_length >= message_len)
			expand_string (messagep, &message_len, offset + line_length + 1);
			strcpy (*messagep + offset, line);
			offset += line_length;
		}
	}
	
	if (fclose (fp) < 0)
		error (0, errno, "warning: cannot close %s", fname);

	if (pre_stbuf.st_mtime == post_stbuf.st_mtime || *messagep == NULL || strcmp (*messagep, "\n") == 0)
	{
		for (;;)
		{
			printf ("\nLog message unchanged or not specified\n");
			printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n");
			printf ("Action: (continue) ");
			fflush (stderr);
			fflush (stdout);
			line_length = getline (&line, &line_chars_allocated, stdin);
			if (line_length < 0)
			{
				error (0, errno, "cannot read from stdin");
				if (unlink_file (fname) < 0)
					error (0, errno, "warning: cannot remove temp file %s", fname);
				error (1, 0, "aborting");
			}
			else if (line_length == 0 || *line == '\n' || *line == 'c' || *line == 'C')
				break;
			if (*line == 'a' || *line == 'A')
			{
				if (unlink_file (fname) < 0)
					error (0, errno, "warning: cannot remove temp file %s", fname);
				error (1, 0, "aborted by user");
			}
			if (*line == 'e' || *line == 'E')
				goto again;
			if (*line == '!')
			{
				reuse_log_message = 1;
				break;
			}
			printf ("Unknown input\n");
		}
    }
    if (line)
		xfree (line);
    if (unlink_file (fname) < 0)
		error (0, errno, "warning: cannot remove temp file %s", fname);
    xfree (fname);
}