1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
/***************************************************************************
*
* $Header: /usr/local/cvsroot/utils/ytree/quit.c,v 1.13 2003/03/16 13:13:29 werner Exp $
*
* Verlassen von ytree
*
*
***************************************************************************/
#include "ytree.h"
/*
quit-to-directory (xtree: alt-Q)(ytree: shift-Q, ^Q)
this uses the Ztree method.
for this to work, a ytree is called via a function in ~/.bashrc
instead of directly. that function generates a pid-unique
file containing a "cd cwd" line before calling ytree, and
sources-in the pid-unique file afterward, thus jumping to the
directory specified.
if ytree rewrites that file to the quit-to dir, the eventual
command-prompt will be in that chosen dir.
thus, a Quit exit jumps to the dir it's already in. a QuitTo
exit jumps to the dir_entry-specified dir.
QuitTo:
- get parent's pid
- get owning uid's homedir
- compose shell stub name
- test:
- exists?
- regular file?
- non-zero length?
- write dir_entry to it, thus replacing the starting-cwd line
- chain to Quit
if user elects not to quit, no harm done:
- rewrite that file to starting-cwd if it passes those checks again
(avoiding race opening vuln)
- return to main program loop
a user can have a bunch of ytrees open, but they'll be run one-per-
shell (i.e. each xterm singletasking) unless the user's ASKING for
trouble, so a given shell-pid will be unique for the xterm that
owns it, even though they're all clustered in the user's homedir.
changes:
- ytree.h add prototype for QuitTo
- filewin.c add call to QuitTo, for Q and ^Q
- dirwin.c add call to QuitTo, for Q and ^Q (q still falls to main)
i've mapped this to ^Q for now on my home machine, but it's probably best to
use just SHIFT-Q for this, following the trend of mapping XtreeGold
Alt-commands to SHIFT-commands in ytree/xtc. that leaves ytree usable in
serial terminals with soft (XOFF/XON) line control protocol.
in .bashrc:
#
# "yt" is part of getting ytree to quit to the target directory rather
# than the starting one (Alt-Q rather than Q, in XTG terms).
# the pid-numbered chdir "bat" will get rewritten to the selected
# dir if ytree is Quit or ^Quit rather than quit, if ytree-1.75b
# (or later version, assuming Werner incorporates my changes) is used.
# This method is based on Kim Henkel's alt-Q batfile method for ZtreeWin.
# --crb3 14jan00/12mar03
#
function yt
{
echo cd $PWD >~/.ytree-$$.chdir
/usr/bin/ytree $1 $2 $3 $4 $5
source ~/.ytree-$$.chdir
rm ~/.ytree-$$.chdir
}
*/
#define MAXPATH (PATH_LENGTH+1)
static int QuitFileCheck(char *fname);
void QuitTo(DirEntry * dir_entry)
{
int parpid;
FILE *qfile;
char nbuf[MAXPATH],qfilename[MAXPATH];
struct passwd *pwp;
GetPath(dir_entry,nbuf);
parpid=getppid();
pwp=getpwuid(getuid());
sprintf(qfilename,"%s/.ytree-%d.chdir",pwp->pw_dir,parpid);
if(!QuitFileCheck(qfilename)){
if( (qfile=fopen(qfilename,"w"))!=NULL)
{
fprintf(qfile,"cd %s\n",nbuf);
fclose(qfile);
}
}
Quit(); /* never come back from a successful quit */
if(!QuitFileCheck(qfilename)){
if( (qfile=fopen(qfilename,"w"))!=NULL)
{
fprintf(qfile,"cd %s\n",Getcwd(NULL,0));
fclose(qfile);
}
}
}
/*
* QuitFileCheck.
* quick safety-check of the shell stub we want to write to.
* if any of these tests fail, somebody's trying to use us for a
* security breach.
*/
static int QuitFileCheck(char *fname)
{
struct stat fstat;
if(stat(fname,&fstat))
return(1);
if(!S_ISREG(fstat.st_mode))
return(1);
if(!fstat.st_size)
return(2);
if(fstat.st_uid != getuid())
return(3);
return(0);
}
void Quit(void)
{
int term;
char path[PATH_LENGTH + 1];
char *p;
term = InputChoise( "quit ytree (Y/N) ?", "YNQq\r\033" );
if( term == 'Y' || term == 'Q' || term == 'q' )
{
if (( p = getenv("HOME") ))
{
sprintf(path, "%s%c%s", p, FILE_SEPARATOR_CHAR, HISTORY_FILENAME);
SaveHistory(path);
}
endwin();
#ifdef XCURSES
XCursesExit();
#endif
exit( 0 );
}
}
|