home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gp_os2.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  24.5 KB  |  963 lines

  1. /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gp_os2.c,v 1.4.2.1 2000/12/05 01:31:14 raph Exp $ */
  20. /* Common platform-specific routines for OS/2 and MS-DOS */
  21. /* compiled with GCC/EMX */
  22.  
  23. #define INCL_DOS
  24. #define INCL_SPL
  25. #define INCL_SPLDOSPRINT
  26. #define INCL_SPLERRORS
  27. #define INCL_BASE
  28. #define INCL_ERRORS
  29. #define INCL_WIN
  30. #include <os2.h>
  31.  
  32. #include "pipe_.h"
  33. #include "stdio_.h"
  34. #include "string_.h"
  35. #include <fcntl.h>
  36.  
  37. #ifdef __IBMC__
  38. #define popen fopen        /* doesn't support popen */
  39. #define pclose fclose        /* doesn't support pclose */
  40. #else
  41. #include <dos.h>
  42. #endif
  43. /* Define the regs union tag for short registers. */
  44. #  define rshort x
  45. #define intdos(a,b) _int86(0x21, a, b)
  46.  
  47. #include "memory_.h"
  48. #include "string_.h"
  49. #include "gx.h"
  50. #include "gsexit.h"
  51. #include "gsmemory.h"
  52. #include "gsstruct.h"
  53. #include "gp.h"
  54. #include "gpmisc.h"
  55. #include "gsutil.h"
  56. #include "stdlib.h"        /* need _osmode, exit */
  57. #include "time_.h"
  58. #include <time.h>        /* should this be in time_.h? */
  59. #include "gdevpm.h"
  60. #ifdef __EMX__
  61. #include <sys/emxload.h>
  62. #endif
  63.  
  64. #if defined(__DLL__) && defined( __EMX__)
  65. /* This isn't provided in any of the libraries */
  66. /* We set this to the process environment in gp_init */
  67. char *fake_environ[3] =
  68. {"", NULL, NULL};
  69. char **environ = fake_environ;
  70. char **_environ = fake_environ;
  71. HWND hwndtext = (HWND) NULL;
  72.  
  73. #endif
  74.  
  75. #ifdef __DLL__
  76. /* use longjmp instead of exit when using DLL */
  77. #include <setjmp.h>
  78. extern jmp_buf gsdll_env;
  79.  
  80. #endif
  81.  
  82. #ifdef __DLL__
  83. #define isos2 TRUE
  84. #else
  85. #define isos2 (_osmode == OS2_MODE)
  86. #endif
  87. char pm_prntmp[256];        /* filename of printer spool temporary file */
  88.  
  89.  
  90. /* ------ Miscellaneous ------ */
  91.  
  92. /* Get the string corresponding to an OS error number. */
  93. /* All reasonable compilers support it. */
  94. const char *
  95. gp_strerror(int errnum)
  96. {
  97.     return strerror(errnum);
  98. }
  99.  
  100. /* use Unix version for date and time */
  101. /* ------ Date and time ------ */
  102.  
  103. /* Read the current time (in seconds since Jan. 1, 1970) */
  104. /* and fraction (in nanoseconds since midnight). */
  105. void
  106. gp_get_realtime(long *pdt)
  107. {
  108.     struct timeval tp;
  109.     struct timezone tzp;
  110.  
  111.     if (gettimeofday(&tp, &tzp) == -1) {
  112.     lprintf("Ghostscript: gettimeofday failed!\n");
  113.     gs_exit(1);
  114.     }
  115.     /* tp.tv_sec is #secs since Jan 1, 1970 */
  116.     pdt[0] = tp.tv_sec;
  117.     pdt[1] = tp.tv_usec * 1000;
  118.  
  119. #ifdef DEBUG_CLOCK
  120.     printf("tp.tv_sec = %d  tp.tv_usec = %d  pdt[0] = %ld  pdt[1] = %ld\n",
  121.        tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]);
  122. #endif
  123. }
  124.  
  125. /* Read the current user CPU time (in seconds) */
  126. /* and fraction (in nanoseconds).  */
  127. void
  128. gp_get_usertime(long *pdt)
  129. {
  130.     gp_get_realtime(pdt);    /* Use an approximation for now.  */
  131. }
  132.  
  133.  
  134. /* ------ Console management ------ */
  135.  
  136. /* Answer whether a given file is the console (input or output). */
  137. /* This is not a standard gp procedure, */
  138. /* but the MS Windows configuration needs it, */
  139. /* and other MS-DOS configurations might need it someday. */
  140. /* Don't know if it is needed for OS/2. */
  141. bool
  142. gp_file_is_console(FILE * f)
  143. {
  144. #ifndef __DLL__
  145.     if (!isos2) {
  146.     union REGS regs;
  147.  
  148.     if (f == NULL)
  149.         return false;
  150.     regs.h.ah = 0x44;    /* ioctl */
  151.     regs.h.al = 0;        /* get device info */
  152.     regs.rshort.bx = fileno(f);
  153.     intdos(®s, ®s);
  154.     return ((regs.h.dl & 0x80) != 0 && (regs.h.dl & 3) != 0);
  155.     }
  156. #endif
  157.     if ((f == gs_stdin) || (f == gs_stdout) || (f == gs_stderr))
  158.     return true;
  159.     return false;
  160. }
  161.  
  162. /* ------ File naming and accessing ------ */
  163.  
  164. /* Define the character used for separating file names in a list. */
  165. const char gp_file_name_list_separator = ';';
  166.  
  167. /* Define the default scratch file name prefix. */
  168. const char gp_scratch_file_name_prefix[] = "gs";
  169.  
  170. /* Define the name of the null output file. */
  171. const char gp_null_file_name[] = "nul";
  172.  
  173. /* Define the name that designates the current directory. */
  174. const char gp_current_directory_name[] = ".";
  175.  
  176. /* Define the string to be concatenated with the file mode */
  177. /* for opening files without end-of-line conversion. */
  178. const char gp_fmode_binary_suffix[] = "b";
  179.  
  180. /* Define the file modes for binary reading or writing. */
  181. const char gp_fmode_rb[] = "rb";
  182. const char gp_fmode_wb[] = "wb";
  183.  
  184. /* Answer whether a file name contains a directory/device specification, */
  185. /* i.e. is absolute (not directory- or device-relative). */
  186. bool
  187. gp_file_name_is_absolute(const char *fname, uint len)
  188. {                /* A file name is absolute if it contains a drive specification */
  189.     /* (second character is a :) or if it start with 0 or more .s */
  190.     /* followed by a / or \. */
  191.     if (len >= 2 && fname[1] == ':')
  192.     return true;
  193.     while (len && *fname == '.')
  194.     ++fname, --len;
  195.     return (len && (*fname == '/' || *fname == '\\'));
  196. }
  197.  
  198. /* Answer the string to be used for combining a directory/device prefix */
  199. /* with a base file name.  The file name is known to not be absolute. */
  200. const char *
  201. gp_file_name_concat_string(const char *prefix, uint plen,
  202.                const char *fname, uint len)
  203. {
  204.     if (plen > 0)
  205.     switch (prefix[plen - 1]) {
  206.         case ':':
  207.         case '/':
  208.         case '\\':
  209.         return "";
  210.     };
  211.     return "\\";
  212. }
  213.  
  214.  
  215. /* ------ File enumeration ------ */
  216.  
  217.  
  218. struct file_enum_s {
  219.     FILEFINDBUF3 findbuf;
  220.     HDIR hdir;
  221.     char *pattern;
  222.     int patlen;            /* orig pattern length */
  223.     int pat_size;        /* allocate space for pattern */
  224.     int head_size;        /* pattern length through last */
  225.     /* :, / or \ */
  226.     int first_time;
  227.     gs_memory_t *memory;
  228. };
  229. gs_private_st_ptrs1(st_file_enum, struct file_enum_s, "file_enum",
  230.             file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern);
  231.  
  232. /* Initialize an enumeration.  may NEED WORK ON HANDLING * ? \. */
  233. file_enum *
  234. gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t * mem)
  235. {
  236.     file_enum *pfen = gs_alloc_struct(mem, file_enum, &st_file_enum, "gp_enumerate_files");
  237.     int pat_size = 2 * patlen + 1;
  238.     char *pattern;
  239.     int hsize = 0;
  240.     int i;
  241.  
  242.     if (pfen == 0)
  243.     return 0;
  244.  
  245.     /* pattern could be allocated as a string, */
  246.     /* but it's simpler for GC and freeing to allocate it as bytes. */
  247.  
  248.     pattern = (char *)gs_alloc_bytes(mem, pat_size,
  249.                      "gp_enumerate_files(pattern)");
  250.     if (pattern == 0)
  251.     return 0;
  252.     memcpy(pattern, pat, patlen);
  253.     /* find directory name = header */
  254.     for (i = 0; i < patlen; i++) {
  255.     switch (pat[i]) {
  256.         case '\\':
  257.         if (i + 1 < patlen && pat[i + 1] == '\\')
  258.             i++;
  259.         /* falls through */
  260.         case ':':
  261.         case '/':
  262.         hsize = i + 1;
  263.     }
  264.     }
  265.     pattern[patlen] = 0;
  266.     pfen->pattern = pattern;
  267.     pfen->patlen = patlen;
  268.     pfen->pat_size = pat_size;
  269.     pfen->head_size = hsize;
  270.     pfen->memory = mem;
  271.     pfen->first_time = 1;
  272.     pfen->hdir = HDIR_CREATE;
  273.     return pfen;
  274. }
  275.  
  276. /* Enumerate the next file. */
  277. uint
  278. gp_enumerate_files_next(file_enum * pfen, char *ptr, uint maxlen)
  279. {
  280.     APIRET rc;
  281.     ULONG cFilenames = 1;
  282.  
  283.     if (!isos2) {
  284.     /* CAN'T DO IT SO JUST RETURN THE PATTERN. */
  285.     if (pfen->first_time) {
  286.         char *pattern = pfen->pattern;
  287.         uint len = strlen(pattern);
  288.  
  289.         pfen->first_time = 0;
  290.         if (len > maxlen)
  291.         return maxlen + 1;
  292.         strcpy(ptr, pattern);
  293.         return len;
  294.     }
  295.     return -1;
  296.     }
  297.     /* else OS/2 */
  298.     if (pfen->first_time) {
  299.     rc = DosFindFirst(pfen->pattern, &pfen->hdir, FILE_NORMAL,
  300.               &pfen->findbuf, sizeof(pfen->findbuf),
  301.               &cFilenames, FIL_STANDARD);
  302.     pfen->first_time = 0;
  303.     } else {
  304.     rc = DosFindNext(pfen->hdir, &pfen->findbuf, sizeof(pfen->findbuf),
  305.              &cFilenames);
  306.     }
  307.     if (rc)
  308.     return -1;
  309.  
  310.     if (pfen->head_size + pfen->findbuf.cchName < maxlen) {
  311.     memcpy(ptr, pfen->pattern, pfen->head_size);
  312.     strcpy(ptr + pfen->head_size, pfen->findbuf.achName);
  313.     return pfen->head_size + pfen->findbuf.cchName;
  314.     }
  315.     if (pfen->head_size >= maxlen)
  316.     return 0;        /* no hope at all */
  317.  
  318.     memcpy(ptr, pfen->pattern, pfen->head_size);
  319.     strncpy(ptr + pfen->head_size, pfen->findbuf.achName,
  320.         maxlen - pfen->head_size - 1);
  321.     return maxlen;
  322. }
  323.  
  324. /* Clean up the file enumeration. */
  325. void
  326. gp_enumerate_files_close(file_enum * pfen)
  327. {
  328.     gs_memory_t *mem = pfen->memory;
  329.  
  330.     if (isos2)
  331.     DosFindClose(pfen->hdir);
  332.     gs_free_object(mem, pfen->pattern,
  333.            "gp_enumerate_files_close(pattern)");
  334.     gs_free_object(mem, pfen, "gp_enumerate_files_close");
  335. }
  336.  
  337. /*************************************************************/
  338. /* from gp_iwatc.c and gp_itbc.c */
  339.  
  340. /* Intel processor, EMX/GCC specific routines for Ghostscript */
  341. #include <signal.h>
  342. #include "stat_.h"
  343. #include "string_.h"
  344.  
  345. /* Library routines not declared in a standard header */
  346. /* extern char *getenv(P1(const char *)); */
  347.  
  348. /* Forward declarations */
  349. private void handle_FPE(P1(int));
  350.  
  351. /* Do platform-dependent initialization. */
  352. void
  353. gp_init(void)
  354. {
  355. #if defined(__DLL__) && defined(__EMX__)
  356.     PTIB pptib;
  357.     PPIB pppib;
  358.     int i;
  359.     char *p;
  360.  
  361.     /* get environment of EXE */
  362.     DosGetInfoBlocks(&pptib, &pppib);
  363.     for (i = 0, p = pppib->pib_pchenv; *p; p += strlen(p) + 1)
  364.     i++;
  365.     _environ = environ = (char **)malloc((i + 2) * sizeof(char *));
  366.  
  367.     for (i = 0, p = pppib->pib_pchenv; *p; p += strlen(p) + 1) {
  368.     environ[i] = p;
  369.     i++;
  370.     }
  371.     environ[i] = p;
  372.     i++;
  373.     environ[i] = NULL;
  374. #endif
  375.  
  376.     /* keep gsos2.exe in memory for number of minutes specified in */
  377.     /* environment variable GS_LOAD */
  378. #ifdef __EMX__
  379.     _emxload_env("GS_LOAD");
  380. #endif
  381.  
  382.     /* Set up the handler for numeric exceptions. */
  383.     signal(SIGFPE, handle_FPE);
  384. }
  385.  
  386.  
  387. /* Trap numeric exceptions.  Someday we will do something */
  388. /* more appropriate with these. */
  389. private void
  390. handle_FPE(int sig)
  391. {
  392.     eprintf("Numeric exception:\n");
  393.     exit(1);
  394. }
  395.  
  396. extern int gs_exit_status;
  397.  
  398. /* Do platform-dependent cleanup. */
  399. void
  400. gp_exit(int exit_status, int code)
  401. {
  402. #ifndef __DLL__
  403.     if (exit_status && (_osmode == OS2_MODE))
  404.     DosSleep(2000);
  405. #endif
  406. #if defined(__DLL__) && defined(__EMX__)
  407.     if (environ != fake_environ) {
  408.     free(environ);
  409.     environ = _environ = fake_environ;
  410.     }
  411. #endif
  412. }
  413.  
  414. /* Exit the program. */
  415. void
  416. gp_do_exit(int exit_status)
  417. {
  418. #if defined(__DLL__)
  419.     /* Use longjmp since exit would terminate caller */
  420.     /* setjmp code will check gs_exit_status */
  421.     longjmp(gsdll_env, gs_exit_status);
  422. #else
  423.     exit(exit_status);
  424. #endif
  425. }
  426.  
  427. /* ------ Printer accessing ------ */
  428. private int pm_find_queue(char *queue_name, char *driver_name);
  429. private int is_os2_spool(const char *queue);
  430. private int pm_spool(char *filename, const char *queue);
  431.  
  432. /* Put a printer file (which might be stdout) into binary or text mode. */
  433. /* This is not a standard gp procedure, */
  434. /* but all MS-DOS configurations need it. */
  435. void
  436. gp_set_file_binary(int prnfno, int binary)
  437. {
  438. #ifndef __IBMC__
  439.     union REGS regs;
  440.  
  441.     regs.h.ah = 0x44;        /* ioctl */
  442.     regs.h.al = 0;        /* get device info */
  443.     regs.rshort.bx = prnfno;
  444.     intdos(®s, ®s);
  445.     if (((regs.rshort.flags) & 1) != 0 || !(regs.h.dl & 0x80))
  446.     return;            /* error, or not a device */
  447.     if (binary)
  448.     regs.h.dl |= 0x20;    /* binary (no ^Z intervention) */
  449.     else
  450.     regs.h.dl &= ~0x20;    /* text */
  451.     regs.h.dh = 0;
  452.     regs.h.ah = 0x44;        /* ioctl */
  453.     regs.h.al = 1;        /* set device info */
  454.     intdos(®s, ®s);
  455. #endif
  456. }
  457.  
  458. /* Open a connection to a printer.  A null file name means use the */
  459. /* standard printer connected to the machine, if any. */
  460. /* Return NULL if the connection could not be opened. */
  461. /* filename can be one of the following values
  462.  *   ""                Spool in default queue
  463.  *   "\\spool\queue"   Spool in "queue"
  464.  *   "|command"        open an output pipe using popen()
  465.  *   "filename"        open filename using fopen()
  466.  *   "port"            open port using fopen()
  467.  */
  468. FILE *
  469. gp_open_printer(char fname[gp_file_name_sizeof], int binary_mode)
  470. {
  471.     FILE *pfile;
  472.  
  473.     if ((strlen(fname) == 0) || is_os2_spool(fname)) {
  474.     if (isos2) {
  475.         /* default or spool */
  476.         if (pm_spool(NULL, fname))    /* check if spool queue valid */
  477.         return NULL;
  478.         pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
  479.                      pm_prntmp, (binary_mode ? "wb" : "w"));
  480.     } else
  481.         pfile = fopen("PRN", (binary_mode ? "wb" : "w"));
  482.     } else if ((isos2) && (fname[0] == '|'))
  483.     /* pipe */
  484.     pfile = popen(fname + 1, (binary_mode ? "wb" : "w"));
  485.     else
  486.     /* normal file or port */
  487.     pfile = fopen(fname, (binary_mode ? "wb" : "w"));
  488.  
  489.     if (pfile == (FILE *) NULL)
  490.     return (FILE *) NULL;
  491.     if (!isos2)
  492.     gp_set_file_binary(fileno(pfile), binary_mode);
  493.     return pfile;
  494. }
  495.  
  496. /* Close the connection to the printer. */
  497. void
  498. gp_close_printer(FILE * pfile, const char *fname)
  499. {
  500.     if (isos2 && (fname[0] == '|'))
  501.     pclose(pfile);
  502.     else
  503.     fclose(pfile);
  504.  
  505.     if ((strlen(fname) == 0) || is_os2_spool(fname)) {
  506.     /* spool temporary file */
  507.     pm_spool(pm_prntmp, fname);
  508.     unlink(pm_prntmp);
  509.     }
  510. }
  511.  
  512. /* ------ File accessing -------- */
  513.  
  514. /* Set a file into binary or text mode. */
  515. int
  516. gp_setmode_binary(FILE * pfile, bool binary)
  517. {
  518.     gp_set_file_binary(fileno(pfile), binary);
  519.     return 0;
  520. }
  521.  
  522. /* ------ Printer Spooling ------ */
  523. #ifndef NERR_BufTooSmall
  524. #define NERR_BufTooSmall 2123    /* For SplEnumQueue */
  525. #endif
  526.  
  527. /* If queue_name is NULL, list available queues */
  528. /* If strlen(queue_name)==0, return default queue and driver name */
  529. /* If queue_name supplied, return driver_name */
  530. /* returns 0 if OK, non-zero for error */
  531. private int
  532. pm_find_queue(char *queue_name, char *driver_name)
  533. {
  534.     SPLERR splerr;
  535.     USHORT jobCount;
  536.     ULONG cbBuf;
  537.     ULONG cTotal;
  538.     ULONG cReturned;
  539.     ULONG cbNeeded;
  540.     ULONG ulLevel;
  541.     ULONG i;
  542.     PSZ pszComputerName;
  543.     PBYTE pBuf;
  544.     PPRQINFO3 prq;
  545.  
  546.     ulLevel = 3L;
  547.     pszComputerName = (PSZ) NULL;
  548.     splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, 0L,    /* cbBuf */
  549.               &cReturned, &cTotal,
  550.               &cbNeeded, NULL);
  551.     if (splerr == ERROR_MORE_DATA || splerr == NERR_BufTooSmall) {
  552.     if (!DosAllocMem((PVOID) & pBuf, cbNeeded,
  553.              PAG_READ | PAG_WRITE | PAG_COMMIT)) {
  554.         cbBuf = cbNeeded;
  555.         splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, cbBuf,
  556.                   &cReturned, &cTotal,
  557.                   &cbNeeded, NULL);
  558.         if (splerr == NO_ERROR) {
  559.         /* Set pointer to point to the beginning of the buffer.           */
  560.         prq = (PPRQINFO3) pBuf;
  561.  
  562.         /* cReturned has the count of the number of PRQINFO3 structures.  */
  563.         for (i = 0; i < cReturned; i++) {
  564.             if (queue_name) {
  565.             /* find queue name and return driver name */
  566.             if (strlen(queue_name) == 0) {    /* use default queue */
  567.                 if (prq->fsType & PRQ3_TYPE_APPDEFAULT)
  568.                 strcpy(queue_name, prq->pszName);
  569.             }
  570.             if (strcmp(prq->pszName, queue_name) == 0) {
  571.                 char *p;
  572.  
  573.                 for (p = prq->pszDriverName; *p && (*p != '.'); p++)
  574.                 /* do nothing */ ;
  575.                 *p = '\0';    /* truncate at '.' */
  576.                 if (driver_name != NULL)
  577.                 strcpy(driver_name, prq->pszDriverName);
  578.                 DosFreeMem((PVOID) pBuf);
  579.                 return 0;
  580.             }
  581.             } else {
  582.             /* list queue details */
  583.             if (prq->fsType & PRQ3_TYPE_APPDEFAULT)
  584.                 fprintf(gs_stdout, "  %s  (DEFAULT)\n", prq->pszName);
  585.             else
  586.                 fprintf(gs_stdout, "  %s\n", prq->pszName);
  587.             }
  588.             prq++;
  589.         }        /*endfor cReturned */
  590.         }
  591.         DosFreeMem((PVOID) pBuf);
  592.     }
  593.     }
  594.     /* end if Q level given */ 
  595.     else {
  596.     /* If we are here we had a bad error code. Print it and some other info. */
  597.     fprintf(gs_stdout, "SplEnumQueue Error=%ld, Total=%ld, Returned=%ld, Needed=%ld\n",
  598.         splerr, cTotal, cReturned, cbNeeded);
  599.     }
  600.     if (splerr)
  601.     return splerr;
  602.     if (queue_name)
  603.     return -1;
  604.     return 0;
  605. }
  606.  
  607.  
  608. /* return TRUE if queue looks like a valid OS/2 queue name */
  609. private int
  610. is_os2_spool(const char *queue)
  611. {
  612.     char *prefix = "\\\\spool\\";    /* 8 characters long */
  613.     int i;
  614.  
  615.     for (i = 0; i < 8; i++) {
  616.     if (prefix[i] == '\\') {
  617.         if ((*queue != '\\') && (*queue != '/'))
  618.         return FALSE;
  619.     } else if (tolower(*queue) != prefix[i])
  620.         return FALSE;
  621.     queue++;
  622.     }
  623.     return TRUE;
  624. }
  625.  
  626. #define PRINT_BUF_SIZE 16384
  627.  
  628. /* Spool file to queue */
  629. /* return 0 if successful, non-zero if error */
  630. /* if filename is NULL, return 0 if spool queue is valid, non-zero if error */
  631. private int
  632. pm_spool(char *filename, const char *queue)
  633. {
  634.     HSPL hspl;
  635.     PDEVOPENSTRUC pdata;
  636.     PSZ pszToken = "*";
  637.     ULONG jobid;
  638.     BOOL rc;
  639.     char queue_name[256];
  640.     char driver_name[256];
  641.     char *buffer;
  642.     FILE *f;
  643.     int count;
  644.  
  645.     if (strlen(queue) != 0) {
  646.     /* queue specified */
  647.     strcpy(queue_name, queue + 8);    /* skip over \\spool\ */
  648.     } else {
  649.     /* get default queue */
  650.     queue_name[0] = '\0';
  651.     }
  652.     if (pm_find_queue(queue_name, driver_name)) {
  653.     /* error, list valid queue names */
  654.     fprintf(gs_stdout, "Invalid queue name.  Use one of:\n");
  655.     pm_find_queue(NULL, NULL);
  656.     return 1;
  657.     }
  658.     if (!filename)
  659.     return 0;        /* we were only asked to check the queue */
  660.  
  661.  
  662.     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL) {
  663.     fprintf(gs_stdout, "Out of memory in pm_spool\n");
  664.     return 1;
  665.     }
  666.     if ((f = fopen(filename, "rb")) == (FILE *) NULL) {
  667.     free(buffer);
  668.     fprintf(gs_stdout, "Can't open temporary file %s\n", filename);
  669.     return 1;
  670.     }
  671.     /* Allocate memory for pdata */
  672.     if (!DosAllocMem((PVOID) & pdata, sizeof(DEVOPENSTRUC),
  673.              (PAG_READ | PAG_WRITE | PAG_COMMIT))) {
  674.     /* Initialize elements of pdata */
  675.     pdata->pszLogAddress = queue_name;
  676.     pdata->pszDriverName = driver_name;
  677.     pdata->pdriv = NULL;
  678.     pdata->pszDataType = "PM_Q_RAW";
  679.     pdata->pszComment = "Ghostscript";
  680.     pdata->pszQueueProcName = NULL;
  681.     pdata->pszQueueProcParams = NULL;
  682.     pdata->pszSpoolerParams = NULL;
  683.     pdata->pszNetworkParams = NULL;
  684.  
  685.     hspl = SplQmOpen(pszToken, 4L, (PQMOPENDATA) pdata);
  686.     if (hspl == SPL_ERROR) {
  687.         fprintf(gs_stdout, "SplQmOpen failed.\n");
  688.         DosFreeMem((PVOID) pdata);
  689.         free(buffer);
  690.         fclose(f);
  691.         return 1;        /* failed */
  692.     }
  693.     rc = SplQmStartDoc(hspl, "Ghostscript");
  694.     if (!rc) {
  695.         fprintf(gs_stdout, "SplQmStartDoc failed.\n");
  696.         DosFreeMem((PVOID) pdata);
  697.         free(buffer);
  698.         fclose(f);
  699.         return 1;
  700.     }
  701.     /* loop, copying file to queue */
  702.     while (rc && (count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0) {
  703.         rc = SplQmWrite(hspl, count, buffer);
  704.         if (!rc)
  705.         fprintf(gs_stdout, "SplQmWrite failed.\n");
  706.     }
  707.     free(buffer);
  708.     fclose(f);
  709.  
  710.     if (!rc) {
  711.         fprintf(gs_stdout, "Aborting Spooling.\n");
  712.         SplQmAbort(hspl);
  713.     } else {
  714.         SplQmEndDoc(hspl);
  715.         rc = SplQmClose(hspl);
  716.         if (!rc)
  717.         fprintf(gs_stdout, "SplQmClose failed.\n");
  718.     }
  719.     } else
  720.     rc = 0;            /* no memory */
  721.     return !rc;
  722. }
  723.  
  724. /* ------ File naming and accessing ------ */
  725.  
  726. /* Create and open a scratch file with a given name prefix. */
  727. /* Write the actual file name at fname. */
  728. FILE *
  729. gp_open_scratch_file(const char *prefix, char fname[gp_file_name_sizeof],
  730.              const char *mode)
  731. {
  732. #ifdef __IBMC__
  733.     char *temp = getenv("TMPDIR");
  734.     char *tname;
  735.  
  736.     if (temp == 0)
  737.     temp = getenv("TEMP");
  738.     *fname = 0;
  739.     tname = _tempnam(temp, (char *)prefix);
  740.     if (tname) {
  741. /****** SHOULD DO A LENGTH CHECK ******/
  742.     strcpy(fname, tname);
  743.     free(tname);
  744.     }
  745. #else
  746.     /* The -7 is for XXXXXX plus a possible final \. */
  747.     int len = gp_file_name_sizeof - strlen(prefix) - 7;
  748.  
  749.     if (gp_gettmpdir(fname, &len) != 0)
  750.     *fname = 0;
  751.     else {
  752.     char last = '\\';
  753.     char *temp;
  754.  
  755.     /* Prevent X's in path from being converted by mktemp. */
  756.     for (temp = fname; *temp; temp++)
  757.         *temp = last = tolower(*temp);
  758.     switch (last) {
  759.         default:
  760.         strcat(fname, "\\");
  761.         case ':':
  762.         case '\\':
  763.         ;
  764.     }
  765.     }
  766.     strcat(fname, prefix);
  767.     strcat(fname, "XXXXXX");
  768.     mktemp(fname);
  769. #endif
  770.     return gp_fopentemp(fname, mode);
  771. }
  772.  
  773. /* Open a file with the given name, as a stream of uninterpreted bytes. */
  774. FILE *
  775. gp_fopen(const char *fname, const char *mode)
  776. {
  777.     return fopen(fname, mode);
  778. }
  779.  
  780. #ifdef __DLL__
  781.  
  782. /* The DLL version must not be allowed direct access to stdin and stdout */
  783. /* Instead these are redirected to the gsdll_callback */
  784. #include "gsdll.h"
  785. #include <stdarg.h>
  786.  
  787. /* for redirecting stdin/out/err */
  788. #include "stream.h"
  789. #include "gxiodev.h"        /* must come after stream.h */
  790.  
  791.  
  792. /* ====== Substitute for stdio ====== */
  793.  
  794. /* this code has been derived from gp_mswin.c */
  795.  
  796. /* Forward references */
  797. private stream_proc_process(pm_std_read_process);
  798. private stream_proc_process(pm_std_write_process);
  799. private stream_proc_available(pm_std_available);
  800.  
  801. /* Use a pseudo IODevice to get pm_stdio_init called at the right time. */
  802. /* This is bad architecture; we'll fix it later. */
  803. private iodev_proc_init(pm_stdio_init);
  804. const gx_io_device gs_iodev_wstdio = {
  805.     /* The name is null to keep this from showing up as a resource. */
  806.     0, "Special",
  807.     {pm_stdio_init, iodev_no_open_device,
  808.      iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,
  809.      iodev_no_delete_file, iodev_no_rename_file,
  810.      iodev_no_file_status, iodev_no_enumerate_files
  811.     }
  812. };
  813.  
  814. /* Discard the contents of the buffer when reading. */
  815. void
  816. pm_std_read_reset(stream * s)
  817. {
  818.     s_std_read_reset(s);
  819.     s->end_status = 0;
  820. }
  821.  
  822. /* Define alternate 'open' routines for our stdin/out/err streams. */
  823.  
  824. extern const gx_io_device gs_iodev_stdin;
  825. private int
  826. pm_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
  827.           gs_memory_t * mem)
  828. {
  829.     int code = gs_iodev_stdin.procs.open_device(iodev, access, ps, mem);
  830.     stream *s = *ps;
  831.  
  832.     if (code != 1)
  833.     return code;
  834.     s->procs.reset = pm_std_read_reset;
  835.     s->procs.process = pm_std_read_process;
  836.     s->procs.available = pm_std_available;
  837.     s->file = NULL;
  838.     return 0;
  839. }
  840.  
  841. extern const gx_io_device gs_iodev_stdout;
  842. private int
  843. pm_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
  844.            gs_memory_t * mem)
  845. {
  846.     int code = gs_iodev_stdout.procs.open_device(iodev, access, ps, mem);
  847.     stream *s = *ps;
  848.  
  849.     if (code != 1)
  850.     return code;
  851.     s->procs.process = pm_std_write_process;
  852.     s->procs.available = pm_std_available;
  853.     s->file = NULL;
  854.     return 0;
  855. }
  856.  
  857. extern const gx_io_device gs_iodev_stderr;
  858. private int
  859. pm_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
  860.            gs_memory_t * mem)
  861. {
  862.     int code = gs_iodev_stderr.procs.open_device(iodev, access, ps, mem);
  863.     stream *s = *ps;
  864.  
  865.     if (code != 1)
  866.     return code;
  867.     s->procs.process = pm_std_write_process;
  868.     s->procs.available = pm_std_available;
  869.     s->file = NULL;
  870.     return 0;
  871. }
  872.  
  873. /* Patch stdin/out/err to use our windows. */
  874. private int
  875. pm_stdio_init(gx_io_device * iodev, gs_memory_t * mem)
  876. {
  877.     /* If stdxxx is the console, replace the 'open' routines, */
  878.     /* which haven't gotten called yet. */
  879.  
  880.     if (gp_file_is_console(gs_stdin))
  881.     gs_findiodevice((const byte *)"%stdin", 6)->procs.open_device =
  882.         pm_stdin_open;
  883.  
  884.     if (gp_file_is_console(gs_stdout))
  885.     gs_findiodevice((const byte *)"%stdout", 7)->procs.open_device =
  886.         pm_stdout_open;
  887.  
  888.     if (gp_file_is_console(gs_stderr))
  889.     gs_findiodevice((const byte *)"%stderr", 7)->procs.open_device =
  890.         pm_stderr_open;
  891.  
  892.     return 0;
  893. }
  894.  
  895.  
  896. /* We should really use a private buffer for line reading, */
  897. /* because we can't predict the size of the supplied input area.... */
  898. private int
  899. pm_std_read_process(stream_state * st, stream_cursor_read * ignore_pr,
  900.             stream_cursor_write * pw, bool last)
  901. {
  902.     int count = pw->limit - pw->ptr;
  903.  
  904.     if (count == 0)        /* empty buffer */
  905.     return 1;
  906.  
  907.     /* callback to get more input */
  908.     count = (*pgsdll_callback) (GSDLL_STDIN, pw->ptr + 1, count);
  909.     if (count == 0) {
  910.     /* EOF */
  911.     /* what should we do? */
  912.     return EOFC;
  913.     }
  914.     pw->ptr += count;
  915.     return 1;
  916. }
  917.  
  918. private int
  919. pm_std_available(register stream * s, long *pl)
  920. {
  921.     *pl = -1;        // EOF, since we can't do it
  922.     return 0;        // OK
  923. }
  924.  
  925.  
  926. private int
  927. pm_std_write_process(stream_state * st, stream_cursor_read * pr,
  928.              stream_cursor_write * ignore_pw, bool last)
  929. {
  930.     uint count = pr->limit - pr->ptr;
  931.  
  932.     (*pgsdll_callback) (GSDLL_STDOUT, (char *)(pr->ptr + 1), count);
  933.     pr->ptr = pr->limit;
  934.     return 0;
  935. }
  936.  
  937. /* This is used instead of the stdio version. */
  938. /* The declaration must be identical to that in <stdio.h>. */
  939. #ifdef __EMX__
  940. int
  941. fprintf(FILE * file, __const__ char *fmt,...)
  942. #else
  943. int
  944. fprintf(FILE * file, const char *fmt,...)
  945. #endif
  946. {
  947.     int count;
  948.     va_list args;
  949.  
  950.     va_start(args, fmt);
  951.     if (gp_file_is_console(file)) {
  952.     char buf[1024];
  953.  
  954.     count = vsprintf(buf, fmt, args);
  955.     (*pgsdll_callback) (GSDLL_STDOUT, buf, count);
  956.     } else {
  957.     count = vfprintf(file, fmt, args);
  958.     }
  959.     va_end(args);
  960.     return count;
  961. }
  962. #endif /* __DLL__ */
  963.