Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Truename (Int 21/AH=60h) #50

Closed
tsupplis opened this issue Apr 19, 2022 · 7 comments
Closed

Support for Truename (Int 21/AH=60h) #50

tsupplis opened this issue Apr 19, 2022 · 7 comments

Comments

@tsupplis
Copy link
Collaborator

Would you be open to add this function? I am happy to provide trial implementation and tests

AH = 60h
DS:SI -> ASCIZ filename or path
ES:DI -> 128-byte buffer for canonicalized name

Return:
CF set on error
AX = error code
02h invalid component in directory path or drive letter only
03h malformed path or invalid drive letter
ES:DI buffer unchanged
CF clear if successful
AH = 00h or 3Ah (DOS 6.1/6.2 for character device)
AL = destroyed (00h or 2Fh or 5Ch or last character of current
directory on drive)
@tsupplis tsupplis changed the title Truname Support (Int 21/AH=60h) Support for Truname (Int 21/AH=60h) Apr 19, 2022
@dmsc
Copy link
Owner

dmsc commented Apr 20, 2022

Hi!

If you have a program that uses it, so it can be tested, sure, I can implement it.

Have Fun!

@tsupplis
Copy link
Collaborator Author

tsupplis commented Apr 20, 2022

Test tool compiled with Borland C++ 2.0.

test.zip

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>

int main(int argc, char ** argv) {
    union REGS regs;
    struct SREGS segs;
    char buffer[128+1];
    int rc;

    if(argc<2) {
        fprintf(stderr,"ERR: wrong command line\n");
        exit(-1);
    }
    memset(&regs,0,sizeof(regs));
    memset(&segs,0,sizeof(segs));
    regs.h.ah=0x60;
    regs.x.si=FP_OFF(argv[1]);
    segs.ds=FP_SEG(argv[1]);
    regs.x.di=FP_OFF(buffer);
    segs.es=FP_SEG(buffer);
    fprintf(stderr,"INF: calling int\n");
    intdosx(&regs,&regs,&segs);
    fprintf(stderr,"INF: cf=%04X\n",regs.x.cflag);
    fprintf(stderr,"INF: ax=%04X\n",regs.x.ax);
    if(!regs.x.cflag) {
        fprintf(stderr,"INF: %s\n",buffer);
    } else {
        fprintf(stderr,"INF: failed\n");
    }
    return 0;
}
./emu2 test.com a:\\test\\foo
INF: calling int
INF: cf=0000
INF: ax=0000
INF: a:\test\foo
./emu2 test.com c:\\test\\foo
INF: calling int
INF: cf=0000
INF: ax=0000
INF: c:\test\foo
./emu2 test.com c:\\test\\foolllllllllllllllll\\aaaaaaa\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
INF: calling int
INF: cf=0001
INF: ax=6000
INF: failed
EMU2_CWD=src ./emu2 test.com c:test\\foo
INF: calling int
INF: cf=0000
INF: ax=0000
INF: c:\src\test\foo
EMU2_CWD=src ./emu2 test.com test\\foo
INF: calling int
INF: cf=0000
INF: ax=0000
INF: c:\src\test\foo
EMU2_CWD=src ./emu2 test.com foo
INF: calling int
INF: cf=0000
INF: ax=0000
INF: c:\src\foo
EMU2_CWD=src ./emu2 test.com c:\\test\\foo
INF: calling int
INF: cf=0000
INF: ax=0000
INF: c:\test\foo
EMU2_CWD=src ./emu2 test.com d:\\foo
INF: calling int
INF: cf=0000
INF: ax=0000
INF: d:\foo

There are differences with the DOS version:

  • The paths are not shorten to appropriate length (should we evolve the current dos_path_normalize function that I reused to clean up file/dir name length?)
  • The path input is limited to 64 characters (limitation of dos_path_normalize)
  • The values are not moved to uppercase (Neither does dosbox)
  • The value of output AH changes (value return is 0x5C as dos 3.3)

@dmsc
Copy link
Owner

dmsc commented Apr 21, 2022

Hi!

  • The value of output AH changes (value return is 0x5C as dos 3.3)

Tested in DOS 3.3, the return value for AL is sometimes 0x53, but not always:
image

Also, DOS 3.3 keeps the trailing backslash if given:
image

This is why I would like to have an actual program using this call, so we could verify what is the expected result from old DOS programs that used it.

In the meantime, I added two commits to the pull request, with minor fixes.

Have Fun!

@tsupplis
Copy link
Collaborator Author

tsupplis commented Apr 21, 2022

Super thank you, working on the samples.
My main focus is binary self identification in compiler runtime, c in particular (argv[0] translation) as the recipe below
https://stackoverflow.com/questions/53570837/full-path-to-self-in-dos-executable
Old compilers put either hardcoded name or psp extracted names.
I will look at the inventory of the compilers I use

  • gcc ia16
  • aztec c
  • turbo and borland c++
  • openwatcom
  • bcc
  • pacific c
  • digital mars c
  • quick c

@tsupplis tsupplis changed the title Support for Truname (Int 21/AH=60h) Support for Truename (Int 21/AH=60h) Apr 21, 2022
@dmsc
Copy link
Owner

dmsc commented Apr 21, 2022

Hi!

My main focus is binary self identification in compiler runtime, c in particular (argv[0] translation) as the recipe below https://stackoverflow.com/questions/53570837/full-path-to-self-in-dos-executable Old compilers put either hardcoded name or psp extracted names. I will look at the inventory of the compilers I use

The answer in that question is correct, you should extract the program name from the environment (just after all the environment variables). But this is actually fully documented in the DOS reference - from "dosref33", about function 4Bh, code 0:

The loaded program also receives an environment, a series of ASCIZ strings of the form parameter=value (for example, verify = on). The environment must begin on a paragraph boundary, be less than 32K bytes long, and end with a byte of 00H (that is, the final entry consists of an ASCIZ string followed by two bytes of 00H). Following the last byte of zeros is a set of initial arguments passed to a program containing a word count followed by an ASCIZ string. If the call finds the file in the current directory, the ASCIZ string contains the drive and pathname of the executable program as passed to Function 4BH. If the call finds the file in the path, it concatenates the filename with the path information. (A program may use this area to determine whence it was loaded.)

So, the program name should be get from the environment, and the path extracted from there. Using truename is not useful - and at least neither borland and microsoft runtimes do that.

I extracted the "dosref33" file from the Microsoft Bookshelf, I converted it to HTML using a custom program, attached is the full file.
dosref33.zip

@tsupplis
Copy link
Collaborator Author

Actually you are correct, and I found contradicting notes on it being internal. Should we drop it?

@dmsc
Copy link
Owner

dmsc commented Apr 22, 2022

Given that the work is mostly down, I will push an implementation - but I will return capitalized results and drop the setting of AX register.

@dmsc dmsc closed this as completed in cf632b9 Oct 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants