home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / CKPM5X_S.ZIP / CKOSTD.C < prev    next >
C/C++ Source or Header  |  1990-05-02  |  14KB  |  418 lines

  1. /******************************************************************************
  2. File name:  ckostd.c    Rev: 01  Date: 31-Jan-90 Programmer: C.P.Armstrong
  3.  
  4. File title: Replaces some of the standard C stdio commands so that output
  5.             can be directed into an AVIO PM windows.
  6.  
  7. Contents:   
  8.  
  9. Modification History:
  10.     01  31-Jan-90   C.P.Armstrong   created
  11.  
  12. ******************************************************************************/
  13. #define INCL_DOS
  14. #define INCL_DOSERRORS
  15. #define INCL_DOSSESMGR
  16. #define INCL_WIN
  17. #define INCL_AVIO
  18. #define INCL_VIO
  19. #include <os2.h>     
  20. #include <stdarg.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <process.h>    /* Process-control function declarations */
  24. #include <malloc.h>
  25. #include <io.h>
  26. #include "ckcker.h"
  27. #include "ckofns.h" 
  28. #include "ckopm.h"
  29.  
  30. /* These are also defined in CKOCON.C (instead of .h for some reason! */
  31. #define SENDCHAR    sendchar
  32. #define UPWARD      6
  33. #define DOWNWARD    7
  34. typedef int     bool;
  35. typedef unsigned char screenmap[4000];
  36. typedef struct ascreen_rec {    /* Structure for saving screen info */
  37.     unsigned char   ox;
  38.     unsigned char   oy;
  39.     unsigned char   att;
  40.     screenmap       scrncpy;
  41. }               ascreen;
  42.  
  43.  
  44. void do_aviotopm(struct avio_cellstr *);
  45. void newses(char*,char*,char*,int*);
  46.  
  47.  
  48. /* putchar is used alot in kermit.  Of course it fails under the PM.  So here */
  49. /* is a PM version.  Note that it will do a CRLF for an LF.                   */
  50. /* NB.  For MSC 5.1 putchar is a macro and should be undefined.               */
  51. /*      With MSC 6.0 there is a problem somewhere which causes the linker to  */
  52. /*      give a multiply defined symbol error for putchar() (not for printf()  */
  53. /*      or puts() though!                                                     */
  54.  
  55. int putchar(int c)
  56.     {
  57.     struct avio_cellstr ac;
  58.     
  59.     ac.fun = PRINTF;
  60.     ac.string = (PCH) &c;
  61.     ac.len    = 1;
  62.     do_aviotopm(&ac); 
  63.     return(1);
  64.     }
  65.  
  66. /* puts() is also used alot - and it fails...... */
  67. int puts(s)
  68.     const char far * s;
  69.     {           
  70.     struct avio_cellstr ac;
  71.     ac.fun = PRINTF;
  72.     ac.string = (char far *) s;
  73.     ac.len = strlen(s);
  74.     do_aviotopm(&ac); 
  75.     return(1);
  76.     }
  77.  
  78.  
  79. /* Replaces write(stdout...) function calls */
  80. int write_buf(char * s, int x)
  81.     {
  82.     struct avio_cellstr ac;
  83.     ac.fun = PRINTF;
  84.     ac.string = s;
  85.      ac.len = x;
  86.     do_aviotopm(&ac); 
  87.     return(x);
  88.     }
  89.  
  90. /******************************************************************************
  91. Function:       pm_system()
  92.  
  93. Description:    Spawns a new OS/2 command line interpreter, passing a command
  94.                 line if required.  The output from the command interpreter is
  95.                 displayed on an AVIO screen.
  96.  
  97. Syntax:         int do_os2_cmd(command)
  98.                     char * command;
  99.  
  100. Returns:        The number of characters entered into the buffer
  101.  
  102. Mods:           12-Sep-89 C.P.Armstrong created
  103.                 13-Sep-89 C.P.Armstrong modified to ensure that all the handles
  104.                                         opened are closed prior to exit from the
  105.                                         function.  Surprisingly this
  106.                                         has to include the duplicate handles.
  107.                 05-Dec-89 C.P.Armstrong A Modified do_os2_cmd()
  108. ******************************************************************************/
  109. int system(command)
  110.     const char * command;
  111.     {
  112.     HFILE ipiper;          /* Pipe handles to receive from DOS */
  113.     HFILE ipipew;
  114.     HFILE opiper;          /* Pipe handles to send to DOS */
  115.     HFILE opipew;
  116.  
  117.     int hdoscapt;
  118.     USHORT cpid,tpid;
  119.  
  120.     HFILE ostdout;  /* Keep record of original stdin/out */
  121.     HFILE ostdin;
  122.     HFILE ostderr;
  123.  
  124.     RESULTCODES resc,temp;
  125.     USHORT end;
  126.  
  127.     ULONG  ramsem=0;                /* Semaphore handle */
  128.     ULONG  wramsem=0;
  129.     USHORT wend,wlen;
  130.     USHORT errcode,werrcode;
  131.     char * buffer;    
  132.     int  length=80;
  133.     char far * pipeinput = buffer;  /* offset into buffer at which to */
  134.                                     /* place pipeinput */      
  135.     int polen=80;
  136.     char far * pipeout;
  137.     char c;
  138.  
  139.     if(stricmp("CMD",command)==0)
  140.         {
  141.         newses("cmd.exe","OS/2 Command Line Interpreter","",& (int) errcode);
  142.         return(0);
  143.         }
  144.     
  145.     /* create the receive and tranmit pipes. Use default pipe size */
  146.     if( ((errcode = DosMakePipe(&ipiper, &ipipew, 0))!=0) ||
  147.         (DosMakePipe(&opiper, &opipew, 0)!=0) )  
  148.         {
  149.         printf("Can't redirect DOS output - Pipe error!");
  150.         close(ipiper);       /* Close these just in case one was opened */
  151.         close(ipipew);
  152.         close(opiper);
  153.         close(opipew);
  154.         return(0);
  155.         }
  156.      
  157.     /* Copy the standard I/O handles - from now on there are 7 files open! */
  158.     ostdout=(HFILE) dup(fileno(stdout)); 
  159.     ostderr=(HFILE) dup(fileno(stderr));
  160.     ostdin = (HFILE) dup(fileno(stdin));
  161.  
  162.     /* Set the standard I/O handles to be the pipe handles */
  163.     dup2((int) ipipew, fileno(stdout));
  164.     dup2((int) ipipew, fileno(stderr));
  165.     dup2((int) opiper, fileno(stdin));
  166.  
  167.     /* Spawn the command using something we can test for the end of. */
  168.     /* The standard output and standard error devices should be set  */
  169.     /* to the pipe write handle. */
  170.  
  171.     cpid = spawnlp(P_NOWAIT, "cmd.exe", "cmd", "/c", command,NULL);
  172.  
  173.     /* Reset the parents standard out */
  174.     dup2((int) ostdout,fileno(stdout));
  175.     dup2((int) ostderr,fileno(stderr)); 
  176.     dup2((int) ostdin, fileno(stdin));
  177.  
  178.     close(ostdout);        /* The duplicate standard I/O handles */
  179.     close(ostderr);        /* are finished with now, so remove them */
  180.     close(ostdin);
  181.     if(cpid <= 0)
  182.         {
  183.         printf("Error starting CMD\n");
  184.         close(ipiper);
  185.         close(ipipew);
  186.         close(opiper);
  187.         close(opipew);
  188.         return(0);
  189.         }
  190.    
  191.     if((buffer = (char far *)malloc(length))==NULL)
  192.         {
  193.         close(ipiper);
  194.         close(ipipew);
  195.         close(opiper);
  196.         close(opipew);
  197.         return(0);
  198.         }
  199.  
  200.     if((pipeout = (char far *)malloc(polen))==NULL)
  201.         {
  202.         free(buffer);
  203.         close(ipiper);
  204.         close(ipipew);
  205.         close(opiper);
  206.         close(opipew);
  207.         return(0);
  208.         }
  209.  
  210.  
  211.     pipeinput = buffer;
  212.     wlen=0;
  213.     pipeout[0]='\0';
  214.  
  215.     /* Read data in the pipe until the task finishes */
  216.     do
  217.         {
  218.         DosSemSet(&ramsem);                 /* Set the semaphore */
  219.  
  220.         end=0;
  221.         /* Read string from pipe asynchronously */
  222.  
  223.         if(DosReadAsync(ipiper,             /* Handle of file */
  224.                      &ramsem,               /* Clear semaphore when finished */
  225.                      &errcode,              /* Return error code */
  226.                      pipeinput,             /* buffer */
  227.                      length-1, &end)!=0)    /* length and # bytes read */
  228.             {
  229.             printf("Problem reading DOS output");
  230.             break;
  231.             }
  232.                      
  233.         /* Now wait for either the end of the process or the semaphore to */
  234.         /* be cleared */
  235.         tpid=cpid+1;  /* Dummy value! */
  236.         while((cpid!=tpid)&& (DosSemWait(&ramsem,50L)==ERROR_SEM_TIMEOUT))
  237.             {
  238.             /* See if process has finished */
  239.             DosCwait(DCWA_PROCESSTREE, DCWW_NOWAIT, &temp, &tpid, cpid);
  240.             if( (c=(char)buff_tgetch(50L))>0)
  241.                 {
  242.                 if((c==13) || (wlen>(polen-2)))
  243.                     {
  244.                     pipeout[wlen++]=10;
  245.                     pipeout[wlen]=0;
  246.                     DosSemSet(&wramsem);
  247.                     if( DosWriteAsync(opipew,&wramsem,&werrcode,pipeout,wlen,&wend)!=0)
  248.                         printf("\nProblem writing DOS input\n");
  249.                     wlen=0;
  250.                     }
  251.                 else if(c==8)
  252.                     {
  253.                     if(wlen>0)
  254.                         {
  255.                         wlen--;
  256.                         printf("\b \b");
  257.                         }
  258.                     }
  259.                 else
  260.                     {
  261.                     printf("%c",c);
  262.                     pipeout[wlen]=c;
  263.                     wlen++;
  264.                     }   /* End of char handling ifs */
  265.                 }   /* End of getch if */
  266.             }  /* End write while */
  267.  
  268.         pipeinput[end] = '\0';              /* Terminate the string */
  269.  
  270.         /* PM multi-thread compatible */
  271.         AVIOwrttyc(pipeinput,end);
  272.         }while(cpid!=tpid);
  273.                                                                       
  274.     if(cpid!=tpid)                          /* Make sure process is dead */
  275.          {
  276.          printf("Killing command process\n");
  277.          DosKillProcess(DKP_PROCESSTREE, cpid);
  278.          }
  279.          
  280.     close(ipiper);       /* Make sure everything is closed otherwise we run */
  281.     close(ipipew);       /* out of file handles pretty damn quick */
  282.     close(opiper);
  283.     close(opipew);
  284.     free(pipeout);
  285.     free(buffer);
  286.  
  287.     return(pipeinput-buffer);   /* Return with the # of bytes read */
  288.     }
  289.  
  290. /* There are too many printf's to go replacing them all with something     */
  291. /* compatible with the AVIO or PM.  So the only thing to do is to re-write */
  292. /* printf to work in the AVIO or PM. The only disadvantage to this is that */
  293. /* I have no idea how to calculate the length of the buffer required to put*/
  294. /* the formatted string in.  Needless to say I'm not going to actually     */
  295. /* rewrite printf, vsprintf will do nicely!! The formatted string can then */
  296. /* be passed to something that can print to the AVIO screen.  Unfortunately*/
  297. /* only the VioWrtTTY function is really compatible with printf but it     */
  298. /* writes characters and some default attribute.  The other functions wrap */
  299. /* at the end of a line but do not scroll at the end of the screen         */
  300. /* another Microsoft fuck-up or do they blame IBM.                         */
  301.  
  302. int far printf(format,...)
  303.     const char* format;
  304.     {
  305.     struct avio_cellstr ac;
  306.     va_list varg_ptr;        /* Pointer to the variable argument list */
  307.     char buffer[512];        /* Buffer used to store the formatted string*/
  308.     int len;
  309.  
  310.     va_start(varg_ptr,format);   /* Get start of optional argument list*/
  311.  
  312. //    if((buffer = (char far *) malloc(sizeof(char)*512))==NULL)
  313. //        return(0);                       /* Max 512 char output*/
  314.  
  315.     vsprintf(buffer,format,varg_ptr);    /* Put formatted string into buffer */
  316.  
  317.     len = strlen(buffer);
  318.     
  319.     ac.fun = PRINTF;
  320.     ac.string = (PCH) buffer;
  321.     ac.len    = len;
  322.     do_aviotopm(&ac); 
  323. //    free(buffer);
  324.     return(len);
  325.     }
  326.     
  327. #include <signal.h>
  328.  
  329. void (far cdecl * far cdecl os_signalA( hand ) ) ()
  330.     void (far cdecl *hand)();
  331.     {
  332.     PFNSIGHANDLER oldsig;
  333.     USHORT oldaction;
  334.     USHORT error;
  335.  
  336.     
  337.     error = DosSetSigHandler((PFNSIGHANDLER)hand,&oldsig,&oldaction,SIGA_ACCEPT,
  338.                 SIG_PFLG_A);
  339.     
  340.     if(error)
  341.         {
  342.         printf("Error setting alarm signal handler\n");
  343.         return(SIG_ERR);
  344.         }
  345.    return((void (far *)())oldsig);
  346.    }
  347.    
  348. void perror(sc)
  349.     const char far * sc;
  350.     {
  351.     char far * s;
  352.     s = (char *) sc;
  353.     printf("%s",_strerror(s));
  354.     }
  355.     
  356. /******************************************************************************
  357. Function:       newses()
  358.  
  359. Description:    Creates a new OS/2 session.  The parameters for the session
  360.                 should be modified before calling this routine.  The default
  361.                 paramters create an indepentant PM windowed session with a
  362.                 screen size for use with the EDC scan programs.
  363.  
  364. Syntax:         void newses(program, title, input, error)
  365.                     char * program; Program file name (-path)
  366.                     char * title;   String to be used as session title
  367.                     char * input;   input parmas for the program
  368.                     int  * error;   Variable for return error
  369.  
  370. Returns:        Nothing
  371.                 Error = 0 for successful creation
  372.                 error = 1 if unsuccessful
  373.  
  374. Mods:           14-Nov-89 C.P.Armstrong created
  375.  
  376. ******************************************************************************/
  377.  
  378. void newses(program, title, input, error)
  379.     char * program; /* Program file name (-path) */
  380.     char * title;   /* String to be used as session title */
  381.     char * input;   /* input parmas for the program */
  382.     int  * error;   /* Variable for return error */
  383.     {
  384.     USHORT sesid;
  385.     USHORT pid;
  386.     STARTDATA sd;
  387.  
  388.     sd.Length  =      50;
  389.     sd.Related =     TRUE;  /* Child session */
  390.     sd.FgBg =        FALSE; /* In the foreground */
  391.     sd.TraceOpt =    0;
  392.     sd.TermQ =       0;
  393.     sd.Environment = NULL;
  394.     sd.InheritOpt =  1;
  395.     sd.SessionType = 2;     /* Do it in a window */
  396.     sd.IconFile =    "";
  397.     sd.PgmHandle =   0L;
  398.     sd.PgmControl =  2;     /* Window is maximized */
  399.     sd.InitXPos =    0;
  400.     sd.InitYPos =    0;
  401.     sd.InitXSize =   0;
  402.     sd.InitYSize =   0;
  403.  
  404.  
  405.     sd.PgmTitle=title;
  406.     sd.PgmName=program;
  407.     sd.PgmInputs=input;
  408.     
  409.     if(DosStartSession(&sd, &sesid, &pid)!=0)
  410.         *error=1;
  411.     else
  412.         *error=0;
  413.         
  414.     return;
  415.     }
  416.  
  417.                                     
  418.