ex_mkrc(
    exarg_T	*eap)
{
    FILE	*fd;
    int		failed = FALSE;
    char_u	*fname;
#ifdef FEAT_BROWSE
    char_u	*browseFile = NULL;
#endif
#ifdef FEAT_SESSION
    int		view_session = FALSE;
    int		using_vdir = FALSE;	/* using 'viewdir'? */
    char_u	*viewFile = NULL;
    unsigned	*flagp;
#endif

    if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview)
    {
#ifdef FEAT_SESSION
	view_session = TRUE;
#else
	ex_ni(eap);
	return;
#endif
    }

#ifdef FEAT_SESSION
    /* Use the short file name until ":lcd" is used.  We also don't use the
     * short file name when 'acd' is set, that is checked later. */
    did_lcd = FALSE;

    /* ":mkview" or ":mkview 9": generate file name with 'viewdir' */
    if (eap->cmdidx == CMD_mkview
	    && (*eap->arg == NUL
		|| (vim_isdigit(*eap->arg) && eap->arg[1] == NUL)))
    {
	eap->forceit = TRUE;
	fname = get_view_file(*eap->arg);
	if (fname == NULL)
	    return;
	viewFile = fname;
	using_vdir = TRUE;
    }
    else
#endif
	if (*eap->arg != NUL)
	fname = eap->arg;
    else if (eap->cmdidx == CMD_mkvimrc)
	fname = (char_u *)VIMRC_FILE;
#ifdef FEAT_SESSION
    else if (eap->cmdidx == CMD_mksession)
	fname = (char_u *)SESSION_FILE;
#endif
    else
	fname = (char_u *)EXRC_FILE;

#ifdef FEAT_BROWSE
    if (cmdmod.browse)
    {
	browseFile = do_browse(BROWSE_SAVE,
# ifdef FEAT_SESSION
		eap->cmdidx == CMD_mkview ? (char_u *)_("Save View") :
		eap->cmdidx == CMD_mksession ? (char_u *)_("Save Session") :
# endif
		(char_u *)_("Save Setup"),
		fname, (char_u *)"vim", NULL,
		(char_u *)_(BROWSE_FILTER_MACROS), NULL);
	if (browseFile == NULL)
	    goto theend;
	fname = browseFile;
	eap->forceit = TRUE;	/* since dialog already asked */
    }
#endif

#if defined(FEAT_SESSION) && defined(vim_mkdir)
    /* When using 'viewdir' may have to create the directory. */
    if (using_vdir && !mch_isdir(p_vdir))
	vim_mkdir_emsg(p_vdir, 0755);
#endif

    fd = open_exfile(fname, eap->forceit, WRITEBIN);
    if (fd != NULL)
    {
#ifdef FEAT_SESSION
	if (eap->cmdidx == CMD_mkview)
	    flagp = &vop_flags;
	else
	    flagp = &ssop_flags;
#endif

#ifdef MKSESSION_NL
	/* "unix" in 'sessionoptions': use NL line separator */
	if (view_session && (*flagp & SSOP_UNIX))
	    mksession_nl = TRUE;
#endif

	/* Write the version command for :mkvimrc */
	if (eap->cmdidx == CMD_mkvimrc)
	    (void)put_line(fd, "version 6.0");

#ifdef FEAT_SESSION
	if (eap->cmdidx == CMD_mksession)
	{
	    if (put_line(fd, "let SessionLoad = 1") == FAIL)
		failed = TRUE;
	}

	if (eap->cmdidx != CMD_mkview)
#endif
	{
	    /* Write setting 'compatible' first, because it has side effects.
	     * For that same reason only do it when needed. */
	    if (p_cp)
		(void)put_line(fd, "if !&cp | set cp | endif");
	    else
		(void)put_line(fd, "if &cp | set nocp | endif");
	}

#ifdef FEAT_SESSION
	if (!view_session
		|| (eap->cmdidx == CMD_mksession
		    && (*flagp & SSOP_OPTIONS)))
#endif
	    failed |= (makemap(fd, NULL) == FAIL
				   || makeset(fd, OPT_GLOBAL, FALSE) == FAIL);

#ifdef FEAT_SESSION
	if (!failed && view_session)
	{
	    if (put_line(fd, "let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0") == FAIL)
		failed = TRUE;
	    if (eap->cmdidx == CMD_mksession)
	    {
		char_u *dirnow;	 /* current directory */

		dirnow = alloc(MAXPATHL);
		if (dirnow == NULL)
		    failed = TRUE;
		else
		{
		    /*
		     * Change to session file's dir.
		     */
		    if (mch_dirname(dirnow, MAXPATHL) == FAIL
					    || mch_chdir((char *)dirnow) != 0)
			*dirnow = NUL;
		    if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR))
		    {
			if (vim_chdirfile(fname, NULL) == OK)
			    shorten_fnames(TRUE);
		    }
		    else if (*dirnow != NUL
			   && (ssop_flags & SSOP_CURDIR) && globaldir != NULL)
		    {
			if (mch_chdir((char *)globaldir) == 0)
			    shorten_fnames(TRUE);
		    }

		    failed |= (makeopens(fd, dirnow) == FAIL);

		    /* restore original dir */
		    if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR)
			|| ((ssop_flags & SSOP_CURDIR) && globaldir != NULL)))
		    {
			if (mch_chdir((char *)dirnow) != 0)
			    emsg(_(e_prev_dir));
			shorten_fnames(TRUE);
		    }
		    vim_free(dirnow);
		}
	    }
	    else
	    {
		failed |= (put_view(fd, curwin, !using_vdir, flagp,
								 -1) == FAIL);
	    }
	    if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save")
								      == FAIL)
		failed = TRUE;
# ifdef FEAT_SEARCH_EXTRA
	    if (no_hlsearch && put_line(fd, "nohlsearch") == FAIL)
		failed = TRUE;
# endif
	    if (put_line(fd, "doautoall SessionLoadPost") == FAIL)
		failed = TRUE;
	    if (eap->cmdidx == CMD_mksession)
	    {
		if (put_line(fd, "unlet SessionLoad") == FAIL)
		    failed = TRUE;
	    }
	}
#endif
	if (put_line(fd, "\" vim: set ft=vim :") == FAIL)
	    failed = TRUE;

	failed |= fclose(fd);

	if (failed)
	    emsg(_(e_write));
#if defined(FEAT_EVAL) && defined(FEAT_SESSION)
	else if (eap->cmdidx == CMD_mksession)
	{
	    /* successful session write - set this_session var */
	    char_u	*tbuf;

	    tbuf = alloc(MAXPATHL);
	    if (tbuf != NULL)
	    {
		if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK)
		    set_vim_var_string(VV_THIS_SESSION, tbuf, -1);
		vim_free(tbuf);
	    }
	}
#endif
#ifdef MKSESSION_NL
	mksession_nl = FALSE;
#endif
    }

#ifdef FEAT_BROWSE
theend:
    vim_free(browseFile);
#endif
#ifdef FEAT_SESSION
    vim_free(viewFile);
#endif
}