Compare commits
24 Commits
22d862cd12
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f940d2d88e | ||
|
|
9ab65e2f00 | ||
|
|
456349088e | ||
|
|
f62ca19c50 | ||
|
|
ff92f72583 | ||
|
|
83f8947ece | ||
|
|
87c1e50cf9 | ||
|
|
7f98d73738 | ||
|
|
3a5b08a4bf | ||
|
|
8b6685c501 | ||
|
|
cfb58237da | ||
|
|
aaf29ed535 | ||
|
|
6f998a497d | ||
|
|
dbf7be5104 | ||
|
|
4a4026e6dd | ||
|
|
20343b497a | ||
|
|
e4227bfda8 | ||
|
|
bb868613d9 | ||
|
|
e4d67917bd | ||
|
|
b8a701b8fe | ||
|
|
dd5e4e9a3b | ||
|
|
82b0f918dd | ||
|
|
b16fc3a64b | ||
|
|
f375f79cce |
161
CMakeLists.txt
161
CMakeLists.txt
@@ -1,17 +1,24 @@
|
|||||||
# DOS utilities for mars-nwe.
|
# DOS utilities for mars-nwe.
|
||||||
#
|
#
|
||||||
# Default mode: install a prebuilt net.exe from this source tree. This keeps the
|
# Default install mode uses a split:
|
||||||
# normal mars-nwe build independent from Open Watcom.
|
# - legacy command names are installed from netold.exe
|
||||||
|
# - new command names that netold.exe does not contain are installed from net.exe
|
||||||
#
|
#
|
||||||
# Maintainer mode: configure with -DMARS_NWE_BUILD_DOSUTILS=ON to rebuild
|
# Maintainer mode can rebuild the new net.exe with Open Watcom. The freshly
|
||||||
# net.exe with Open Watcom v2 on Linux.
|
# built binary is only installed when MARS_NWE_INSTALL_NEW_DOSUTILS is ON, or
|
||||||
|
# for the new-only command names in the default split install.
|
||||||
|
|
||||||
set(MARS_DOSUTILS_NET_EXE
|
set(MARS_DOSUTILS_LEGACY_NET_EXE
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/net.exe"
|
"${CMAKE_CURRENT_SOURCE_DIR}/netold.exe"
|
||||||
CACHE FILEPATH "Prebuilt DOS net.exe used for installation when MARS_NWE_BUILD_DOSUTILS is OFF"
|
CACHE FILEPATH "Legacy/pre-Client32 DOS net.exe used by default for legacy command names"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(MARS_DOSUTILS_PUBLIC_TOOLS
|
set(MARS_DOSUTILS_NEW_NET_EXE
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/net.exe"
|
||||||
|
CACHE FILEPATH "New/experimental DOS net.exe used for new-only tools or when MARS_NWE_INSTALL_NEW_DOSUTILS is ON"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(MARS_DOSUTILS_LEGACY_TOOLS
|
||||||
net
|
net
|
||||||
login
|
login
|
||||||
profile
|
profile
|
||||||
@@ -27,8 +34,15 @@ set(MARS_DOSUTILS_PUBLIC_TOOLS
|
|||||||
endcap
|
endcap
|
||||||
)
|
)
|
||||||
|
|
||||||
# Do not install slist.exe yet: func_slist() is empty and SLIST is disabled in net.c.
|
# Tools not present in netold.exe. These are installed from the new binary
|
||||||
# Do not install tests/debug by default either; they are developer-only helpers.
|
# even in the default split mode.
|
||||||
|
set(MARS_DOSUTILS_NEW_ONLY_TOOLS
|
||||||
|
slist
|
||||||
|
flag
|
||||||
|
flagdir
|
||||||
|
rights
|
||||||
|
grant
|
||||||
|
)
|
||||||
|
|
||||||
if(MARS_NWE_BUILD_DOSUTILS)
|
if(MARS_NWE_BUILD_DOSUTILS)
|
||||||
find_package(OpenWatcom REQUIRED)
|
find_package(OpenWatcom REQUIRED)
|
||||||
@@ -40,6 +54,12 @@ if(MARS_NWE_BUILD_DOSUTILS)
|
|||||||
ncpcall.c
|
ncpcall.c
|
||||||
login.c
|
login.c
|
||||||
map.c
|
map.c
|
||||||
|
slist.c
|
||||||
|
flag.c
|
||||||
|
flagdir.c
|
||||||
|
rights.c
|
||||||
|
grant.c
|
||||||
|
c32ncp.c
|
||||||
nwcrypt.c
|
nwcrypt.c
|
||||||
nwdebug.c
|
nwdebug.c
|
||||||
nwtests.c
|
nwtests.c
|
||||||
@@ -55,10 +75,39 @@ if(MARS_NWE_BUILD_DOSUTILS)
|
|||||||
-fo="${CMAKE_CURRENT_BINARY_DIR}/kern.obj"
|
-fo="${CMAKE_CURRENT_BINARY_DIR}/kern.obj"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/kern_wasm.asm"
|
"${CMAKE_CURRENT_SOURCE_DIR}/kern_wasm.asm"
|
||||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/kern_wasm.asm"
|
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/kern_wasm.asm"
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(DOSUTILS_OBJECTS)
|
||||||
|
foreach(src IN LISTS DOSUTILS_C_SOURCES)
|
||||||
|
get_filename_component(obj_name "${src}" NAME_WE)
|
||||||
|
set(obj "${CMAKE_CURRENT_BINARY_DIR}/${obj_name}.obj")
|
||||||
|
list(APPEND DOSUTILS_OBJECTS "${obj}")
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${obj}"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E env ${OPENWATCOM_ENV}
|
||||||
|
"${OPENWATCOM_WCL}"
|
||||||
|
-q
|
||||||
|
-zq
|
||||||
|
-bt=dos
|
||||||
|
-ml
|
||||||
|
-0
|
||||||
|
-c
|
||||||
|
-fo="${obj}"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${src}"
|
||||||
|
DEPENDS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${src}"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/net.h"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/kern.h"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/c32ncp.h"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/nwcrypt.h"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/net.exe"
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/net.exe"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E env ${OPENWATCOM_ENV}
|
COMMAND "${CMAKE_COMMAND}" -E env ${OPENWATCOM_ENV}
|
||||||
@@ -70,15 +119,12 @@ if(MARS_NWE_BUILD_DOSUTILS)
|
|||||||
-0
|
-0
|
||||||
-k32768
|
-k32768
|
||||||
-fe="${CMAKE_CURRENT_BINARY_DIR}/net.exe"
|
-fe="${CMAKE_CURRENT_BINARY_DIR}/net.exe"
|
||||||
${DOSUTILS_C_SOURCES}
|
${DOSUTILS_OBJECTS}
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/kern.obj"
|
"${CMAKE_CURRENT_BINARY_DIR}/kern.obj"
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${DOSUTILS_C_SOURCES}
|
${DOSUTILS_OBJECTS}
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/kern.obj"
|
"${CMAKE_CURRENT_BINARY_DIR}/kern.obj"
|
||||||
net.h
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
kern.h
|
|
||||||
nwcrypt.h
|
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -86,32 +132,69 @@ if(MARS_NWE_BUILD_DOSUTILS)
|
|||||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/net.exe"
|
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/net.exe"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(MARS_DOSUTILS_NET_EXE "${CMAKE_CURRENT_BINARY_DIR}/net.exe")
|
set(MARS_DOSUTILS_BUILT_NET_EXE "${CMAKE_CURRENT_BINARY_DIR}/net.exe")
|
||||||
else()
|
else()
|
||||||
if(NOT EXISTS "${MARS_DOSUTILS_NET_EXE}")
|
set(MARS_DOSUTILS_BUILT_NET_EXE "")
|
||||||
message(FATAL_ERROR
|
|
||||||
"Prebuilt DOS utility missing: ${MARS_DOSUTILS_NET_EXE}. "
|
|
||||||
"Either commit net.exe into dosutils or configure with "
|
|
||||||
"-DMARS_NWE_BUILD_DOSUTILS=ON and Open Watcom installed."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(tool IN LISTS MARS_DOSUTILS_PUBLIC_TOOLS)
|
if(MARS_NWE_BUILD_DOSUTILS)
|
||||||
if(tool STREQUAL "net")
|
set(MARS_DOSUTILS_SELECTED_NEW_EXE "${MARS_DOSUTILS_BUILT_NET_EXE}")
|
||||||
install(FILES "${MARS_DOSUTILS_NET_EXE}"
|
else()
|
||||||
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/public")
|
set(MARS_DOSUTILS_SELECTED_NEW_EXE "${MARS_DOSUTILS_NEW_NET_EXE}")
|
||||||
else()
|
endif()
|
||||||
install(FILES "${MARS_DOSUTILS_NET_EXE}"
|
|
||||||
|
if(MARS_NWE_INSTALL_NEW_DOSUTILS)
|
||||||
|
set(MARS_DOSUTILS_SELECTED_LEGACY_EXE "${MARS_DOSUTILS_SELECTED_NEW_EXE}")
|
||||||
|
else()
|
||||||
|
set(MARS_DOSUTILS_SELECTED_LEGACY_EXE "${MARS_DOSUTILS_LEGACY_NET_EXE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(MARS_NWE_INSTALL_DOSUTILS)
|
||||||
|
if(NOT EXISTS "${MARS_DOSUTILS_SELECTED_LEGACY_EXE}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Selected legacy/default DOS utility missing: ${MARS_DOSUTILS_SELECTED_LEGACY_EXE}. "
|
||||||
|
"Commit dosutils/netold.exe, enable MARS_NWE_INSTALL_NEW_DOSUTILS, "
|
||||||
|
"or enable MARS_NWE_BUILD_DOSUTILS."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${MARS_DOSUTILS_SELECTED_NEW_EXE}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Selected new DOS utility missing: ${MARS_DOSUTILS_SELECTED_NEW_EXE}. "
|
||||||
|
"Commit dosutils/net.exe or enable MARS_NWE_BUILD_DOSUTILS."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "DOS legacy/default utility binary: ${MARS_DOSUTILS_SELECTED_LEGACY_EXE}")
|
||||||
|
message(STATUS "DOS new-only utility binary: ${MARS_DOSUTILS_SELECTED_NEW_EXE}")
|
||||||
|
|
||||||
|
foreach(tool IN LISTS MARS_DOSUTILS_LEGACY_TOOLS)
|
||||||
|
if(tool STREQUAL "net")
|
||||||
|
install(FILES "${MARS_DOSUTILS_SELECTED_LEGACY_EXE}"
|
||||||
|
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/public"
|
||||||
|
RENAME net.exe)
|
||||||
|
else()
|
||||||
|
install(FILES "${MARS_DOSUTILS_SELECTED_LEGACY_EXE}"
|
||||||
|
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/public"
|
||||||
|
RENAME "${tool}.exe")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(tool IN LISTS MARS_DOSUTILS_NEW_ONLY_TOOLS)
|
||||||
|
install(FILES "${MARS_DOSUTILS_SELECTED_NEW_EXE}"
|
||||||
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/public"
|
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/public"
|
||||||
RENAME "${tool}.exe")
|
RENAME "${tool}.exe")
|
||||||
endif()
|
endforeach()
|
||||||
endforeach()
|
|
||||||
|
|
||||||
install(FILES "${MARS_DOSUTILS_NET_EXE}"
|
install(FILES "${MARS_DOSUTILS_SELECTED_LEGACY_EXE}"
|
||||||
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/login"
|
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/login"
|
||||||
RENAME login.exe)
|
RENAME login.exe)
|
||||||
|
|
||||||
install(FILES "${MARS_DOSUTILS_NET_EXE}"
|
install(FILES "${MARS_DOSUTILS_SELECTED_LEGACY_EXE}"
|
||||||
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/login"
|
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/login"
|
||||||
RENAME map.exe)
|
RENAME map.exe)
|
||||||
|
|
||||||
|
install(FILES "${MARS_DOSUTILS_SELECTED_LEGACY_EXE}"
|
||||||
|
DESTINATION "${MARS_NWE_INSTALL_FULL_FILEDIR}/SYS/login"
|
||||||
|
RENAME slist.exe)
|
||||||
|
endif()
|
||||||
|
|||||||
290
README.md
290
README.md
@@ -5,9 +5,28 @@ DOS client-side utilities for **mars_nwe** and compatible NetWare-style NCP envi
|
|||||||
This repository contains the source for a small DOS utility suite built around a **single multi-call executable**, `net.exe`. The program can be used either as:
|
This repository contains the source for a small DOS utility suite built around a **single multi-call executable**, `net.exe`. The program can be used either as:
|
||||||
|
|
||||||
- `net <command> [args...]`, or
|
- `net <command> [args...]`, or
|
||||||
- a renamed executable such as `login.exe`, `map.exe`, `capture.exe`, or `logout.exe`
|
- a renamed executable such as `login.exe`, `map.exe`, `flag.exe`, `flagdir.exe`, `capture.exe`, or `logout.exe`.
|
||||||
|
|
||||||
That design is explicit in the command table in `net.c`, and the install rules also deploy the same binary under multiple command names. The original project documentation describes it as a “simple DOS-client program to allow standard NCP network actions, mainly for mars_nwe,” and also notes that it was still incomplete at the time of writing.
|
The command dispatcher lives in `net.c`, and the install rules deploy the same binary under multiple command names in `SYS:PUBLIC` and selected names in `SYS:LOGIN`.
|
||||||
|
|
||||||
|
## Current status
|
||||||
|
|
||||||
|
The tree is a modernization of the historical mars_nwe DOS utilities. It still keeps the original Borland-era style and APIs where useful, but now also has an Open Watcom/CMake build path and working DOS Client32 support for the FLAG-family tools.
|
||||||
|
|
||||||
|
Validated recently:
|
||||||
|
|
||||||
|
- `FLAG` file attribute read/modify through DOS Client32
|
||||||
|
- `FLAGDIR` directory attribute read/modify through DOS Client32
|
||||||
|
- Novell-tool comparison for `FLAG`, including `ALL`, `N`, `RO`, `RW`, high bits, and display layout
|
||||||
|
- Novell-tool comparison for `FLAGDIR`, including `Normal`, `System`, `Hidden`, `DeleteInhibit`, `Purge`, `RenameInhibit`, and combined attributes
|
||||||
|
- CMake/Open Watcom build using binary-directory object files, so `.obj`/`.o` files are no longer written into the source tree
|
||||||
|
|
||||||
|
Still to validate or continue:
|
||||||
|
|
||||||
|
- DOSX/VLM/NETX fallback behavior for `FLAG` and `FLAGDIR`
|
||||||
|
- More complex `FLAGDIR` paths beyond the simple mapped-directory cases already tested
|
||||||
|
- OS/2 requester/tool behavior
|
||||||
|
- Additional Novell-like utilities such as `RIGHTS`, `GRANT`, `REVOKE`, `NDIR`, `PURGE`, and `SALVAGE`
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -18,7 +37,12 @@ That design is explicit in the command table in `net.c`, and the install rules a
|
|||||||
- Printer capture and release (`CAPTURE`, `ENDCAP`)
|
- Printer capture and release (`CAPTURE`, `ENDCAP`)
|
||||||
- Scripted session setup through command files
|
- Scripted session setup through command files
|
||||||
- External program execution via `SPAWN` and `EXEC`
|
- External program execution via `SPAWN` and `EXEC`
|
||||||
|
- Server listing through `SLIST`
|
||||||
|
- File attribute management through `FLAG`
|
||||||
|
- Directory attribute management through `FLAGDIR`
|
||||||
|
- Effective rights display through `RIGHTS`
|
||||||
- Optional mars_nwe debug control hooks
|
- Optional mars_nwe debug control hooks
|
||||||
|
- Developer diagnostics through `TESTS`
|
||||||
|
|
||||||
## Available commands
|
## Available commands
|
||||||
|
|
||||||
@@ -37,31 +61,64 @@ The current command dispatcher includes these built-ins:
|
|||||||
- `PATHDEL`
|
- `PATHDEL`
|
||||||
- `CAPTURE`
|
- `CAPTURE`
|
||||||
- `ENDCAP`
|
- `ENDCAP`
|
||||||
|
- `SLIST`
|
||||||
|
- `FLAG`
|
||||||
|
- `FLAGDIR`
|
||||||
|
- `RIGHTS`
|
||||||
- `DEBUG`
|
- `DEBUG`
|
||||||
- `ECHO`
|
- `ECHO`
|
||||||
- `CD`
|
- `CD`
|
||||||
- `TESTS` (developer/testing only)
|
- `TESTS` developer/testing only
|
||||||
|
|
||||||
`SLIST` is present in the historical build/install metadata, but the command is disabled in the dispatcher and the provided `slist.c` is only a stub in this source snapshot.
|
The CMake install rules also install the multi-call `net.exe` under several of those command names.
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
The program resolves the command from either:
|
The program resolves the command from either:
|
||||||
|
|
||||||
1. the executable name itself, or
|
1. the executable name itself, or
|
||||||
2. the first command-line argument
|
2. the first command-line argument.
|
||||||
|
|
||||||
That means all of the following styles are valid:
|
That means all of the following styles are valid:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
NET LOGIN alice secret
|
NET LOGIN alice secret
|
||||||
NET MAP F:=SYS:
|
NET MAP F:=SYS:
|
||||||
|
NET FLAG LOGIN.EXE
|
||||||
LOGIN.EXE alice secret
|
LOGIN.EXE alice secret
|
||||||
MAP.EXE F:=SYS:
|
MAP.EXE F:=SYS:
|
||||||
|
FLAG.EXE LOGIN.EXE A
|
||||||
CAPTURE.EXE LPT1 Q1
|
CAPTURE.EXE LPT1 Q1
|
||||||
```
|
```
|
||||||
|
|
||||||
This is one of the key design ideas of the project, and the original README specifically recommends copying or linking `net.exe` to `login.exe` for convenience.
|
## Client32 NCP support
|
||||||
|
|
||||||
|
The modern Client32 path is implemented through a small reusable helper layer:
|
||||||
|
|
||||||
|
- `c32ncp.c`
|
||||||
|
- `c32ncp.h`
|
||||||
|
- Client32 assembly entry points in `kern_wasm.asm`
|
||||||
|
|
||||||
|
The working sequence is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
C32_MapVar_Probe(4,0)
|
||||||
|
-> obtains the active connection reference
|
||||||
|
|
||||||
|
C32_OpenRef_Probe()
|
||||||
|
-> opens that reference and returns a Client32 handle
|
||||||
|
|
||||||
|
C32_NCP87_Raw5_Probe()
|
||||||
|
-> sends NCP 87 requests through COMPATNcpRequestReply
|
||||||
|
```
|
||||||
|
|
||||||
|
This path is currently used by:
|
||||||
|
|
||||||
|
- `FLAG`
|
||||||
|
- `FLAGDIR`
|
||||||
|
- `RIGHTS`
|
||||||
|
|
||||||
|
The old `Net_Call` / INT 21h requester path is kept as a fallback where appropriate, but Client32 is now preferred for the validated FLAG-family operations.
|
||||||
|
|
||||||
## Command reference
|
## Command reference
|
||||||
|
|
||||||
@@ -92,10 +149,7 @@ Change a user password.
|
|||||||
PASSWD [user]
|
PASSWD [user]
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes:
|
If no username is supplied, the tool attempts to resolve the currently logged-in user. The password-change code prefers the encrypted/keyed flow where available and keeps older unencrypted calls as fallback.
|
||||||
|
|
||||||
- If no username is supplied, the tool attempts to resolve the currently logged-in user. fileciteturn1file2L162-L190
|
|
||||||
- The source comments note that password changes currently use the older unencrypted password-change call.
|
|
||||||
|
|
||||||
### `PROFILE`
|
### `PROFILE`
|
||||||
|
|
||||||
@@ -105,7 +159,7 @@ Execute a command script.
|
|||||||
PROFILE <filename>
|
PROFILE <filename>
|
||||||
```
|
```
|
||||||
|
|
||||||
This is a central part of the workflow. The command reader parses non-empty lines, ignores `#` comments, uppercases the command token, and dispatches it through the same internal command table used for direct invocation. `ECHO` is treated specially so the rest of the line is preserved as a single string.
|
The command reader parses non-empty lines, ignores `#` comments, uppercases the command token, and dispatches it through the same internal command table used for direct invocation. `ECHO` is treated specially so the rest of the line is preserved as a single string.
|
||||||
|
|
||||||
### `SPAWN`
|
### `SPAWN`
|
||||||
|
|
||||||
@@ -157,7 +211,7 @@ List or set a search-path entry.
|
|||||||
PATH sn:[=[path]]
|
PATH sn:[=[path]]
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `sn` is `s1` through `s16`. The original documentation notes that this updates the path environment rather than directly creating a drive mapping.
|
Where `sn` is `s1` through `s16`.
|
||||||
|
|
||||||
### `PATHINS`
|
### `PATHINS`
|
||||||
|
|
||||||
@@ -211,6 +265,131 @@ Example:
|
|||||||
ENDCAP LPT1
|
ENDCAP LPT1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `SLIST`
|
||||||
|
|
||||||
|
List known NetWare file servers.
|
||||||
|
|
||||||
|
Typical usage:
|
||||||
|
|
||||||
|
```text
|
||||||
|
SLIST [server] [/Continue]
|
||||||
|
```
|
||||||
|
|
||||||
|
The current `slist.c` implementation scans bindery file server objects and prints known servers.
|
||||||
|
|
||||||
|
### `FLAG`
|
||||||
|
|
||||||
|
Display or modify NetWare DOS file attributes.
|
||||||
|
|
||||||
|
Typical usage:
|
||||||
|
|
||||||
|
```text
|
||||||
|
FLAG file [option...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```text
|
||||||
|
FLAG LOGIN.EXE
|
||||||
|
FLAG LOGIN.EXE A
|
||||||
|
FLAG LOGIN.EXE -A
|
||||||
|
FLAG LOGIN.EXE P T DI RI CI RA WA
|
||||||
|
FLAG LOGIN.EXE N
|
||||||
|
FLAG LOGIN.EXE ALL
|
||||||
|
FLAG LOGIN.EXE RO
|
||||||
|
FLAG LOGIN.EXE RW
|
||||||
|
```
|
||||||
|
|
||||||
|
Supported attributes and aliases include:
|
||||||
|
|
||||||
|
- `RO`
|
||||||
|
- `RW`
|
||||||
|
- `S`
|
||||||
|
- `A`
|
||||||
|
- `H`
|
||||||
|
- `SY`, `SYS`, `SYSTEM`
|
||||||
|
- `T`
|
||||||
|
- `P`
|
||||||
|
- `RA`
|
||||||
|
- `WA`
|
||||||
|
- `CI`
|
||||||
|
- `DI`
|
||||||
|
- `RI`
|
||||||
|
- `ALL`
|
||||||
|
- `N` / `NORMAL`
|
||||||
|
|
||||||
|
The output is intentionally close to Novell FLAG formatting:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ro/Rw S/- A/- - H/- Sy/-- T/- P/- Ra/-- Wa/-- CI/-- DI/-- RI/--
|
||||||
|
```
|
||||||
|
|
||||||
|
The Client32 path handles both low and high NetWare attribute bits. High bits such as `P`, `DI`, `RI`, `CI`, `RA`, and `WA` must be handled as 32-bit values in 16-bit DOS builds.
|
||||||
|
|
||||||
|
### `FLAGDIR`
|
||||||
|
|
||||||
|
Display or modify NetWare directory attributes.
|
||||||
|
|
||||||
|
Typical usage:
|
||||||
|
|
||||||
|
```text
|
||||||
|
FLAGDIR [path [option...]]
|
||||||
|
```
|
||||||
|
|
||||||
|
Supported 386-style options:
|
||||||
|
|
||||||
|
- `Normal`
|
||||||
|
- `System`
|
||||||
|
- `Hidden`
|
||||||
|
- `DeleteInhibit`
|
||||||
|
- `Purge`
|
||||||
|
- `RenameInhibit`
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```text
|
||||||
|
FLAGDIR UDIR
|
||||||
|
FLAGDIR UDIR SYSTEM
|
||||||
|
FLAGDIR UDIR HIDDEN
|
||||||
|
FLAGDIR UDIR DELETEINHIBIT
|
||||||
|
FLAGDIR UDIR PURGE
|
||||||
|
FLAGDIR UDIR RENAMEINHIBIT
|
||||||
|
FLAGDIR UDIR NORMAL
|
||||||
|
```
|
||||||
|
|
||||||
|
For simple mapped paths, the display is kept close to Novell FLAGDIR style:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MARS/SYS:UDIR
|
||||||
|
UDIR System Hidden DeleteInhibit Purge RenameInhibit
|
||||||
|
```
|
||||||
|
|
||||||
|
`Private` is intentionally rejected for the current NetWare 386-style path.
|
||||||
|
|
||||||
|
|
||||||
|
### `RIGHTS`
|
||||||
|
|
||||||
|
Display effective NetWare rights for a file or directory.
|
||||||
|
|
||||||
|
Typical usage:
|
||||||
|
|
||||||
|
```text
|
||||||
|
RIGHTS [path]
|
||||||
|
```
|
||||||
|
|
||||||
|
Supported in this first version:
|
||||||
|
|
||||||
|
- directory paths
|
||||||
|
- file paths, using the parent directory rights for the first read-only implementation
|
||||||
|
- Novell-like display of the effective rights mask
|
||||||
|
|
||||||
|
Rights are shown in the traditional order:
|
||||||
|
|
||||||
|
```text
|
||||||
|
S R W C E M F A
|
||||||
|
Supervisor, Read, Write, Create, Erase, Modify, File scan, Access Control
|
||||||
|
```
|
||||||
|
|
||||||
### `DEBUG`
|
### `DEBUG`
|
||||||
|
|
||||||
Set mars_nwe debug levels for selected server-side modules.
|
Set mars_nwe debug levels for selected server-side modules.
|
||||||
@@ -220,7 +399,7 @@ DEBUG NCPSERV|NWCONN|NWBIND level
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `level` must be between `0` and `99`.
|
- `level` must be between `0` and `99`.
|
||||||
- The original docs say this requires `FUNC_17_02_IS_DEBUG` to be enabled in `mars_nwe/config.h`.
|
- This requires the matching mars_nwe server-side debug call to be enabled.
|
||||||
|
|
||||||
### `ECHO`
|
### `ECHO`
|
||||||
|
|
||||||
@@ -234,9 +413,19 @@ Change the current DOS directory. It also adjusts the active drive if a drive-qu
|
|||||||
|
|
||||||
Internal developer test routines. Not intended as a regular end-user command.
|
Internal developer test routines. Not intended as a regular end-user command.
|
||||||
|
|
||||||
|
The currently useful Client32 test is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
TESTS NCP87C32ATTR
|
||||||
|
```
|
||||||
|
|
||||||
|
It verifies the working Client32 NCP87 attribute path.
|
||||||
|
|
||||||
## Login script workflow
|
## Login script workflow
|
||||||
|
|
||||||
A particularly important feature is the automatic execution of a file named `login` located beside the executable after a successful login. The historical README gives this example:
|
A particularly important feature is the automatic execution of a file named `login` located beside the executable after a successful login.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
map f:=SYS:
|
map f:=SYS:
|
||||||
@@ -253,7 +442,7 @@ This makes the tool suite useful not just for authentication, but for setting up
|
|||||||
|
|
||||||
### Historical DOS build
|
### Historical DOS build
|
||||||
|
|
||||||
The included `makefile.bcc` is the primary historical build file and targets **Borland C / Borland tools** on DOS.
|
The included `makefile.bcc` is the primary historical build file and targets Borland C / Borland tools on DOS.
|
||||||
|
|
||||||
Key settings from the makefile:
|
Key settings from the makefile:
|
||||||
|
|
||||||
@@ -264,29 +453,42 @@ Key settings from the makefile:
|
|||||||
- define: `-Dmsdos`
|
- define: `-Dmsdos`
|
||||||
- output: `net.exe`
|
- output: `net.exe`
|
||||||
|
|
||||||
The object list includes:
|
The historical object list includes the original C sources plus `kern.asm`.
|
||||||
|
|
||||||
- `net.c`
|
### CMake / Open Watcom maintainer build
|
||||||
- `tools.c`
|
|
||||||
- `netcall.c`
|
|
||||||
- `ncpcall.c`
|
|
||||||
- `login.c`
|
|
||||||
- `map.c`
|
|
||||||
- `slist.c`
|
|
||||||
- `nwcrypt.c`
|
|
||||||
- `nwdebug.c`
|
|
||||||
- `nwtests.c`
|
|
||||||
- `capture.c`
|
|
||||||
- `kern.asm`
|
|
||||||
|
|
||||||
|
The modern CMake build can rebuild `net.exe` with Open Watcom v2 on Linux.
|
||||||
|
|
||||||
### CMake status
|
Configure with:
|
||||||
|
|
||||||
A `CMakeLists.txt` is present, but in this snapshot it is only a **partial modern build description**. It defines include paths, version-related macros, and install rules, while the actual `add_executable(...)` line is still commented out. That means it is better understood as packaging metadata than a ready-to-use complete build system.
|
```bash
|
||||||
|
cmake -S . -B build -DMARS_NWE_BUILD_DOSUTILS=ON
|
||||||
|
cmake --build build
|
||||||
|
```
|
||||||
|
|
||||||
|
The CMake build:
|
||||||
|
|
||||||
|
- assembles `kern_wasm.asm` with `wasm`
|
||||||
|
- compiles each C file to a binary-directory `.obj`
|
||||||
|
- links `net.exe` from those binary-directory objects
|
||||||
|
- keeps `.obj`/`.o` intermediate files out of the source directory
|
||||||
|
|
||||||
|
If old object files were produced in the source tree by an earlier build, remove them once:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd dosutils
|
||||||
|
rm -f *.o *.obj
|
||||||
|
```
|
||||||
|
|
||||||
|
### Default install behavior
|
||||||
|
|
||||||
|
When `MARS_NWE_BUILD_DOSUTILS` is disabled, CMake installs a prebuilt `net.exe` from the source tree.
|
||||||
|
|
||||||
|
That keeps the normal mars_nwe build independent from Open Watcom. Maintainers can enable the Open Watcom build only when they want to regenerate the DOS binary.
|
||||||
|
|
||||||
## Installation layout
|
## Installation layout
|
||||||
|
|
||||||
The CMake install rules deploy the same binary multiple times into `SYS/public`:
|
The install rules deploy the same binary multiple times into `SYS/public`, including:
|
||||||
|
|
||||||
- `net.exe`
|
- `net.exe`
|
||||||
- `login.exe`
|
- `login.exe`
|
||||||
@@ -300,19 +502,32 @@ The CMake install rules deploy the same binary multiple times into `SYS/public`:
|
|||||||
- `mapdel.exe`
|
- `mapdel.exe`
|
||||||
- `logout.exe`
|
- `logout.exe`
|
||||||
- `slist.exe`
|
- `slist.exe`
|
||||||
|
- `flag.exe`
|
||||||
|
- `flagdir.exe`
|
||||||
- `capture.exe`
|
- `capture.exe`
|
||||||
- `endcap.exe`
|
- `endcap.exe`
|
||||||
|
|
||||||
They also install minimal `login.exe` and `map.exe` copies into `SYS/login`.
|
They also install selected copies such as `login.exe`, `map.exe`, and `slist.exe` into `SYS/login` where appropriate.
|
||||||
|
|
||||||
|
## Development notes
|
||||||
|
|
||||||
|
- `kern_wasm.asm` is the 16-bit Open Watcom assembly implementation used by the modern build.
|
||||||
|
- `kern.c` was an experimental C-side test wrapper and is no longer required by the current Client32 FLAG/FLAGDIR path.
|
||||||
|
- `c32ncp.c` and `c32ncp.h` contain reusable Client32 NCP helper functions for DOS tools.
|
||||||
|
- The verified Client32 path uses NCP 87 subfunction 6 for obtaining DOS information and subfunction 7 for modifying DOS information.
|
||||||
|
- For modify operations, use the modify information mask `DM_ATTRIBUTES` (`0x00000002`) rather than the read-side `RIM_ATTRIBUTES` mask.
|
||||||
|
- High NetWare attributes must be stored and displayed as 32-bit values even in 16-bit DOS builds.
|
||||||
|
|
||||||
## Project status and limitations
|
## Project status and limitations
|
||||||
|
|
||||||
This is legacy DOS networking code from the mid-1990s, and a few caveats are worth keeping in mind:
|
This is legacy DOS networking code from the mid-1990s, and a few caveats are worth keeping in mind:
|
||||||
|
|
||||||
- The original README explicitly says the program was still incomplete.
|
- The code is tightly coupled to DOS, IPX/NCP behavior, and mars_nwe/NetWare requester semantics.
|
||||||
- `SLIST` is not implemented in the provided source snapshot.
|
- Client32 support has been validated for the FLAG-family tools, but not yet generalized to every command.
|
||||||
- Parts of the authentication and password-change path still rely on older unencrypted operations when the newer keyed flow is unavailable or disabled.
|
- DOSX/VLM/NETX fallback testing is still pending.
|
||||||
- The code is tightly coupled to DOS, IPX/NCP behavior, and mars_nwe-specific expectations.
|
- `FLAGDIR` currently focuses on the NetWare 386-style attributes and simple mapped directory paths.
|
||||||
|
- OS/2 requester behavior is still future work.
|
||||||
|
- Some authentication and password-change paths still keep older calls as compatibility fallbacks.
|
||||||
|
|
||||||
## Historical metadata
|
## Historical metadata
|
||||||
|
|
||||||
@@ -325,7 +540,6 @@ From the included project metadata:
|
|||||||
- platforms: `DOS`, `DOSEMU`
|
- platforms: `DOS`, `DOSEMU`
|
||||||
- author/maintainer: Martin Stover
|
- author/maintainer: Martin Stover
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
No standalone license file is included in the provided snapshot. The source files do contain copyright notices naming **Martin Stover**. Anyone planning to redistribute or modernize the project should verify licensing status before publishing derivative releases.
|
No standalone license file is included in the provided snapshot. The source files do contain copyright notices naming Martin Stover. Anyone planning to redistribute or modernize the project should verify licensing status before publishing derivative releases.
|
||||||
|
|||||||
595
c32ncp.c
Normal file
595
c32ncp.c
Normal file
@@ -0,0 +1,595 @@
|
|||||||
|
#include "net.h"
|
||||||
|
#include "c32ncp.h"
|
||||||
|
|
||||||
|
/* c32ncp.c - Client32 NCP helpers for mars-dosutils */
|
||||||
|
static void c32_put_word_lh(uint8 *p, uint16 v)
|
||||||
|
{
|
||||||
|
p[0] = (uint8)(v & 0xff);
|
||||||
|
p[1] = (uint8)((v >> 8) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void c32_put_dword_lh(uint8 *p, uint32 v)
|
||||||
|
{
|
||||||
|
p[0] = (uint8)(v & 0xff);
|
||||||
|
p[1] = (uint8)((v >> 8) & 0xff);
|
||||||
|
p[2] = (uint8)((v >> 16) & 0xff);
|
||||||
|
p[3] = (uint8)((v >> 24) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void c32_put_dword_hl(uint8 *p, uint32 v)
|
||||||
|
{
|
||||||
|
p[0] = (uint8)((v >> 24) & 0xff);
|
||||||
|
p[1] = (uint8)((v >> 16) & 0xff);
|
||||||
|
p[2] = (uint8)((v >> 8) & 0xff);
|
||||||
|
p[3] = (uint8)(v & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16 c32_get_word_lh(uint8 *p)
|
||||||
|
{
|
||||||
|
return((uint16)(p[0] | ((uint16)p[1] << 8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32 c32_get_dword_lh(uint8 *p)
|
||||||
|
{
|
||||||
|
return((uint32)p[0] |
|
||||||
|
((uint32)p[1] << 8) |
|
||||||
|
((uint32)p[2] << 16) |
|
||||||
|
((uint32)p[3] << 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
static UI c32_build_handle_path(uint8 *buf, uint8 dhandle,
|
||||||
|
uint16 dirbase, uint8 style,
|
||||||
|
int count,
|
||||||
|
const char *c1, const char *c2, const char *c3)
|
||||||
|
{
|
||||||
|
uint8 *p;
|
||||||
|
int l;
|
||||||
|
UI used;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DeveloperNet/ncpdos16 path structure used by NCP87/S6 through
|
||||||
|
* Client32 COMPATNcpRequestReply.
|
||||||
|
*
|
||||||
|
* This is the exact shape verified by TESTS NCP87C32AUTO:
|
||||||
|
* 00 02 00 00 00 00 01 09 4C 4F 47 49 4E 2E 45 58 45
|
||||||
|
*
|
||||||
|
* Meaning:
|
||||||
|
* word[1] = short dir handle
|
||||||
|
* word[3] = dir base
|
||||||
|
* byte[5] = dirstyle
|
||||||
|
* byte[6] = component count
|
||||||
|
* then len/name components
|
||||||
|
*
|
||||||
|
* The old/simple struct used by the INT 21h F257 fallback is not accepted
|
||||||
|
* by this Client32 path.
|
||||||
|
*/
|
||||||
|
memset(buf, 0, 0x140);
|
||||||
|
|
||||||
|
if (dhandle) {
|
||||||
|
c32_put_word_lh(buf + 1, (uint16)dhandle);
|
||||||
|
c32_put_word_lh(buf + 3, dirbase);
|
||||||
|
buf[5] = style;
|
||||||
|
} else {
|
||||||
|
buf[5] = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buf + 6;
|
||||||
|
*p++ = (uint8)count;
|
||||||
|
|
||||||
|
if (count > 0 && c1) {
|
||||||
|
l = strlen(c1);
|
||||||
|
if (l > 255) l = 255;
|
||||||
|
*p++ = (uint8)l;
|
||||||
|
memcpy(p, c1, l);
|
||||||
|
p += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 1 && c2) {
|
||||||
|
l = strlen(c2);
|
||||||
|
if (l > 255) l = 255;
|
||||||
|
*p++ = (uint8)l;
|
||||||
|
memcpy(p, c2, l);
|
||||||
|
p += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 2 && c3) {
|
||||||
|
l = strlen(c3);
|
||||||
|
if (l > 255) l = 255;
|
||||||
|
*p++ = (uint8)l;
|
||||||
|
memcpy(p, c3, l);
|
||||||
|
p += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
used = (UI)(p - buf);
|
||||||
|
c32_put_word_lh(buf + 0x13c, used);
|
||||||
|
return(used);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static UI c32_build_handle_path_from_dos_path(uint8 *buf, uint8 dhandle,
|
||||||
|
uint16 dirbase, uint8 style,
|
||||||
|
const char *dospath)
|
||||||
|
{
|
||||||
|
uint8 *p;
|
||||||
|
uint8 *countp;
|
||||||
|
int count = 0;
|
||||||
|
const char *s;
|
||||||
|
UI used;
|
||||||
|
|
||||||
|
memset(buf, 0, 0x140);
|
||||||
|
|
||||||
|
if (dhandle) {
|
||||||
|
c32_put_word_lh(buf + 1, (uint16)dhandle);
|
||||||
|
c32_put_word_lh(buf + 3, dirbase);
|
||||||
|
buf[5] = style;
|
||||||
|
} else {
|
||||||
|
buf[5] = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buf + 6;
|
||||||
|
countp = p++;
|
||||||
|
|
||||||
|
s = dospath;
|
||||||
|
if (!s) s = "";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DOS tools mostly pass relative paths against the current directory
|
||||||
|
* handle. Accept simple DOS decoration here so RIGHTS can pass "." or
|
||||||
|
* ".\\UDIR\\FILE" without constructing path components in the caller.
|
||||||
|
*/
|
||||||
|
if (s[0] && s[1] == ':')
|
||||||
|
s += 2;
|
||||||
|
|
||||||
|
while (*s == '\\' || *s == '/')
|
||||||
|
s++;
|
||||||
|
|
||||||
|
while (*s && p < buf + 0x138 && count < 32) {
|
||||||
|
const char *start;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
while (*s == '\\' || *s == '/')
|
||||||
|
s++;
|
||||||
|
|
||||||
|
if (*s == '.'
|
||||||
|
&& (s[1] == '\0' || s[1] == '\\' || s[1] == '/')) {
|
||||||
|
s++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = s;
|
||||||
|
while (*s && *s != '\\' && *s != '/')
|
||||||
|
s++;
|
||||||
|
|
||||||
|
len = (int)(s - start);
|
||||||
|
if (len <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (len > 255)
|
||||||
|
len = 255;
|
||||||
|
|
||||||
|
if (p + 1 + len >= buf + 0x138)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*p++ = (uint8)len;
|
||||||
|
memcpy(p, start, len);
|
||||||
|
p += len;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*countp = (uint8)count;
|
||||||
|
|
||||||
|
used = (UI)(p - buf);
|
||||||
|
c32_put_word_lh(buf + 0x13c, used);
|
||||||
|
return(used);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Current verified Client32 path for mars-nwe DOS utilities:
|
||||||
|
*
|
||||||
|
* C32_MapVar_Probe(4,0) -> connRefLocal FFFF:FFFE
|
||||||
|
* C32_OpenRef_Probe(connRefLocal) -> Client32 handle, e.g. 0101:0001
|
||||||
|
*
|
||||||
|
* C32_MapVar_Probe currently contains the confirmed Mars server-name scan
|
||||||
|
* shape. It is intentionally kept small and isolated here so FLAG and later
|
||||||
|
* tools do not carry the old exploratory tests.
|
||||||
|
*/
|
||||||
|
int c32_get_ncp_handle(uint16 *handle_lo, uint16 *handle_hi)
|
||||||
|
{
|
||||||
|
uint8 mapout[32];
|
||||||
|
uint8 openout[32];
|
||||||
|
uint16 map_ret_ax, map_ret_dx;
|
||||||
|
uint16 cref_lo, cref_hi;
|
||||||
|
uint16 open_ret_ax, open_ret_dx;
|
||||||
|
|
||||||
|
if (!handle_lo || !handle_hi)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
*handle_lo = 0;
|
||||||
|
*handle_hi = 0;
|
||||||
|
|
||||||
|
memset(mapout, 0, sizeof(mapout));
|
||||||
|
C32_MapVar_Probe(4, 0, mapout);
|
||||||
|
|
||||||
|
map_ret_ax = c32_get_word_lh(mapout + 14);
|
||||||
|
map_ret_dx = c32_get_word_lh(mapout + 16);
|
||||||
|
cref_lo = c32_get_word_lh(mapout + 22);
|
||||||
|
cref_hi = c32_get_word_lh(mapout + 24);
|
||||||
|
|
||||||
|
if (map_ret_ax != 0 || map_ret_dx != 0 || (cref_lo == 0 && cref_hi == 0))
|
||||||
|
return(2);
|
||||||
|
|
||||||
|
memset(openout, 0, sizeof(openout));
|
||||||
|
C32_OpenRef_Probe(cref_lo, cref_hi, openout);
|
||||||
|
|
||||||
|
open_ret_ax = c32_get_word_lh(openout + 14);
|
||||||
|
open_ret_dx = c32_get_word_lh(openout + 16);
|
||||||
|
*handle_lo = c32_get_word_lh(openout + 18);
|
||||||
|
*handle_hi = c32_get_word_lh(openout + 20);
|
||||||
|
|
||||||
|
if (open_ret_ax != 0 || open_ret_dx != 0 || (*handle_lo == 0 && *handle_hi == 0))
|
||||||
|
return(3);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int c32_ncp87_obtain_rim_attributes(const char *name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint32 *attr_out,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out)
|
||||||
|
{
|
||||||
|
uint16 handle_lo, handle_hi;
|
||||||
|
uint8 hdr[16];
|
||||||
|
uint8 path[0x140];
|
||||||
|
uint8 rep0[0x60];
|
||||||
|
uint8 rep1[0x110];
|
||||||
|
uint8 rawout[32];
|
||||||
|
uint16 raw_ret_ax, raw_ret_dx;
|
||||||
|
uint16 actual_lo;
|
||||||
|
int path_len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!name || !attr_out)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
*attr_out = 0;
|
||||||
|
if (actual_out) *actual_out = 0;
|
||||||
|
if (handle_lo_out) *handle_lo_out = 0;
|
||||||
|
if (handle_hi_out) *handle_hi_out = 0;
|
||||||
|
|
||||||
|
rc = c32_get_ncp_handle(&handle_lo, &handle_hi);
|
||||||
|
if (rc)
|
||||||
|
return(10 + rc);
|
||||||
|
|
||||||
|
memset(hdr, 0, sizeof(hdr));
|
||||||
|
hdr[0] = 6; /* NCP87 subfunction 6 */
|
||||||
|
hdr[1] = 0; /* source namespace DOS */
|
||||||
|
hdr[2] = 0; /* target namespace DOS */
|
||||||
|
c32_put_word_lh(hdr + 3, 0x0006); /* SA_ALL */
|
||||||
|
c32_put_dword_lh(hdr + 5, 0x00000004UL); /* RIM_ATTRIBUTES */
|
||||||
|
|
||||||
|
path_len = c32_build_handle_path(path, (uint8)dir_handle, 0, 0, 1,
|
||||||
|
name, NULL, NULL);
|
||||||
|
|
||||||
|
memset(rep0, 0, sizeof(rep0));
|
||||||
|
memset(rep1, 0, sizeof(rep1));
|
||||||
|
memset(rawout, 0, sizeof(rawout));
|
||||||
|
|
||||||
|
C32_NCP87_Raw5_Probe(handle_lo, handle_hi,
|
||||||
|
hdr, 9,
|
||||||
|
path, (UI)path_len,
|
||||||
|
rep0, 0x4d,
|
||||||
|
rep1, 0x100,
|
||||||
|
rawout);
|
||||||
|
|
||||||
|
raw_ret_ax = c32_get_word_lh(rawout + 14);
|
||||||
|
raw_ret_dx = c32_get_word_lh(rawout + 16);
|
||||||
|
actual_lo = c32_get_word_lh(rawout + 18);
|
||||||
|
|
||||||
|
if (raw_ret_ax != 0 || raw_ret_dx != 0)
|
||||||
|
return(20);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verified reply layout for RIM_ATTRIBUTES:
|
||||||
|
* REP0+4 little-endian dword = DOS attributes
|
||||||
|
* Example LOGIN.EXE: 20h archive.
|
||||||
|
*/
|
||||||
|
*attr_out = c32_get_dword_lh(rep0 + 4);
|
||||||
|
|
||||||
|
if (actual_out) *actual_out = actual_lo;
|
||||||
|
if (handle_lo_out) *handle_lo_out = handle_lo;
|
||||||
|
if (handle_hi_out) *handle_hi_out = handle_hi;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int c32_ncp87_modify_dos_attributes(char *name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint32 attrs,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out)
|
||||||
|
{
|
||||||
|
uint16 handle_lo, handle_hi;
|
||||||
|
uint8 modbuf[64];
|
||||||
|
uint8 path[0x140];
|
||||||
|
uint8 rep0[0x20];
|
||||||
|
uint8 rep1[0x20];
|
||||||
|
uint8 rawout[32];
|
||||||
|
uint8 *p;
|
||||||
|
UI mod_len;
|
||||||
|
UI path_len;
|
||||||
|
uint16 raw_ret_ax, raw_ret_dx;
|
||||||
|
uint16 actual_lo;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
if (actual_out)
|
||||||
|
*actual_out = 0;
|
||||||
|
if (handle_lo_out)
|
||||||
|
*handle_lo_out = 0;
|
||||||
|
if (handle_hi_out)
|
||||||
|
*handle_hi_out = 0;
|
||||||
|
|
||||||
|
rc = c32_get_ncp_handle(&handle_lo, &handle_hi);
|
||||||
|
if (rc)
|
||||||
|
return(10 + rc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NCP 87 subfunction 7: Modify DOS information.
|
||||||
|
*
|
||||||
|
* First request fragment contains the fixed header and DOS info structure.
|
||||||
|
* Second request fragment contains the verified SDK-style path structure.
|
||||||
|
*
|
||||||
|
* This avoids the old INT 21h F257 modify path, which can hang under DOS
|
||||||
|
* Client32 for high FLAG bits such as Transactional.
|
||||||
|
*/
|
||||||
|
memset(modbuf, 0, sizeof(modbuf));
|
||||||
|
p = modbuf;
|
||||||
|
|
||||||
|
*p++ = 7; /* subfunction: modify DOS info */
|
||||||
|
*p++ = 0; /* namespace DOS */
|
||||||
|
*p++ = 0; /* reserved */
|
||||||
|
c32_put_word_lh(p, 0x0006); p += 2; /* SA_ALL */
|
||||||
|
c32_put_dword_lh(p, 0x00000002UL); p += 4; /* DM_ATTRIBUTES: attributes */
|
||||||
|
|
||||||
|
c32_put_dword_lh(p, attrs); p += 4; /* Attributes */
|
||||||
|
memset(p, 0, 34); p += 34; /* rest of DOS info */
|
||||||
|
mod_len = (UI)(p - modbuf);
|
||||||
|
|
||||||
|
path_len = c32_build_handle_path(path, (uint8)dir_handle, 0, 0, 1,
|
||||||
|
name, NULL, NULL);
|
||||||
|
|
||||||
|
memset(rep0, 0, sizeof(rep0));
|
||||||
|
memset(rep1, 0, sizeof(rep1));
|
||||||
|
memset(rawout, 0, sizeof(rawout));
|
||||||
|
|
||||||
|
C32_NCP87_Raw5_Probe(handle_lo, handle_hi,
|
||||||
|
modbuf, mod_len,
|
||||||
|
path, path_len,
|
||||||
|
rep0, sizeof(rep0),
|
||||||
|
rep1, sizeof(rep1),
|
||||||
|
rawout);
|
||||||
|
|
||||||
|
raw_ret_ax = c32_get_word_lh(rawout + 14);
|
||||||
|
raw_ret_dx = c32_get_word_lh(rawout + 16);
|
||||||
|
actual_lo = c32_get_word_lh(rawout + 18);
|
||||||
|
|
||||||
|
if (actual_out)
|
||||||
|
*actual_out = actual_lo;
|
||||||
|
if (handle_lo_out)
|
||||||
|
*handle_lo_out = handle_lo;
|
||||||
|
if (handle_hi_out)
|
||||||
|
*handle_hi_out = handle_hi;
|
||||||
|
|
||||||
|
if (raw_ret_ax != 0 || raw_ret_dx != 0)
|
||||||
|
return(20);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int c32_ncp87_get_effective_rights(const char *path_name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint16 *rights_out,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out)
|
||||||
|
{
|
||||||
|
uint16 handle_lo, handle_hi;
|
||||||
|
uint8 hdr[16];
|
||||||
|
uint8 path[0x140];
|
||||||
|
uint8 rep0[0x20];
|
||||||
|
uint8 rep1[0x20];
|
||||||
|
uint8 rawout[32];
|
||||||
|
uint16 raw_ret_ax, raw_ret_dx;
|
||||||
|
uint16 actual_lo;
|
||||||
|
uint16 rights0;
|
||||||
|
uint16 rights4;
|
||||||
|
UI path_len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!rights_out)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
*rights_out = 0;
|
||||||
|
if (actual_out) *actual_out = 0;
|
||||||
|
if (handle_lo_out) *handle_lo_out = 0;
|
||||||
|
if (handle_hi_out) *handle_hi_out = 0;
|
||||||
|
|
||||||
|
rc = c32_get_ncp_handle(&handle_lo, &handle_hi);
|
||||||
|
if (rc)
|
||||||
|
return(10 + rc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NCP 87 subfunction 29: Get effective rights.
|
||||||
|
*
|
||||||
|
* This mirrors ncpfs ncp_get_eff_directory_rights():
|
||||||
|
* byte 29
|
||||||
|
* byte source namespace
|
||||||
|
* byte target namespace
|
||||||
|
* word search attributes, little endian
|
||||||
|
* dword reserved, zero
|
||||||
|
* handle/path
|
||||||
|
*
|
||||||
|
* Reply is a little-endian word with NCP rights bits.
|
||||||
|
*/
|
||||||
|
memset(hdr, 0, sizeof(hdr));
|
||||||
|
hdr[0] = 29;
|
||||||
|
hdr[1] = 0; /* source namespace DOS */
|
||||||
|
hdr[2] = 0; /* target namespace DOS */
|
||||||
|
c32_put_word_lh(hdr + 3, 0x0006); /* SA_ALL */
|
||||||
|
c32_put_dword_lh(hdr + 5, 0L); /* reserved */
|
||||||
|
|
||||||
|
path_len = c32_build_handle_path_from_dos_path(path, (uint8)dir_handle,
|
||||||
|
0, 0, path_name);
|
||||||
|
|
||||||
|
memset(rep0, 0, sizeof(rep0));
|
||||||
|
memset(rep1, 0, sizeof(rep1));
|
||||||
|
memset(rawout, 0, sizeof(rawout));
|
||||||
|
|
||||||
|
C32_NCP87_Raw5_Probe(handle_lo, handle_hi,
|
||||||
|
hdr, 9,
|
||||||
|
path, path_len,
|
||||||
|
rep0, sizeof(rep0),
|
||||||
|
rep1, sizeof(rep1),
|
||||||
|
rawout);
|
||||||
|
|
||||||
|
raw_ret_ax = c32_get_word_lh(rawout + 14);
|
||||||
|
raw_ret_dx = c32_get_word_lh(rawout + 16);
|
||||||
|
actual_lo = c32_get_word_lh(rawout + 18);
|
||||||
|
|
||||||
|
if (actual_out) *actual_out = actual_lo;
|
||||||
|
if (handle_lo_out) *handle_lo_out = handle_lo;
|
||||||
|
if (handle_hi_out) *handle_hi_out = handle_hi;
|
||||||
|
|
||||||
|
if (raw_ret_ax != 0 || raw_ret_dx != 0)
|
||||||
|
return(20);
|
||||||
|
|
||||||
|
rights0 = c32_get_word_lh(rep0 + 0);
|
||||||
|
rights4 = c32_get_word_lh(rep0 + 4);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Most NCP replies start at REP0+0. The existing RIM_ATTRIBUTES helper
|
||||||
|
* found attributes at REP0+4 on Client32. Accept the +4 location only
|
||||||
|
* if +0 is empty, so restricted rights value 0 still works when +4 is
|
||||||
|
* also zero.
|
||||||
|
*/
|
||||||
|
if (rights0 == 0 && rights4 != 0)
|
||||||
|
rights0 = rights4;
|
||||||
|
|
||||||
|
*rights_out = rights0;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int c32_ncp87_add_trustee_rights(const char *path_name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint32 object_id,
|
||||||
|
uint16 rights,
|
||||||
|
uint16 rights_mask,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out)
|
||||||
|
{
|
||||||
|
uint16 handle_lo, handle_hi;
|
||||||
|
uint8 hdr[16];
|
||||||
|
uint8 reqpath[0x180];
|
||||||
|
uint8 rep0[0x20];
|
||||||
|
uint8 rep1[0x20];
|
||||||
|
uint8 rawout[32];
|
||||||
|
uint16 raw_ret_ax, raw_ret_dx;
|
||||||
|
uint16 actual_lo;
|
||||||
|
UI path_struct_len;
|
||||||
|
UI reqpath_len;
|
||||||
|
uint8 *tp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (actual_out) *actual_out = 0;
|
||||||
|
if (handle_lo_out) *handle_lo_out = 0;
|
||||||
|
if (handle_hi_out) *handle_hi_out = 0;
|
||||||
|
|
||||||
|
rc = c32_get_ncp_handle(&handle_lo, &handle_hi);
|
||||||
|
if (rc)
|
||||||
|
return(10 + rc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NCP 87 subfunction 10: Add trustee.
|
||||||
|
*
|
||||||
|
* This mirrors ncpfs ncp_ns_trustee_add():
|
||||||
|
* byte 10
|
||||||
|
* byte namespace DOS
|
||||||
|
* byte reserved
|
||||||
|
* word search attributes, little endian
|
||||||
|
* word rights mask, little endian
|
||||||
|
* word object count, little endian
|
||||||
|
* handle/path
|
||||||
|
* trustee array at request offset 16 + 307
|
||||||
|
*
|
||||||
|
* Client32 Raw5 has two request fragments, so the second fragment carries
|
||||||
|
* the handle/path and the padded trustee record.
|
||||||
|
*/
|
||||||
|
memset(hdr, 0, sizeof(hdr));
|
||||||
|
hdr[0] = 10;
|
||||||
|
hdr[1] = 0; /* DOS namespace */
|
||||||
|
hdr[2] = 0; /* reserved */
|
||||||
|
c32_put_word_lh(hdr + 3, 0x8006); /* SA_ALL: files/subdirs + system + hidden */
|
||||||
|
c32_put_word_lh(hdr + 5, rights_mask);
|
||||||
|
c32_put_word_lh(hdr + 7, 1); /* one trustee */
|
||||||
|
|
||||||
|
memset(reqpath, 0, sizeof(reqpath));
|
||||||
|
path_struct_len = c32_build_handle_path_from_dos_path(reqpath,
|
||||||
|
(uint8)dir_handle,
|
||||||
|
0, 0,
|
||||||
|
path_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ncpfs seeks to absolute packet offset 16+307 before writing the
|
||||||
|
* trustee list. The NCP request header is 7 bytes, so inside the NCP
|
||||||
|
* payload the trustee list begins at:
|
||||||
|
*
|
||||||
|
* (16 + 307) - 7 = 316
|
||||||
|
*
|
||||||
|
* Our first Raw5 request fragment is the 9-byte subfunction header,
|
||||||
|
* so the trustee list begins in the second fragment at:
|
||||||
|
*
|
||||||
|
* 316 - 9 = 307
|
||||||
|
*/
|
||||||
|
if (path_struct_len > 307)
|
||||||
|
return(2);
|
||||||
|
|
||||||
|
tp = reqpath + 307;
|
||||||
|
c32_put_dword_hl(tp, object_id); tp += 4;
|
||||||
|
c32_put_word_lh(tp, rights); tp += 2;
|
||||||
|
reqpath_len = (UI)(tp - reqpath);
|
||||||
|
|
||||||
|
memset(rep0, 0, sizeof(rep0));
|
||||||
|
memset(rep1, 0, sizeof(rep1));
|
||||||
|
memset(rawout, 0, sizeof(rawout));
|
||||||
|
|
||||||
|
C32_NCP87_Raw5_Probe(handle_lo, handle_hi,
|
||||||
|
hdr, 9,
|
||||||
|
reqpath, reqpath_len,
|
||||||
|
rep0, sizeof(rep0),
|
||||||
|
rep1, sizeof(rep1),
|
||||||
|
rawout);
|
||||||
|
|
||||||
|
raw_ret_ax = c32_get_word_lh(rawout + 14);
|
||||||
|
raw_ret_dx = c32_get_word_lh(rawout + 16);
|
||||||
|
actual_lo = c32_get_word_lh(rawout + 18);
|
||||||
|
|
||||||
|
if (actual_out) *actual_out = actual_lo;
|
||||||
|
if (handle_lo_out) *handle_lo_out = handle_lo;
|
||||||
|
if (handle_hi_out) *handle_hi_out = handle_hi;
|
||||||
|
|
||||||
|
if (raw_ret_ax != 0 || raw_ret_dx != 0)
|
||||||
|
return(20);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
38
c32ncp.h
Normal file
38
c32ncp.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* c32ncp.h - minimal Client32 NCP helpers for mars-dosutils */
|
||||||
|
|
||||||
|
#ifndef C32NCP_H
|
||||||
|
#define C32NCP_H
|
||||||
|
int c32_get_ncp_handle(uint16 *handle_lo, uint16 *handle_hi);
|
||||||
|
|
||||||
|
int c32_ncp87_obtain_rim_attributes(const char *name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint32 *attr_out,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out);
|
||||||
|
|
||||||
|
|
||||||
|
int c32_ncp87_modify_dos_attributes(char *name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint32 attrs,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out);
|
||||||
|
|
||||||
|
int c32_ncp87_get_effective_rights(const char *path,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint16 *rights_out,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out);
|
||||||
|
|
||||||
|
int c32_ncp87_add_trustee_rights(const char *path_name,
|
||||||
|
uint16 dir_handle,
|
||||||
|
uint32 object_id,
|
||||||
|
uint16 rights,
|
||||||
|
uint16 rights_mask,
|
||||||
|
uint16 *actual_out,
|
||||||
|
uint16 *handle_lo_out,
|
||||||
|
uint16 *handle_hi_out);
|
||||||
|
|
||||||
|
#endif
|
||||||
509
flag.c
Normal file
509
flag.c
Normal file
@@ -0,0 +1,509 @@
|
|||||||
|
/* flag.c - Novell FLAG-like DOS utility, stage 1 */
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "c32ncp.h"
|
||||||
|
#include <dos.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FLAG v4b: NCP 87 namespace DOS info.
|
||||||
|
*
|
||||||
|
* ncpfs reference:
|
||||||
|
* ncp_ns_modify_entry_dos_info():
|
||||||
|
* subfunction 7, namespace DOS, search attrs SA_ALL,
|
||||||
|
* ModifyInformationMask, struct ncp_dos_info, handle/path.
|
||||||
|
*
|
||||||
|
* We use dirstyle=0 (short directory handle) against the current DOS
|
||||||
|
* directory handle and a one-component DOS filename.
|
||||||
|
*/
|
||||||
|
#define FLAG_NW_NS_DOS 0x00
|
||||||
|
#define FLAG_SA_ALL 0x0006
|
||||||
|
#define FLAG_RIM_ATTRIBUTES 0x00000004UL
|
||||||
|
|
||||||
|
#define NWFA_RO 0x00000001UL
|
||||||
|
#define NWFA_H 0x00000002UL
|
||||||
|
#define NWFA_SY 0x00000004UL
|
||||||
|
#define NWFA_A 0x00000020UL
|
||||||
|
#define NWFA_S 0x00000080UL
|
||||||
|
#define NWFA_T 0x00001000UL
|
||||||
|
#define NWFA_RA 0x00004000UL
|
||||||
|
#define NWFA_WA 0x00008000UL
|
||||||
|
#define NWFA_P 0x00010000UL
|
||||||
|
#define NWFA_RI 0x00020000UL
|
||||||
|
#define NWFA_DI 0x00040000UL
|
||||||
|
#define NWFA_CI 0x00080000UL
|
||||||
|
|
||||||
|
static void flag_put_word_lh(uint8 *p, uint16 v)
|
||||||
|
{
|
||||||
|
p[0] = (uint8)(v & 0xff);
|
||||||
|
p[1] = (uint8)((v >> 8) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flag_put_dword_lh(uint8 *p, uint32 v)
|
||||||
|
{
|
||||||
|
p[0] = (uint8)(v & 0xff);
|
||||||
|
p[1] = (uint8)((v >> 8) & 0xff);
|
||||||
|
p[2] = (uint8)((v >> 16) & 0xff);
|
||||||
|
p[3] = (uint8)((v >> 24) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32 flag_get_dword_lh(uint8 *p)
|
||||||
|
{
|
||||||
|
return((uint32)p[0] |
|
||||||
|
((uint32)p[1] << 8) |
|
||||||
|
((uint32)p[2] << 16) |
|
||||||
|
((uint32)p[3] << 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_get_current_drive(void)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
|
||||||
|
regs.h.ah = 0x19; /* DOS get current default drive */
|
||||||
|
int86(0x21, ®s, ®s); /* AL = 0 for A:, 1 for B:, ... */
|
||||||
|
|
||||||
|
return((int)regs.h.al);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_current_dhandle(uint8 *dhandle)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive;
|
||||||
|
|
||||||
|
drive = flag_get_current_drive();
|
||||||
|
if (get_drive_info((uint8)drive, &connid, dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_add_handle_path(uint8 *p, uint8 dhandle, char *name)
|
||||||
|
{
|
||||||
|
int nlen;
|
||||||
|
|
||||||
|
nlen = strlen(name);
|
||||||
|
if (nlen > 255) nlen = 255;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle/path:
|
||||||
|
* volume/handle byte
|
||||||
|
* dir base dword
|
||||||
|
* dirstyle byte (0 = short dir handle)
|
||||||
|
* path components: 1 component, length, bytes
|
||||||
|
*/
|
||||||
|
*p++ = dhandle;
|
||||||
|
flag_put_dword_lh(p, 0L); p += 4;
|
||||||
|
*p++ = 0; /* dirstyle = handle */
|
||||||
|
*p++ = 1; /* one path component */
|
||||||
|
*p++ = (uint8)nlen;
|
||||||
|
memcpy(p, name, nlen);
|
||||||
|
p += nlen;
|
||||||
|
|
||||||
|
return(1 + 4 + 1 + 1 + 1 + nlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_ncp87_obtain_attrs(char *name, uint32 *attrs)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 data[320];
|
||||||
|
} req;
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 data[128];
|
||||||
|
} repl;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint8 *p;
|
||||||
|
int hlen;
|
||||||
|
|
||||||
|
if (flag_current_dhandle(&dhandle))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prefer the verified Client32 NCP87 path. If it is not available,
|
||||||
|
* fall back to the historical INT 21h/Net_Call path below.
|
||||||
|
*/
|
||||||
|
if (c32_ncp87_obtain_rim_attributes(name, (uint16)dhandle,
|
||||||
|
attrs, NULL, NULL, NULL) == 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
memset(&repl, 0, sizeof(repl));
|
||||||
|
|
||||||
|
p = req.data;
|
||||||
|
*p++ = 6; /* subfunction: obtain file/subdir info */
|
||||||
|
*p++ = FLAG_NW_NS_DOS; /* source namespace */
|
||||||
|
*p++ = FLAG_NW_NS_DOS; /* target namespace */
|
||||||
|
flag_put_word_lh(p, FLAG_SA_ALL); p += 2;
|
||||||
|
flag_put_dword_lh(p, FLAG_RIM_ATTRIBUTES); p += 4;
|
||||||
|
hlen = flag_add_handle_path(p, dhandle, name);
|
||||||
|
p += hlen;
|
||||||
|
|
||||||
|
req.len = (uint16)(p - req.data);
|
||||||
|
repl.len = sizeof(repl.data);
|
||||||
|
|
||||||
|
neterrno = Net_Call(0xF257, &req, &repl);
|
||||||
|
if (neterrno)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With RIM_ATTRIBUTES only, ncpfs expects NSI_Attributes first.
|
||||||
|
* First dword is the 32-bit Attributes field.
|
||||||
|
*/
|
||||||
|
if (attrs)
|
||||||
|
*attrs = flag_get_dword_lh(repl.data);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_ncp87_modify_attrs(char *name, uint32 attrs)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 data[384];
|
||||||
|
} req;
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 data[8];
|
||||||
|
} repl;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint8 *p;
|
||||||
|
int hlen;
|
||||||
|
|
||||||
|
if (flag_current_dhandle(&dhandle))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prefer verified Client32 modify path. The old INT 21h/F257 modify path
|
||||||
|
* can hang under DOS Client32 for high FLAG bits such as T/P/DI/RI.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
uint16 actual = 0;
|
||||||
|
uint16 hlo = 0;
|
||||||
|
uint16 hhi = 0;
|
||||||
|
if (!c32_ncp87_modify_dos_attributes(name, (uint16)dhandle, attrs,
|
||||||
|
&actual, &hlo, &hhi))
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
memset(&repl, 0, sizeof(repl));
|
||||||
|
|
||||||
|
p = req.data;
|
||||||
|
*p++ = 7; /* subfunction: modify DOS info */
|
||||||
|
*p++ = FLAG_NW_NS_DOS;
|
||||||
|
*p++ = 0; /* reserved */
|
||||||
|
flag_put_word_lh(p, FLAG_SA_ALL); p += 2;
|
||||||
|
|
||||||
|
flag_put_dword_lh(p, FLAG_RIM_ATTRIBUTES); p += 4; /* modify mask */
|
||||||
|
flag_put_dword_lh(p, attrs); p += 4; /* Attributes */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remaining ncp_dos_info fields. Mask says only Attributes is valid,
|
||||||
|
* so these should be ignored, but ncpfs still sends the full structure.
|
||||||
|
*/
|
||||||
|
memset(p, 0, 34);
|
||||||
|
p += 34;
|
||||||
|
|
||||||
|
hlen = flag_add_handle_path(p, dhandle, name);
|
||||||
|
p += hlen;
|
||||||
|
|
||||||
|
req.len = (uint16)(p - req.data);
|
||||||
|
repl.len = sizeof(repl.data);
|
||||||
|
|
||||||
|
neterrno = Net_Call(0xF257, &req, &repl);
|
||||||
|
if (neterrno)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _A_NORMAL
|
||||||
|
#define _A_NORMAL 0x00
|
||||||
|
#endif
|
||||||
|
#ifndef _A_RDONLY
|
||||||
|
#define _A_RDONLY 0x01
|
||||||
|
#endif
|
||||||
|
#ifndef _A_HIDDEN
|
||||||
|
#define _A_HIDDEN 0x02
|
||||||
|
#endif
|
||||||
|
#ifndef _A_SYSTEM
|
||||||
|
#define _A_SYSTEM 0x04
|
||||||
|
#endif
|
||||||
|
#ifndef _A_SUBDIR
|
||||||
|
#define _A_SUBDIR 0x10
|
||||||
|
#endif
|
||||||
|
#ifndef _A_ARCH
|
||||||
|
#define _A_ARCH 0x20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int flag_same(char *a, char *b)
|
||||||
|
{
|
||||||
|
while (*a || *b) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flag_help(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "USAGE: FLAG [path [ option | [+|-] attribute(s) ] [SUB]]\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, "386 Attributes:\n");
|
||||||
|
fprintf(stdout, "--------------\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, "RO Read Only\n");
|
||||||
|
fprintf(stdout, "RW Read Write\n");
|
||||||
|
fprintf(stdout, "S Sharable\n");
|
||||||
|
fprintf(stdout, "H Hidden\n");
|
||||||
|
fprintf(stdout, "Sy System\n");
|
||||||
|
fprintf(stdout, "T Transactional\n");
|
||||||
|
fprintf(stdout, "P Purge\n");
|
||||||
|
fprintf(stdout, "A Archive Needed\n");
|
||||||
|
fprintf(stdout, "RA Read Audit\n");
|
||||||
|
fprintf(stdout, "WA Write Audit\n");
|
||||||
|
fprintf(stdout, "CI Copy Inhibit\n");
|
||||||
|
fprintf(stdout, "DI Delete Inhibit\n");
|
||||||
|
fprintf(stdout, "RI Rename Inhibit\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, "All All\n");
|
||||||
|
fprintf(stdout, "N Normal\n");
|
||||||
|
fprintf(stdout, "SUB\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_attr_mask(char *s, uint32 *setbits, uint32 *clearbits)
|
||||||
|
{
|
||||||
|
int set = 1;
|
||||||
|
char *p = s;
|
||||||
|
|
||||||
|
if (*p == '+') {
|
||||||
|
set = 1;
|
||||||
|
p++;
|
||||||
|
} else if (*p == '-') {
|
||||||
|
set = 0;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*p) return(-1);
|
||||||
|
|
||||||
|
if (flag_same(p, "RO")) {
|
||||||
|
if (set) {
|
||||||
|
*setbits |= (NWFA_RO | NWFA_DI | NWFA_RI);
|
||||||
|
} else {
|
||||||
|
*clearbits |= (NWFA_RO | NWFA_DI | NWFA_RI);
|
||||||
|
}
|
||||||
|
} else if (flag_same(p, "RW")) {
|
||||||
|
*clearbits |= (NWFA_RO | NWFA_DI | NWFA_RI);
|
||||||
|
} else if (flag_same(p, "S")) {
|
||||||
|
if (set) *setbits |= NWFA_S;
|
||||||
|
else *clearbits |= NWFA_S;
|
||||||
|
} else if (flag_same(p, "H")) {
|
||||||
|
if (set) *setbits |= NWFA_H;
|
||||||
|
else *clearbits |= NWFA_H;
|
||||||
|
} else if (flag_same(p, "SY") || flag_same(p, "SYS") || flag_same(p, "SYSTEM")) {
|
||||||
|
if (set) *setbits |= NWFA_SY;
|
||||||
|
else *clearbits |= NWFA_SY;
|
||||||
|
} else if (flag_same(p, "T")) {
|
||||||
|
if (set) *setbits |= NWFA_T;
|
||||||
|
else *clearbits |= NWFA_T;
|
||||||
|
} else if (flag_same(p, "P")) {
|
||||||
|
if (set) *setbits |= NWFA_P;
|
||||||
|
else *clearbits |= NWFA_P;
|
||||||
|
} else if (flag_same(p, "A")) {
|
||||||
|
if (set) *setbits |= NWFA_A;
|
||||||
|
else *clearbits |= NWFA_A;
|
||||||
|
} else if (flag_same(p, "RA")) {
|
||||||
|
if (set) *setbits |= NWFA_RA;
|
||||||
|
else *clearbits |= NWFA_RA;
|
||||||
|
} else if (flag_same(p, "WA")) {
|
||||||
|
if (set) *setbits |= NWFA_WA;
|
||||||
|
else *clearbits |= NWFA_WA;
|
||||||
|
} else if (flag_same(p, "CI")) {
|
||||||
|
if (set) *setbits |= NWFA_CI;
|
||||||
|
else *clearbits |= NWFA_CI;
|
||||||
|
} else if (flag_same(p, "DI")) {
|
||||||
|
if (set) *setbits |= NWFA_DI;
|
||||||
|
else *clearbits |= NWFA_DI;
|
||||||
|
} else if (flag_same(p, "RI")) {
|
||||||
|
if (set) *setbits |= NWFA_RI;
|
||||||
|
else *clearbits |= NWFA_RI;
|
||||||
|
} else if (flag_same(p, "N") || flag_same(p, "NORMAL")) {
|
||||||
|
*clearbits |= (NWFA_RO | NWFA_H | NWFA_SY | NWFA_A |
|
||||||
|
NWFA_S | NWFA_T | NWFA_P |
|
||||||
|
NWFA_RA | NWFA_WA | NWFA_CI | NWFA_DI | NWFA_RI);
|
||||||
|
} else if (flag_same(p, "ALL")) {
|
||||||
|
*setbits |= (NWFA_RO | NWFA_H | NWFA_SY | NWFA_A |
|
||||||
|
NWFA_S | NWFA_T | NWFA_P |
|
||||||
|
NWFA_RA | NWFA_WA | NWFA_CI | NWFA_DI | NWFA_RI);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unknown attribute encountered in command line.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flag_print_attrs(uint32 attr)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Novell order:
|
||||||
|
* Ro/Rw S A - H Sy T P Ra Wa CI DI RI
|
||||||
|
*/
|
||||||
|
fprintf(stdout, "[ ");
|
||||||
|
fprintf(stdout, "%s ", (attr & NWFA_RO) ? "Ro" : "Rw");
|
||||||
|
fprintf(stdout, "%c ", (attr & NWFA_S) ? 'S' : '-');
|
||||||
|
fprintf(stdout, "%c ", (attr & NWFA_A) ? 'A' : '-');
|
||||||
|
fprintf(stdout, "- ");
|
||||||
|
fprintf(stdout, "%c ", (attr & NWFA_H) ? 'H' : '-');
|
||||||
|
fprintf(stdout, "%s ", (attr & NWFA_SY) ? "Sy" : "--");
|
||||||
|
fprintf(stdout, "%c ", (attr & NWFA_T) ? 'T' : '-');
|
||||||
|
fprintf(stdout, "%c ", (attr & NWFA_P) ? 'P' : '-');
|
||||||
|
fprintf(stdout, "%s ", (attr & NWFA_RA) ? "Ra" : "--");
|
||||||
|
fprintf(stdout, "%s ", (attr & NWFA_WA) ? "Wa" : "--");
|
||||||
|
fprintf(stdout, "%s ", (attr & NWFA_CI) ? "CI" : "--");
|
||||||
|
fprintf(stdout, "%s ", (attr & NWFA_DI) ? "DI" : "--");
|
||||||
|
fprintf(stdout, "%s ", (attr & NWFA_RI) ? "RI" : "--");
|
||||||
|
fprintf(stdout, "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flag_display_one(char *name, uint32 attr)
|
||||||
|
{
|
||||||
|
fprintf(stdout, " %-23s ", name);
|
||||||
|
flag_print_attrs(attr);
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_has_wildcards(char *s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
if (*s == '*' || *s == '?') return(1);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_list(char *pattern)
|
||||||
|
{
|
||||||
|
struct find_t ff;
|
||||||
|
unsigned findattr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
if (_dos_findfirst(pattern, findattr, &ff))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!(ff.attrib & _A_SUBDIR)) {
|
||||||
|
uint32 nwattrs;
|
||||||
|
|
||||||
|
if (flag_ncp87_obtain_attrs(ff.name, &nwattrs))
|
||||||
|
nwattrs = (uint32)ff.attrib;
|
||||||
|
|
||||||
|
flag_display_one(ff.name, nwattrs);
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
} while (!_dos_findnext(&ff));
|
||||||
|
|
||||||
|
return(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_apply(char *pattern, uint32 setbits, uint32 clearbits)
|
||||||
|
{
|
||||||
|
struct find_t ff;
|
||||||
|
unsigned findattr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH;
|
||||||
|
int shown = 0;
|
||||||
|
|
||||||
|
if (_dos_findfirst(pattern, findattr, &ff))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
do {
|
||||||
|
uint32 attrs;
|
||||||
|
uint32 newattrs;
|
||||||
|
char fname[260];
|
||||||
|
|
||||||
|
if (ff.attrib & _A_SUBDIR) continue;
|
||||||
|
|
||||||
|
strmaxcpy(fname, ff.name, sizeof(fname) - 1);
|
||||||
|
|
||||||
|
if (flag_ncp87_obtain_attrs(fname, &attrs))
|
||||||
|
attrs = (uint32)ff.attrib;
|
||||||
|
|
||||||
|
newattrs = (attrs | (uint32)setbits) & ~((uint32)clearbits);
|
||||||
|
|
||||||
|
if (newattrs != attrs) {
|
||||||
|
if (flag_ncp87_modify_attrs(fname, newattrs)) {
|
||||||
|
unsigned dosattr = (newattrs & (_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_ARCH));
|
||||||
|
if (_dos_setfileattr(fname, dosattr)) {
|
||||||
|
fprintf(stderr, "You don't have rights to change : %s\n", fname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag_ncp87_obtain_attrs(fname, &attrs))
|
||||||
|
attrs = newattrs;
|
||||||
|
|
||||||
|
flag_display_one(fname, newattrs);
|
||||||
|
shown++;
|
||||||
|
|
||||||
|
} while (!_dos_findnext(&ff));
|
||||||
|
|
||||||
|
return(shown);
|
||||||
|
}
|
||||||
|
|
||||||
|
int func_flag(int argc, char *argv[], int mode)
|
||||||
|
{
|
||||||
|
char *path = "*.*";
|
||||||
|
int i;
|
||||||
|
uint32 setbits = 0;
|
||||||
|
uint32 clearbits = 0;
|
||||||
|
int have_change = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
(void)mode;
|
||||||
|
|
||||||
|
if (argc > 1 && (flag_same(argv[1], "/?") || flag_same(argv[1], "-?") ||
|
||||||
|
flag_same(argv[1], "?"))) {
|
||||||
|
flag_help();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
path = argv[1];
|
||||||
|
if (flag_same(path, "SUB")) path = "*.*";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 2; i < argc; i++) {
|
||||||
|
if (flag_same(argv[i], "SUB")) continue;
|
||||||
|
|
||||||
|
rc = flag_attr_mask(argv[i], &setbits, &clearbits);
|
||||||
|
if (rc < 0) return(1);
|
||||||
|
if (rc > 0) continue;
|
||||||
|
have_change = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_change) {
|
||||||
|
rc = flag_apply(path, setbits, clearbits);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Files could not be found with pattern \"%s\"\n", path);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = flag_list(path);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Files could not be found with pattern \"%s\"\n", path);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
296
flagdir.c
Normal file
296
flagdir.c
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
/* flagdir.c - Novell FLAGDIR-like DOS utility, first Client32 version */
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "c32ncp.h"
|
||||||
|
#include <dos.h>
|
||||||
|
|
||||||
|
#define FD_NWFA_H 0x00000002UL
|
||||||
|
#define FD_NWFA_SY 0x00000004UL
|
||||||
|
#define FD_NWFA_P 0x00010000UL
|
||||||
|
#define FD_NWFA_RI 0x00020000UL
|
||||||
|
#define FD_NWFA_DI 0x00040000UL
|
||||||
|
|
||||||
|
#define FD_DIR_BITS (FD_NWFA_H | FD_NWFA_SY | FD_NWFA_P | FD_NWFA_RI | FD_NWFA_DI)
|
||||||
|
|
||||||
|
#ifndef _A_RDONLY
|
||||||
|
#define _A_RDONLY 0x01
|
||||||
|
#endif
|
||||||
|
#ifndef _A_HIDDEN
|
||||||
|
#define _A_HIDDEN 0x02
|
||||||
|
#endif
|
||||||
|
#ifndef _A_SYSTEM
|
||||||
|
#define _A_SYSTEM 0x04
|
||||||
|
#endif
|
||||||
|
#ifndef _A_SUBDIR
|
||||||
|
#define _A_SUBDIR 0x10
|
||||||
|
#endif
|
||||||
|
#ifndef _A_ARCH
|
||||||
|
#define _A_ARCH 0x20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int fd_same(char *a, char *b)
|
||||||
|
{
|
||||||
|
while (*a || *b) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fd_upcopy(char *dst, char *src, int max)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (*src && i < max - 1) {
|
||||||
|
char c = *src++;
|
||||||
|
if (c >= 'a' && c <= 'z') c -= 32;
|
||||||
|
dst[i++] = c;
|
||||||
|
}
|
||||||
|
dst[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd_get_current_drive(void)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
regs.h.ah = 0x19;
|
||||||
|
int86(0x21, ®s, ®s);
|
||||||
|
return((int)regs.h.al);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd_current_dhandle(uint8 *dhandle)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive;
|
||||||
|
|
||||||
|
drive = fd_get_current_drive();
|
||||||
|
if (get_drive_info((uint8)drive, &connid, dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int fd_current_prefix(char *out, int max)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive;
|
||||||
|
char server[52];
|
||||||
|
char path[260];
|
||||||
|
char volume[32];
|
||||||
|
char *p;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!out || max < 8)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
out[0] = '\0';
|
||||||
|
|
||||||
|
drive = fd_get_current_drive();
|
||||||
|
if (get_drive_info((uint8)drive, &connid, &dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
server[0] = '\0';
|
||||||
|
if (get_fs_name(connid, server))
|
||||||
|
server[0] = '\0';
|
||||||
|
|
||||||
|
path[0] = '\0';
|
||||||
|
if (get_dir_path(dhandle, path) || !path[0])
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
p = strchr(path, ':');
|
||||||
|
if (!p)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
while (path + i < p && i < (int)sizeof(volume) - 1) {
|
||||||
|
volume[i] = path[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
volume[i] = '\0';
|
||||||
|
|
||||||
|
if (!volume[0])
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (server[0])
|
||||||
|
sprintf(out, "%s/%s:", server, volume);
|
||||||
|
else
|
||||||
|
sprintf(out, "%s:", volume);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void fd_help(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "386 Usage: Flagdir [path [option...]]\n");
|
||||||
|
fprintf(stdout, "Options: Normal\n");
|
||||||
|
fprintf(stdout, " System\n");
|
||||||
|
fprintf(stdout, " Hidden\n");
|
||||||
|
fprintf(stdout, " Deleteinhibit\n");
|
||||||
|
fprintf(stdout, " Purge\n");
|
||||||
|
fprintf(stdout, " Renameinhibit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd_attr_mask(char *s, uint32 *setbits, uint32 *clearbits)
|
||||||
|
{
|
||||||
|
if (fd_same(s, "N") || fd_same(s, "NORMAL")) {
|
||||||
|
*clearbits |= FD_DIR_BITS;
|
||||||
|
} else if (fd_same(s, "S") || fd_same(s, "SY") ||
|
||||||
|
fd_same(s, "SYS") || fd_same(s, "SYSTEM")) {
|
||||||
|
*setbits |= FD_NWFA_SY;
|
||||||
|
} else if (fd_same(s, "H") || fd_same(s, "HIDDEN")) {
|
||||||
|
*setbits |= FD_NWFA_H;
|
||||||
|
} else if (fd_same(s, "DI") || fd_same(s, "DELETEINHIBIT")) {
|
||||||
|
*setbits |= FD_NWFA_DI;
|
||||||
|
} else if (fd_same(s, "P") || fd_same(s, "PURGE")) {
|
||||||
|
*setbits |= FD_NWFA_P;
|
||||||
|
} else if (fd_same(s, "RI") || fd_same(s, "RENAMEINHIBIT")) {
|
||||||
|
*setbits |= FD_NWFA_RI;
|
||||||
|
} else if (fd_same(s, "PRIVATE") || fd_same(s, "PR")) {
|
||||||
|
fprintf(stderr, "Private is valid on NetWare 2.15 and above, except NetWare 386.\n");
|
||||||
|
return(-1);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unknown attribute: %s.\n", s);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fd_display(char *path, uint32 attrs)
|
||||||
|
{
|
||||||
|
char up[260];
|
||||||
|
int any = 0;
|
||||||
|
|
||||||
|
fd_upcopy(up, path, sizeof(up));
|
||||||
|
|
||||||
|
{
|
||||||
|
char prefix[90];
|
||||||
|
if (fd_current_prefix(prefix, sizeof(prefix)))
|
||||||
|
prefix[0] = '\0';
|
||||||
|
fprintf(stdout, "%s%s \n", prefix, up);
|
||||||
|
}
|
||||||
|
fprintf(stdout, " %-12.12s ", up);
|
||||||
|
|
||||||
|
if (!(attrs & FD_DIR_BITS)) {
|
||||||
|
fprintf(stdout, "Normal\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs & FD_NWFA_SY) {
|
||||||
|
fprintf(stdout, "System");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if (attrs & FD_NWFA_H) {
|
||||||
|
fprintf(stdout, "%sHidden", any ? " " : "");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if (attrs & FD_NWFA_DI) {
|
||||||
|
fprintf(stdout, "%sDeleteInhibit", any ? " " : "");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if (attrs & FD_NWFA_P) {
|
||||||
|
fprintf(stdout, "%sPurge", any ? " " : "");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if (attrs & FD_NWFA_RI) {
|
||||||
|
fprintf(stdout, "%sRenameInhibit", any ? " " : "");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd_is_directory(char *path)
|
||||||
|
{
|
||||||
|
struct find_t ff;
|
||||||
|
unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH;
|
||||||
|
if (_dos_findfirst(path, attr, &ff))
|
||||||
|
return(0);
|
||||||
|
return((ff.attrib & _A_SUBDIR) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd_obtain(char *path, uint8 dhandle, uint32 *attrs)
|
||||||
|
{
|
||||||
|
if (c32_ncp87_obtain_rim_attributes(path, (uint16)dhandle,
|
||||||
|
attrs, NULL, NULL, NULL) == 0)
|
||||||
|
return(0);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fd_modify(char *path, uint8 dhandle, uint32 attrs)
|
||||||
|
{
|
||||||
|
if (c32_ncp87_modify_dos_attributes(path, (uint16)dhandle, attrs,
|
||||||
|
NULL, NULL, NULL) == 0)
|
||||||
|
return(0);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int func_flagdir(int argc, char *argv[], int mode)
|
||||||
|
{
|
||||||
|
char *path = ".";
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint32 attrs = 0;
|
||||||
|
uint32 setbits = 0;
|
||||||
|
uint32 clearbits = 0;
|
||||||
|
uint32 newattrs;
|
||||||
|
int have_change = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
(void)mode;
|
||||||
|
|
||||||
|
if (argc > 1 && (fd_same(argv[1], "/?") || fd_same(argv[1], "-?") ||
|
||||||
|
fd_same(argv[1], "?"))) {
|
||||||
|
fd_help();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
path = argv[1];
|
||||||
|
|
||||||
|
if (fd_current_dhandle(&dhandle)) {
|
||||||
|
fprintf(stderr, "FlagDir only works on network directories.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fd_is_directory(path)) {
|
||||||
|
fprintf(stderr, "Directory %s not found.\n", path);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 2; i < argc; i++) {
|
||||||
|
if (fd_attr_mask(argv[i], &setbits, &clearbits))
|
||||||
|
return(1);
|
||||||
|
have_change = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd_obtain(path, dhandle, &attrs)) {
|
||||||
|
fprintf(stderr, "Unable to get directory attributes.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_change) {
|
||||||
|
newattrs = (attrs | setbits) & ~clearbits;
|
||||||
|
if (newattrs != attrs) {
|
||||||
|
if (fd_modify(path, dhandle, newattrs)) {
|
||||||
|
fprintf(stderr, "Unable to change attributes.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
attrs = newattrs;
|
||||||
|
/* Try to read back; keep requested value if readback fails. */
|
||||||
|
fd_obtain(path, dhandle, &attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_display(path, attrs);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
519
grant.c
Normal file
519
grant.c
Normal file
@@ -0,0 +1,519 @@
|
|||||||
|
/* grant.c - Novell GRANT-like DOS utility, first Client32 implementation */
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "c32ncp.h"
|
||||||
|
|
||||||
|
#define GRANT_BINDERY_USER 0x0001
|
||||||
|
#define GRANT_BINDERY_GROUP 0x0002
|
||||||
|
|
||||||
|
#define NCP_RIGHT_READ 0x0001
|
||||||
|
#define NCP_RIGHT_WRITE 0x0002
|
||||||
|
#define NCP_RIGHT_OPEN 0x0004
|
||||||
|
#define NCP_RIGHT_CREATE 0x0008
|
||||||
|
#define NCP_RIGHT_DELETE 0x0010
|
||||||
|
#define NCP_RIGHT_OWNER 0x0020
|
||||||
|
#define NCP_RIGHT_SEARCH 0x0040
|
||||||
|
#define NCP_RIGHT_MODIFY 0x0080
|
||||||
|
#define NCP_RIGHT_SUPER 0x0100
|
||||||
|
|
||||||
|
#define NCP_RIGHT_ALL_386 (NCP_RIGHT_SUPER | NCP_RIGHT_READ | \
|
||||||
|
NCP_RIGHT_WRITE | NCP_RIGHT_CREATE | \
|
||||||
|
NCP_RIGHT_DELETE | NCP_RIGHT_MODIFY | \
|
||||||
|
NCP_RIGHT_SEARCH | NCP_RIGHT_OWNER)
|
||||||
|
|
||||||
|
static int grant_same(char *a, char *b)
|
||||||
|
{
|
||||||
|
while (*a || *b) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grant_is_help(char *s)
|
||||||
|
{
|
||||||
|
if (!s) return(0);
|
||||||
|
return(grant_same(s, "/?") || grant_same(s, "-?") || grant_same(s, "?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grant_usage_error(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Command line arguments violate grammar defined for GRANT.\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grant_usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Usage: GRANT rightslist* [FOR path] TO [USER | GROUP] name [options]\n");
|
||||||
|
fprintf(stdout, "Options: /SubDirectories | /Files\n\n");
|
||||||
|
fprintf(stdout, "386 Rights:\n");
|
||||||
|
fprintf(stdout, "--------------------\n");
|
||||||
|
fprintf(stdout, "ALL = All\n");
|
||||||
|
fprintf(stdout, "N = No Rights\n");
|
||||||
|
fprintf(stdout, "S = Supervisor\n");
|
||||||
|
fprintf(stdout, "R = Read\n");
|
||||||
|
fprintf(stdout, "W = Write\n");
|
||||||
|
fprintf(stdout, "C = Create\n");
|
||||||
|
fprintf(stdout, "E = Erase\n");
|
||||||
|
fprintf(stdout, "M = Modify\n");
|
||||||
|
fprintf(stdout, "F = File Scan\n");
|
||||||
|
fprintf(stdout, "A = Access Control\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grant_get_current_drive(void)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
|
||||||
|
regs.h.ah = 0x19;
|
||||||
|
int86(0x21, ®s, ®s);
|
||||||
|
return((int)regs.h.al);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grant_current_dhandle(uint8 *connid, uint8 *dhandle)
|
||||||
|
{
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive = grant_get_current_drive();
|
||||||
|
|
||||||
|
if (get_drive_info((uint8)drive, connid, dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!*connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int grant_current_prefix(char *out, int max)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive;
|
||||||
|
char server[52];
|
||||||
|
char dpath[260];
|
||||||
|
char volume[32];
|
||||||
|
char *p;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!out || max < 8)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
out[0] = '\0';
|
||||||
|
|
||||||
|
drive = grant_get_current_drive();
|
||||||
|
if (get_drive_info((uint8)drive, &connid, &dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
server[0] = '\0';
|
||||||
|
if (get_fs_name(connid, server))
|
||||||
|
server[0] = '\0';
|
||||||
|
|
||||||
|
dpath[0] = '\0';
|
||||||
|
if (get_dir_path(dhandle, dpath) || !dpath[0])
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
p = strchr(dpath, ':');
|
||||||
|
if (!p)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
while (dpath + i < p && i < (int)sizeof(volume) - 1) {
|
||||||
|
volume[i] = dpath[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
volume[i] = '\0';
|
||||||
|
|
||||||
|
if (!volume[0])
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (server[0])
|
||||||
|
sprintf(out, "%s/%s:", server, volume);
|
||||||
|
else
|
||||||
|
sprintf(out, "%s:", volume);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grant_upcopy(char *dst, char *src, int max)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!src) src = "";
|
||||||
|
|
||||||
|
while (*src && i < max - 1) {
|
||||||
|
char c = *src++;
|
||||||
|
if (c == '/') c = '\\';
|
||||||
|
if (c >= 'a' && c <= 'z') c -= 32;
|
||||||
|
dst[i++] = c;
|
||||||
|
}
|
||||||
|
dst[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grant_basename(char *dst, char *src, int max)
|
||||||
|
{
|
||||||
|
char up[260];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
grant_upcopy(up, src, sizeof(up));
|
||||||
|
p = strrchr(up, '\\');
|
||||||
|
if (!p) p = strrchr(up, ':');
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
strmaxcpy(dst, p + 1, max - 1);
|
||||||
|
else
|
||||||
|
strmaxcpy(dst, up, max - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grant_header_path(char *out, char *path, int max)
|
||||||
|
{
|
||||||
|
char prefix[90];
|
||||||
|
char up[260];
|
||||||
|
|
||||||
|
if (grant_current_prefix(prefix, sizeof(prefix)))
|
||||||
|
prefix[0] = '\0';
|
||||||
|
|
||||||
|
grant_upcopy(up, path, sizeof(up));
|
||||||
|
|
||||||
|
strmaxcpy(out, prefix, max - 1);
|
||||||
|
if ((int)(strlen(out) + strlen(up)) < max - 1)
|
||||||
|
strcat(out, up);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grant_rights_bracket(uint16 rights, char *out)
|
||||||
|
{
|
||||||
|
out[0] = (rights & NCP_RIGHT_SUPER) ? 'S' : ' ';
|
||||||
|
out[1] = (rights & NCP_RIGHT_READ) ? 'R' : ' ';
|
||||||
|
out[2] = (rights & NCP_RIGHT_WRITE) ? 'W' : ' ';
|
||||||
|
out[3] = (rights & NCP_RIGHT_CREATE) ? 'C' : ' ';
|
||||||
|
out[4] = (rights & NCP_RIGHT_DELETE) ? 'E' : ' ';
|
||||||
|
out[5] = (rights & NCP_RIGHT_MODIFY) ? 'M' : ' ';
|
||||||
|
out[6] = (rights & NCP_RIGHT_SEARCH) ? 'F' : ' ';
|
||||||
|
out[7] = (rights & NCP_RIGHT_OWNER) ? 'A' : ' ';
|
||||||
|
out[8] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void grant_rights_string(uint16 rights, char *out)
|
||||||
|
{
|
||||||
|
char *p = out;
|
||||||
|
|
||||||
|
if (rights == 0) {
|
||||||
|
strcpy(out, "N");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rights & NCP_RIGHT_ALL_386) == NCP_RIGHT_ALL_386) {
|
||||||
|
strcpy(out, "ALL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rights & NCP_RIGHT_SUPER) *p++ = 'S';
|
||||||
|
if (rights & NCP_RIGHT_READ) *p++ = 'R';
|
||||||
|
if (rights & NCP_RIGHT_WRITE) *p++ = 'W';
|
||||||
|
if (rights & NCP_RIGHT_CREATE) *p++ = 'C';
|
||||||
|
if (rights & NCP_RIGHT_DELETE) *p++ = 'E';
|
||||||
|
if (rights & NCP_RIGHT_MODIFY) *p++ = 'M';
|
||||||
|
if (rights & NCP_RIGHT_SEARCH) *p++ = 'F';
|
||||||
|
if (rights & NCP_RIGHT_OWNER) *p++ = 'A';
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grant_add_right_word(char *s, uint16 *rights)
|
||||||
|
{
|
||||||
|
if (grant_same(s, "ALL")) {
|
||||||
|
*rights = NCP_RIGHT_ALL_386;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "N") || grant_same(s, "NONE")) {
|
||||||
|
*rights = 0;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "S") || grant_same(s, "SUPERVISOR")) {
|
||||||
|
*rights |= NCP_RIGHT_SUPER;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "R") || grant_same(s, "READ")) {
|
||||||
|
*rights |= NCP_RIGHT_READ;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "W") || grant_same(s, "WRITE")) {
|
||||||
|
*rights |= NCP_RIGHT_WRITE;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "C") || grant_same(s, "CREATE")) {
|
||||||
|
*rights |= NCP_RIGHT_CREATE;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "E") || grant_same(s, "ERASE")) {
|
||||||
|
*rights |= NCP_RIGHT_DELETE;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "M") || grant_same(s, "MODIFY")) {
|
||||||
|
*rights |= NCP_RIGHT_MODIFY;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "F") || grant_same(s, "FILESCAN") ||
|
||||||
|
grant_same(s, "FILE") || grant_same(s, "SCAN")) {
|
||||||
|
*rights |= NCP_RIGHT_SEARCH;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(s, "A") || grant_same(s, "ACCESS") ||
|
||||||
|
grant_same(s, "CONTROL") || grant_same(s, "ACCESSCONTROL")) {
|
||||||
|
*rights |= NCP_RIGHT_OWNER;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grant_is_option(char *s)
|
||||||
|
{
|
||||||
|
if (!s) return(0);
|
||||||
|
return(s[0] == '/' || s[0] == '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int grant_last_rc = 0;
|
||||||
|
|
||||||
|
static int grant_set_one(char *path, uint16 dhandle,
|
||||||
|
uint32 object_id, uint16 rights)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = c32_ncp87_add_trustee_rights(path,
|
||||||
|
dhandle,
|
||||||
|
object_id,
|
||||||
|
rights,
|
||||||
|
0xffff,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
grant_last_rc = rc;
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grant_is_dot_dir(char *name)
|
||||||
|
{
|
||||||
|
if (!name) return(0);
|
||||||
|
if (name[0] == '.' && name[1] == '\0') return(1);
|
||||||
|
if (name[0] == '.' && name[1] == '.' && name[2] == '\0') return(1);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grant_join_path(char *out, char *base, char *name, int max)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
out[0] = '\0';
|
||||||
|
strmaxcpy(out, base, max - 1);
|
||||||
|
len = strlen(out);
|
||||||
|
|
||||||
|
if (len > 0 && out[len - 1] != '\\' && out[len - 1] != '/' &&
|
||||||
|
out[len - 1] != ':') {
|
||||||
|
if (len < max - 1) {
|
||||||
|
out[len++] = '\\';
|
||||||
|
out[len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)(strlen(out) + strlen(name)) < max - 1)
|
||||||
|
strcat(out, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Apply the grant to PATH and every directory below it.
|
||||||
|
*
|
||||||
|
* This intentionally walks through the DOS redirector, not through another
|
||||||
|
* NCP search helper, so it works with the same mapped-drive view that the
|
||||||
|
* user passed to GRANT.
|
||||||
|
*/
|
||||||
|
static int grant_set_subdirs(char *path, uint16 dhandle,
|
||||||
|
uint32 object_id, uint16 rights)
|
||||||
|
{
|
||||||
|
struct find_t ff;
|
||||||
|
char pattern[260];
|
||||||
|
char child[260];
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (grant_set_one(path, dhandle, object_id, rights))
|
||||||
|
rc = 1;
|
||||||
|
|
||||||
|
grant_join_path(pattern, path, "*.*", sizeof(pattern));
|
||||||
|
|
||||||
|
if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) {
|
||||||
|
do {
|
||||||
|
if ((ff.attrib & _A_SUBDIR) && !grant_is_dot_dir(ff.name)) {
|
||||||
|
grant_join_path(child, path, ff.name, sizeof(child));
|
||||||
|
if (grant_set_subdirs(child, dhandle, object_id, rights))
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
} while (_dos_findnext(&ff) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int func_grant(int argc, char *argv[], int mode)
|
||||||
|
{
|
||||||
|
uint16 rights = 0;
|
||||||
|
char *path = ".";
|
||||||
|
char *objname = NULL;
|
||||||
|
uint16 objtype = GRANT_BINDERY_USER;
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint8 namebuf[48];
|
||||||
|
uint32 object_id;
|
||||||
|
int recurse_subdirs = 0;
|
||||||
|
int i = 1;
|
||||||
|
int have_rights = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
(void)mode;
|
||||||
|
|
||||||
|
if (argc < 2 || grant_is_help(argv[1])) {
|
||||||
|
if (argc < 2)
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(argc < 2 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GRANT rightslist* [FOR path] TO [USER|GROUP] name [options]
|
||||||
|
*/
|
||||||
|
while (i < argc) {
|
||||||
|
if (grant_same(argv[i], "FOR") || grant_same(argv[i], "TO"))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (grant_is_option(argv[i]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (grant_add_right_word(argv[i], &rights)) {
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
have_rights = 1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_rights || i >= argc) {
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(argv[i], "FOR")) {
|
||||||
|
i++;
|
||||||
|
if (i >= argc) {
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
path = argv[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= argc || !grant_same(argv[i], "TO")) {
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i < argc && grant_same(argv[i], "USER")) {
|
||||||
|
objtype = GRANT_BINDERY_USER;
|
||||||
|
i++;
|
||||||
|
} else if (i < argc && grant_same(argv[i], "GROUP")) {
|
||||||
|
objtype = GRANT_BINDERY_GROUP;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= argc) {
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
objname = argv[i++];
|
||||||
|
|
||||||
|
while (i < argc) {
|
||||||
|
if (!grant_is_option(argv[i])) {
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* /FILES is harmless because the explicit path is passed to the
|
||||||
|
* NCP87 trustee-add call. /SUBDIRECTORIES recursively applies the
|
||||||
|
* same grant to all subdirectories below the given path.
|
||||||
|
*/
|
||||||
|
if (grant_same(argv[i], "/FILES") || grant_same(argv[i], "-FILES") ||
|
||||||
|
grant_same(argv[i], "/F") || grant_same(argv[i], "-F")) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_same(argv[i], "/SUBDIRECTORIES") ||
|
||||||
|
grant_same(argv[i], "-SUBDIRECTORIES") ||
|
||||||
|
grant_same(argv[i], "/S") || grant_same(argv[i], "-S")) {
|
||||||
|
recurse_subdirs = 1;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
grant_usage_error();
|
||||||
|
grant_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant_current_dhandle(&connid, &dhandle)) {
|
||||||
|
fprintf(stdout, "Specified path not locatable.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strmaxcpy(namebuf, objname, sizeof(namebuf) - 1);
|
||||||
|
upstr(namebuf);
|
||||||
|
object_id = ncp_17_35(namebuf, objtype);
|
||||||
|
if (!object_id) {
|
||||||
|
fprintf(stdout, "Object not found.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recurse_subdirs)
|
||||||
|
rc = grant_set_subdirs(path, (uint16)dhandle, object_id, rights);
|
||||||
|
else
|
||||||
|
rc = grant_set_one(path, (uint16)dhandle, object_id, rights);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stdout, "Could not add trustee rights. rc=%d\n", grant_last_rc);
|
||||||
|
return(grant_last_rc ? grant_last_rc : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char header[300];
|
||||||
|
char base[80];
|
||||||
|
char bracket[10];
|
||||||
|
|
||||||
|
grant_header_path(header, path, sizeof(header));
|
||||||
|
grant_basename(base, path, sizeof(base));
|
||||||
|
grant_rights_bracket(rights, bracket);
|
||||||
|
|
||||||
|
fprintf(stdout, "%s\n", header);
|
||||||
|
fprintf(stdout, "%-29.29sRights set to [%s]\n", base, bracket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
12
kern.h
12
kern.h
@@ -3,6 +3,8 @@
|
|||||||
#define KERN_CALL _Cdecl
|
#define KERN_CALL _Cdecl
|
||||||
#else
|
#else
|
||||||
#define KERN_CALL
|
#define KERN_CALL
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int KERN_CALL IPXinit(void);
|
extern int KERN_CALL IPXinit(void);
|
||||||
@@ -13,8 +15,14 @@ extern void asm_esr_routine(void);
|
|||||||
extern void esr_routine(ECB *ecb);
|
extern void esr_routine(ECB *ecb);
|
||||||
extern void KERN_CALL xmemmove(void *ziel, void *quelle, UI anz);
|
extern void KERN_CALL xmemmove(void *ziel, void *quelle, UI anz);
|
||||||
extern int KERN_CALL Net_Call(UI func, void *req, void *repl);
|
extern int KERN_CALL Net_Call(UI func, void *req, void *repl);
|
||||||
|
extern int KERN_CALL C32_MapVar_Probe(UI specLen, UI flag, void *outbuf);
|
||||||
|
extern int KERN_CALL C32_OpenRef_Probe(UI refLo, UI refHi, void *outbuf);
|
||||||
|
extern int KERN_CALL C32_NCP87_Raw5_Probe(UI connLo, UI connHi,
|
||||||
|
void *hdr, UI hdrLen,
|
||||||
|
void *path, UI pathLen,
|
||||||
|
void *rep0, UI rep0Len,
|
||||||
|
void *rep1, UI rep1Len,
|
||||||
|
void *outbuf);
|
||||||
#undef KERN_CALL
|
#undef KERN_CALL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
750
kern_wasm.asm
750
kern_wasm.asm
@@ -20,7 +20,9 @@ public _IPXclose_socket
|
|||||||
public _IPXlisten
|
public _IPXlisten
|
||||||
public _xmemmove
|
public _xmemmove
|
||||||
public _Net_Call
|
public _Net_Call
|
||||||
|
public _C32_NCP87_Raw5_Probe
|
||||||
|
public _C32_OpenRef_Probe
|
||||||
|
public _C32_MapVar_Probe
|
||||||
_IPXinit proc far
|
_IPXinit proc far
|
||||||
push bp
|
push bp
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
@@ -213,4 +215,750 @@ _Net_Call proc far
|
|||||||
ret
|
ret
|
||||||
_Net_Call endp
|
_Net_Call endp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; int C32_OpenRef_Probe(UI refLo, UI refHi, void *outbuf)
|
||||||
|
;
|
||||||
|
; Opens a Client32 connection by connection reference using the same d32wrap
|
||||||
|
; convention as _CONNOpenByReference / w95ocref.o.
|
||||||
|
;
|
||||||
|
; Input:
|
||||||
|
; refLo/refHi = connection reference, e.g. C32PRIMREF returned 0028:0000.
|
||||||
|
;
|
||||||
|
; outbuf:
|
||||||
|
; +00 load AX from D8C1
|
||||||
|
; +02 resolver off
|
||||||
|
; +04 resolver seg
|
||||||
|
; +06 trampoline off
|
||||||
|
; +08 trampoline seg
|
||||||
|
; +0A function off
|
||||||
|
; +0C function seg
|
||||||
|
; +0E return AX
|
||||||
|
; +10 return DX
|
||||||
|
; +12 handle low
|
||||||
|
; +14 handle high
|
||||||
|
_C32_OpenRef_Probe proc far
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
sub sp, 80
|
||||||
|
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
; clear ESI/ECX
|
||||||
|
db 66h, 33h, 0F6h
|
||||||
|
db 66h, 33h, 0C9h
|
||||||
|
|
||||||
|
mov ax, 0D8C1h
|
||||||
|
int 2Fh
|
||||||
|
|
||||||
|
mov [bp-4], ax ; load AX
|
||||||
|
; resolver ESI -> [bp-8]
|
||||||
|
db 66h, 89h, 76h, 0F8h
|
||||||
|
; trampoline ECX -> [bp-12]
|
||||||
|
db 66h, 89h, 4Eh, 0F4h
|
||||||
|
|
||||||
|
or ax, ax
|
||||||
|
jne c32openref_fail
|
||||||
|
|
||||||
|
; resolve "CONNOpenByReference"
|
||||||
|
push cs
|
||||||
|
push offset c32openref_name
|
||||||
|
push 0
|
||||||
|
push 0
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 8
|
||||||
|
mov [bp-16], ax
|
||||||
|
mov [bp-14], dx
|
||||||
|
or ax, dx
|
||||||
|
jne c32openref_have_func
|
||||||
|
jmp c32openref_fail
|
||||||
|
|
||||||
|
c32openref_have_func:
|
||||||
|
; local output handle dword at [bp-20]
|
||||||
|
mov word ptr [bp-20], 0
|
||||||
|
mov word ptr [bp-18], 0
|
||||||
|
|
||||||
|
; MapLockFlat(&handle, 4) -> flat [bp-24]
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push ss
|
||||||
|
lea ax, -20[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-24], ax
|
||||||
|
mov [bp-22], dx
|
||||||
|
|
||||||
|
; Call NIOS trampoline command 5 / CONNOpenByReference.
|
||||||
|
; This matches d32wrap _CONNOpenByReference after w95ocref:
|
||||||
|
; flat handle ptr,
|
||||||
|
; refHi/refLo,
|
||||||
|
; 0,0,
|
||||||
|
; FEFE FEFE FEFE FEFE,
|
||||||
|
; command 5,
|
||||||
|
; function ptr.
|
||||||
|
push word ptr [bp-22] ; flat handle high
|
||||||
|
push word ptr [bp-24] ; flat handle low
|
||||||
|
push word ptr [bp+8] ; ref high
|
||||||
|
push word ptr [bp+6] ; ref low
|
||||||
|
push 0
|
||||||
|
push 0
|
||||||
|
push 0fefeH
|
||||||
|
push 0fefeH
|
||||||
|
push 0fefeH
|
||||||
|
push 0fefeH
|
||||||
|
push 0
|
||||||
|
push 5
|
||||||
|
push word ptr [bp-14] ; function seg
|
||||||
|
push word ptr [bp-16] ; function off
|
||||||
|
call dword ptr [bp-12]
|
||||||
|
add sp, 1cH
|
||||||
|
|
||||||
|
mov [bp-28], ax
|
||||||
|
mov [bp-26], dx
|
||||||
|
|
||||||
|
; UnlockFlat(handle flat, 4)
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push word ptr [bp-22]
|
||||||
|
push word ptr [bp-24]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
jmp short c32openref_store
|
||||||
|
|
||||||
|
c32openref_fail:
|
||||||
|
mov word ptr [bp-16], 0
|
||||||
|
mov word ptr [bp-14], 0
|
||||||
|
mov word ptr [bp-28], 0ffffH
|
||||||
|
mov word ptr [bp-26], 0ffffH
|
||||||
|
mov word ptr [bp-20], 0
|
||||||
|
mov word ptr [bp-18], 0
|
||||||
|
|
||||||
|
c32openref_store:
|
||||||
|
les di, dword ptr [bp+10]
|
||||||
|
|
||||||
|
mov ax, [bp-4]
|
||||||
|
mov es:[di+0], ax
|
||||||
|
mov ax, [bp-8]
|
||||||
|
mov es:[di+2], ax
|
||||||
|
mov ax, [bp-6]
|
||||||
|
mov es:[di+4], ax
|
||||||
|
mov ax, [bp-12]
|
||||||
|
mov es:[di+6], ax
|
||||||
|
mov ax, [bp-10]
|
||||||
|
mov es:[di+8], ax
|
||||||
|
mov ax, [bp-16]
|
||||||
|
mov es:[di+10], ax
|
||||||
|
mov ax, [bp-14]
|
||||||
|
mov es:[di+12], ax
|
||||||
|
mov ax, [bp-28]
|
||||||
|
mov es:[di+14], ax
|
||||||
|
mov ax, [bp-26]
|
||||||
|
mov es:[di+16], ax
|
||||||
|
mov ax, [bp-20]
|
||||||
|
mov es:[di+18], ax
|
||||||
|
mov ax, [bp-18]
|
||||||
|
mov es:[di+20], ax
|
||||||
|
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
xor ah, ah
|
||||||
|
ret
|
||||||
|
|
||||||
|
c32openref_name db 'CONNOpenByReference',0
|
||||||
|
|
||||||
|
_C32_OpenRef_Probe endp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; int C32_MapVar_Probe(UI specLen, UI flag, void *outbuf)
|
||||||
|
;
|
||||||
|
; Exact-ish raw version of w95mconn.o::__C32MapConn16To32 second step.
|
||||||
|
;
|
||||||
|
; It emulates:
|
||||||
|
; C32MAPCONNONE 40 -> server name MARS
|
||||||
|
; NWCSCANCONNINFO(scanIterator/result ptr,
|
||||||
|
; scanInfoLevel=0A, scanConnInfo=NWCString/SPECTDATA "MARS",
|
||||||
|
; scanFlags=1, connInfoVersion=0,
|
||||||
|
; returnInfoLevel=0, returnConnInfo=NULL,
|
||||||
|
; connReference local)
|
||||||
|
;
|
||||||
|
; But calls Client32 CONNScanInfo directly through ECX/NIOS command 0A.
|
||||||
|
;
|
||||||
|
; outbuf:
|
||||||
|
; +00 load AX
|
||||||
|
; +02 resolver off
|
||||||
|
; +04 resolver seg
|
||||||
|
; +06 trampoline off
|
||||||
|
; +08 trampoline seg
|
||||||
|
; +0A function off
|
||||||
|
; +0C function seg
|
||||||
|
; +0E ret AX
|
||||||
|
; +10 ret DX
|
||||||
|
; +12 resultRef low ; corresponds to caller output ptr in w95mconn
|
||||||
|
; +14 resultRef high
|
||||||
|
; +16 connRefLocal low ; corresponds to d32conni local -1c
|
||||||
|
; +18 connRefLocal high
|
||||||
|
_C32_MapVar_Probe proc far
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
sub sp, 140
|
||||||
|
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
; clear ESI/ECX
|
||||||
|
db 66h, 33h, 0F6h
|
||||||
|
db 66h, 33h, 0C9h
|
||||||
|
|
||||||
|
mov ax, 0D8C1h
|
||||||
|
int 2Fh
|
||||||
|
|
||||||
|
mov [bp-4], ax ; load AX
|
||||||
|
; resolver ESI -> [bp-8]
|
||||||
|
db 66h, 89h, 76h, 0F8h
|
||||||
|
; trampoline ECX -> [bp-12]
|
||||||
|
db 66h, 89h, 4Eh, 0F4h
|
||||||
|
|
||||||
|
or ax, ax
|
||||||
|
jne c32mapvar_fail
|
||||||
|
|
||||||
|
; resolve "CONNScanInfo"
|
||||||
|
push cs
|
||||||
|
push offset c32mapvar_name
|
||||||
|
push 0
|
||||||
|
push 0
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 8
|
||||||
|
mov [bp-16], ax
|
||||||
|
mov [bp-14], dx
|
||||||
|
or ax, dx
|
||||||
|
jne c32mapvar_have_func
|
||||||
|
jmp c32mapvar_fail
|
||||||
|
|
||||||
|
c32mapvar_have_func:
|
||||||
|
; resultRef/output dword at [bp-20], init 0
|
||||||
|
mov word ptr [bp-20], 0
|
||||||
|
mov word ptr [bp-18], 0
|
||||||
|
|
||||||
|
; connReference local dword at [bp-24], init 0
|
||||||
|
mov word ptr [bp-24], 0
|
||||||
|
mov word ptr [bp-22], 0
|
||||||
|
|
||||||
|
; string buffer at [bp-80], copy "MARS", zero padded enough
|
||||||
|
lea di, -80[bp]
|
||||||
|
push ss
|
||||||
|
pop es
|
||||||
|
mov byte ptr es:[di+0], 'M'
|
||||||
|
mov byte ptr es:[di+1], 'A'
|
||||||
|
mov byte ptr es:[di+2], 'R'
|
||||||
|
mov byte ptr es:[di+3], 'S'
|
||||||
|
mov byte ptr es:[di+4], 0
|
||||||
|
|
||||||
|
; Map string buffer len 31h -> [bp-28]
|
||||||
|
push 0
|
||||||
|
push 31H
|
||||||
|
push ss
|
||||||
|
lea ax, -80[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-28], ax
|
||||||
|
mov [bp-26], dx
|
||||||
|
|
||||||
|
; Build SPECTDATA/NWCString transfer block at [bp-48], len 10h.
|
||||||
|
; Mirrors d32conni initialization for server-name scan.
|
||||||
|
mov ax, [bp+6]
|
||||||
|
mov word ptr [bp-48], ax
|
||||||
|
mov word ptr [bp-46], 0
|
||||||
|
mov ax, [bp-28]
|
||||||
|
mov word ptr [bp-44], ax
|
||||||
|
mov ax, [bp-26]
|
||||||
|
mov word ptr [bp-42], ax
|
||||||
|
mov word ptr [bp-40], 1
|
||||||
|
mov word ptr [bp-38], 0
|
||||||
|
mov word ptr [bp-36], 0
|
||||||
|
mov word ptr [bp-34], 0
|
||||||
|
|
||||||
|
; Map scanInfo spectdata block len 10h -> [bp-32]
|
||||||
|
push 0
|
||||||
|
push 10H
|
||||||
|
push ss
|
||||||
|
lea ax, -48[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-32], ax
|
||||||
|
mov [bp-30], dx
|
||||||
|
|
||||||
|
; Map resultRef/output len4 -> [bp-56] (this is w95mconn caller ptr)
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push ss
|
||||||
|
lea ax, -20[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-56], ax
|
||||||
|
mov [bp-54], dx
|
||||||
|
|
||||||
|
; Map connReference local len4 -> [bp-60]
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push ss
|
||||||
|
lea ax, -24[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-60], ax
|
||||||
|
mov [bp-58], dx
|
||||||
|
|
||||||
|
; Raw CONNScanInfo via NIOS, following d32wrap _CONNScanInfo
|
||||||
|
; argument order from d32conni L$115.
|
||||||
|
push word ptr [bp-58] ; connReference flat high
|
||||||
|
push word ptr [bp-60] ; connReference flat low
|
||||||
|
|
||||||
|
push 0 ; returnConnInfo flat high = NULL
|
||||||
|
push 0 ; returnConnInfo flat low = NULL
|
||||||
|
|
||||||
|
push 0 ; returnInfoLen high
|
||||||
|
push 0 ; returnInfoLen low
|
||||||
|
|
||||||
|
push 0 ; returnInfoLevel high
|
||||||
|
push 4 ; returnInfoLevel low, as d32conni L$115
|
||||||
|
|
||||||
|
push 0 ; scan flag high
|
||||||
|
push word ptr [bp+8] ; scan flag low
|
||||||
|
|
||||||
|
push word ptr [bp-30] ; scanInfo flat high
|
||||||
|
push word ptr [bp-32] ; scanInfo flat low
|
||||||
|
|
||||||
|
push 0 ; scanInfoLevel high
|
||||||
|
push 0aH ; scanInfoLevel low = SERVER_NAME
|
||||||
|
|
||||||
|
push word ptr [bp-54] ; scanIterator/result flat high
|
||||||
|
push word ptr [bp-56] ; scanIterator/result flat low
|
||||||
|
|
||||||
|
push 0fefeH
|
||||||
|
push 0fefeH
|
||||||
|
push 0fefeH
|
||||||
|
push 0fefeH
|
||||||
|
|
||||||
|
push 0
|
||||||
|
push 0aH
|
||||||
|
push word ptr [bp-14]
|
||||||
|
push word ptr [bp-16]
|
||||||
|
call dword ptr [bp-12]
|
||||||
|
add sp, 30H
|
||||||
|
|
||||||
|
mov [bp-64], ax
|
||||||
|
mov [bp-62], dx
|
||||||
|
|
||||||
|
; Unlock maps.
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push word ptr [bp-58]
|
||||||
|
push word ptr [bp-60]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push word ptr [bp-54]
|
||||||
|
push word ptr [bp-56]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
push 0
|
||||||
|
push 10H
|
||||||
|
push word ptr [bp-30]
|
||||||
|
push word ptr [bp-32]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
push 0
|
||||||
|
push 31H
|
||||||
|
push word ptr [bp-26]
|
||||||
|
push word ptr [bp-28]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-8]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
jmp short c32mapvar_store
|
||||||
|
|
||||||
|
c32mapvar_fail:
|
||||||
|
mov word ptr [bp-16], 0
|
||||||
|
mov word ptr [bp-14], 0
|
||||||
|
mov word ptr [bp-64], 0ffffH
|
||||||
|
mov word ptr [bp-62], 0ffffH
|
||||||
|
mov word ptr [bp-20], 0
|
||||||
|
mov word ptr [bp-18], 0
|
||||||
|
mov word ptr [bp-24], 0
|
||||||
|
mov word ptr [bp-22], 0
|
||||||
|
|
||||||
|
c32mapvar_store:
|
||||||
|
les di, dword ptr [bp+10]
|
||||||
|
|
||||||
|
mov ax, [bp-4]
|
||||||
|
mov es:[di+0], ax
|
||||||
|
mov ax, [bp-8]
|
||||||
|
mov es:[di+2], ax
|
||||||
|
mov ax, [bp-6]
|
||||||
|
mov es:[di+4], ax
|
||||||
|
mov ax, [bp-12]
|
||||||
|
mov es:[di+6], ax
|
||||||
|
mov ax, [bp-10]
|
||||||
|
mov es:[di+8], ax
|
||||||
|
mov ax, [bp-16]
|
||||||
|
mov es:[di+10], ax
|
||||||
|
mov ax, [bp-14]
|
||||||
|
mov es:[di+12], ax
|
||||||
|
mov ax, [bp-64]
|
||||||
|
mov es:[di+14], ax
|
||||||
|
mov ax, [bp-62]
|
||||||
|
mov es:[di+16], ax
|
||||||
|
mov ax, [bp-20]
|
||||||
|
mov es:[di+18], ax
|
||||||
|
mov ax, [bp-18]
|
||||||
|
mov es:[di+20], ax
|
||||||
|
mov ax, [bp-24]
|
||||||
|
mov es:[di+22], ax
|
||||||
|
mov ax, [bp-22]
|
||||||
|
mov es:[di+24], ax
|
||||||
|
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
xor ah, ah
|
||||||
|
ret
|
||||||
|
|
||||||
|
c32mapvar_name db 'CONNScanInfo',0
|
||||||
|
|
||||||
|
_C32_MapVar_Probe endp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; int C32_NCP87_Raw5_Probe(UI connLo, UI connHi,
|
||||||
|
; void *hdr, UI hdrLen,
|
||||||
|
; void *path, UI pathLen,
|
||||||
|
; void *rep0, UI rep0Len,
|
||||||
|
; void *rep1, UI rep1Len,
|
||||||
|
; void *outbuf)
|
||||||
|
;
|
||||||
|
; Same as C32_NCP87_Raw_Probe but uses d32wrap-compatible 5-slot
|
||||||
|
; fragment tables: 5 * 8 = 0x28 bytes for request and reply.
|
||||||
|
_C32_NCP87_Raw5_Probe proc far
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
sub sp, 180
|
||||||
|
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
; clear ESI/ECX
|
||||||
|
db 66h, 33h, 0F6h
|
||||||
|
db 66h, 33h, 0C9h
|
||||||
|
|
||||||
|
mov ax, 0D8C1h
|
||||||
|
int 2Fh
|
||||||
|
|
||||||
|
mov [bp-2], ax
|
||||||
|
db 66h, 89h, 76h, 0FAh ; resolver at [bp-6]
|
||||||
|
db 66h, 89h, 4Eh, 0F6h ; trampoline at [bp-10]
|
||||||
|
|
||||||
|
or ax, ax
|
||||||
|
jne raw5_fail
|
||||||
|
|
||||||
|
; resolve COMPATNcpRequestReply
|
||||||
|
push cs
|
||||||
|
push offset raw5_name
|
||||||
|
push 0
|
||||||
|
push 0
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 8
|
||||||
|
mov [bp-14], ax
|
||||||
|
mov [bp-12], dx
|
||||||
|
or ax, dx
|
||||||
|
jne raw5_have_func
|
||||||
|
jmp raw5_fail
|
||||||
|
|
||||||
|
raw5_have_func:
|
||||||
|
; actual reply len dword at [bp-36]
|
||||||
|
mov word ptr [bp-36], 0
|
||||||
|
mov word ptr [bp-34], 0
|
||||||
|
|
||||||
|
; map hdr -> [bp-20]
|
||||||
|
push 0
|
||||||
|
push word ptr [bp+0eH]
|
||||||
|
push word ptr [bp+0cH]
|
||||||
|
push word ptr [bp+0aH]
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-20], ax
|
||||||
|
mov [bp-18], dx
|
||||||
|
|
||||||
|
; map path -> [bp-24]
|
||||||
|
push 0
|
||||||
|
push word ptr [bp+14H]
|
||||||
|
push word ptr [bp+12H]
|
||||||
|
push word ptr [bp+10H]
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-24], ax
|
||||||
|
mov [bp-22], dx
|
||||||
|
|
||||||
|
; map rep0 -> [bp-28]
|
||||||
|
push 0
|
||||||
|
push word ptr [bp+1aH]
|
||||||
|
push word ptr [bp+18H]
|
||||||
|
push word ptr [bp+16H]
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-28], ax
|
||||||
|
mov [bp-26], dx
|
||||||
|
|
||||||
|
; map rep1 -> [bp-32]
|
||||||
|
push 0
|
||||||
|
push word ptr [bp+20H]
|
||||||
|
push word ptr [bp+1eH]
|
||||||
|
push word ptr [bp+1cH]
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-32], ax
|
||||||
|
mov [bp-30], dx
|
||||||
|
|
||||||
|
; zero req table [bp-160] len 40 and reply table [bp-120] len 40
|
||||||
|
push ss
|
||||||
|
pop es
|
||||||
|
cld
|
||||||
|
xor ax, ax
|
||||||
|
lea di, -160[bp]
|
||||||
|
mov cx, 20
|
||||||
|
rep stosw
|
||||||
|
lea di, -120[bp]
|
||||||
|
mov cx, 20
|
||||||
|
rep stosw
|
||||||
|
|
||||||
|
; req entry0 = hdr
|
||||||
|
mov ax, [bp-20]
|
||||||
|
mov [bp-160], ax
|
||||||
|
mov ax, [bp-18]
|
||||||
|
mov [bp-158], ax
|
||||||
|
mov ax, [bp+0eH]
|
||||||
|
mov [bp-156], ax
|
||||||
|
mov word ptr [bp-154], 0
|
||||||
|
|
||||||
|
; req entry1 = path
|
||||||
|
mov ax, [bp-24]
|
||||||
|
mov [bp-152], ax
|
||||||
|
mov ax, [bp-22]
|
||||||
|
mov [bp-150], ax
|
||||||
|
mov ax, [bp+14H]
|
||||||
|
mov [bp-148], ax
|
||||||
|
mov word ptr [bp-146], 0
|
||||||
|
|
||||||
|
; reply entry0 = rep0
|
||||||
|
mov ax, [bp-28]
|
||||||
|
mov [bp-120], ax
|
||||||
|
mov ax, [bp-26]
|
||||||
|
mov [bp-118], ax
|
||||||
|
mov ax, [bp+1aH]
|
||||||
|
mov [bp-116], ax
|
||||||
|
mov word ptr [bp-114], 0
|
||||||
|
|
||||||
|
; reply entry1 = rep1
|
||||||
|
mov ax, [bp-32]
|
||||||
|
mov [bp-112], ax
|
||||||
|
mov ax, [bp-30]
|
||||||
|
mov [bp-110], ax
|
||||||
|
mov ax, [bp+20H]
|
||||||
|
mov [bp-108], ax
|
||||||
|
mov word ptr [bp-106], 0
|
||||||
|
|
||||||
|
; map req table 0x28 -> [bp-40]
|
||||||
|
push 0
|
||||||
|
push 28H
|
||||||
|
push ss
|
||||||
|
lea ax, -160[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-40], ax
|
||||||
|
mov [bp-38], dx
|
||||||
|
|
||||||
|
; map reply table 0x28 -> [bp-44]
|
||||||
|
push 0
|
||||||
|
push 28H
|
||||||
|
push ss
|
||||||
|
lea ax, -120[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-44], ax
|
||||||
|
mov [bp-42], dx
|
||||||
|
|
||||||
|
; map actual reply len -> [bp-48]
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push ss
|
||||||
|
lea ax, -36[bp]
|
||||||
|
push ax
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
mov [bp-48], ax
|
||||||
|
mov [bp-46], dx
|
||||||
|
|
||||||
|
; call COMPAT via NIOS command 8
|
||||||
|
push word ptr [bp-46]
|
||||||
|
push word ptr [bp-48]
|
||||||
|
push word ptr [bp-42]
|
||||||
|
push word ptr [bp-44]
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
push word ptr [bp-38]
|
||||||
|
push word ptr [bp-40]
|
||||||
|
push 0
|
||||||
|
push 2
|
||||||
|
push 0
|
||||||
|
push 57H
|
||||||
|
push 0
|
||||||
|
push 0
|
||||||
|
push word ptr [bp+8]
|
||||||
|
push word ptr [bp+6]
|
||||||
|
push 0
|
||||||
|
push 8
|
||||||
|
push word ptr [bp-12]
|
||||||
|
push word ptr [bp-14]
|
||||||
|
call dword ptr [bp-10]
|
||||||
|
add sp, 28H
|
||||||
|
|
||||||
|
mov [bp-52], ax
|
||||||
|
mov [bp-50], dx
|
||||||
|
|
||||||
|
; unlock important mappings only; ignore return
|
||||||
|
push 0
|
||||||
|
push 4
|
||||||
|
push word ptr [bp-46]
|
||||||
|
push word ptr [bp-48]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
push 0
|
||||||
|
push 28H
|
||||||
|
push word ptr [bp-42]
|
||||||
|
push word ptr [bp-44]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
push 0
|
||||||
|
push 28H
|
||||||
|
push word ptr [bp-38]
|
||||||
|
push word ptr [bp-40]
|
||||||
|
push 0
|
||||||
|
push 3
|
||||||
|
call dword ptr [bp-6]
|
||||||
|
add sp, 0cH
|
||||||
|
|
||||||
|
jmp short raw5_store
|
||||||
|
|
||||||
|
raw5_fail:
|
||||||
|
mov word ptr [bp-14], 0
|
||||||
|
mov word ptr [bp-12], 0
|
||||||
|
mov word ptr [bp-52], 0ffffH
|
||||||
|
mov word ptr [bp-50], 0ffffH
|
||||||
|
mov word ptr [bp-36], 0
|
||||||
|
mov word ptr [bp-34], 0
|
||||||
|
|
||||||
|
raw5_store:
|
||||||
|
les di, dword ptr [bp+22H]
|
||||||
|
mov ax, [bp-2]
|
||||||
|
mov es:[di+0], ax
|
||||||
|
mov ax, [bp-6]
|
||||||
|
mov es:[di+2], ax
|
||||||
|
mov ax, [bp-4]
|
||||||
|
mov es:[di+4], ax
|
||||||
|
mov ax, [bp-10]
|
||||||
|
mov es:[di+6], ax
|
||||||
|
mov ax, [bp-8]
|
||||||
|
mov es:[di+8], ax
|
||||||
|
mov ax, [bp-14]
|
||||||
|
mov es:[di+10], ax
|
||||||
|
mov ax, [bp-12]
|
||||||
|
mov es:[di+12], ax
|
||||||
|
mov ax, [bp-52]
|
||||||
|
mov es:[di+14], ax
|
||||||
|
mov ax, [bp-50]
|
||||||
|
mov es:[di+16], ax
|
||||||
|
mov ax, [bp-36]
|
||||||
|
mov es:[di+18], ax
|
||||||
|
mov ax, [bp-34]
|
||||||
|
mov es:[di+20], ax
|
||||||
|
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
xor ah, ah
|
||||||
|
ret
|
||||||
|
|
||||||
|
raw5_name db 'COMPATNcpRequestReply',0
|
||||||
|
|
||||||
|
_C32_NCP87_Raw5_Probe endp
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
734
login.c
734
login.c
@@ -6,6 +6,577 @@
|
|||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "nwcrypt.h"
|
#include "nwcrypt.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifndef BLACK
|
||||||
|
#define BLACK 0
|
||||||
|
#endif
|
||||||
|
#ifndef BLUE
|
||||||
|
#define BLUE 1
|
||||||
|
#endif
|
||||||
|
#ifndef LIGHTGRAY
|
||||||
|
#define LIGHTGRAY 7
|
||||||
|
#endif
|
||||||
|
#ifndef WHITE
|
||||||
|
#define WHITE 15
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint8 script_login_name[64];
|
||||||
|
static uint8 script_file_server[52];
|
||||||
|
|
||||||
|
static char **build_argv(char *buf, int bufsize, char *str);
|
||||||
|
extern int read_command_file(char *fstr);
|
||||||
|
extern int get_fs_name(int connid, char *name);
|
||||||
|
|
||||||
|
|
||||||
|
static uint8 login_video_attr = 0x07;
|
||||||
|
|
||||||
|
static void login_gotoxy(int x, int y)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
|
||||||
|
regs.h.ah = 0x02;
|
||||||
|
regs.h.bh = 0x00;
|
||||||
|
regs.h.dh = (uint8)(y - 1);
|
||||||
|
regs.h.dl = (uint8)(x - 1);
|
||||||
|
int86(0x10, ®s, ®s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void login_cls_attr(uint8 attr)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
|
||||||
|
regs.h.ah = 0x06;
|
||||||
|
regs.h.al = 0x00;
|
||||||
|
regs.h.bh = attr;
|
||||||
|
regs.h.ch = 0;
|
||||||
|
regs.h.cl = 0;
|
||||||
|
regs.h.dh = 24;
|
||||||
|
regs.h.dl = 79;
|
||||||
|
int86(0x10, ®s, ®s);
|
||||||
|
login_gotoxy(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void login_write_attr(int x, int y, const char *s, uint8 attr)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
int col = x;
|
||||||
|
|
||||||
|
while (*s) {
|
||||||
|
login_gotoxy(col++, y);
|
||||||
|
regs.h.ah = 0x09;
|
||||||
|
regs.h.al = (uint8)*s++;
|
||||||
|
regs.h.bh = 0;
|
||||||
|
regs.h.bl = attr;
|
||||||
|
regs.x.cx = 1;
|
||||||
|
int86(0x10, ®s, ®s);
|
||||||
|
}
|
||||||
|
login_gotoxy(col, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void login_fill_line(int y, uint8 attr)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
|
||||||
|
login_gotoxy(1, y);
|
||||||
|
regs.h.ah = 0x09;
|
||||||
|
regs.h.al = ' ';
|
||||||
|
regs.h.bh = 0;
|
||||||
|
regs.h.bl = attr;
|
||||||
|
regs.x.cx = 80;
|
||||||
|
int86(0x10, ®s, ®s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void login_screen_normal(void)
|
||||||
|
{
|
||||||
|
login_video_attr = 0x07;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int login_help(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, " LOGIN General Help Mars NWE\n");
|
||||||
|
fprintf(stdout, " ------------------------------------------------------------------------\n");
|
||||||
|
fprintf(stdout, " Purpose: To gain access to the network.\n");
|
||||||
|
fprintf(stdout, " Syntax: LOGIN [/VER] [[Server | Tree/][Username] [/options]\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, " To: Use:\n");
|
||||||
|
fprintf(stdout, " Login without running login scripts /NS\n");
|
||||||
|
fprintf(stdout, " Clear the screen before executing /CLS\n");
|
||||||
|
fprintf(stdout, " Specify a script file /S filename\n");
|
||||||
|
fprintf(stdout, " Display version information /VER\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, " Examples:\n");
|
||||||
|
fprintf(stdout, " LOGIN SUPERVISOR\n");
|
||||||
|
fprintf(stdout, " LOGIN MARS/SUPERVISOR\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void login_banner(void)
|
||||||
|
{
|
||||||
|
login_cls_attr(0x07); /* normal black background */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NetWare-like header, but blue for Mars NWE:
|
||||||
|
* blue separator
|
||||||
|
* blue title line
|
||||||
|
* blue separator
|
||||||
|
* then normal black prompt area.
|
||||||
|
*/
|
||||||
|
login_fill_line(1, 0x1f); /* white on blue */
|
||||||
|
login_fill_line(2, 0x1f); /* white on blue */
|
||||||
|
login_write_attr(36, 2, "Mars NWE", 0x1f);
|
||||||
|
login_fill_line(3, 0x1f); /* white on blue */
|
||||||
|
|
||||||
|
login_screen_normal();
|
||||||
|
login_gotoxy(1, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *skip_spaces(char *p)
|
||||||
|
{
|
||||||
|
while (*p == 32 || *p == '\t') p++;
|
||||||
|
return(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void strip_quotes(char *s)
|
||||||
|
{
|
||||||
|
char *d = s;
|
||||||
|
char quote = 0;
|
||||||
|
|
||||||
|
while (*s) {
|
||||||
|
if (!quote && (*s == '"' || *s == '\'')) {
|
||||||
|
quote = *s++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (quote && *s == quote) {
|
||||||
|
quote = 0;
|
||||||
|
s++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void script_get_timevar(char *name, char *out, int outlen)
|
||||||
|
{
|
||||||
|
time_t now;
|
||||||
|
struct tm *tmv;
|
||||||
|
int hour;
|
||||||
|
static char *months[] = {
|
||||||
|
"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
|
||||||
|
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
|
||||||
|
};
|
||||||
|
static char *days[] = {
|
||||||
|
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
|
||||||
|
"THURSDAY", "FRIDAY", "SATURDAY"
|
||||||
|
};
|
||||||
|
|
||||||
|
*out = '\0';
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
tmv = localtime(&now);
|
||||||
|
if (!tmv) return;
|
||||||
|
|
||||||
|
upstr(name);
|
||||||
|
|
||||||
|
if (!strcmp(name, "GREETING_TIME")) {
|
||||||
|
if (tmv->tm_hour < 12) strcpy(out, "MORNING");
|
||||||
|
else if (tmv->tm_hour < 18) strcpy(out, "AFTERNOON");
|
||||||
|
else strcpy(out, "EVENING");
|
||||||
|
} else if (!strcmp(name, "MONTH_NAME")) {
|
||||||
|
strmaxcpy(out, months[tmv->tm_mon], outlen - 1);
|
||||||
|
} else if (!strcmp(name, "MONTH")) {
|
||||||
|
sprintf(out, "%02d", tmv->tm_mon + 1);
|
||||||
|
} else if (!strcmp(name, "DAY")) {
|
||||||
|
sprintf(out, "%02d", tmv->tm_mday);
|
||||||
|
} else if (!strcmp(name, "YEAR")) {
|
||||||
|
sprintf(out, "%04d", tmv->tm_year + 1900);
|
||||||
|
} else if (!strcmp(name, "DAY_OF_WEEK")) {
|
||||||
|
strmaxcpy(out, days[tmv->tm_wday], outlen - 1);
|
||||||
|
} else if (!strcmp(name, "HOUR")) {
|
||||||
|
hour = tmv->tm_hour % 12;
|
||||||
|
if (!hour) hour = 12;
|
||||||
|
sprintf(out, "%d", hour);
|
||||||
|
} else if (!strcmp(name, "MINUTE")) {
|
||||||
|
sprintf(out, "%02d", tmv->tm_min);
|
||||||
|
} else if (!strcmp(name, "SECOND")) {
|
||||||
|
sprintf(out, "%02d", tmv->tm_sec);
|
||||||
|
} else if (!strcmp(name, "AM_PM")) {
|
||||||
|
strcpy(out, tmv->tm_hour >= 12 ? "PM" : "AM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void script_expand_var(char *name, char *out, int outlen)
|
||||||
|
{
|
||||||
|
upstr(name);
|
||||||
|
*out = '\0';
|
||||||
|
|
||||||
|
if (!strcmp(name, "LOGIN_NAME")) {
|
||||||
|
strmaxcpy(out, script_login_name, outlen - 1);
|
||||||
|
} else if (!strcmp(name, "FILE_SERVER")) {
|
||||||
|
strmaxcpy(out, script_file_server, outlen - 1);
|
||||||
|
} else if (!strcmp(name, "P_STATION") || !strcmp(name, "STATION")) {
|
||||||
|
strcpy(out, "000000000000");
|
||||||
|
} else {
|
||||||
|
script_get_timevar(name, out, outlen);
|
||||||
|
if (!*out) {
|
||||||
|
strcpy(out, "%");
|
||||||
|
strncat(out, name, outlen - strlen(out) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void script_put_expanded(char *s)
|
||||||
|
{
|
||||||
|
while (s && *s) {
|
||||||
|
if (*s == '%') {
|
||||||
|
char name[64];
|
||||||
|
char value[128];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
s++;
|
||||||
|
while ((*s == '_' ||
|
||||||
|
(*s >= 'A' && *s <= 'Z') ||
|
||||||
|
(*s >= 'a' && *s <= 'z') ||
|
||||||
|
(*s >= '0' && *s <= '9')) &&
|
||||||
|
i < (int)sizeof(name) - 1) {
|
||||||
|
name[i++] = *s++;
|
||||||
|
}
|
||||||
|
name[i] = '\0';
|
||||||
|
|
||||||
|
if (i) {
|
||||||
|
script_expand_var(name, value, sizeof(value));
|
||||||
|
fprintf(stdout, "%s", value);
|
||||||
|
} else {
|
||||||
|
fputc('%', stdout);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fputc(*s++, stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void script_write(char *p)
|
||||||
|
{
|
||||||
|
p = skip_spaces(p);
|
||||||
|
strip_quotes(p);
|
||||||
|
script_put_expanded(p);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void script_join_args(char **argv, int argc)
|
||||||
|
{
|
||||||
|
if (argc > 2) {
|
||||||
|
char *p = argv[argc-1];
|
||||||
|
while (p-- > argv[1]) {
|
||||||
|
if (*p == '\0') *p = 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void script_call_line(char *line)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
char **argv;
|
||||||
|
int argc = 0;
|
||||||
|
char **pp;
|
||||||
|
|
||||||
|
buf = xmalloc(512);
|
||||||
|
argv = build_argv(buf, 512, line);
|
||||||
|
if (argv != NULL) {
|
||||||
|
pp = argv;
|
||||||
|
while (*pp) {
|
||||||
|
argc++;
|
||||||
|
pp++;
|
||||||
|
}
|
||||||
|
if (argc > 0) {
|
||||||
|
upstr(argv[0]);
|
||||||
|
call_func_entry(argc, argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xfree(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int script_eval_if(char *line)
|
||||||
|
{
|
||||||
|
char tmp[512];
|
||||||
|
char *p;
|
||||||
|
char *q;
|
||||||
|
int neg = 0;
|
||||||
|
|
||||||
|
strmaxcpy(tmp, line, sizeof(tmp) - 1);
|
||||||
|
upstr(tmp);
|
||||||
|
|
||||||
|
if (strstr(tmp, "MEMBER OF") != NULL) {
|
||||||
|
if (strstr(tmp, "EVERYONE") != NULL) return(1);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strstr(tmp, "LOGIN_NAME");
|
||||||
|
if (p != NULL) {
|
||||||
|
q = strstr(p, "<>");
|
||||||
|
if (q != NULL) neg = 1;
|
||||||
|
else q = strchr(p, '=');
|
||||||
|
|
||||||
|
if (q != NULL) {
|
||||||
|
char want[64];
|
||||||
|
char have[64];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
q += neg ? 2 : 1;
|
||||||
|
q = skip_spaces(q);
|
||||||
|
if (*q == '"' || *q == '\'') q++;
|
||||||
|
|
||||||
|
while (*q && *q != '"' && *q != '\'' && *q != 32 && *q != '\t' && i < 63)
|
||||||
|
want[i++] = *q++;
|
||||||
|
want[i] = '\0';
|
||||||
|
|
||||||
|
strmaxcpy(have, script_login_name, sizeof(have) - 1);
|
||||||
|
upstr(have);
|
||||||
|
|
||||||
|
if (neg) return(strcmp(have, want) != 0);
|
||||||
|
return(strcmp(have, want) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strstr(tmp, "DAY_OF_WEEK");
|
||||||
|
if (p != NULL) {
|
||||||
|
q = strchr(p, '=');
|
||||||
|
if (q != NULL) {
|
||||||
|
char want[64];
|
||||||
|
char have[64];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
q++;
|
||||||
|
q = skip_spaces(q);
|
||||||
|
if (*q == '"' || *q == '\'') q++;
|
||||||
|
|
||||||
|
while (*q && *q != '"' && *q != '\'' && *q != 32 && *q != '\t' && i < 63)
|
||||||
|
want[i++] = *q++;
|
||||||
|
want[i] = '\0';
|
||||||
|
|
||||||
|
strcpy(have, "DAY_OF_WEEK");
|
||||||
|
script_get_timevar(have, have, sizeof(have));
|
||||||
|
upstr(have);
|
||||||
|
|
||||||
|
return(strcmp(have, want) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int login_strnicmp(char *a, char *b, int n)
|
||||||
|
{
|
||||||
|
while (n-- > 0) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(ca - cb);
|
||||||
|
if (!ca) return(0);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int script_execute_line(char *line)
|
||||||
|
{
|
||||||
|
char work[512];
|
||||||
|
char cmd[32];
|
||||||
|
char *p;
|
||||||
|
char *arg;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
strmaxcpy(work, line, sizeof(work) - 1);
|
||||||
|
p = skip_spaces(work);
|
||||||
|
|
||||||
|
if (!*p || *p == ';') return(0);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (p[i] && p[i] != 32 && p[i] != '\t' && i < 31) {
|
||||||
|
cmd[i] = p[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
cmd[i] = '\0';
|
||||||
|
upstr(cmd);
|
||||||
|
|
||||||
|
arg = skip_spaces(p + i);
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "WRITE") || !strcmp(cmd, "ECHO")) {
|
||||||
|
script_write(arg);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "PAUSE")) {
|
||||||
|
fprintf(stdout, "Strike any key when ready . . .");
|
||||||
|
fflush(stdout);
|
||||||
|
getch();
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "CLS")) {
|
||||||
|
login_cls_attr(0x07);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "BREAK")) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "SET")) {
|
||||||
|
if (*arg) putglobenv(arg);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "DRIVE")) {
|
||||||
|
arg = skip_spaces(arg);
|
||||||
|
if ((*arg >= 'A' && *arg <= 'Z') || (*arg >= 'a' && *arg <= 'z')) {
|
||||||
|
if (*arg >= 'a') setdisk(*arg - 'a');
|
||||||
|
else setdisk(*arg - 'A');
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "MAP")) {
|
||||||
|
char up[512];
|
||||||
|
|
||||||
|
strmaxcpy(up, arg, sizeof(up) - 1);
|
||||||
|
upstr(up);
|
||||||
|
|
||||||
|
if (!strncmp(up, "DISPLAY", 7)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strncmp(up, "ROOT ", 5)) {
|
||||||
|
char callbuf[512];
|
||||||
|
sprintf(callbuf, "MAP %s", skip_spaces(arg + 5));
|
||||||
|
script_call_line(callbuf);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strncmp(up, "INS ", 4) || !strncmp(up, "INSERT ", 7)) {
|
||||||
|
char callbuf[512];
|
||||||
|
char *a = arg;
|
||||||
|
if (!login_strnicmp(up, "INS ", 4)) a += 4;
|
||||||
|
else a += 7;
|
||||||
|
sprintf(callbuf, "PATHINS %s", skip_spaces(a));
|
||||||
|
script_call_line(callbuf);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strncmp(up, "DEL ", 4) || !strncmp(up, "DELETE ", 7)) {
|
||||||
|
char callbuf[512];
|
||||||
|
char *a = arg;
|
||||||
|
if (!login_strnicmp(up, "DEL ", 4)) a += 4;
|
||||||
|
else a += 7;
|
||||||
|
sprintf(callbuf, "PATHDEL %s", skip_spaces(a));
|
||||||
|
script_call_line(callbuf);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "ATTACH")) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "EXIT")) {
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
script_call_line(p);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int try_login_script_file(char *name)
|
||||||
|
{
|
||||||
|
return(read_command_file(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_login_script(void)
|
||||||
|
{
|
||||||
|
char profile[200];
|
||||||
|
char drive;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Novell LOGIN looks for the system login script using server based paths,
|
||||||
|
* for example \\SERVER\SYS\PUBLIC\NET$LOG.DAT. Try that first.
|
||||||
|
*/
|
||||||
|
if (*script_file_server) {
|
||||||
|
sprintf(profile, "\\\\%s\\SYS\\PUBLIC\\NET$LOG.DAT", script_file_server);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "\\\\%s\\SYS\\PUBLIC\\net$log.dat", script_file_server);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "\\\\%s\\SYS\\LOGIN\\LOGIN", script_file_server);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "\\\\%s\\SYS\\LOGIN\\NET$LOG.DAT", script_file_server);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Then try current directory and the executable path. LOGIN.EXE is often
|
||||||
|
* executed from PUBLIC, so this covers SYS:PUBLIC\NET$LOG.DAT without
|
||||||
|
* relying on an absolute drive path.
|
||||||
|
*/
|
||||||
|
if (try_login_script_file("NET$LOG.DAT") != -2) return(0);
|
||||||
|
if (try_login_script_file("net$log.dat") != -2) return(0);
|
||||||
|
if (try_login_script_file("LOGIN") != -2) return(0);
|
||||||
|
if (try_login_script_file("login") != -2) return(0);
|
||||||
|
|
||||||
|
if (*prgpath) {
|
||||||
|
sprintf(profile, "%sNET$LOG.DAT", prgpath);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "%snet$log.dat", prgpath);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "%sLOGIN", prgpath);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "%slogin", prgpath);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fallbacks for requesters/runtimes that cannot open UNC from C fopen().
|
||||||
|
*/
|
||||||
|
if (try_login_script_file("\\PUBLIC\\NET$LOG.DAT") != -2) return(0);
|
||||||
|
if (try_login_script_file("\\public\\net$log.dat") != -2) return(0);
|
||||||
|
if (try_login_script_file("\\PUBLIC\\LOGIN") != -2) return(0);
|
||||||
|
if (try_login_script_file("\\public\\login") != -2) return(0);
|
||||||
|
|
||||||
|
if (try_login_script_file("\\LOGIN\\LOGIN") != -2) return(0);
|
||||||
|
if (try_login_script_file("\\login\\login") != -2) return(0);
|
||||||
|
if (try_login_script_file("\\LOGIN\\NET$LOG.DAT") != -2) return(0);
|
||||||
|
if (try_login_script_file("\\login\\net$log.dat") != -2) return(0);
|
||||||
|
|
||||||
|
for (drive = 'C'; drive <= 'Z'; drive++) {
|
||||||
|
sprintf(profile, "%c:\\PUBLIC\\NET$LOG.DAT", drive);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "%c:\\public\\net$log.dat", drive);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "%c:\\PUBLIC\\LOGIN", drive);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "%c:\\LOGIN\\LOGIN", drive);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
|
||||||
|
sprintf(profile, "%c:\\LOGIN\\NET$LOG.DAT", drive);
|
||||||
|
if (try_login_script_file(profile) != -2) return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int do_change_object_passwd(char *name,
|
static int do_change_object_passwd(char *name,
|
||||||
uint16 objtyp,
|
uint16 objtyp,
|
||||||
@@ -14,31 +585,55 @@ static int do_change_object_passwd(char *name,
|
|||||||
|
|
||||||
{
|
{
|
||||||
uint8 key[8];
|
uint8 key[8];
|
||||||
if (0 && !ncp_17_17(key)) {
|
|
||||||
|
if (!ncp_17_17(key)) {
|
||||||
uint32 objid = ncp_17_35(name, objtyp);
|
uint32 objid = ncp_17_35(name, objtyp);
|
||||||
if (objid) {
|
if (objid) {
|
||||||
uint8 buff[128];
|
uint8 oldpwd[16]; /* old passwd as stored by server */
|
||||||
uint8 encrypted[8];
|
uint8 newpwd[16]; /* new passwd as stored by server */
|
||||||
uint8 newcryptpasswd[16];
|
uint8 cryptkey[8];
|
||||||
int passwdx=0;
|
|
||||||
uint8 tmpid[4];
|
uint8 tmpid[4];
|
||||||
|
uint8 passwdx;
|
||||||
|
int newlen;
|
||||||
|
|
||||||
|
memcpy(cryptkey, key, 8);
|
||||||
U32_TO_BE32(objid, tmpid);
|
U32_TO_BE32(objid, tmpid);
|
||||||
shuffle(tmpid, oldpassword, strlen(oldpassword), buff);
|
|
||||||
nw_encrypt(key, buff, encrypted);
|
|
||||||
|
|
||||||
shuffle(tmpid, newpassword, strlen(newpassword), buff);
|
shuffle(tmpid, oldpassword, strlen(oldpassword), oldpwd);
|
||||||
|
shuffle(tmpid, newpassword, strlen(newpassword), newpwd);
|
||||||
|
|
||||||
if (!ncp_17_4b(encrypted, name, objtyp, passwdx, newcryptpasswd)) {
|
nw_encrypt(cryptkey, oldpwd, cryptkey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Same keyed change password transformation as ncpfs
|
||||||
|
* ncp_change_login_passwd(): encrypt both 8-byte halves of the
|
||||||
|
* stored new password using the stored old password as key material.
|
||||||
|
* newpassencrypt() intentionally mutates oldpwd; the passwd length
|
||||||
|
* byte must be calculated afterwards, just like ncpfs does it.
|
||||||
|
*/
|
||||||
|
newpassencrypt(oldpwd, newpwd);
|
||||||
|
newpassencrypt(oldpwd + 8, newpwd + 8);
|
||||||
|
|
||||||
|
newlen = strlen(newpassword);
|
||||||
|
if (newlen > 63) newlen = 63;
|
||||||
|
passwdx = (uint8)(((newlen ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40);
|
||||||
|
|
||||||
|
if (!ncp_17_4b(cryptkey, name, objtyp, passwdx, newpwd)) {
|
||||||
;;
|
;;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { /* now we use old unencrypted algorithmus */
|
|
||||||
if (!ncp_17_40(name, objtyp, oldpassword, newpassword)) {
|
|
||||||
;;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fallback for old servers/requesters where Get Encryption Key is not
|
||||||
|
* available. Keep the original unencrypted behavior as fallback only.
|
||||||
|
*/
|
||||||
|
if (!ncp_17_40(name, objtyp, oldpassword, newpassword)) {
|
||||||
|
;;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +678,10 @@ static int get_raw_str(uint8 *s, int maxlen, int doecho)
|
|||||||
case 8 : if (len) {
|
case 8 : if (len) {
|
||||||
--len;
|
--len;
|
||||||
--s;
|
--s;
|
||||||
if (doecho) fprintf(stdout, "\010 \010");
|
if (doecho) {
|
||||||
|
fprintf(stdout, "\010 \010");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
} else beep();
|
} else beep();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -94,7 +692,10 @@ static int get_raw_str(uint8 *s, int maxlen, int doecho)
|
|||||||
len++;
|
len++;
|
||||||
break;
|
break;
|
||||||
} /* switch */
|
} /* switch */
|
||||||
if (doecho) fprintf(stdout, "%c", (uint8)key);
|
if (doecho) {
|
||||||
|
fprintf(stdout, "%c", (uint8)key);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*s='\0';
|
*s='\0';
|
||||||
return(len);
|
return(len);
|
||||||
@@ -110,9 +711,7 @@ static void getstr(char *what, char *str, int rsize, int doecho)
|
|||||||
|
|
||||||
static int login_usage(void)
|
static int login_usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage:\t%s [-u] [user | user password]\n", funcname);
|
return(login_help());
|
||||||
fprintf(stderr, "\t-u : use unecrypted password\n" );
|
|
||||||
return(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int func_login(int argc, char *argv[], int mode)
|
int func_login(int argc, char *argv[], int mode)
|
||||||
@@ -122,10 +721,23 @@ int func_login(int argc, char *argv[], int mode)
|
|||||||
uint8 uname[200];
|
uint8 uname[200];
|
||||||
uint8 upasswd[200];
|
uint8 upasswd[200];
|
||||||
SEARCH_VECTOR save_drives;
|
SEARCH_VECTOR save_drives;
|
||||||
|
int interactive_login = 0;
|
||||||
|
int no_script = 0;
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
if (argv[1][0] == '-') {
|
if (!strcmp(argv[1], "/?") || !strcmp(argv[1], "-?") || !strcmp(argv[1], "?"))
|
||||||
if (argv[1][1] == 'u') option |= 1;
|
return(login_help());
|
||||||
|
if (!strcmp(argv[1], "/VER") || !strcmp(argv[1], "-VER")) {
|
||||||
|
fprintf(stdout, "Mars NWE LOGIN 0.99\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
if (argv[1][0] == '-' || argv[1][0] == '/') {
|
||||||
|
if (argv[1][1] == 'u' || argv[1][1] == 'U') option |= 1;
|
||||||
|
else if (!strcmp(argv[1], "/NS") || !strcmp(argv[1], "-NS")) no_script = 1;
|
||||||
|
else if (!strcmp(argv[1], "/CLS") || !strcmp(argv[1], "-CLS")) login_cls_attr(0x07);
|
||||||
else return(login_usage());
|
else return(login_usage());
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
@@ -138,13 +750,18 @@ int func_login(int argc, char *argv[], int mode)
|
|||||||
if (argc > 2) strmaxcpy(upasswd, argv[2], sizeof(upasswd) -1);
|
if (argc > 2) strmaxcpy(upasswd, argv[2], sizeof(upasswd) -1);
|
||||||
else upasswd[0]='\0';
|
else upasswd[0]='\0';
|
||||||
|
|
||||||
|
if (!uname[0]) {
|
||||||
|
interactive_login = 1;
|
||||||
|
login_banner();
|
||||||
|
}
|
||||||
|
|
||||||
while (result) {
|
while (result) {
|
||||||
if (!uname[0]) getstr("Login", uname, sizeof(uname)-1, 1);
|
if (!uname[0]) getstr("Enter your login name", uname, sizeof(uname)-1, 1);
|
||||||
if (uname[0]) {
|
if (uname[0]) {
|
||||||
upstr(uname);
|
upstr(uname);
|
||||||
upstr(upasswd);
|
upstr(upasswd);
|
||||||
if ((result = do_object_login(uname, 0x1, upasswd, option)) < 0 && !*upasswd) {
|
if ((result = do_object_login(uname, 0x1, upasswd, option)) < 0 && !*upasswd) {
|
||||||
getstr("Password", upasswd, sizeof(upasswd)-1, 0);
|
getstr("Enter your password", upasswd, sizeof(upasswd)-1, 0);
|
||||||
upstr(upasswd);
|
upstr(upasswd);
|
||||||
result = do_object_login(uname, 0x1, upasswd, option);
|
result = do_object_login(uname, 0x1, upasswd, option);
|
||||||
}
|
}
|
||||||
@@ -156,10 +773,18 @@ int func_login(int argc, char *argv[], int mode)
|
|||||||
} else break;
|
} else break;
|
||||||
}
|
}
|
||||||
if (result > -1) {
|
if (result > -1) {
|
||||||
char profile[200];
|
strmaxcpy(script_login_name, uname, sizeof(script_login_name) - 1);
|
||||||
|
|
||||||
|
if (get_fs_name(1, script_file_server))
|
||||||
|
strcpy(script_file_server, "MARS");
|
||||||
|
|
||||||
|
if (interactive_login)
|
||||||
|
fprintf(stdout, "You are attached to server %s.\n", script_file_server);
|
||||||
|
|
||||||
remove_nwpathes();
|
remove_nwpathes();
|
||||||
sprintf(profile, "%slogin", prgpath);
|
|
||||||
read_command_file(profile);
|
if (!no_script)
|
||||||
|
run_login_script();
|
||||||
} else {
|
} else {
|
||||||
(void)set_search_drive_vektor(save_drives);
|
(void)set_search_drive_vektor(save_drives);
|
||||||
}
|
}
|
||||||
@@ -294,36 +919,53 @@ int read_command_file(char *fstr)
|
|||||||
{
|
{
|
||||||
FILE *f=fopen(fstr, "r");
|
FILE *f=fopen(fstr, "r");
|
||||||
int result=-1;
|
int result=-1;
|
||||||
|
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
char *linebuf= xmalloc(512);
|
char *linebuf = xmalloc(512);
|
||||||
char *buf = xmalloc(512);
|
char *buf = xmalloc(512);
|
||||||
|
int stack[16];
|
||||||
|
int level = 0;
|
||||||
|
int active = 1;
|
||||||
|
|
||||||
while (get_line(f, buf, 512, linebuf, 512) > -1) {
|
while (get_line(f, buf, 512, linebuf, 512) > -1) {
|
||||||
char **argv=build_argv(buf, 512, linebuf);
|
char tmp[512];
|
||||||
if (argv != NULL) {
|
char *p;
|
||||||
int argc=0;
|
|
||||||
char **pp=argv;
|
strmaxcpy(tmp, linebuf, sizeof(tmp) - 1);
|
||||||
while (*pp) {
|
p = skip_spaces(tmp);
|
||||||
argc++;
|
upstr(p);
|
||||||
pp++;
|
|
||||||
|
if (!strncmp(p, "IF ", 3)) {
|
||||||
|
if (level < 16) {
|
||||||
|
stack[level++] = active;
|
||||||
|
active = active && script_eval_if(linebuf);
|
||||||
}
|
}
|
||||||
upstr(argv[0]);
|
|
||||||
if (argc > 2 && !strcmp(argv[0], "ECHO")) {
|
|
||||||
char *p=argv[argc-1];
|
|
||||||
while (p-- > argv[1]) {
|
|
||||||
if (*p=='\0') *p=32;
|
|
||||||
}
|
|
||||||
argc=2;
|
|
||||||
}
|
|
||||||
call_func_entry(argc, argv);
|
|
||||||
result = 0;
|
result = 0;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(p, "END") || !strncmp(p, "END ", 4)) {
|
||||||
|
if (level > 0) active = stack[--level];
|
||||||
|
result = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!active) {
|
||||||
|
result = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script_execute_line(linebuf))
|
||||||
|
break;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
xfree(linebuf);
|
xfree(linebuf);
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
} else result=-2;
|
} else result=-2;
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,9 +1034,9 @@ int func_exec(int argc, char *argv[], int mode)
|
|||||||
xfree(buff);
|
xfree(buff);
|
||||||
if (nargv != NULL) {
|
if (nargv != NULL) {
|
||||||
if (!mode)
|
if (!mode)
|
||||||
spawnvp(P_WAIT, buf, nargv);
|
spawnvp(P_WAIT, buf, (const char *const *)nargv);
|
||||||
else
|
else
|
||||||
execvp(buf, nargv);
|
execvp(buf, (const char *const *)nargv);
|
||||||
}
|
}
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
}
|
}
|
||||||
|
|||||||
355
map.c
355
map.c
@@ -28,9 +28,9 @@ static void show_map(uint8 *drvstr)
|
|||||||
if (flags & 0x80) { /* lokal DRIVE */
|
if (flags & 0x80) { /* lokal DRIVE */
|
||||||
path[0]= '\\';
|
path[0]= '\\';
|
||||||
if (j < 2){
|
if (j < 2){
|
||||||
strcpy(path, "DISK LW");
|
strcpy(path, "maps to a local disk.");
|
||||||
} else if (getcurdir(j+1, path+1)) {
|
} else if (getcurdir(j+1, path+1)) {
|
||||||
strcpy(path, "LW !OK");
|
strcpy(path, "maps to a local disk.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (get_dir_path(dhandle, path)) {
|
if (get_dir_path(dhandle, path)) {
|
||||||
@@ -41,7 +41,7 @@ static void show_map(uint8 *drvstr)
|
|||||||
strcat(servern, "\\");
|
strcat(servern, "\\");
|
||||||
} else servern[0]='\0';
|
} else servern[0]='\0';
|
||||||
}
|
}
|
||||||
printf("MAP %c: = %s%s\n", (char)j+'A', servern, path);
|
if (flags & 0x80) printf("Drive %c: %s\n", (char)j+'A', path); else printf("Drive %c: = %s%s\n", (char)j+'A', servern, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,9 +58,9 @@ static void do_map(int drive, NWPATH *nwp)
|
|||||||
if (flags & 0x80) { /* lokal DRIVE */
|
if (flags & 0x80) { /* lokal DRIVE */
|
||||||
path[0]= '\\';
|
path[0]= '\\';
|
||||||
if (drive < 2){
|
if (drive < 2){
|
||||||
strcpy(path, "DISK LW");
|
strcpy(path, "maps to a local disk.");
|
||||||
} else if (getcurdir(drive+1, path+1)) {
|
} else if (getcurdir(drive+1, path+1)) {
|
||||||
strcpy(path, "LW !OK");
|
strcpy(path, "maps to a local disk.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (get_dir_path(dhandle, path)) {
|
if (get_dir_path(dhandle, path)) {
|
||||||
@@ -80,19 +80,41 @@ static void do_map(int drive, NWPATH *nwp)
|
|||||||
static int do_map(int drive, NWPATH *nwp, int delete)
|
static int do_map(int drive, NWPATH *nwp, int delete)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
if (drive > -1 && drive < 32) {
|
if (drive > -1 && drive < 32) {
|
||||||
uint8 connid;
|
uint8 connid = 0;
|
||||||
uint8 dhandle;
|
uint8 dhandle = 0;
|
||||||
uint8 flags;
|
uint8 flags = 0;
|
||||||
if (!delete ||
|
|
||||||
(!get_drive_info(drive, &connid, &dhandle, &flags) && flags && connid)){
|
if (delete) {
|
||||||
uint8 nmdrive[3];
|
if (!get_drive_info(drive, &connid, &dhandle, &flags)
|
||||||
nmdrive[0] = drive+'A';
|
&& flags && !(flags & 0x80) && connid) {
|
||||||
nmdrive[1] = ':';
|
result = dealloc_dir_handle(dhandle);
|
||||||
nmdrive[2] = '\0';
|
}
|
||||||
result = redir_device_drive(delete ? -1 : 0x4, nmdrive, nwp->path);
|
} else {
|
||||||
|
/*
|
||||||
|
* The old mars-dosutils MAP used DOS redirector INT 21h AX=5F03h.
|
||||||
|
* NetWare Client32 returns AX=0001 for that call, while Novell MAP
|
||||||
|
* works. Use the NetWare shell/NCP "Allocate Permanent Directory
|
||||||
|
* Handle" path instead; this is what the surrounding code already
|
||||||
|
* provides via alloc_permanent_dir_handle().
|
||||||
|
*/
|
||||||
|
if (!get_drive_info(drive, &connid, &dhandle, &flags)
|
||||||
|
&& flags && !(flags & 0x80) && connid) {
|
||||||
|
(void)dealloc_dir_handle(dhandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = alloc_permanent_dir_handle(0, nwp->path, drive + 'A', NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some requesters historically accepted lowercase drive letters in
|
||||||
|
* this call. Keep this only as compatibility fallback.
|
||||||
|
*/
|
||||||
|
if (result < 0)
|
||||||
|
result = alloc_permanent_dir_handle(0, nwp->path, drive + 'a', NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,18 +188,133 @@ static int parse_argv(uint8 *drvstr, NWPATH *nwpath,
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int parse_pathins_arg(uint8 *drvstr, NWPATH *nwp,
|
||||||
|
int argc, char *argv[], int mode);
|
||||||
|
static int set_search_native(uint8 *drvstr, NWPATH *nwp, int pathmode);
|
||||||
|
static int show_search(uint8 *drvstr);
|
||||||
|
|
||||||
|
static int map_same_arg(char *a, char *b)
|
||||||
|
{
|
||||||
|
while (*a || *b) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int map_is_drive_arg(char *s)
|
||||||
|
{
|
||||||
|
if (!s || !s[0] || s[1] != ':' || s[2]) return(0);
|
||||||
|
if (s[0] >= 'A' && s[0] <= 'Z') return(1);
|
||||||
|
if (s[0] >= 'a' && s[0] <= 'z') return(1);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int map_drive_index(char *s)
|
||||||
|
{
|
||||||
|
if (s[0] >= 'a' && s[0] <= 'z') return(s[0] - 'a');
|
||||||
|
return(s[0] - 'A');
|
||||||
|
}
|
||||||
|
|
||||||
|
static void map_drive_name(char *dst, char *src)
|
||||||
|
{
|
||||||
|
dst[0] = src[0];
|
||||||
|
if (dst[0] >= 'a' && dst[0] <= 'z') dst[0] -= 32;
|
||||||
|
dst[1] = ':';
|
||||||
|
dst[2] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int map_handle_path_command(int argc, char *argv[], int pathmode)
|
||||||
|
{
|
||||||
|
uint8 drvstr[22];
|
||||||
|
NWPATH nwpath;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = parse_pathins_arg(drvstr, &nwpath, argc, argv, pathmode);
|
||||||
|
if (!rc) {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (*(nwpath.path) || pathmode == 1)
|
||||||
|
result = set_search_native(drvstr, &nwpath, pathmode);
|
||||||
|
|
||||||
|
if (result < 0)
|
||||||
|
fprintf(stderr, "Cannot interpret line. errcode=-1\n");
|
||||||
|
else if (pathmode != 1)
|
||||||
|
show_search(drvstr);
|
||||||
|
else
|
||||||
|
fprintf(stdout, "The search mapping for drive S%d: was deleted\n",
|
||||||
|
(int)drvstr[1]);
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Cannot interpret line. errcode=-1\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int func_map(int argc, char *argv[], int mode)
|
int func_map(int argc, char *argv[], int mode)
|
||||||
{
|
{
|
||||||
uint8 drvstr[22];
|
uint8 drvstr[22];
|
||||||
NWPATH nwpath;
|
NWPATH nwpath;
|
||||||
|
|
||||||
if (!ipx_init()) argc = 1;
|
if (!ipx_init()) argc = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Novell MAP accepts subcommands through MAP itself:
|
||||||
|
* MAP DEL H:
|
||||||
|
* MAP INS S1:=SYS:PUBLIC
|
||||||
|
* MAP DEL S1:
|
||||||
|
* The original mars-dosutils exposed those mainly as MAPDEL/PATHINS/PATHDEL,
|
||||||
|
* so handle the Novell syntax here and then reuse the existing primitives.
|
||||||
|
*/
|
||||||
|
if (argc > 1) {
|
||||||
|
if (map_same_arg(argv[1], "/?") || map_same_arg(argv[1], "-?") ||
|
||||||
|
map_same_arg(argv[1], "?")) {
|
||||||
|
fprintf(stderr, "Directory \"/?\" is not locatable.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map_same_arg(argv[1], "INS") || map_same_arg(argv[1], "INSERT")) {
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "Cannot interpret line. errcode=-1\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
return(map_handle_path_command(argc - 1, argv + 1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map_same_arg(argv[1], "DEL") || map_same_arg(argv[1], "DELETE")) {
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "Cannot interpret line. errcode=-1\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map_is_drive_arg(argv[2])) {
|
||||||
|
char dname[3];
|
||||||
|
int drive = map_drive_index(argv[2]);
|
||||||
|
|
||||||
|
if (do_map(drive, &nwpath, 1) < 0) {
|
||||||
|
fprintf(stderr, "Cannot interpret line. errcode=-1\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
map_drive_name(dname, argv[2]);
|
||||||
|
fprintf(stdout, "The mapping for drive %s has been deleted.\n", dname);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(map_handle_path_command(argc - 1, argv + 1, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!parse_argv(drvstr, &nwpath, argc, argv, 0, mode)) {
|
if (!parse_argv(drvstr, &nwpath, argc, argv, 0, mode)) {
|
||||||
if (*(nwpath.path) || mode==1) {
|
if (*(nwpath.path) || mode==1) {
|
||||||
{
|
if (do_map(*drvstr - 'A', &nwpath, mode)< 0)
|
||||||
int rc = do_map(*drvstr - 'A', &nwpath, mode);
|
fprintf(stderr, "MAP Error\n");
|
||||||
if (rc < 0)
|
|
||||||
fprintf(stderr, "MAP Error rc=%d\n", rc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (mode != 1)
|
if (mode != 1)
|
||||||
show_map(drvstr);
|
show_map(drvstr);
|
||||||
@@ -278,18 +415,192 @@ static int set_search(uint8 *drvstr, NWPATH *nwp, int pathmode)
|
|||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int path_is_drive_path(uint8 *path)
|
||||||
|
{
|
||||||
|
if (!path || !path[0] || path[1] != ':') return(0);
|
||||||
|
if (path[0] >= 'A' && path[0] <= 'Z') return(1);
|
||||||
|
if (path[0] >= 'a' && path[0] <= 'z') return(1);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void upstr_local(uint8 *s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
if (*s >= 'a' && *s <= 'z') *s -= 0x20;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_pathins_arg(uint8 *drvstr, NWPATH *nwp, int argc, char *argv[], int mode)
|
||||||
|
{
|
||||||
|
char joined[512];
|
||||||
|
char *p;
|
||||||
|
char *q;
|
||||||
|
int slot = 0;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
*drvstr = '\0';
|
||||||
|
memset(nwp, 0, sizeof(NWPATH));
|
||||||
|
nwp->path = nwp->buff;
|
||||||
|
*(nwp->buff) = '\0';
|
||||||
|
|
||||||
|
if (argc < 2) return(1);
|
||||||
|
|
||||||
|
joined[0] = '\0';
|
||||||
|
for (k = 1; k < argc; k++) {
|
||||||
|
if (k > 1) strcat(joined, " ");
|
||||||
|
strncat(joined, argv[k], sizeof(joined) - strlen(joined) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = joined;
|
||||||
|
while (*p == ' ' || *p == '\t') p++;
|
||||||
|
|
||||||
|
if (*p != 'S' && *p != 's') return(-1);
|
||||||
|
p++;
|
||||||
|
|
||||||
|
while (*p >= '0' && *p <= '9') {
|
||||||
|
slot = slot * 10 + (*p - '0');
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot < 1 || slot > 16) return(-1);
|
||||||
|
if (*p != ':') return(-1);
|
||||||
|
p++;
|
||||||
|
|
||||||
|
drvstr[0] = 's';
|
||||||
|
drvstr[1] = (uint8)slot;
|
||||||
|
drvstr[2] = '\0';
|
||||||
|
|
||||||
|
while (*p == ' ' || *p == '\t') p++;
|
||||||
|
|
||||||
|
if (mode == 1) {
|
||||||
|
/* PATHDEL S1: */
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '=') p++;
|
||||||
|
while (*p == ' ' || *p == '\t') p++;
|
||||||
|
|
||||||
|
if (!*p) return(-1);
|
||||||
|
|
||||||
|
q = nwp->buff;
|
||||||
|
while (*p && (q - nwp->buff) < (int)sizeof(nwp->buff) - 1) {
|
||||||
|
*q++ = *p++;
|
||||||
|
}
|
||||||
|
*q = '\0';
|
||||||
|
|
||||||
|
upstr_local(nwp->buff);
|
||||||
|
nwp->path = nwp->buff;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_search_native(uint8 *drvstr, NWPATH *nwp, int pathmode)
|
||||||
|
{
|
||||||
|
int result=-1;
|
||||||
|
SEARCH_VECTOR drives;
|
||||||
|
SEARCH_VECTOR_ENTRY *p=drives;
|
||||||
|
int j=0;
|
||||||
|
int entry = (*drvstr=='s') ? *(drvstr+1) : 0;
|
||||||
|
|
||||||
|
get_search_drive_vektor(drives);
|
||||||
|
|
||||||
|
while (p->drivenummer != 0xff && j++ < 16) {
|
||||||
|
if (!entry && path_is_drive_path(nwp->path)
|
||||||
|
&& (p->drivenummer + 'A' == nwp->path[0])) entry=j;
|
||||||
|
|
||||||
|
if (path_is_drive_path(nwp->path)
|
||||||
|
&& p->drivenummer + 'A' == nwp->path[0]
|
||||||
|
&& !strcmp(nwp->path+2, p->dospath)) {
|
||||||
|
p->drivenummer=0xfe;
|
||||||
|
*(p->dospath) = '\0';
|
||||||
|
p->flags = 0;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry > 0) {
|
||||||
|
if (entry > 16) entry = 16;
|
||||||
|
|
||||||
|
if (pathmode == 2 && entry <= j && entry < 16) { /* insert modus */
|
||||||
|
int k=j+1-entry;
|
||||||
|
if (j < 16) {
|
||||||
|
p++;
|
||||||
|
k++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
while (k--) {
|
||||||
|
memcpy(p, p-1, sizeof(SEARCH_VECTOR_ENTRY));
|
||||||
|
--p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--entry < j)
|
||||||
|
p = drives+entry;
|
||||||
|
else
|
||||||
|
(p+1)->drivenummer = 0xff;
|
||||||
|
|
||||||
|
memset(p, 0, sizeof(SEARCH_VECTOR_ENTRY));
|
||||||
|
|
||||||
|
if (pathmode==1) {
|
||||||
|
p->drivenummer = 0xfe;
|
||||||
|
*(p->dospath) = '\0';
|
||||||
|
result = set_search_drive_vektor(drives);
|
||||||
|
} else if (path_is_drive_path(nwp->path)) {
|
||||||
|
p->flags = 0;
|
||||||
|
p->drivenummer = (uint8)(nwp->path[0] - 'A');
|
||||||
|
if (nwp->path[0] >= 'a' && nwp->path[0] <= 'z')
|
||||||
|
p->drivenummer = (uint8)(nwp->path[0] - 'a');
|
||||||
|
strmaxcpy(p->dospath, nwp->path+2, sizeof(p->dospath)-1);
|
||||||
|
result = set_search_drive_vektor(drives);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Search path entries are not drive mappings. The original code stores
|
||||||
|
* the NetWare path text directly in dospath with drivenummer=0xfe.
|
||||||
|
* Client32 keeps/prints these entries correctly; allocating a permanent
|
||||||
|
* directory handle here made set_search_drive_vektor() return success,
|
||||||
|
* but the entry did not actually replace SEARCH1.
|
||||||
|
*/
|
||||||
|
p->flags = 0;
|
||||||
|
p->drivenummer = 0xfe;
|
||||||
|
strmaxcpy(p->dospath, nwp->path, sizeof(p->dospath)-1);
|
||||||
|
result = set_search_drive_vektor(drives);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int func_path(int argc, char *argv[], int mode)
|
int func_path(int argc, char *argv[], int mode)
|
||||||
{
|
{
|
||||||
uint8 drvstr[22];
|
uint8 drvstr[22];
|
||||||
NWPATH nwpath;
|
NWPATH nwpath;
|
||||||
if (!parse_argv(drvstr, &nwpath, argc, argv, 1, mode)) {
|
int rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PATH/PATHINS/PATHDEL need their own parser. The old parse_argv()
|
||||||
|
* rejects common login-script syntax such as:
|
||||||
|
* PATHINS S1:=SYS:PUBLIC
|
||||||
|
* MAP INS S1:=SYS:PUBLIC
|
||||||
|
*/
|
||||||
|
if (argc < 2) {
|
||||||
|
show_search("");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = parse_pathins_arg(drvstr, &nwpath, argc, argv, mode);
|
||||||
|
if (!rc) {
|
||||||
int result=0;
|
int result=0;
|
||||||
if (*(nwpath.path) || mode==1)
|
if (*(nwpath.path) || mode==1)
|
||||||
result=set_search(drvstr, &nwpath, mode);
|
result=set_search_native(drvstr, &nwpath, mode);
|
||||||
if (mode != 1)
|
if (mode != 1)
|
||||||
show_search(drvstr);
|
show_search(drvstr);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Cannot interpret line. errcode=-1\n");
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
103
ncpcall.c
103
ncpcall.c
@@ -283,3 +283,106 @@ int ncp_17_4b(uint8 *cryptkey, uint8 *objname, uint16 objtyp,
|
|||||||
if (neterrno) return(-1);
|
if (neterrno) return(-1);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ncp_17_37(uint32 last_id, uint16 objtyp, uint8 *pattern,
|
||||||
|
BINDERY_OBJECT *target)
|
||||||
|
/* scan bindery object */
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 func;
|
||||||
|
uint8 last_id[4];
|
||||||
|
uint8 typ[2];
|
||||||
|
uint8 patlen;
|
||||||
|
uint8 pattern[48];
|
||||||
|
} req;
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 object_id[4];
|
||||||
|
uint8 object_type[2];
|
||||||
|
uint8 object_name[48];
|
||||||
|
uint8 object_flags;
|
||||||
|
uint8 object_security;
|
||||||
|
uint8 object_has_prop;
|
||||||
|
} repl;
|
||||||
|
int patlen = (pattern) ? min(48, strlen(pattern)) : 1;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
memset(&repl, 0, sizeof(repl));
|
||||||
|
|
||||||
|
req.func = 0x37;
|
||||||
|
U32_TO_BE32(last_id, req.last_id);
|
||||||
|
U16_TO_BE16(objtyp, req.typ);
|
||||||
|
req.patlen = (uint8)patlen;
|
||||||
|
if (pattern) memcpy(req.pattern, pattern, patlen);
|
||||||
|
else req.pattern[0] = '*';
|
||||||
|
req.len = 8 + patlen;
|
||||||
|
|
||||||
|
repl.len = sizeof(repl) - sizeof(uint16);
|
||||||
|
|
||||||
|
neterrno = Net_Call(0xE300, &req, &repl);
|
||||||
|
if (neterrno) return(-1);
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
target->object_id = GET_BE32(repl.object_id);
|
||||||
|
target->object_type = GET_BE16(repl.object_type);
|
||||||
|
memcpy(target->object_name, repl.object_name, 48);
|
||||||
|
target->object_name[48] = '\0';
|
||||||
|
deb(target->object_name);
|
||||||
|
target->object_flags = repl.object_flags;
|
||||||
|
target->object_security = repl.object_security;
|
||||||
|
target->object_has_prop = repl.object_has_prop;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ncp_17_3d(uint16 objtyp, uint8 *objname, int segment,
|
||||||
|
uint8 *propname, NW_PROPERTY *target)
|
||||||
|
/* read bindery property value */
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 func;
|
||||||
|
uint8 typ[2];
|
||||||
|
uint8 buff[1+48+1+1+16];
|
||||||
|
} req;
|
||||||
|
struct {
|
||||||
|
uint16 len;
|
||||||
|
uint8 value[128];
|
||||||
|
uint8 more_flag;
|
||||||
|
uint8 property_flag;
|
||||||
|
} repl;
|
||||||
|
uint8 *p = req.buff;
|
||||||
|
int objlen = min(48, strlen(objname));
|
||||||
|
int proplen = min(16, strlen(propname));
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
memset(&repl, 0, sizeof(repl));
|
||||||
|
|
||||||
|
req.func = 0x3d;
|
||||||
|
U16_TO_BE16(objtyp, req.typ);
|
||||||
|
|
||||||
|
*p++ = (uint8)objlen;
|
||||||
|
memcpy(p, objname, objlen);
|
||||||
|
p += objlen;
|
||||||
|
|
||||||
|
*p++ = (uint8)segment;
|
||||||
|
|
||||||
|
*p++ = (uint8)proplen;
|
||||||
|
memcpy(p, propname, proplen);
|
||||||
|
|
||||||
|
req.len = 6 + objlen + proplen;
|
||||||
|
repl.len = sizeof(repl) - sizeof(uint16);
|
||||||
|
|
||||||
|
neterrno = Net_Call(0xE300, &req, &repl);
|
||||||
|
if (neterrno) return(-1);
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
memcpy(target->value, repl.value, 128);
|
||||||
|
target->more_flag = repl.more_flag;
|
||||||
|
target->property_flag = repl.property_flag;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
6
net.c
6
net.c
@@ -34,9 +34,11 @@ static struct s_net_functions {
|
|||||||
{"PATHDEL","removes search path" , func_path , 1},
|
{"PATHDEL","removes search path" , func_path , 1},
|
||||||
{"PATHINS","insert search path" , func_path , 2},
|
{"PATHINS","insert search path" , func_path , 2},
|
||||||
{"LOGOUT", "logout from server", func_logout , 0},
|
{"LOGOUT", "logout from server", func_logout , 0},
|
||||||
#if 0
|
{"FLAG", "display or modify file attributes", func_flag , 0},
|
||||||
|
{"FLAGDIR","display or modify directory attributes",func_flagdir, 0},
|
||||||
|
{"GRANT", "grant trustee rights", func_grant , 0},
|
||||||
|
{"RIGHTS", "display effective file/directory rights",func_rights, 0},
|
||||||
{"SLIST", "list servers", func_slist , 0},
|
{"SLIST", "list servers", func_slist , 0},
|
||||||
#endif
|
|
||||||
{"PASSWD", "change password", func_passwd , 0},
|
{"PASSWD", "change password", func_passwd , 0},
|
||||||
#if 1
|
#if 1
|
||||||
{"TESTS", "only testroutines!", func_tests , 0},
|
{"TESTS", "only testroutines!", func_tests , 0},
|
||||||
|
|||||||
30
net.h
30
net.h
@@ -58,7 +58,7 @@ typedef struct {
|
|||||||
uint16 fragment_count; /* Anzahl Fragment Buffers */
|
uint16 fragment_count; /* Anzahl Fragment Buffers */
|
||||||
uint8 *fragment_1;
|
uint8 *fragment_1;
|
||||||
uint16 fragment_1_size;
|
uint16 fragment_1_size;
|
||||||
/* K”nnen auch mehr sein */
|
/* K<EFBFBD>nnen auch mehr sein */
|
||||||
} ECB;
|
} ECB;
|
||||||
|
|
||||||
#include "kern.h"
|
#include "kern.h"
|
||||||
@@ -106,6 +106,24 @@ typedef struct {
|
|||||||
#define NWCLIENT 4
|
#define NWCLIENT 4
|
||||||
#define NWBIND 5
|
#define NWBIND 5
|
||||||
|
|
||||||
|
#define NCP_BINDERY_FSERVER 0x0004
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32 object_id;
|
||||||
|
uint16 object_type;
|
||||||
|
uint8 object_name[49];
|
||||||
|
uint8 object_flags;
|
||||||
|
uint8 object_security;
|
||||||
|
uint8 object_has_prop;
|
||||||
|
} BINDERY_OBJECT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8 value[128];
|
||||||
|
uint8 more_flag;
|
||||||
|
uint8 property_flag;
|
||||||
|
} NW_PROPERTY;
|
||||||
|
|
||||||
|
|
||||||
/* net.c */
|
/* net.c */
|
||||||
extern char *funcname;
|
extern char *funcname;
|
||||||
extern char prgpath[];
|
extern char prgpath[];
|
||||||
@@ -234,5 +252,15 @@ extern int func_tests (int argc, char *argv[], int mode);
|
|||||||
/* capture.c */
|
/* capture.c */
|
||||||
extern int func_capture(int argc, char *argv[], int mode);
|
extern int func_capture(int argc, char *argv[], int mode);
|
||||||
|
|
||||||
|
/* flag.c */
|
||||||
|
extern int func_flag (int argc, char *argv[], int mode);
|
||||||
|
extern int func_flagdir(int argc, char *argv[], int mode);
|
||||||
|
extern int func_grant(int argc, char *argv[], int mode);
|
||||||
|
extern int func_rights (int argc, char *argv[], int mode);
|
||||||
|
|
||||||
|
|
||||||
|
extern int ncp_17_37(uint32 last_id, uint16 objtyp, uint8 *pattern,
|
||||||
|
BINDERY_OBJECT *target);
|
||||||
|
extern int ncp_17_3d(uint16 objtyp, uint8 *objname, int segment,
|
||||||
|
uint8 *propname, NW_PROPERTY *target);
|
||||||
|
|
||||||
|
|||||||
25
netcall.c
25
netcall.c
@@ -54,38 +54,24 @@ int redir_device_drive(int devicetyp, uint8 *devname, uint8 *remotename)
|
|||||||
{
|
{
|
||||||
REGS regs;
|
REGS regs;
|
||||||
SREGS sregs;
|
SREGS sregs;
|
||||||
|
int result;
|
||||||
uint8 buff1[16];
|
uint8 buff1[16];
|
||||||
uint8 buff2[128];
|
uint8 buff2[128];
|
||||||
uint8 *ldevname = buff1;
|
uint8 *ldevname = buff1;
|
||||||
uint8 *lremotename = buff2;
|
uint8 *lremotename = buff2;
|
||||||
|
strncpy(ldevname, devname, 16);
|
||||||
memset(®s, 0, sizeof(regs));
|
|
||||||
memset(&sregs, 0, sizeof(sregs));
|
|
||||||
memset(buff1, 0, sizeof(buff1));
|
|
||||||
memset(buff2, 0, sizeof(buff2));
|
|
||||||
|
|
||||||
strmaxcpy(ldevname, devname, sizeof(buff1) - 1);
|
|
||||||
|
|
||||||
regs.x.ax = (devicetyp == -1) ? 0x5f04 : 0x5f03;
|
regs.x.ax = (devicetyp == -1) ? 0x5f04 : 0x5f03;
|
||||||
regs.h.bl = (uint8)devicetyp;
|
regs.h.bl = (uint8)devicetyp;
|
||||||
regs.x.cx = 0x574e; /* user sign 'NW' */
|
regs.x.cx = 0x574e; /* user sign 'NW' */
|
||||||
sregs.ds = FP_SEG(ldevname);
|
sregs.ds = FP_SEG(ldevname);
|
||||||
regs.x.si = FP_OFF(ldevname);
|
regs.x.si = FP_OFF(ldevname);
|
||||||
|
|
||||||
if (devicetyp > -1) {
|
if (devicetyp > -1) {
|
||||||
strmaxcpy(lremotename, remotename, sizeof(buff2) - 1);
|
strncpy(lremotename, remotename, 128);
|
||||||
sregs.es = FP_SEG(lremotename);
|
sregs.es = FP_SEG(lremotename);
|
||||||
regs.x.di = FP_OFF(lremotename);
|
regs.x.di = FP_OFF(lremotename);
|
||||||
}
|
}
|
||||||
|
result = intdosx(®s, ®s, &sregs);
|
||||||
intdosx(®s, ®s, &sregs);
|
return(regs.x.cflag ? -result : 0);
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the actual DOS/redirector error code from AX when carry is set.
|
|
||||||
* The old code returned the intdosx() function result. With OpenWatcom
|
|
||||||
* this can hide which redirector error happened.
|
|
||||||
*/
|
|
||||||
return(regs.x.cflag ? -(int)regs.x.ax : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int list_redir(int index, int *devicetyp, uint8 *devname, uint8 *remotename)
|
int list_redir(int index, int *devicetyp, uint8 *devname, uint8 *remotename)
|
||||||
@@ -255,7 +241,6 @@ int alloc_dir_handle(int func,
|
|||||||
printf("alloc_dir_handle, path=%s, len=%d, disk=%c\n", path, pathlen, driveletter);
|
printf("alloc_dir_handle, path=%s, len=%d, disk=%c\n", path, pathlen, driveletter);
|
||||||
*/
|
*/
|
||||||
neterrno = Net_Call(0xE200, &req, &repl);
|
neterrno = Net_Call(0xE200, &req, &repl);
|
||||||
fprintf(stderr, "neterrno=%d\n", neterrno);
|
|
||||||
if (neterrno && neterrno != 0xff) return(-1);
|
if (neterrno && neterrno != 0xff) return(-1);
|
||||||
|
|
||||||
if (effrights) *effrights = repl.effrights;
|
if (effrights) *effrights = repl.effrights;
|
||||||
|
|||||||
BIN
netold.exe
Executable file
BIN
netold.exe
Executable file
Binary file not shown.
113
nwcrypt.c
113
nwcrypt.c
@@ -118,6 +118,7 @@ static buf32 encryptkeys =
|
|||||||
0x6B,0x0F,0xD5,0x70,0xAE,0xFB,0xAD,0x11,
|
0x6B,0x0F,0xD5,0x70,0xAE,0xFB,0xAD,0x11,
|
||||||
0xF4,0x47,0xDC,0xA7,0xEC,0xCF,0x50,0xC0};
|
0xF4,0x47,0xDC,0xA7,0xEC,0xCF,0x50,0xC0};
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include "nwcrypt.h"
|
#include "nwcrypt.h"
|
||||||
static void
|
static void
|
||||||
shuffle1(buf32 temp, unsigned char *target)
|
shuffle1(buf32 temp, unsigned char *target)
|
||||||
@@ -210,4 +211,116 @@ nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til)
|
|||||||
til[s] = k[s] ^ k[15 - s];
|
til[s] = k[s] ^ k[15 - s];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char
|
||||||
|
newshuffle[256] =
|
||||||
|
{
|
||||||
|
0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09,
|
||||||
|
0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a,
|
||||||
|
0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08,
|
||||||
|
0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07,
|
||||||
|
|
||||||
|
0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00,
|
||||||
|
0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07,
|
||||||
|
0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
|
||||||
|
0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e,
|
||||||
|
|
||||||
|
0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00,
|
||||||
|
0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09,
|
||||||
|
0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c,
|
||||||
|
0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e,
|
||||||
|
|
||||||
|
0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07,
|
||||||
|
0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f,
|
||||||
|
0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e,
|
||||||
|
0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c,
|
||||||
|
|
||||||
|
0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a,
|
||||||
|
0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09,
|
||||||
|
0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f,
|
||||||
|
0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09,
|
||||||
|
|
||||||
|
0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00,
|
||||||
|
0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08,
|
||||||
|
0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04,
|
||||||
|
0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06,
|
||||||
|
|
||||||
|
0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b,
|
||||||
|
0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d,
|
||||||
|
0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c,
|
||||||
|
0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d,
|
||||||
|
|
||||||
|
0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01,
|
||||||
|
0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a,
|
||||||
|
0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00,
|
||||||
|
0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char final_shuffle[16] = {
|
||||||
|
0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05,
|
||||||
|
0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* verschluesseln des neuen Passworts fuer keyed change password
|
||||||
|
* Verwendung:
|
||||||
|
* - Shuffle (aus nwcrypt.c) altes passwort nach old (16 bytes)
|
||||||
|
* - shuffle neues passwort nach new (16 bytes)
|
||||||
|
* - nwpassencrypt (diese Funktion) zweimal aufrufen fuer je 8 bytes:
|
||||||
|
* nwpassencrypt(old+0, new+0, out+0)
|
||||||
|
* nwpassencrypt(old+8, new+8, out+8)
|
||||||
|
* - NCP-Buffer aufbauen:
|
||||||
|
* 2 byte Laenge im Hi-Lo-Format
|
||||||
|
* 1 byte Funktion (0x4b)
|
||||||
|
* 8 byte (nwcrypt Ergebnis analog login/verify password)
|
||||||
|
* 2 byte Objecttype
|
||||||
|
* 1 byte Objectname-Laenge
|
||||||
|
* n byte Objectname
|
||||||
|
* 1 byte (Laenge des eingegebenen neuen Passworts ^ old[0] ^ old[1])&0x7f|0x40
|
||||||
|
* 16 byte (Ergebnis dieser Funktion doppelt aufgerufen, s.o.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encrypt the new password for keyed change password
|
||||||
|
* For info on how to use this function, look at ncp_change_login_passwd
|
||||||
|
* in ncplib.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
newpassencrypt(unsigned char *old, unsigned char *npwd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
int di, ax;
|
||||||
|
unsigned char *p, *bx;
|
||||||
|
unsigned char cl, dl, ch;
|
||||||
|
unsigned char copy[8];
|
||||||
|
|
||||||
|
memcpy(copy, npwd, 8);
|
||||||
|
for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++)
|
||||||
|
{
|
||||||
|
cl = newshuffle[(((copy[di] ^ *p) >> 4) & 0x0f) + ax + 0x10] << 4;
|
||||||
|
dl = newshuffle[((copy[di] ^ *p) & 0xf) + ax];
|
||||||
|
copy[di] = cl | dl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = old[7];
|
||||||
|
for (bx = old + 7; bx > old; bx--)
|
||||||
|
{
|
||||||
|
*bx = ((bx[-1] >> 4) & 0x0f) | ((*bx) << 4);
|
||||||
|
}
|
||||||
|
*old = ((ch >> 4) & 0x0f) | (*old) << 4;
|
||||||
|
|
||||||
|
memset(npwd, 0, 8);
|
||||||
|
|
||||||
|
for (di = 0; di < 16; di++)
|
||||||
|
{
|
||||||
|
if (final_shuffle[di] & 1)
|
||||||
|
ch = ((copy[final_shuffle[di] / 2] >> 4) & 0x0f);
|
||||||
|
else
|
||||||
|
ch = copy[final_shuffle[di] / 2] & 0x0f;
|
||||||
|
npwd[di / 2] |= ((di & 1) ? ch << 4 : ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ extern void shuffle(unsigned char *lon,
|
|||||||
|
|
||||||
extern void nw_encrypt(unsigned char *fra,
|
extern void nw_encrypt(unsigned char *fra,
|
||||||
unsigned char *buf,unsigned char *til);
|
unsigned char *buf,unsigned char *til);
|
||||||
|
|
||||||
|
extern void newpassencrypt(unsigned char *old, unsigned char *npwd);
|
||||||
|
|||||||
128
nwtests.c
128
nwtests.c
@@ -1,44 +1,104 @@
|
|||||||
/* nwtests.c 20-May-96 */
|
/* nwtests.c - small DOS utility tests */
|
||||||
|
|
||||||
/****************************************************************
|
|
||||||
* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany *
|
|
||||||
****************************************************************/
|
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "c32ncp.h"
|
||||||
static int usage(void)
|
static int tests_same_arg(char *a, char *b)
|
||||||
{
|
{
|
||||||
return(-1);
|
while (*a || *b) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tests_usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Usage: TESTS [NCP87C32ATTR|NCP87C32AUTO]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tests_get_current_drive(void)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
|
||||||
|
regs.h.ah = 0x19;
|
||||||
|
int86(0x21, ®s, ®s);
|
||||||
|
return((int)regs.h.al);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tests_current_dhandle(uint8 *dhandle)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive;
|
||||||
|
|
||||||
|
drive = tests_get_current_drive();
|
||||||
|
if (get_drive_info((uint8)drive, &connid, dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tests_ncp87c32attr(void)
|
||||||
|
{
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint32 attr = 0;
|
||||||
|
uint16 actual = 0;
|
||||||
|
uint16 handle_lo = 0;
|
||||||
|
uint16 handle_hi = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (tests_current_dhandle(&dhandle)) {
|
||||||
|
fprintf(stdout, "NCP87C32ATTR failed: current drive is not a network drive\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = c32_ncp87_obtain_rim_attributes("LOGIN.EXE",
|
||||||
|
(uint16)dhandle,
|
||||||
|
&attr,
|
||||||
|
&actual,
|
||||||
|
&handle_lo,
|
||||||
|
&handle_hi);
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stdout, "NCP87C32ATTR failed rc=%d\n", rc);
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "NCP87C32ATTR LOGIN.EXE attr=%02lX handle=%04X:%04X actual=%04X\n",
|
||||||
|
attr & 0xffUL, handle_hi, handle_lo, actual);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tests_ncp87c32auto(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Kept as a compatibility alias for the former verbose test command.
|
||||||
|
* The production helper path is exercised by NCP87C32ATTR.
|
||||||
|
*/
|
||||||
|
return tests_ncp87c32attr();
|
||||||
}
|
}
|
||||||
|
|
||||||
int func_tests(int argc, char *argv[], int mode)
|
int func_tests(int argc, char *argv[], int mode)
|
||||||
{
|
{
|
||||||
int level = ncp_17_02(NWCONN, 6);
|
(void)mode;
|
||||||
int dirhandle = alloc_temp_dir_handle(0, "SYS:", 'd', NULL);
|
|
||||||
int result = -1;
|
|
||||||
uint8 *path = (argc < 2) ? "SYS:\\TMP" : argv[1];
|
|
||||||
if (dirhandle > -1) {
|
|
||||||
result = ncp_16_02(dirhandle, "SYSTEM/", NULL, NULL, NULL, NULL);
|
|
||||||
result = ncp_16_02(dirhandle, "SYSTEM", NULL, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
fprintf(stdout, "dirhandle=%d, result=%d\n", dirhandle, result);
|
|
||||||
result = redir_device_drive(0x4, "u:", path);
|
|
||||||
fprintf(stdout, "redir path=%s, result=%d\n", path, result);
|
|
||||||
|
|
||||||
path="Q1";
|
if (argc < 2) {
|
||||||
result = redir_device_drive(0x3, "LPT1", path);
|
tests_usage();
|
||||||
fprintf(stdout, "redir path=%s, result=%d\n", path, result);
|
return(1);
|
||||||
|
|
||||||
{
|
|
||||||
int k =-1;
|
|
||||||
uint8 devname[20];
|
|
||||||
uint8 remotename[130];
|
|
||||||
int devicetyp;
|
|
||||||
while ((result = list_redir(++k, &devicetyp, devname, remotename)) > -1){
|
|
||||||
fprintf(stdout, "index=%d, dev=%s(%d), %s result=%d\n",
|
|
||||||
k, devname, devicetyp, remotename, result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (level > -1) (void) ncp_17_02(NWCONN, level);
|
|
||||||
return(0);
|
if (tests_same_arg(argv[1], "NCP87C32ATTR"))
|
||||||
|
return tests_ncp87c32attr();
|
||||||
|
|
||||||
|
if (tests_same_arg(argv[1], "NCP87C32AUTO"))
|
||||||
|
return tests_ncp87c32auto();
|
||||||
|
|
||||||
|
tests_usage();
|
||||||
|
return(1);
|
||||||
}
|
}
|
||||||
|
|||||||
408
rights.c
Normal file
408
rights.c
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
/* rights.c - Novell RIGHTS-like DOS utility, read-only v4 */
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "c32ncp.h"
|
||||||
|
#include <dos.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#ifndef S_IFDIR
|
||||||
|
#define S_IFDIR 0040000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NW_RIGHT_S 0x01
|
||||||
|
#define NW_RIGHT_R 0x02
|
||||||
|
#define NW_RIGHT_W 0x04
|
||||||
|
#define NW_RIGHT_C 0x08
|
||||||
|
#define NW_RIGHT_E 0x10
|
||||||
|
#define NW_RIGHT_M 0x20
|
||||||
|
#define NW_RIGHT_F 0x40
|
||||||
|
#define NW_RIGHT_A 0x80
|
||||||
|
|
||||||
|
/* NCP effective-rights bits returned by NCP87 subfunction 29. */
|
||||||
|
#define NCP_RIGHT_READ 0x0001
|
||||||
|
#define NCP_RIGHT_WRITE 0x0002
|
||||||
|
#define NCP_RIGHT_OPEN 0x0004
|
||||||
|
#define NCP_RIGHT_CREATE 0x0008
|
||||||
|
#define NCP_RIGHT_DELETE 0x0010
|
||||||
|
#define NCP_RIGHT_OWNER 0x0020
|
||||||
|
#define NCP_RIGHT_SEARCH 0x0040
|
||||||
|
#define NCP_RIGHT_MODIFY 0x0080
|
||||||
|
#define NCP_RIGHT_SUPER 0x0100
|
||||||
|
|
||||||
|
static uint8 rights_map_ncp_mask(uint16 ncp_rights);
|
||||||
|
|
||||||
|
|
||||||
|
static int rights_same(char *a, char *b)
|
||||||
|
{
|
||||||
|
while (*a || *b) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rights_is_help(char *s)
|
||||||
|
{
|
||||||
|
if (!s) return(0);
|
||||||
|
return(rights_same(s, "/?") || rights_same(s, "-?") || rights_same(s, "?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rights_usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Usage: RIGHTS [path]\n\n");
|
||||||
|
fprintf(stdout, "Rights = All | Supervisor | Read | Write | Create | Erase\n");
|
||||||
|
fprintf(stdout, " Modify | File scan | Access Control\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rights_get_current_drive(void)
|
||||||
|
{
|
||||||
|
REGS regs;
|
||||||
|
|
||||||
|
regs.h.ah = 0x19;
|
||||||
|
int86(0x21, ®s, ®s);
|
||||||
|
return((int)regs.h.al);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rights_current_dhandle(uint8 *connid, uint8 *dhandle)
|
||||||
|
{
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive = rights_get_current_drive();
|
||||||
|
|
||||||
|
if (get_drive_info((uint8)drive, connid, dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!*connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rights_is_current_path(char *path)
|
||||||
|
{
|
||||||
|
if (!path || !*path) return(1);
|
||||||
|
if (rights_same(path, ".")) return(1);
|
||||||
|
if (rights_same(path, ".\\")) return(1);
|
||||||
|
if (rights_same(path, "./")) return(1);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rights_upcopy(char *dst, char *src, int max)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!src) src = "";
|
||||||
|
|
||||||
|
while (*src && i < max - 1) {
|
||||||
|
char c = *src++;
|
||||||
|
if (c == '/') c = '\\';
|
||||||
|
if (c >= 'a' && c <= 'z') c -= 32;
|
||||||
|
dst[i++] = c;
|
||||||
|
}
|
||||||
|
dst[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rights_parent_path(char *dst, char *src, int max)
|
||||||
|
{
|
||||||
|
char tmp[260];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
rights_upcopy(tmp, src, sizeof(tmp));
|
||||||
|
|
||||||
|
p = strrchr(tmp, '\\');
|
||||||
|
if (!p) p = strrchr(tmp, ':');
|
||||||
|
|
||||||
|
if (!p) {
|
||||||
|
dst[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == ':') {
|
||||||
|
p++;
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
strmaxcpy(dst, tmp, max - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rights_path_is_dir(char *path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (rights_is_current_path(path))
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
if (stat(path, &st) == 0) {
|
||||||
|
if (st.st_mode & S_IFDIR)
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rights_current_prefix(char *out, int max)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint8 flags = 0;
|
||||||
|
int drive;
|
||||||
|
char server[52];
|
||||||
|
char dpath[260];
|
||||||
|
char volume[32];
|
||||||
|
char *p;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!out || max < 8)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
out[0] = '\0';
|
||||||
|
|
||||||
|
drive = rights_get_current_drive();
|
||||||
|
if (get_drive_info((uint8)drive, &connid, &dhandle, &flags))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (!connid || (flags & 0x80))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
server[0] = '\0';
|
||||||
|
if (get_fs_name(connid, server))
|
||||||
|
server[0] = '\0';
|
||||||
|
|
||||||
|
dpath[0] = '\0';
|
||||||
|
if (get_dir_path(dhandle, dpath) || !dpath[0])
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
p = strchr(dpath, ':');
|
||||||
|
if (!p)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
while (dpath + i < p && i < (int)sizeof(volume) - 1) {
|
||||||
|
volume[i] = dpath[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
volume[i] = '\0';
|
||||||
|
|
||||||
|
if (!volume[0])
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (server[0])
|
||||||
|
sprintf(out, "%s/%s:", server, volume);
|
||||||
|
else
|
||||||
|
sprintf(out, "%s:", volume);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void rights_make_header_path(char *out, char *path)
|
||||||
|
{
|
||||||
|
char up[260];
|
||||||
|
char prefix[90];
|
||||||
|
|
||||||
|
if (rights_current_prefix(prefix, sizeof(prefix)))
|
||||||
|
prefix[0] = '\0';
|
||||||
|
|
||||||
|
if (rights_is_current_path(path)) {
|
||||||
|
strcpy(out, prefix);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rights_upcopy(up, path, sizeof(up));
|
||||||
|
strcpy(out, prefix);
|
||||||
|
strcat(out, up);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rights_effective_mask(char *path, int is_dir, uint8 *mask)
|
||||||
|
{
|
||||||
|
uint8 connid = 0;
|
||||||
|
uint8 dhandle = 0;
|
||||||
|
uint8 eff = 0;
|
||||||
|
char usepath[260];
|
||||||
|
int newhandle;
|
||||||
|
uint16 ncp_rights = 0;
|
||||||
|
|
||||||
|
if (mask) *mask = 0;
|
||||||
|
|
||||||
|
if (rights_current_dhandle(&connid, &dhandle))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prefer the explicit Client32 NCP87 effective-rights request. This is
|
||||||
|
* the DOS Client32 equivalent of ncpfs ncp_get_eff_directory_rights().
|
||||||
|
* It works for both files and directories, so pass the requested path
|
||||||
|
* itself instead of mapping files to their parent directory.
|
||||||
|
*/
|
||||||
|
if (!c32_ncp87_get_effective_rights(rights_is_current_path(path) ? "" : path,
|
||||||
|
(uint16)dhandle,
|
||||||
|
&ncp_rights,
|
||||||
|
NULL, NULL, NULL)) {
|
||||||
|
if (mask) *mask = rights_map_ncp_mask(ncp_rights);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fallback for older requesters/paths: allocate a temporary directory
|
||||||
|
* handle and use the returned old-style effective-rights byte.
|
||||||
|
* This cannot directly target a file, so files are mapped to their parent.
|
||||||
|
*/
|
||||||
|
if (rights_is_current_path(path)) {
|
||||||
|
usepath[0] = '\0';
|
||||||
|
} else if (is_dir) {
|
||||||
|
rights_upcopy(usepath, path, sizeof(usepath));
|
||||||
|
} else {
|
||||||
|
rights_parent_path(usepath, path, sizeof(usepath));
|
||||||
|
}
|
||||||
|
|
||||||
|
newhandle = alloc_temp_dir_handle(dhandle, usepath, 0, &eff);
|
||||||
|
if (newhandle < 0) {
|
||||||
|
if (usepath[0]) {
|
||||||
|
int subdir = 1;
|
||||||
|
int r = ncp_16_02(dhandle, (uint8 *)usepath, &subdir,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
if (r >= 0) {
|
||||||
|
eff = (uint8)r;
|
||||||
|
} else {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eff = 0xff;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dealloc_dir_handle(newhandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask) *mask = eff;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8 rights_map_ncp_mask(uint16 ncp_rights)
|
||||||
|
{
|
||||||
|
uint8 mask = 0;
|
||||||
|
|
||||||
|
if (ncp_rights & NCP_RIGHT_SUPER) mask |= NW_RIGHT_S;
|
||||||
|
if (ncp_rights & NCP_RIGHT_READ) mask |= NW_RIGHT_R;
|
||||||
|
if (ncp_rights & NCP_RIGHT_WRITE) mask |= NW_RIGHT_W;
|
||||||
|
if (ncp_rights & NCP_RIGHT_CREATE) mask |= NW_RIGHT_C;
|
||||||
|
if (ncp_rights & NCP_RIGHT_DELETE) mask |= NW_RIGHT_E;
|
||||||
|
if (ncp_rights & NCP_RIGHT_MODIFY) mask |= NW_RIGHT_M;
|
||||||
|
if (ncp_rights & NCP_RIGHT_SEARCH) mask |= NW_RIGHT_F;
|
||||||
|
if (ncp_rights & NCP_RIGHT_OWNER) mask |= NW_RIGHT_A;
|
||||||
|
|
||||||
|
return(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void rights_mask_string(uint8 mask, char *out)
|
||||||
|
{
|
||||||
|
out[0] = (mask & NW_RIGHT_S) ? 'S' : '-';
|
||||||
|
out[1] = (mask & NW_RIGHT_R) ? 'R' : '-';
|
||||||
|
out[2] = (mask & NW_RIGHT_W) ? 'W' : '-';
|
||||||
|
out[3] = (mask & NW_RIGHT_C) ? 'C' : '-';
|
||||||
|
out[4] = (mask & NW_RIGHT_E) ? 'E' : '-';
|
||||||
|
out[5] = (mask & NW_RIGHT_M) ? 'M' : '-';
|
||||||
|
out[6] = (mask & NW_RIGHT_F) ? 'F' : '-';
|
||||||
|
out[7] = (mask & NW_RIGHT_A) ? 'A' : '-';
|
||||||
|
out[8] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Novell RIGHTS layout:
|
||||||
|
* - lines with star: two leading blanks, star, blank, text
|
||||||
|
* - lines without star: four leading blanks, text
|
||||||
|
* Keep the right-column letter at a fixed-ish DOS-screen position.
|
||||||
|
*/
|
||||||
|
static void rights_print_line(int have, int star, char *text, char letter)
|
||||||
|
{
|
||||||
|
(void)have;
|
||||||
|
|
||||||
|
if (star)
|
||||||
|
fprintf(stdout, " * %-43s(%c)\n", text, letter);
|
||||||
|
else
|
||||||
|
fprintf(stdout, " %-43s(%c)\n", text, letter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rights_display(char *path, int is_dir, uint8 mask)
|
||||||
|
{
|
||||||
|
char hdr[300];
|
||||||
|
char mstr[10];
|
||||||
|
|
||||||
|
rights_make_header_path(hdr, path);
|
||||||
|
rights_mask_string(mask, mstr);
|
||||||
|
|
||||||
|
fprintf(stdout, "%s\n", hdr);
|
||||||
|
|
||||||
|
if (is_dir)
|
||||||
|
fprintf(stdout, "Your Effective Rights for this directory are [%s]\n", mstr);
|
||||||
|
else
|
||||||
|
fprintf(stdout, "Your Effective Rights for this file are [%s]\n", mstr);
|
||||||
|
|
||||||
|
if (is_dir) {
|
||||||
|
rights_print_line(mask & NW_RIGHT_S, 0, "You have Supervisor Rights to Directory.", 'S');
|
||||||
|
rights_print_line(mask & NW_RIGHT_R, 1, "May Read from File.", 'R');
|
||||||
|
rights_print_line(mask & NW_RIGHT_W, 1, "May Write to File.", 'W');
|
||||||
|
rights_print_line(mask & NW_RIGHT_C, 0, "May Create Subdirectories and Files.", 'C');
|
||||||
|
rights_print_line(mask & NW_RIGHT_E, 0, "May Erase Directory.", 'E');
|
||||||
|
rights_print_line(mask & NW_RIGHT_M, 0, "May Modify Directory.", 'M');
|
||||||
|
rights_print_line(mask & NW_RIGHT_F, 0, "May Scan for Files.", 'F');
|
||||||
|
rights_print_line(mask & NW_RIGHT_A, 0, "May Change Access Control.", 'A');
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, " * Has no effect on directory.\n\n");
|
||||||
|
fprintf(stdout, " Entries in Directory May Inherit [%s] rights.\n", mstr);
|
||||||
|
if (mask == 0xff)
|
||||||
|
fprintf(stdout, " You have ALL RIGHTS to Directory Entry.\n");
|
||||||
|
} else {
|
||||||
|
rights_print_line(mask & NW_RIGHT_S, 0, "You have Supervisor Rights to File.", 'S');
|
||||||
|
rights_print_line(mask & NW_RIGHT_R, 0, "May Read from File.", 'R');
|
||||||
|
rights_print_line(mask & NW_RIGHT_W, 0, "May Write to File.", 'W');
|
||||||
|
rights_print_line(mask & NW_RIGHT_C, 1, "May Create Subdirectories and Files.", 'C');
|
||||||
|
rights_print_line(mask & NW_RIGHT_E, 0, "May Erase File.", 'E');
|
||||||
|
rights_print_line(mask & NW_RIGHT_M, 0, "May Modify File.", 'M');
|
||||||
|
rights_print_line(mask & NW_RIGHT_F, 0, "May Scan for File.", 'F');
|
||||||
|
rights_print_line(mask & NW_RIGHT_A, 0, "May Change Access Control.", 'A');
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, " * Create is necessary to salvage a file that has been deleted.\n\n");
|
||||||
|
if (mask == 0xff)
|
||||||
|
fprintf(stdout, " You have ALL RIGHTS to Directory Entry.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int func_rights(int argc, char *argv[], int mode)
|
||||||
|
{
|
||||||
|
char *path = ".";
|
||||||
|
uint8 mask = 0;
|
||||||
|
int is_dir;
|
||||||
|
|
||||||
|
(void)mode;
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
rights_usage();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
if (rights_is_help(argv[1])) {
|
||||||
|
rights_usage();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
path = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
is_dir = rights_path_is_dir(path);
|
||||||
|
|
||||||
|
if (rights_effective_mask(path, is_dir, &mask)) {
|
||||||
|
fprintf(stdout, "Specified path not locatable.\n");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rights_display(path, is_dir, mask);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
106
slist.c
106
slist.c
@@ -1,15 +1,111 @@
|
|||||||
/* map.c 12-Jan-96 */
|
/* slist.c - list known NetWare file servers, DOS mars-dosutils version */
|
||||||
|
|
||||||
/****************************************************************
|
|
||||||
* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany *
|
|
||||||
****************************************************************/
|
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
|
#define NCP_BINDERY_FSERVER 0x0004
|
||||||
|
|
||||||
|
static int usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Usage: SLIST [Server] [/Continue]\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int same_arg(char *a, char *b)
|
||||||
|
{
|
||||||
|
while (*a || *b) {
|
||||||
|
int ca = *a++;
|
||||||
|
int cb = *b++;
|
||||||
|
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||||
|
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||||
|
if (ca != cb) return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_help_arg(char *s)
|
||||||
|
{
|
||||||
|
if (!s) return(0);
|
||||||
|
return(same_arg(s, "/?") || same_arg(s, "-?") || same_arg(s, "?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long node_to_number(uint8 *addr)
|
||||||
|
{
|
||||||
|
unsigned long n = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 4; i < 10; i++)
|
||||||
|
n = (n << 8) + addr[i];
|
||||||
|
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_net_node_status(uint8 *addr, int is_default)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "[%08lX][%12lu]%s",
|
||||||
|
(unsigned long)GET_BE32(addr),
|
||||||
|
node_to_number(addr),
|
||||||
|
is_default ? "Default" : "");
|
||||||
|
}
|
||||||
|
|
||||||
int func_slist(int argc, char *argv[], int mode)
|
int func_slist(int argc, char *argv[], int mode)
|
||||||
{
|
{
|
||||||
|
BINDERY_OBJECT obj;
|
||||||
|
uint32 last_id = MAX_U32;
|
||||||
|
uint8 pattern[50];
|
||||||
|
int found = 0;
|
||||||
|
int result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
(void)mode;
|
||||||
|
|
||||||
|
strcpy(pattern, "*");
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (is_help_arg(argv[i])) return(usage());
|
||||||
|
|
||||||
|
if (argv[i][0] == '/' || argv[i][0] == '-') {
|
||||||
|
if (same_arg(argv[i], "/C") || same_arg(argv[i], "/CONTINUE") ||
|
||||||
|
same_arg(argv[i], "-C") || same_arg(argv[i], "-CONTINUE")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return(usage());
|
||||||
|
}
|
||||||
|
|
||||||
|
strmaxcpy(pattern, argv[i], sizeof(pattern) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
upstr(pattern);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Novell-like layout from the DOS client:
|
||||||
|
* Known NetWare File Servers Network Node Address Status
|
||||||
|
* ------------------------- -------- -------------------
|
||||||
|
*/
|
||||||
|
fprintf(stdout, "%-44sNetwork Node Address Status\n",
|
||||||
|
"Known NetWare File Servers");
|
||||||
|
fprintf(stdout, "%-44s------- ----------- ------\n",
|
||||||
|
"--------------------------");
|
||||||
|
|
||||||
|
while ((result = ncp_17_37(last_id, NCP_BINDERY_FSERVER,
|
||||||
|
pattern, &obj)) == 0) {
|
||||||
|
NW_PROPERTY prop;
|
||||||
|
|
||||||
|
found++;
|
||||||
|
last_id = obj.object_id;
|
||||||
|
|
||||||
|
fprintf(stdout, "%-44s", obj.object_name);
|
||||||
|
|
||||||
|
if (!ncp_17_3d(NCP_BINDERY_FSERVER, obj.object_name,
|
||||||
|
1, "NET_ADDRESS", &prop)) {
|
||||||
|
print_net_node_status(prop.value, found == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
|
||||||
|
if (last_id == MAX_U32) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "\nTotal of %d file servers found\n", found);
|
||||||
|
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|||||||
4
teste.c
4
teste.c
@@ -22,11 +22,11 @@ int main()
|
|||||||
close(fd);
|
close(fd);
|
||||||
_chmod(fn, 1, _chmod(fn, 0) | 0x80 );
|
_chmod(fn, 1, _chmod(fn, 0) | 0x80 );
|
||||||
stat(fn, &stbuff);
|
stat(fn, &stbuff);
|
||||||
printf("Filesize <20>ber stat =%ld\n", stbuff.st_size);
|
printf("Filesize <20>ber stat =%ld\n", stbuff.st_size);
|
||||||
fd = open(fn, O_RDWR | O_BINARY |O_DENYNONE);
|
fd = open(fn, O_RDWR | O_BINARY |O_DENYNONE);
|
||||||
|
|
||||||
offset = lseek(fd, 0L, SEEK_END);
|
offset = lseek(fd, 0L, SEEK_END);
|
||||||
printf("Filesize <20>ber lseek =%ld\n", offset);
|
printf("Filesize <20>ber lseek =%ld\n", offset);
|
||||||
write(fd, buff, strlen(buff));
|
write(fd, buff, strlen(buff));
|
||||||
|
|
||||||
lseek(fd, 0L, SEEK_SET);
|
lseek(fd, 0L, SEEK_SET);
|
||||||
|
|||||||
2
tools.c
2
tools.c
@@ -328,7 +328,7 @@ int putglobenv(char *option)
|
|||||||
}
|
}
|
||||||
search=nextp;
|
search=nextp;
|
||||||
}
|
}
|
||||||
/* nicht gefunden , nun eintragen, falls m”glich */
|
/* nicht gefunden , nun eintragen, falls m<EFBFBD>glich */
|
||||||
if (*(equal+1) && optionlen < maxenvsize - aktenvsize) {
|
if (*(equal+1) && optionlen < maxenvsize - aktenvsize) {
|
||||||
strcpy(search, option);
|
strcpy(search, option);
|
||||||
*(search+optionlen+1) = '\0'; /* letzter Eintrag '\0' nicht vergessen */
|
*(search+optionlen+1) = '\0'; /* letzter Eintrag '\0' nicht vergessen */
|
||||||
|
|||||||
Reference in New Issue
Block a user