/* use long instead of int so vfork works OK with -mshort */ long tfork(int (*func)(long), long arg) { register BASEPAGE *b; register long pid; register long savpending, savmask; register BASEPAGE *savbase; sighandler_t savhandler[NSIG]; long now; int i; b = (BASEPAGE *)Pexec(PE_CBASEPAGE, 0L, "", 0L); (void)Mshrink(b, SIZE+256); b->p_tbase = (char *)startup; b->p_dbase = (char *)func; b->p_dlen = arg; b->p_hitpa = ((char *)b) + SIZE + 256; pid = Pexec(104, 0L, b, 0L); if (pid == -ENOSYS) { /* save the signal masks and signal handlers, * the child may change them */ savpending = _sigpending; _sigpending = 0; savmask = _sigmask; _sigmask = 0; for (i = 0; i < NSIG; i++) savhandler[i] = _sig_handler[i]; savbase = _base; _base = b; now = _clock(); pid = Pexec(4, 0L, b, 0L); _base = savbase; /* restore signal stuff */ for (i = 0; i < NSIG; i++) _sig_handler[i] = savhandler[i]; _sigmask = savmask; _sigpending = savpending; if (pid >= 0) { long retval = pid; /* see the TOS algorithm for getpid() */ pid = ((long)b) >> 8; __waitval = (pid << 16) | retval; raise(SIGCHLD); __waittime = _clock() - now; _childtime += __waittime; }
main() { Cconws ("Ceci est le programme appelant.\15\12\12"); if (Pexec (CHARGE_ET_LANCE, NOMFICH, PARAMETRE, ENVIRONNEMENT) < 0) Cconws("Une erreur s'est produite!!!\15\12\12"); Cconws ("Revoici le programme appelant!\15\12"); Crawcin(); /* Fin en tapant une touche */ }
int execute(char program[MAXSTRING],char command[MAXSTRING],int multi) { char comstring[MAXSTRING+1]; if(!multi) { // hide_dialog(NULL); strncpy(comstring," ",MAXSTRING); comstring[MAXSTRING]=EOL; strncat(comstring,command,MAXSTRING); comstring[MAXSTRING]=EOL; Pexec(0,program,comstring,NULL); menu_bar(menu_tree, 1); redraw_window(NULL); // unhide_dialog(NULL); } Return TRUE; }
/*********************************** * create new list of gem fonts to reconfigure ttf-gdos for the new gem fonts, * then call fontwid.app */ static void call_fontwid( void ) { FILE_NAME *const pf0 = calloc( gem_font_count, sizeof(FILE_NAME) ); register FILE_NAME * pf = pf0; char *const gempath = ((char**)pInfo)[-1]; /* use ttf-gdos hook */ register int16 i; int16 r; int16 save_nr_gemfonts = pInfo->nr_gemfonts; FILE_NAME *save_gem_font_ptr; /****************** * fontwid saves only 20 chars of file path (including null at end) * we need 3 chars for the file name */ #define MAX_PATH_LEN 17 #define STR(s) #s #define STRVAL(s) STR(s) if( pInfo->len_gem_path < MAX_PATH_LEN ) { /** this fills ttf-gdos info structure with the gem fonts **/ pInfo->nr_gemfonts = gem_font_count; save_gem_font_ptr = ((FILE_NAME**)pInfo)[-2]; ((FILE_NAME**)pInfo)[-2] = pf0; for( i=0; i<gem_font_count; i++, pf++ ) { FONT_FILE_NAME( &pf[0][0], i ); } /* for */ r = Pexec( 0, "fontwid.app", NULL, NULL ); if( r != 0 ) { sprintf( err_string, "[3][error while running fontwid.app|%s][OK]", strerror(-r) ); form_alert(1, err_string ); } /* if */ pInfo->nr_gemfonts = save_nr_gemfonts;; ((void**)pInfo)[-2] = save_gem_font_ptr; } else { sprintf( err_string, "[3][gem path '%.*s'|must be less than " STRVAL(MAX_PATH_LEN) " chars][OK]", pInfo->len_gem_path, gempath ); form_alert(1, err_string ); } /* if */ free( pf0 ); } /* call_fontwid() */
main() { unlink("cat2lod1.tos"); Pexec(0,"arc602.ttp"," XZ CAT", ""); unlink("cat.arc"); Pexec(0,"arc602.ttp"," XZ CATTXT", ""); unlink("cattxt.arc"); Pexec(0,"arc602.ttp"," XZ CATTUTR5", ""); unlink("cattutr5.arc"); Pexec(0,"arc602.ttp"," XZ CATEXPRT", ""); unlink("catexprt.arc"); Pexec(0,"arc602.ttp"," XZ CATTUTR1", ""); unlink("cattutr1.arc"); Pexec(0,"arc602.ttp"," XZ CATTUTR2", ""); unlink("cattutr2.arc"); Pexec(0,"arc602.ttp"," XZ CATTUTR3", ""); unlink("cattutr3.arc"); Pexec(0,"arc602.ttp"," XZ CATTUTR4", ""); unlink("cattutr4.arc"); unlink("cat2lod2.tos"); unlink("catread.me"); }
// ------------------------------------------------------------------ // LONG Pexec( mode, fname, cmdline, envstr ) int32_t custom_pexec( void *sp ) { BYTE *params = (BYTE *) sp; // retrieve params from stack mode = *((WORD *) params); params += 2; fname = (char *) *((DWORD *) params); params += 4; cmdline = (char *) *((DWORD *) params); params += 4; envstr = (char *) *((DWORD *) params); // for any other than these modes don't do anything special, just call the original if(mode != PE_LOADGO && mode != PE_LOAD) { // not one of 2 supported modes? Call original Pexec() pexec_callOrig = 1; // will call the original Pexec() handler from asm when this finishes return 0; } // if we got here, the mode is PE_LOADGO || PE_LOAD WORD drive = getDriveFromPath((char *) fname); if(!isOurDrive(drive, 0)) { // not our drive? Call original Pexec() pexec_callOrig = 1; // will call the original Pexec() handler from asm when this finishes return 0; } // Do PE_LOAD, and if this was PE_LOADGO, then the GO part will be done in gemdos_asm.s // if we got here, then it's a PRG on our drive... BYTE prgStart[32]; pPrgStart = &prgStart[4]; pPrgStart = (BYTE *) (((DWORD) pPrgStart) & 0xfffffffc); // make temp buffer pointer to be at multiple of 4 // create base page BYTE *pBasePage = (BYTE *) Pexec(PE_BASEPAGE, 0, cmdline, envstr); if((int) pBasePage < 1000) { // Pexec seems to failed -- insufficient memory return ENSMEM; } TBasePage *sBasePage = (TBasePage *) pBasePage; // this is now the pointer to the basePage structure // load the file to memory int32_t file = Fopen(fname, 0); // try to open the file if(file < 0) { // if the handle is negative, fail -- file not found freeTheBasePage(sBasePage); // free the base page return EFILNF; } DWORD diskProgSize = Fseek(0, file, 2); // seek to end, returns file size (bytes before end) Fseek(0, file, 0); // seek to the start if(diskProgSize < 28) { // if the program is too small, this wouldn't work Fclose(file); // close the file freeTheBasePage(sBasePage); // free the base page return EPLFMT; // be Invalid program load format } Fread(file, 28, pPrgStart); // read first 28 bytes to this buffer TPrgHead *prgHead = (TPrgHead *) pPrgStart; // get file size, see if it will fit in the free memory DWORD memProgSize = prgHead->tsize + prgHead->dsize + prgHead->bsize + prgHead->ssize; // calculate the program size in RAM as size of text + data + bss + symbols DWORD memoryAvailable = sBasePage->hitpa - sBasePage->lowtpa; // calculate how much memory we have for the program if(memoryAvailable < memProgSize || memoryAvailable < diskProgSize) { // if the program (in RAM or on disk) is bigger than the available free memory Fclose(file); // close the file freeTheBasePage(sBasePage); // free the base page return ENSMEM; // error: insufficient memory } Fread(file, diskProgSize - 28, pBasePage + 0x100); // now read the rest of the file Fclose(file); // fill the base page sBasePage->tbase = sBasePage->lowtpa + 0x100; sBasePage->tlen = prgHead->tsize; sBasePage->dbase = sBasePage->tbase + sBasePage->tlen; sBasePage->dlen = prgHead->dsize; sBasePage->bbase = sBasePage->dbase + sBasePage->dlen; sBasePage->blen = prgHead->bsize; // do the addresses fixup if needed BYTE *fixups = (BYTE *) (sBasePage->tbase + prgHead->tsize + prgHead->dsize + prgHead->ssize); DWORD fixupOffset = *((DWORD *) fixups); BYTE fixup = 0; if(fixupOffset != 0) { // if fixup needed? BYTE *pWhereToFix; pWhereToFix = (BYTE *) (sBasePage->tbase + fixupOffset); // calculate the first DWORD position that needs to be fixed fixups += 4; // move to the fixups array while(1) { DWORD oldVal = *((DWORD *)pWhereToFix); DWORD newVal = oldVal + sBasePage->tbase; if(fixup != 1) { // fix the value only if the fixup isn't ONE *((DWORD *)pWhereToFix) = newVal; } fixup = *fixups; fixups++; if(fixup == 0) { // terminate fixup break; } if(fixup == 1) { // just move forward by 0xfe pWhereToFix += 0xfe; } else { // move forward and fixup pWhereToFix += (DWORD) fixup; } } } memset((BYTE *) sBasePage->bbase, 0, sBasePage->blen); // clear BSS section if(mode == PE_LOADGO) { // if we're doing PE_LOADGO, then we're going to freeTheBasePage() pLastBasePage = pBasePage; pexec_postProc = 1; // mark that after this function ends, the asm handler should do PE_GO part... } // Return the pointer to basepage. // for PE_LOAD this will be used as return value. // for PE_LOADGO this will be used to call Pexec(PE_GO) in gemdos_asm.s after this custom function. return (DWORD) pBasePage; // the PE_LOAD was successful }
/* ** Description ** Let the user select an application and start it */ static void launch_application (void) { char execpath[128]; /*FIXME length of string */ char oldpath[128]; char * tmp; int button; /* Open file selector */ fsel_exinput(progpath, progfile, &button, "Select program to start"); /* Handle request if OK was selected */ if(button == FSEL_OK) { int err; char newpath[128]; strcpy(newpath,progpath); tmp = strrchr (newpath, PATH_SEPARATOR); if(tmp) { *tmp = 0; sprintf (execpath, "%s%c%s", newpath, PATH_SEPARATOR, progfile); } else { strcpy (execpath, progfile); } #ifdef MINT_TARGET /* FIXME: Use shel_write instead */ Dgetpath(oldpath, 0); misc_setpath(newpath); err = Pexec(100, execpath, 0L, 0L); misc_setpath(oldpath); #else getcwd (oldpath, 128); chdir (newpath); if (fork () == 0) { execlp (execpath, NULL); exit (0); } chdir (oldpath); err = 0; #endif if (err < 0) { form_error ((WORD) -err - 31); } } }