diff options
Diffstat (limited to 'win32')
42 files changed, 12821 insertions, 0 deletions
diff --git a/win32/BSDLOGO.BMP b/win32/BSDLOGO.BMP Binary files differnew file mode 100644 index 000000000000..f45c05863153 --- /dev/null +++ b/win32/BSDLOGO.BMP diff --git a/win32/BSDLOGO.ICO b/win32/BSDLOGO.ICO Binary files differnew file mode 100644 index 000000000000..914714f5128b --- /dev/null +++ b/win32/BSDLOGO.ICO diff --git a/win32/BSDLOGO.RC b/win32/BSDLOGO.RC new file mode 100644 index 000000000000..2973a877b203 --- /dev/null +++ b/win32/BSDLOGO.RC @@ -0,0 +1,2 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/BSDLOGO.RC,v 1.3 2004/05/19 18:22:27 christos Exp $*/ +IDI_ICON1 ICON DISCARDABLE "win32/BSDLOGO.ICO" diff --git a/win32/CODING b/win32/CODING new file mode 100644 index 000000000000..212a22b67d7f --- /dev/null +++ b/win32/CODING @@ -0,0 +1,20 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/CODING,v 1.3 2004/05/19 18:22:27 christos Exp $*/ +Read this if you plan to contribute changes to the source: + +Please do not use any heap allocation routine other than: + +1. heap_alloc()/heap_free(), if the memory will never be acessed in a child +process (i.e, is not expected to be inherited). this is a macro defined +in ntport.h + +2. xmalloc()/xfree(), if the memory is to be inherited by a child process. +this is allocated from a seperate heap and is copied to the child during fork(). + +Avoid using C-runtime functions that store static variables +(like strtok, for example). + +It is preferrable to avoid any c-runtime function other than strlen,strcat +etc. + +Thanks. +-amol diff --git a/win32/ChangeLog b/win32/ChangeLog new file mode 100644 index 000000000000..d878ef5d8bb7 --- /dev/null +++ b/win32/ChangeLog @@ -0,0 +1,686 @@ +Rev 7.00 +Sun Aug 11 00:39:38 2002 <amol@AMOLDWHISPHOME> + * various files: Remove GPL'ed termcap code. Partial fix for + horizontal scroll. Fix visiblebell. +Sat May 04 22:38:36 2002 <amol@AMOLDWHISPHOME> + * ntfunc.c: fixed leak in nt_texec ?? (fast exec path). + Removed sourcerc and printrc. +Rev 6.07 +Mon Mar 18 17:54:44 2002 <amol@AMOLDWHISPHOME> + * support.c,fork.c: wow64 (32-bit on ia64) seems to work now. +Rev 6.06 +Sun Mar 17 21:25:28 2002 <amol@AMOLDWHISPHOME> + * support.c,fork.c: attempt wow64 support. +Rev 6.05 +Sat Mar 16 10:53:21 2002 <amol@AMOLDWHISPHOME> + + * console.c: Fix refreshing problems with searching history. + +Rev 6.04 +Fri Mar 01 18:52:30 2002 <amol@AMOLDWHISPHOME> + + * ntfunc.c: Fix another bug. Some associated files were launched twice. + +Rev 6.03 +Mon Feb 18 19:24:47 2002 <amol@AMOLDWHISPHOME> + + * ntfunc.c,support.c: Of course, fix bug introduced by previous fix. + (#! emulation was broken) + +Rev 6.02 +Sun Feb 17 15:10:50 2002 <amol@AMOLDWHISPHOME> + * various files, many fixes, + 1. SetFileApisToOEM: Fix display problems with Euro filenames. + 2. Try explorer associations in fast exec path as well. + 3. Fix bug with TCSHONLYSTARTEXES not working for extensions less + than 3 chars + 4. Fix bug with e_page_up/down that always made them beep. + 5. Fix bug related to backward-search refreshing problem +Wed Oct 10 21:58:50 2001 <amold@AMOLDHOME> + * win32\clip.c: Fix bug in redirection to /dev/clipboard. it should work + now. +Rev 6.00 +Thu Aug 16 18:55:54 2001 <amold@AMOLDHOME> + * win32\clip.c: Integrate with 6.10.02, put e_copy_from_clipboad and + e_paste_from_clipboard back. Document N-S binding in README.NT. +Rev 5.56,5.57 +Tue Jun 19 22:13:52 2001 <amold@AMOLDHOME> + * various files: Remove stacksize builtin. Shift keymap. Sync with + tcsh-6.10.01. e_undosify etc. +Rev 5.55 +Wed Mar 28 17:19:06 2001 <amold@AMOLDHOME> + * misc files: add sourcerc and printrc builtins +Rev 5.54 +Sat Jan 27 18:45:20 2001 <amold@AMOLDHOME> + * win32\ps.c: Fixed bug that made ps crash on NT 4.0 +Rev 5.53 +Thu Nov 30 14:30:03 2000 <amold@SKYNYRD> + * win32\ntfunc.c: 6.10, fix bug in 'start' and TCSHONLYSTARTEXES +Rev 5.52 +Wed Nov 15 03:54:03 2000 <Administrator@AMOLDHOME> + * misc files: integrate 6.09.04 +Rev 5.51 +Thu Jul 20 19:25:41 2000 <amold@AMOLDHOME> + * win32\ps.c: Fix bug in ps.c +Rev 5.50 +Fri Jul 14 20:33:33 2000 <amold@AMOLDHOME> + * various: Fix TCSHONLYSTARTEXES and completion. add e_page_up + and e_page_down editor functions. Some 64-bit work. +Rev 5.49 +Mon Jun 05 17:42:55 2000 <amold@SKYNYRD> + * win32\ntfunc.c: move executable() to NT source. +Rev 5.48 +Mon May 29 14:22:03 2000 <amold@SKYNYRD> + * various files: Finally integrate patches for "start <directory>". + Also, completions will recognize extensions from TCSHONLYSTARTEXES +Rev 5.46 +Wed Mar 01 10:32:22 2000 <amold@SKYNYRD> + * win32\ntfunc.c,win32\support.c: Make NTlamepathfix consistent + across fast exec, launched associations as well as normal + command execution. +Rev 5.45 +Fri Jan 07 11:50:03 2000 <amold@SKYNYRD> + * win32\support.c, ntfunc.c, Makefile.win32: Remove stack probing + in fork() by commiting 1/2MB of the thread stack instead of the + default page size. To reduce the footprint of spawned threads + (for clipboard or SIGCHILD), a new builtin stacksize has been + added. +Rev 5.44 +Thu Jan 06 12:28:55 2000 <amold@SKYNYRD> + * win32\stdio.c: Fixed serious bug that would cause backticked + expressions in shell scripts to not run. Should also fix hangs + with piped builtins like "bindkey | wc -l" +Rev 5.43 +Fri Oct 29 11:10:58 1999 <amold@SKYNYRD> + * win32\support.c: added NTnoquoteprotect variable. +Rev 5.42 +Sun Oct 24 11:52:06 1999 <amold@SKYNYRD> + * win32\ntfunc.c: Fix $? on fast exec path. +Rev 5.41 +Fri Oct 08 11:08:41 1999 <amold@SKYNYRD> + * win32\support.c: Support for NTcaseifypwd +Rev 5.37 +Fri Apr 02 11:51:54 1999 <amold@SKYNYRD> + * tc.func.c: Fixed bug that showed files in ls //server/share + as directories. +Rev 5.36 +Wed Mar 24 14:36:50 1999 <amold@SKYNYRD> + * tc.func.c, win32\stdio.c: Cleaned up code. fixed bug + that would prevent ls //unc (introduced in 5.35, of course). +Rev 5.34,5.35 +Tue Mar 23 12:07:52 1999 <amold@SKYNYRD> + * various files: Fix for ls c:/bin/* and paths with spaces +Rev 5.33 +Wed Mar 17 12:37:50 1999 <amold@SKYNYRD> + * win32\support.c: Fix bug to resume converting $HOME to + '/'-delimited. +Mon Mar 15 11:15:51 1999 <amold@SKYNYRD> + * sh.func.c: Make setting environment variables case-insensitve +Rev 5.321 +Mon Mar 15 09:46:34 1999 <amold@SKYNYRD> + * win32\ntfunc.c: remove stupid hardcoded breakpoint. Hit when + executing scripts, batch files, etc. +Rev 5.32 +Sat Mar 13 12:58:34 1999 <amold@SKYNYRD> + * various files: Use hashtable to check command spelling. Will + eliminate bogus corrections on NT. Code re-org in support.c. + Also backed out agressive correction introduced in 5.29. +Rev 5.29 +Tue Feb 09 16:23:39 1999 <amold@SKYNYRD> + * tw.parse.c,tw.spell.c: Aggressive spelling correction. Apppend + ".exe" to a command while doing spellcheck. +Rev 5.28 +Wed Feb 03 16:58:46 1999 <amold@SKYNYRD> + * various files: speed up argument parsing in exec. should + make commands with long argument strings run considerably faster. + Speed up argument parsing for the start builtin as above. remove + shell limit on command length. + Code cleanups, move heap_init() to executable entry point instead + of fork_init() to prevent heap conflicts in child processes. +Rev 5.27 +Fri Jan 08 10:36:24 1999 <amold@SKYNYRD> + * win32\io.c: ignore ctrl-space and ctrl-@ if NOREBIND + is not set. This should fix the bug which caused altgr-q + to not work, for example. +Rev 5.261 +Fri Nov 20 15:34:32 1998 <amold@SKYNYRD> + * sh.sem.c: fixed stupid bug that neutralized the fast exec + path. set NTslowexec if you get funky behaviour from the shell. +Rev 5.26 +Fri Nov 20 15:13:51 1998 <amold@SKYNYRD> + * ed.refresh.c: Patch from taga nayuta for fixing problems + with rprompt and prompt both having ANSI escapes. +Rev 5.25 +Tue Nov 03 12:23:20 1998 <amold@SKYNYRD> + * win32\support.c: Win9x-specific fix for apps which may + have been started from a directory with a '.' in the name, but + without specifying the extension. e.g., c:/foo.bar/baz +Rev 5.24 +Sat Oct 31 16:12:20 1998 <amold@SALEMS_LOT> + * tc.bind.c,win32\nt.bind.c: Bindkey extensions for N-C + N-M. See README.NT for details. Fixed bug in clipboard + pasting on win95 +Rev 5.23 +Fri Oct 16 12:51:25 1998 <amold@SKYNYRD> + * win32\support.c: improve support for win32 GUI app + detection on Win9x (for TCSH_NOASYNCGUI). +Rev 5.21 +Tue Oct 06 12:15:30 1998 <amold@SKYNYRD> + * sh.dir.c,sh.exec.c: Synced with tcsh-6.08 and applied + patches to that same. (setenv HOME foo crash, and + compilation problem with sh.exec.c) +Rev 5.202 +Thu Oct 01 11:55:53 1998 <amold@SKYNYRD> + * win32\io.c, sh.exec.c: KANJI+multibyte fixes from + taga nayuta. + Fix for "where" failing with directories that had '.' in + their name. +Rev 5.18 +Fri Sep 11 08:21:18 1998 <amold@SKYNYRD> + * win32\clip.c: Fixed bug that caused crashes when pasting + international characters from clipboard using e_paste... +Rev 5.17 +Tue Sep 08 11:04:35 1998 <amold@SKYNYRD> + * tc.func.c: Bugfix for hang when rmstar is set. +Rev 5.16 +Wed Aug 26 10:18:42 1998 <amold@SKYNYRD> + * win32\ntfunc.c,sh.dir.c: Fixed bug in interaction between + TCSHONLYSTARTEXES and "start". Fixed bug that caused a crash + if you tried set home=C:\\ (which is WRONG anyway). +Rev 5.15 +Tue Aug 04 14:48:32 1998 <amold@SKYNYRD> + * ed.chared.c,ed.defns.c,ed.decls.h: Added e_dosify_prev. See + README.NT for details. +Rev 5.14 +Tue Jul 28 10:17:53 1998 <amold@SKYNYRD> + * win32\ntfunc.c: change in behaviour of TCSHONLYSTARTEXES. Please + check README.NT for details. +Rev 5.12 +Sat Jul 18 13:12:39 1998 <amold@SKYNYRD> + * win32\ntfunc.c: Patch from taga nayuta for start <URL> +Rev 5.11 +Tue Jul 14 15:55:32 1998 <amold@SKYNYRD> + * ed.screen.c: Changed literal spec. in prompt to use ANSI + sequences instead of old hack. This is made necessary by the + color-ls patch. It does not make any sense to have two methods + of parsing these strings. +Rev 5.10 +Tue Jul 14 12:40:41 1998 <amold@SKYNYRD> + * sh.sem.c: Check for NTslowexec before mangling the syntax + tree. +Rev 5.09 +Sun Jul 12 17:13:09 1998 <amold@SALEMS_LOT> + * win32\io.c,console.c: patches from TAGA nayuta. Includes fix for + clear-screen, color-ls and ctrl-space, ctrl-@ +Rev 5.04-5.08 +Sat Jul 11 21:19:47 1998 <amold@SALEMS_LOT> + * win32\signal.c: Hacked signal mechanism to deliver signal in + the main thread. May cause crashes/hangs. Can be compiled out. +Rev 5.03 +Wed Jul 08 17:06:41 1998 <amold@SKYNYRD> + * ed.refresh.c: Fixed bug in edit-time refresh of lines > 1 line. +Rev 5.02 +Mon Jul 06 11:08:12 1998 <amold@SKYNYRD> + * various: separated nt-specific builtins from the rest of the + shell. Makes maintainence easier. +Rev 5.00 +Tue Jun 30 14:46:26 1998 <amold@SKYNYRD> + * various: synced with tcsh-6.07.08. Fixed bug in alias + interactions with fast exec. make settc work with li and + co. +Rev 4.09 +Mon Jun 01 13:54:05 1998 <amold@SKYNYRD> + * win32\ntfunc.c: Fixed fast exec path to use the hash +Rev 4.07 +Sat May 30 13:37:26 1998 <amold@SKYNYRD> + * sh.sem.c: Fixed bug in dollar expansion in the fast exec + path. + * win32\clip.c: Removed 4Kb clipboard limitation. + + Misc. code cleanup. +Rev 4.05 +Thu May 28 14:17:57 1998 <amold@SKYNYRD> + * win32\support.c,win32\ntfunc.c,sh.sem.c: Fixed bug that + prevented execution of programs whose path had spaces in them. + Added optimization for simple commands to avoid fork(). Please + read about NTslowexec in README.NT if you see any weird + behaviour from the shell. +Rev 4.03 +Fri May 22 08:19:32 1998 <amold@SKYNYRD> + * win32\support.c: Fixed parsing of quoted args to child processes. + hopefully. +Rev 4.02 +Thu May 14 18:52:22 1998 <amold@SKYNYRD> + * win32\support.c: Fixed bug that caused UNC-path-exes to be + spawned in a new window. Also fixed wildcard expansion bug + (ls *.c ) caused by merge with standard distribution. +Rev 4.0 +Thu Apr 23 09:49:28 1998 <amold@SKYNYRD> + + * tcsh-6.07.06 pre-release. Please try it out and see if + anything got broken in integration. + +rev 3.661 +Fri Apr 10 16:48:04 1998 <amold@SKYNYRD> + * tc.const.c: Changed NTONLYSTARTEXES to TCSHONLYSTARTEXES. really. +rev 3.66 +Sat Apr 04 15:22:02 1998 <amold@SKYNYRD> + * win32\support.c: fixed bug that was restricting command line + lengths. +Rev 3.652 +Fri Mar 27 11:26:24 1998 <amold@SKYNYRD> + * tc.prompt.c: Keep server names in prompt when %C is specified. + * win32\ntfunc.c: Fixed crash in the start builtin when options + were specified but no command. +Rev 3.651 +Tue Mar 24 17:53:32 1998 <amold@SKYNYRD> + * win32\ntfunc.c: Took out 512-char limit in setenv. +Rev 3.65 +Wed Mar 11 09:26:43 1998 <amold@SKYNYRD> + * sh.h: Fixed bug that caused problem with 'which' or + crashed the shell when a path component did not have + the drive letter. e.g., '/bin' or set home=/foo +Rev 3.643 +Sun Mar 08 12:55:04 1998 <amold@SKYNYRD> + * sh.dir.c: Fixed crash in echo `dirs` +Rev 3.641 +Sat Feb 21 12:06:18 1998 <amold@SALEMS_LOT> + * win32\support.c: NTONLYSTARTEXES changed to TCSHONLYSTARTEXES + NTlameargfix done by default. The variable has no effect now. + Both changes due to major restructuring of execve(). It's faster, + but probably not appreciable to the human eye. + +Rev 3.64 +Fri Feb 20 17:08:27 1998 <amold@SKYNYRD> + * win32\support.c: cleaned up execve(), fixed crash in win95 when + trying file associations. + (cleanup may have introduced bugs, be careful) +Rev 3.63 +Thu Feb 12 10:07:10 1998 <amold@SKYNYRD> + * win32\ps.c: psapi.dll no longer needed, but will be used if + it exists (of course, Windows NT only). +Rev 3.62 +Thu Feb 05 11:31:56 1998 <amold@SKYNYRD> + * win32\ps.c: Added -3 argument for the kill builtin. This will + send a WM_CLOSE message to the app's window. May be a useful + way to shut down GUI apps. tcsh itself can also be killed + with this "signal" (maps to a SIGHUP or CTRL_CLOSE_EVENT). + +Rev 3.612 +Fri Jan 30 14:29:44 1998 <amold@SKYNYRD> + * sh.proc.c: Changed kill to take hex pid (0xff...) as well + Probably helps on win95 if you use the builtin ps + to list processes. +Rev 3.611 +Tue Jan 27 17:48:02 1998 <amold@SKYNYRD> + * win32\support.c: of course, the /dev/clipboard stuff had + a bug. +Rev 3.61 +Tue Jan 27 14:04:21 1998 <amold@SKYNYRD> + * win32\clip.c,win32\stdio.c: Hack to treat /dev/clipboard + as a special case for i/o redirection. Limit of 4K, not fully + tested. Use at your own risk. Idea by David Sinck. +Rev 3.60 +Tue Jan 27 09:06:41 1998 <amold@SKYNYRD> + * ed.chared.c,ed.defns.c: added e_dosify_next editor function + to enable converting '/'-delimited paths to '\'-delimited. + For those times when you just have to use xcopy. +Rev 3.59 +Thu Jan 22 11:16:00 1998 <amold@SKYNYRD> + * win32\globals.c,support.c: Added support for starting + GUI apps asynchronously (don't wait for them to terminate). + Can be overridden by setting TCSH_NOASYNCGUI to a non-zero + length. Also put in logic to try appending ".exe" as well + as ".EXE" to a command. This is for some case-sensitive + filesystem drivers out there. +Rev 3.581 +Fri Jan 02 10:26:16 1998 <amold@SKYNYRD> + + * win32\clip.c: Fixed minor bugs and removed shared kill buffer + code. Only the clipboard can be used to share data now. See + README.NT for details on how to use the clipboard. + +Rev 3.58 +Wed Dec 31 13:26:40 1997 <amold@SKYNYRD> + * ed.defns.c,win32\clip.c: Added support for the clipboard + functions. Disabled shared kill buffers +Rev 3.57 +Tue Dec 30 17:42:27 1997 <amold@SKYNYRD> + * ed.chared.c,win32\support.c: Experimental sharing of + kill buffers among all active instances of tcsh. + I'm not sure how well this works yet. +Rev 3.563 +Tue Dec 30 10:32:34 1997 <amold@SKYNYRD> + * sh.func.c: Fixed bug in unsetenv (it wasn't working at all). +Rev 3.561 +Mon Dec 29 11:57:16 1997 <amold@SKYNYRD> + * win32\ps.c: Fixed bug in ps. Also added manadatory + "now" argument to shutdown. +Rev 3.56 +Tue Dec 23 14:05:16 1997 <amold@SKYNYRD> + * win32\ps.c: Added shutdown builtin. +Rev 3.55 +Fri Dec 19 13:28:25 1997 <amold@SKYNYRD> + * win32\ps.c: Added ps builtin. +Rev 3.544 +Fri Dec 12 13:41:52 1997 <amold@SKYNYRD> + * tw.parse.c: Fixed bug in complete=igncase +Rev 3.543 +Wed Dec 10 14:01:12 1997 <amold@SKYNYRD> + * win32\io.c: Fix for redirecting to /dev/null. +Rev 3.542 +Wed Dec 03 10:15:45 1997 <amold@SKYNYRD> + * win32\io.c: Fix for spurious CR's on win95 when + running commands that read from stdin. +Rev 3.541 +Tue Nov 25 11:22:05 1997 <amold@SKYNYRD> + * win32\ntfunc.c: Fix for some bugs with NTONLYSTARTEXES +Rev 3.54 +Mon Nov 24 15:32:45 1997 <amold@SKYNYRD> + * tc.const.c,sh.func.c: Added environment variable + NTONLYSTARTEXES, which can be set on the fly, to + control whether associations (e.g., notepad with .txt) + should be recognized. +Recv 3.53 +Mon Nov 24 13:17:04 1997 <amold@SKYNYRD> + * misc files: Changed copyright to Berkeley. Fixed minor + bugs. +Rev 3.52 +Fri Nov 21 09:41:03 1997 <amold@SKYNYRD> + * win32\fork.c: Fixed bug in environment inheritance. +Rev 3.51 +Mon Nov 17 14:51:57 1997 <amold@SKYNYRD> + * tc.func.c: Fix for ls //server +Rev 3.4,3.5 +Fri Nov 14 09:34:13 1997 <amold@SKYNYRD> + * misc: Integrated into standard distribution. + Feeping creaturism: Added support for file associations. + e.g, start foo.txt will start notepad with foo.txt etc. +Rev 3.325 +Tue Oct 28 16:38:03 1997 <amold@SKYNYRD> + * sh.h: Fix to make $$ inherited by child process. The bug + showed up in tcsh <infile>out.$$, for example +Rev. 3.323,3.324 +Wed Oct 22 13:06:59 1997 <amold@SKYNYRD> + * ntport\support.c: Made hack below a little smarter. Add '.' + only if the command is not found by the usual search. + * ntport\ntfunc.c: Fix to pass arguments on to batch files +Rev. 3.322 +Wed Oct 15 14:37:22 1997 <amold@SKYNYRD> + * ntport\support.c: Win95-only hack to add '.' to the end + of a command that does not have any '.'-s. +Rev. 3.321 +Mon Oct 13 09:47:35 1997 <amold@SKYNYRD> + + * sh.func.c: Fix for TCSHSUBSTHB when the #! command contains only + one word. + * ntport\support.c: Fix for paths with "./" instead of "." on + win95. + +Rev 3.32 +Thu Oct 09 17:01:30 1997 <amold@SKYNYRD> + + * ntport\ntfunc.c,sh.func.c: Hacks for TCSHSUBSTHB. See README.NT + for details. Allegedly makes it easier to run scripts directly + from Unix. + +Rev 3.31 +Mon Oct 06 18:22:10 1997 <amold@SKYNYRD> + + * tc.const.c: Fixed bug in NTlamepathfix. Added variable + NTlameargfix. This will make it possible to run cmd or print + etc. without aliasing them. + +Rev 3.30 +Mon Sep 22 14:52:50 1997 <amold@SKYNYRD> + + * ntport\support.c: Added wrapper for chdir, to convert + '/'s to '\'s on Win95. + +Rev 3.29 +Mon Sep 15 08:52:11 1997 <amold@SKYNYRD> + + * ntport\bogus.c: Fixed bug in ~-expansion. ~foo was being expanded + to $home for the current user. + * sh.func.c: Changed isbfunc to use StrQcmp instead of my own + hacked unqoute_Strcmp. + +Rev 3.281 +Fri Sep 05 15:13:18 1997 <amold@SKYNYRD> + + * ntport\ntfunc.c: Fixed stupid bug in unsetenv. Instead of + unsetting, a garbage value was being filled in. + +Rev 3.27 +Wed Aug 27 19:23:49 1997 <amold@SALEMS_LOT> + + * sh.func.c: Fix for quoting aliased builtins. Thanks to + Vincent Fatica for pointing this bug out. It exists with + the unix version of tcsh 6.07.02 as well. + +Rev 3.262,Rev 3.263 +Tue Aug 26 17:33:38 1997 <amold@SKYNYRD> + + * support.c: Fixed HOSTTYPE string to show NT service packs. + * sh.c: Fix for win95's lameness in parsing c://.tcshrc + If you really want to set a silly home directory like + C:/, it should work now. + +Rev 3.26, 3.261 +Mon Aug 18 17:53:25 1997 <amold@SKYNYRD> + + * sh.dol.c: Fix for echoing input when using $< interactively + * sh.exec.c: Fix for completing directory names properly. For + example, c:/b<tab> will list directories as well as executables. + +Rev 3.25 +Thu Aug 07 07:47:07 1997 <amold@SKYNYRD> + + * sh.exec.c,ntport\ntfunc.c: Added hack to run .cmd or + .bat files. If they are hashed, they shall be run. + +Rev 3.24 +Wed Aug 06 17:36:50 1997 <amold@SKYNYRD> + + * sh.exec.c: Fix for which/where on Win95 + +Rev 3.232 +Wed Aug 06 14:21:01 1997 <amold@SKYNYRD> + + * ntport\support.c: Fix for fix for dirs with spaces in path. + +Rev 3.23 +Thu Jul 31 11:43:56 1997 <amold@SKYNYRD> + + * sh.lex.c,tc.func.c,ntport\io.c: Major code change. CRLF + translation was messing up loops in scripts. The shell would + seek to the wrong offset. Thanks to Rickard Westman for + isolating the problem. The file i/o routines now do no translation. + Everything is done in the shell code itself. This may lead to + unforseen bugs, so beware. + +Rev 3.22 +Mon Jul 28 07:58:24 1997 <amold@SKYNYRD> + + * ed.chared.c: Fix for ^C aborting current input + * ntport\ntfunc.c: Make 'start' print error message if + command is not found. + +Rev 3.21 +Thu Jul 24 08:50:52 1997 <amold@SKYNYRD> + + * ntport\support.c: fix for directories with space in $path + +Rev 3.20 +Thu Jul 17 09:59:32 1997 <amold@SKYNYRD> + + * ntport\console.c: Fix for scroll messing up dislay + +Rev 3.19 +Wed Jul 09 14:20:30 1997 <amold@SKYNYRD> + + * ntport\ntfunc.c: changed 'start' to only use '-' for switches + * ntport\ntfunc.c: added 'cls' builtin. The normal clear-screen function + has been fixed to clear only the visible window. Use cls if you need + to clear the entire buffer. + +Rev 3.18 +Fri Jun 27 14:08:40 1997 <amold@SKYNYRD> + + * ntport\support.c,tc.const.c : Added variable NTlamepathfix, which + when set will replace '/' in the PATH with '\' for child processes. Also + works with the start builtin. + +Rev 3.17 +Tue Jun 24 17:51:17 1997 <amold@SKYNYRD> + + * ntport\nt.who.c: Fix for crashes on exit in win95. + +Rev 3.16 +Fri Jun 20 08:28:58 1997 <amold@SKYNYRD> + + * ntport\ntfunc.c: Fix for env variable fix. Also other misc memory + cleanup things. Env variables greater than 1024 now CANNOT be set. + +Rev 3.15 +Mon Jun 16 19:55:00 1997 <amold@SALEMS_LOT> + + * ntport\ntfunc.c: Fixed buffer overrun problems in nt_set_env. + Environment variables will now be truncated at 1024 bytes. + * sh.proc.,ntport\support.c: nohup foo & now creates a detached process. + This child has no access to the parent's console, and will continue to run + if the parent shell exits and the console goes away. + +Rev 3.14 +Fri Jun 13 08:54:53 1997 <amold@SKYNYRD> + + * dirent.c, signal.c, io.c: minor bugfixes for dirent. Major + fixes for sigint handling. + +Rev 3.12 +Sun Jun 08 13:57:16 1997 <amold@SKYNYRD> + + * ntport\nt.who.c, tc.who.c: Added support for watch(). Needs + more testing. + +Rev 3.11 +Thu Jun 05 16:33:01 1997 <amold@SKYNYRD> + + * ntport\ntfunc.c: added new variable 'oldtitle'. stores the + previous value of title, every time the title builtin is used. + +Rev 3.10 +Wed May 28 13:47:44 1997 <amold@SKYNYRD> + + * ntport\dirent.c: Enhancements for cd //server/<tab> or + ls //server. Basically, enumerate shares as if they were files. + May not work if the server is win95, but I don't give a damn + about that. + +Rev 3.09 +Thu May 22 08:31:19 1997 <amold@SKYNYRD> + + * tw.parse.c: Support for complete=igncase. Like enhance, but + restricted to case-insensitive completion. + +Rev 3.08 +Mon May 19 11:54:22 1997 <amold@SKYNYRD> + + * ntport\io.c: Fix for file descriptor confusion in non-interactive + shell.(Manifested as hangs in emacs compilation, for example) + +Rev 3.07 +Sat May 17 15:12:24 1997 <amold@SKYNYRD> + + * tc.func.c: Fixes to hashbang for #!c:/bin/tcsh.exe<space> + +Rev 3.06 +Thu May 15 08:37:47 1997 <amold@SKYNYRD> + + * ntport\io.c: Fix for heinous append(or lack thereof) redirection + bug. + +Rev 3.06 +Mon May 12 16:19:42 1997 <amold@SKYNYRD> + + * tc.prompt.c: Fix to print drive letter with %c prompt format + +Rev 3.05 +Thu May 08 17:54:12 1997 <amold@SKYNYRD> + + * ntport\ntfunc.c: Restored 'title' builtin + +Rev 3.04 +Wed May 07 14:02:32 1997 <amold@SKYNYRD> + + * sh.c: Fixed comparison with argv[0] for %c prompt format + +Rev 3.03 +Tue Apr 29 15:48:15 1997 <amold@SKYNYRD> + + * sh.sem.c: Really fixed cd this time. + +Rev 3.02 +Fri Apr 25 07:51:26 1997 <amold@SKYNYRD> + + * sh.sem.c: Fix for C: changing drives when implicitcd is set + +Rev 3.01 +Sat Apr 19 16:00:23 1997 amold <amold@SALEMS_LOT> + + * ntport\io.c: Fixed heredoc temp files to be deleted on close. + +Rev 3.0 +Thu Apr 17 09:24:46 1997 <amold@SKYNYRD> + + * ntport\io.c, ntport\fork.c: Fixes for compiling with optimization + turned on. This is a release version. I've named it 3.0 to + differentiate it from the 6.06.02 nt-rev-2.10 junk. + +Rev 1.9-beta +Mon Apr 14 19:26:01 1997 amold <amold@SALEMS_LOT> + + * sh.dol.c: Hacks to fix here documents. (cat <<EOF) + +Rev 1.8-beta +Mon Apr 14 15:27:24 1997 <amold@SKYNYRD> + + * ntport\signal.c: Put in a hack to avoid bad longjmps when ^C is hit. + (showed up as a 0xC00000029 exception) + +Rev 1.7-beta +Fri Apr 11 07:43:39 1997 <amold@SKYNYRD> + + * sh.proc.c: Fix for shell hanging on win95, after running command. + +Rev 1.6-Beta +Thu Apr 10 19:56:57 1997 amold <amold@SALEMS_LOT> + + * tw.parse.c: Fix to recognize C: when doing ls-F + +Rev 1.5-Beta +Wed Apr 09 22:05:51 1997 amold <amold@SALEMS_LOT> + + * ntport\signal.c: fixes for sched builtin. rearchitectured alarm() + +Rev 1.4 Beta +Wed Apr 09 09:24:58 1997 <amold@SKYNYRD> + + * ed.refresh.c: Edit-time refreshing fix from prev. tcsh + +Rev 1.3-Beta +Tue Apr 08 21:02:14 1997 amold <amold@SALEMS_LOT> + + * sh.exec.c, ntport\support.c: Fixed exec builtin. + +Rev 1.2-Beta +Tue Apr 08 19:54:29 1997 amold <amold@SALEMS_LOT> + + * sh.c: Fixed importpath to convert '\' to '/'. This fixes the where + builtin + +Rev 1.1-Beta +Tue Apr 08 08:42:11 1997 <amold@SKYNYRD> + + * sh.func.c: Fixed inheritance of environment variables. + diff --git a/win32/Contributors b/win32/Contributors new file mode 100644 index 000000000000..8ccc71bad284 --- /dev/null +++ b/win32/Contributors @@ -0,0 +1,15 @@ +People who have contributed to tcsh for win32 with bugfixes, functionality, +and other useful pieces of code. If I've left you out, please let me know ! + +(In alphabetical order) + +Tom Kludy (tom.kludy@citrix.com) +Yarek Kowalik (Yarek.Kowalik@Sitraka.com) +Edward Lam +Matt Landau +Avner Lottem (avner.lottem@intel.com) +blucas (?) (blucas@broadcom.com) +Chun-Pong Yu (bol.pacific.net.sg) +TAGA nayuta (nayuta@is.s.u-tokyo.ac.jp) +Mike Thomas (miketh@brisbane.paradigmgeo.com) +Mark Tucker (mtucker@fiji.sidefx.com) diff --git a/win32/Makefile.win32 b/win32/Makefile.win32 new file mode 100644 index 000000000000..cddec24f185f --- /dev/null +++ b/win32/Makefile.win32 @@ -0,0 +1,285 @@ +# $Id: Makefile.win32,v 1.15 2010/05/24 22:19:26 amold Exp $ +# Makefile.std 4.3 6/11/83 +# +# C Shell with process control; VM/UNIX VAX Makefile +# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria +# +# With an input editor, command completion, etc. and ported to all sorts of +# things; Paul Placeway, CIS Dept., Ohio State University +# +# +# Windows NT version: Amol Deshpande, Microsoft Corp. +# + +################################################################ +## CFLAGS. For various -D things, see config.h +################################################################ +# +# These are the default suffixes from .c to .o and -c to get there +# but to use the global optimizer on the mips boxes, see below +# +SUF=obj +CF=-c -nologo + +INCLUDES=-I. -I.. -Iwin32 + +DEBUG_CRTLIBS= libcmtd.lib oldnames.lib libcpmtd.lib +CRTLIBS= libcmt.lib oldnames.lib libcpmt.lib + +EXTRAFLAGS = -DWINNT_NATIVE -DNO_CRYPT -DHAVE_DIRENT_H $(EFL) +WINDOWS_WARNING_LEVEL=-W4 -WX +REST_WARNING_LEVEL=-WX -W3 +ANALYZE_FLAGS = -analyze + + +!if "$(PROCESSOR_ARCHITECTURE)" == "AMD64" +#main code is broken for 64-bit. ignore warnings and pray it works + +REST_WARNING_LEVEL= -W3 +ANALYZE_FLAGS= +IGNORE_64= -wd4244 -wd4267 + +!if "$(WIN64)" == "" +!Message +!Message Assuming x64 compile. pass WIN64=0 in command line if compiling 32-bit +!Message +WIN64=1 +!endif + +!endif + + +!if "$(WIN64)" == "" +WIN64=0 +ARCH=x86 +!else +ARCH=x64 +WIN64=1 +!endif + +BUILD=tcsh-$(ARCH).exe + +!if "$(BLDTYPE)" == "" +BLDTYPE=retail +!endif + +!if "$(BLDTYPE)" == "debug" + + +NTLDFLAGS= -entry:silly_entry -debug +NTCFLAGS = -Zi -DNTDBG -Od +LIBES= user32.lib advapi32.lib kernel32.lib $(DEBUG_CRTLIBS) strsafe.lib + +!else if "$(BLDTYPE)" == "retail" + +NTLDFLAGS= -entry:silly_entry -debug +NTCFLAGS = -Zi -O2 +LIBES= user32.lib advapi32.lib kernel32.lib $(CRTLIBS) strsafe.lib + +!else + +!ERROR Unknown compilation mode $(BLDTYPE). Set debug or retail +!endif + +!if "$(WIN64)" == "1" +NTCFLAGS = $(NTCFLAGS) -Zp8 +!endif + +CFLAGS= -MT $(NTCFLAGS) $(INCLUDES) +LDFLAGS= -nodefaultlib $(NTLDFLAGS) -stack:1048576,524288 + + +CC= cl + +ED= ed +RM= -del +# +# Resources. which icon you want to use. +NTRES = BSDLOGO + +ASSRCS= sh.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.char.c \ + sh.exp.c sh.file.c sh.func.c sh.glob.c sh.hist.c sh.init.c \ + sh.lex.c sh.misc.c sh.parse.c sh.print.c sh.proc.c sh.sem.c \ + sh.set.c sh.time.c sh.char.h sh.dir.h sh.proc.h sh.h +PSSRCS= sh.decls.h glob.c glob.h mi.termios.c mi.wait.h mi.varargs.h ma.setp.c \ + vms.termcap.c +SHSRCS= $(ASSRCS) $(PSSRCS) +SHOBJS= sh.$(SUF) sh.dir.$(SUF) sh.dol.$(SUF) sh.err.$(SUF) sh.exec.$(SUF) \ + sh.char.$(SUF) sh.exp.$(SUF) sh.func.$(SUF) sh.glob.$(SUF) \ + sh.hist.$(SUF) sh.init.$(SUF) sh.lex.$(SUF) sh.misc.$(SUF) \ + sh.parse.$(SUF) sh.print.$(SUF) sh.proc.$(SUF) sh.sem.$(SUF) \ + sh.set.$(SUF) sh.time.$(SUF) glob.$(SUF) mi.termios.$(SUF) \ + ma.setp.$(SUF) + +TWSRCS= tw.decls.h tw.h tw.help.c tw.init.c tw.parse.c tw.spell.c \ + tw.comp.c tw.color.c +TWOBJS= tw.help.$(SUF) tw.init.$(SUF) tw.parse.$(SUF) tw.spell.$(SUF) \ + tw.comp.$(SUF) tw.color.$(SUF) + +EDSRCS= ed.chared.c ed.decls.h ed.defns.c ed.h ed.init.c ed.inputl.c \ + ed.refresh.c ed.xmap.c ed.term.c ed.term.h +EDOBJS= ed.chared.$(SUF) ed.refresh.$(SUF) ed.init.$(SUF) \ + ed.inputl.$(SUF) ed.defns.$(SUF) ed.xmap.$(SUF) ed.term.$(SUF) + +TCSRCS= tc.alloc.c tc.bind.c tc.const.c tc.decls.h tc.disc.c \ + tc.func.c tc.os.c tc.os.h tc.printf.c tc.prompt.c tc.nsl.c \ + tc.sched.c tc.sig.c tc.sig.h tc.str.c sh.types.h tc.vers.c tc.wait.h \ + tc.who.c tc.h +TCOBJS= tc.alloc.$(SUF) tc.bind.$(SUF) tc.const.$(SUF) \ + tc.disc.$(SUF) tc.func.$(SUF) tc.os.$(SUF) tc.printf.$(SUF) tc.nls.$(SUF) \ + tc.prompt.$(SUF) tc.sched.$(SUF) tc.sig.$(SUF) tc.str.$(SUF) \ + tc.vers.$(SUF) tc.who.$(SUF) + +NTSRCS = win32\io.c win32\stdio.c win32\dirent.c win32\signal.c\ + win32\support.c \ + win32\nt.char.c win32\bogus.c win32\console.c win32\fork.c \ + win32\ntfunc.c win32\ntb1.c win32\ntb2.c win32\globals.c \ + win32\nt.who.c win32\ps.c win32\clip.c win32\nt.const.c \ + win32\nt.bind.c win32\nt.screen.c +NTOBJS = io.$(SUF) stdio.$(SUF) dirent.$(SUF) signal.$(SUF) support.$(SUF) \ + nt.char.$(SUF) bogus.$(SUF) console.$(SUF) fork.$(SUF) ntfunc.$(SUF) \ + globals.$(SUF) nt.who.$(SUF) ps.$(SUF) \ + clip.$(SUF) nt.const.$(SUF) nt.bind.$(SUF) nt.screen.$(SUF) + +VHSRCS=$(PVSRCS) $(AVSRCS) + + +ALLSRCS= $(SHSRCS) $(TWSRCS) $(EDSRCS) $(TCSRCS) $(VHSRCS) $(NTSRCS) +DISTSRCS= $(PSSRCS) $(TWSRCS) $(EDSRCS) $(TCSRCS) $(AVSRCS) + + +OBJS= $(SHOBJS) $(TWOBJS) $(EDOBJS) $(TCOBJS) $(NTOBJS) + + +all: $(BUILD) + +$(BUILD): $(OBJS) ntb1.$(SUF) ntb2.$(SUF) win32/$(NTRES).res + link $(LDFLAGS) ntb1.$(SUF) $(OBJS) $(LIBES) ntb2.$(SUF) $(EXTRALIBS) \ + win32/$(NTRES).res $(LOADABLE_RES) -map:tcsh.map -out:$(BUILD) + +gcompress:$(BUILD) + gzip -v9 $(BUILD) + +bintar: gcompress + tar -cvf tcsh-$(ARCH)-bin.tar $(BUILD) win32/README.NT \ + win32/example.tcshrc win32/tcsh-html.tgz win32/bin + gzip -v9 tcsh-$(ARCH)-bin.tar + move tcsh-$(ARCH)-bin.tar.gz .. + +win32srctar: $(NTSRCS) + tar -cvf tcshwin32src.tar win32 --exclude win32/bin + gzip -v9 tcshwin32src.tar + move tcshwin32src.tar.gz .. + + +chlog: + tcsh -fc "echo \<XMP\> > win32\\Changelog.html" + type win32\Changelog >> win32\ChangeLog.html + tcsh -fc "echo \</XMP\> >> win32\\ChangeLog.html" + + + +.c.$(SUF): + $(CC) $(CF) $(CFLAGS) $(REST_WARNING_LEVEL) $(DFLAGS) $(EXTRAFLAGS) $< + + +ed.defns.h: ed.defns.c + -@del $@ + @echo /* Do not edit this file, make creates it. */ > $@ + @echo #ifndef _h_ed_defns >> $@ + @echo #define _h_ed_defns >> $@ + findstr /R [FV]_ ed.defns.c | findstr /B #define >> $@ + @echo #endif /* _h_ed_defns */ >> $@ + +sh.err.h: sh.err.c + -@del $@ + @echo /* Do not edit this file, make creates it. */ > $@ + @echo #ifndef _h_sh_err >> $@ + @echo #define _h_sh_err >> $@ + findstr ERR_ sh.err.c | findstr /B #define >> $@ + @echo #endif /* _h_sh_err */ >> $@ + +tc.const.h: tc.const.c sh.char.h config.h config_f.h sh.types.h sh.err.h + -@del $@ + @echo /* Do not edit this file, make creates it. */ > $@ + @echo #ifndef _h_tc_const >> $@ + @echo #define _h_tc_const >> $@ + @for /f "tokens=1 delims==" %i in ('$(CC) -E $(INCLUDES) $(DFLAGS) $(EXTRAFLAGS) -D_h_tc_const -nologo \ + tc.const.c ^| findstr /c:"Char STR" ^| sort') do @echo extern %i; >> $@ + @echo #endif /* _h_tc_const */ >> $@ + +win32\nt.const.h: win32\nt.const.c sh.char.h config.h config_f.h sh.types.h sh.err.h tc.const.h + -@del $@ + @echo /* Do not edit this file, make creates it. */ > $@ + @echo #ifndef _h_nt_const >> $@ + @echo #define _h_nt_const >> $@ + @for /f "tokens=1 delims==" %i in ('$(CC) -E $(INCLUDES) $(DFLAGS) $(EXTRAFLAGS) -D_h_nt_const -nologo \ + win32\nt.const.c ^| findstr /c:"Char STR" ^| sort') do @echo extern %i; >> $@ + @echo #endif /* _h_nt_const */ >> $@ + +clean: + $(RM) *.$(SUF) sh.prof.c ed.defns.h tc.const.h sh.err.h tc.defs.c + $(RM) *.pdb *.pch *.ilk *.map *.dbg *.res + cd win32 + $(RM) *.res nt.const.h + cd .. + +cleanall: clean + -del $(BUILD) + + +config.h: config_f.h + +TCH=tc.h tc.const.h tc.decls.h tc.os.h tc.sig.h +SHH=sh.h sh.types.h sh.char.h sh.err.h sh.dir.h sh.proc.h pathnames.h \ + sh.decls.h $(TCH) +TWH=tw.h tw.decls.h +EDH=ed.h ed.decls.h + +# EDH +EDINC=sh.$(SUF) sh.func.$(SUF) sh.lex.$(SUF) sh.print.$(SUF) sh.proc.$(SUF) \ + sh.set.$(SUF) tc.bind.$(SUF) tc.os.$(SUF) tc.prompt.$(SUF) \ + tc.sched.$(SUF) tw.parse.$(SUF) +$(EDOBJS) $(EDINC) : $(EDH) + +# SHH +$(OBJS): win32\nt.const.h win32\ntport.h win32\version.h config.h $(SHH) + +# TWH +TWINC=ed.chared.$(SUF) ed.inputl.$(SUF) sh.exec.$(SUF) sh.func.$(SUF) \ + sh.set.$(SUF) tc.func.$(SUF) +$(TWOBJS) $(TWINC): $(TWH) + +# glob.h +glob.$(SUF) sh.glob.$(SUF): glob.h + +# ed.defns.h +EDDINC=tc.bind.$(SUF) tc.func.$(SUF) tc.os.$(SUF) +$(EDOBJS) $(EDDINC): ed.defns.h + +# tc.defs.o +tc.defs.$(SUF): tc.defs.c sh.h + +# too many 64-bit warnings in these files. for now, turn the warning off. +ed.chared.$(SUF): ed.chared.c + $(CC) $(CF) $(CFLAGS) $(DFLAGS) $(EXTRAFLAGS) $(IGNORE_64) ed.chared.c +ed.inputl.$(SUF): ed.inputl.c + $(CC) $(CF) $(CFLAGS) $(DFLAGS) $(EXTRAFLAGS) $(IGNORE_64) ed.inputl.c + +# +# NT dependencies and rules +# +CFLAGS_WX = $(CFLAGS) $(WINDOWS_WARNING_LEVEL) -DWINDOWS_ONLY $(ANALYZE_FLAGS) + +{win32}.c.$(SUF): + $(CC) $(CF) $(CFLAGS_WX) $(DFLAGS) $(EXTRAFLAGS) $< + +fork.$(SUF):win32\fork.c + $(CC) $(CF) $(CFLAGS_WX) $(DFLAGS) $(EXTRAFLAGS) -GS- win32\fork.c + +nt.bind.$(SUF):win32\nt.bind.c ed.defns.h + +nt.screen.$(SUF):win32\nt.screen.c ed.defns.h + +win32/$(NTRES).res: win32/$(NTRES).rc win32/tcshrc.rc + rc -v $(RCFLAGS_WX) -r win32/$(NTRES).rc diff --git a/win32/README.NT b/win32/README.NT new file mode 100644 index 000000000000..ab48e2548adc --- /dev/null +++ b/win32/README.NT @@ -0,0 +1,605 @@ +tcsh Windows NT version +----------------------- + +You can get current binaries for this version of tcsh from +ftp.blarg.net:users/amol/tcsh. + +-------------------------------------------------------------------------- +NT sources for tcsh can be now found in the same place as +the unix tcsh sources, via anonymous ftp from ftp.astron.com. +The location is /pub/tcsh. + +Files to get: + +tcsh-6.xx.tar.gz - Basic Unix source +tcsh-6.xxwin32src.tar.gz - Extracts into "win32" subdirectory of basic source. + +Pre-compiled binaries and html docs for Alpha and x86 can also be +found in the same location. +-------------------------------------------------------------------------- + +Send comments/bug-fixes/questions to amol@blarg.net + +(Any requests to make tcsh more like DOS shells will be ignored. If you +like DOS shells, use them. tcsh provides unix shell behaviour on windows, +not the other way around.) + +Please do not ask me general shell questions either. If you've never +used a unix shell, read the man pages and docs. Read the comp.unix.shell +FAQ. + +Bug reports that do not contain your operating system type will +also be ignored. + +Bug reports that can be solved by reading the docs or README.NT will be +ignored as well. + +Microsoft Corporation has nothing to do with this code. It is not supported in +any fashion by Microsoft. + +----------------------------------------------------------------------------- +This is NOT a Cygwin gcc version. It will not compile with Cygwin gcc or +work seamlessly with Cygwin apps. Do NOT ask me to hack support for Cygwin +'mount points' unless you are willing to provide the translation code. + +To prevent Cygwin applications from expanding wildcards, set the environment +variable CYGWIN to "noglob". i.e., in your .tcshrc, put a line like this: + +setenv CYGWIN noglob + +(Cygwin applications assume that if they are not started from a shell +using the Cygwin runtime, the parent shell does not have the ability to glob. +This is visible as tcsh apparently expanding wildcards for quoted arguments.) + +----------------------------------------------------------------------------- + +All paths MUST be '/'-delimited. Do not expect the shell to work with +DOS-style paths. + + +Compiling: +--------- +You will need sed to generate some headers. + +You must extract the win32src.tar.gz into a subdirectory of the basic +unix source. + +tcsh currently only compiles with Microsoft Visual C++ (2.0 and greater) on +x86 or Alpha platforms. Simply copy config/win32 to config.h and +win32/makefile.win32 to the base directory. + +run nmake -f makefile.win32 + +If you plan to contribute changes, PLEASE read the file CODING + +(Note: This distribution does not have a VC project. To compile the shell, +you will need to open a cmd.exe/command.com window, run vcvars32.bat from +your VC bin subdirectory and then run nmake as above). + + + +Known Bugs: +---------- +* Horizontal scrolling is completely busted. +* The 'time' builtin does not work. + +* There is a hard limit of 64Kb on the size of the command line. This is + an os-specific limit and cannot be changed. + +* Launching applications via explorer associations is slow if the argument + list is large. + +----------------------------------------------------------------------------- +* This section only documents features specific to Windows NT/95 or +* behaviour that is different from the Unix version. For complete tcsh +* documentation, please read the man pages or html docs. +----------------------------------------------------------------------------- + +Version numbers below refer to the tail end of the $version variable, +containing the NT-specific version. For example, + +tcsh 6.09.00 (Astron) 1999-08-16 (i586-Microsoft-Windows2000) options 8b,nls,dl,hb,color,nt-rev-5.40 + +In this case, the NT-specific version is 5.40 + + +Environment Variables: +--------------------- +Environment variables are case-insensitive on NT. tcsh as of 5.33 has +also been changed to reflect this behaviour. Thus, + +setenv FOO bar + +and, + +setenv foo bar + +are equivalent. + +Note that the *value* is, of course, not case-insensitive. + + +Features +-------- + +* No backgrounding/job control. Use 'start' instead + + You can also use + <foo> & + or, + nohup <foo> & + + where <foo> is some arbitrary command. + +DO NOT start console apps with & unless u want them to read/write to your +console. (A "console app" is any 32-bit application that is not GUI based.) + +(nohup foo & will say "foo Done" pretty quickly, but ignore that. There is no +way for the shell to know when the nohupped process dies. Your job may still +be running in the background.) + +* Filenames in the directories under WINNT (or WINDOWS or whatever you call + your windows directory) are hashed only if they are .EXE. + Names which are uppercase (For example, CALC.EXE) will also be hashed as + lowercase,without extension. Thus, "where calc" as well as + "where CALC.EXE" will work. + +(Explanation: tcsh uses a hashtable to track the location of executables. By +default on Unix, all the files in every path element are hashed. Since the +SystemRoot on NT has hundreds of junk files, tcsh will only hash .EXE files. +This hashing is, of course, case-sensitive. Thus CALC.EXE hashes to a +different value than calc.exe would. To enable the shell to work in a Windows +environment, tcsh will hash CALC.EXE as CALC.EXE as well as "calc"). + + +Special Variables +----------------- +* The tcsh "complete" variable can be set to igncase and will cause the shell + to ignore case in completion. This is slightly different from + the behaviour of complete=enhance, which should still work as before. + +* oldtitle: + + Stores the previous value of the console title, when you use + the title builtin below. Use it like so: + + title "$oldtitle" + + to restore the previous title. + +* NTlamepathfix: + + When set, '/'-s in the PATH environment variable will be + changed to '\'. This helps applications started within tcsh that may + not handle Unix-style PATHs. + +* NTslowexec: + + When set, this variable disables attempts to save a fork() by + directly executing simple commands. "Simple" command means one which is + interactive and not piped, niced, nohupped etc. redirecting output of + a command also disables this optimization. + + Since this shortcut feature is new, the variable provides a way to retain + backward compatibility. It may be taken out at some time in the future, if + the shell is found to be stable enough. + + If you see problems like the shell seeming to expand wildcards when it + shouldn't, or other substitutions which should be quoted, set this + variable and see if that fixes the problem. + +* NTnoquoteprotect: + + Ordinarily , if you pass a double quote to a command string, tcsh + will protect the quotes by adding backslashes. For example, + + find . -name '"*.c"' + would get executed as + + find . -name \"*.c\" + + Some applications (MKS find, for example) do not like the '\'. To + prevent tcsh from quoting such arguments, set this variable. + + Of course, it may cause other applications to break, so use at + your own risk. + +* NTcaseifypwd: + + If set, corrects case of current directory when cd'ing into it. Apparently, + some "filesystems" can't handle the default behaviour. Only works on + Windows NT. + +* TCSHSUBSTHB (Environment, NOT shell variable): + + Specifies mappings for hashbang emulation. Should be ';'-separated pairs + of blank-separated mappings. + + For example, + + setenv TCSHSUBSTHB "/usr/local/bin/perl c:/bin/perl.exe;" + + will substitute #!c:/bin/perl.exe for scripts which have + #!/usr/local/bin/perl at the top. + + The final ';' MUST be included. I don't check for errors too + carefully, so it's up to you to supply the exact sequence. + There is a hardcoded limit of 20 such pairs. + + +* TCSHONLYSTARTEXES (Environment variable): + + Can be set on the fly and controls whether associations will be tried + for non-executables. + + ("Associations" here means Explorer file-type associations, that cause, + for example, Microsoft Word to be launched when you type "foo.doc" at + a command prompt. That can have unexpected side-effects like batch files + and perl scripts launching in another window when run from tcsh. ) + + Any changes to this variable will NOT affect the the "start" builtin. + This builtin ALWAYS launches associations, since the whole point of + using "start" is to not block the current shell. + + You can also supply a semi-colon-separated list of extensions for + which to NOT try associations. For example, if the variable is set to + + "cmd;bat", + + .cmd/.bat files will be executed in the same window because the default + association is not used, instead an internal hack feeds them to the + DOS command processor. + + If the file extension does not match the list, the shell will try to + launch an association. + + o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o- + + To achieve the old behaviour of this setting, you must set the + variable to a 1-character value.i.e., + + setenv TCSHONLYSTARTEXES + + should be replaced by + + setenv TCSHONLYSTARTEXES 1 + + This setting, as before, will prevent tcsh from trying associations + for ANY non-executable. + + (a zero-length setting will not work. A length greater than 1 will + be assumed to be a list of extensions as above.) + + o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o- + + + +* TCSH_NOASYNCGUI (Enviroment variable): + + Makes tcsh wait for win32 GUI apps to terminate, instead of returning + immediately. This affects child processes, so it can be set/unset in + the parent shell at any point. + + +NT-specific Builtins +-------------------- +* start: like cmd.exe's start +* title: change the shell title +* cls: Clear the entire console buffer instead of just the visible window. +* ps: list processes running currently. With -w, list window titles as well. + +* shutdown: (works on Windows NT only) + + shutdown -[r|l|f] now + +(Even though no time argument is supported, "now" must be specified, EXCEPT +with -l .This is to prevent you from accidentally shutting the machine down.) + -r reboots, -l logs you off and -f forces apps to terminate. + +The default action is to shut the machine down. + + +* sourcerc: tcsh can be compiled with a stringtable resource that can be + sourced using this command. This feature is designed as a way to avoid + having to copy the .tcshrc to every computer you run tcsh on. The default + resource is a simple version of my .tcshrc. More complicated settings can + then be copied when needed. + +* printrc: print the compiled-in resource that will be sourced by sourcerc. + + +Notes: +----- +* You should probably get the Cygwin utilities from http://cygwin.com + + Things like 'ls' and 'cat' are useful, since we don't have a 'type' or 'dir' + anymore. 'ls' is pretty much a requirement unless you never do 'ls -l'. + + +* tcsh was compiled with Visual C++ >= 4.2. I don't guarantee it will compile + with any other compilers, but it should. It will *not* compile with the + Cygwin gcc port, so don't even tell me about it. + +* It should be pointed out that there is also a Cygwin version of tcsh that + will compile with gcc and provide all the other features emulated by the + Cygwin runtime (like job control, signals, etc.). So, if you are looking for + a way to pretend that you are on Unix, you should use that version. + The same holds true for UWIN as well. + + +Startup Files: +-------------- + +For Windows 95: + <windows_directory>/.tcshrc + For Example, C:\WINDOWS\.tcshrc + +For Windows NT: + version 3.51: <getenv(HOMEDRIVE)/getenv(HOMEPATH)/.tcshrc> + Usually something like C:\USERS\DEFAULT\.tcshrc + + version 4.00: <getenv(USERPROFILE)/.tcshrc) + Usually something like C:\WINNT\USERS\amold\profile\.tcshrc + +These can all be overridden by setting HOME in the user's environment + + + +* TCSHLANG: NLS support + +You can get messages in a specific language by doing: + + setenv TCSHLANG <dll>, where <dll> is the name of the NLS dll. + +tcsh comes with: + + tcshde.dll -> German + tcshfr.dll -> French + tcshsp.dll -> Spanish + tcsh-it.dll -> Italian + + tcshc.dll => Default "C" locale + +You can change the dll at runtime by setting/unsetting this variable. + +You can specify the DLL name, or the complete path, if it is not in your +standard search path. + +(Using tcshc.dll is useless and adds unnecessary overhead. If you are +using English versions, do not install the dlls) + + +Virtual key code bindings: +------------------------- +To use keys like function keys, arrows, insert, etc., the following +form of bindkey must be used: + +bindkey -b N-xxx <command> + +where xxx is either: + a) A number from 1 through 24, representing the fucntion keys. + For example, bindkey -b N-1 run-help + + b) The strings "pgup","pgdown","end","home", "left","up","right","down", + "ins","del" + For example, bindkey -b N-del delete-char + +Here are the bindings I use in my .tcshrc: + +# NT specific bindkey extensions + bindkey -b N-up up-history + bindkey -b N-down down-history + bindkey -b N-right forward-char + bindkey -b N-left backward-char + bindkey -b N-del delete-char + bindkey -b N-ins overwrite-mode + bindkey -b N-1 which-command + bindkey -b N-2 expand-history + bindkey -b N-3 complete-word-raw + bindkey -b N-home beginning-of-line + bindkey -b N-end end-of-line + + bindkey -b N-pgup e_page_up + bindkey -b N-pgdown e_page_down + +(Note that on Win9x, you must set your console window to NOT be Auto +sized, and you must use the "settc" builtin to increase and then reduce +back the number of lines, in order to get a scrollbar. pgup and +pgdown will not work without a scroll bar) + + +To bind ctrl or alt combinations, use the following as examples. + + bindkey -b N-C-left backward-word + bindkey -b N-M-right forward-word + +For Shift combinations: + bindkey -b N-S-1 backward-word + +Clipboard support +----------------- +Since version 3.58, you can cut and paste to and from the clipboard +directly from the shell. To do this, use bindings like the following: + + bindkey -b M-x e_copy_to_clipboard + bindkey -b M-y e_paste_from_clipboard + +Then, to paste text from the clipboard into the current input line, you +can type: + M-y +And to copy the current shell's kill buffer to the clipboard, + M-x + +(The kill buffer contains the last deletion from an editing command. Sort +of like an 'undo' buffer). + +You can also use the clipboard to redirect I/O, with /dev/clipboard as +the destination/source file. + + +NOTE: From version 6.00 onwards, the e_paste operation does NOT copy the +clipboard contents to the shell kill buffer. + + + +e_dosify_next +------------- +A key bound to this editor function can be used to convert unix-style +paths to DOS-style paths. +For example, + bindkey -b M-/ e_dosify_next +Then, if I had line like so: + xcopy /e /u c:/nt40/system32 +I would move the cursor to the C: and hit alt-/. magically, the command +line changes to + xcopy /e /u c:\\nt40\\system32 + +This function converts every '/' to '\\' until the first space. If the +space is escaped by a '\', the function looks for the next space. + +e_dosify_prev +------------- +Works like above, but on the previous word. Matt Landau pointed out that +this was much more convenient. + +e_page_up +--------- +Editor function to move console window up one page. Can be bound to +PageUp key. + +e_page_down +---------- +Ditto for page down. + + +Literal Prompt Characters +------------------------- +tcsh uses a special syntax for embedding literal character sequences in the +prompt. For example, ANSI escapes. +Thus, if you did +set prompt='%{<ESC>[44mfoo%}\>', +this will print the prompt in the appropriate colors. + +The color-ls patch in 6.07.09 implements parsing for ANSI escapes. To keep +the prompt specification consistent with the availablity of this feature, +the literal string will now accept ANSI escapes like color-ls would. + +The shell can be compiled for the old behaviour, but I don't recommend it. + +I'm aware this is a major incompatibility, but I think the change is +worthwhile. + +As an example, here is my new prompt, with the old one as a reference. + +#old specification +# set prompt='%{f9%}%c03%{gg%}\>' +# set prompt3 = '%{fc%}Correct to %R ?(y|n|e)%{gg%} ' + +# new spec. + set prompt='%{^[[1;34m%}%c03%{^[[0m%}\>' + set prompt3='%{^[[1;31m%}Correct to %R ?(y|n|e)%{^[[0m%} ' +# +# + +ls-F is noticeably slow if color is set. This is especially true on slower +machines (P100, for example). You may not want to set it for those kinds +of systems. More so if you already have an external color-ls. + +watch: +----- +Since rev 3.12, support (ha ha) for the watch variable has been added. This +will work only on a Microsoft Windows Network, i.e, where computers +participate in an NT domain. Here is how tcsh will work if your network +configuration is to its taste: + + set watch=(2 AMOLD SKYNYRD any LYNYRD) + +sets a watch for AMOLD on machine SKYNYRD, and any user on machine LYNYRD. The +watch interval is 2 minutes. + +Note that these are NETBIOS names, and hence the results may be flaky. There +is no good way to distinguish computer names from user names in a netbios name +table (even a good guess is very expensive), so be prepared for unexpected +results. + +There may be problems depending on what protocol is on lana number 0. +(This will usually be shown (and/or set) on NT in the properties for the +NETBIOS interface in the control panel/networks applet. Win95 is screwed up, +and if you have more than one protocol, watch may not work. Don't bug me +about it) + +Also note that names must all be uppercase. + +The default time interval of 10 minutes is probably good, since you don't want +to generate too much network traffic. + +Nice: +----- +// +// nice(niceness) +// +// where niceness is an integer in the range -6 to +7 +// +// A usual foreground process starts at level 9 in the chart below +// +// the range -6 to +7 takes it from Base priority 15 down to 2. +// +// Note that level 1 or > 15 are not allowed. +// +// Priority Level 11 (niceness -2) or greater affects system performance, +// so use with care. +// +// niceness defaults to +4, which is lowest for background normal class. +// As in unix, +ve niceness indicates lower priorities. + +/*************************************************************************** +Niceness Base Priority class/thread priority + + 1 Idle, normal, or high class, THREAD_PRIORITY_IDLE + ++7 2 Idle class, THREAD_PRIORITY_LOWEST ++6 3 Idle class, THREAD_PRIORITY_BELOW_NORMAL ++5 4 Idle class, THREAD_PRIORITY_NORMAL ++4 5 Background normal class, THREAD_PRIORITY_LOWEST + Idle class, THREAD_PRIORITY_ABOVE_NORMAL ++3 6 Background normal class, THREAD_PRIORITY_BELOW_NORMAL + Idle class, THREAD_PRIORITY_HIGHEST ++2 7 Foreground normal class, THREAD_PRIORITY_LOWEST + Background normal class, THREAD_PRIORITY_NORMAL ++1 8 Foreground normal class, THREAD_PRIORITY_BELOW_NORMAL + Background normal class, THREAD_PRIORITY_ABOVE_NORMAL + 0 9 Foreground normal class, THREAD_PRIORITY_NORMAL + Background normal class, THREAD_PRIORITY_HIGHEST +-1 10 Foreground normal class, THREAD_PRIORITY_ABOVE_NORMAL +-2 11 High class, THREAD_PRIORITY_LOWEST + Foreground normal class, THREAD_PRIORITY_HIGHEST +-3 12 High class, THREAD_PRIORITY_BELOW_NORMAL +-4 13 High class, THREAD_PRIORITY_NORMAL +-5 14 High class, THREAD_PRIORITY_ABOVE_NORMAL +-6 15 Idle, normal, or high class, THREAD_PRIORITY_TIME_CRITICAL + High class, THREAD_PRIORITY_HIGHEST + + + 16 Real-time class, THREAD_PRIORITY_IDLE + 22 Real-time class, THREAD_PRIORITY_LOWEST + 23 Real-time class, THREAD_PRIORITY_BELOW_NORMAL + 24 Real-time class, THREAD_PRIORITY_NORMAL + 25 Real-time class, THREAD_PRIORITY_ABOVE_NORMAL + 26 Real-time class, THREAD_PRIORITY_HIGHEST + 31 Real-time class, THREAD_PRIORITY_TIME_CRITICAL +****************************************************************************/ + +kill: +---- + +You can try to kill a process 4 ways: + +kill -1 <pid> (which will send a sigint) +kill -2 <pid> (which will send a sigbreak) + +1 and 2 are only good for processes started in the same console. The +signals cannot be sent to other process groups (other consoles/GUI apps). + +kill -3 <pid> (which will send a quit message to each window of the child> + +kill -7 <pid> , which will call TerminateProcess() diff --git a/win32/WindowsReadme.1st b/win32/WindowsReadme.1st new file mode 100644 index 000000000000..91ff88fddb23 --- /dev/null +++ b/win32/WindowsReadme.1st @@ -0,0 +1,556 @@ +This document applies to the Windows NT (including Windows 2000, XP, Server
+ 2003 etc.) native versions of tcsh.
+
+Note that the shell probably does work on Windows NT 4.0 or Windows 95, 98, and
+Me. However, making fixes solely for those operating systems is lowest on my
+priority list.
+
+"Windows NT" from here on refers to Windows 2000, XP etc. "Win 9x" means
+Windows 95,98 etc.
+
+
+I will attempt to describe the various differences between the Unix and the
+native Windows versions of tcsh. I assume at least a passing familiarity with
+Unix, Windows and tcsh.
+
+
+How to tell if you're running the native version (versus cygwin)
+----------------------------------------------------------------
+If,
+ - You built the binary from the tcsh distribution, using Visual C++.
+
+ Or, you downloaded it from www.blarg.net/~amol/~tcsh.exe.gz.
+
+ Or, you downloaded it from ftp.blarg.net:users/amol/tcsh.
+
+ Or, you type echo $version and see something like:
+
+ tcsh 6.12.01 (Astron) 2003-02-08 (i686-Microsoft-WindowsXP) options 8b,nls,dl,hb,color,nt-rev-7.03
+
+ (The string "nt-rev-N.NN" only exists on native binaries of
+ tcsh. The actual revision may be different, as it is a minor
+ revision of the tcsh major version (6.12.01 in this case).)
+
+ If none of the above is true, this document is not for you.
+
+
+Who do I bug about bugs ?
+-------------------------
+
+ If the bug is on the lines of "cmd.exe does this, but tcsh doesn't", you
+ have a very slim chance of having me look at it. If you feel strongly
+ enough, grab the source and hack away. Isn't that the joy of Open Source
+ (TM) ?
+
+
+ Also, try running the latest version if you can. Your bug may already be
+ fixed.
+
+ If you still want to report a bug:
+
+ First, verify if applicable/possible on a Unix system that the behaviour is
+ actually different.
+
+ Secondly, setenv CYGWIN noglob if it's not already set. If that still
+ doesn't work, then
+
+ Third,
+
+ set NTslowexec
+ setenv TCSHONLYSTARTEXES 1
+
+ and try to reproduce the problem.
+
+
+ Even if the 3rd step seems to fix the behaviour, you should still report the
+ bug to amol@blarg.net with the following information:
+
+ - The output of echo $version
+ - The version of the operating system ("Windows" is not good enough.)
+ - The output from "set" and "setenv"
+ - The exact steps to reproduce the problem.
+
+
+ Be prepared to be quizzed on the contents of this file.
+
+How do I compile the source ?
+-----------------------------
+ - Download and extract the source from ftp.astron.com. Say it creates a
+ directory called tcsh-6.12.01
+
+ - Open a cmd.exe prompt and cd into this directory. Run "vcvars32.bat" from
+ your Visual C++ installation.
+
+ - type "copy config\win32 config.h"
+
+ - type "nmake -f win32\makefile.win32"
+
+
+ You will need sed to generate some headers.
+
+
+
+Known bugs
+----------
+ The "time" builtin does not work.
+
+
+Startup Files:
+--------------
+
+tcsh will create a HOME variable, if none is set, based on the OS.
+
+For Win 9x:
+ <windows_directory>/.tcshrc
+ For Example, C:\WINDOWS\.tcshrc
+
+For Windows NT:
+ version 3.51: <getenv(HOMEDRIVE)/getenv(HOMEPATH)/.tcshrc>
+ Usually something like C:\USERS\DEFAULT\.tcshrc
+
+ version 4.00 and above: <getenv(USERPROFILE)/.tcshrc)
+
+ This can vary from something like C:\WINNT\USERS\amol\profile\.tcshrc
+ on NT 4.0 to C:\Documents And Settings\amol\.tcshrc on Windows 2000 and
+ higher.
+
+These can all be overridden by setting HOME in the user's environment before
+the shell is launched.
+
+To create a .tcshrc on Windows, you just need a real editor like Vim.
+
+
+
+o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
+
+ Various differences from Unix, FAQs, etc.
+
+o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
+
+
+This document is correct as of 6.12.01
+
+ New Builtins
+ ------------
+ * start : Works like cmd.exe's "start". Use to launch an application or
+ launch a filetype association.
+
+ Can also be used to launch Windows Explorer on a directory by
+ typing "start c:/foo", for example.
+
+ Also "start http://www.tcsh.org" will launch Internet explorer
+ with that URL.
+
+ ("Associations" here means Explorer file-type associations, that cause,
+ for example, Microsoft Word to be launched when you type "foo.doc" at
+ a cmd.exe prompt. That can have unexpected side-effects like batch files
+ and perl scripts launching in another window when run from tcsh. )
+
+ * title: Sets the title of the shell. Stores the current title in
+ $oldtitle before changing it.
+
+
+ * cls: Clear the entire console screen buffer instead of the visible
+ window.
+
+ * ps : List processes. With -w, list titles as well.
+
+
+ * shutdown [-r | -l | -f] now : Windows NT only. Reboot or log off. -f
+ forces open applications to close. "now" must be specified for reboots.
+
+
+ Builtins that behave differently
+ ------------------------------------
+This section documents the builtins that present on Unix as well as windows,
+but function slightly differently on Windows. Also mentioned is behaviour that
+is different from what you are used to on Windows.
+
+ * Backgrounding (launching commands with '&').
+
+ While this is possible, be aware that Windows does not have any job
+ control. Thus you cannot attempt to bring a backgrounded job into the
+ foreground with '%<job number>' as on Unix.
+
+ Also note that a background job will most likely be killed if you exit
+ the command prompt that launched it. To prevent this from happening,
+ use the "nohup" builtin. For example:
+
+ nohup foo &
+
+ This will print "foo Done" quickly, as if the job actually completed.
+ However, if you type "ps", you will see that foo is still running. The
+ shell does not know after nohup whether the child process is
+ running or not.
+
+ * Case insenstivity of environment variable names.
+
+ To maintain consistency with Windows, and avoid conflicts, the
+ following are equivalent on Windows:
+
+ setenv FOO bar
+
+ setenv foo bar
+
+ Note that setenv foo BAR and setenv foo bar ARE NOT the same. Thus if
+ some application is sensitive to the case of an environment variable's
+ VALUE, you should set it exactly as required.
+
+ * No termcap set/unset with settc/echotc/telltc.
+
+ The only capabilities controllable are lines and columns. For example,
+
+ settc co 80
+ settc li 50
+
+ similarly,
+
+ echotc cols
+ or
+ echotc lines
+
+ will echo the number of columns and lines respectively.
+
+ echotc buffer
+
+ will echo the size of the console screen buffer.
+
+
+ Note that settc has an interesting side effect, which was left in
+ because it can be useful. Consider the following:
+
+ If your original line size was 50, with a console screen buffer of 50
+ as well (no scrollback), then typing
+
+ settc li 300
+
+ followed by
+
+ settc li 50
+
+
+ has the effect of setting your console screen buffer to 300, so you
+ now have a scrollback, without having to set the properties of the
+ tcsh.exe window.
+
+
+ This is particularly useful on Win9x, where getting a console
+ scrollback buffer seems to be practically impossible in a reasonable
+ fashion otherwise.
+
+
+ * No execution of .bat or .cmd files by name alone.
+
+ That is, you have to type foo.bat or foo.cmd to execute a batch file,
+ even if it is in your path.
+
+ This is by design. No file types other than 32-bit executables are
+ recognized by the shell. Unless you type the full name, the shell
+ attempt to execute either the name as typed ("foo" for example) or the
+ name with .exe appended to it ("foo.exe").
+
+ * The "watch" variable and the "log" builtin.
+
+ To attempt to duplicate the functionality of the log/watch combination
+ on Unix, the Windows version of shell uses NETBIOS and the semantics
+ are slightly different.
+
+ Whereas in Unix you might type
+
+ set watch=(amol tty0 root any)
+
+ in Windows you would type
+
+ set watch=(AMOL AMOLSCOMPUTER THEBOSS any)
+
+ Thus, instead of tty, the computer name of the user may be specified.
+ In this case, you will be notified if the user AMOL is logged on
+ AMOLSCOMPUTER or THEBOSS is logged on any computer.
+
+ Note that the names must be uppercase.
+
+ * The "nice" builtin.
+
+ Functionally, pretty much the same as Unix, with the range being from
+ -6 to +7, and +4 by default.
+
+ These niceness numbers map to absolutes priorities based on the
+ assumption that the process started at the typical Foreground Normal
+ Priority Class.
+
+ That means, if your shell is somehow started at a higher than normal
+ priority, even a nice +1 will lower the priority to below normal, much
+ more than just a relative lowering by one level.
+
+ * The "kill" builtin.
+
+ You can try to kill a process 4 ways:
+
+ kill -1 <pid> (which will send a sigint)
+ kill -2 <pid> (which will send a sigbreak)
+
+ 1 and 2 are only good for processes started in the same console. The
+ signals cannot be sent to other process groups (other consoles/GUI apps).
+
+ kill -3 <pid> (sends a WM_QUIT message to each window of the child>
+ Useful for closing GUI apps.
+
+ kill -7 <pid> , which will call TerminateProcess() on the process.
+ This is dangerous and should be a last resort.
+
+
+
+ Special Variables
+ -----------------
+
+ o Environment Variables:
+ *-*-*-*-*-*-*-*-*-*-*-*-*
+
+ This version of tcsh uses the following environment variables
+
+
+ - TCSHSUBSTHB (Short for "tcsh substitute hashbang"):
+
+ Supplies mappings for the shell's hashbang emulation. For example,
+
+ setenv TCSHSUBSTHB "/usr/local/bin/perl c:/bin/perl.exe;"
+
+ If the variable is thus set, any script that has
+ "#!/usr/local/bin/perl" on the first line will be run as
+ if "#!c:/bin/perl.exe" was the first line.
+
+ The terminating ";" is a must.There is a limit of 20 such pairs.
+
+ - TCSHONLYSTARTEXES
+
+ Controls whether Explorer Associations will be tried for
+ non-executables.
+
+
+ For example, "setenv TCSHONLYSTARTEXES 1" , tells tcsh to not try to
+ execute a non-exe or non-script.
+
+ The value must be EXACTLY one character long.
+
+ (a zero-length setting will not work. A length greater than 1 will
+ be assumed to be a list of extensions as below.)
+
+
+ You can also supply a semi-colon-separated list of extensions for
+ which to NOT try associations. For example, if the variable is set to
+
+ "cmd;bat",
+
+ .cmd/.bat files will be executed in the same window because the
+ default association is not used, instead an internal hack feeds them
+ to the DOS command processor.
+
+ If the file extension does not match the list, the shell will try to
+ launch an association.
+
+
+ Any changes to this variable will NOT affect the the "start" builtin.
+ That builtin ALWAYS launches associations, since the whole point of
+ using "start" is to launch an application.
+
+
+ - TCSH_NOASYNCGUI:
+
+ By default, a Windows GUI application is launched asynchronously.
+ That is, the shell does not wait for the application to terminate
+ but immediately returns you to the prompt. If this variable is set,
+ the shell will wait for the GUI application to exit before going on.
+
+ - TCSHLANG: NLS support
+
+ You can get messages in a specific language by doing:
+
+ setenv TCSHLANG <dll>, where <dll> is the name of the NLS dll.
+
+ tcsh comes with:
+
+ tcshde.dll -> German
+ tcshfr.dll -> French
+ tcshsp.dll -> Spanish
+ tcsh-it.dll -> Italian
+
+ tcshc.dll => Default "C" locale
+
+ You can change the dll at runtime by setting/unsetting this
+ variable.
+ You can specify the DLL name, or the complete path, if it is not
+ in your standard search path.
+
+ (Using tcshc.dll is useless and adds unnecessary overhead. If you
+ are using English versions, do not install the dlls)
+
+ o Shell Variables:
+ *-*-*-*-*-*-*-*
+
+ This version of tcsh recognizes the following shell variables:
+
+ - oldtitle : Stores the previous value of the title, when the "title"
+ builtin is used to change it. So, "title $oldtitle", will
+ restore the previous title.
+
+
+ - NTlamepathfix:
+
+ Normally, tcsh sets the PATH variable to be delimited by
+ "/". However, some applications may have trouble with this, so you can
+ force the shell to convert "/" to "\" before executing an external (not
+ builtin) command.
+
+ - NTslowexec:
+
+ The shell will usually try to avoid forking if a command can be executed
+ directly (using the CreateProcess() API instead of fork()). This only
+ applies to "simple" commands. These are commands that do not have their
+ output piped, redirected or are not niced or nohupped.
+
+ If you see any strange behaviour from the shell in terms of wildcard
+ expansion or quote substitution, try setting this variable (AFTER
+ setting CYGWIN noglob!!!).
+
+ - NTnoquoteprotect:
+
+
+ Ordinarily , if you pass a double quote to a command string, tcsh
+ will protect the quotes by adding backslashes. For example,
+
+ find . -name '"*.c"'
+ would get executed as
+
+ find . -name \"*.c\"
+
+ Some applications (MKS find, for example) do not like the '\'. To
+ prevent tcsh from quoting such arguments, set this variable.
+
+ Of course, it may cause other applications to break, so use at
+ your own risk.
+
+ - NTcaseifypwd:
+
+ If set, corrects case of current directory when cd'ing into it.
+ Some "filesystems" can't handle the default behaviour. Only works on
+ Windows NT.
+
+
+
+ Key bindings, clipboard support and edit functions
+ --------------------------------------------------
+
+ To use keys like function keys, arrows, insert, etc., the following
+ form of bindkey must be used:
+
+ bindkey -b N-xxx <command>
+
+ where xxx is either:
+ a) A number from 1 through 24, representing the fucntion keys.
+ For example, bindkey -b N-1 run-help
+
+ b) The strings "pgup","pgdown","end","home", "left","up","right","down",
+ "ins","del"
+ For example, bindkey -b N-del delete-char
+
+ Here are the bindings I use in my .tcshrc:
+
+ # NT specific bindkey extensions
+ bindkey -b N-up up-history
+ bindkey -b N-down down-history
+ bindkey -b N-right forward-char
+ bindkey -b N-left backward-char
+ bindkey -b N-del delete-char
+ bindkey -b N-ins overwrite-mode
+ bindkey -b N-1 which-command
+ bindkey -b N-2 expand-history
+ bindkey -b N-3 complete-word-raw
+ bindkey -b N-home beginning-of-line
+ bindkey -b N-end end-of-line
+
+ bindkey -b N-pgup e_page_up
+ bindkey -b N-pgdown e_page_down
+
+ (Note that on Win9x, you must set your console window to NOT be Auto
+ sized, and you must use the "settc" builtin to increase and then reduce
+ back the number of lines, in order to get a scrollbar. pgup and
+ pgdown will not work without a scroll bar)
+
+
+ To bind ctrl or alt combinations, use the following as examples.
+ (Alt on PC keyboards is treated as the Meta on Unix keyboards )
+
+ bindkey -b N-C-left backward-word
+ bindkey -b N-M-right forward-word
+
+ For Shift combinations:
+ bindkey -b N-S-1 backward-word
+
+ Clipboard support
+ o-o-o-o-o-o-o-o-o
+
+ You can also cut and paste to and from the clipboard directly from
+ the shell. To do this, use bindings like the following:
+
+ bindkey -b M-x e_copy_to_clipboard
+ bindkey -b M-y e_paste_from_clipboard
+
+ Then, to paste text from the clipboard into the current input
+ line, you can type:
+ M-y
+ And to copy the current shell's kill buffer to the clipboard,
+ M-x
+
+ (The kill buffer contains the last deletion from an editing
+ command. Sort of like an 'undo' buffer).
+
+ You can also use the clipboard to redirect I/O, with /dev/clipboard as
+ the destination/source file.
+
+
+
+ Editor Functions
+ o-o-o-o-o-o-o-o-o
+
+ e_dosify_next
+ -------------
+ A key bound to this editor function can be used to convert
+ unix-style paths to DOS-style paths.
+
+ For example,
+
+ bindkey -b M-/ e_dosify_next
+
+ Then, if I had line like so:
+
+ xcopy /e /u c:/nt40/system32
+
+ I would move the cursor to the C: and hit alt-/. magically, the
+ command line changes to
+
+ xcopy /e /u c:\\nt40\\system32
+
+ This function converts every '/' to '\\' until the first space.
+ If the space is escaped by a '\', the function looks for the
+ next space.
+
+ e_dosify_prev
+ -------------
+ Works like above, but on the previous word.
+
+ e_page_up
+ ---------
+ Editor function to move console window up one page. Can be bound to
+ PageUp key, for example.
+
+ e_page_down
+ ----------
+ Ditto for page down.
+
+ e_copy_to_clipboard
+ -------------------
+ See Clipboard Support above.
+
+ e_paste_from_clipboard
+ -----------------------
+ See Clipboard Support above.
diff --git a/win32/bogus.c b/win32/bogus.c new file mode 100644 index 000000000000..5e34c4d8ee8c --- /dev/null +++ b/win32/bogus.c @@ -0,0 +1,168 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/bogus.c,v 1.9 2008/10/11 12:47:39 christos Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * bogus.c: various routines that are really silly + * -amol + * + */ +#include "ntport.h" +#include "sh.h" + +static struct passwd pass_bogus; +static char username[20]; +static char homedir[MAX_PATH + 1];/*FIXBUF*/ +static char *this_shell="tcsh"; + +static char dummy[2]={0,0}; + +gid_t getuid(void) { + return 0; +} +gid_t getgid(void) { + return 0; +} +gid_t geteuid(void) { + return 0; +} +gid_t getegid(void) { + return 0; +} +#undef free +struct passwd * getpwnam(const char *name) { + + char *ptr; + DWORD size =20; + size_t esize = 0; + + if (pass_bogus.pw_name == NULL) { + GetUserName(username,&size); + if (_dupenv_s(&ptr,&esize,"HOME") == 0){ + StringCbCopy(homedir,sizeof(homedir),ptr); + pass_bogus.pw_dir = &homedir[0]; + free(ptr); + } + pass_bogus.pw_name = &username[0]; + pass_bogus.pw_shell = this_shell; + + + pass_bogus.pw_passwd= &dummy[0]; + pass_bogus.pw_gecos=&dummy[0]; + pass_bogus.pw_passwd= &dummy[0]; + + } + if (_stricmp(username,name) ) + return NULL; + return &pass_bogus; +} +struct passwd * getpwuid(uid_t myuid) { + + char *ptr; + DWORD size =20; + size_t esize = 0; + + UNREFERENCED_PARAMETER(myuid); + if (pass_bogus.pw_name == NULL) { + GetUserName(username,&size); + if (_dupenv_s(&ptr,&esize,"HOME") == 0){ + StringCbCopy(homedir,sizeof(homedir),ptr); + pass_bogus.pw_dir = &homedir[0]; + free(ptr); + } + pass_bogus.pw_name = &username[0]; + pass_bogus.pw_shell = this_shell; + + + pass_bogus.pw_passwd= &dummy[0]; + pass_bogus.pw_gecos=&dummy[0]; + pass_bogus.pw_passwd= &dummy[0]; + + } + return &pass_bogus; +} +struct group * getgrnam(char *name) { + UNREFERENCED_PARAMETER(name); + return NULL; +} +struct group * getgrgid(gid_t mygid) { + UNREFERENCED_PARAMETER(mygid); + return NULL; +} +char * ttyname(int fd) { + + if (isatty(fd)) return "/dev/tty"; + return NULL; +} +int times(struct tms * ignore) { + FILETIME c,e,kernel,user; + + ignore->tms_utime=0; + ignore->tms_stime=0; + ignore->tms_cutime=0; + ignore->tms_cstime=0; + if (!GetProcessTimes(GetCurrentProcess(), + &c, + &e, + &kernel, + &user) ) + return -1; + + if (kernel.dwHighDateTime){ + return GetTickCount(); + } + // + // Units of 10ms. I *think* this is right. -amol 6/2/97 + ignore->tms_stime = kernel.dwLowDateTime / 1000 /100; + ignore->tms_utime = user.dwLowDateTime / 1000 /100; + + return GetTickCount(); +} +int tty_getty(int fd, void*ignore) { + UNREFERENCED_PARAMETER(fd); + UNREFERENCED_PARAMETER(ignore); + return 0; +} +int tty_setty(int fd, void*ignore) { + UNREFERENCED_PARAMETER(fd); + UNREFERENCED_PARAMETER(ignore); + return 0; +} +int tty_geteightbit(void *ignore) { + UNREFERENCED_PARAMETER(ignore); + return 1; +} + void +dosetty(Char **v, struct command *t) +{ + UNREFERENCED_PARAMETER(v); + UNREFERENCED_PARAMETER(t); + xprintf("setty not supported in NT\n"); +} + diff --git a/win32/clip.c b/win32/clip.c new file mode 100644 index 000000000000..bc057d8b4e92 --- /dev/null +++ b/win32/clip.c @@ -0,0 +1,570 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/clip.c,v 1.9 2006/03/05 08:59:36 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * clip.c : support for clipboard functions. + * -amol + * + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdio.h> +#include "sh.h" +#include "ed.h" + +BOOL InitApplication(HINSTANCE); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); + + +HWND ghwndmain; + +extern int ctrl_handler(DWORD); +extern void c_insert(int); + +/* + * Creating a hidden window may not be strictly necessary on + * NT, but why tempt fate ? + * -amol + */ + +void clipper_thread(void) { + + MSG msg; + HINSTANCE hInstance = GetModuleHandle(NULL); + + + if (!InitApplication(hInstance)) { + return ; + } + + if (!InitInstance(hInstance, 0)) { + return ; + } + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + if ( !ctrl_handler(CTRL_CLOSE_EVENT)) + init_clipboard(); + return; +} +void init_clipboard(void) { + HANDLE ht; + DWORD tid; + + ht = CreateThread(NULL,gdwStackSize, + (LPTHREAD_START_ROUTINE)clipper_thread, NULL,0,&tid); + + if (!ht) + abort(); + CloseHandle(ht); +} + +BOOL InitApplication(HINSTANCE hInstance) +{ + WNDCLASS wc; + + + // Fill in window class structure with parameters that describe + // the main window. + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = NULL;//LoadIcon (hInstance, szAppName); + wc.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)IntToPtr(COLOR_WINDOW+1); + + wc.lpszMenuName = NULL; + wc.lpszClassName = "tcshclipboard"; + + return RegisterClass(&wc); +} + +// +// FUNCTION: InitInstance(HANDLE, int) +// +// PURPOSE: Saves instance handle and creates main window +// +// COMMENTS: +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { + HWND hWnd; + + + UNREFERENCED_PARAMETER(nCmdShow); + + hWnd = CreateWindow("tcshclipboard", "tcshclipboard", + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, + NULL, NULL, hInstance, NULL); + + if (!hWnd) { + return (FALSE); + } + + UpdateWindow(hWnd); + ghwndmain = hWnd; + + return (TRUE); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + + switch (message) { + + case WM_DESTROYCLIPBOARD: + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + return (0); +} + +CCRETVAL e_copy_to_clipboard(Char c) { + unsigned char *cbp; + Char *kp; + int err; + size_t len; + unsigned char *clipbuf; + HANDLE hclipbuf; + + UNREFERENCED_PARAMETER(c); + + if (!ghwndmain) + return (CC_ERROR); + + if (KillRingLen == 0) + return (CC_ERROR); + + len = Strlen(KillRing[YankPos].buf); + + hclipbuf = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, len+2); + if (!hclipbuf) + return (CC_ERROR); + clipbuf = (unsigned char*)GlobalLock(hclipbuf); + + if (!clipbuf){ + err = GetLastError(); + GlobalFree(hclipbuf); + return (CC_ERROR); + } + + kp = KillRing[YankPos].buf; + cbp = clipbuf; + + while(*kp != '\0') { + *cbp = (u_char)(*kp & CHAR); + cbp++;kp++; + } + *cbp = 0; + + GlobalUnlock(clipbuf); + + if (!OpenClipboard(ghwndmain)) + goto error; + + if (!EmptyClipboard()) + goto error; + + if (SetClipboardData(CF_TEXT,hclipbuf) != hclipbuf){ + err = GetLastError(); + goto error; + + } + + CloseClipboard(); + return (CC_NORM); +error: + GlobalFree(hclipbuf); + CloseClipboard(); + return (CC_ERROR); +} +CCRETVAL e_paste_from_clipboard(Char c) { + HANDLE hclip; + unsigned char *cbp; + Char *cp; + int len; + unsigned char *clipbuf; + + + + UNREFERENCED_PARAMETER(c); + + if (!ghwndmain) + return (CC_ERROR); + if (!IsClipboardFormatAvailable(CF_TEXT)) + return CC_ERROR; + + if (!OpenClipboard(ghwndmain)) + return CC_ERROR; + + + hclip = GetClipboardData(CF_TEXT); + if (hclip) { + clipbuf = (unsigned char*)GlobalLock(hclip); + + cbp = clipbuf; + len = 0; + + while(*cbp && *cbp != '\r') { + len++; + cbp++; + } + cbp = clipbuf; + + cp = Cursor; + + c_insert(len); + + if (LastChar + len >= InputLim) + goto error; + + while(*cbp && *cbp !='\r' && (cp <LastChar) ) { + *cp = *cbp ; + cp++;cbp++; + } + Cursor = cp; + GlobalUnlock(hclip); + } + CloseClipboard(); + + return (CC_REFRESH); +error: + return (CC_ERROR); +} + +int is_dev_clipboard_active=0; +HANDLE ghdevclipthread; + +/* Reads from pipe and write to clipboard */ +void clip_writer_proc(HANDLE hinpipe) { + unsigned char *realbuf; + unsigned char *clipbuf; + unsigned char *ptr; + DWORD bread=0,spleft,err,i,rbsize; + DWORD ptrloc; + HANDLE hclipbuf; + + + rbsize = 4096; + realbuf = heap_alloc(rbsize); + ptr = realbuf; + ptrloc = 0; + spleft = rbsize; + + while(spleft) { + if (!ReadFile(hinpipe,ptr,spleft,&bread,NULL)) { + spleft = GetLastError(); + dprintf("hinpipe returend %d\n",spleft); + if (spleft == ERROR_BROKEN_PIPE) + break; + } + if (bread == 0) + break; + ptr += bread; + ptrloc += bread; + spleft -=bread; + + if (spleft <=0){ + u_char *tmp; + + rbsize <<=1; + + tmp = realbuf; + realbuf = heap_realloc(realbuf,rbsize); + if (!realbuf) { + realbuf = tmp; + break; + } + spleft += rbsize >> 1; + + ptr = realbuf+ptrloc; + + dprintf("updated size now %d, splef %d, ptrloc %d, ptr 0x%08x, realbuf 0x%08x\n",rbsize,spleft,ptrloc,ptr,realbuf); + } + } + CloseHandle(hinpipe); + + bread = rbsize-spleft; + + hclipbuf = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, bread+256); + if (!hclipbuf) { + is_dev_clipboard_active=0; + return; + } + clipbuf = (u_char*)GlobalLock(hclipbuf); + + if (!clipbuf){ + err = GetLastError(); + GlobalFree(hclipbuf); + is_dev_clipboard_active=0; + return ; + } + ptr = clipbuf; + for (i=0;i <bread;i++) { + + if (realbuf[i] == '\n' && (i >0 && realbuf[i-1] != '\r') ) + *ptr++ = '\r'; + + *ptr++ =realbuf[i]; + + if ((ptr - clipbuf) >= rbsize) + break; + } + *ptr=0; + + heap_free(realbuf); + + GlobalUnlock(clipbuf); + + if (!OpenClipboard(ghwndmain)) + goto error; + + if (!EmptyClipboard()) + goto error; + + if (SetClipboardData(CF_TEXT,hclipbuf) != hclipbuf){ + err = GetLastError(); + goto error; + + } + CloseClipboard(); + is_dev_clipboard_active=0; + return ; +error: + is_dev_clipboard_active=0; + GlobalFree(hclipbuf); + CloseClipboard(); +} +HANDLE create_clip_writer_thread(void) { + HANDLE hread,hwrite; + DWORD tid; + SECURITY_ATTRIBUTES secd; + + if (is_dev_clipboard_active) + return INVALID_HANDLE_VALUE; + secd.nLength=sizeof(secd); + secd.lpSecurityDescriptor=NULL; + secd.bInheritHandle=FALSE; + + if (!CreatePipe(&hread,&hwrite,&secd,0)) { + abort(); + } + is_dev_clipboard_active = 1; + ghdevclipthread = CreateThread(NULL,gdwStackSize, + (LPTHREAD_START_ROUTINE)clip_writer_proc, hread,0,&tid); +// CloseHandle(ht); + return hwrite; +} + +/* Read from clipboard and write to pipe */ +void clip_reader_proc(HANDLE houtpipe) { + + HANDLE hclip; + unsigned char *cbp; + unsigned char *clipbuf; + unsigned char * outbuf,*ptr; + DWORD bwrote, len; + DWORD obsize; + + obsize = 4096; + outbuf = heap_alloc(obsize); + ptr = outbuf; + + + if (!IsClipboardFormatAvailable(CF_TEXT)) + goto done ; + + if (!OpenClipboard(ghwndmain)) + goto done ; + + + len = 0; + hclip = GetClipboardData(CF_TEXT); + if (hclip) { + clipbuf = (unsigned char*)GlobalLock(hclip); + + cbp = clipbuf; + + while(*cbp ) { + *ptr++ = *cbp++; + len++; + if (len == obsize) { + obsize <<= 1; + outbuf = heap_realloc(outbuf,obsize); + if (!outbuf) + break; + ptr = outbuf+len; + } + } + GlobalUnlock(hclip); + } + CloseClipboard(); + + if (!WriteFile(houtpipe,outbuf,len,&bwrote,NULL)) { + ; + } + CloseHandle(houtpipe); + heap_free(outbuf); + +done: + is_dev_clipboard_active=0; + return; +} +HANDLE create_clip_reader_thread(void) { + HANDLE hread,hwrite; + DWORD tid; + SECURITY_ATTRIBUTES secd; + + if (is_dev_clipboard_active) + return INVALID_HANDLE_VALUE; + + secd.nLength=sizeof(secd); + secd.lpSecurityDescriptor=NULL; + secd.bInheritHandle=FALSE; + + if (!CreatePipe(&hread,&hwrite,&secd,0)) { + abort(); + } + is_dev_clipboard_active = 1; + ghdevclipthread = CreateThread(NULL,gdwStackSize, + (LPTHREAD_START_ROUTINE)clip_reader_proc, hwrite,0,&tid); + return hread; +} + +CCRETVAL +e_dosify_next(Char c) +{ + register Char *cp, *buf, *bp; + int len; + BOOL bDone = FALSE; + + + USE(c); + if (Cursor == LastChar) + return(CC_ERROR); + + // worst case assumption + buf = heap_alloc(( LastChar - Cursor + 1)*2*sizeof(Char)); + + cp = Cursor; + bp = buf; + len = 0; + + while( cp < LastChar) { + if ( ((*cp & CHAR) == ' ') && ((cp[-1] & CHAR) != '\\') ) + bDone = TRUE; + if (!bDone && (*cp & CHAR) == '/') { + *bp++ = '\\' | (Char)(*cp & ~(*cp & CHAR) ); + *bp++ = '\\' | (Char)(*cp & ~(*cp & CHAR) ); + + len++; + + cp++; + } + else + *bp++ = *cp++; + + len++; + } + if (Cursor+ len >= InputLim) { + heap_free(buf); + return CC_ERROR; + } + cp = Cursor; + bp = buf; + while(len > 0) { + *cp++ = *bp++; + len--; + } + + heap_free(buf); + + Cursor = cp; + + if(LastChar < Cursor + len) + LastChar = Cursor + len; + + return (CC_REFRESH); +} +/*ARGSUSED*/ +CCRETVAL +e_dosify_prev(Char c) +{ + register Char *cp; + + USE(c); + if (Cursor == InputBuf) + return(CC_ERROR); + /* else */ + + cp = Cursor-1; + /* Skip trailing spaces */ + while ((cp > InputBuf) && ( (*cp & CHAR) == ' ')) + cp--; + + while (cp > InputBuf) { + if ( ((*cp & CHAR) == ' ') && ((cp[-1] & CHAR) != '\\') ) + break; + cp--; + } + if(cp != InputBuf) + Cursor = cp + 1; + else + Cursor = cp; + + return e_dosify_next(0); +} +extern BOOL ConsolePageUpOrDown(BOOL); +CCRETVAL +e_page_up(Char c) //blukas@broadcom.com +{ + USE(c); + ConsolePageUpOrDown(TRUE); + return (CC_REFRESH); +} +CCRETVAL +e_page_down(Char c) +{ + USE(c); + ConsolePageUpOrDown(FALSE); + return (CC_REFRESH); +} diff --git a/win32/console.c b/win32/console.c new file mode 100644 index 000000000000..220d56eaea94 --- /dev/null +++ b/win32/console.c @@ -0,0 +1,636 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/console.c,v 1.9 2006/08/27 01:13:28 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * console.c: hacks to do various cursor movement/attribute things + * -amol + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <wincon.h> +#include <stdio.h> +#include "ntport.h" + + +// int to SHORT. caused by all the stupid functions that take WORDs +#pragma warning(disable:4244) + +void ScrollBuf(HANDLE,CONSOLE_SCREEN_BUFFER_INFO*,int); +void NT_MoveToLineOrChar(int ,int ) ; +WORD get_attributes(); + + +#define FSHIN 16 /* Preferred desc for shell input */ +#define FSHOUT 17 /* Preferred desc for shell input */ + +#define FOREGROUND_BLACK (FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FOREGROUND_WHITE 0 +#define BACKGROUND_BLACK (BACKGROUND_RED |BACKGROUND_GREEN | BACKGROUND_BLUE) +#define BACKGROUND_WHITE 0 + +static WORD wNormalAttributes; + + +static int nt_is_raw; +// +// The following are used to optimize some console routines. It avoids having +// to call GetConsoleScreenBufferInfo. +// Seems to have helped the speed a bit. -amol +// +HANDLE ghstdout; +HANDLE ghReverse; + +// +// This function is called to set the values for above variables. +// +void redo_console(void) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hTemp= GetStdHandle(STD_OUTPUT_HANDLE); + WORD dbga; + DWORD wrote; + COORD origin = {0,0}; + + if (!DuplicateHandle(GetCurrentProcess(),hTemp,GetCurrentProcess(), + &ghstdout,0,TRUE,DUPLICATE_SAME_ACCESS) ) { + ; + } + + if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) { + wNormalAttributes = FOREGROUND_BLACK | BACKGROUND_WHITE; + } + else + wNormalAttributes = scrbuf.wAttributes; + + ghReverse = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CONSOLE_TEXTMODE_BUFFER, + NULL); + + dbga = ((wNormalAttributes & 0x00f0) >> 4) | + ((wNormalAttributes & 0x000f) << 4) ; + + FillConsoleOutputAttribute(ghReverse,dbga, + scrbuf.dwSize.X*scrbuf.dwSize.Y, + origin, + &wrote); +} +void nt_term_cleanup(void) { + CloseHandle(ghstdout); +} +void nt_term_init() { + + DWORD dwmode; + HANDLE hinput =GetStdHandle(STD_INPUT_HANDLE); + + if (!GetConsoleMode(hinput,&dwmode) ){ + ; + } + if(!SetConsoleMode(hinput,dwmode | ENABLE_WINDOW_INPUT) ){ + return; + } + + redo_console(); + + return; +} +int do_nt_check_cooked_mode(void) { + + return !nt_is_raw; +} +void do_nt_raw_mode() { + + DWORD dwmode; + HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN); + + if (hinput == INVALID_HANDLE_VALUE) + return; + if (!GetConsoleMode(hinput,&dwmode) ){ + ; + } + if(!SetConsoleMode(hinput,dwmode & (~( + ENABLE_LINE_INPUT |ENABLE_ECHO_INPUT + | ENABLE_PROCESSED_INPUT)| ENABLE_WINDOW_INPUT ) + ) ){ + return; + } + nt_is_raw = 1; + return; +} +void do_nt_cooked_mode() { + + DWORD dwmode; + HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN); + + if (hinput == INVALID_HANDLE_VALUE) + return; + if (!GetConsoleMode(hinput,&dwmode) ){ + ; + } + if(!SetConsoleMode(hinput,dwmode | ( ( + ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT | + ENABLE_PROCESSED_INPUT) ) + ) ){ + } + nt_is_raw = 0; + return; +} +// +// this function is a bit ugly, but I don't know how to do it better +// -amol +// +int nt_ClearEOL( void) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout =ghstdout ; + DWORD numwrote; + char errbuf[128];/*FIXME: uninitialized*/ + int num=0; + COORD savepos; + + + if (hStdout == INVALID_HANDLE_VALUE){ + ExitProcess(0xFFFF); + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return 0 ; + } + num =2048; + + savepos = scrbuf.dwCursorPosition; + if (!FillConsoleOutputCharacter(hStdout,' ',num,scrbuf.dwCursorPosition, + &numwrote) ){ + dprintf("error from FillCons %s",errbuf); + } + else if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, num, + scrbuf.dwCursorPosition,&numwrote)) { + dprintf("error from FillConsAttr %s",errbuf); + } + return 0; +} +void nt_move_next_tab(void) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout = ghstdout; + int where; + + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + where = 8 - (scrbuf.dwCursorPosition.X+1)%8; + scrbuf.dwCursorPosition.X += where; + if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) { + ; + } + +} +void NT_VisibleBell(void) { + + if(ghReverse != INVALID_HANDLE_VALUE) { + SetConsoleActiveScreenBuffer(ghReverse); + Sleep(100); + SetConsoleActiveScreenBuffer(ghstdout); + + } + +} +void NT_WrapHorizontal(void) { + SMALL_RECT wnd; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + + + if (ghstdout == INVALID_HANDLE_VALUE){ + return; + } + if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) { + return; + } + //absolute movement + wnd.Left = 0;//scrbuf.srWindow.Left ; + wnd.Right = scrbuf.srWindow.Right- scrbuf.srWindow.Left + 1; + wnd.Top = scrbuf.srWindow.Top; + wnd.Bottom = scrbuf.srWindow.Bottom; + + SetConsoleWindowInfo(ghstdout,TRUE,&wnd); +} +void ScrollBufHorizontal(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf, + int where) { + SMALL_RECT wnd; + int diff; + CHAR_INFO chr; + + + //absolute movement + wnd.Left = (where - scrbuf->srWindow.Right) + scrbuf->srWindow.Left ; + wnd.Right = where; + wnd.Top = scrbuf->srWindow.Top; + wnd.Bottom = scrbuf->srWindow.Bottom; + + //diff = scrbuf->srWindow.Right - where; + //dprintf("\tdiff1 %d\n",diff); + + diff = scrbuf->dwSize.X - where -1; + + if (diff < 0) { //would scroll past console buffer + + chr.Char.AsciiChar = ' '; + chr.Attributes = scrbuf->wAttributes; + + scrbuf->dwCursorPosition.Y = scrbuf->srWindow.Top ; + scrbuf->dwCursorPosition.X = scrbuf->srWindow.Right+ diff; + + dprintf("scroll diff %d\n",diff); + if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow), + NULL, + scrbuf->dwCursorPosition,&chr)) + ; + + return; + } + + SetConsoleWindowInfo(hOut,TRUE,&wnd); +} +// relative movement of "where". line is 1 if we want to move to a line, +// or 0 if the movement is horizontal +void NT_MoveToLineOrChar(int where,int line) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout = ghstdout; + + + if (hStdout == INVALID_HANDLE_VALUE){ + return; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return; + } + + if (line){ + if ( ((scrbuf.dwCursorPosition.Y+where)> (scrbuf.srWindow.Bottom-1)) + &&( where >0)){ + ScrollBuf(hStdout,&scrbuf,where); + scrbuf.dwCursorPosition.Y += where; + } + else + scrbuf.dwCursorPosition.Y += where; + } + else{ + if ( (where> (scrbuf.srWindow.Right)) &&( where >0)){ + ScrollBufHorizontal(hStdout,&scrbuf,where); + } + scrbuf.dwCursorPosition.X = where; + } + if (scrbuf.dwCursorPosition.X < 0 || scrbuf.dwCursorPosition.Y <0) + return; + if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) { + return; + } + +} +void ScrollBuf(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf,int where) { + SMALL_RECT wnd; + int diff; + CHAR_INFO chr; + COORD newpos; + + + wnd.Left = 0; + wnd.Right = 0; + wnd.Top = where; + wnd.Bottom = where; + + //dwSize is not 0-based, so add 1 to proposed location + diff = scrbuf->srWindow.Bottom + where + 1; + + diff = scrbuf->dwSize.Y - diff; + + if (diff < 0) { //would scroll past console buffer + + chr.Char.AsciiChar = ' '; + chr.Attributes = scrbuf->wAttributes; + + newpos.Y = scrbuf->srWindow.Top + diff; + newpos.X = scrbuf->srWindow.Left; + + dprintf("scroll diff %d\n",diff); + if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow), + NULL, + newpos,&chr)) + ; + + // need this to be in sync with tcsh + scrbuf->dwCursorPosition.Y += diff; + return; + } + + SetConsoleWindowInfo(hOut,FALSE,&wnd); +} +BOOL ConsolePageUpOrDown(BOOL Up) { + + HANDLE hStdout = ghstdout; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + SMALL_RECT srect; + short diff; + + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return FALSE; + } + diff = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ; + + + if (Up) + diff = -diff; + + if ((scrbuf.srWindow.Top + diff > 0) && + (scrbuf.srWindow.Bottom + diff < scrbuf.dwSize.Y)) { + srect.Top = diff; + srect.Bottom = diff; + srect.Left = 0; + srect.Right = 0; + + if (! SetConsoleWindowInfo( hStdout, FALSE, &srect)) { + return FALSE; + } + } + + return TRUE; +} +int nt_getsize(int * lins, int * cols, int *visiblecols) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout = ghstdout; + + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + *lins = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ; + + if(visiblecols) + *visiblecols = scrbuf.srWindow.Right -scrbuf.srWindow.Left +1; + + *cols = scrbuf.dwSize.X; + return 1; +} +void nt_set_size(int lins, int cols) { + SMALL_RECT srect; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + int expand; + + /* The screen buffer visible window is specified as co-ordinates + * not size. Therefore, it must be zero-based + */ + cols--; + lins--; + + srect.Left = srect.Top = 0; + srect.Right = cols; + srect.Bottom = lins; + + if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) + return; + + expand = 0; + if (scrbuf.dwSize.X < cols){ + expand = 1; + scrbuf.dwSize.X = cols+1; + } + if (scrbuf.dwSize.Y < lins){ + expand = 1; + scrbuf.dwSize.Y = lins+1; + } + + if (expand && !SetConsoleScreenBufferSize(ghstdout,scrbuf.dwSize)) + return; + + if(!SetConsoleWindowInfo(ghstdout,TRUE,&srect)){ + int err; + err=GetLastError(); + dprintf("error %d\n",err); + } +} +void NT_ClearEOD(void) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + DWORD numwrote; + COORD origin; + int ht,wt; + HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE); + + if (hStdout == INVALID_HANDLE_VALUE){ + return ; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return ; + } + origin = scrbuf.dwCursorPosition; + ht = scrbuf.dwSize.Y - origin.Y; + wt = scrbuf.dwSize.X - origin.X; + if(!FillConsoleOutputCharacter(hStdout,' ',ht*wt,origin,&numwrote) ) { + return ; + } + if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, ht*wt, + scrbuf.dwCursorPosition,&numwrote)) { + return; + } + return; +} +void NT_ClearScreen(void) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + DWORD numwrote; + COORD origin={0,0}; + HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE); + + if (hStdout == INVALID_HANDLE_VALUE){ + ; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + origin.X = scrbuf.srWindow.Left; + origin.Y = scrbuf.srWindow.Top; + if(!FillConsoleOutputCharacter(hStdout,' ',scrbuf.dwSize.X*scrbuf.dwSize.Y, + origin,&numwrote) ) { + ; + } + if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, + scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) { + ; + } + if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor + ; + } + return; +} +void NT_ClearScreen_WholeBuffer(void) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + DWORD numwrote; + COORD origin={0,0}; + HANDLE hStdout = ghstdout; + + if (hStdout == INVALID_HANDLE_VALUE){ + ; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + if(!FillConsoleOutputCharacter(hStdout,' ',scrbuf.dwSize.X*scrbuf.dwSize.Y, + origin,&numwrote) ) { + ; + } + if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, + scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) { + ; + } + if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor + ; + } + return; +} + +#ifndef COLOR_LS_F +void set_cons_attr(char *attr2) { + char cp[3]; + USHORT attr; + HANDLE outhandle = (HANDLE)_get_osfhandle(FSHOUT); + static WORD old_attribs; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + + if (!old_attribs) { + if(!GetConsoleScreenBufferInfo(outhandle, &scrbuf) ) { + return; + } + old_attribs = scrbuf.wAttributes; + } + cp[0] = (unsigned char)(attr2[0]); + cp[1] = (unsigned char)(attr2[1]); + cp[2] = 0; + if (cp[0] != 'g' || cp[1] != 'g') + attr = (USHORT)strtol(cp,NULL,16); + else{ + attr = old_attribs; + old_attribs=0; + } + + SetConsoleTextAttribute(outhandle, attr ); +} +#endif /* !COLOR_LS_F */ + + +/* + color escape sequences (ISO 6429, aixterm) + - nayuta + */ + + +WORD get_attributes() { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + if (!GetConsoleScreenBufferInfo(ghstdout, &scrbuf)) + return 0x70; // ERROR: return white background, black text + return scrbuf.wAttributes; +} + + +#ifndef COMMON_LVB_REVERSE_VIDEO +#define COMMON_LVB_REVERSE_VIDEO 0x4000 +#define COMMON_LVB_UNDERSCORE 0x8000 +#endif + + +void set_attributes(const unsigned char *color) { + + static const int colors[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + WORD wAttributes; + const char *t; + + if (color[0] == '\x1b' && color[1] == '[') + color += 2; + + if (!('0' <= color[0] && color[0] <= '9')) { + SetConsoleTextAttribute(ghstdout, wNormalAttributes); + return; + } + + wAttributes = get_attributes(); + t = (char*)color; + + while (t) { + int n = atoi(t); + + if ((t = strchr(t, ';')) != NULL) + t++; + + if (n == 0) // Normal (default) + wAttributes = wNormalAttributes; + else if (n == 1) // Bold + wAttributes |= FOREGROUND_INTENSITY; + else if (n == 4) // Underlined + wAttributes |= COMMON_LVB_UNDERSCORE; + else if (n == 5) // Blink (appears as BACKGROUND_INTENSITY) + wAttributes |= BACKGROUND_INTENSITY; + else if (n == 7) // Inverse + wAttributes |= COMMON_LVB_REVERSE_VIDEO; + else if (n == 21) // Not bold + wAttributes &= ~FOREGROUND_INTENSITY; + else if (n == 24) // Not underlined + wAttributes &= ~COMMON_LVB_UNDERSCORE; + else if (n == 25) // Steady (not blinking) + wAttributes &= ~BACKGROUND_INTENSITY; + else if (n == 27) // Positive (not inverse) + wAttributes &= ~COMMON_LVB_REVERSE_VIDEO; + else if (30 <= n && n <= 37) // Set foreground color + wAttributes = (wAttributes & ~0x0007) | colors[n - 30]; + else if (n == 39) // Set foreground color to default + wAttributes = (wAttributes & ~0x0007) | (wNormalAttributes & 0x0007); + else if (40 <= n && n <= 47) // Set background color + wAttributes = (wAttributes & ~0x0070) | (colors[n - 40] << 4); + else if (n == 49) // Set background color to default + wAttributes = (wAttributes & ~0x0070) | (wNormalAttributes & 0x0070); + else if (90 <= n && n <= 97) // Set foreground color (bright) + wAttributes = (wAttributes & ~0x0007) | colors[n - 90] + | FOREGROUND_INTENSITY; + else if (100 <= n && n <= 107) // Set background color (bright) + wAttributes = (wAttributes & ~0x0070) | (colors[n - 100] << 4) + | BACKGROUND_INTENSITY; + else // (default) + wAttributes = wNormalAttributes; + } + + // Though Windows' console supports COMMON_LVB_REVERSE_VIDEO, + // it seems to be buggy. So we must simulate it. + if (wAttributes & COMMON_LVB_REVERSE_VIDEO) + wAttributes = (wAttributes & COMMON_LVB_UNDERSCORE) + | ((wAttributes & 0x00f0) >> 4) | ((wAttributes & 0x000f) << 4); + SetConsoleTextAttribute(ghstdout, wAttributes); +} +void StartHighlight(void) +{ +} +void StopHighlight(void) +{ +} diff --git a/win32/customstep.cmd b/win32/customstep.cmd new file mode 100644 index 000000000000..85e6b0f6f2f8 --- /dev/null +++ b/win32/customstep.cmd @@ -0,0 +1,7 @@ +@echo off
+setlocal
+call "%VS90COMNTOOLS%"\vsvars32.bat
+pushd "%1"
+copy config\win32 config.h
+nmake -f win32\makefile.win32 prebuild
+popd
diff --git a/win32/dirent.c b/win32/dirent.c new file mode 100644 index 000000000000..bfe7d075c4b1 --- /dev/null +++ b/win32/dirent.c @@ -0,0 +1,364 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/dirent.c,v 1.9 2006/04/07 00:57:59 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* dirent.c + * directory interface functions. Sort of like dirent functions on unix. + * Also allow browsing network shares as if they were directories + * + * -amol + * + */ +#define WIN32_LEAN_AND_MEAN +#include <stdio.h> +#include <errno.h> +#include <assert.h> +#include <direct.h> +#include "dirent.h" +#include <winnetwk.h> + +#ifndef WINDOWS_ONLY +#define STRSAFE_NO_DEPRECATE +#endif /* WINDOWS_ONLY*/ +#define STRSAFE_LIB +#define STRSAFE_NO_CCH_FUNCTIONS +#include <strsafe.h> + +#pragma intrinsic("memset") + +static HANDLE open_enum(char *,WIN32_FIND_DATA*); +static void close_enum(DIR*) ; +static int enum_next_share(DIR*); + +typedef struct _enum_h { + unsigned char *netres; + HANDLE henum; +} nethandle_t; + +static int inode= 1; // useless piece that some unix programs need +DIR * opendir(const char *inbuf) { + + DIR *dptr; + WIN32_FIND_DATA fdata = {0}; + char *tmp = NULL; + char *buf = NULL; + int is_net=0; + int had_error = 0; + size_t buflen; + + buflen = lstrlen(inbuf) + 1; + buf= (char *)heap_alloc(buflen); + (void)StringCbCopy(buf,buflen,inbuf); + + if (!buf) + buf = "." ; + tmp = buf; + while(*tmp) { +#ifdef DSPMBYTE + if (Ismbyte1(*tmp) && *(tmp + 1)) + tmp ++; + else +#endif DSPMBYTE + if (*tmp == '\\') + *tmp = '/'; + tmp++; + } + /* + * paths like / confuse NT because it looks like a UNC name + * when we append "\*" -amol + */ + if (*(tmp -1) == '/') + *(tmp -1) = 0; + + buflen = lstrlen(buf) + 4; + tmp= (char *)heap_alloc(buflen); + + if ( (buf[0] == '/') && (buf[1] != '/') ) { + (void)StringCbPrintf(tmp,buflen, "%c:%s*", + 'A' + (_getdrive()-1),buf); + } + else if ( (buf[0] == '/') && (buf[1] == '/') ){ + is_net = 1; + (void)StringCbPrintf(tmp,buflen,"%s",buf); + } + else { + (void)StringCbPrintf(tmp,buflen,"%s/*",buf); + } + + dptr = (DIR *)heap_alloc(sizeof(DIR)); + dptr->dd_fd = INVALID_HANDLE_VALUE; + if (!dptr){ + errno = ENOMEM; + had_error =1; + goto done; + } + + if (is_net){ + dptr->dd_fd = open_enum(tmp,&fdata); + dptr->flags = IS_NET; + } + if (dptr->dd_fd == INVALID_HANDLE_VALUE){ + (void)StringCbPrintf(tmp,buflen,"%s/*",buf); + dptr->flags = 0; + dptr->dd_fd = FindFirstFile(tmp,&fdata); + } + if (dptr->dd_fd == INVALID_HANDLE_VALUE){ + if (GetLastError() == ERROR_DIRECTORY) + errno = ENOTDIR; + else + errno = ENOENT; + + had_error =1; + goto done; + } + memset(dptr->orig_dir_name,0,sizeof(dptr->orig_dir_name)); + memcpy(dptr->orig_dir_name,tmp,lstrlen(tmp)); + + dptr->dd_loc = 0; + dptr->dd_size = fdata.nFileSizeLow; + dptr->dd_buf = (struct dirent *)heap_alloc(sizeof(struct dirent)); + if (!dptr->dd_buf){ + errno = ENOMEM; + had_error=1; + goto done; + } + (dptr->dd_buf)->d_ino = inode++; + (dptr->dd_buf)->d_off = 0; + (dptr->dd_buf)->d_reclen = 0; + if (lstrcmpi(fdata.cFileName,".") ){ + //dptr->dd_buf->d_name[0] = '.'; + memcpy((dptr->dd_buf)->d_name,".",2); + dptr->flags |= IS_ROOT; + } + else + memcpy((dptr->dd_buf)->d_name,fdata.cFileName,MAX_PATH); + +done: + if(tmp) + heap_free(tmp); + if(had_error) { + heap_free(dptr); + dptr = NULL; + } + + return dptr; +} +int closedir(DIR *dptr){ + + if (!dptr) + return 0; + if (dptr->flags & IS_NET) { + close_enum(dptr); + } + else + FindClose(dptr->dd_fd); + heap_free(dptr->dd_buf); + heap_free(dptr); + return 0; +} +void rewinddir(DIR *dptr) { + + HANDLE hfind; + WIN32_FIND_DATA fdata; + char *tmp = dptr->orig_dir_name; + + if (!dptr) return; + + if (dptr->flags & IS_NET) { + hfind = open_enum(tmp,&fdata); + close_enum(dptr); + dptr->dd_fd = hfind; + } + else { + hfind = FindFirstFile(tmp,&fdata); + assert(hfind != INVALID_HANDLE_VALUE); + FindClose(dptr->dd_fd); + dptr->dd_fd = hfind; + } + dptr->dd_size = fdata.nFileSizeLow; + (dptr->dd_buf)->d_ino = inode++; + (dptr->dd_buf)->d_off = 0; + (dptr->dd_buf)->d_reclen = 0; + memcpy((dptr->dd_buf)->d_name,fdata.cFileName,MAX_PATH); + return; +} +struct dirent *readdir(DIR *dir) { + + WIN32_FIND_DATA fdata = {0}; + HANDLE hfind; + char *tmp ; + + if (!dir) + return NULL; + + if (dir->flags & IS_NET) { + if(enum_next_share(dir)<0) + return NULL; + } + // special hack for root (which does not have . or ..) + else if (dir->flags & IS_ROOT) { + tmp= dir->orig_dir_name; + hfind = FindFirstFile(tmp,&fdata); + FindClose(dir->dd_fd); + dir->dd_fd = hfind; + dir->dd_size = fdata.nFileSizeLow; + (dir->dd_buf)->d_ino = inode++; + (dir->dd_buf)->d_off = 0; + (dir->dd_buf)->d_reclen = 0; + memcpy((dir->dd_buf)->d_name,fdata.cFileName,MAX_PATH); + dir->flags &= ~IS_ROOT; + return dir->dd_buf; + + } + if(!(dir->flags & IS_NET) && !FindNextFile(dir->dd_fd,&fdata) ){ + return NULL; + } + (dir->dd_buf)->d_ino = inode++; + (dir->dd_buf)->d_off = 0; + (dir->dd_buf)->d_reclen = 0; + if (! (dir->flags & IS_NET)) + memcpy((dir->dd_buf)->d_name,fdata.cFileName,MAX_PATH); + + return dir->dd_buf; + +} + +// Support for treating share names as directories +// -amol 5/28/97 +static int ginited = 0; +static HMODULE hmpr; + +typedef DWORD (__stdcall *open_fn)(DWORD,DWORD,DWORD,NETRESOURCE *, HANDLE*); +typedef DWORD (__stdcall *close_fn)( HANDLE); +typedef DWORD (__stdcall *enum_fn)( HANDLE,DWORD * ,void *,DWORD*); + + +static open_fn p_WNetOpenEnum; +static close_fn p_WNetCloseEnum; +static enum_fn p_WNetEnumResource; + +HANDLE open_enum(char *server, WIN32_FIND_DATA *fdata) { + + NETRESOURCE netres; + HANDLE henum; + unsigned long ret; + char *ptr; + int slashes; + + nethandle_t *hnet; + + ptr = server; + slashes = 0; + + while(*ptr) { + if (*ptr == '/') { + *ptr = '\\'; + slashes++; + } + ptr++; + } + + if (!ginited) { + hmpr = LoadLibrary("MPR.DLL"); + if (!hmpr) + return INVALID_HANDLE_VALUE; + + p_WNetOpenEnum = (open_fn)GetProcAddress(hmpr,"WNetOpenEnumA"); + p_WNetCloseEnum = (close_fn)GetProcAddress(hmpr,"WNetCloseEnum"); + p_WNetEnumResource = (enum_fn)GetProcAddress(hmpr,"WNetEnumResourceA"); + + if (!p_WNetOpenEnum || !p_WNetCloseEnum || !p_WNetEnumResource) + return INVALID_HANDLE_VALUE; + ginited = 1; + } + if (slashes > 2) + return INVALID_HANDLE_VALUE; + + memset(fdata,0,sizeof(WIN32_FIND_DATA)); + fdata->cFileName[0] = '.'; + + netres.dwScope = RESOURCE_GLOBALNET; + netres.dwType = RESOURCETYPE_ANY; + netres.lpRemoteName = server; + netres.lpProvider = NULL; + netres.dwUsage = 0; + + ret = p_WNetOpenEnum(RESOURCE_GLOBALNET,RESOURCETYPE_ANY,0, + &netres,&henum); + if (ret != NO_ERROR) + return INVALID_HANDLE_VALUE; + + hnet = heap_alloc(sizeof(nethandle_t)); + hnet->netres = heap_alloc(1024);/*FIXBUF*/ + hnet->henum = henum; + + + return (HANDLE)hnet; + +} +void close_enum(DIR*dptr) { + nethandle_t *hnet; + + hnet = (nethandle_t*)(dptr->dd_fd); + + heap_free(hnet->netres); + p_WNetCloseEnum(hnet->henum); + heap_free(hnet); +} +int enum_next_share(DIR *dir) { + nethandle_t *hnet; + char *tmp,*p1; + HANDLE henum; + DWORD count, breq,ret; + + hnet = (nethandle_t*)(dir->dd_fd); + henum = hnet->henum; + count = 1; + breq = 1024; + + ret = p_WNetEnumResource(henum, &count,hnet->netres,&breq); + if (ret != NO_ERROR) + return -1; + + tmp = ((NETRESOURCE*)hnet->netres)->lpRemoteName; + p1 = &tmp[2]; +#ifdef DSPMBYTE + for (; *p1 != '\\'; p1 ++) + if (Ismbyte1(*p1) && *(p1 + 1)) + p1 ++; +#else /* DSPMBYTE */ + while(*p1++ != '\\'); +#endif /* DSPMBYTE */ + + memcpy( (dir->dd_buf)->d_name, p1, lstrlen(p1)+1); + + dir->dd_size = 0; + + return 0; +} diff --git a/win32/dirent.h b/win32/dirent.h new file mode 100644 index 000000000000..95fb8b38dd5a --- /dev/null +++ b/win32/dirent.h @@ -0,0 +1,72 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/dirent.h,v 1.6 2006/03/03 22:08:45 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * dirent.h + * directory interface functions. Sort of like dirent functions on unix. + * -amol + * + */ +#ifndef DIRENT_H +#define DIRENT_H + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define heap_alloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s)) +#define heap_free(p) HeapFree(GetProcessHeap(),0,(p)) +#define heap_realloc(p,s) HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(p),(s)) + +#define NAME_MAX MAX_PATH + +#define IS_ROOT 0x01 +#define IS_NET 0x02 + +struct dirent { + long d_ino; + int d_off; + unsigned short d_reclen; + char d_name[NAME_MAX+1]; +}; + +typedef struct { + HANDLE dd_fd; + int dd_loc; + int dd_size; + int flags; + char orig_dir_name[NAME_MAX +1]; + struct dirent *dd_buf; +}DIR; + +DIR *opendir(const char*); +struct dirent *readdir(DIR*); +int closedir(DIR*); +void rewinddir(DIR*); +#endif DIRENT_H diff --git a/win32/example.tcshrc b/win32/example.tcshrc new file mode 100644 index 000000000000..bb3b52d023b7 --- /dev/null +++ b/win32/example.tcshrc @@ -0,0 +1,211 @@ +#set verbose +# set environmental variables + setenv EDITOR vi.exe + setenv PAGER c:/bin/less +# setenv DISPLAY unix:0 + setenv LESS "-B -c -h4 -i -M -q -x4 -G" + setenv SHELL C:/bin/tcsh.exe +if ($?PROCESSOR_ARCHITECTURE) then + setenv USER $USERNAME + setenv LOGNAME $USER + setenv HOSTNAME $COMPUTERNAME +endif + +umask 077 +if (! $?prompt) then # Everything else is interactive + exit(0) +endif + +#tcsh-specific stuff +if ($?tcsh) then +# bindkey -v + set autolist + set listlinks + set pushdtohome + set visiblebell + + set ellipsis + set rmstar +# set prompt='%{f9%}%/%{gg%}(%{f2%}%?%{gg%})\>' +if ($?TERM) then + if ($TERM == "emacs") then + set prompt='%/\>' + else + set prompt='%{f9%}%c03%{gg%}\>' + set prompt3 = '%{fc%}Correct to %R ?(y|n|e)%{gg%} ' + endif +else + set prompt='%{f9%}%c03%{gg%}\>' + set prompt3 = '%{fc%}Correct to %R ?(y|n|e)%{gg%} ' +endif + + if ($?loginsh) then + set correct=all + set savedirs=100 + set autocorrect + endif + +# set printexitvalue + set complete=igncase + + complete which 'p/*/c/' + complete where 'p/*/c/' + complete start 'p/*/c/' + complete cd 'p/1/d/' + complete pushd 'p/1/d/' + complete popd 'p/1/d/' + complete tar 'n/-tvf/t:*.tar/' 'n/-xvf/t:*.tar/' + complete winhlp32 'p/*/f:*.HLP/' + complete pkunzip 'p/*/f:*.{ZIP,zip}/' + complete pkzip 'p/*/f:*.{zip,ZIP}/' + complete nmake 'p/*/f:*.MAK/' + complete bindkey 'p/*/b/' + complete set 'p/*/v/' + complete unset 'p/*/v/' + +# complex completions + +set noglob + complete gzip c/--/"(stdout to-stdout decompress uncompress \ + force help list license no-name quiet recurse \ + suffix test verbose version fast best)"/ \ + c/-/"(c d f h l L n q r S t v V 1 2 3 4 5 6 7 8 9 -)"/\ + n/{-S,--suffix}/x:'<file_name_suffix>'/ \ + n/{-d,--{de,un}compress}/f:*.{gz,Z,z,zip,taz,tgz}/ \ + N/{-d,--{de,un}compress}/f:*.{gz,Z,z,zip,taz,tgz}/ \ + n/*/f:^*.{gz,Z,z,zip,taz,tgz}/ + complete {gunzip,ungzip} c/--/"(stdout to-stdout force help list license \ + no-name quiet recurse suffix test verbose version)"/ \ + c/-/"(c f h l L n q r S t v V -)"/ \ + n/{-S,--suffix}/x:'<file_name_suffix>'/ \ + n/*/f:*.{gz,Z,z,zip,taz,tgz}/ + complete mv c/--/"(backup force interactive update verbose suffix \ + version-control help version)"/ \ + c/-/"(b f i u v S V -)"/ \ + n/{-S,--suffix}/x:'<suffix>'/ \ + n/{-V,--version-control}/"(t numbered nil existing \ + never simple)"/ n/-/f/ N/-/d/ p/1/f/ p/2/d/ n/*/f/ + complete cp c/--/"(archive backup no-dereference force interactive \ + link preserve symbolic-link update verbose parents \ + one-file-system recursive suffix version-control help \ + version)"/ c/-/"(a b d f i l p r s u v x P R S V -)"/ \ + n/-*r/d/ n/{-S,--suffix}/x:'<suffix>'/ \ + n/{-V,--version-control}/"(t numbered nil existing \ + never simple)"/ n/-/f/ N/-/d/ p/1/f/ p/2/d/ n/*/f/ + + + complete net p/1/"(accounts computer config continue file group \ + help helpmsg localgroup name pause print send session \ + share start statistics stop time use user view)"/ \ + n/config/"(server workstation)"/ \ + n/help/"(accounts computer config continue file group \ + help helpmsg localgroup name pause print send session \ + share start statistics stop time use user view)"/ \ + n/view/"( \\server1 \\server2 )"/ \ + n/\*/"( \\server1\share1 \\server2\share2 )"/ + + complete cl c@-@"(O G F C D E P U u I X v Z ? c H J nologo T V \ + w W Y M L link)"@ \ + n@-link@F:d:/lang/msdev/lib@ \ + c/-O/"(1 2 a b d g i p s t w x y)"/ \ + c/-G/"(3 4 5 B d r z e s f y h X)"/ \ + c/-F/"(a A d e m o p r R)"/ \ + c/-Z/"(i 7 d p a e g l z)"/ \ + c/-M/"(T D L)"/ \ + n@*@f:*.{c,C,cpp,CPP}@ +unset noglob +#end completions + + bindkey -b ^W backward-delete-word + bindkey -b ^U backward-kill-line + bindkey -b ^R complete-word-fwd + bindkey -b M-g list-glob + bindkey -b M-* expand-glob + bindkey -b M-v expand-variables + bindkey -b M-w normalize-command + bindkey -b M-/ which-command + bindkey -b M-r i-search-back + bindkey -b M-s i-search-fwd + +# bindkey -b C-I complete-word-fwd + +# NT specific bindkey extensions + bindkey -b N-up up-history + bindkey -b N-down down-history + bindkey -b N-right forward-char + bindkey -b N-left backward-char + bindkey -b N-del delete-char + bindkey -b N-ins overwrite-mode + bindkey -b N-1 which-command + bindkey -b N-2 expand-history + bindkey -b N-3 complete-word-raw + bindkey -b N-home beginning-of-line + bindkey -b N-end end-of-line + +#csh stuff +else + set sedstr = "s:/[^/]*/[^/]*/[^/]*/::" + set prompt="`echo $cwd | sed -e 's:/[^/]*/[^/]*/[^/]*/::'`>" + alias cd ' cd \!*; set prompt=`echo $cwd | sed -e "$sedstr"`\>' + alias pushd ' pushd \!*; set prompt=`echo $cwd | sed -e "$sedstr"`\>' + alias popd ' popd \!*; set prompt=`echo $cwd | sed -e "$sedstr"`\>' +endif + +#common to tcsh and csh + + + +if (! $?PATH_DONE) then +set path=($path c:/gnubin .) +setenv PATH_DONE 1 +endif + +set notify +set cdpath=( C:/ D:/ )#E:/ H:/samples ) +set noclobber +set filec +set history=(1000) +#"%h %T %{a2%}%R%{gg%}\n") +#set histdup=all +set savehist=(200 merge) +set ignoreeof +set fignore =(.obj .pdb .bsc .ilk .idb .OBJ .PDB .BSC .ILK .IDB) + +set NTlamepathfix +eval `dircolors` +unalias v d ls vdir dir + +alias ls ls-F +alias lc ls $LS_OPTIONS +alias h history +#alias cwdcmd 'title `echo $cwd`' + +# +# use the win32gnu utils for the following. or the win32sdk ones if you prefer. +# PLEASE don't alias them to the posix utils in the reskit.. +# +alias rm c:/gnubin/rm.exe -i +alias rd c:/gnubin/rmdir.exe +alias md c:/gnubin/mkdir.exe +alias mv C:/bin/mv.exe -i +alias cp C:/bin/cp.exe -i +alias pwd 'echo $cwd' +# +alias env printenv +alias net NET.EXE # avoid spelling correction to "set" +alias cl CL.EXE # avoid spelling correction to "cp" +alias word c:/apps/winword/winword/winword.exe +alias excel e:/apps/excel/Excel/Excel.exe +#alias telnet qvtnet32 +alias emacs c:/bin/emacs.csh +alias gemacs c:/bin/gemacs.csh #gui emacs +alias eshell c:/bin/eshell.csh +alias helpcommand winhlp32 +alias benvcmd start cmd /k benv.cmd +alias benv source c:/bin/razzle.csh + +alias use c:/bin/netuse.csh +alias unuse c:/bin/netunuse.csh + +alias unsave unset savehist savedirs + diff --git a/win32/fork.c b/win32/fork.c new file mode 100644 index 000000000000..d173e7ce0422 --- /dev/null +++ b/win32/fork.c @@ -0,0 +1,614 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/fork.c,v 1.11 2008/08/31 14:09:01 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The fork() here is based on the ideas used by cygwin + * -amol + * + */ + +/* + * _M_ALPHA changes by Mark Tucker + */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <fcntl.h> +#include <io.h> +#include <stdlib.h> +#include <setjmp.h> +#include <ntport.h> +#include "forkdata.h" +#include "sh.h" + +#pragma intrinsic("memcpy", "memset","memcmp") +#pragma warning(push,3) // forget about W4 here + +typedef unsigned long u_long; +typedef void *ptr_t; +typedef unsigned char U_char; +typedef unsigned int U_int; +typedef unsigned short U_short; +typedef unsigned long U_long; + + +static void stack_probe(void *ptr) ; +/*static void heap_init(void);*/ +BOOL CreateWow64Events(DWORD , HANDLE *, HANDLE *, BOOL); + +// +// This is exported from the user program. +// It must return 0 for no error !!!! +extern int fork_copy_user_mem(HANDLE ); + +/* + * Apparently , visual c++ on the alpha does not place the + * fork data contiguously. To work around that, Mark created + * this structure (see forkdata.h) + * -amol + */ +ForkData gForkData = {0,0,0,0,0,{0},0,0,0}; + + +#ifdef _M_IX86 + +u_long _old_exr = 0; // Saved exception registration for longjmp + +#endif // _M_ALPHA +/* + * This hack is an attempt at getting to the exception registration + * in an architecture-independent way. It's critical for longjmp in a + * code using __try/__except blocks. Microsoft Visual C++ does a global + * unwind during a longjmp, and that can cause havoc if the exception + * registration stored in longjmp is lower(address wise, indicating a jump + * from below of the stack upward.) in the stack than the current + * registration (returned by NtCurrentTeb). + * + * This works with VC++, because that's all I have. With other compilers, + * there might be minimal changes required, depending on where the + * exception registration record is stored in the longjmp structure. + * + * -amol 2/6/97 + */ + +NT_TIB * (* myNtCurrentTeb)(void); + +#define GETEXCEPTIONREGIST() (((NT_TIB*)get_teb())->ExceptionList) +#define GETSTACKBASE() (((NT_TIB*)get_teb())->StackBase) + + + +static NT_TIB *the_tib; + +#if !defined(_M_IA64) && !defined(_M_AMD64) +void *get_teb(void) { + + + if (the_tib) + return the_tib; + + myNtCurrentTeb = (void*)GetProcAddress(LoadLibrary("ntdll.dll"), + "NtCurrentTeb"); + if (!myNtCurrentTeb) + return NULL; + the_tib = myNtCurrentTeb(); + + if (the_tib == NULL) + abort(); + return the_tib; +} +#else +#define get_teb NtCurrentTeb +#endif _M_IA64 + +void set_stackbase(void*ptr){ + GETSTACKBASE() = ptr; +} +/* + * This must be called by the application as the first thing it does. + * -amol 2/6/97 + * + * Well, maybe not the FIRST.. + * -amol 11/10/97 + */ + +extern BOOL bIsWow64Process; + +int fork_init(void) { + + + //heap_init(); Now called as the very first thing in silly_entry(). + + if (__forked) { + + + // stack_probe probes out a decent-sized stack for the child, + // since initially it has a very small stack (1 page). + // + + /* not needed since default commit is set to 0.5MB in + * makefile.win32 + * + * stack_probe((char *)__fork_stack_end - 64); + */ + + // + // Save the old Exception registration record and jump + // off the cliff. + // +#ifdef _M_IX86 + _old_exr = __fork_context[6]; + __fork_context[6] =(int)GETEXCEPTIONREGIST();//tmp; +#endif _M_ALPHA + // + // Whee ! + longjmp(__fork_context,1); + } + + return 0; +} +int fork(void) { + + size_t rc; + size_t stacksize; + char modname[512];/*FIXBUF*/ + HANDLE hProc,hThread, hArray[2]; + STARTUPINFO si; + PROCESS_INFORMATION pi; + SECURITY_ATTRIBUTES sa; + DWORD dwCreationflags; + unsigned int priority; + HANDLE h64Parent,h64Child; + +#ifndef _M_ALPHA + unsigned long fork_stack_end; +#endif _M_ALPHA + + __fork_stack_begin =GETSTACKBASE(); + +#ifndef _M_ALPHA + __fork_stack_end = &fork_stack_end; +#else + __fork_stack_end = (unsigned long *)__asm("mov $sp, $0"); +#endif /*_M_ALPHA*/ + + h64Parent = h64Child = NULL; + // + // Create two inheritable events + // + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor =0; + sa.bInheritHandle = TRUE; + if (!__hforkchild) + __hforkchild = CreateEvent(&sa,TRUE,FALSE,NULL); + if (!__hforkparent) + __hforkparent = CreateEvent(&sa,TRUE,FALSE,NULL); + + rc = setjmp(__fork_context); + + if (rc) { // child +#ifdef _M_IX86 + // + // Restore old registration + // -amol 2/2/97 + GETEXCEPTIONREGIST() = (struct _EXCEPTION_REGISTRATION_RECORD*)_old_exr; +#endif // _M_ALPHA + SetEvent(__hforkchild); + + dprintf("Child ready to rumble\n"); + if(WaitForSingleObject(__hforkparent,FORK_TIMEOUT) != WAIT_OBJECT_0) + ExitProcess(0xFFFF); + + CloseHandle(__hforkchild); + CloseHandle(__hforkparent); + __hforkchild = __hforkparent=0; + + //__asm { int 3}; + restore_fds(); + + STR_environ = blk2short(environ); + environ = short2blk(STR_environ); /* So that we can free it */ + + return 0; + } + copy_fds(); + memset(&si,0,sizeof(si)); + si.cb= sizeof(si); + + /* + * This f!@#!@% function returns the old value even if the std handles + * have been closed. + * Skip this step, since we know tcsh will do the right thing later. + * + si.hStdInput= GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + */ + + if (!GetModuleFileName(GetModuleHandle(NULL),modname,512) ) { + rc = GetLastError(); + return -1; + } + dwCreationflags = GetPriorityClass(GetCurrentProcess()); + priority = GetThreadPriority(GetCurrentThread()); + rc = CreateProcess(NULL, + modname, + NULL, + NULL, + TRUE, + CREATE_SUSPENDED | dwCreationflags, + NULL, + NULL, + &si, + &pi); + if (!rc) { + rc = GetLastError(); + return -1; + } + + ResetEvent(__hforkchild); + ResetEvent(__hforkparent); + + hProc = pi.hProcess; + hThread = pi.hThread; + + + __forked=1; + /* + * Usage of events in the wow64 case: + * + * h64Parent : initially non-signalled + * h64Child : initially non-signalled + * + * 1. Create the events, resume the child thread. + * 2. Child opens h64Parent to see if it is a child process in wow64 + * 3. Child opens and sets h64Child to tell parent it's running. (This + * step is needed because we can't copy to a process created in the + * suspended state on wow64.) + * 4. Copy gForkData and then set h64Parent. This tells the child + * that the parameters in the structure are trustworthy. + * 5. Wait for h64Child so that we know the child has created the stack + * in dynamic memory. + * + * The rest of the fork hack should now proceed as in x86 + * + */ + if (bIsWow64Process) { + + // allocate the heap for the child. this can be done even when + // the child is suspended. + // avoids inexplicable allocation failures in the child. + if (VirtualAllocEx(hProc, + __heap_base, + __heap_size, + MEM_RESERVE, + PAGE_READWRITE) == NULL) { + dprintf("virtual allocex failed %d\n",GetLastError()); + goto error; + } + if (VirtualAllocEx(hProc, + __heap_base, + __heap_size, + MEM_COMMIT, + PAGE_READWRITE) == NULL) { + dprintf("virtual allocex2 failed %d\n",GetLastError()); + goto error; + } + + // Do NOT expect existing events + if (!CreateWow64Events(pi.dwProcessId,&h64Parent,&h64Child,FALSE)) { + goto error; + } + ResumeThread(hThread); + + // wait for the child to tell us it is running + //if (WaitForSingleObject(h64Child,FORK_TIMEOUT) != WAIT_OBJECT_0) { + // rc = GetLastError(); + // goto error; + //} + hArray[0] = h64Child; + hArray[1] = hProc; + + if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != + WAIT_OBJECT_0){ + + rc = GetLastError(); + goto error; + } + + } + // + // Copy all the shared data + // + if (!WriteProcessMemory(hProc,&gForkData,&gForkData, + sizeof(ForkData),&rc)) { + goto error; + } + if (rc != sizeof(ForkData)) + goto error; + + if (!bIsWow64Process) { + rc = ResumeThread(hThread); + } + // in the wow64 case, the child will be waiting on h64parent again. + // set it, and then wait for h64child. This will mean the child has + // a stack set up at the right location. + else { + SetEvent(h64Parent); + hArray[0] = h64Child; + hArray[1] = hProc; + + if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != + WAIT_OBJECT_0){ + + rc = GetLastError(); + goto error; + } + CloseHandle(h64Parent); + CloseHandle(h64Child); + h64Parent = h64Child = NULL; + } + + // + // Wait for the child to start and init itself. + // The timeout is so that we don't wait too long + // + hArray[0] = __hforkchild; + hArray[1] = hProc; + + if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != WAIT_OBJECT_0){ + + int err = GetLastError(); // For debugging purposes + dprintf("wait failed err %d\n",err); + goto error; + } + + // Stop the child again and copy the stack and heap + // + SuspendThread(hThread); + + if (!SetThreadPriority(hThread,priority) ) { + priority =GetLastError(); + } + + // stack + stacksize = (char*)__fork_stack_begin - (char*)__fork_stack_end; + if (!WriteProcessMemory(hProc,(char *)__fork_stack_end, + (char *)__fork_stack_end, + (u_long)stacksize, + &rc)){ + goto error; + } + // + // copy heap itself + if (!WriteProcessMemory(hProc, (void*)__heap_base,(void*)__heap_base, + (DWORD)((char*)__heap_top-(char*)__heap_base), + &rc)){ + goto error; + } + + rc = fork_copy_user_mem(hProc); + + if(rc) { + goto error; + } + + // Release the child. + SetEvent(__hforkparent); + rc = ResumeThread(hThread); + + __forked=0; + dprintf("forked process %d\n",pi.dwProcessId); + start_sigchild_thread(hProc,pi.dwProcessId); + close_copied_fds(); + + CloseHandle(hThread); + // + // return process id to parent. + return pi.dwProcessId; + +error: + __forked=0; + SetEvent(__hforkparent); + ResumeThread(hThread); + CloseHandle(hProc); + CloseHandle(hThread); + if (h64Parent) { + SetEvent(h64Parent); // don't let child block forever + CloseHandle(h64Parent); + } + if (h64Child) + CloseHandle(h64Child); + return -1; +} +#pragma optimize("",off) +// The damn optimizer will remove the recursion, resulting in an infinite +// loop. -amol 4/17/97 +void stack_probe (void *ptr) { + char buf[1000]; + int x; + + if (&x > (int *)ptr) + stack_probe(ptr); + (void)buf; +} +#pragma optimize("",on) +// +// This function basically reserves some heap space. +// In the child it also commits the size committed in the parent. +void heap_init(void) { + + char * temp; + int err; + if (__forked) { + temp = (char *)VirtualAlloc((void*)__heap_base,__heap_size, MEM_RESERVE, + PAGE_READWRITE); + if (temp != (char*)__heap_base) { + if (!temp){ + err = GetLastError(); + if (bIsWow64Process) + ExitProcess(0); + abort(); + } + else + __heap_base = temp; + } + if (!VirtualAlloc(__heap_base,(char*)__heap_top -(char*)__heap_base, + MEM_COMMIT,PAGE_READWRITE)){ + err = GetLastError(); + if (bIsWow64Process) + ExitProcess(0); + abort(); + } + temp = (char*)__heap_base; + } + else { + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + __heap_size = sysinfo.dwPageSize * 1024; + __heap_base = VirtualAlloc(0 , __heap_size,MEM_RESERVE|MEM_TOP_DOWN, + PAGE_READWRITE); + + if (__heap_base == 0) { + abort(); + } + + __heap_top = __heap_base; + } + +} +// +// Implementation of sbrk() for the fmalloc family +// +void * sbrk(int delta) { + + void *retval; + void *old_top=__heap_top; + char *b = (char*)__heap_top; + + if (delta == 0) + return __heap_top; + if (delta > 0) { + + retval =VirtualAlloc((void*)__heap_top,delta,MEM_COMMIT,PAGE_READWRITE); + + if (retval == 0 ) + abort(); + + b += delta; + __heap_top = (void*)b; + } + else { + retval = VirtualAlloc((void*)((char*)__heap_top - delta), + delta,MEM_DECOMMIT, PAGE_READWRITE); + + if (retval == 0) + abort(); + + b -= delta; + __heap_top = (void*)b; + } + + return (void*) old_top; +} +/* + * Semantics of CreateWow64Events + * + * Try to open the events even if bOpenExisting is FALSE. This will help + * us detect name duplication. + * + * 1. If OpenEvent succeeds,and bOpenExisting is FALSE, fail. + * + * 2. If OpenEvent failed,and bOpenExisting is TRUE fail + * + * 3. else create the events anew + * + */ +#define TCSH_WOW64_PARENT_EVENT_NAME "tcsh-wow64-parent-event" +#define TCSH_WOW64_CHILD_EVENT_NAME "tcsh-wow64-child-event" +BOOL CreateWow64Events(DWORD pid, HANDLE *hParent, HANDLE *hChild, + BOOL bOpenExisting) { + + SECURITY_ATTRIBUTES sa; + char parentname[256],childname[256]; + + *hParent = *hChild = NULL; + + // make darn sure they're not inherited + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor =0; + sa.bInheritHandle = FALSE; + // + +#pragma warning(disable:4995) + + // This event tells the child to hold for gForkData to be copied + wsprintfA(parentname, "Local\\%d-%s",pid, TCSH_WOW64_PARENT_EVENT_NAME); + + wsprintfA(childname, "Local\\%d-%s",pid, TCSH_WOW64_CHILD_EVENT_NAME ); + +#pragma warning(default:4995) + + *hParent = OpenEvent(EVENT_ALL_ACCESS,FALSE, parentname); + + if(*hParent) { + if (bOpenExisting == FALSE) { // didn't expect to be a child process + CloseHandle(*hParent); + *hParent = NULL; + return FALSE; + } + + *hChild = OpenEvent(EVENT_ALL_ACCESS,FALSE, childname); + if (!*hChild) { + CloseHandle(*hParent); + *hParent = NULL; + return FALSE; + } + + return TRUE; + } + else { //event does not exist + if (bOpenExisting == TRUE) + return FALSE; + } + + *hParent = CreateEvent(&sa,FALSE,FALSE,parentname); + if (!*hParent) + return FALSE; + + + *hChild = CreateEvent(&sa,FALSE,FALSE,childname); + if (!*hChild){ + CloseHandle(*hParent); + *hParent = NULL; + return FALSE; + } + return TRUE; +} diff --git a/win32/forkdata.h b/win32/forkdata.h new file mode 100644 index 000000000000..5d3f30a37f4e --- /dev/null +++ b/win32/forkdata.h @@ -0,0 +1,76 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/forkdata.h,v 1.4 2004/05/19 18:22:27 christos Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef FORK_DATA_H +#define FORK_DATA_H + +#include <setjmp.h> + +/* + * This structure is copied by fork() to the child process. It + * contains variables of national importance + * + * Thanks to Mark Tucker for the idea. tcsh now finally works on + * alphas. + * -amol + */ +typedef struct _fork_data { + unsigned long _forked; + void *_fork_stack_begin; + void *_fork_stack_end; + unsigned long _heap_size; + HANDLE _hforkparent, _hforkchild; + void * _heap_base; + void * _heap_top; + jmp_buf _fork_context; +} ForkData; + +#define __forked gForkData._forked +#define __fork_stack_begin gForkData._fork_stack_begin +#define __fork_stack_end gForkData._fork_stack_end +#define __hforkparent gForkData._hforkparent +#define __hforkchild gForkData._hforkchild +#define __fork_context gForkData._fork_context +#define __heap_base gForkData._heap_base +#define __heap_size gForkData._heap_size +#define __heap_top gForkData._heap_top + +extern ForkData gForkData; + +#ifdef NTDBG +#define FORK_TIMEOUT INFINITE +#else +#define FORK_TIMEOUT (50000) +#endif /*!NTDBG */ + + + +#endif FORK_DATA_H diff --git a/win32/globals.c b/win32/globals.c new file mode 100644 index 000000000000..7c5cc95b5217 --- /dev/null +++ b/win32/globals.c @@ -0,0 +1,222 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/globals.c,v 1.11 2008/09/10 20:34:21 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * globals.c: The mem locations needed in the child are copied here. + * -amol + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdlib.h> +#include <stdio.h> +#define STRSAFE_LIB +#define STRSAFE_NO_CCH_FUNCTIONS +#include <strsafe.h> + +extern unsigned long bookend1,bookend2; +extern char **environ; + +#define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224 +#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240 + +#ifdef _WIN64 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL64_HEADER +#else +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL32_HEADER +#endif + + +#undef dprintf +void +dprintf(char *format, ...) +{ /* } */ + va_list vl; + char putbuf[2048]; + DWORD err; + + err = GetLastError(); + { + va_start(vl, format); +#pragma warning(disable:4995) + wvsprintf(putbuf,format, vl); +#pragma warning(default:4995) + va_end(vl); + OutputDebugString(putbuf); + } + SetLastError(err); +} +/* + * This function is called by fork(). The process must copy + * whatever memory is needed in the child. hproc is a handle + * to the child process + * + */ +int fork_copy_user_mem(HANDLE hproc) { + + SIZE_T bytes,rc; + SIZE_T size; + void *low = &bookend1, *high= &bookend2; + + if(&bookend1 > &bookend2) { + low = &bookend2; + high = &bookend1; + } + + size =(char*)high - (char*)low; + + + rc =WriteProcessMemory(hproc,low,low, (DWORD)size, &bytes); + + if (!rc) { + rc = GetLastError(); + return -1; + } + if (size != bytes) { + //dprintf("size %d , wrote %d\n",size,bytes); + } + return 0; +} +/* + * Inspired by Microsoft KB article ID: Q90493 + * + * returns 0 (false) if app is non-gui, 1 otherwise. +*/ +#include <winnt.h> +#include <ntport.h> + +__inline BOOL wait_for_io(HANDLE hi, OVERLAPPED *pO) { + + DWORD bytes = 0; + if(GetLastError() != ERROR_IO_PENDING) + { + return FALSE; + } + + return GetOverlappedResult(hi,pO,&bytes,TRUE); +} +#define CHECK_IO(h,o) if(!wait_for_io(h,o)) {goto done;} + +int is_gui(char *exename) { + + HANDLE hImage; + + DWORD bytes; + OVERLAPPED overlap; + + ULONG ntSignature; + + struct DosHeader{ + IMAGE_DOS_HEADER doshdr; + DWORD extra[16]; + }; + + struct DosHeader dh; + IMAGE_OPTIONAL_HEADER optionalhdr; + + int retCode = 0; + + memset(&overlap,0,sizeof(overlap)); + + + hImage = CreateFile(exename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, NULL); + if (INVALID_HANDLE_VALUE == hImage) { + return 0; + } + + ReadFile(hImage, &dh, sizeof(struct DosHeader), &bytes,&overlap); + CHECK_IO(hImage,&overlap); + + + if (IMAGE_DOS_SIGNATURE != dh.doshdr.e_magic) { + goto done; + } + + // read from the coffheaderoffset; + overlap.Offset = dh.doshdr.e_lfanew; + + ReadFile(hImage, &ntSignature, sizeof(ULONG), &bytes,&overlap); + CHECK_IO(hImage,&overlap); + + if (IMAGE_NT_SIGNATURE != ntSignature) { + goto done; + } + overlap.Offset = dh.doshdr.e_lfanew + sizeof(ULONG) + + sizeof(IMAGE_FILE_HEADER); + + ReadFile(hImage, &optionalhdr,IMAGE_SIZEOF_NT_OPTIONAL_HEADER, &bytes,&overlap); + CHECK_IO(hImage,&overlap); + + if (optionalhdr.Subsystem ==IMAGE_SUBSYSTEM_WINDOWS_GUI) + retCode = 1; +done: + CloseHandle(hImage); + return retCode; +} +int is_9x_gui(char *prog) { + + char *progpath; + DWORD dwret; + char *pathbuf; + char *pext; + + pathbuf=heap_alloc(MAX_PATH+1); + if(!pathbuf) + return 0; + + progpath=heap_alloc((MAX_PATH<<1)+1); + if(!progpath) + return 0; + + if (GetEnvironmentVariable("PATH",pathbuf,MAX_PATH) ==0) { + goto failed; + } + + pathbuf[MAX_PATH]=0; + + dwret = SearchPath(pathbuf,prog,".EXE",MAX_PATH<<1,progpath,&pext); + + if ( (dwret == 0) || (dwret > (MAX_PATH<<1) ) ) + goto failed; + + dprintf("progpath is %s\n",progpath); + dwret = is_gui(progpath); + + heap_free(pathbuf); + heap_free(progpath); + + return dwret; + +failed: + heap_free(pathbuf); + heap_free(progpath); + return 0; + + +} diff --git a/win32/io.c b/win32/io.c new file mode 100644 index 000000000000..0124f1b2a028 --- /dev/null +++ b/win32/io.c @@ -0,0 +1,479 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/io.c,v 1.9 2006/04/13 00:59:02 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * io.c + * wrapper functions for some i/o routines. + * -amol + * + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdio.h> +#include <fcntl.h> +#include <memory.h> +#include <errno.h> +#include "sh.h" +#include "ntport.h" +#include "signal.h" + + +#pragma warning(disable:4127) //conditional expr is constant + +#define CR 0x0d + + +extern void make_err_str(unsigned int ,char *,int ) ; +extern void generic_handler(int); +extern int console_write(HANDLE,unsigned char*,int); + +int consoleread(HANDLE , unsigned char * ,size_t ) ; + +INPUT_RECORD girec[2048]; + +unsigned short __nt_want_vcode=0,__nt_vcode=0; +HANDLE __h_con_alarm=0; +HANDLE __h_con_int=0; +HANDLE __h_con_hup=0; + +extern int NoNLSRebind; + +extern int OLDSTD, SHIN; +/* + * force_read: Forces a ReadFile, instead of ReadConsole + * + */ +int force_read(int fd, unsigned char * buf, size_t howmany) { + DWORD numread=0,err=0; + HANDLE hRead ; + + + hRead= (HANDLE)__nt_get_osfhandle(fd); + if (hRead == INVALID_HANDLE_VALUE) { + return 0; + } +again: + if (!ReadFile(hRead, buf,(DWORD)howmany,&numread, NULL ) ){ + err = GetLastError(); + switch(err) { + case ERROR_IO_PENDING: + break; + case ERROR_ACCESS_DENIED: + case ERROR_INVALID_HANDLE: + errno = EBADF; + return -1; + break; + case ERROR_HANDLE_EOF: + case ERROR_BROKEN_PIPE: + errno = 0; + return 0; + default: + errno = EBADF; + return 0; + } + } + if (numread == 1 && buf[0] == CR) + goto again; + return numread; +} +int nt_read(int fd, unsigned char * buf, size_t howmany) { + + DWORD numread=0,err=0; + HANDLE hRead ; + DWORD ftype; + // + + hRead= (HANDLE)__nt_get_osfhandle(fd); + if (hRead == INVALID_HANDLE_VALUE) { + return 0; + } + + ftype = GetFileType(hRead); + + + if ((ftype == FILE_TYPE_CHAR) /*&& (fd != OLDSTD) && (fd != SHIN)*/) + return consoleread(hRead,buf,howmany); +again: + if (!ReadFile(hRead, buf,(DWORD)howmany,&numread, NULL ) ){ + err = GetLastError(); + switch(err) { + case ERROR_IO_PENDING: + break; + case ERROR_ACCESS_DENIED: + case ERROR_INVALID_HANDLE: + errno = EBADF; + return -1; + break; + case ERROR_HANDLE_EOF: + case ERROR_BROKEN_PIPE: + errno = 0; + return 0; + default: + errno = EBADF; + return 0; + } + } + if (numread) { + if (buf[numread-1] == CR) + numread--; + if (numread == 0) + goto again; + } + return numread; +} + +/* color-ls patches from TAGA nayuta (nayuta@is.s.u-tokyo.ac.jp) */ +#ifdef COLOR_LS_F + +int nt_write_(int , const unsigned char * , size_t ); +int nt_write(int fd, const unsigned char * buf, size_t howmany) { + static unsigned char color_buf[256]; + static char len = 0; + + ssize_t i; + ssize_t start = 0; + int rc,wrote = 0; + + if (!isatty(fd) || (varval(STRcolor) == NULL)) + return nt_write_(fd, buf, howmany); + + for (i = 0; i < howmany; i++) { + switch (len) { + case 0: + if (buf[i] == '\x1b') { + color_buf[len++] = buf[i]; + if (0 < i - start){ + if ((rc=nt_write_(fd, &(buf[start]), i - start)) <0) + return -1; + else + wrote += rc; + } + start = -1; + } + break; + + case 1: + if (buf[i] != '[') + goto set_color; + color_buf[len++] = buf[i]; + break; + + default: + if (buf[i] == 'm' || (!isdigit(buf[i]) && buf[i] != ';')) + goto set_color; + color_buf[len++] = buf[i]; + break; + + case sizeof(color_buf) - 1: +set_color: + color_buf[len] = '\0'; + set_attributes(color_buf); + len = 0; + start = i + 1; + break; + } + } + + if (0 < i - start && 0 <= start) { + if ((rc=nt_write_(fd, &(buf[start]), i - start)) < 0) + return -1; + else + wrote += rc; + } + return wrote; +} +int nt_write_(int fd, const unsigned char * buf, size_t howmany) +#else /* if !COLOR_LS_F */ +int nt_write(int fd, const unsigned char * buf, size_t howmany) +#endif /* COLOR_LS_F */ +{ + int bytes_rtn,err; + HANDLE hout; + + + hout = (HANDLE)__nt_get_osfhandle(fd); + /* + if (isatty(fd)) + ;// return console_write(hout,buf,howmany); + */ + + if(!WriteFile(hout, buf,(DWORD)howmany,(ULONG*)&bytes_rtn, + NULL)){ + err = GetLastError(); + switch(err) { + case ERROR_ACCESS_DENIED: + case ERROR_INVALID_HANDLE: + errno = EBADF; + return -1; + break; + case ERROR_BROKEN_PIPE: + errno = EPIPE; + return -1; + default: + errno = EBADF; + return -1; + } + + } + return bytes_rtn?bytes_rtn:-1; + +} + +#define IS_CTRL_COMBO(a) ( (a) & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED) ) +#define IS_ALT_COMBO(a) ( /*(a) &*/ alt_pressed ) +#define IS_SHIFT_COMBO(a) ( (a) & SHIFT_PRESSED) + +int consoleread(HANDLE hInput, unsigned char * buf,size_t howmany) { + + INPUT_RECORD *irec = NULL; + DWORD numread,controlkey,i; + WORD vcode; + unsigned char ch; + int rc; + size_t where=0; + int alt_pressed = 0,memfree=0; + HANDLE hevents[4]; + static int pre_ch = -1; + + if (0 <= pre_ch) { + buf[0] = (unsigned char)pre_ch; + pre_ch = -1; + return 1; + } + + howmany /= 2; // [ALT + KEY] is expanded ESC KEY, so we need more buffer + if (howmany == 0) + howmany = 1; + + if (howmany > 2048){ + irec = heap_alloc(howmany*sizeof(INPUT_RECORD)); + memfree=1; + } + else + irec = &(girec[0]); + if (!irec){ + errno = ENOMEM; + return -1; + } + while(1) { + hevents[0] = __h_con_alarm; + hevents[1] = __h_con_int; + hevents[2] = __h_con_hup; + hevents[3] = hInput; + rc = WaitForMultipleObjects(sizeof(hevents)/sizeof(hevents[0]), + hevents,FALSE,INFINITE); + if (rc == WAIT_OBJECT_0) { + generic_handler(SIGALRM); + } + if (rc == (WAIT_OBJECT_0 +1) ) { + errno = EINTR; + generic_handler(SIGINT); + break; + } + if (rc == (WAIT_OBJECT_0 +2) ) { + errno = EINTR; + generic_handler(SIGHUP); + break; + } + rc = ReadConsoleInput(hInput,irec,(DWORD)howmany,&numread); + if (!rc) { + rc = GetLastError(); + switch (rc) { + case ERROR_INVALID_HANDLE: + case ERROR_ACCESS_DENIED: + errno = EBADF; + break; + } + if (memfree) + heap_free(irec); + return -1; + } + __nt_vcode=0; + for(i=0;i<numread;i++) { + switch(irec[i].EventType) { + case KEY_EVENT: + if (irec[i].Event.KeyEvent.bKeyDown) { + vcode=(irec[i].Event.KeyEvent.wVirtualKeyCode); + ch=(irec[i].Event.KeyEvent.uChar.AsciiChar); + controlkey=(irec[i].Event.KeyEvent.dwControlKeyState); + if (controlkey & LEFT_ALT_PRESSED) + alt_pressed=1; + else if (controlkey & RIGHT_ALT_PRESSED){ + if (NoNLSRebind) + alt_pressed=1; + } + + if (__nt_want_vcode != 1) + goto skippy; + + if (vcode >= VK_F1 && vcode <= VK_F24) { + + __nt_vcode=NT_SPECIFIC_BINDING_OFFSET ; + __nt_vcode += (vcode- VK_F1) + SINGLE_KEY_OFFSET; + + if (IS_CTRL_COMBO(controlkey)) + __nt_vcode += CTRL_KEY_OFFSET; + + else if (IS_ALT_COMBO(controlkey)) + __nt_vcode += ALT_KEY_OFFSET; + else if (IS_SHIFT_COMBO(controlkey)) + __nt_vcode += SHIFT_KEY_OFFSET; + + __nt_want_vcode=2; + + return 1; + } + else if (vcode>= VK_PRIOR && vcode <= VK_DOWN) { + + __nt_vcode = NT_SPECIFIC_BINDING_OFFSET ; + __nt_vcode += KEYPAD_MAPPING_BEGIN; + __nt_vcode += (vcode -VK_PRIOR); + + __nt_vcode += SINGLE_KEY_OFFSET ; + + if (IS_CTRL_COMBO(controlkey)) + __nt_vcode += CTRL_KEY_OFFSET; + + else if (IS_ALT_COMBO(controlkey)) + __nt_vcode += ALT_KEY_OFFSET; + else if (IS_SHIFT_COMBO(controlkey)) + __nt_vcode += SHIFT_KEY_OFFSET; + + __nt_want_vcode=2; + return 1; + } + else if (vcode == VK_INSERT) { + __nt_vcode = NT_SPECIFIC_BINDING_OFFSET ; + __nt_vcode += INS_DEL_MAPPING_BEGIN; + + if (IS_CTRL_COMBO(controlkey)) + __nt_vcode += CTRL_KEY_OFFSET; + + else if (IS_ALT_COMBO(controlkey)) + __nt_vcode += ALT_KEY_OFFSET; + + else if (IS_SHIFT_COMBO(controlkey)) + __nt_vcode += SHIFT_KEY_OFFSET; + + __nt_want_vcode=2; + return 1; + } + else if (vcode == VK_DELETE) { + __nt_vcode = NT_SPECIFIC_BINDING_OFFSET ; + __nt_vcode += INS_DEL_MAPPING_BEGIN + 1; + + if (IS_CTRL_COMBO(controlkey)) + __nt_vcode += CTRL_KEY_OFFSET; + + else if (IS_ALT_COMBO(controlkey)) + __nt_vcode += ALT_KEY_OFFSET; + + else if (IS_SHIFT_COMBO(controlkey)) + __nt_vcode += SHIFT_KEY_OFFSET; + + __nt_want_vcode=2; + + return 1; + } +skippy: + switch(vcode) { + case VK_ESCAPE: + buf[where++]='\033'; + break; + default: + if(ch ){ + /* + * Looks like win95 has a spurious + * newline left over + */ + if (gdwPlatform == + VER_PLATFORM_WIN32_WINDOWS && + ch == '\r'){ + DWORD bread; + (void)ReadFile(hInput,&ch,1,&bread,NULL); + } + /* patch from TAGA nayuta */ + if ( NoNLSRebind && + (ch == ' ' || ch == '@') && + IS_CTRL_COMBO(controlkey) + /*(controlkey & LEFT_CTRL_PRESSED || + controlkey & RIGHT_CTRL_PRESSED)*/ + ) + ch = 0; + if (alt_pressed) { +#ifdef DSPMBYTE + buf[where++] = '\033'; + if (howmany == 1) + pre_ch = ch; + else + buf[where++] = ch; +#else /* !DSPMBYTE */ + buf[where++] = ch | 0200; +#endif /* !DSPMBYTE */ + } + else + buf[where++] = ch; + } + break; + } + + alt_pressed=0; + } + break; + default: + break; + } + } + if (where == 0) + continue; + if (howmany < where) // avoid trashing memory. -amol 4/16/97 + buf[where]=0; + break; + } + if (memfree) + heap_free(irec); + if (!where) + return -1; + return (int)(where ); +} +int console_write(HANDLE hout, unsigned char * buf,int howmany) { + int bytes,rc; + + bytes = -1; + + rc = WriteConsole(hout,buf,howmany,(DWORD*)&bytes,NULL); + if (!rc) { + errno = EBADF; + bytes = -1; + rc = GetLastError(); + } + + return bytes; +} diff --git a/win32/msg/Makefile b/win32/msg/Makefile new file mode 100644 index 000000000000..bfe1e3541a11 --- /dev/null +++ b/win32/msg/Makefile @@ -0,0 +1,49 @@ +!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
+MACHINE = ix86
+!else if "$(PROCESSOR_ARCHITECTURE)" == "ALPHA"
+MACHINE = alpha
+!else #Assume win9x
+MACHINE = ix86
+!endif
+LIBS= libcmt.lib kernel32.lib
+
+all: tcshfr.dll tcshc.dll tcshde.dll tcshsp.dll tcshja.dll tcsh-it.dll
+
+stubdll.obj:stubdll.c
+ cl -W3 -MT -c stubdll.c
+
+tcshgr.dll: tcshgr.res stubdll.obj
+ link -machine:$(MACHINE) -nodefaultlib $(LIBS) tcshgr.res stubdll.obj \
+ -out:tcshgr.dll
+
+tcshfr.dll: tcshfr.res stubdll.obj
+ link -machine:$(MACHINE) -dll -nodefaultlib $(LIBS) tcshfr.res stubdll.obj \
+ -out:tcshfr.dll
+
+tcshde.dll: tcshde.res stubdll.obj
+ link -machine:$(MACHINE) -dll -nodefaultlib $(LIBS) tcshde.res stubdll.obj \
+ -out:tcshde.dll
+
+tcshsp.dll: tcshsp.res stubdll.obj
+ link -machine:$(MACHINE) -dll -nodefaultlib $(LIBS) tcshsp.res stubdll.obj \
+ -out:tcshsp.dll
+
+tcsh-it.dll: tcsh-it.res stubdll.obj
+ link -machine:$(MACHINE) -dll -nodefaultlib $(LIBS) tcsh-it.res stubdll.obj\
+ -out:tcsh-it.dll
+
+tcshja.dll: tcshja.res stubdll.obj
+ link -machine:$(MACHINE) -dll -nodefaultlib $(LIBS) tcshja.res stubdll.obj \
+ -out:tcshja.dll
+
+tcshc.dll: tcshc.res stubdll.obj
+ link -machine:$(MACHINE) -dll -nodefaultlib $(LIBS) tcshc.res stubdll.obj \
+ -out:tcshc.dll
+
+test.exe: test.obj
+ link test.obj user32.lib -out:test.exe
+clean:
+ -del *.obj *.res
+
+cleanall: clean
+ -del *.dll *.exe
diff --git a/win32/msg/makerc.pl b/win32/msg/makerc.pl new file mode 100644 index 000000000000..39805f7c3914 --- /dev/null +++ b/win32/msg/makerc.pl @@ -0,0 +1,43 @@ +# This script converts a tcsh nls file into a format suitable for compiling
+# with RC and stubdll.c. This gives us a stringtable resource in the DLL
+# which can be loaded at startup for tcsh messages.
+#
+# Depending on the languages, the final output may take some tweaking. I have
+# not been able to get Greek to compile in the resource compiler. French,
+# German, and the C locale seem to work.
+#
+# This prints to stdout, so redirect to appropriate place.
+#
+# The alogrithm is simple :
+#
+# String ID = set number * 10,000 + message number
+#
+# This is because we cannot have two messages with the same id.
+#
+# -amol 9/15/96
+#
+#
+print "#include <windows.h>\n";
+print "STRINGTABLE DISCARDABLE\n";
+print "BEGIN\n";
+
+for($i=1; $i <32;$i++) {
+ $filename = "set" . $i;
+
+ open(CURRSET,$filename);
+
+ while(<CURRSET>) {
+ chop $_;
+ if (/^\$/) {
+ print "//" . $_ . "\n";
+ }
+ else {
+# comment following for greek ???
+ s/\"/\"\"/g;
+ ($num,$line)= split(' ',$_,2);
+ print ($i*10000 + $num);
+ print " \"" . $line . "\"\n";
+ }
+ }
+}
+print "END\n"
diff --git a/win32/msg/makercjp.pl b/win32/msg/makercjp.pl new file mode 100644 index 000000000000..39694a850a4f --- /dev/null +++ b/win32/msg/makercjp.pl @@ -0,0 +1,31 @@ +# This script is almost as same as makerc.pl except that the coding of
+# nls files is converted from euc_japan to shift_jis by nkf.exe
+#
+# this is for japanese nls files
+#
+# 1998/09/23 - nayuta
+
+print "#include <windows.h>\n";
+print "STRINGTABLE DISCARDABLE\n";
+print "BEGIN\n";
+
+for($i=1; $i <32;$i++) {
+ $filename = "set" . $i;
+
+ open(CURRSET,"nkf -E -s $filename |");
+
+ while(<CURRSET>) {
+ chop $_;
+ if (/^\$/) {
+ print "//" . $_ . "\n";
+ }
+ else {
+# comment following for greek ???
+ s/\"/\"\"/g;
+ ($num,$line)= split(' ',$_,2);
+ print ($i*10000 + $num);
+ print " \"" . $line . "\"\n";
+ }
+ }
+}
+print "END\n"
diff --git a/win32/msg/makercrc.pl b/win32/msg/makercrc.pl new file mode 100644 index 000000000000..d75dea79ee5c --- /dev/null +++ b/win32/msg/makercrc.pl @@ -0,0 +1,35 @@ +# This script converts a .tcshrc file into a format suitable for compiling
+# with RC and stubdll.c. This gives us a stringtable resource in the DLL
+# which can be loaded with the loadresource builtin
+#
+# This prints to stdout, so redirect to appropriate place.
+#
+# The alogrithm is simple :
+#
+# String ID = 666 + line number
+#
+# -amol 3/28/01
+#
+#
+print "#include <windows.h>\n";
+print "STRINGTABLE DISCARDABLE\n";
+print "BEGIN\n";
+
+$filename = $ARGV[0];
+
+open(RCFILE,$filename);
+
+$i = 666;
+while(<RCFILE>) {
+ chop $_;
+ next if (/^#/) ;
+ next if (/^$/);
+
+ s/\"/\"\"/g;
+# print $_;
+
+ print ($i);
+ print " \"" . $_ . "\"\n";
+ $i++;
+}
+print "END\n"
diff --git a/win32/msg/stubdll.c b/win32/msg/stubdll.c new file mode 100644 index 000000000000..aadadb79237d --- /dev/null +++ b/win32/msg/stubdll.c @@ -0,0 +1,7 @@ +#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+BOOL WINAPI DllEntryPoint(HINSTANCE hdll,DWORD dwreason,LPVOID ignore) {
+
+ return 1;
+}
diff --git a/win32/msg/test.c b/win32/msg/test.c new file mode 100644 index 000000000000..d47d5933812b --- /dev/null +++ b/win32/msg/test.c @@ -0,0 +1,33 @@ +#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+#include <locale.h>
+
+void main(int argc, char **argv) {
+
+ HINSTANCE hinst;
+ WCHAR buffer[128];
+ unsigned char winbuf[128],oembuf[128];
+ unsigned int number;
+
+ if (argc <3)
+ return;
+
+ hinst = LoadLibrary(argv[1]);
+
+ number = atoi(argv[2]);
+ printf("Load String returns %i\n",
+ LoadStringW(hinst, number, buffer, sizeof(buffer)));
+
+ WideCharToMultiByte(CP_OEMCP,
+ 0,
+ buffer,
+ -1,
+ winbuf,
+ 128,
+ NULL,
+ NULL);
+
+ CharToOem(winbuf,oembuf);
+ printf("oem: %s\n",oembuf);
+}
diff --git a/win32/nt.bind.c b/win32/nt.bind.c new file mode 100644 index 000000000000..17e5a75910ca --- /dev/null +++ b/win32/nt.bind.c @@ -0,0 +1,1351 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/nt.bind.c,v 1.6 2006/03/05 08:59:36 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "sh.h" +#include "ed.h" +#include "ed.defns.h" + + +KEYCMD CcEmacsMap[] = { + /* keymap table, each index into above tbl; should be + (256+extra NT bindings)*sizeof(KEYCMD) bytes long */ + + F_SET_MARK, /* ^@ */ + F_TOBEG, /* ^A */ + F_CHARBACK, /* ^B */ + F_TTY_INT, /* ^C */ + F_DELNEXT_LIST_EOF, /* ^D */ + F_TOEND, /* ^E */ + F_CHARFWD, /* ^F */ + F_UNASSIGNED, /* ^G */ + F_DELPREV, /* ^H */ + F_COMPLETE, /* ^I */ + F_NEWLINE, /* ^J */ + F_KILLEND, /* ^K */ + F_CLEARDISP, /* ^L */ + F_NEWLINE, /* ^M */ + F_DOWN_HIST, /* ^N */ + F_TTY_FLUSHO, /* ^O */ + F_UP_HIST, /* ^P */ + F_TTY_STARTO, /* ^Q */ + F_REDISP, /* ^R */ + F_TTY_STOPO, /* ^S */ + F_CHARSWITCH, /* ^T */ + F_KILLALL, /* ^U */ + F_QUOTE, /* ^V */ + F_KILLREGION, /* ^W */ + F_XKEY, /* ^X */ + F_YANK_KILL, /* ^Y */ + F_TTY_TSUSP, /* ^Z */ + F_METANEXT, /* ^[ */ + F_TTY_QUIT, /* ^\ */ + F_TTY_DSUSP, /* ^] */ + F_UNASSIGNED, /* ^^ */ + F_UNASSIGNED, /* ^_ */ + F_INSERT, /* SPACE */ + F_INSERT, /* ! */ + F_INSERT, /* " */ + F_INSERT, /* # */ + F_INSERT, /* $ */ + F_INSERT, /* % */ + F_INSERT, /* & */ + F_INSERT, /* ' */ + F_INSERT, /* ( */ + F_INSERT, /* ) */ + F_INSERT, /* * */ + F_INSERT, /* + */ + F_INSERT, /* , */ + F_INSERT, /* - */ + F_INSERT, /* . */ + F_INSERT, /* / */ + F_DIGIT, /* 0 */ + F_DIGIT, /* 1 */ + F_DIGIT, /* 2 */ + F_DIGIT, /* 3 */ + F_DIGIT, /* 4 */ + F_DIGIT, /* 5 */ + F_DIGIT, /* 6 */ + F_DIGIT, /* 7 */ + F_DIGIT, /* 8 */ + F_DIGIT, /* 9 */ + F_INSERT, /* : */ + F_INSERT, /* ; */ + F_INSERT, /* < */ + F_INSERT, /* = */ + F_INSERT, /* > */ + F_INSERT, /* ? */ + F_INSERT, /* @ */ + F_INSERT, /* A */ + F_INSERT, /* B */ + F_INSERT, /* C */ + F_INSERT, /* D */ + F_INSERT, /* E */ + F_INSERT, /* F */ + F_INSERT, /* G */ + F_INSERT, /* H */ + F_INSERT, /* I */ + F_INSERT, /* J */ + F_INSERT, /* K */ + F_INSERT, /* L */ + F_INSERT, /* M */ + F_INSERT, /* N */ + F_INSERT, /* O */ + F_INSERT, /* P */ + F_INSERT, /* Q */ + F_INSERT, /* R */ + F_INSERT, /* S */ + F_INSERT, /* T */ + F_INSERT, /* U */ + F_INSERT, /* V */ + F_INSERT, /* W */ + F_INSERT, /* X */ + F_INSERT, /* Y */ + F_INSERT, /* Z */ + F_INSERT, /* [ */ + F_INSERT, /* \ */ + F_INSERT, /* ] */ + F_INSERT, /* ^ */ + F_INSERT, /* _ */ + F_INSERT, /* ` */ + F_INSERT, /* a */ + F_INSERT, /* b */ + F_INSERT, /* c */ + F_INSERT, /* d */ + F_INSERT, /* e */ + F_INSERT, /* f */ + F_INSERT, /* g */ + F_INSERT, /* h */ + F_INSERT, /* i */ + F_INSERT, /* j */ + F_INSERT, /* k */ + F_INSERT, /* l */ + F_INSERT, /* m */ + F_INSERT, /* n */ + F_INSERT, /* o */ + F_INSERT, /* p */ + F_INSERT, /* q */ + F_INSERT, /* r */ + F_INSERT, /* s */ + F_INSERT, /* t */ + F_INSERT, /* u */ + F_INSERT, /* v */ + F_INSERT, /* w */ + F_INSERT, /* x */ + F_INSERT, /* y */ + F_INSERT, /* z */ + F_INSERT, /* { */ + F_INSERT, /* | */ + F_INSERT, /* } */ + F_INSERT, /* ~ */ + F_DELPREV, /* ^? */ + F_UNASSIGNED, /* M-^@ */ + F_UNASSIGNED, /* M-^A */ + F_UNASSIGNED, /* M-^B */ + F_UNASSIGNED, /* M-^C */ + F_LIST_CHOICES, /* M-^D */ + F_UNASSIGNED, /* M-^E */ + F_UNASSIGNED, /* M-^F */ + F_UNASSIGNED, /* M-^G */ + F_DELWORDPREV, /* M-^H */ + F_COMPLETE, /* M-^I */ + F_UNASSIGNED, /* M-^J */ + F_UNASSIGNED, /* M-^K */ + F_CLEARDISP, /* M-^L */ + F_UNASSIGNED, /* M-^M */ + F_UNASSIGNED, /* M-^N */ + F_UNASSIGNED, /* M-^O */ + F_UNASSIGNED, /* M-^P */ + F_UNASSIGNED, /* M-^Q */ + F_UNASSIGNED, /* M-^R */ + F_UNASSIGNED, /* M-^S */ + F_UNASSIGNED, /* M-^T */ + F_UNASSIGNED, /* M-^U */ + F_UNASSIGNED, /* M-^V */ + F_UNASSIGNED, /* M-^W */ + F_UNASSIGNED, /* M-^X */ + F_UNASSIGNED, /* M-^Y */ + F_RUN_FG_EDITOR, /* M-^Z */ + F_COMPLETE, /* M-^[ */ + F_UNASSIGNED, /* M-^\ */ + F_UNASSIGNED, /* M-^] */ + F_UNASSIGNED, /* M-^^ */ + F_COPYPREV, /* M-^_ */ + F_EXPAND_HISTORY, /* M-SPACE */ + F_EXPAND_HISTORY, /* M-! */ + F_UNASSIGNED, /* M-" */ + F_UNASSIGNED, /* M-# */ + F_CORRECT_L, /* M-$ */ + F_UNASSIGNED, /* M-% */ + F_UNASSIGNED, /* M-& */ + F_UNASSIGNED, /* M-' */ + F_UNASSIGNED, /* M-( */ + F_UNASSIGNED, /* M-) */ + F_UNASSIGNED, /* M-* */ + F_UNASSIGNED, /* M-+ */ + F_UNASSIGNED, /* M-, */ + F_UNASSIGNED, /* M-- */ + F_UNASSIGNED, /* M-. */ + F_DABBREV_EXPAND, /* M-/ */ + F_ARGDIGIT, /* M-0 */ + F_ARGDIGIT, /* M-1 */ + F_ARGDIGIT, /* M-2 */ + F_ARGDIGIT, /* M-3 */ + F_ARGDIGIT, /* M-4 */ + F_ARGDIGIT, /* M-5 */ + F_ARGDIGIT, /* M-6 */ + F_ARGDIGIT, /* M-7 */ + F_ARGDIGIT, /* M-8 */ + F_ARGDIGIT, /* M-9 */ + F_UNASSIGNED, /* M-: */ + F_UNASSIGNED, /* M-; */ + F_UNASSIGNED, /* M-< */ + F_UNASSIGNED, /* M-= */ + F_UNASSIGNED, /* M-> */ + F_WHICH, /* M-? */ + F_UNASSIGNED, /* M-@ */ + F_UNASSIGNED, /* M-A */ + F_WORDBACK, /* M-B */ + F_CASECAPITAL, /* M-C */ + F_DELWORDNEXT, /* M-D */ + F_UNASSIGNED, /* M-E */ + F_WORDFWD, /* M-F */ + F_UNASSIGNED, /* M-G */ + F_HELPME, /* M-H */ + F_UNASSIGNED, /* M-I */ + F_UNASSIGNED, /* M-J */ + F_UNASSIGNED, /* M-K */ + F_CASELOWER, /* M-L */ + F_UNASSIGNED, /* M-M */ + F_DOWN_SEARCH_HIST, /* M-N */ + F_XKEY, /* M-O *//* extended key esc PWP Mar 88 */ + F_UP_SEARCH_HIST, /* M-P */ + F_UNASSIGNED, /* M-Q */ + F_TOGGLE_HIST, /* M-R */ + F_CORRECT, /* M-S */ + F_UNASSIGNED, /* M-T */ + F_CASEUPPER, /* M-U */ + F_UNASSIGNED, /* M-V */ + F_COPYREGION, /* M-W */ + F_UNASSIGNED, /* M-X */ + F_UNASSIGNED, /* M-Y */ + F_UNASSIGNED, /* M-Z */ + F_XKEY, /* M-[ *//* extended key esc -mf Oct 87 */ + F_UNASSIGNED, /* M-\ */ + F_UNASSIGNED, /* M-] */ + F_UNASSIGNED, /* M-^ */ + F_LAST_ITEM, /* M-_ */ + F_UNASSIGNED, /* M-` */ + F_UNASSIGNED, /* M-a */ + F_WORDBACK, /* M-b */ + F_CASECAPITAL, /* M-c */ + F_DELWORDNEXT, /* M-d */ + F_UNASSIGNED, /* M-e */ + F_WORDFWD, /* M-f */ + F_UNASSIGNED, /* M-g */ + F_HELPME, /* M-h */ + F_UNASSIGNED, /* M-i */ + F_UNASSIGNED, /* M-j */ + F_UNASSIGNED, /* M-k */ + F_CASELOWER, /* M-l */ + F_UNASSIGNED, /* M-m */ + F_DOWN_SEARCH_HIST, /* M-n */ + F_UNASSIGNED, /* M-o */ + F_UP_SEARCH_HIST, /* M-p */ + F_UNASSIGNED, /* M-q */ + F_TOGGLE_HIST, /* M-r */ + F_CORRECT, /* M-s */ + F_UNASSIGNED, /* M-t */ + F_CASEUPPER, /* M-u */ + F_UNASSIGNED, /* M-v */ + F_COPYREGION, /* M-w */ + F_UNASSIGNED, /* M-x */ + F_UNASSIGNED, /* M-y */ + F_UNASSIGNED, /* M-z */ + F_UNASSIGNED, /* M-{ */ + F_UNASSIGNED, /* M-| */ + F_UNASSIGNED, /* M-} */ + F_UNASSIGNED, /* M-~ */ + F_DELWORDPREV, /* M-^? */ + /* Extra keys begin here */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + /* ctrl key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + + /* alt key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + /* shift key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED /* DEL */ +}; + +/* + * keymap table for vi. Each index into above tbl; should be + * 256 entries long. Vi mode uses a sticky-extend to do command mode: + * insert mode characters are in the normal keymap, and command mode + * in the extended keymap. + */ +KEYCMD CcViMap[] = { +#ifdef KSHVI + F_UNASSIGNED, /* ^@ */ + F_INSERT, /* ^A */ + F_INSERT, /* ^B */ + F_INSERT, /* ^C */ + F_INSERT, /* ^D */ + F_INSERT, /* ^E */ + F_INSERT, /* ^F */ + F_INSERT, /* ^G */ + V_DELPREV, /* ^H */ /* BackSpace key */ + F_COMPLETE, /* ^I */ /* Tab Key */ + F_NEWLINE, /* ^J */ + F_INSERT, /* ^K */ + F_INSERT, /* ^L */ + F_NEWLINE, /* ^M */ + F_INSERT, /* ^N */ + F_INSERT, /* ^O */ + F_INSERT, /* ^P */ + F_TTY_STARTO, /* ^Q */ + F_INSERT, /* ^R */ + F_INSERT, /* ^S */ + F_INSERT, /* ^T */ + F_INSERT, /* ^U */ + F_QUOTE, /* ^V */ + F_DELWORDPREV, /* ^W */ /* Only until start edit pos */ + F_INSERT, /* ^X */ + F_INSERT, /* ^Y */ + F_INSERT, /* ^Z */ + V_CMD_MODE, /* ^[ */ /* [ Esc ] key */ + F_TTY_QUIT, /* ^\ */ + F_INSERT, /* ^] */ + F_INSERT, /* ^^ */ + F_INSERT, /* ^_ */ +#else /* !KSHVI */ + F_UNASSIGNED, /* ^@ */ /* NOTE: These mapping do NOT */ + F_TOBEG, /* ^A */ /* Correspond well to the KSH */ + F_CHARBACK, /* ^B */ /* VI editting assignments */ + F_TTY_INT, /* ^C */ /* On the other hand they are */ + F_LIST_EOF, /* ^D */ /* convenient any many people */ + F_TOEND, /* ^E */ /* have gotten used to them */ + F_CHARFWD, /* ^F */ + F_LIST_GLOB, /* ^G */ + F_DELPREV, /* ^H */ /* BackSpace key */ + F_COMPLETE, /* ^I */ /* Tab Key */ + F_NEWLINE, /* ^J */ + F_KILLEND, /* ^K */ + F_CLEARDISP, /* ^L */ + F_NEWLINE, /* ^M */ + F_DOWN_HIST, /* ^N */ + F_TTY_FLUSHO, /* ^O */ + F_UP_HIST, /* ^P */ + F_TTY_STARTO, /* ^Q */ + F_REDISP, /* ^R */ + F_TTY_STOPO, /* ^S */ + F_CHARSWITCH, /* ^T */ + F_KILLBEG, /* ^U */ + F_QUOTE, /* ^V */ + F_DELWORDPREV, /* ^W */ + F_EXPAND, /* ^X */ + F_TTY_DSUSP, /* ^Y */ + F_TTY_TSUSP, /* ^Z */ + V_CMD_MODE, /* ^[ */ + F_TTY_QUIT, /* ^\ */ + F_UNASSIGNED, /* ^] */ + F_UNASSIGNED, /* ^^ */ + F_UNASSIGNED, /* ^_ */ +#endif /* KSHVI */ + F_INSERT, /* SPACE */ + F_INSERT, /* ! */ + F_INSERT, /* " */ + F_INSERT, /* # */ + F_INSERT, /* $ */ + F_INSERT, /* % */ + F_INSERT, /* & */ + F_INSERT, /* ' */ + F_INSERT, /* ( */ + F_INSERT, /* ) */ + F_INSERT, /* * */ + F_INSERT, /* + */ + F_INSERT, /* , */ + F_INSERT, /* - */ + F_INSERT, /* . */ + F_INSERT, /* / */ + F_INSERT, /* 0 */ + F_INSERT, /* 1 */ + F_INSERT, /* 2 */ + F_INSERT, /* 3 */ + F_INSERT, /* 4 */ + F_INSERT, /* 5 */ + F_INSERT, /* 6 */ + F_INSERT, /* 7 */ + F_INSERT, /* 8 */ + F_INSERT, /* 9 */ + F_INSERT, /* : */ + F_INSERT, /* ; */ + F_INSERT, /* < */ + F_INSERT, /* = */ + F_INSERT, /* > */ + F_INSERT, /* ? */ + F_INSERT, /* @ */ + F_INSERT, /* A */ + F_INSERT, /* B */ + F_INSERT, /* C */ + F_INSERT, /* D */ + F_INSERT, /* E */ + F_INSERT, /* F */ + F_INSERT, /* G */ + F_INSERT, /* H */ + F_INSERT, /* I */ + F_INSERT, /* J */ + F_INSERT, /* K */ + F_INSERT, /* L */ + F_INSERT, /* M */ + F_INSERT, /* N */ + F_INSERT, /* O */ + F_INSERT, /* P */ + F_INSERT, /* Q */ + F_INSERT, /* R */ + F_INSERT, /* S */ + F_INSERT, /* T */ + F_INSERT, /* U */ + F_INSERT, /* V */ + F_INSERT, /* W */ + F_INSERT, /* X */ + F_INSERT, /* Y */ + F_INSERT, /* Z */ + F_INSERT, /* [ */ + F_INSERT, /* \ */ + F_INSERT, /* ] */ + F_INSERT, /* ^ */ + F_INSERT, /* _ */ + F_INSERT, /* ` */ + F_INSERT, /* a */ + F_INSERT, /* b */ + F_INSERT, /* c */ + F_INSERT, /* d */ + F_INSERT, /* e */ + F_INSERT, /* f */ + F_INSERT, /* g */ + F_INSERT, /* h */ + F_INSERT, /* i */ + F_INSERT, /* j */ + F_INSERT, /* k */ + F_INSERT, /* l */ + F_INSERT, /* m */ + F_INSERT, /* n */ + F_INSERT, /* o */ + F_INSERT, /* p */ + F_INSERT, /* q */ + F_INSERT, /* r */ + F_INSERT, /* s */ + F_INSERT, /* t */ + F_INSERT, /* u */ + F_INSERT, /* v */ + F_INSERT, /* w */ + F_INSERT, /* x */ + F_INSERT, /* y */ + F_INSERT, /* z */ + F_INSERT, /* { */ + F_INSERT, /* | */ + F_INSERT, /* } */ + F_INSERT, /* ~ */ + F_DELPREV, /* ^? */ + F_UNASSIGNED, /* M-^@ */ + F_UNASSIGNED, /* M-^A */ + F_UNASSIGNED, /* M-^B */ + F_UNASSIGNED, /* M-^C */ + F_UNASSIGNED, /* M-^D */ + F_UNASSIGNED, /* M-^E */ + F_UNASSIGNED, /* M-^F */ + F_UNASSIGNED, /* M-^G */ + F_UNASSIGNED, /* M-^H */ + F_UNASSIGNED, /* M-^I */ + F_UNASSIGNED, /* M-^J */ + F_UNASSIGNED, /* M-^K */ + F_UNASSIGNED, /* M-^L */ + F_UNASSIGNED, /* M-^M */ + F_UNASSIGNED, /* M-^N */ + F_UNASSIGNED, /* M-^O */ + F_UNASSIGNED, /* M-^P */ + F_UNASSIGNED, /* M-^Q */ + F_UNASSIGNED, /* M-^R */ + F_UNASSIGNED, /* M-^S */ + F_UNASSIGNED, /* M-^T */ + F_UNASSIGNED, /* M-^U */ + F_UNASSIGNED, /* M-^V */ + F_UNASSIGNED, /* M-^W */ + F_UNASSIGNED, /* M-^X */ + F_UNASSIGNED, /* M-^Y */ + F_UNASSIGNED, /* M-^Z */ + F_UNASSIGNED, /* M-^[ */ + F_UNASSIGNED, /* M-^\ */ + F_UNASSIGNED, /* M-^] */ + F_UNASSIGNED, /* M-^^ */ + F_UNASSIGNED, /* M-^_ */ + F_UNASSIGNED, /* M-SPACE */ + F_UNASSIGNED, /* M-! */ + F_UNASSIGNED, /* M-" */ + F_UNASSIGNED, /* M-# */ + F_UNASSIGNED, /* M-$ */ + F_UNASSIGNED, /* M-% */ + F_UNASSIGNED, /* M-& */ + F_UNASSIGNED, /* M-' */ + F_UNASSIGNED, /* M-( */ + F_UNASSIGNED, /* M-) */ + F_UNASSIGNED, /* M-* */ + F_UNASSIGNED, /* M-+ */ + F_UNASSIGNED, /* M-, */ + F_UNASSIGNED, /* M-- */ + F_UNASSIGNED, /* M-. */ + F_UNASSIGNED, /* M-/ */ + F_UNASSIGNED, /* M-0 */ + F_UNASSIGNED, /* M-1 */ + F_UNASSIGNED, /* M-2 */ + F_UNASSIGNED, /* M-3 */ + F_UNASSIGNED, /* M-4 */ + F_UNASSIGNED, /* M-5 */ + F_UNASSIGNED, /* M-6 */ + F_UNASSIGNED, /* M-7 */ + F_UNASSIGNED, /* M-8 */ + F_UNASSIGNED, /* M-9 */ + F_UNASSIGNED, /* M-: */ + F_UNASSIGNED, /* M-; */ + F_UNASSIGNED, /* M-< */ + F_UNASSIGNED, /* M-= */ + F_UNASSIGNED, /* M-> */ + F_UNASSIGNED, /* M-? */ + F_UNASSIGNED, /* M-@ */ + F_UNASSIGNED, /* M-A */ + F_UNASSIGNED, /* M-B */ + F_UNASSIGNED, /* M-C */ + F_UNASSIGNED, /* M-D */ + F_UNASSIGNED, /* M-E */ + F_UNASSIGNED, /* M-F */ + F_UNASSIGNED, /* M-G */ + F_UNASSIGNED, /* M-H */ + F_UNASSIGNED, /* M-I */ + F_UNASSIGNED, /* M-J */ + F_UNASSIGNED, /* M-K */ + F_UNASSIGNED, /* M-L */ + F_UNASSIGNED, /* M-M */ + F_UNASSIGNED, /* M-N */ + F_UNASSIGNED, /* M-O */ + F_UNASSIGNED, /* M-P */ + F_UNASSIGNED, /* M-Q */ + F_UNASSIGNED, /* M-R */ + F_UNASSIGNED, /* M-S */ + F_UNASSIGNED, /* M-T */ + F_UNASSIGNED, /* M-U */ + F_UNASSIGNED, /* M-V */ + F_UNASSIGNED, /* M-W */ + F_UNASSIGNED, /* M-X */ + F_UNASSIGNED, /* M-Y */ + F_UNASSIGNED, /* M-Z */ + F_UNASSIGNED, /* M-[ */ + F_UNASSIGNED, /* M-\ */ + F_UNASSIGNED, /* M-] */ + F_UNASSIGNED, /* M-^ */ + F_UNASSIGNED, /* M-_ */ + F_UNASSIGNED, /* M-` */ + F_UNASSIGNED, /* M-a */ + F_UNASSIGNED, /* M-b */ + F_UNASSIGNED, /* M-c */ + F_UNASSIGNED, /* M-d */ + F_UNASSIGNED, /* M-e */ + F_UNASSIGNED, /* M-f */ + F_UNASSIGNED, /* M-g */ + F_UNASSIGNED, /* M-h */ + F_UNASSIGNED, /* M-i */ + F_UNASSIGNED, /* M-j */ + F_UNASSIGNED, /* M-k */ + F_UNASSIGNED, /* M-l */ + F_UNASSIGNED, /* M-m */ + F_UNASSIGNED, /* M-n */ + F_UNASSIGNED, /* M-o */ + F_UNASSIGNED, /* M-p */ + F_UNASSIGNED, /* M-q */ + F_UNASSIGNED, /* M-r */ + F_UNASSIGNED, /* M-s */ + F_UNASSIGNED, /* M-t */ + F_UNASSIGNED, /* M-u */ + F_UNASSIGNED, /* M-v */ + F_UNASSIGNED, /* M-w */ + F_UNASSIGNED, /* M-x */ + F_UNASSIGNED, /* M-y */ + F_UNASSIGNED, /* M-z */ + F_UNASSIGNED, /* M-{ */ + F_UNASSIGNED, /* M-| */ + F_UNASSIGNED, /* M-} */ + F_UNASSIGNED, /* M-~ */ + F_UNASSIGNED, /* M-^? */ + /* Extra keys begin here */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + /* ctrl key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + + /* alt key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + /* shift key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED /* DEL */ +}; + +KEYCMD CcViCmdMap[] = { + F_UNASSIGNED, /* ^@ */ + F_TOBEG, /* ^A */ + F_UNASSIGNED, /* ^B */ + F_TTY_INT, /* ^C */ + F_LIST_CHOICES, /* ^D */ + F_TOEND, /* ^E */ + F_UNASSIGNED, /* ^F */ + F_LIST_GLOB, /* ^G */ + F_CHARBACK, /* ^H */ + V_CM_COMPLETE, /* ^I */ + F_NEWLINE, /* ^J */ + F_KILLEND, /* ^K */ + F_CLEARDISP, /* ^L */ + F_NEWLINE, /* ^M */ + F_DOWN_HIST, /* ^N */ + F_TTY_FLUSHO, /* ^O */ + F_UP_HIST, /* ^P */ + F_TTY_STARTO, /* ^Q */ + F_REDISP, /* ^R */ + F_TTY_STOPO, /* ^S */ + F_UNASSIGNED, /* ^T */ + F_KILLBEG, /* ^U */ + F_UNASSIGNED, /* ^V */ + F_DELWORDPREV, /* ^W */ + F_EXPAND, /* ^X */ + F_UNASSIGNED, /* ^Y */ + F_UNASSIGNED, /* ^Z */ + F_METANEXT, /* ^[ */ + F_TTY_QUIT, /* ^\ */ + F_UNASSIGNED, /* ^] */ + F_UNASSIGNED, /* ^^ */ + F_UNASSIGNED, /* ^_ */ + F_CHARFWD, /* SPACE */ + F_EXPAND_HISTORY, /* ! */ + F_UNASSIGNED, /* " */ + F_UNASSIGNED, /* # */ + F_TOEND, /* $ */ + F_UNASSIGNED, /* % */ + F_UNASSIGNED, /* & */ + F_UNASSIGNED, /* ' */ + F_UNASSIGNED, /* ( */ + F_UNASSIGNED, /* ) */ + F_EXPAND_GLOB, /* * */ + F_DOWN_HIST, /* + */ + V_RCHAR_BACK, /* , */ + F_UP_HIST, /* - */ + F_UNASSIGNED, /* . */ + V_DSH_META, /* / */ + V_ZERO, /* 0 */ + F_ARGDIGIT, /* 1 */ + F_ARGDIGIT, /* 2 */ + F_ARGDIGIT, /* 3 */ + F_ARGDIGIT, /* 4 */ + F_ARGDIGIT, /* 5 */ + F_ARGDIGIT, /* 6 */ + F_ARGDIGIT, /* 7 */ + F_ARGDIGIT, /* 8 */ + F_ARGDIGIT, /* 9 */ + F_UNASSIGNED, /* : */ + V_RCHAR_FWD, /* ; */ + F_UNASSIGNED, /* < */ + F_UNASSIGNED, /* = */ + F_UNASSIGNED, /* > */ + V_USH_META, /* ? */ + F_UNASSIGNED, /* @ */ + V_ADDEND, /* A */ + V_WORDBACK, /* B */ + V_CHGTOEND, /* C */ + F_KILLEND, /* D */ + V_ENDWORD, /* E */ + V_CHAR_BACK, /* F */ + F_UNASSIGNED, /* G */ + F_UNASSIGNED, /* H */ + V_INSBEG, /* I */ + F_DOWN_SEARCH_HIST, /* J */ + F_UP_SEARCH_HIST, /* K */ + F_UNASSIGNED, /* L */ + F_UNASSIGNED, /* M */ + V_RSRCH_BACK, /* N */ + F_XKEY, /* O */ + F_UNASSIGNED, /* P */ + F_UNASSIGNED, /* Q */ + V_REPLMODE, /* R */ + V_SUBSTLINE, /* S */ + V_CHARTO_BACK, /* T */ + F_UNASSIGNED, /* U */ + F_EXPAND_VARS, /* V */ + V_WORDFWD, /* W */ + F_DELPREV, /* X */ + F_UNASSIGNED, /* Y */ + F_UNASSIGNED, /* Z */ + F_XKEY, /* [ */ + F_UNASSIGNED, /* \ */ + F_UNASSIGNED, /* ] */ + F_TOBEG, /* ^ */ + F_UNASSIGNED, /* _ */ + F_UNASSIGNED, /* ` */ + V_ADD, /* a */ + F_WORDBACK, /* b */ + V_CHGMETA, /* c */ + V_DELMETA, /* d */ + V_EWORD, /* e */ + V_CHAR_FWD, /* f */ + F_UNASSIGNED, /* g */ + F_CHARBACK, /* h */ + V_INSERT, /* i */ + F_DOWN_HIST, /* j */ + F_UP_HIST, /* k */ + F_CHARFWD, /* l */ + F_UNASSIGNED, /* m */ + V_RSRCH_FWD, /* n */ + F_UNASSIGNED, /* o */ + F_UNASSIGNED, /* p */ + F_UNASSIGNED, /* q */ + V_REPLONE, /* r */ + V_SUBSTCHAR, /* s */ + V_CHARTO_FWD, /* t */ + V_UNDO, /* u */ + F_EXPAND_VARS, /* v */ + V_WORDBEGNEXT, /* w */ + F_DELNEXT_EOF, /* x */ + F_UNASSIGNED, /* y */ + F_UNASSIGNED, /* z */ + F_UNASSIGNED, /* { */ + F_UNASSIGNED, /* | */ + F_UNASSIGNED, /* } */ + V_CHGCASE, /* ~ */ + F_DELPREV, /* ^? */ + F_UNASSIGNED, /* M-^@ */ + F_UNASSIGNED, /* M-^A */ + F_UNASSIGNED, /* M-^B */ + F_UNASSIGNED, /* M-^C */ + F_UNASSIGNED, /* M-^D */ + F_UNASSIGNED, /* M-^E */ + F_UNASSIGNED, /* M-^F */ + F_UNASSIGNED, /* M-^G */ + F_UNASSIGNED, /* M-^H */ + F_UNASSIGNED, /* M-^I */ + F_UNASSIGNED, /* M-^J */ + F_UNASSIGNED, /* M-^K */ + F_UNASSIGNED, /* M-^L */ + F_UNASSIGNED, /* M-^M */ + F_UNASSIGNED, /* M-^N */ + F_UNASSIGNED, /* M-^O */ + F_UNASSIGNED, /* M-^P */ + F_UNASSIGNED, /* M-^Q */ + F_UNASSIGNED, /* M-^R */ + F_UNASSIGNED, /* M-^S */ + F_UNASSIGNED, /* M-^T */ + F_UNASSIGNED, /* M-^U */ + F_UNASSIGNED, /* M-^V */ + F_UNASSIGNED, /* M-^W */ + F_UNASSIGNED, /* M-^X */ + F_UNASSIGNED, /* M-^Y */ + F_UNASSIGNED, /* M-^Z */ + F_UNASSIGNED, /* M-^[ */ + F_UNASSIGNED, /* M-^\ */ + F_UNASSIGNED, /* M-^] */ + F_UNASSIGNED, /* M-^^ */ + F_UNASSIGNED, /* M-^_ */ + F_UNASSIGNED, /* M-SPACE */ + F_UNASSIGNED, /* M-! */ + F_UNASSIGNED, /* M-" */ + F_UNASSIGNED, /* M-# */ + F_UNASSIGNED, /* M-$ */ + F_UNASSIGNED, /* M-% */ + F_UNASSIGNED, /* M-& */ + F_UNASSIGNED, /* M-' */ + F_UNASSIGNED, /* M-( */ + F_UNASSIGNED, /* M-) */ + F_UNASSIGNED, /* M-* */ + F_UNASSIGNED, /* M-+ */ + F_UNASSIGNED, /* M-, */ + F_UNASSIGNED, /* M-- */ + F_UNASSIGNED, /* M-. */ + F_UNASSIGNED, /* M-/ */ + F_UNASSIGNED, /* M-0 */ + F_UNASSIGNED, /* M-1 */ + F_UNASSIGNED, /* M-2 */ + F_UNASSIGNED, /* M-3 */ + F_UNASSIGNED, /* M-4 */ + F_UNASSIGNED, /* M-5 */ + F_UNASSIGNED, /* M-6 */ + F_UNASSIGNED, /* M-7 */ + F_UNASSIGNED, /* M-8 */ + F_UNASSIGNED, /* M-9 */ + F_UNASSIGNED, /* M-: */ + F_UNASSIGNED, /* M-; */ + F_UNASSIGNED, /* M-< */ + F_UNASSIGNED, /* M-= */ + F_UNASSIGNED, /* M-> */ + F_HELPME, /* M-? */ + F_UNASSIGNED, /* M-@ */ + F_UNASSIGNED, /* M-A */ + F_UNASSIGNED, /* M-B */ + F_UNASSIGNED, /* M-C */ + F_UNASSIGNED, /* M-D */ + F_UNASSIGNED, /* M-E */ + F_UNASSIGNED, /* M-F */ + F_UNASSIGNED, /* M-G */ + F_UNASSIGNED, /* M-H */ + F_UNASSIGNED, /* M-I */ + F_UNASSIGNED, /* M-J */ + F_UNASSIGNED, /* M-K */ + F_UNASSIGNED, /* M-L */ + F_UNASSIGNED, /* M-M */ + F_UNASSIGNED, /* M-N */ + F_XKEY, /* M-O *//* extended key esc PWP Mar 88 */ + F_UNASSIGNED, /* M-P */ + F_UNASSIGNED, /* M-Q */ + F_UNASSIGNED, /* M-R */ + F_UNASSIGNED, /* M-S */ + F_UNASSIGNED, /* M-T */ + F_UNASSIGNED, /* M-U */ + F_UNASSIGNED, /* M-V */ + F_UNASSIGNED, /* M-W */ + F_UNASSIGNED, /* M-X */ + F_UNASSIGNED, /* M-Y */ + F_UNASSIGNED, /* M-Z */ + F_XKEY, /* M-[ *//* extended key esc -mf Oct 87 */ + F_UNASSIGNED, /* M-\ */ + F_UNASSIGNED, /* M-] */ + F_UNASSIGNED, /* M-^ */ + F_UNASSIGNED, /* M-_ */ + F_UNASSIGNED, /* M-` */ + F_UNASSIGNED, /* M-a */ + F_UNASSIGNED, /* M-b */ + F_UNASSIGNED, /* M-c */ + F_UNASSIGNED, /* M-d */ + F_UNASSIGNED, /* M-e */ + F_UNASSIGNED, /* M-f */ + F_UNASSIGNED, /* M-g */ + F_UNASSIGNED, /* M-h */ + F_UNASSIGNED, /* M-i */ + F_UNASSIGNED, /* M-j */ + F_UNASSIGNED, /* M-k */ + F_UNASSIGNED, /* M-l */ + F_UNASSIGNED, /* M-m */ + F_UNASSIGNED, /* M-n */ + F_UNASSIGNED, /* M-o */ + F_UNASSIGNED, /* M-p */ + F_UNASSIGNED, /* M-q */ + F_UNASSIGNED, /* M-r */ + F_UNASSIGNED, /* M-s */ + F_UNASSIGNED, /* M-t */ + F_UNASSIGNED, /* M-u */ + F_UNASSIGNED, /* M-v */ + F_UNASSIGNED, /* M-w */ + F_UNASSIGNED, /* M-x */ + F_UNASSIGNED, /* M-y */ + F_UNASSIGNED, /* M-z */ + F_UNASSIGNED, /* M-{ */ + F_UNASSIGNED, /* M-| */ + F_UNASSIGNED, /* M-} */ + F_UNASSIGNED, /* M-~ */ + F_UNASSIGNED, /* M-^? */ + /* extra keys begin here */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + + /* ctrl key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + + /* alt key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED, /* DEL */ + /* shift key mappings */ + F_UNASSIGNED, /* f-1 */ + F_UNASSIGNED, /* f-2 */ + F_UNASSIGNED, /* f-3 */ + F_UNASSIGNED, /* f-4 */ + F_UNASSIGNED, /* f-5 */ + F_UNASSIGNED, /* f-6 */ + F_UNASSIGNED, /* f-7 */ + F_UNASSIGNED, /* f-8 */ + F_UNASSIGNED, /* f-9 */ + F_UNASSIGNED, /* f-10 */ + F_UNASSIGNED, /* f-11 */ + F_UNASSIGNED, /* f-12 */ + F_UNASSIGNED, /* f-13 */ + F_UNASSIGNED, /* f-14 */ + F_UNASSIGNED, /* f-15 */ + F_UNASSIGNED, /* f-16 */ + F_UNASSIGNED, /* f-17 */ + F_UNASSIGNED, /* f-18 */ + F_UNASSIGNED, /* f-19 */ + F_UNASSIGNED, /* f-20 */ + F_UNASSIGNED, /* f-21 */ + F_UNASSIGNED, /* f-22 */ + F_UNASSIGNED, /* f-23 */ + F_UNASSIGNED, /* f-24 */ + F_UNASSIGNED, /* PgUp */ + F_UNASSIGNED, /* PgDn */ + F_UNASSIGNED, /* end */ + F_UNASSIGNED, /* home */ + F_UNASSIGNED, /* LEFT */ + F_UNASSIGNED, /* UP */ + F_UNASSIGNED, /* RIGHT */ + F_UNASSIGNED, /* DOWN */ + F_UNASSIGNED, /* INS */ + F_UNASSIGNED /* DEL */ +}; + static void +nt_bad_spec(const Char *keystr) +{ + xprintf(CGETS(20, 4, "Bad key spec %S\n"), keystr); +} +extern int lstricmp(char*,char*); +Char nt_translate_bindkey(const Char*s) { + char *astr = short2str(s); + short fkey; + char corm; /* 1 for ctrl map, 2 for meta map, 3 for shift map*/ + Char keycode = 0; + + corm = 0; + + if (astr[0] == 'C') + corm= 1; + else if (astr[0] == 'M') + corm = 2; + else if (astr[0] == 'S') /*shift keymap by avner.lottem@intel.com*/ + corm = 3; + + if (corm) + astr += 2; /* skip C- or M- or S-*/ + + fkey = (short)atoi(astr); + if (fkey !=0) { + keycode = (NT_SPECIFIC_BINDING_OFFSET+ (fkey-1) ); + } + else { + if (!_stricmp("pgup",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN); + } + else if (!_stricmp("pgdown",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN + 1); + } + else if (!_stricmp("end",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN + 2); + } + else if (!_stricmp("home",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN + 3); + } + else if (!_stricmp("left",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN + 4); + } + else if (!_stricmp("up",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN + 5); + } + else if (!_stricmp("right",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN + 6); + } + else if (!_stricmp("down",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + KEYPAD_MAPPING_BEGIN + 7); + } + else if (!_stricmp("ins",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET + INS_DEL_MAPPING_BEGIN ); + } + else if (!_stricmp("del",astr)) { + keycode = (NT_SPECIFIC_BINDING_OFFSET +INS_DEL_MAPPING_BEGIN +1 ); + } + else + nt_bad_spec(s); + } + if (keycode && corm) { + if (corm == 1) + keycode += CTRL_KEY_OFFSET; + else if (corm == 2) + keycode += ALT_KEY_OFFSET; + else if (corm == 3) + keycode += SHIFT_KEY_OFFSET; + } + + return keycode; +} diff --git a/win32/nt.char.c b/win32/nt.char.c new file mode 100644 index 000000000000..f76bfefd9cb9 --- /dev/null +++ b/win32/nt.char.c @@ -0,0 +1,127 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/nt.char.c,v 1.10 2008/10/11 12:47:39 christos Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * nt.char.c : Does NLS-like stuff + * -amol + * + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdlib.h> +#include "sh.h" + + +static HMODULE hlangdll; + + +extern DWORD gdwPlatform; + + +unsigned char oem_it(unsigned char ch) { + unsigned char ch1[2],ch2[2]; + + ch1[0] = ch; + ch1[1] = 0; + + OemToChar((char*)ch1,(char*)ch2); + + return ch2[0]; +} +void nls_dll_unload(void) { + FreeLibrary(hlangdll); + hlangdll=NULL; +} +char * nt_cgets(int set, int msgnum, char *def) { + + int rc; + int msg; + static char oembuf[256];/*FIXBUF*/ + WCHAR buffer[256];/*FIXBUF*/ + + + + if (!hlangdll) + return def; + + msg = set * 10000 + msgnum; + + if (gdwPlatform == VER_PLATFORM_WIN32_WINDOWS) { + rc = LoadString(hlangdll,msg,oembuf,sizeof(oembuf)); + + if(!rc) + return def; + return oembuf; + } + rc = LoadStringW(hlangdll,msg,buffer,ARRAYSIZE(buffer)); + + if(!rc) + return def; + + WideCharToMultiByte(CP_OEMCP, + 0, + buffer, + -1, + oembuf,//winbuf, + 256, + NULL,NULL); + + return oembuf; +} +#if defined(DSPMBYTE) +void nt_autoset_dspmbyte(void) { + switch (GetConsoleCP()) { + case 932: /* Japan */ + setcopy(CHECK_MBYTEVAR, STRsjis, VAR_READWRITE); + update_dspmbyte_vars(); + break; + } +} + +// _mbmap must be copied to the child during fork() +unsigned short _mbmap[256] = { 0 }; +#endif + +#undef free +void nls_dll_init(void) { + + char *ptr; + size_t size = 0; + + + if (_dupenv_s(&ptr,&size,"TCSHLANG") == 0){ + + if (hlangdll) + FreeLibrary(hlangdll); + hlangdll = LoadLibrary(ptr); + + free(ptr); + } +} diff --git a/win32/nt.const.c b/win32/nt.const.c new file mode 100644 index 000000000000..daee2881ee41 --- /dev/null +++ b/win32/nt.const.c @@ -0,0 +1,50 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/nt.const.c,v 1.4 2003/02/08 20:03:29 christos Exp $*/ +/* + * nt.const.c: NT-specific String constants for tcsh. + */ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define _h_tc_const +#include "sh.h" +#ifdef WINNT_NATIVE +Char STRoldtitle[] = { 'o', 'l', 'd', 't', 'i', 't', 'l', 'e', '\0' }; +Char STRNTlamepathfix[] = { 'N', 'T', 'l', 'a', 'm', 'e', 'p', 'a', 't', 'h', + 'f', 'i','x','\0'}; +Char STRtcshlang[] = { 'T', 'C', 'S', 'H', 'L', 'A', 'N', 'G', '\0' }; +Char STRtcshsubsthb[] = { 'T', 'C', 'S', 'H', 'S', 'U', 'B', 'S', 'T', + 'H', 'B', '\0' }; +Char STRtcshonlystartexes[] = { 'T', 'C', 'S', 'H', 'O', 'N', 'L', 'Y', 'S', + 'T', 'A', 'R', 'T', 'E', 'X', 'E', 'S', '\0' }; +Char STRNTslowexec[] = {'N','T','s','l','o','w','e','x','e','c','\0'}; + +Char STRNTcaseifypwd[]={'N','T','c','a','s','e','i','f','y','p','w','d','\0'}; +Char STRdotEXE[] = {'.','E','X','E','\0'}; + +Char STRNTnoquoteprotect[]={'N','T','n','o','q','u','o','t','e','p','r','o','t','e','c','t','\0'}; +#endif /* WINNT_NATIVE */ diff --git a/win32/nt.screen.c b/win32/nt.screen.c new file mode 100644 index 000000000000..702591506cf5 --- /dev/null +++ b/win32/nt.screen.c @@ -0,0 +1,539 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/nt.screen.c,v 1.14 2006/03/14 01:22:57 mitr Exp $*/ +/* + * ed.screen.c: Editor/termcap-curses interface + */ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "sh.h" + + +#include "ed.h" +#include "tc.h" +#include "ed.defns.h" + + +/* #define DEBUG_LITERAL */ + +/* + * IMPORTANT NOTE: these routines are allowed to look at the current screen + * and the current possition assuming that it is correct. If this is not + * true, then the update will be WRONG! This is (should be) a valid + * assumption... + */ + + + +extern int nt_getsize(int*,int*,int*); +extern int nt_ClearEOL( void) ; +extern void NT_ClearEOD( void) ; +extern void NT_ClearScreen(void) ; +extern void NT_VisibleBell(void); +extern void NT_WrapHorizontal(void); + +static int GetSize(int *lins, int *cols); + +int DisplayWindowHSize; + void +terminit(void) +{ + return; +} + + + +int T_ActualWindowSize; + +static void ReBufferDisplay (void); + + +/*ARGSUSED*/ + void +TellTC(void) +{ + + xprintf(CGETS(7, 1, "\n\tYou're using a Windows console.\n")); +} + + + static void +ReBufferDisplay(void) +{ + register int i; + Char **b; + Char **bufp; + int lins,cols; + + nt_getsize(&lins,&cols,&DisplayWindowHSize); + + b = Display; + Display = NULL; + if (b != NULL) { + for (bufp = b; *bufp != NULL; bufp++) + xfree((ptr_t) * bufp); + xfree((ptr_t) b); + } + b = Vdisplay; + Vdisplay = NULL; + if (b != NULL) { + for (bufp = b; *bufp != NULL; bufp++) + xfree((ptr_t) * bufp); + xfree((ptr_t) b); + } + TermH = cols; + + TermV = (INBUFSIZE * 4) / TermH + 1;/*FIXBUF*/ + b = (Char **) xmalloc((size_t) (sizeof(*b) * (TermV + 1))); + for (i = 0; i < TermV; i++) + b[i] = (Char *) xmalloc((size_t) (sizeof(*b[i]) * (TermH + 1))); + b[TermV] = NULL; + Display = b; + b = (Char **) xmalloc((size_t) (sizeof(*b) * (TermV + 1))); + for (i = 0; i < TermV; i++) + b[i] = (Char *) xmalloc((size_t) (sizeof(*b[i]) * (TermH + 1))); + b[TermV] = NULL; + Vdisplay = b; +} + + void +SetTC(char *what, char *how) +{ + int li,win,co; + + nt_getsize(&li,&co,&win); + if (!lstrcmp(what,"li")) { + li = atoi(how); + + }else if(!lstrcmp(what,"co")) { //set window, not buffer size + win = atoi(how); + } + else + stderror(ERR_SYSTEM, "SetTC","Sorry, this function is not supported"); + + ChangeSize(li,win); + return; +} + + +/* + * Print the termcap string out with variable substitution + */ + void +EchoTC(Char **v) +{ + Char **globbed; + char cv[BUFSIZE];/*FIXBUF*/ + int verbose = 0, silent = 0; + static char *fmts = "%s\n", *fmtd = "%d\n"; + int li,co; + + + setname("echotc"); + + v = glob_all_or_error(v); + globbed = v; + cleanup_push(globbed, blk_cleanup); + + if (!v || !*v || *v[0] == '\0') + goto end; + if (v[0][0] == '-') { + switch (v[0][1]) { + case 'v': + verbose = 1; + break; + case 's': + silent = 1; + break; + default: + stderror(ERR_NAME | ERR_TCUSAGE); + break; + } + v++; + } + if (!*v || *v[0] == '\0') + goto end; + (void) StringCbCopy(cv,sizeof(cv), short2str(*v)); + + GetSize(&li,&co); + + if(!lstrcmp(cv,"rows") || !lstrcmp(cv,"lines") ) { + xprintf(fmtd,T_Lines); + goto end; + } + else if(!lstrcmp(cv,"cols") ) { + xprintf(fmtd,T_ActualWindowSize); + goto end; + } + else if(!lstrcmp(cv,"buffer") ) { + xprintf(fmtd,T_Cols); + goto end; + } + else + stderror(ERR_SYSTEM, "EchoTC","Sorry, this function is not supported"); + +end: + cleanup_until(globbed); +} + +int GotTermCaps = 0; + + + void +ResetArrowKeys(void) +{ +} + + void +DefaultArrowKeys(void) +{ +} + + + int +SetArrowKeys(const CStr *name, XmapVal *fun, int type) +{ + UNREFERENCED_PARAMETER(name); + UNREFERENCED_PARAMETER(fun); + UNREFERENCED_PARAMETER(type); + return -1; +} + + int +IsArrowKey(Char *name) +{ + UNREFERENCED_PARAMETER(name); + return 0; +} + + int +ClearArrowKeys(const CStr *name) +{ + UNREFERENCED_PARAMETER(name); + return -1; +} + + void +PrintArrowKeys(const CStr *name) +{ + UNREFERENCED_PARAMETER(name); + return; +} + + + void +BindArrowKeys(void) +{ + return; +} + +#define GoodStr(ignore) 1 + void +SetAttributes(Char atr) +{ + atr &= ATTRIBUTES; +} + +/* PWP 6-27-88 -- if the tty driver thinks that we can tab, we ask termcap */ + int +CanWeTab(void) +{ + return 1; +} + +/* move to line <where> (first line == 0) as efficiently as possible; */ + void +MoveToLine(int where) +{ + int del; + + if (where == CursorV) + return; + + if (where > TermV) { +#ifdef DEBUG_SCREEN + xprintf("MoveToLine: where is ridiculous: %d\r\n", where); + flush(); +#endif /* DEBUG_SCREEN */ + return; + } + + del = where - CursorV; + + NT_MoveToLineOrChar(del, 1); + + CursorV = where; /* now where is here */ +} + +/* move to character position (where) as efficiently as possible */ + void +MoveToChar(int where) +{ + if (where == CursorH) + return; + + if (where >= TermH) { +#ifdef DEBUG_SCREEN + xprintf("MoveToChar: where is riduculous: %d\r\n", where); + flush(); +#endif /* DEBUG_SCREEN */ + return; + } + + if (!where) { /* if where is first column */ + //(void) putraw('\r'); /* do a CR */ + NT_MoveToLineOrChar(where, 0); + flush(); + CursorH = 0; + return; + } + + NT_MoveToLineOrChar(where, 0); + CursorH = where; /* now where is here */ +} + + void +so_write(register Char *cp, register int n) +{ + if (n <= 0) + return; /* catch bugs */ + + if (n > TermH) { + return; + } + + do { + if (*cp & LITERAL) { + Char *d; + + for (d = litptr + (*cp++ & ~LITERAL) * LIT_FACTOR; *d; + d++) + (void) putraw(*d); + } + else + (void) putraw(*cp++); + CursorH++; + } while (--n); + + if (CursorH >= TermH) { /* wrap? */ + CursorH = 0; + CursorV++; + NT_WrapHorizontal(); + + } + else if(CursorH >= DisplayWindowHSize) { + flush(); + NT_MoveToLineOrChar(CursorH,0); + } +} + + + void +DeleteChars(int num) /* deletes <num> characters */ +{ + if (num <= 0) + return; + + if (!T_CanDel) { +#ifdef DEBUG_EDIT + xprintf(CGETS(7, 16, "ERROR: cannot delete\r\n")); +#endif /* DEBUG_EDIT */ + flush(); + return; + } + + if (num > TermH) { +#ifdef DEBUG_SCREEN + xprintf(CGETS(7, 17, "DeletChars: num is riduculous: %d\r\n"), num); + flush(); +#endif /* DEBUG_SCREEN */ + return; + } + +} + +/* Puts terminal in insert character mode, or inserts num characters in the + line */ + void +Insert_write(register Char *cp, register int num) +{ + UNREFERENCED_PARAMETER(cp); + + if (num <= 0) + return; + if (!T_CanIns) { +#ifdef DEBUG_EDIT + xprintf(CGETS(7, 18, "ERROR: cannot insert\r\n")); +#endif /* DEBUG_EDIT */ + flush(); + return; + } + + if (num > TermH) { +#ifdef DEBUG_SCREEN + xprintf(CGETS(7, 19, "StartInsert: num is riduculous: %d\r\n"), num); + flush(); +#endif /* DEBUG_SCREEN */ + return; + } + + +} + +/* clear to end of line. There are num characters to clear */ + void +ClearEOL(int num) +{ + + if (num <= 0) + return; + + nt_ClearEOL(); + +} + + void +ClearScreen(void) +{ /* clear the whole screen and home */ + + NT_ClearScreen(); + +} + + void +SoundBeep(void) +{ /* produce a sound */ + beep_cmd (); + if (adrof(STRnobeep)) + return; + + if (adrof(STRvisiblebell)) + NT_VisibleBell(); /* visible bell */ + else + MessageBeep(MB_ICONQUESTION); +} + + void +ClearToBottom(void) +{ /* clear to the bottom of the screen */ + NT_ClearEOD(); + +} + + void +GetTermCaps(void) +{ + int lins,cols; + + nt_getsize(&lins,&cols,&DisplayWindowHSize); + + GotTermCaps = 1; + + T_Cols = cols; + T_Lines = lins; + T_ActualWindowSize = DisplayWindowHSize; + T_Margin = MARGIN_AUTO; + T_CanCEOL = 1; + T_CanDel = 0; + T_CanIns = 0; + T_CanUP = 1; + + ReBufferDisplay(); + ClearDisp(); + + return; +} +/* GetSize(): + * Return the new window size in lines and cols, and + * true if the size was changed. + */ + int +GetSize(int *lins, int *cols) +{ + + int ret = 0; + + *lins = T_Lines; + + *cols = T_Cols; + + nt_getsize(lins,cols,&DisplayWindowHSize); + + // compare the actual visible window size,but return the console buffer size + // this is seriously demented. + ret = (T_Lines != *lins || T_ActualWindowSize != DisplayWindowHSize); + + T_Lines = *lins; + T_Cols = *cols; + T_ActualWindowSize = DisplayWindowHSize; + + return ret; +} + void +ChangeSize(int lins, int cols) +{ + + int rc = 0; + // here we're setting the window size, not the buffer size. + // + nt_set_size(lins,cols); + + rc = GetSize(&lins,&cols); + + + ReBufferDisplay(); /* re-make display buffers */ + ClearDisp(); +} + void +PutPlusOne(Char c, int width) +{ + extern int OldvcV; + + while (width > 1 && CursorH + width > DisplayWindowHSize) + PutPlusOne(' ', 1); + if ((c & LITERAL) != 0) { + Char *d; + for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++) + (void) putwraw(*d); + } else { + (void) putwraw(c); + } + + Display[CursorV][CursorH++] = (Char) c; + while (--width > 0) + Display[CursorV][CursorH++] = CHAR_DBWIDTH; + + if (CursorH >= TermH) { /* if we must overflow */ + CursorH = 0; + CursorV++; + OldvcV++; + NT_WrapHorizontal(); + } + else if(CursorH >= DisplayWindowHSize) { + NT_MoveToLineOrChar(CursorH,0); + } +} diff --git a/win32/nt.who.c b/win32/nt.who.c new file mode 100644 index 000000000000..59ef39eec42d --- /dev/null +++ b/win32/nt.who.c @@ -0,0 +1,275 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/nt.who.c,v 1.6 2006/03/05 08:59:36 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * nt.who.c: Support for who-like functions, using NETBIOS + * -amol + * + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <nb30.h> +#include <stdio.h> +#include "sh.h" + + +typedef struct _ASTAT_ { + ADAPTER_STATUS adapt; + NAME_BUFFER NameBuff [10]; +} ASTAT; + +typedef struct _n_ctx { + NCB ncb; + u_char usr_name[NCBNAMSZ]; + u_char mach_name[NCBNAMSZ]; +} ncb_ctx; + +typedef UCHAR (APIENTRY *netbios_func)(NCB *); + + +static netbios_func p_Netbios =0; +static int ginited = 0; + +static CRITICAL_SECTION nb_critter; +static HMODULE hnetapi; + + +extern int add_to_who_list(u_char *,u_char*); + +void init_netbios(void ) { + + + if (!ginited) { + hnetapi = LoadLibrary("NETAPI32.DLL"); + if (!hnetapi) + return ; + + p_Netbios = (netbios_func)GetProcAddress(hnetapi,"Netbios"); + + if (!p_Netbios ) + return ; + ginited = 1; + } + InitializeCriticalSection(&nb_critter); +} +void cleanup_netbios(void) { + if (hnetapi){ + DeleteCriticalSection(&nb_critter); + FreeLibrary(hnetapi); + } +} +void CALLBACK complete_ncb( NCB * p_ncb) { + + int count,i; + ADAPTER_STATUS *p_ad; + ASTAT *pas; + char *p1; + ncb_ctx *ctx = (ncb_ctx *)p_ncb; + + if (p_ncb->ncb_retcode) + goto end; + + __try { + + EnterCriticalSection(&nb_critter); + pas = ((ASTAT*) p_ncb->ncb_buffer); + p_ad = &pas->adapt; + + count = p_ad->name_count; + + if (count <=0 ) + __leave; + + if (ctx->usr_name[0] == 0) { //any user on given machine + for(i=0; i<count;i++) { + if (pas->NameBuff[i].name[15] == 03) { // unique name + if (!strncmp((char*)(pas->NameBuff[i].name), + (char*)(p_ncb->ncb_callname), + NCBNAMSZ)) { + continue; + } + else { + p1 = strchr((char*)(pas->NameBuff[i].name),' '); + if (p1) + *p1 = 0; + else + pas->NameBuff[i].name[15]= 0; + add_to_who_list(pas->NameBuff[i].name, + ctx->mach_name); + break; + } + } + } + } + else if (ctx->mach_name[0] == 0) { // given user on any machine + for(i=0; i<count;i++) { + if (pas->NameBuff[i].name[15] == 03) { // unique name + if (!strncmp((char*)(pas->NameBuff[i].name), + (char*)(p_ncb->ncb_callname), + NCBNAMSZ)) + continue; + else { + p1 = strchr((char*)(pas->NameBuff[i].name),' '); + if (p1) + *p1 = 0; + else + pas->NameBuff[i].name[15]= 0; + + add_to_who_list(ctx->usr_name, pas->NameBuff[i].name); + + break; + } + } + } + } + else { // specific user on specific machine + for(i=0; i<count;i++) { + if (pas->NameBuff[i].name[15] == 03) { // unique name + // skip computer name + if (!strncmp((char*)(pas->NameBuff[i].name), + (char*)(p_ncb->ncb_callname), + NCBNAMSZ)) { + continue; + } + else if (!strncmp((char*)(pas->NameBuff[i].name), + (char*)(ctx->usr_name), + lstrlen((char*)ctx->usr_name))) { + p1 = strchr((char*)pas->NameBuff[i].name,' '); + if (p1) + *p1 = 0; + else + pas->NameBuff[i].name[15]= 0; + add_to_who_list(pas->NameBuff[i].name,ctx->mach_name); + break; + } + } + } + } + } + __except(GetExceptionCode()) { + ; + } + LeaveCriticalSection(&nb_critter); +end: + heap_free(p_ncb->ncb_buffer); + heap_free(p_ncb); + return; +} +void start_ncbs (Char **vp) { + + ncb_ctx * p_ctx; + NCB *Ncb; + Char **namevec = vp; + char *p1,*p2,*nb_name; + UCHAR uRetCode; + ASTAT *Adapter; + + if (!ginited) { + init_netbios(); + } + if (!ginited) + return; + + for (namevec = vp;*namevec != NULL;namevec +=2) { + + p_ctx = heap_alloc(sizeof(ncb_ctx)); + Adapter = heap_alloc(sizeof(ASTAT)); + + Ncb = (NCB*)p_ctx; + + memset( Ncb, 0, sizeof(NCB) ); + + Ncb->ncb_command = NCBRESET; + Ncb->ncb_lana_num = 0; + + uRetCode = p_Netbios( Ncb ); + + if(uRetCode) + goto cleanup; + + if ((**namevec == '\0' ) || ( *(namevec +1) == NULL) || + (**(namevec +1) == '\0') ) + break; + + + p1 = short2str(*namevec); + if (!_stricmp(p1,"any") ) { + p_ctx->usr_name[0] = 0; + } + else { + StringCbCopy((char*)p_ctx->usr_name,sizeof(p_ctx->usr_name),p1); + } + p1 = (char*)&(p_ctx->usr_name[0]); + + p2 = short2str(*(namevec+1)); + // + // If machine is not "any", make it the callname + // + if (!_stricmp(p2,"any") ) { + p_ctx->mach_name[0] = 0; + nb_name = p1; + } + else { + StringCbCopy((char*)p_ctx->mach_name,sizeof(p_ctx->mach_name),p2); + nb_name = p2; + } + + // do not permit any any + // + if( (p_ctx->mach_name[0] == 0) && (p_ctx->usr_name[0] == 0) ) + goto cleanup; + + + + memset( Ncb, 0, sizeof (NCB) ); + + Ncb->ncb_command = NCBASTAT | ASYNCH; + Ncb->ncb_lana_num = 0; + + memset(Ncb->ncb_callname,' ',sizeof(Ncb->ncb_callname)); + + Ncb->ncb_callname[15]=03; + + memcpy(Ncb->ncb_callname,nb_name,lstrlen(nb_name)); + + Ncb->ncb_buffer = (u_char *) Adapter; + Ncb->ncb_length = sizeof(*Adapter); + + Ncb->ncb_post = complete_ncb; + + uRetCode = p_Netbios( Ncb ); + } + return; + +cleanup: + heap_free(Adapter); + heap_free(p_ctx); + return; +} diff --git a/win32/ntb1.c b/win32/ntb1.c new file mode 100644 index 000000000000..ccc54451c116 --- /dev/null +++ b/win32/ntb1.c @@ -0,0 +1,35 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/ntb1.c,v 1.4 2004/05/19 18:22:28 christos Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +// +// Placeholder variable to mark beginning of data segment. +// -amol +// +#include "ntport.h" +unsigned long bookend1=0; diff --git a/win32/ntb2.c b/win32/ntb2.c new file mode 100644 index 000000000000..99a119917185 --- /dev/null +++ b/win32/ntb2.c @@ -0,0 +1,34 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/ntb2.c,v 1.4 2004/05/19 18:22:28 christos Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +// +// Placeholder variable to mark end of data segment. +// +#include "ntport.h" +unsigned long bookend2=0; diff --git a/win32/ntfunc.c b/win32/ntfunc.c new file mode 100644 index 000000000000..2799715cb109 --- /dev/null +++ b/win32/ntfunc.c @@ -0,0 +1,1207 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/ntfunc.c,v 1.19 2006/08/27 01:13:28 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * ntfunc.c builtins specific to NT + * -amol + * + */ +#pragma warning(push,3) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <shellapi.h> +#pragma warning(pop) +#include <errno.h> +#include <sh.h> +#include "ed.h" + +#include "nt.const.h" + + +extern DWORD gdwPlatform; + +extern int StrQcmp(Char *, Char *); +extern int hashval_extern(Char*); +extern int bit_extern(int,int); +extern void bis_extern(int,int); +extern int hashname(Char*); + +extern void NT_ClearScreen_WholeBuffer(void); + +BOOL is_url(const char *cmd); + +void error(char * ) ; +void make_err_str(unsigned int ,char *,int) ; + +#define INF INT_MAX +struct biltins nt_bfunc[] = { + { "cls", docls, 0, 0 }, +#ifdef NTDBG + { "debugbreak", dodebugbreak, 0, 0 }, +#endif /* NTDBG */ + { "ps", dops, 0, 1 }, + { "shutdown", doshutdown, 0, 2 }, + { "start", dostart, 1, INF }, + { "title", dotitle, 1, INF }, +}; +int nt_nbfunc = sizeof nt_bfunc / sizeof *nt_bfunc; + +char start_usage[] = { ":\n \ + Similar to cmd.exe's start \n \ + start [-Ttitle] [-Dpath] [-min] [-max] [-separate] [-shared] \n \ + [-low|normal|realtime|high] program args \n \ + Batch/Cmd files must be started with CMD /K \n" +}; + +struct biltins * nt_check_additional_builtins(Char *cp) { + + register struct biltins *bp1, *bp2; + int i; + + for (bp1 = nt_bfunc, bp2 = nt_bfunc + nt_nbfunc; bp1 < bp2;bp1++) { + + if ((i = ((char) *cp) - *bp1->bname) == 0 && + (i = StrQcmp(cp, str2short(bp1->bname))) == 0) + return bp1; + } + return (0); +} +void nt_print_builtins(size_t maxwidth) { + + /* would use print_by_column() in tw.parse.c but that assumes + * we have an array of Char * to pass.. (sg) + */ + extern int Tty_raw_mode; + extern int TermH; /* from the editor routines */ + extern int lbuffed; /* from sh.print.c */ + + register struct biltins *b; + register size_t row, col, columns, rows; + size_t w ,oldmax; + + + /* find widest string */ + + oldmax = maxwidth; + + for ( b = nt_bfunc; b < &nt_bfunc[nt_nbfunc]; ++b) + maxwidth = max(maxwidth, (int)lstrlen(b->bname)); + + if (oldmax != maxwidth) + ++maxwidth; /* for space */ + + columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */ + if (!columns) + columns = 1; + rows = (nt_nbfunc + (columns - 1)) / columns; + + for (b = nt_bfunc, row = 0; row < rows; row++) { + for (col = 0; col < columns; col++) { + if (b < &nt_bfunc[nt_nbfunc]) { + w = (int)lstrlen(b->bname); + xprintf("%s", b->bname); + if (col < (columns - 1)) /* Not last column? */ + for (; w < maxwidth; w++) + xputchar(' '); + ++b; + } + } + if (Tty_raw_mode) + xputchar('\r'); + xputchar('\n'); + } + +} +/* patch from TAGA Nayuta for start . */ +BOOL is_directory(const char *the_cmd) { + DWORD attr = GetFileAttributes(the_cmd); + return (attr != 0xFFFFFFFF && + (attr & FILE_ATTRIBUTE_DIRECTORY)); +} +void dostart(Char ** vc, struct command *c) { + + char *cmdstr,*cmdend,*ptr; + char argv0[256];/*FIXBUF*/ + DWORD cmdsize; + char *currdir=NULL; + char *savepath; + char **v = NULL; + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD dwCreationFlags=CREATE_NEW_CONSOLE; + DWORD k,cmdlen,j,jj,ret; + + + UNREFERENCED_PARAMETER(c); + vc++; + + cmdsize = 512; + cmdstr = heap_alloc(cmdsize); + cmdend = cmdstr; + cmdlen = 0; + + memset(&si,0,sizeof(si)); + si.cb = sizeof(si); + + vc = glob_all_or_error(vc); + v = short2blk(vc); + if(v == NULL) { + stderror(ERR_NOMEM); + return; + } + blkfree(vc); + for (k = 0; v[k] != NULL ; k++){ + + if ( v[k][0] == '-' ) { + /* various options */ + if( (v[k][1] == 'T') || (v[k][1] == 't')) + si.lpTitle =&( v[k][2]); + else if ( (v[k][1] == 'D') || (v[k][1] == 'd')) + currdir =&( v[k][2]); + else if (!_stricmp(&v[k][1],"MIN") ) + si.wShowWindow = SW_SHOWMINIMIZED; + else if (!_stricmp(&v[k][1],"MAX") ) + si.wShowWindow = SW_SHOWMAXIMIZED; + else if (!_stricmp(&v[k][1],"SEPARATE") ) + dwCreationFlags |= CREATE_SEPARATE_WOW_VDM; + else if (!_stricmp(&v[k][1],"SHARED") ) + dwCreationFlags |= CREATE_SHARED_WOW_VDM; + else if (!_stricmp(&v[k][1],"LOW") ) + dwCreationFlags |= IDLE_PRIORITY_CLASS; + else if (!_stricmp(&v[k][1],"NORMAL") ) + dwCreationFlags |= NORMAL_PRIORITY_CLASS; + else if (!_stricmp(&v[k][1],"HIGH") ) + dwCreationFlags |= HIGH_PRIORITY_CLASS; + else if (!_stricmp(&v[k][1],"REALTIME") ) + dwCreationFlags |= REALTIME_PRIORITY_CLASS; + else{ + blkfree((Char **)v); + stderror(ERR_SYSTEM,start_usage,"See CMD.EXE for more info");/*FIXRESET*/ + } + } + else{ // non-option arg + break; + } + } + /* + * Stop the insanity of requiring start "tcsh -l" + * Option processing now stops at first non-option arg + * -amol 5/30/96 + */ + for (jj=k;v[jj] != NULL; jj++) { + j=(lstrlen(v[jj]) + 2); + if (j + cmdlen > cmdsize) { + ptr = cmdstr; + cmdstr = heap_realloc(cmdstr, max(cmdsize << 1, j+cmdlen) ); + if(!cmdstr) + { + heap_free(ptr); + stderror(ERR_NOMEM,"start");/*FIXRESET*/ + } + cmdend = cmdstr + (cmdend - ptr); + cmdsize <<= 1; + } + ptr = v[jj]; + while (*ptr) { + *cmdend++ = *ptr++; + cmdlen++; + } + *cmdend++ = ' '; + cmdlen++; + } + if (jj == k) { + blkfree((Char **)v); + stderror(ERR_SYSTEM,start_usage,"See CMD.EXE for more info");/*FIXRESET*/ + return; + } + *cmdend = 0; + StringCbCopy(argv0,sizeof(argv0),v[k]); + + + /* + * strictly speaking, it should do no harm to set the path + * back to '\'-delimited even in the parent, but in the + * interest of consistency, we save the old value and restore it + * later + */ + + savepath = fix_path_for_child(); + + if (! CreateProcess(NULL, + cmdstr, + NULL, + NULL, + FALSE, + dwCreationFlags, + NULL, + currdir, + &si, + &pi) ) { + + restore_path(savepath); + + ret = GetLastError(); + if (ret == ERROR_BAD_EXE_FORMAT || ret == ERROR_ACCESS_DENIED || + (ret == ERROR_FILE_NOT_FOUND && + (is_url(v[k]) || is_directory(v[k])) + ) + ) { + + char erbuf[MAX_PATH]; + + errno = ENOEXEC; + + try_shell_ex(&v[k],0,FALSE); + + heap_free(cmdstr); /* free !! */ + + if (errno) { + strerror_s(erbuf,sizeof(erbuf),errno); + stderror(ERR_ARCH,argv0,erbuf);/*FIXRESET*/ + } + } + else if (ret == ERROR_INVALID_PARAMETER) { + + errno = ENAMETOOLONG; + + heap_free(cmdstr); /* free !! */ + + stderror(ERR_TOOLARGE,argv0);/*FIXRESET*/ + + } + else { + errno = ENOENT; + if ( + ( (v[k][0] == '\\') ||(v[k][0] == '/') ) && + ( (v[k][1] == '\\') ||(v[k][1] == '/') ) && + (!v[k+1]) + ) + try_shell_ex(&v[k],0,FALSE); + + heap_free(cmdstr); /* free !! */ + if (errno) { + stderror(ERR_NOTFOUND,argv0);/*FIXRESET*/ + } + } + } + else { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + heap_free(cmdstr); + restore_path(savepath); + } + blkfree((Char **)v); + return; +} +void error(char * ebuf) { + + write(2,(unsigned char*)ebuf,lstrlen(ebuf)); +} +void make_err_str(unsigned int error,char *buf,int size) { + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + error, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + buf, + size, + NULL); + return; + +} + +// We should really use the environ array, but NT likes it to be sorted. +// So we just let the win32 apis take care of inheritance of the environment. +// -amol 4/7/97 +// +//char nameBuf[BUFSIZ], valBuf[BUFSIZ]; +char dummy; +char *nameBuf=&dummy, *valBuf=&dummy; + +void nt_set_env(const Char *name, const Char *val) { + char *cname, *cval; + int len; + + cname = name?short2str(name):NULL; + if(cname) { + len = lstrlen(cname); + nameBuf = heap_alloc(len+1); + if (!nameBuf) { + stderror(ERR_TOOLARGE); + } + StringCbCopy(nameBuf,len+1,cname); + } + cval = val?short2str(val):NULL; + if(cval) { + len = lstrlen(cval); + valBuf = heap_alloc(len+1); + StringCbCopy(valBuf,len+1,cval); + } + + SetEnvironmentVariable(nameBuf,cval?valBuf:NULL); + + if (!lstrcmp(nameBuf,"TCSHONLYSTARTEXES")) + init_shell_dll(); + + heap_free(nameBuf); + if (cval) + heap_free(valBuf); + + +} +void dotitle(Char **vc, struct command * c) { + + int k; + char titlebuf[512]; + char errbuf[128],err2[128]; + char **v; + + UNREFERENCED_PARAMETER(c); + vc++; + vc = glob_all_or_error(vc); + cleanup_push(vc, blk_cleanup); + + if ((k=GetConsoleTitle(titlebuf,512) ) != 0) { + titlebuf[k]=0; + setcopy(STRoldtitle,str2short(titlebuf),VAR_READWRITE); + } + + memset(titlebuf,0,512); + v = short2blk(vc); + cleanup_until(vc); + cleanup_push((Char **)v, blk_cleanup); + for (k = 0; v[k] != NULL ; k++){ + __try { + StringCbCat(titlebuf,sizeof(titlebuf),v[k]); + StringCbCat(titlebuf,sizeof(titlebuf)," "); + } + __except(GetExceptionCode()) { + stderror(ERR_TOOMANY); + } + } + + if (!SetConsoleTitle(titlebuf) ) { + make_err_str(GetLastError(),errbuf,128); + (void)StringCbPrintf(err2,sizeof(err2),"%s",v[k]); + stderror(ERR_SYSTEM,err2,errbuf); + } + cleanup_until((Char **)v); + return; +} +void docls(Char **vc, struct command *c) { + UNREFERENCED_PARAMETER(vc); + UNREFERENCED_PARAMETER(c); + NT_ClearScreen_WholeBuffer(); +} +int nt_feed_to_cmd(char *file,char **argv) { + + char *ptr, *orig; + char cmdbuf[128]; + HANDLE htemp; + STARTUPINFO si; + PROCESS_INFORMATION pi; + + if (!file) + return 1; + + ptr = strrchr(file,'.'); + + if(!ptr) + return 1; + + if (lstrlen(ptr) <4) + return 1; + + if ( _stricmp(ptr,".bat") && _stricmp(ptr,".cmd") ) + return 1; + + + memset(&si,0,sizeof(si)); + memset(&pi,0,sizeof(pi)); + + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + htemp= (HANDLE)_get_osfhandle(0); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdInput,0,TRUE,DUPLICATE_SAME_ACCESS); + htemp= (HANDLE)_get_osfhandle(1); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdOutput,0,TRUE,DUPLICATE_SAME_ACCESS); + htemp= (HANDLE)_get_osfhandle(2); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdError,0,TRUE,DUPLICATE_SAME_ACCESS); + + + ptr =file; + while(*ptr) { + if (*ptr == '/') + *ptr = '\\'; + ptr++; + } + if (gdwPlatform == VER_PLATFORM_WIN32_WINDOWS){ + (void)StringCbPrintf(cmdbuf,sizeof(cmdbuf), + "command.com /c %s",file); + } + else + (void)StringCbPrintf(cmdbuf,sizeof(cmdbuf), + "cmd /c %s",file); + + argv++; + ptr = &cmdbuf[0] ; + orig = ptr; + while(*argv) { + StringCbCat(ptr,sizeof(cmdbuf) - (orig - ptr), " "); + StringCbCat(ptr,sizeof(cmdbuf) - (orig - ptr),*argv); + argv++; + } + + ptr = fix_path_for_child(); + + if (!CreateProcess(NULL, + cmdbuf, + NULL, + NULL, + TRUE, + 0,//CREATE_NEW_CONSOLE |CREATE_NEW_PROCESS_GROUP, + NULL, + NULL, + &si, + &pi) ){ + restore_path(ptr); + } + else { + + restore_path(ptr); + CloseHandle(pi.hThread); + WaitForSingleObject(pi.hProcess,INFINITE); + CloseHandle(pi.hProcess); + ExitProcess(0); + } + + return 1; /*NOTREACHED*/ +} +static char *hb_subst_array[20] ; +void init_hb_subst(void) { + int i= 0; + size_t len; + char envbuf[1024]; + char *ptr; + char *p2; + + envbuf[0]=0; + + GetEnvironmentVariable("TCSHSUBSTHB",envbuf,1024); + + ptr = &envbuf[0]; + + if (!*ptr) + return; + + p2 = ptr; + + while (*ptr) { + if (*ptr == ';') { + len = ptr - p2; + if (!len){ + ptr++; + continue; + } + hb_subst_array[i] = heap_alloc(len+1); + StringCbCopy(hb_subst_array[i],len + 1, p2); + + i++; + p2 = ptr+1; + } + ptr++; + } +} +char *hb_subst(char *orig) { + int i, match; + char *p1; + + for(i =0 ;i <20; i++) { + p1 = hb_subst_array[i]; + if (!p1) + continue; + while(*p1 != ' ') + p1++; + + *p1 = 0; + match = !_stricmp(orig,hb_subst_array[i]); + *p1 = ' '; + if (match){ + return (p1+1); + } + } + return NULL; + +} +typedef BOOL (__stdcall *shell_ex_func)(LPSHELLEXECUTEINFO); + +/* DO NOT initialize these here -amol */ +static HMODULE hShellDll; +static shell_ex_func pShellExecuteEx; +int __nt_only_start_exes; + +static char no_assoc[256]; //the environment string/*FIXBUF*/ +static char *no_assoc_array[20]; // the list of extensions to NOT try /*FIXBUF*/ +// explorer associations for + +void init_shell_dll(void) { + + int rc,i; + size_t len; + char *p2, *ptr; + + if (!hShellDll) { + hShellDll = LoadLibrary("Shell32.dll"); + if (hShellDll) { + pShellExecuteEx = (shell_ex_func)GetProcAddress( + hShellDll, + "ShellExecuteEx"); + } + } + rc=GetEnvironmentVariable("TCSHONLYSTARTEXES",no_assoc,256) ; + if (!rc || (rc > 255)) + return; + + if (rc == 1) { + __nt_only_start_exes = 1; + return; + } + + ptr = &no_assoc[0]; + i = 0; + + if (!ptr) + return; + + p2 = ptr; + + while (i < 20) { + if (*ptr == ';' || (!*ptr)) { + len = ptr - p2; + if (!len){ + ptr++; + continue; + } + no_assoc_array[i] = heap_alloc(len+1); + StringCbCopy(no_assoc_array[i],len+1, p2); + dprintf("no_assoc array %d inited to %s\n",i,no_assoc_array[i]); + + i++; + p2 = ptr+1; + } + if (!*ptr) + break; + ptr++; + } +#if NTDBG + for(i=0;i<20,no_assoc_array[i] != NULL;i++) + dprintf("no_assoc array %d inited remains %s\n",i,no_assoc_array[i]); +#endif NTDBG + +} +// return non-zero if str is found in no_assoc_array +int find_no_assoc(char *my_str) { + int i, match; + char *p1; + + for(i =0 ;i <20; i++) { + p1 = no_assoc_array[i]; + dprintf("no_assoc array %d is %s\n",i,no_assoc_array[i]); + if (!p1) + continue; + match = !_stricmp(my_str,no_assoc_array[i]); + if (match) + return 1; + } + return 0; +} +void try_shell_ex(char **argv,int exitsuccess, BOOL throw_ok) {/*FIXRESET*/ + + char *prog; + char *cmdstr, *p2, *cmdend; + char *originalPtr = NULL; + unsigned int cmdsize,cmdlen; + char err2[256]; + char *ptr; + SHELLEXECUTEINFO shinfo; + unsigned long mask = SEE_MASK_FLAG_NO_UI; + BOOL rc; + char *extension; + + prog=*argv; + + dprintf("trying shellex for prog %s\n",prog); + ptr = prog; + if (!is_url(prog)) { + + while(*ptr) { + if (*ptr == '/') + *ptr = '\\'; + ptr++; + } + + extension = ptr; + + // search back for "." + while(extension != prog) { + if (*extension == '.') { + extension++; + break; + } + else + extension--; + } + /* check if this matches a member in the no_assoc array. + */ + if (extension != prog) { + if (find_no_assoc(extension)) + return; + } + + } + originalPtr = cmdstr= heap_alloc(MAX_PATH<<2); + + cmdsize = MAX_PATH<<2; + + p2 = cmdstr; + + cmdlen = 0; + cmdend = p2; + + argv++; // the first arg is the command + + + dprintf("try_shell_ex calling c_a_a_q"); + if(!concat_args_and_quote(argv,&originalPtr,&cmdstr,&cmdlen,&cmdend,&cmdsize)) + { + errno = ENOMEM; + heap_free(originalPtr); + return; + } + + *cmdend = 0; + + + memset(&shinfo,0,sizeof(shinfo)); + shinfo.cbSize = sizeof(shinfo); + shinfo.fMask = SEE_MASK_FLAG_DDEWAIT | mask; + shinfo.hwnd = NULL; + shinfo.lpVerb = NULL; + shinfo.lpFile = prog; + shinfo.lpParameters = &cmdstr[0]; + shinfo.lpDirectory = 0; + shinfo.nShow = SW_SHOWDEFAULT; + + + ptr = fix_path_for_child(); + + rc = pShellExecuteEx(&shinfo); + if (rc ) { + if (exitsuccess) + ExitProcess(0); + errno = 0; + + heap_free(originalPtr); + return; + } + if (throw_ok) { + // if we got here, ShellExecuteEx failed, so reset() via stderror() + // this may cause the caller to leak, but the assumption is that + // only a child process sets exitsuccess, so it will be dead soon + // anyway + + restore_path(ptr); + + make_err_str(GetLastError(),cmdstr,512);//don't need the full size + (void)StringCbPrintf(err2,sizeof(err2),"%s",prog); + stderror(ERR_SYSTEM,err2,cmdstr);/*FIXRESET*/ + } + + heap_free(originalPtr); + restore_path(ptr); + + errno = ENOEXEC; + +} +#ifdef NTDBG +void dodebugbreak(Char **vc, struct command *c) { + UNREFERENCED_PARAMETER(vc); + UNREFERENCED_PARAMETER(c); + DebugBreak(); +} +#endif NTDBG +int nt_texec(char *, char**) ; +static Char *epath; +static Char *abspath[] = {STRNULL,0}; +int nt_try_fast_exec(struct command *t) { + register Char **pv, **av; + register Char *dp,*sav; + register char **tt; + register char *f; + register struct varent *v; + register int hashval,i; + register int slash; + int rc = 0, gflag; + Char *vp; + Char *blk[2]; + + vp = varval(STRNTslowexec); + if (vp != STRNULL) + return 1; + + blk[0] = t->t_dcom[0]; + blk[1] = 0; + + // don't do backtick + if(Strchr(t->t_dcom[0],'`') ) + return 1; + + + gflag = tglob(blk); + if (gflag) { + pv = globall(blk, gflag); + if (pv == 0) { + return 1; + } + } + else + pv = saveblk(blk); + + trim(pv); + + epath = Strsave(pv[0]); + v = adrof(STRpath); + if (v == 0 && epath[0] != '/' && epath[0] != '.') { + blkfree(pv); + return 1; + } + slash = any(short2str(epath),'/'); + /* + * Glob the argument list, if necessary. Otherwise trim off the quote bits. + */ + av = &t->t_dcom[1]; + gflag = tglob(av); + if (gflag) { + av = globall(av, gflag);/*FIXRESET*/ + if (av == 0) { + blkfree(pv); + return 1; + } + } + else + av = saveblk(av); + + blkfree(t->t_dcom); + t->t_dcom = blkspl(pv, av); + xfree((ptr_t) pv); + xfree((ptr_t) av); + av = t->t_dcom; + //trim(av); + + if (*av == NULL || **av == '\0') + return 1; + + xechoit(av);/*FIXRESET*/ /* Echo command if -x */ + if (v == 0 || v->vec[0] == 0 || slash) + pv = abspath; + else + pv = v->vec; + + sav = Strspl(STRslash,*av); + hashval = hashval_extern(*av); + + i = 0; + do { +#pragma warning(disable:4310) + if (!slash && ABSOLUTEP(pv[0]) && havhash) { +#pragma warning(default:4310) + if (!bit_extern(hashval,i)){ + pv++;i++; + continue; + } + } + if (pv[0][0] == 0 || eq(pv[0],STRdot)) { + + tt = short2blk(av); + f = short2str(*av); + + rc = nt_texec(f, tt); + + blkfree((Char**)tt); + if (!rc) + break; + } + else { + dp = Strspl(*pv,sav); + tt = short2blk(av); + f = short2str(dp); + + rc = nt_texec(f, tt); + + blkfree((Char**)tt); + xfree((ptr_t)dp); + if (!rc) + break; + } + pv++; + i++; + }while(*pv); + return rc; +} +int nt_texec(char *prog, char**args ) { + + STARTUPINFO si; + PROCESS_INFORMATION pi; + HANDLE htemp; + DWORD type=0; + DWORD dwCreationflags; + unsigned int priority; + char *argv0 = NULL, *savepath = NULL; + char *cmdstr,*cmdend ; + char *originalPtr = NULL; + unsigned int cmdsize,cmdlen; + char *p2; + char **savedargs; + int retries=0; + int hasdot =0; + int is_winnt=0; + int retval = 1; + + memset(&si,0,sizeof(si)); + savedargs = args; + + /* MUST FREE !! */ + originalPtr = cmdstr= heap_alloc(MAX_PATH<<2); + cmdsize = MAX_PATH<<2; + + is_winnt = (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS); + + + p2 = cmdstr; + + cmdlen = 0; + cmdlen += copy_quote_and_fix_slashes(prog,cmdstr,&hasdot); + p2 += cmdlen; + + if (*cmdstr != '"') { + // If not quoted, skip initial character we left for quote + *cmdstr = 'A'; + cmdstr++; + cmdsize--; + } + *p2 = 0; + cmdend = p2; + + if (!is_winnt) { + argv0 = NULL; + } + else { + argv0= heap_alloc(MAX_PATH); + (void)StringCbPrintf(argv0,MAX_PATH,"%s",prog); + } + + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + htemp= (HANDLE)_get_osfhandle(SHIN); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdInput,0,TRUE,DUPLICATE_SAME_ACCESS); + htemp= (HANDLE)_get_osfhandle(SHOUT); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdOutput,0,TRUE,DUPLICATE_SAME_ACCESS); + htemp= (HANDLE)_get_osfhandle(SHDIAG); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdError,0,TRUE,DUPLICATE_SAME_ACCESS); + + + /* + quotespace hack needed since execv() would have separated args, but + createproces doesnt + -amol 9/14/96 + */ + + args++; // the first arg is the command + + dprintf("nt_texec calling c_a_a_q"); + if(concat_args_and_quote(args,&originalPtr,&cmdstr,&cmdlen,&cmdend,&cmdsize) == NULL) + { + retval = 1; + errno = ENOMEM; + heap_free(originalPtr); + goto free_mem; + } + + *cmdend = 0; + + dwCreationflags = GetPriorityClass(GetCurrentProcess()); + priority = GetThreadPriority(GetCurrentThread()); + + if (is_winnt) { + retries = 0; + // For NT, try ShellExecuteEx first + do { + if (GetBinaryType(argv0,&type)) + break; + if (GetLastError() == ERROR_BAD_EXE_FORMAT){ + errno = ENOEXEC; + if (!__nt_only_start_exes) + try_shell_ex(savedargs,0,FALSE); + if (errno) { + retval = 1; + goto free_mem; + } + else { + retval = 0; + goto free_mem; + } + } + // only try shellex again after appending ".exe fails + else if ( retries > 1 ){ + if ( + ( (argv0[0] == '\\') ||(argv0[0] == '/') ) && + ( (argv0[1] == '\\') ||(argv0[1] == '/') ) && + (!args[1]) + ) + if (!__nt_only_start_exes) + try_shell_ex(savedargs,0,FALSE); + errno = ENOENT; + } + if (retries == 0) + (void)StringCbPrintf(argv0,MAX_PATH,"%s.exe",prog); + else if (retries == 1) { + (void)StringCbPrintf(argv0,MAX_PATH,"%s.EXE",prog); + } + retries++; + }while(retries < 3); + } + savepath = fix_path_for_child(); +re_cp: + dprintf("nt_texec cmdstr %s\n",cmdstr); + + + if (!CreateProcess(argv0, + cmdstr, + NULL, + NULL, + TRUE, // need this for redirecting std handles + dwCreationflags, + NULL,//envcrap, + NULL, + &si, + &pi) ){ + + if (GetLastError() == ERROR_BAD_EXE_FORMAT) { + errno = ENOEXEC; + } + else if (GetLastError() == ERROR_INVALID_PARAMETER) { + errno = ENAMETOOLONG; + }else { + errno = ENOENT; + } + if (!is_winnt && !hasdot) { //append '.' to the end if needed + StringCbCat(cmdstr,cmdsize,"."); + hasdot=1; + goto re_cp; + } + retval = 1; + } + else{ + int gui_app ; + DWORD exitcode; + char guivar[50]; + + + if (GetEnvironmentVariable("TCSH_NOASYNCGUI",guivar,50)) + gui_app=0; + else + gui_app= is_gui(argv0); + + if(!gui_app) { + WaitForSingleObject(pi.hProcess,INFINITE); + (void)GetExitCodeProcess(pi.hProcess,&exitcode); + setv(STRstatus, putn(exitcode), VAR_READWRITE);/*FIXRESET*/ + } + retval = 0; + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } +free_mem: + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + + if(savepath) + restore_path(savepath); + + heap_free(originalPtr); + if (argv0) + heap_free(argv0); + return retval; +} +BOOL is_url(const char *thecmd) { + char *protocol; + const char *c; + HKEY hkey; + char buf[2]; + DWORD type; + DWORD size; + + c = strchr(thecmd, ':'); + size = (DWORD)(c - thecmd); + if (!c || size <= 1) + return FALSE; + + protocol = (char *)heap_alloc(size + 2); + StringCbCopy(protocol,size+2, thecmd); + protocol[size] = '\0'; + + if (RegOpenKeyEx(HKEY_CLASSES_ROOT, protocol, 0, KEY_READ, &hkey) + != ERROR_SUCCESS ) { + heap_free(protocol); + return FALSE; + } + + heap_free(protocol); + + type = REG_SZ; + size = sizeof(buf); + if ( RegQueryValueEx(hkey, "URL Protocol", NULL, &type, (BYTE*)buf, &size) + != ERROR_SUCCESS) { + RegCloseKey(hkey); + return FALSE; + } + RegCloseKey(hkey); + return TRUE; +} +/* + * patch based on work by Chun-Pong Yu (bol.pacific.net.sg) + */ +BOOL is_nt_executable(char *path,char *extension) { + DWORD exetype; + + if (GetBinaryType(path,&exetype)) + return TRUE; + if (*extension && find_no_assoc(extension)) + return TRUE; + + return FALSE; +} +int executable(const Char *dir, const Char *name, int dir_ok) +{ + struct stat stbuf; + Char path[MAXPATHLEN + 1]; + char *strname; + char extension[MAXPATHLEN]; + char *ptr, *p2 ; + int has_ext = 0; + extern void copyn(Char *, const Char *, size_t); + extern void catn(Char *, const Char *, int); + + (void) memset(path, 0, sizeof(path)); + + if (dir && *dir) { + copyn(path, dir, MAXPATHLEN); + catn(path, name, MAXPATHLEN); + + p2 = ptr = short2str(path); + + while (*ptr++) + continue; + --ptr; + + while(ptr > p2) { + if (*ptr == '/') + break; + if (*ptr == '.') { + has_ext = 1; + StringCbCopy(extension,MAXPATHLEN,ptr+1); + break; + } + ptr--; + } + if (!has_ext && (nt_stat(p2, &stbuf) == -1)) + catn(path, STRdotEXE, MAXPATHLEN); + strname = short2str(path); + } + else + strname = short2str(name); + + return (stat(strname, &stbuf) != -1 && + ((dir_ok && S_ISDIR(stbuf.st_mode)) || + (S_ISREG(stbuf.st_mode) && + (is_nt_executable(strname,extension) || + (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR))) + ))); +} + int +nt_check_if_windir(char *path) +{ + char windir[MAX_PATH]; + + (void)GetWindowsDirectory(windir, sizeof(windir)); + windir[2] = '/'; + + return (strstr(path, windir) != NULL); +} + + void +nt_check_name_and_hash(int is_windir, char *file, int i) +{ + char name_only[MAX_PATH]; + char *tmp = (char *)strrchr(file, '.'); + char uptmp[5], *nameptr, *np2; + int icount, hashval; + + if(!tmp || tmp[4]) + goto nodot; + + for (icount = 0; icount < 4; icount++) + uptmp[icount] = (char)toupper(tmp[icount]); + uptmp[4]=0; + + if (is_windir) + if((uptmp[1] != 'E') || (uptmp[2] != 'X') || (uptmp[3] != 'E')) + return; + (void) memset(name_only, 0, MAX_PATH); + nameptr = file; + np2 = name_only; + while(nameptr != tmp) { + *np2++= (char)tolower(*nameptr); + nameptr++; + } + hashval = hashname(str2short(name_only)); + bis_extern(hashval, i); +nodot: + hashval = hashname(str2short(file)); + bis_extern(hashval, i); +} diff --git a/win32/ntport.h b/win32/ntport.h new file mode 100644 index 000000000000..d78fbf684a51 --- /dev/null +++ b/win32/ntport.h @@ -0,0 +1,511 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/ntport.h,v 1.14 2010/05/23 17:20:32 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// ntport.h +// the main header. +// -amol +// +// +#ifndef NTPORT_H +#define NTPORT_H +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <io.h> +#include <direct.h> +#include "dirent.h" +#include "version.h" + +#ifndef WINDOWS_ONLY +#define STRSAFE_NO_DEPRECATE +#endif /* WINDOWS_ONLY*/ +#define STRSAFE_LIB +#define STR_NO_CCH_FUNCTIONS +#include <strsafe.h> + +// These needed for fork(), which controls the heap management. +#pragma data_seg(".fusrdata") +#define INIT_ZERO =0 +#define INIT_ZERO_STRUCT ={0} +#define malloc fmalloc +#define calloc fcalloc +#define realloc frealloc +#define free ffree +#undef min +#undef max + +#define heap_alloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s)) +#define heap_free(p) HeapFree(GetProcessHeap(),0,(p)) +#define heap_realloc(p,s) HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(p),(s)) + +#pragma warning(disable:4018) //signed-unsigned mismatch +#define HAVENOLIMIT + +/* os-dependent stuff. belongs in tc.os.h, but I never said this would be +pretty */ + +#define lstat stat +#ifdef S_IFMT +# if !defined(S_ISDIR) && defined(S_IFDIR) +# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) +# endif /* ! S_ISDIR && S_IFDIR */ +# if !defined(S_ISCHR) && defined(S_IFCHR) +# define S_ISCHR(a) (((a) & S_IFMT) == S_IFCHR) +# endif /* ! S_ISCHR && S_IFCHR */ +# if !defined(S_ISBLK) && defined(S_IFBLK) +# define S_ISBLK(a) (((a) & S_IFMT) == S_IFBLK) +# endif /* ! S_ISBLK && S_IFBLK */ +# if !defined(S_ISREG) && defined(S_IFREG) +# define S_ISREG(a) (((a) & S_IFMT) == S_IFREG) +# endif /* ! S_ISREG && S_IFREG */ +# if !defined(S_ISFIFO) && defined(S_IFIFO) +# define S_ISFIFO(a) (((a) & S_IFMT) == S_IFIFO) +# endif /* ! S_ISFIFO && S_IFIFO */ +# if !defined(S_ISNAM) && defined(S_IFNAM) +# define S_ISNAM(a) (((a) & S_IFMT) == S_IFNAM) +# endif /* ! S_ISNAM && S_IFNAM */ +# if !defined(S_ISLNK) && defined(S_IFLNK) +# define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK) +# endif /* ! S_ISLNK && S_IFLNK */ +# if !defined(S_ISSOCK) && defined(S_IFSOCK) +# define S_ISSOCK(a) (((a) & S_IFMT) == S_IFSOCK) +# endif /* ! S_ISSOCK && S_IFSOCK */ +#endif /* S_IFMT */ + +/* port defines */ +#define getpid GetCurrentProcessId +#define getpgrp GetCurrentProcessId +#define tcgetpgrp(a) GetCurrentProcessId() +#define tcsetpgrp(a,b) 0 +#define setpgid(a,b) 0 + + +#define close(a) nt_close(a) +#define execv(a,b) nt_exec((a),(b)) +#define execve(a,b,c) nt_execve((a),(b),(c)) + +#define open nt_open +#define read(f,b,n) nt_read((f),(b),(n)) +#define write(f,b,n) nt_write((f),(b),(n)) +#define creat(f,m) nt_creat((f),(m)) +#define _exit(a) ExitProcess((a)) + +#define chdir(a) nt_chdir(a) + +#undef putc +#undef putchar +#define fgetc(a) nt_fgetc(a) +#define fputs(a,b) nt_fputs((a),(b)) +#define putc(a,b) nt_putc((char)(a),(b)) +#define fflush(a) nt_fflush((a)) +#define fputc(a,b) nt_fputc((char)(a),(b)) +#define fprintf nt_fprintf +#define puts(a) nt_puts(a) +#define putchar(a) nt_putchar((char)(a)) +#define fclose(p) nt_fclose(p) +#define _get_osfhandle __nt_get_osfhandle +#define _open_osfhandle __nt_open_osfhandle +#define clearerr nt_clearerr +#define dup2 nt_dup2 +#define fdopen nt_fdopen +#define fgets nt_fgets +#define fileno nt_fileno +#define fopen nt_fopen +#define fread nt_fread +#define fseek nt_fseek +#define ftell nt_ftell +#define fwrite nt_fwrite +#define isatty nt_isatty +#define lseek nt_lseek +#define printf nt_printf +#define access nt_access +#define fstat(a,b) nt_fstat((a),(b)) +#define stat(a,b) nt_stat((a),(b)) + +#define setvbuf(a,b,c,d) +#define setpgrp(a,b) (-1) +#define tcsetattr(a,b,c) 0 + +#define inline __inline + +#undef stdin +#undef stdout +#undef stderr +#define stdin ((FILE*)my_stdin) +#define stdout ((FILE*)my_stdout) +#define stderr ((FILE*)my_stderr) + +#define dup(f) nt_dup((f)) +#define sleep(a) Sleep((a)*1000) + +#define getcwd(a,b) forward_slash_get_cwd((a),(b)) + + +#define L_SET SEEK_SET +#define L_XTND SEEK_END +#define L_INCR SEEK_CUR +#define S_IXUSR S_IEXEC +#define S_IXGRP S_IEXEC +#define S_IXOTH S_IEXEC + +#define NOFILE 64 +#define ARG_MAX 1024 +#define MAXSIG NSIG + +/* +mode Value Checks File For + +00 Existence only +02 Write permission +04 Read permission +06 Read and write permission +*/ +#define F_OK 0 +#define X_OK 1 +#define W_OK 2 +#define R_OK 4 +#define XD_OK 9 //executable and not directory + +/* base key mappings + ctrl-key mappings + alt-key mappings */ +/* see nt.bind.c to figure these out */ +/* 256 + + 4*24 (fkeys) + + 4*4 (arrow) + + 4*2 (pgup/dn) + + 4*2 (home/end) + + 4*2 (ins/del) +*/ +#define NT_NUM_KEYS 392 + +#define NT_SPECIFIC_BINDING_OFFSET 256 /* where our bindings start */ + +#define KEYPAD_MAPPING_BEGIN 24 /* offset from NT_SPECIFIC + where keypad mappings begin */ +#define INS_DEL_MAPPING_BEGIN 32 + +#define SINGLE_KEY_OFFSET 0 /*if no ctrl or alt pressed */ +#define CTRL_KEY_OFFSET 34 +#define ALT_KEY_OFFSET (34*2) +#define SHIFT_KEY_OFFSET (34*3) + +typedef int pid_t; +typedef int speed_t; +typedef unsigned char u_char; +typedef size_t caddr_t; +typedef int sig_atomic_t; +typedef int mode_t; +typedef UINT32 uint32_t; + +struct timeval{ + long tv_sec; + long tv_usec; +}; +struct termios; +/* +struct timezone{ + int tz_minuteswest; + int dsttime; +}; +*/ +struct rusage { + + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ + long ru_maxrss; /* maximum resident set size */ + long ru_ixrss; /* integral shared memory size */ + long ru_idrss; /* integral unshared data size */ + long ru_isrss; /* integral unshared stack size */ + long ru_minflt; /* page reclaims */ + long ru_majflt; /* page faults */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary context switches */ +}; +typedef int uid_t; +typedef int gid_t; +typedef long ssize_t; + +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* user password */ + uid_t pw_uid; /* user id */ + gid_t pw_gid; /* group id */ + char *pw_gecos; /* real name */ + char *pw_dir; /* home directory */ + char *pw_shell; /* shell program */ +}; +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + gid_t gr_gid; /* group id */ + char **gr_mem; /* group members */ +}; + +#ifndef _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef __int64 intptr_t; +#else +typedef int intptr_t; +#endif +#define _INTPTR_T_DEFINED +#endif +/* ntport.c */ +extern char * ttyname(int); +extern struct passwd* getpwuid(uid_t ) ; +extern struct group * getgrgid(gid_t ) ; +extern struct passwd* getpwnam(const char* ) ; +extern struct group* getgrnam(char* ) ; +extern gid_t getuid(void) ; +extern gid_t getgid(void) ; +extern gid_t geteuid(void) ; +extern gid_t getegid(void) ; + +#ifdef NTDBG +extern void dprintf(char *,...); +#define DBreak() __asm {int 3} +#else +#define dprintf (void) +#endif NTDBG + +#define pipe(a) nt_pipe(a) + + +/* support.c */ +extern void nt_init(void); +extern int gethostname(char*,int); +extern char* forward_slash_get_cwd(char *,size_t len ); +extern int nt_chdir(char*); +extern void nt_execve(char *,char**,char**); +extern void nt_exec(char *,char**); +extern int quoteProtect(char *, char *,unsigned long) ; +extern char* fix_path_for_child(void) ; +extern void restore_path(char *) ; +extern int copy_quote_and_fix_slashes(char *,char *, int * ); +extern char* concat_args_and_quote(char **,char**,char **,unsigned int *, char **, + unsigned int *) ; + + +extern int is_nt_executable(char*,char*); +/* io.c */ +extern int force_read(int, unsigned char*,size_t); +extern int nt_read(int, unsigned char*,size_t); +extern int nt_write(int, const unsigned char*,size_t); +extern int stringtable_read(int,char*,size_t); + +/* tparse.c */ +extern int tc_putc(char,FILE*); + + +void nt_cleanup(void); + +/* stdio.c */ +extern int nt_creat(const char*,int); +extern int nt_close(int); +extern int nt_open(const char*,int ,...); +extern int nt_pipe(int*); +extern void restore_fds(void ) ; +extern void copy_fds(void); +extern void close_copied_fds(void ) ; +extern int nt_fgetc(FILE*); +extern int nt_dup(int); +extern int nt_fputs(char*,FILE*); +extern int nt_putc(char,FILE*); +extern int nt_fflush(FILE*); +extern int nt_fputc(char, FILE*); +extern int nt_fprintf(FILE*,char*,...); +extern int nt_puts(char*); +extern int nt_putchar(char); +extern int nt_fclose(FILE*); +extern int nt_fputs(char *, FILE*); +extern intptr_t __nt_get_osfhandle(int); +extern int __nt_open_osfhandle(intptr_t, int); +extern int nt_clearerr(FILE*); +extern int nt_dup2(int,int ); +extern FILE* nt_fdopen(int,char*); +extern char * nt_fgets(char *,int, FILE*); +extern int nt_fileno(FILE*); +extern FILE *nt_fopen(char *,char*); +extern int nt_fread(void *,size_t,size_t,FILE*); +extern int nt_fwrite(void*,size_t,size_t,FILE*); +extern int nt_fseek(FILE*,long,int); +extern long nt_ftell(FILE*); +extern int nt_isatty(int); +extern int nt_lseek(int,long,int); +extern int nt_printf(char*,...); +extern int nt_access(char*,int); +extern int nt_fstat(int, struct stat *) ; +extern int nt_stat(const char *, struct stat *) ; +extern void nt_close_on_exec(int , int); +extern void init_stdio(void) ; +extern int is_resource_file(int); +#ifndef STDIO_C +extern void *my_stdin,*my_stdout,*my_stderr; +#endif STDIO_C + + +/* nt.char.c */ +extern unsigned char oem_it(unsigned char ); +extern char *nt_cgets(int,int,char*); +extern void nls_dll_init(void); +extern void nls_dll_unload(void); +extern void nt_autoset_dspmbyte(void); + +/* fork.c */ +extern int fork_init(void); +extern int fork(void); +extern void *sbrk(int); +extern void *fmalloc(size_t); +extern void ffree(void *); +extern void *frealloc(void*,size_t); +extern void *fcalloc(size_t,size_t); +extern void set_stackbase(void*); + +/* console.c */ +extern void do_nt_cooked_mode(void ); +extern void do_nt_raw_mode(void ) ; +extern int do_nt_check_cooked_mode(void); +extern void set_cons_attr (char *); +extern void NT_MoveToLineOrChar(int ,int ) ; +extern void nt_term_init(void); +extern void nt_term_cleanup(void); +extern void nt_set_size(int,int); +//extern DWORD set_cooked_mode(HANDLE); +//extern void set_raw_mode(HANDLE); +//extern void set_arbitrary_mode(HANDLE,DWORD); +extern void set_attributes(const unsigned char *color); + +/* ../sh.exec.c */ +extern int nt_check_if_windir(char *); +extern void nt_check_name_and_hash(int ,char *,int); + + +/* clip.c */ +extern void cut_clip(void); +extern int paste_clip(void); +extern void init_clipboard(void); +extern HANDLE create_clip_writer_thread(void) ; +extern HANDLE create_clip_reader_thread(void) ; + +/* signal.c */ +extern int kill(int,int); +extern int nice(int); +extern void nt_init_signals(void) ; +extern void nt_cleanup_signals(void) ; +extern void start_sigchild_thread(HANDLE , DWORD ) ; + +/* nt.who.c */ +extern void start_ncbs(short **); +extern void cleanup_netbios(void); + +/* ntfunc.c */ +struct command; +extern void dostart(short **,struct command *); +extern void docls(short **,struct command *); +extern void dotitle(short **, struct command * ) ; +extern void dostacksize(short**,struct command *); +extern void dosourceresource(short **, struct command * ) ; +extern void doprintresource(short **, struct command * ) ; +#ifdef NTDBG +extern void dodebugbreak(short **, struct command * ) ; +#endif NTDBG +extern void nt_set_env(const short *, const short*); +extern char *hb_subst(char *) ; +extern void init_hb_subst() ; +extern void init_shell_dll(void) ; +extern void try_shell_ex(char**,int,BOOL); +extern int nt_try_fast_exec(struct command *); +extern int nt_feed_to_cmd(char*,char**); +extern short nt_translate_bindkey(const short*); + +extern struct biltins *nt_check_additional_builtins(short *); +extern void nt_print_builtins(size_t); + +/* ps.c */ +extern void init_plister(void); +extern void dops(short **,struct command *); +extern void doshutdown(short **,struct command *); +extern int kill_by_wm_close(int ) ; + +/* globals.c */ +extern int is_gui(char*); +extern int is_9x_gui(char*); + + +/* Global variables */ +extern unsigned short __nt_want_vcode,__nt_vcode,__nt_really_exec; +extern int __dup_stdin; +extern int __nt_only_start_exes; +extern unsigned short __nt_child_nohupped; +extern DWORD gdwPlatform,gdwVersion; +extern int is_dev_clipboard_active; +extern HANDLE ghdevclipthread; +extern DWORD gdwStackSize; + +// bogus +#define getppid() 0 + +struct tms { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; +}; +#define UT_UNKNOWN 0 +#define DEAD_PROCESS 7 +#define USER_PROCESS 8 +#define UT_LINESIZE 16 +#define UT_NAMESIZE 8 +#define UT_HOSTSIZE 16 + +struct utmp { + short ut_type; /* type of login */ + pid_t ut_pid; + char ut_line[UT_LINESIZE]; /* device pref'/dev/' */ + char ut_id[2]; /*abbrev tty name */ + time_t ut_time; /* login time */ + char ut_user[UT_NAMESIZE]; /* user name */ + char ut_host[UT_HOSTSIZE]; /* hostname for rlogin */ + long ut_addr; /*ipaddr of remote host */ +}; + + +#define ut_name ut_user +#define killpg kill + +#endif NTPORT_H diff --git a/win32/ps.c b/win32/ps.c new file mode 100644 index 000000000000..bc81f1c954ee --- /dev/null +++ b/win32/ps.c @@ -0,0 +1,371 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/ps.c,v 1.9 2006/03/14 01:22:58 mitr Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * ps.c : ps,shutdown builtins. + * -amol + * + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winperf.h> +#include <tlhelp32.h> +#include <sh.h> +#include <errno.h> + + +#define REGKEY_PERF "software\\microsoft\\windows nt\\currentversion\\perflib" +#define REGSUBKEY_COUNTERS "Counters" +#define PROCESS_COUNTER "process" +#define PROCESSID_COUNTER "id process" + +typedef struct _pslist { + DWORD pid; + HANDLE hwnd; + char exename[MAX_PATH]; + char title[80]; +}pslist; + + +typedef BOOL (WINAPI *walker)(HANDLE,LPPROCESSENTRY32); +typedef HANDLE (WINAPI *create_snapshot)(DWORD,DWORD); +static walker proc32First; +static walker proc32Next; +static create_snapshot createSnapshot; + +typedef BOOL (WINAPI *enumproc)(DWORD *,DWORD,DWORD *); +typedef BOOL (WINAPI *enummod)(HANDLE,HMODULE*,DWORD,DWORD*); +typedef DWORD(WINAPI *getfilename_ex)(HANDLE,HANDLE , char*,DWORD); +typedef DWORD (WINAPI *getbasename)(HANDLE,HMODULE,char*,DWORD); +static enumproc enum_processes; +static enummod enum_process_modules; +static getfilename_ex getfilenameex; +static getbasename GetModuleBaseNameA; + +typedef DWORD (*plist_proc)(void); + +DWORD Win95Lister(void); +DWORD NTLister(void); + +plist_proc ProcessListFunc; +pslist *processlist; +static unsigned long numprocs, g_dowindows; + +static HMODULE hlib; + +extern DWORD gdwPlatform; +extern void make_err_str(int,char *,int); + +BOOL CALLBACK enum_wincb(HWND hwnd,LPARAM nump) { + + unsigned int i; + DWORD pid = 0; + + if (!GetWindowThreadProcessId(hwnd,&pid)) + return TRUE; + + for (i =0;i < nump;i++) { + if (processlist[i].pid == pid){ + processlist[i].hwnd = hwnd; + if (processlist[i].title[0] !=0) + break;; + GetWindowText(hwnd,processlist[i].title, + sizeof(processlist[i].title)); + break; + } + } + return TRUE; +} +static HWND ghwndtokillbywm_close; +BOOL CALLBACK enum_wincb2(HWND hwnd,LPARAM pidtokill) { + DWORD pid = 0; + + if (!GetWindowThreadProcessId(hwnd,&pid)) + return TRUE; + if (pid == (DWORD)pidtokill){ + ghwndtokillbywm_close = hwnd; + PostMessage( hwnd, WM_CLOSE, 0, 0 ); + return TRUE; + } + + return TRUE; +} +int kill_by_wm_close(int pid) { + EnumWindows(enum_wincb2,(LPARAM)pid); + if (!ghwndtokillbywm_close) + return -1; + ghwndtokillbywm_close = NULL; + return 0; +} +DWORD Win95Lister(void) { + + HANDLE hsnap; + PROCESSENTRY32 pe; + unsigned long nump =0; + + + hsnap = createSnapshot(TH32CS_SNAPPROCESS,0); + if (hsnap == INVALID_HANDLE_VALUE) + return 0; + + // if (processlist) + // p_free(processlist); + + pe.dwSize = sizeof(PROCESSENTRY32); + if (proc32First(hsnap,&pe) ) { + processlist = heap_alloc(100*sizeof(pslist)); + if (!processlist) + goto done; + + do { + StringCbCopy(processlist[nump].exename, + sizeof(processlist[nump].exename),pe.szExeFile); + + processlist[nump].title[0] = 0; + processlist[nump].pid = pe.th32ProcessID; + nump++; + }while(proc32Next(hsnap,&pe)); + } +done: + CloseHandle(hsnap); + + if (g_dowindows) { + EnumWindows(enum_wincb,(LPARAM)nump); + } + return nump; +} + +DWORD NTLister(void) { + + DWORD procs[200],dummy,ignore; + HANDLE hproc; + HMODULE hmod; + unsigned int i; + + + // if (processlist) + // p_free(processlist); + + if (!enum_processes(procs,sizeof(procs),&dummy) ) { + return 0; + } + + dummy = dummy/sizeof(DWORD); // number of entries filled + + processlist = heap_alloc(dummy*sizeof(pslist)); + if (!processlist){ + return 0; + } + + for(i=0 ; i< dummy;i++) { + processlist[i].pid = procs[i]; + processlist[i].title[0] = 0; + hproc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, + FALSE,procs[i]); + if (hproc) { + if (enum_process_modules(hproc,&hmod,sizeof(hmod),&ignore)) { + GetModuleBaseNameA(hproc,hmod, processlist[i].exename,MAX_PATH); + } + else + StringCbCopy(processlist[i].exename, + sizeof(processlist[i].exename),"(unknown)"); + CloseHandle(hproc); + } + else + StringCbCopy(processlist[i].exename, + sizeof(processlist[i].exename),"(unknown)"); + + } + if (g_dowindows) { + EnumWindows(enum_wincb,(LPARAM)dummy); + } + return dummy; +} + +void init_plister(void) { + + + hlib = LoadLibrary("kernel32.dll"); + if (!hlib) + return ; + + + ProcessListFunc = Win95Lister; + + proc32First = (walker)GetProcAddress(hlib,"Process32First"); + proc32Next = (walker)GetProcAddress(hlib,"Process32Next"); + createSnapshot= (create_snapshot)GetProcAddress(hlib, + "CreateToolhelp32Snapshot"); + + FreeLibrary(hlib); + if (!proc32First || !proc32Next || !createSnapshot) { + ProcessListFunc = NULL; + } +} +void dops(Char ** vc, struct command *c) { + + DWORD nump; + unsigned int i,k; + char **v; + + UNREFERENCED_PARAMETER(c); + + if (!ProcessListFunc) + return; + vc = glob_all_or_error(vc); + v = short2blk(vc); + blkfree(vc); + for (k = 0; v[k] != NULL ; k++){ + if ( v[k][0] == '-' ) { + if( (v[k][1] == 'W') || (v[k][1] == 'w')) + g_dowindows = 1; + } + } + blkfree((Char**)v); + nump = ProcessListFunc(); + + for(i=0; i< nump; i++) { + if (gdwPlatform == VER_PLATFORM_WIN32_NT) + xprintf("%6u %-20s %-30s\n",processlist[i].pid, + processlist[i].exename, + g_dowindows?processlist[i].title:""); + else + xprintf("0x%08x %-20s %-30s\n",processlist[i].pid, + processlist[i].exename, + g_dowindows?processlist[i].title:""); + } + g_dowindows =0; + + if (processlist) + heap_free(processlist); + +} +static char shutdown_usage[]= {"shutdown -[r|l][f] now\n-r reboots, -l logs\ + off the current user\n-f forces termination of running applications.\n\ + The default action is to shutdown without a reboot.\n\"now\" must be \ + specified to actually shutdown or reboot\n"}; + +void doshutdown(Char **vc, struct command *c) { + + unsigned int flags = 0; + unsigned char reboot,shutdown,logoff,shutdown_ok; + char **v; + char *ptr; + char errbuf[128]; + int k; + HANDLE hToken; + TOKEN_PRIVILEGES tp,tpPrevious; + LUID luid; + DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); + + UNREFERENCED_PARAMETER(c); + + if (gdwPlatform != VER_PLATFORM_WIN32_NT) { + stderror(ERR_SYSTEM,"shutdown","Sorry,not supported on win95"); + } + + shutdown_ok = reboot = shutdown = logoff = 0; + vc = glob_all_or_error(vc); + v = short2blk(vc); + blkfree(vc); + cleanup_push((Char **)v, blk_cleanup); + for (k = 0; v[k] != NULL ; k++){ + if ( v[k][0] == '-' ) { + ptr = v[k]; + ptr++; + while( ptr && *ptr) { + if (*ptr == 'f') + flags |= EWX_FORCE; + if (*ptr == 'r') + reboot =1; + else if (*ptr == 'l') + logoff =1; + else + stderror(ERR_SYSTEM,"Usage",shutdown_usage); + ptr++; + } + } + else if (!_stricmp(v[k],"now")) { + shutdown_ok = 1; + } + } + if (k == 0) + stderror(ERR_SYSTEM,"Usage",shutdown_usage); + if (!reboot && !logoff){ + flags |= EWX_SHUTDOWN; + shutdown = 1; + } + if (reboot && logoff ) + stderror(ERR_SYSTEM,"Usage",shutdown_usage); + if (reboot) + flags |= EWX_REBOOT; + if (logoff) + flags |= EWX_LOGOFF; + + if ((reboot || shutdown) && (!shutdown_ok) ) + stderror(ERR_SYSTEM,"shutdown","Specify \"now\" to really shutdown"); + + + if (!OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES| TOKEN_QUERY, + &hToken) ){ + make_err_str(GetLastError(),errbuf,128); + stderror(ERR_SYSTEM,"shutdown failed",errbuf); + } + + + if (!LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&luid)) { + make_err_str(GetLastError(),errbuf,128); + stderror(ERR_SYSTEM,"shutdown failed",errbuf); + } + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = 0; + + if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),&tpPrevious, + &cbPrevious)){ + make_err_str(GetLastError(),errbuf,128); + stderror(ERR_SYSTEM,"shutdown failed",errbuf); + } + tpPrevious.PrivilegeCount = 1; + tpPrevious.Privileges[0].Luid = luid; + tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(hToken,FALSE,&tpPrevious,cbPrevious,NULL, + NULL)){ + make_err_str(GetLastError(),errbuf,128); + stderror(ERR_SYSTEM,"shutdown failed",errbuf); + } + if ( !ExitWindowsEx(flags,0) ) { + make_err_str(GetLastError(),errbuf,128); + stderror(ERR_SYSTEM,"shutdown failed",errbuf); + } + cleanup_until((Char **)v); +} diff --git a/win32/signal.c b/win32/signal.c new file mode 100644 index 000000000000..facede8c40f0 --- /dev/null +++ b/win32/signal.c @@ -0,0 +1,728 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/signal.c,v 1.12 2010/05/13 22:04:17 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * signal.c: Signal emulation hacks. + * -amol + * + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <errno.h> +#include <stdlib.h> +#include "ntport.h" +#include "forkdata.h" +#include "signal.h" + +#pragma warning(disable:4055) + +#define SIGBAD(signo) ( (signo) <=0 || (signo) >=NSIG) +#define fast_sigmember(a,b) ( (*(a) & (1 << (b-1)) ) ) +#define inc_pending(a) (gPending[(a)]+=1) + +#define suspend_main_thread() SuspendThread(hmainthr) +#define resume_main_thread() ResumeThread(hmainthr) + +int generic_handler(DWORD); +int ctrl_handler(DWORD); + +typedef struct _child_list { + DWORD dwProcessId; + DWORD exitcode; + struct _child_list *next; +}ChildListNode; + +Sigfunc *handlers[NSIG]={0}; +static unsigned long gPending[NSIG]={0}; +static unsigned long gBlockMask = 0; + +static ChildListNode *clist_h; //head of list +static ChildListNode *clist_t; // tail of list + +static CRITICAL_SECTION sigcritter; +static HANDLE hmainthr; +static HANDLE hsigsusp; +static int __is_suspended = 0; +static HANDLE __halarm=0; + +extern HANDLE __h_con_alarm,__h_con_int, __h_con_hup; + +// must be done before fork; +void nt_init_signals(void) { + + SetConsoleCtrlHandler((PHANDLER_ROUTINE)ctrl_handler,TRUE); + InitializeCriticalSection(&sigcritter); + + clist_t = clist_h = NULL; + + + if (!DuplicateHandle(GetCurrentProcess(), + GetCurrentThread(), + GetCurrentProcess(), + &hmainthr, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)){ + ExitProcess(GetLastError()); + } + hsigsusp = CreateEvent(NULL,FALSE,FALSE,NULL); + __h_con_alarm=CreateEvent(NULL,FALSE,FALSE,NULL); + __h_con_int=CreateEvent(NULL,FALSE,FALSE,NULL); + __h_con_hup=CreateEvent(NULL,FALSE,FALSE,NULL); + if (!hsigsusp) + abort(); + +} +void nt_cleanup_signals(void) { + if (__forked) + return; + DeleteCriticalSection(&sigcritter); + CloseHandle(hmainthr); + CloseHandle(hsigsusp); + CloseHandle(__h_con_alarm); + CloseHandle(__h_con_int); + CloseHandle(__h_con_hup); + CloseHandle(__halarm); +} +int sigaddset(sigset_t *set, int signo) { + + if (SIGBAD(signo)) { + errno = EINVAL; + return -1; + } + *set |= 1 << (signo-1); + return 0; +} +int sigdelset(sigset_t *set, int signo) { + if (SIGBAD(signo)) { + errno = EINVAL; + return -1; + } + *set &= ~( 1 << (signo-1)); + + return 0; + +} +int sigismember(const sigset_t *set, int signo) { + if (SIGBAD(signo)) { + errno = EINVAL; + return -1; + } + + return ( (*set & (1 <<(signo-1)) ) != 0); + +} +void deliver_pending(void) { + unsigned long temp; + int sig=1; + + temp = ~gBlockMask; + while(temp && (sig < NSIG)) { + + if (temp & 0x01){ + if (gPending[sig]){ + //gPending[sig]=0; + do { + dprintf("deliver_pending for sig %d\n",sig); + gPending[sig]--; + generic_handler(sig); + }while(gPending[sig] != 0); + } + } + temp >>= 1; + sig++; + } +} +int sigprocmask(int how, const sigset_t *set, sigset_t*oset) { + + if (oset) + *oset = gBlockMask; + if (set) { + switch (how) { + case SIG_BLOCK: + gBlockMask |= *set; + break; + case SIG_UNBLOCK: + gBlockMask &= (~(*set)); + break; + case SIG_SETMASK: + gBlockMask = *set; + break; + default: + break; + } + } + if (how != SIG_BLOCK) + deliver_pending(); + + return 0; + +} +int sigsuspend(const sigset_t *mask) { + sigset_t omask; + + + EnterCriticalSection(&sigcritter); + __is_suspended++; + LeaveCriticalSection(&sigcritter); + + sigprocmask(SIG_SETMASK,mask,&omask); + + dprintf("suspending main thread susp count %d\n",__is_suspended); + do { + WaitForSingleObject(hsigsusp,INFINITE); + }while(__is_suspended > 0); + + + sigprocmask(SIG_SETMASK,&omask,0); + errno = EINTR; + return -1; + +} + +int sigaction(int signo, const struct sigaction *act, struct sigaction *oact) { + + if (SIGBAD(signo)) { + errno = EINVAL; + return -1; + } + + if(oact){ + oact->sa_handler = handlers[signo]; + oact->sa_mask = 0; + oact->sa_flags =0; + } + if ((signo == SIGHUP) && (act && (act->sa_handler == SIG_IGN)) + && __forked) + __nt_child_nohupped = 1; + if (act) + handlers[signo]=act->sa_handler; + + return 0; + +} +int ctrl_handler(DWORD event) { + + if (event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT) { + SetEvent(__h_con_int); + return TRUE; + } + if (event == CTRL_CLOSE_EVENT) { + SetEvent(__h_con_hup); + return TRUE; + } + + return generic_handler(event+1); +} +int generic_handler(DWORD signo) { + + int blocked=0; + + if (SIGBAD(signo) ) + return FALSE; + switch (signo) { + case SIGINT: + if (handlers[signo] != SIG_IGN){ + if (fast_sigmember(&gBlockMask,signo) ) { + inc_pending(signo); + blocked=1; + } + else if (handlers[signo] == SIG_DFL) + ExitProcess(0xC000013AL); + else + handlers[signo](signo); + } + break; + case SIGBREAK: + if (handlers[signo] != SIG_IGN){ + if (fast_sigmember(&gBlockMask,signo) ) { + inc_pending(signo); + blocked=1; + } + else if (handlers[signo] == SIG_DFL) + ExitProcess(0xC000013AL); + else + handlers[signo](signo); + } + break; + case SIGHUP: //CTRL_CLOSE_EVENT + if (handlers[signo] != SIG_IGN){ + if (fast_sigmember(&gBlockMask,signo) ) { + inc_pending(signo); + blocked=1; + } + else if (handlers[signo] == SIG_DFL) + ExitProcess(604); + else + handlers[signo](signo); + } + break; + case SIGTERM: //CTRL_LOGOFF_EVENT + if (handlers[signo] != SIG_IGN){ + if (fast_sigmember(&gBlockMask,signo) ) { + inc_pending(signo); + blocked=1; + } + else if (handlers[signo] == SIG_DFL) + ExitProcess(604); + else + handlers[signo](signo); + } + else + ExitProcess(604); + break; + case SIGKILL: //CTRL_SHUTDOWN_EVENT + if (handlers[signo] != SIG_IGN){ + if (fast_sigmember(&gBlockMask,signo) ) { + inc_pending(signo); + blocked=1; + } + else if (handlers[signo] == SIG_DFL) + ExitProcess(604); + else + handlers[signo](signo); + } + else + ExitProcess(604); + break; + case SIGALRM: + if (handlers[signo] != SIG_IGN){ + if (fast_sigmember(&gBlockMask,signo) ) { + inc_pending(signo); + blocked=1; + } + else if (handlers[signo] == SIG_DFL) + ExitProcess(604); + else + handlers[signo](signo); + } + break; + case SIGCHLD: + if (handlers[signo] != SIG_IGN){ + if (fast_sigmember(&gBlockMask,signo) ) { + dprintf("inc pending for sig %d count %d\n",signo, + gPending[signo]); + inc_pending(signo); + blocked=1; + } + else if (handlers[signo] != SIG_DFL) + handlers[signo](signo); + } + break; + default: + ExitProcess(604); + break; + } + if (!blocked && __is_suspended) { + EnterCriticalSection(&sigcritter); + __is_suspended--; + LeaveCriticalSection(&sigcritter); + dprintf("releasing suspension is_suspsend = %d\n",__is_suspended); + SetEvent(hsigsusp); + } + return TRUE; +} +Sigfunc *_nt_signal(int signal, Sigfunc * handler) { + + Sigfunc *old; + + if (SIGBAD(signal)) { + errno = EINVAL; + return SIG_ERR; + } + if (signal == SIGHUP && handler == SIG_IGN && __forked) { + __nt_child_nohupped = 1; + } + + + old = handlers[signal]; + handlers[signal] = handler; + + + return old; +} +int waitpid(pid_t pid, int *statloc, int options) { + + ChildListNode *temp; + int retcode; + + UNREFERENCED_PARAMETER(options); + errno = EINVAL; + if (pid != -1) + return -1; + + EnterCriticalSection(&sigcritter); + if (!clist_h) + retcode =0; + else { + retcode = clist_h->dwProcessId; + if (statloc) *statloc = clist_h->exitcode; + temp = clist_h; + clist_h = clist_h->next; + heap_free(temp); + } + LeaveCriticalSection(&sigcritter); + + errno = 0; + return retcode; + +} +unsigned int __alarm_set=0; + +void CALLBACK alarm_callback( unsigned long interval) { + + int rc; + + rc = WaitForSingleObject(__halarm,interval*1000); + if (rc != WAIT_TIMEOUT) + return ; + + SetEvent(__h_con_alarm); + __alarm_set = 0; + return; + + // consoleread() now waits for above event, and calls generic_handler to + // handle SIGALRM in the main thread. That helps me avoid + // problems with fork() when we are in a secondary thread. + // + // This means sched, periodic etc will not be signalled unless consoleread + // is called, but that's a reasonable risk, i think. + // -amol 4/10/97 + +} +unsigned int alarm(unsigned int seconds) { + + unsigned int temp; + static unsigned int prev_val=0; + HANDLE ht; + DWORD tid; + SECURITY_ATTRIBUTES secd; + + secd.nLength=sizeof(secd); + secd.lpSecurityDescriptor=NULL; + secd.bInheritHandle=TRUE; + + + if (!__halarm) { + __halarm=CreateEvent(&secd,FALSE,FALSE,NULL); + } + if(__alarm_set ) + SetEvent(__halarm); + + if (!seconds){ + __alarm_set=0; + return 0; + } + __alarm_set = 1; + + ht = CreateThread(NULL,gdwStackSize, + (LPTHREAD_START_ROUTINE)alarm_callback, + (void*)UIntToPtr(seconds), + 0,&tid); + if (ht) + CloseHandle(ht); + + temp = prev_val; + prev_val = seconds*1000; + + return temp; +} +void add_to_child_list(DWORD dwpid,DWORD exitcode) { + if (clist_h == NULL) { + clist_h = heap_alloc(sizeof(ChildListNode)); + if (!clist_h) + goto end; + clist_h->dwProcessId = dwpid; + clist_h->exitcode = exitcode; + clist_h->next= NULL; + clist_t = clist_h; + } + else { + clist_t->next = heap_alloc(sizeof(ChildListNode)); + if (!clist_t->next) + goto end; + clist_t = clist_t->next; + clist_t->dwProcessId= dwpid; + clist_h->exitcode = exitcode; + clist_t->next = NULL; + } +end: + ; +} +void sig_child_callback(DWORD pid,DWORD exitcode) { + + DWORD ecode = 0; + + EnterCriticalSection(&sigcritter); + add_to_child_list(pid,exitcode); + suspend_main_thread(); + // + // pchild() tries to reset(), which crashes the thread + // + __try { + generic_handler(SIGCHLD); + } + __except(ecode = GetExceptionCode()) { + ; + } + resume_main_thread(); + LeaveCriticalSection(&sigcritter); + +} +struct thread_args { + DWORD pid; + HANDLE hproc; +}; +void sigchild_thread(struct thread_args *args) { + + DWORD exitcode=0; + WaitForSingleObject(args->hproc,INFINITE); + GetExitCodeProcess(args->hproc,&exitcode); + CloseHandle(args->hproc); + sig_child_callback(args->pid,exitcode); + dprintf("exiting sigchild thread for pid %d\n",args->pid); + heap_free(args); +} +void start_sigchild_thread(HANDLE hproc, DWORD pid) { + + struct thread_args *args=heap_alloc(sizeof(struct thread_args)); + DWORD tid; + HANDLE hthr; + args->hproc = hproc; + args->pid = pid; + + dprintf("creating sigchild thread for pid %d\n",pid); + hthr = CreateThread(NULL, + gdwStackSize, + (LPTHREAD_START_ROUTINE)sigchild_thread, + (LPVOID)args, + 0, + &tid); + + + CloseHandle(hthr); + +} +int kill(int pid, int sig) { + + HANDLE hproc; + int ret =0; + extern DWORD gdwPlatform; + BOOL is_winnt = TRUE; + + errno = EPERM; + is_winnt = (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS); + + if(is_winnt) { + if(pid < 0) + { + if (pid == -1) + return -1; + pid = -pid; //no groups that we can actually do anything with. + + } + } + else { //win9x has -ve pids + if(pid > 0) + { + if (pid == 1) + return -1; + pid = -pid; //no groups that we can actually do anything with. + + } + } + + + switch(sig) { + case 0: + case 7: + hproc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid); + if (hproc == NULL) { + errno = ESRCH; + ret = -1; + dprintf("proc %d not found\n",pid); + } + else{ + dprintf("proc %d found\n",pid); + } + if (sig == 7) { + if (!TerminateProcess(hproc,0xC000013AL) ) { + ret = -1; + } + } + CloseHandle(hproc); + break; + case 1: + if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT,pid)) + ret = -1; + break; + case 2: + if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,pid)) + ret = -1; + break; + case 3: + if (kill_by_wm_close(pid) <0 ) { + errno = ESRCH; + ret = -1; + } + default: + break; + } + return ret; +} +// +// nice(niceness) +// +// where niceness is an integer in the range -6 to +7 +// +// A usual foreground process starts at level 9 in the chart below +// +// the range -6 to +7 takes it from Base priority 15 down to 2. +// +// Note that level 1 or > 15 are not allowed. +// +// Priority Level 11 (niceness -2) or greater affects system performance, +// so use with care. +// +// niceness defaults to +4, which is lowest for background normal class. +// As in unix, +ve niceness indicates lower priorities. + +/*************************************************************************** +Niceness Base Priority class/thread priority + + 1 Idle, normal, or high class, THREAD_PRIORITY_IDLE + ++7 2 Idle class, THREAD_PRIORITY_LOWEST ++6 3 Idle class, THREAD_PRIORITY_BELOW_NORMAL ++5 4 Idle class, THREAD_PRIORITY_NORMAL ++4 5 Background normal class, THREAD_PRIORITY_LOWEST + Idle class, THREAD_PRIORITY_ABOVE_NORMAL ++3 6 Background normal class, THREAD_PRIORITY_BELOW_NORMAL + Idle class, THREAD_PRIORITY_HIGHEST ++2 7 Foreground normal class, THREAD_PRIORITY_LOWEST + Background normal class, THREAD_PRIORITY_NORMAL ++1 8 Foreground normal class, THREAD_PRIORITY_BELOW_NORMAL + Background normal class, THREAD_PRIORITY_ABOVE_NORMAL + 0 9 Foreground normal class, THREAD_PRIORITY_NORMAL + Background normal class, THREAD_PRIORITY_HIGHEST +-1 10 Foreground normal class, THREAD_PRIORITY_ABOVE_NORMAL +-2 11 High class, THREAD_PRIORITY_LOWEST + Foreground normal class, THREAD_PRIORITY_HIGHEST +-3 12 High class, THREAD_PRIORITY_BELOW_NORMAL +-4 13 High class, THREAD_PRIORITY_NORMAL +-5 14 High class, THREAD_PRIORITY_ABOVE_NORMAL +-6 15 Idle, normal, or high class, THREAD_PRIORITY_TIME_CRITICAL + High class, THREAD_PRIORITY_HIGHEST + + + 16 Real-time class, THREAD_PRIORITY_IDLE + 22 Real-time class, THREAD_PRIORITY_LOWEST + 23 Real-time class, THREAD_PRIORITY_BELOW_NORMAL + 24 Real-time class, THREAD_PRIORITY_NORMAL + 25 Real-time class, THREAD_PRIORITY_ABOVE_NORMAL + 26 Real-time class, THREAD_PRIORITY_HIGHEST + 31 Real-time class, THREAD_PRIORITY_TIME_CRITICAL +****************************************************************************/ +int nice(int niceness) { + + DWORD pclass = IDLE_PRIORITY_CLASS; + int priority = THREAD_PRIORITY_NORMAL; + + if (niceness < -6 || niceness > 7) { + errno = EPERM; + return -1; + } + switch (niceness) { + case 7: + pclass = IDLE_PRIORITY_CLASS; + priority = THREAD_PRIORITY_LOWEST; + break; + case 6: + pclass = IDLE_PRIORITY_CLASS; + priority = THREAD_PRIORITY_BELOW_NORMAL; + break; + case 5: + pclass = IDLE_PRIORITY_CLASS; + priority = THREAD_PRIORITY_NORMAL; + break; + case 4: + pclass = IDLE_PRIORITY_CLASS; + priority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case 3: + pclass = IDLE_PRIORITY_CLASS; + priority = THREAD_PRIORITY_HIGHEST; + break; + case 2: + pclass = NORMAL_PRIORITY_CLASS; + priority = THREAD_PRIORITY_LOWEST; + break; + case 1: + pclass = NORMAL_PRIORITY_CLASS; + priority = THREAD_PRIORITY_BELOW_NORMAL; + break; + case (-1): + pclass = NORMAL_PRIORITY_CLASS; + priority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case (-2): + pclass = NORMAL_PRIORITY_CLASS; + priority = THREAD_PRIORITY_HIGHEST; + break; + case (-3): + pclass = HIGH_PRIORITY_CLASS; + priority = THREAD_PRIORITY_BELOW_NORMAL; + break; + case (-4): + pclass = HIGH_PRIORITY_CLASS; + priority = THREAD_PRIORITY_NORMAL; + break; + case (-5): + pclass = HIGH_PRIORITY_CLASS; + priority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case (-6): + pclass = HIGH_PRIORITY_CLASS; + priority = THREAD_PRIORITY_HIGHEST; + break; + default: + break; + } + + if (!SetPriorityClass(GetCurrentProcess(),pclass)){ + errno = EPERM; + return -1; + } + if (!SetThreadPriority(GetCurrentThread(),priority)){ + errno = EPERM; + return -1; + } + return -1; +} diff --git a/win32/signal.h b/win32/signal.h new file mode 100644 index 000000000000..ba7f1b49b7d4 --- /dev/null +++ b/win32/signal.h @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +// signal.h: signal emulation things +// -amol +// +#ifndef SIGNAL_H +#define SIGNAL_H + + +#define NSIG 23 + +// These must be CTRL_xxx_EVENT+1 (in wincon.h) +// +#define SIGINT 1 +#define SIGBREAK 2 +#define SIGHUP 3 //CTRL_CLOSE_EVENT +// 3 and 4 are reserved. hence we can't use 4 and 5 +#define SIGTERM 6 // ctrl_logoff +#define SIGKILL 7 // ctrl_shutdown + +#define SIGILL 8 +#define SIGFPE 9 +#define SIGALRM 10 +//#define SIGWINCH 11 +#define SIGSEGV 12 +#define SIGSTOP 13 +#define SIGPIPE 14 +#define SIGCHLD 15 +#define SIGCONT 16 +#define SIGTSTP 18 +#define SIGTTOU 19 +#define SIGTTIN 20 +#define SIGABRT 22 + +#define SIGQUIT SIGBREAK + +/* signal action codes */ + +#define SIG_DFL (void (*)(int))IntToPtr(0) /* default signal action */ +#define SIG_IGN (void (*)(int))IntToPtr(1) /* ignore signal */ +#define SIG_SGE (void (*)(int))IntToPtr(3) /* signal gets error */ +#define SIG_ACK (void (*)(int))IntToPtr(4) /* acknowledge */ + + +/* signal error value (returned by signal call on error) */ + +#define SIG_ERR (void (*)(int))IntToPtr(-1) /* signal error value */ + + +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 + +#undef signal +#define signal _nt_signal + +typedef unsigned long sigset_t; +typedef void Sigfunc (int); + +struct sigaction { + Sigfunc *sa_handler; + sigset_t sa_mask; + int sa_flags; +}; + + +#define sigemptyset(ptr) (*(ptr) = 0) +#define sigfillset(ptr) ( *(ptr) = ~(sigset_t)0,0) + + +/* Function prototypes */ + +void (* _nt_signal(int, void (*)(int)))(int); + +int sigaddset(sigset_t*, int); +int sigdelset(sigset_t*,int); +unsigned int alarm(unsigned int); + +int sigismember(const sigset_t *set, int); +int sigprocmask(int ,const sigset_t*,sigset_t*); +int sigaction(int, const struct sigaction *, struct sigaction*); +int sigsuspend(const sigset_t *sigmask); + +#define WNOHANG 0 +#define WUNTRACED 1 + +#define WIFEXITED(a) 1 +#define WEXITSTATUS(a) (a) +//#define WIFSIGNALED(a) ((a!= -1)&&(((((unsigned long)(a)) >>24) & 0xC0)!=0)) +#define WIFSIGNALED(a) ((a !=-1)&&((((unsigned long)(a)) & 0xC0000000 ) != 0)) +#define WTERMSIG(a) (((unsigned long)(a))==0xC000013AL?SIGINT:SIGSEGV) +#define WCOREDUMP(a) 0 +#define WIFSTOPPED(a) 0 +#define WSTOPSIG(a) 0 + +int waitpid(pid_t, int*,int); +int times(struct tms*); + +#endif SIGNAL_H diff --git a/win32/stdio.c b/win32/stdio.c new file mode 100644 index 000000000000..2fa3fc66869a --- /dev/null +++ b/win32/stdio.c @@ -0,0 +1,628 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/stdio.c,v 1.10 2010/05/27 04:00:23 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * stdio.c Implement a whole load of i/o functions. + * This makes it much easier to keep track of inherited handles and + * also makes us reasonably vendor crt-independent. + * -amol + * + */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#define STDIO_C +#include <ntport.h> +#include <forkdata.h> + + +#define __MAX_OPEN_FILES 64 + +#define FIOCLEX 1 +#define FCONSOLE 2 + +typedef struct _myfile { + HANDLE handle; + unsigned long flags; +} MY_FILE; + +typedef unsigned long u_long; + +#define INVHL (INVALID_HANDLE_VALUE) + +MY_FILE __gOpenFiles[__MAX_OPEN_FILES]={0}; +MY_FILE __gOpenFilesCopy[__MAX_OPEN_FILES]={0}; + +MY_FILE *my_stdin=0, *my_stdout=0, *my_stderr=0; + +extern int didfds; +int __dup_stdin = 0; + + +void init_stdio(void) { + + int i; + __gOpenFiles[0].handle = GetStdHandle(STD_INPUT_HANDLE); + __gOpenFiles[1].handle = GetStdHandle(STD_OUTPUT_HANDLE); + __gOpenFiles[2].handle = GetStdHandle(STD_ERROR_HANDLE); + + __gOpenFiles[0].flags = (GetFileType(ULongToPtr(STD_INPUT_HANDLE))== + FILE_TYPE_CHAR)? FCONSOLE:0; + __gOpenFiles[1].flags = (GetFileType(ULongToPtr(STD_OUTPUT_HANDLE))== + FILE_TYPE_CHAR)? FCONSOLE:0; + __gOpenFiles[2].flags = (GetFileType(ULongToPtr(STD_ERROR_HANDLE))== + FILE_TYPE_CHAR)? FCONSOLE:0; + + for(i=3;i<__MAX_OPEN_FILES;i++) { + __gOpenFiles[i].handle = INVHL; + __gOpenFilesCopy[i].handle = INVHL; + __gOpenFiles[i].flags = 0; + } + + my_stdin = &__gOpenFiles[0]; + my_stdout = &__gOpenFiles[1]; + my_stderr = &__gOpenFiles[2]; +} + + void nt_close_on_exec(int fd, int on) { + if(on) + __gOpenFiles[fd].flags |= FIOCLEX; + else + __gOpenFiles[fd].flags &= ~FIOCLEX; + } +void restore_fds(void ) { + int i; + int min=3; + + if (__forked && (didfds|| __dup_stdin)) + min =0; + // + // ok for tcsh. see fork.c for why + // + __gOpenFiles[0].handle = INVHL; + __gOpenFiles[1].handle = INVHL; + __gOpenFiles[2].handle = INVHL; + my_stdin = &__gOpenFiles[0]; + my_stdout = &__gOpenFiles[1]; + my_stderr = &__gOpenFiles[2]; + for(i=min;i<__MAX_OPEN_FILES;i++) { + if (__gOpenFilesCopy[i].handle == INVHL) + continue; + __gOpenFiles[i].handle = __gOpenFilesCopy[i].handle ; + __gOpenFiles[i].flags = __gOpenFilesCopy[i].flags ; + } +} +void close_copied_fds(void ) { + int i; + int min=3; + if (didfds|| __dup_stdin) + min =0; + for(i=min;i<__MAX_OPEN_FILES;i++) { + if (__gOpenFilesCopy[i].handle == INVHL) + continue; + CloseHandle((HANDLE)__gOpenFilesCopy[i].handle); + __gOpenFilesCopy[i].handle = INVHL; + } + __dup_stdin=0; +} +void copy_fds(void ) { + int i; + int min=3; + if (didfds || __dup_stdin) + min =0; + for(i=min;i<__MAX_OPEN_FILES;i++) { + if (__gOpenFiles[i].handle == INVHL) { + __gOpenFilesCopy[i].handle = INVHL; + continue; + } + + if(!DuplicateHandle(GetCurrentProcess(), + (HANDLE)__gOpenFiles[i].handle , + GetCurrentProcess(), + (HANDLE*)&__gOpenFilesCopy[i].handle, + 0, TRUE, DUPLICATE_SAME_ACCESS) ) + __gOpenFilesCopy[i].handle = INVHL; + __gOpenFilesCopy[i].flags = __gOpenFiles[i].flags; + } +} +intptr_t __nt_get_osfhandle(int fd) { + return (intptr_t)(__gOpenFiles[fd].handle); +} +int __nt_open_osfhandle(intptr_t h1, int mode) { + int i; + + UNREFERENCED_PARAMETER(mode); + + for(i=0;i<__MAX_OPEN_FILES;i++) { + if (__gOpenFiles[i].handle == INVHL) { + __gOpenFiles[i].handle = (HANDLE)h1; + __gOpenFiles[i].flags = 0; + return i; + } + } + errno = EMFILE; + return -1; +} +int nt_close(int fd) { + + if( (fd == -1) ||(__gOpenFiles[fd].handle == INVHL)) + return 0; + CloseHandle((HANDLE)(__gOpenFiles[fd].handle)); + __gOpenFiles[fd].handle = INVHL; + __gOpenFiles[fd].flags = 0; + + // dprintf("closing 0x%08x\n",(__gOpenFiles[fd].handle)); + return 0; +} +int nt_access(char *filename, int mode) { + + DWORD attribs=(DWORD)-1, bintype; + int tries=0; + char buf[512];/*FIXBUF*/ + + if (!filename) { + errno = ENOENT; + return -1; + } + (void)StringCbPrintf(buf,sizeof(buf),"%s",filename); +retry: + attribs = GetFileAttributes(buf); + tries++; + + if (attribs == (DWORD) -1) { + if( (GetLastError() == ERROR_FILE_NOT_FOUND) && (mode & X_OK) ) { + switch(tries){ + case 1: + (void)StringCbPrintf(buf,sizeof(buf),"%s.exe",filename); + break; + case 2: + (void)StringCbPrintf(buf,sizeof(buf),"%s.cmd",filename); + break; + case 3: + (void)StringCbPrintf(buf,sizeof(buf),"%s.bat",filename); + break; + case 4: + (void)StringCbPrintf(buf,sizeof(buf),"%s.com",filename); + break; + default: + goto giveup; + break; + } + goto retry; + } + } +giveup: + if (attribs == (DWORD)-1 ) { + errno = EACCES; + return -1; + } + if ( (mode & W_OK) && (attribs & FILE_ATTRIBUTE_READONLY) ) { + errno = EACCES; + return -1; + } + if (mode & X_OK) { + if ((mode & XD_OK) && (attribs & FILE_ATTRIBUTE_DIRECTORY) ){ + errno = EACCES; + return -1; + } + if ((!(attribs & FILE_ATTRIBUTE_DIRECTORY)) && + !GetBinaryType(buf,&bintype) &&(tries >4) ) { + errno = EACCES; + return -1; + } + } + return 0; +} +int nt_seek(HANDLE h1, long offset, int how) { + DWORD dwmove; + + switch(how) { + case SEEK_CUR: + dwmove = FILE_CURRENT; + break; + case SEEK_END: + dwmove = FILE_END; + break; + case SEEK_SET: + dwmove = FILE_BEGIN; + break; + default: + errno = EINVAL; + return -1; + } + + if (SetFilePointer(h1,offset,NULL,dwmove) == -1){ + errno = EBADF; + return -1; + } + return 0; +} +int nt_lseek(int fd,long offset, int how) { + HANDLE h1 ; + h1 =__gOpenFiles[fd].handle; + return nt_seek(h1,offset,how); +} +int nt_isatty(int fd) { + return (__gOpenFiles[fd].flags & FCONSOLE); +} +int nt_dup(int fdin) { + + HANDLE hdup; + HANDLE horig = __gOpenFiles[fdin].handle; + int ret; + + + if (!DuplicateHandle(GetCurrentProcess(), + horig, + GetCurrentProcess(), + &hdup, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + errno = GetLastError(); + errno = EBADF; + return -1; + } + ret = __nt_open_osfhandle((intptr_t)hdup,_O_BINARY | _O_NOINHERIT); + + __gOpenFiles[ret].flags = __gOpenFiles[fdin].flags; + + return ret; +} +int nt_dup2(int fdorig,int fdcopy) { + + HANDLE hdup; + HANDLE horig = __gOpenFiles[fdorig].handle; + + + if (__gOpenFiles[fdcopy].handle != INVHL) { + CloseHandle((HANDLE)__gOpenFiles[fdcopy].handle ); + __gOpenFiles[fdcopy].handle = INVHL; + __gOpenFiles[fdcopy].flags = 0; + } + if (!DuplicateHandle(GetCurrentProcess(), + horig, + GetCurrentProcess(), + &hdup, + 0, + fdcopy<3?TRUE:FALSE, DUPLICATE_SAME_ACCESS)) { + errno = GetLastError(); + errno = EBADF; + return -1; + } + __gOpenFiles[fdcopy].handle = hdup; + __gOpenFiles[fdcopy].flags = __gOpenFiles[fdorig].flags; + switch(fdcopy) { + case 0: + SetStdHandle(STD_INPUT_HANDLE,hdup); + break; + case 1: + SetStdHandle(STD_OUTPUT_HANDLE,hdup); + break; + case 2: + SetStdHandle(STD_ERROR_HANDLE,hdup); + break; + default: + break; + } + + return 0; +} +int nt_pipe2(HANDLE hpipe[2]) { + + SECURITY_ATTRIBUTES secd; + + secd.nLength=sizeof(secd); + secd.lpSecurityDescriptor=NULL; + secd.bInheritHandle=FALSE; + + return (!CreatePipe(&hpipe[0],&hpipe[1],&secd,0)); +} +int nt_pipe(int hpipe[2]) { + HANDLE hpipe2[2]; + + nt_pipe2(hpipe2); + hpipe[0] = __nt_open_osfhandle((intptr_t)hpipe2[0],O_NOINHERIT); + hpipe[1] = __nt_open_osfhandle((intptr_t)hpipe2[1],O_NOINHERIT); + return 0; +} +/* check if name is //server. if checkifShare is set, + * also check if //server/share + */ +int is_server(const char *name,int checkifShare) { + const char *p1, *p2; + + if (!*name || !*(name+1)) + return 0; + + p1 = name; + if (((p1[0] != '/') && (p1[0] != '\\') ) || + ((p1[1] != '/') && (p1[1] != '\\') )) + return 0; + + p2 = p1 + 2; + while (*p2 && *p2 != '/' && *p2 != '\\') +#ifdef DSPMBYTE + if (Ismbyte1(*p2) && *(p2 + 1)) + p2 += 2; + else +#endif /* DSPMBYTE */ + p2++; + + /* just check for server */ + if (!checkifShare) { + /* null terminated unc server name */ + /* terminating '/' (//server/) is also ok */ + if (!*p2 || !*(p2+1)) + return 1; + + } + else { + if (!*p2 || !*(p2+1)) + return 0; + p2++; + while(*p2 && *p2 != '/' && *p2 != '\\') + p2++; + if (!*p2 || !*(p2+1)) + return 1; + } + return 0; + +} +__inline int is_unc(char *filename) { + if (*filename && (*filename == '/' || *filename == '\\') + && *(filename+1) + && (*(filename+1) == '/' || *(filename+1) == '\\')) { + return 1; + } + return 0; +} +int nt_stat(const char *filename, struct stat *stbuf) { + + // stat hangs on server name + // Use any directory, since the info in stat means %$!* on + // windows anyway. + // -amol 5/28/97 + /* is server or share */ + if (is_server(filename,0) || is_server(filename,1) || + (*(filename+1) && *(filename+1) == ':' && !*(filename+2)) ) { + return _stat("C:/",(struct _stat *)stbuf); + } + else { + char *last = (char*)filename + strlen(filename) -1; + int rc = 0; + BOOL lastslash = (*last == '/'); + if(lastslash) + { + *last = 0; + } + rc = _stat(filename,(struct _stat *)stbuf); + if(lastslash) + { + *last = '/'; + } + return rc; + } +} +// +// replacement for creat that makes handle non-inheritable. +// -amol +// +int nt_creat(const char *filename, int mode) { + // ignore the bloody mode + + int fd = 0,is_cons =0; + HANDLE retval; + SECURITY_ATTRIBUTES security; + + UNREFERENCED_PARAMETER(mode); + + + security.nLength = sizeof(security); + security.lpSecurityDescriptor = NULL; + security.bInheritHandle = FALSE; + + if (!_stricmp(filename,"/dev/tty") ){ + filename = "CONOUT$"; + is_cons = 1; + } + else if (!_stricmp(filename,"/dev/null") ){ + filename = "NUL"; + } + else if (!_stricmp(filename,"/dev/clipboard")) { + retval = create_clip_writer_thread(); + if (retval == INVHL) + return -1; + goto get_fd; + } + retval = CreateFile(filename, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + is_cons?NULL:&security, + CREATE_ALWAYS, + 0, + NULL); + + if (retval == INVALID_HANDLE_VALUE) { + errno = EACCES; + return -1; + } +get_fd: + fd = __nt_open_osfhandle((intptr_t)retval,_O_BINARY); + if (fd <0) { + //should never happen + abort(); + } + else { + if (is_cons) { + __gOpenFiles[fd].flags = FCONSOLE; + } + } + return fd; + +} +int nt_open(const char *filename, int perms,...) { + + // ignore the bloody mode + + int fd,mode, is_cons=0; + HANDLE retval; + SECURITY_ATTRIBUTES security; + DWORD dwAccess, dwFlags, dwCreateDist; + va_list ap; + + va_start(ap,perms); + mode = va_arg(ap,int); + va_end(ap); + + if (!lstrcmp(filename,"/dev/tty") ){ + if (perms == O_RDONLY) //o_rdonly is 0 + filename = "CONIN$"; + else if (perms & O_WRONLY) + filename = "CONOUT$"; + is_cons = 1; + } + else if (!lstrcmp(filename,"/dev/null") ){ + filename = "NUL"; + } + else if (!_stricmp(filename,"/dev/clipboard")) { + retval = create_clip_reader_thread(); + goto get_fd; + } + security.nLength = sizeof(security); + security.lpSecurityDescriptor = NULL; + security.bInheritHandle = FALSE; + + switch (perms & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) { + case _O_RDONLY: + dwAccess = GENERIC_READ; + break; + case _O_WRONLY: + dwAccess = GENERIC_WRITE; + break; + case _O_RDWR: + dwAccess = GENERIC_READ | GENERIC_WRITE ; + break; + default: + errno = EINVAL; + return -1; + } + switch (perms & (_O_CREAT | _O_TRUNC) ){ + case 0: + dwCreateDist = OPEN_EXISTING; + break; + case _O_CREAT: + dwCreateDist = CREATE_ALWAYS; + break; + case _O_CREAT | _O_TRUNC: + dwCreateDist = CREATE_ALWAYS; + break; + case _O_TRUNC: + dwCreateDist = TRUNCATE_EXISTING; + break; + default: + errno = EINVAL; + return -1; + } + dwFlags = 0; + if (perms & O_TEMPORARY) + dwFlags = FILE_FLAG_DELETE_ON_CLOSE; + retval = CreateFile(filename, + dwAccess,//GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &security, + dwCreateDist,//CREATE_ALWAYS, + dwFlags, + NULL); + + if (retval == INVALID_HANDLE_VALUE) { + int err = GetLastError(); + if (err == ERROR_FILE_NOT_FOUND) + errno = ENOENT; + else + errno = EACCES; + return -1; + } + if (perms & O_APPEND) { + SetFilePointer(retval,0,NULL,FILE_END); + } +get_fd: + fd = __nt_open_osfhandle((intptr_t)retval,_O_BINARY); + if (fd <0) { + //should never happen + abort(); + } + else { + if (is_cons) { + __gOpenFiles[fd].flags = FCONSOLE; + } + } + return fd; + +} +/* + * This should be the LAST FUNCTION IN THIS FILE + * + */ +#undef fstat +#undef _open_osfhandle +#undef close +int nt_fstat(int fd, struct stat *stbuf) { + int realfd; + HANDLE h1; + + errno = EBADF; + + if(!DuplicateHandle(GetCurrentProcess(), + (HANDLE)__gOpenFiles[fd].handle, + GetCurrentProcess(), + &h1, + 0, + FALSE, + DUPLICATE_SAME_ACCESS) ) + return -1; + realfd = _open_osfhandle((intptr_t)h1,0); + if (realfd <0 ) + return -1; + + if( fstat(realfd,stbuf) <0 ) { + _close(realfd); + return -1; + } + _close(realfd); + errno =0; + return 0; + +} + diff --git a/win32/support.c b/win32/support.c new file mode 100644 index 000000000000..dd3c117af693 --- /dev/null +++ b/win32/support.c @@ -0,0 +1,941 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/support.c,v 1.14 2008/08/31 14:09:01 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * support.c + * various routines to do exec, etc. + * + */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <wincon.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <locale.h> +#include "ntport.h" +#include "sh.err.h" +#include "sh.h" +#include "nt.const.h" + + +DWORD gdwPlatform,gdwVersion; +unsigned short __nt_really_exec = 0,__nt_child_nohupped =0; +DWORD gdwStackSize = 524288;//0.5 MB + +void path_slashify(char *pstr) { + while(*pstr) { +#ifdef DSPMBYTE + if (Ismbyte1(*pstr) && *(pstr + 1)) + pstr ++; + else +#endif /* DSPMBYTE */ + if (*pstr == '\\') + *pstr = '/'; + pstr++; + } +} + +void do_nothing(const wchar_t *p1, const wchar_t *p2, const wchar_t*p3, + unsigned int p4, uintptr_t p5) { + UNREFERENCED_PARAMETER(p1); + UNREFERENCED_PARAMETER(p2); + UNREFERENCED_PARAMETER(p3); + UNREFERENCED_PARAMETER(p4); + UNREFERENCED_PARAMETER(p5); +} +void nt_init(void) { + + +#ifdef SECURE_CD + { + char temp[512];/*FIXBUF*/ + extern char gcurr_drive; + if(!GetCurrentDirectory(512,temp)) + ExitProcess((DWORD)-1); + gcurr_drive=temp[0]; + } +#endif SECURE_CD + + _set_invalid_parameter_handler(do_nothing); + init_stdio(); + nt_init_signals(); + nt_term_init(); + init_hb_subst(); + setlocale(LC_ALL,""); + init_shell_dll(); + init_plister(); + fork_init(); + init_clipboard(); + return; +} +void nt_cleanup(void){ + nt_term_cleanup(); + nt_cleanup_signals(); + cleanup_netbios(); +} +void caseify_pwd(char *curwd) { + char *sp, *dp, p,*s; + WIN32_FIND_DATA fdata; + HANDLE hFind; + + if (gdwPlatform !=VER_PLATFORM_WIN32_NT) + return; + + if (*curwd == '\\' && (!curwd[1] || curwd[1] == '\\')) + return; + sp = curwd +3; + dp = curwd +3; + do { + p= *sp; + if (p && p != '\\'){ + sp++; + continue; + } + else { + *sp = 0; + hFind = FindFirstFile(curwd,&fdata); + *sp = p; + if (hFind != INVALID_HANDLE_VALUE) { + FindClose(hFind); + s = fdata.cFileName; + while(*s) { + *dp++ = *s++; + } + dp++; + sp = dp; + } + else { + sp++; + dp = sp; + } + } + sp++; + }while(p != 0); + +} +static char defcwd[MAX_PATH]; +char * forward_slash_get_cwd(char * path, size_t maxlen) { + + char *ptemp; + Char *vp; + int rc ; + + if ((path == NULL) || (maxlen == 0)) { + path = &defcwd[0]; + maxlen = MAX_PATH; + } + + rc = GetCurrentDirectory((DWORD)maxlen,path); + if (rc > maxlen) { + errno = ERANGE; + return NULL; + } + vp = varval(STRNTcaseifypwd); + if (vp != STRNULL) { + caseify_pwd(path); + } + ptemp=path; + + path_slashify(ptemp); + + return path; +} +void getmachine (void) { + + char temp[256]; + char *vendor, *ostype; + OSVERSIONINFO osver; + SYSTEM_INFO sysinfo; + + + memset(&osver,0,sizeof(osver)); + memset(&sysinfo,0,sizeof(sysinfo)); + vendor = "Microsoft"; + + tsetenv(STRVENDOR,str2short(vendor)); + + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + if (!GetVersionEx(&osver)) { + MessageBox(NULL,"GetVersionEx failed in getmachine", + "tcsh",MB_ICONHAND); + ExitProcess(0xFF); + } + GetSystemInfo(&sysinfo); + + if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { + char *ostr; + ostype = "WindowsNT"; + ostr = "Windows NT"; + + (void)StringCbPrintf(temp,sizeof(temp),"%s %d.%d Build %d (%s)", + ostr, + osver.dwMajorVersion,osver.dwMinorVersion, + osver.dwBuildNumber, + osver.szCSDVersion[0]?osver.szCSDVersion:""); + tsetenv(STRHOSTTYPE,str2short(temp)); + } + else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + ostype = "Windows9x"; + (void)StringCbPrintf(temp,sizeof(temp), + "Win9x %d.%d:%d",osver.dwMajorVersion,osver.dwMinorVersion, + LOWORD(osver.dwBuildNumber)); + tsetenv(STRHOSTTYPE,str2short(temp)); + } + else { + ostype = "WindowsWhoKnows"; + MessageBox(NULL,"Unknown platform","tcsh",MB_ICONHAND); + } + tsetenv(STROSTYPE,str2short(ostype)); + switch (sysinfo.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_INTEL: + if ( ( sysinfo.wProcessorLevel < 3) || + ( sysinfo.wProcessorLevel > 9) ) + sysinfo.wProcessorLevel = 3; + + (void)StringCbPrintf(temp,sizeof(temp), + "i%d86",sysinfo.wProcessorLevel); + break; + case PROCESSOR_ARCHITECTURE_ALPHA: + (void)StringCbPrintf(temp,sizeof(temp),"Alpha"); + break; + case PROCESSOR_ARCHITECTURE_MIPS: + (void)StringCbPrintf(temp,sizeof(temp),"Mips"); + break; + case PROCESSOR_ARCHITECTURE_PPC: + (void)StringCbPrintf(temp,sizeof(temp),"PPC"); + break; + case PROCESSOR_ARCHITECTURE_AMD64: + (void)StringCbPrintf(temp,sizeof(temp),"AMD64"); + break; + default: + (void)StringCbPrintf(temp,sizeof(temp),"Unknown"); + break; + } + tsetenv(STRMACHTYPE,str2short(temp)); + +} +void nt_exec(char *prog, char**args) { + nt_execve(prog,args,NULL); +} +void nt_execve(char *prog, char**args, char**envir ) { + + STARTUPINFO si; + PROCESS_INFORMATION pi; + HANDLE htemp; + BOOL bRet; + DWORD type=0; + DWORD dwCreationflags; + unsigned int priority; + char *argv0= NULL; + char *cmdstr, *cmdend ; + char *originalPtr; + unsigned int cmdsize,cmdlen; + char *p2; + char **savedargs; + int retries=0; + int hasdot =0; + int is_winnt ; + + UNREFERENCED_PARAMETER(envir); + + memset(&si,0,sizeof(si)); + savedargs = args; + + /* + * This memory is not freed because we are exec()ed and will + * not be alive long. + */ + originalPtr = cmdstr= heap_alloc(MAX_PATH<<2); + + is_winnt = (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS); + + + cmdsize = MAX_PATH<<2; + + p2 = cmdstr; + + cmdlen = 0; + cmdlen += copy_quote_and_fix_slashes(prog,cmdstr,&hasdot); + + p2 += cmdlen; + + /* If the command was not quoted , + skip initial character we left for quote */ + if (*cmdstr != '"') { + *cmdstr = 'A'; + cmdstr++; + cmdsize--; + } + *p2 = 0; + cmdend = p2; + + + if (!is_winnt){ + argv0 = NULL; + goto win95_directly_here; + } + else { + argv0 = heap_alloc(MAX_PATH); /* not freed */ + (void)StringCbPrintf(argv0,MAX_PATH,"%s",prog); + } + +retry: + + bRet=GetBinaryType(argv0,&type); + dprintf("binary type for %s is %d\n",argv0,bRet); + // + // For NT, append .EXE and retry + // + if (is_winnt && !bRet ) { + /* Don't append .EXE if it could be a script file */ + if (GetLastError() == ERROR_BAD_EXE_FORMAT){ + errno = ENOEXEC; + if (!__nt_only_start_exes) + try_shell_ex(args,1,FALSE); //can't throw on error + return; + } + else if ( retries ){ + if ( + ( (argv0[0] == '\\') ||(argv0[0] == '/') ) && + ( (argv0[1] == '\\') ||(argv0[1] == '/') ) && + (!args[1]) + ) + if (!__nt_only_start_exes) + try_shell_ex(args,1,FALSE); + errno = ENOENT; + } + if (retries > 1){ + return; + } + // Try uppercase once and then lower case + // + if (!retries) { + (void)StringCbPrintf(argv0,MAX_PATH,"%s.exe",prog); + } + else { + (void)StringCbPrintf(argv0,MAX_PATH,"%s.EXE",prog); + /* fix for clearcase */ + } + retries++; + goto retry; + } + +win95_directly_here: + + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + htemp= (HANDLE)_get_osfhandle(0); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdInput,0,TRUE,DUPLICATE_SAME_ACCESS); + htemp= (HANDLE)_get_osfhandle(1); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdOutput,0,TRUE,DUPLICATE_SAME_ACCESS); + htemp= (HANDLE)_get_osfhandle(2); + DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), + &si.hStdError,0,TRUE,DUPLICATE_SAME_ACCESS); + + + + args++; // the first arg is the command + + + dprintf("nt_execve calling c_a_a_q"); + if(!concat_args_and_quote(args,&originalPtr,&cmdstr,&cmdlen,&cmdend, + &cmdsize)) + { + dprintf("concat_args_and_quote failed\n"); + heap_free(originalPtr); + errno = ENOMEM; + goto fail_return; + } + + *cmdend = 0; + + dwCreationflags = GetPriorityClass(GetCurrentProcess()); + if (__nt_child_nohupped) { + dwCreationflags |= DETACHED_PROCESS; + } + priority = GetThreadPriority(GetCurrentThread()); + + (void)fix_path_for_child(); + + if (is_winnt) + dwCreationflags |= CREATE_SUSPENDED; + + +re_cp: + dprintf("argv0 %s cmdstr %s\n",argv0,cmdstr); + bRet = CreateProcessA(argv0, cmdstr, + NULL, NULL, + TRUE, // need this for redirecting std handles + dwCreationflags, + NULL, NULL, + &si, + &pi); + if (!bRet){ + if (GetLastError() == ERROR_BAD_EXE_FORMAT) { + if (!__nt_only_start_exes) + try_shell_ex(savedargs,1,FALSE); + errno = ENOEXEC; + } + else if (GetLastError() == ERROR_INVALID_PARAMETER) { + /* can't get invalid parameter, so this must be + * the case when we exceed the command length limit. + */ + errno = ENAMETOOLONG; + } + else { + errno = ENOENT; + } + if (!is_winnt && !hasdot) { //append '.' to the end if needed + (void)StringCbCat(cmdstr,cmdsize,"."); + hasdot=1; + goto re_cp; + } + } + else{ + int gui_app ; + char guivar[50]; + + if (GetEnvironmentVariable("TCSH_NOASYNCGUI",guivar,50)) + gui_app=0; + else { + if (is_winnt || hasdot) + gui_app= is_gui(argv0); + else + gui_app = is_9x_gui(prog); + } + + if (is_winnt && !SetThreadPriority(pi.hThread,priority) ) { + priority =GetLastError(); + } + if (is_winnt) + ResumeThread(pi.hThread); + errno= 0; + + if (__nt_really_exec||__nt_child_nohupped || gui_app){ + ExitProcess(0); + } + else { + DWORD exitcode=0; + WaitForSingleObject(pi.hProcess,INFINITE); + (void)GetExitCodeProcess(pi.hProcess,&exitcode); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + /* + * If output was redirected to /dev/clipboard, + * we need to close the pipe handles + */ + if (is_dev_clipboard_active) { + CloseHandle((HANDLE)_get_osfhandle(0)); + CloseHandle((HANDLE)_get_osfhandle(1)); + CloseHandle((HANDLE)_get_osfhandle(2)); + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + WaitForSingleObject(ghdevclipthread,60*1000); + } + ExitProcess(exitcode); + } + } +fail_return: + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + return; +} +/* This function from Mark Tucker (mtucker@fiji.sidefx.com) */ +int quoteProtect(char *dest, char *src,unsigned long destsize) { + char *prev, *curr; + for (curr = src; *curr; curr++) { + + // Protect " from MS-DOS expansion + if (*curr == '"') { + // Now, protect each preceeding backslash + for (prev = curr-1; prev >= src && *prev == '\\'; prev--) { + *dest++ = '\\'; + destsize--; + if(destsize == 0) + return ERROR_BUFFER_OVERFLOW; + } + + *dest++ = '\\'; + destsize--; + if(destsize == 0) + return ERROR_BUFFER_OVERFLOW; + } + *dest++ = *curr; + destsize--; + if(destsize == 0) + return ERROR_BUFFER_OVERFLOW; + + } + *dest = 0; + + return NO_ERROR; +} + + +int gethostname(char *buf, int len) { + GetComputerName(buf,(DWORD*)&len); + return 0; +} +int nt_chdir (char *path) { + char *tmp = path; + if (gdwPlatform !=VER_PLATFORM_WIN32_NT) { + while(*tmp) { + if (*tmp == '/') *tmp = '\\'; + tmp++; + } + } + return _chdir(path); +} +void WINAPI uhef( EXCEPTION_POINTERS *lpep) { + ExitProcess(lpep->ExceptionRecord->ExceptionCode); +} +extern BOOL CreateWow64Events(DWORD,HANDLE*,HANDLE*,BOOL); +// load kernel32 and look for iswow64. if not found, assume FALSE +BOOL bIsWow64Process = FALSE; +void init_wow64(void) { + HMODULE hlib; + //BOOL (WINAPI *pfnIsWow64)(HANDLE,BOOL*); + FARPROC pfnIsWow64; + + bIsWow64Process = FALSE; + + hlib = LoadLibrary("kernel32.dll"); + if (!hlib) { + return; + } + pfnIsWow64 = GetProcAddress(hlib,"IsWow64Process"); + if (!pfnIsWow64) { + FreeLibrary(hlib); + return; + } + if (!pfnIsWow64(GetCurrentProcess(),&bIsWow64Process) ) + bIsWow64Process = FALSE; + + FreeLibrary(hlib); + return; + +} + +extern void mainCRTStartup(void *); + +/* + * heap_init() MUST NOT be moved outside the entry point. Sometimes child + * processes may load random DLLs not loaded by the parent and + * use the heap address reserved for fmalloc() in the parent. This + * causes havoc as no dynamic memory can then be inherited. + * + */ +extern void heap_init(void); + +#include <forkdata.h> +void silly_entry(void *peb) { + char * path1=NULL; + int rc; + char temp[MAX_PATH+5]; + char buf[MAX_PATH]; + char ptr1[MAX_PATH]; + char ptr2[MAX_PATH]; + char ptr3[MAX_PATH]; + OSVERSIONINFO osver; + + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + if (!GetVersionEx(&osver)) { + MessageBox(NULL,"GetVersionEx failed","tcsh",MB_ICONHAND); + ExitProcess(0xFF); + } + gdwVersion = osver.dwMajorVersion; + + if(gdwVersion < 6) // no wow64 hackery for vista. + { + init_wow64(); + } + +#ifdef _M_IX86 + // look at the explanation in fork.c for why we do these steps. + if (bIsWow64Process) { + HANDLE h64Parent,h64Child; + char *stk, *end; + DWORD mb = (1<<20); + + // if we found the events, then we're the product of a fork() + if (CreateWow64Events(GetCurrentProcessId(), + &h64Parent,&h64Child,TRUE)) { + + if (!h64Parent || !h64Child) + return; + + // tell parent we're rolling + SetEvent(h64Child); + + if(WaitForSingleObject(h64Parent,FORK_TIMEOUT) != WAIT_OBJECT_0) { + return; + } + + // if __forked is 0, we shouldn't have found the events + if (!__forked) + return; + } + + // now create the stack + + if (!__forked) { + stk = VirtualAlloc(NULL,mb+65536,MEM_COMMIT,PAGE_READWRITE); + if (!stk) { + dprintf("virtual alloc in parent failed %d\n",GetLastError()); + return; + } + end = stk + mb + 65536; + end -= sizeof(char*); + + __fork_stack_begin = end; + + __asm {mov esp,end }; + + set_stackbase(end); + heap_init(); + } + else { // child process + stk = (char*)__fork_stack_begin + sizeof(char*)- mb - 65536; + + dprintf("begin is 0x%08x\n",stk); + end = VirtualAlloc(stk, mb+65536 , MEM_RESERVE , PAGE_READWRITE); + if (!end) { + rc = GetLastError(); + dprintf("virtual alloc 1 in child failed %d\n",rc); + return; + } + stk = VirtualAlloc(end, mb+65536 , MEM_COMMIT , PAGE_READWRITE); + if (!stk) { + rc = GetLastError(); + dprintf("virtual alloc 2 in child failed %d\n",rc); + return; + } + end = stk + mb + 65536; + __asm {mov esp, end}; + set_stackbase(end); + + SetEvent(h64Child); + + CloseHandle(h64Parent); + CloseHandle(h64Child); + } + } +#endif _M_IX86 + + + SetFileApisToOEM(); + + if (!bIsWow64Process) + heap_init(); + + + + + /* If home is set, we only need to change '\' to '/' */ + rc = GetEnvironmentVariable("HOME",buf,MAX_PATH); + if (rc && (rc < MAX_PATH)){ + path_slashify(buf); + (void)SetEnvironmentVariable("HOME",buf); + goto skippy; + } + + memset(ptr1,0,MAX_PATH); + memset(ptr2,0,MAX_PATH); + memset(ptr3,0,MAX_PATH); + + if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { + GetEnvironmentVariable("USERPROFILE",ptr1,MAX_PATH); + GetEnvironmentVariable("HOMEDRIVE",ptr2,MAX_PATH); + GetEnvironmentVariable("HOMEPATH",ptr3,MAX_PATH); + + ptr1[MAX_PATH -1] = ptr2[MAX_PATH-1] = ptr3[MAX_PATH-1]= 0; + +#pragma warning(disable:4995) + if (!ptr1[0] || osver.dwMajorVersion <4) { + wsprintfA(temp, "%s%s",ptr2[0]?ptr2:"C:",ptr3[0]?ptr3:"\\"); + } + else if (osver.dwMajorVersion >= 4) { + wsprintfA(temp, "%s",ptr1); + } +#pragma warning(default:4995) + } + else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + + rc = GetWindowsDirectory(ptr1,MAX_PATH); + if (rc > MAX_PATH) { + MessageBox(NULL,"This should never happen","tcsh",MB_ICONHAND); + ExitProcess(0xFF); + } + (void)StringCbPrintf(temp,sizeof(temp),"%s",ptr1); + } + else { + MessageBox(NULL,"Unknown platform","tcsh",MB_ICONHAND); + } + path_slashify(temp); + SetEnvironmentVariable("HOME",temp); + +skippy: + gdwPlatform = osver.dwPlatformId; + + + rc = GetEnvironmentVariable("Path",path1,0); + if ( rc !=0) { + + path1 =heap_alloc(rc); + + GetEnvironmentVariable("Path",path1,rc); + SetEnvironmentVariable("Path",NULL); + /*SetEnvironmentVariable("PATH",NULL);*/ + SetEnvironmentVariable("PATH",path1); + + heap_free(path1); + } + mainCRTStartup(peb); +} + +/* + * Copy source into target, quote if it has space, also converting '/' to '\'. + * + * hasdot is set to 1 if source ends in a file extension + * return value is the length of the string copied. + */ +int copy_quote_and_fix_slashes(char *source,char *target, int *hasdot ) { + + int len ; + int hasspace; + char *save; + char *ptr; + + save = target; /* leave space for quote */ + len = 1; + + target++; + + hasspace = 0; + while(*source) { + if (*source == '/') + *source = '\\'; + else if (*source == ' ') + hasspace = 1; + + *target++ = *source; + + source++; + len++; + } + ptr = target;//source; + while( (ptr > save ) && (*ptr != '\\')) { + if (*ptr == '.') + *hasdot = 1; + ptr--; + } + + if (hasspace) { + *save = '"'; + *target = '"'; + len++; + } + return len; +} +/* + * This routine is a replacement for the old, horrible strcat() loop + * that was used to turn the argv[] array into a string for CreateProcess(). + * It's about a zillion times faster. + * -amol 2/4/99 + */ +char *concat_args_and_quote(char **args, char **poriginalPtr,char **cstr, + unsigned int *clen, char **cend, unsigned int *cmdsize) { + + unsigned int argcount, arglen, cmdlen; + char *tempptr, *cmdend ,*cmdstr; + short quotespace = 0; + short quotequote = 0; + short noquoteprotect = 0; + char *tempquotedbuf; + unsigned long tqlen = 256; + int rc; + + dprintf("entering concat_args_and_quote\n"); + tempquotedbuf = heap_alloc(tqlen); + + noquoteprotect = (short)(varval(STRNTnoquoteprotect) != STRNULL); + /* + quotespace hack needed since execv() would have separated args, but + createproces doesnt + -amol 9/14/96 + */ + cmdend= *cend; + cmdstr = *cstr; + cmdlen = *clen; + + argcount = 0; + while (*args) { + + *cmdend++ = ' '; + cmdlen++; + + tempptr = *args; + + arglen = 0; + argcount++; + + //dprintf("args is %s\n",*args); + if (!*tempptr) { + *cmdend++ = '"'; + *cmdend++ = '"'; + } + while(*tempptr) { + if (*tempptr == ' ' || *tempptr == '\t') + quotespace = 1; + else if (*tempptr == '"') + quotequote = 1; + tempptr++; + arglen++; + } + if (arglen + cmdlen +4 > *cmdsize) { // +4 is if we have to quote + + + tempptr = heap_realloc(*poriginalPtr,*cmdsize<<1); + + if(!tempptr) + return NULL; + + // If it's not the same heap block, re-adjust the pointers. + if (tempptr != *poriginalPtr) { + cmdstr = tempptr + (cmdstr - *poriginalPtr); + cmdend = tempptr + (cmdend- *poriginalPtr); + *poriginalPtr = tempptr; + } + + *cmdsize <<=1; + } + if (quotespace) + *cmdend++ = '"'; + + if ((noquoteprotect == 0) && quotequote){ + tempquotedbuf[0]=0; + + tempptr = &tempquotedbuf[0]; + + rc = quoteProtect(tempquotedbuf,*args,tqlen); + + while(rc == ERROR_BUFFER_OVERFLOW) { + char *tmp = tempquotedbuf; + tempquotedbuf = heap_realloc(tempquotedbuf,tqlen <<1); + if(!tempquotedbuf) { + heap_free(tmp); + return NULL; + } + tqlen <<= 1; + tempptr = &tempquotedbuf[0]; + rc = quoteProtect(tempquotedbuf,*args,tqlen); + } + while (*tempptr) { + *cmdend = *tempptr; + cmdend++; + tempptr++; + } + cmdlen +=2; + } + else { + tempptr = *args; + while(*tempptr) { + *cmdend = *tempptr; + cmdend++; + tempptr++; + } + } + + if (quotespace) { + *cmdend++ = '"'; + cmdlen +=2; + } + cmdlen += arglen; + + args++; + } + *clen = cmdlen; + *cend = cmdend; + *cstr = cmdstr; + + heap_free(tempquotedbuf); + + + return cmdstr; +} +char *fix_path_for_child(void) { + + char *ptr; + Char *vp; + char *pathstr; + char *oldpath; + long len; + + vp = varval(STRNTlamepathfix); + + if (vp != STRNULL) { + + len = GetEnvironmentVariable("PATH",NULL,0); + + oldpath = heap_alloc(len+1); + pathstr = heap_alloc(len+1); + + len = GetEnvironmentVariable("PATH",oldpath,len+1); + memcpy(pathstr,oldpath,len); + + ptr = pathstr; + while(*ptr) { + if (*ptr == '/') + *ptr = '\\'; + ptr++; + } + SetEnvironmentVariable("PATH",pathstr); + heap_free(pathstr); + + return oldpath; //freed in restore_path; + } + else + return NULL; + +} +void restore_path(char *oldpath) { + if (oldpath) { + SetEnvironmentVariable("PATH",oldpath); + heap_free(oldpath); + } +} diff --git a/win32/tcshrc.rc b/win32/tcshrc.rc new file mode 100644 index 000000000000..e51f3e9b8c86 --- /dev/null +++ b/win32/tcshrc.rc @@ -0,0 +1,99 @@ +#if 0 +#include <windows.h> +STRINGTABLE DISCARDABLE +BEGIN +666 " setenv EDITOR vi.exe" +667 " setenv PAGER c:/bin/less" +668 " setenv NOREBIND 1" +669 " setenv LESS ""-B -c -h4 -i -M -q -x4 -G""" +670 " setenv SHELL C:/bin/tcsh.exe" +671 "if ($?PROCESSOR_ARCHITECTURE) then" +672 " setenv USER $USERNAME" +673 " setenv LOGNAME $USER" +674 " setenv HOSTNAME $COMPUTERNAME" +675 "endif" +676 "umask 077" +677 "if (! $?prompt) then # Everything else is interactive" +678 " exit(0)" +679 "endif" +680 "unsetenv EXINIT" +681 "if ($?tcsh) then" +682 " set autolist" +683 " set listlinks" +684 " set pushdtohome" +685 " set visiblebell" +686 " set ellipsis" +687 " set rmstar" +688 "if ($?TERM) then" +689 " if ($TERM == ""emacs"") then" +690 " set prompt='%/\>'" +691 " else" +692 " set prompt='%{[1;34m%}%c03%{[0m%}\>'" +693 " set prompt3='%{[1;31m%}Correct to %R ?(y|n|e)%{[0m%} '" +694 " endif" +695 "else" +696 " set prompt='%{[1;34m%}%c03%{[0m%}\>'" +697 " set prompt3='%{[1;31m%}Correct to %R ?(y|n|e)%{[0m%} '" +698 "endif" +699 " if ($?loginsh) then" +700 " set correct=all" +701 " set savedirs=100" +702 " set autocorrect" +703 " endif" +704 " set complete=igncase" +705 " complete which 'p/*/c/'" +706 " complete where 'p/*/c/'" +707 " complete start 'p/1/c/'" +708 " complete cd 'p/1/d/'" +709 " complete pushd 'p/1/d/'" +710 " complete popd 'p/1/d/'" +711 " complete bindkey 'p/*/b/'" +712 " complete set 'p/*/v/'" +713 " complete unset 'p/*/v/'" +714 " bindkey -b ^W backward-delete-word" +715 " bindkey -b ^U backward-kill-line" +716 " bindkey -b ^R complete-word-fwd" +717 " bindkey -b M-g list-glob" +718 " bindkey -b M-* expand-glob" +719 " bindkey -b M-v expand-variables" +720 " bindkey -b M-w normalize-command" +721 " bindkey -b M-/ e_dosify_prev" +722 " bindkey -b M-r i-search-back" +723 " bindkey -b M-x e_copy_to_clipboard" +724 " bindkey -b M-y e_paste_from_clipboard" +725 " bindkey -b N-up up-history" +726 " bindkey -b N-down down-history" +727 " bindkey -b N-right forward-char" +728 " bindkey -b N-left backward-char" +729 " bindkey -b N-del delete-char" +730 " bindkey -b N-ins overwrite-mode" +731 " bindkey -b N-1 which-command" +732 " bindkey -b N-2 expand-history" +733 " bindkey -b N-3 complete-word-raw" +734 " bindkey -b N-home beginning-of-line" +735 " bindkey -b N-end end-of-line" +736 "endif" +737 "if (! $?PATH_DONE) then" +738 "set path=($path:q c:/bin .)" +739 "setenv PATH_DONE 1" +740 "endif" +741 "set notify" +742 "set noclobber" +743 "set filec" +744 "set history=(200) " +745 "set savehist=(200 merge)" +746 "set ignoreeof" +747 "set fignore =(.obj .pdb .bsc .ilk .idb .OBJ .PDB .BSC .ILK .IDB)" +748 "set color=(ls-F)" +749 "alias ls ls-F " +750 "alias h history" +751 "alias rm c:/bin/rm.exe -i" +752 "alias rd c:/bin/rmdir.exe" +753 "alias md c:/bin/mkdir.exe" +754 "alias mv C:/bin/mv.exe -i" +755 "alias cp C:/bin/cp.exe -i" +756 "alias pwd 'echo $cwd'" +757 "alias env printenv" +758 "alias unsave unset savehist savedirs" +END +#endif 0 diff --git a/win32/version.h b/win32/version.h new file mode 100644 index 000000000000..44d425764877 --- /dev/null +++ b/win32/version.h @@ -0,0 +1,14 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/version.h,v 1.24 2008/09/10 20:34:21 amold Exp $*/ +#ifndef VERSION_H +#define VERSION_H + +/* remember to change both instance of the version -amol */ + +#ifdef NTDBG +#define LOCALSTR ",nt-rev-8.10-debug" +#else +#define LOCALSTR ",nt-rev-8.10" + //patches +#endif NTDBG + +#endif VERSION_H |