Commit | Line | Data |
---|---|---|
5b80f84b WJ |
1 | /* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* gp_unix.c */ | |
21 | /* Unix-specific routines for Ghostscript */ | |
22 | #include "memory_.h" | |
23 | #include "string_.h" | |
24 | #include "gx.h" | |
25 | #include "gp.h" | |
26 | #include "stat_.h" | |
27 | #include "time_.h" | |
28 | ||
29 | /* popen isn't POSIX-standard, so we declare it here. */ | |
30 | extern FILE *popen(); | |
31 | extern int pclose(); | |
32 | ||
33 | /* Do platform-dependent initialization. */ | |
34 | void | |
35 | gp_init() | |
36 | { | |
37 | } | |
38 | ||
39 | /* Do platform-dependent cleanup. */ | |
40 | void | |
41 | gp_exit() | |
42 | { | |
43 | } | |
44 | ||
45 | /* ------ Date and time ------ */ | |
46 | ||
47 | /* Read the current date (in days since Jan. 1, 1980) */ | |
48 | /* and time (in milliseconds since midnight). */ | |
49 | void | |
50 | gp_get_clock(long *pdt) | |
51 | { long secs_since_1980; | |
52 | struct timeval tp; | |
53 | struct timezone tzp; | |
54 | time_t tsec; | |
55 | struct tm *tm, *localtime(); | |
56 | ||
57 | if ( gettimeofday(&tp, &tzp) == -1 ) | |
58 | { perror("Ghostscript: gettimeofday failed:"); | |
59 | exit(-1); | |
60 | } | |
61 | ||
62 | /* tp.tv_sec is #secs since Jan 1, 1970 */ | |
63 | ||
64 | /* subtract off number of seconds in 10 years */ | |
65 | /* leap seconds are not accounted for */ | |
66 | secs_since_1980 = tp.tv_sec - (long)(60 * 60 * 24 * 365.25 * 10); | |
67 | ||
68 | /* adjust for timezone */ | |
69 | secs_since_1980 -= (tzp.tz_minuteswest * 60); | |
70 | ||
71 | /* adjust for daylight savings time - assume dst offset is 1 hour */ | |
72 | tsec = tp.tv_sec; | |
73 | tm = localtime(&tsec); | |
74 | if ( tm->tm_isdst ) | |
75 | secs_since_1980 += (60 * 60); | |
76 | ||
77 | /* divide secs by #secs/day to get #days (integer division truncates) */ | |
78 | pdt[0] = secs_since_1980 / (60 * 60 * 24); | |
79 | /* modulo + microsecs/1000 gives number of millisecs since midnight */ | |
80 | pdt[1] = (secs_since_1980 % (60 * 60 * 24)) * 1000 + tp.tv_usec / 1000; | |
81 | #ifdef DEBUG_CLOCK | |
82 | printf("tp.tv_sec = %d tp.tv_usec = %d pdt[0] = %ld pdt[1] = %ld\n", | |
83 | tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]); | |
84 | #endif | |
85 | } | |
86 | ||
87 | /* ------ Screen management ------ */ | |
88 | ||
89 | /* Write a string to the console. */ | |
90 | void | |
91 | gp_console_puts(const char *str, uint size) | |
92 | { fwrite(str, 1, size, stdout); | |
93 | } | |
94 | ||
95 | /* Make the console current on the screen. */ | |
96 | int | |
97 | gp_make_console_current(struct gx_device_s *dev) | |
98 | { return 0; | |
99 | } | |
100 | ||
101 | /* Make the graphics current on the screen. */ | |
102 | int | |
103 | gp_make_graphics_current(struct gx_device_s *dev) | |
104 | { return 0; | |
105 | } | |
106 | ||
107 | /* ------ Printer accessing ------ */ | |
108 | ||
109 | /* Open a connection to a printer. A null file name means use the */ | |
110 | /* standard printer connected to the machine, if any. */ | |
111 | /* "|command" opens an output pipe. */ | |
112 | /* Return NULL if the connection could not be opened. */ | |
113 | FILE * | |
114 | gp_open_printer(char *fname) | |
115 | { return | |
116 | (strlen(fname) == 0 ? | |
117 | gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "wb") : | |
118 | fname[0] == '|' ? | |
119 | popen(fname + 1, "wb") : | |
120 | fopen(fname, "wb")); | |
121 | } | |
122 | ||
123 | /* Close the connection to the printer. */ | |
124 | void | |
125 | gp_close_printer(FILE *pfile, const char *fname) | |
126 | { if ( fname[0] == '|' ) | |
127 | pclose(pfile); | |
128 | else | |
129 | fclose(pfile); | |
130 | } | |
131 | ||
132 | /* ------ File names ------ */ | |
133 | ||
134 | /* Define the character used for separating file names in a list. */ | |
135 | const char gp_file_name_list_separator = ':'; | |
136 | ||
137 | /* Define the default scratch file name prefix. */ | |
138 | const char gp_scratch_file_name_prefix[] = "/tmp/gs_"; | |
139 | ||
140 | /* Define whether case is insignificant in file names. */ | |
141 | const int gp_file_names_ignore_case = 0; | |
142 | ||
143 | /* Create and open a scratch file with a given name prefix. */ | |
144 | /* Write the actual file name at fname. */ | |
145 | FILE * | |
146 | gp_open_scratch_file(const char *prefix, char *fname, const char *mode) | |
147 | { strcpy(fname, prefix); | |
148 | strcat(fname, "XXXXXX"); | |
149 | mktemp(fname); | |
150 | return fopen(fname, mode); | |
151 | } | |
152 | ||
153 | /* Answer whether a file name contains a directory/device specification, */ | |
154 | /* i.e. is absolute (not directory- or device-relative). */ | |
155 | int | |
156 | gp_file_name_is_absolute(const char *fname, uint len) | |
157 | { /* A file name is absolute if it starts with a /. */ | |
158 | return ( len >= 1 && *fname == '/' ); | |
159 | } | |
160 | ||
161 | /* Answer the string to be used for combining a directory/device prefix */ | |
162 | /* with a base file name. The file name is known to not be absolute. */ | |
163 | char * | |
164 | gp_file_name_concat_string(const char *prefix, uint plen, | |
165 | const char *fname, uint len) | |
166 | { if ( plen > 0 && prefix[plen - 1] == '/' ) | |
167 | return ""; | |
168 | return "/"; | |
169 | } | |
170 | ||
171 | /* ------ File operations ------ */ | |
172 | ||
173 | /* If the file given by fname exists, fill in its status and return 1; */ | |
174 | /* otherwise return 0. */ | |
175 | int | |
176 | gp_file_status(const char *fname, file_status *pstatus) | |
177 | { struct stat sbuf; | |
178 | /* The RS/6000 prototype for stat doesn't include const, */ | |
179 | /* so we have to explicitly remove the const modifier. */ | |
180 | if ( stat((char *)fname, &sbuf) < 0 ) return 0; | |
181 | pstatus->size_pages = stat_blocks(&sbuf); /* st_blocks is */ | |
182 | /* missing on some systems, */ | |
183 | /* see stat_.h */ | |
184 | pstatus->size_bytes = sbuf.st_size; | |
185 | pstatus->time_referenced = sbuf.st_mtime; | |
186 | pstatus->time_created = sbuf.st_ctime; | |
187 | return 1; | |
188 | } | |
189 | ||
190 | /* ------ File enumeration ------ */ | |
191 | ||
192 | /****** THIS IS NOT SUPPORTED ON UNIX SYSTEMS. ******/ | |
193 | /* Amazingly enough, there is no standard Unix library routine */ | |
194 | /* for enumerating the files matching a pattern, */ | |
195 | /* or even for enumerating (conveniently) the files in a directory. */ | |
196 | ||
197 | struct file_enum_s { | |
198 | char *pattern; | |
199 | int first_time; | |
200 | gs_memory_procs mprocs; | |
201 | }; | |
202 | ||
203 | /* Initialize an enumeration. NEEDS WORK ON HANDLING * ? \. */ | |
204 | file_enum * | |
205 | gp_enumerate_files_init(const char *pat, uint patlen, | |
206 | proc_alloc_t palloc, proc_free_t pfree) | |
207 | { file_enum *pfen = (file_enum *)(*palloc)(1, sizeof(file_enum), "gp_enumerate_files"); | |
208 | char *pattern; | |
209 | if ( pfen == 0 ) return 0; | |
210 | pattern = (*palloc)(patlen + 1, 1, | |
211 | "gp_enumerate_files(pattern)"); | |
212 | if ( pattern == 0 ) return 0; | |
213 | memcpy(pattern, pat, patlen); | |
214 | pattern[patlen] = 0; | |
215 | pfen->pattern = pattern; | |
216 | pfen->mprocs.alloc = palloc; | |
217 | pfen->mprocs.free = pfree; | |
218 | pfen->first_time = 1; | |
219 | return pfen; | |
220 | } | |
221 | ||
222 | /* Enumerate the next file. */ | |
223 | uint | |
224 | gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen) | |
225 | { if ( pfen->first_time ) | |
226 | { pfen->first_time = 0; | |
227 | } | |
228 | return -1; | |
229 | } | |
230 | ||
231 | /* Clean up the file enumeration. */ | |
232 | void | |
233 | gp_enumerate_files_close(file_enum *pfen) | |
234 | { proc_free_t pfree = pfen->mprocs.free; | |
235 | (*pfree)(pfen->pattern, strlen(pfen->pattern) + 1, 1, | |
236 | "gp_enumerate_files_close(pattern)"); | |
237 | (*pfree)((char *)pfen, 1, sizeof(file_enum), "gp_enumerate_files_close"); | |
238 | } |