Commit | Line | Data |
---|---|---|
af364716 WJ |
1 | /* sys4.unx |
2 | The system dependent routines to read command files for Unix. | |
3 | These routines are used by uucico to get the commands it should | |
4 | execute. | |
5 | ||
6 | Copyright (C) 1991, 1992 Ian Lance Taylor | |
7 | ||
8 | This file is part of the Taylor UUCP package. | |
9 | ||
10 | This program is free software; you can redistribute it and/or | |
11 | modify it under the terms of the GNU General Public License as | |
12 | published by the Free Software Foundation; either version 2 of the | |
13 | License, or (at your option) any later version. | |
14 | ||
15 | This program is distributed in the hope that it will be useful, but | |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
21 | along with this program; if not, write to the Free Software | |
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
23 | ||
24 | The author of the program may be contacted at ian@airs.com or | |
25 | c/o AIRS, P.O. Box 520, Waltham, MA 02254. | |
26 | ||
27 | $Log: sys4.unx,v $ | |
28 | Revision 1.17 1992/03/12 19:56:10 ian | |
29 | Debugging based on types rather than number | |
30 | ||
31 | Revision 1.16 1992/03/11 00:18:50 ian | |
32 | Save temporary file if file send fails | |
33 | ||
34 | Revision 1.15 1992/03/04 21:34:12 ian | |
35 | Johan Vromans: set *pbgrade correctly in fsysdep_has_work | |
36 | ||
37 | Revision 1.14 1992/03/04 02:13:23 ian | |
38 | Bob Denny: warn if we can't open a command file | |
39 | ||
40 | Revision 1.13 1992/02/23 03:26:51 ian | |
41 | Overhaul to use automatic configure shell script | |
42 | ||
43 | Revision 1.12 1992/02/20 04:18:59 ian | |
44 | Added uustat | |
45 | ||
46 | Revision 1.11 1992/02/09 03:14:48 ian | |
47 | Added HAVE_OLD_DIRECTORIES for systems without readdir routines | |
48 | ||
49 | Revision 1.10 1992/02/08 20:11:47 ian | |
50 | Work data was freed up incorrectly if a file transfer failed in the middle | |
51 | ||
52 | Revision 1.9 1992/02/08 03:54:18 ian | |
53 | Include <string.h> only in <uucp.h>, added 1992 copyright | |
54 | ||
55 | Revision 1.8 1992/01/29 18:28:34 ian | |
56 | Patrick Smith: fixed casts in iswork_cmp | |
57 | ||
58 | Revision 1.7 1991/12/29 04:04:18 ian | |
59 | Added a bunch of extern definitions | |
60 | ||
61 | Revision 1.6 1991/12/20 00:10:39 ian | |
62 | Sort the earlier files so that bsearch can work correctly | |
63 | ||
64 | Revision 1.5 1991/12/19 01:09:38 ian | |
65 | David Nugent: rescan work directory before quitting | |
66 | ||
67 | Revision 1.4 1991/11/16 00:45:50 ian | |
68 | If fsysdep_work frees qSwork_file, it must set it to NULL | |
69 | ||
70 | Revision 1.3 1991/11/15 21:58:02 ian | |
71 | Move ssline definition out of ssfile | |
72 | ||
73 | Revision 1.2 1991/11/08 04:47:19 ian | |
74 | Hannu Strang: don't check system name for BNU work files | |
75 | ||
76 | Revision 1.1 1991/09/10 19:45:50 ian | |
77 | Initial revision | |
78 | ||
79 | */ | |
80 | ||
81 | #include "uucp.h" | |
82 | ||
83 | #if USE_RCS_ID | |
84 | char sys4_unx_rcsid[] = "$Id: sys4.unx,v 1.17 1992/03/12 19:56:10 ian Rel $"; | |
85 | #endif | |
86 | ||
87 | #include <ctype.h> | |
88 | #include <errno.h> | |
89 | ||
90 | #include "system.h" | |
91 | #include "sysdep.h" | |
92 | ||
93 | #if HAVE_OPENDIR | |
94 | #if HAVE_DIRENT_H | |
95 | #include <dirent.h> | |
96 | #else /* ! HAVE_DIRENT_H */ | |
97 | #include <sys/dir.h> | |
98 | #define dirent direct | |
99 | #endif /* ! HAVE_DIRENT_H */ | |
100 | #endif /* HAVE_OPENDIR */ | |
101 | ||
102 | /* External functions. */ | |
103 | extern int fclose (); | |
104 | \f | |
105 | /* Local functions. */ | |
106 | ||
107 | static const char *zswork_directory P((const char *zsystem)); | |
108 | static boolean fswork_file P((const char *zsystem, const char *zfile, | |
109 | char *pbgrade)); | |
110 | \f | |
111 | /* These functions can support multiple actions going on at once. | |
112 | This allows the UUCP package to send and receive multiple files at | |
113 | the same time. This is a very flexible feature, but I'm not sure | |
114 | it will actually be used all that much. | |
115 | ||
116 | The ssfile structure holds a command file name and all the lines | |
117 | read in from that command file. The union within the ssline | |
118 | structure initially holds a line from the file and then holds a | |
119 | pointer back to the ssfile structure; a pointer to this union is | |
120 | used as a sequence pointer. The ztemp entry of the ssline | |
121 | structure holds the name of a temporary file to delete, if any. */ | |
122 | ||
123 | #define CFILELINES (10) | |
124 | ||
125 | struct ssline | |
126 | { | |
127 | char *zline; | |
128 | struct ssfile *qfile; | |
129 | char *ztemp; | |
130 | }; | |
131 | ||
132 | struct ssfile | |
133 | { | |
134 | char *zfile; | |
135 | int clines; | |
136 | int cdid; | |
137 | struct ssline aslines[CFILELINES]; | |
138 | }; | |
139 | ||
140 | /* Static variables for the work scan. */ | |
141 | ||
142 | static char **azSwork_files; | |
143 | static int cSwork_files; | |
144 | static int iSwork_file; | |
145 | static struct ssfile *qSwork_file; | |
146 | ||
147 | /* Given a system name, return a directory to search for work. */ | |
148 | ||
149 | static const char * | |
150 | zswork_directory (zsystem) | |
151 | const char *zsystem; | |
152 | { | |
153 | #if SPOOLDIR_V2 | |
154 | return "."; | |
155 | #endif /* SPOOLDIR_V2 */ | |
156 | #if SPOOLDIR_BSD42 | SPOOLDIR_BSD43 | |
157 | return "C."; | |
158 | #endif /* SPOOLDIR_BSD42 | SPOOLDIR_BSD43 */ | |
159 | #if SPOOLDIR_BNU | |
160 | return zsystem; | |
161 | #endif /* SPOOLDIR_BNU */ | |
162 | #if SPOOLDIR_ULTRIX | |
163 | static int c; | |
164 | static char *z; | |
165 | int cwant; | |
166 | ||
167 | cwant = strlen (zsystem); | |
168 | if (cwant < sizeof "DEFAULT" - 1) | |
169 | cwant = sizeof "DEFAULT" - 1; | |
170 | cwant += sizeof "sys//C."; | |
171 | if (c < cwant) | |
172 | { | |
173 | xfree ((pointer) z); | |
174 | z = (char *) xmalloc (cwant); | |
175 | c = cwant; | |
176 | } | |
177 | ||
178 | if (fsultrix_has_spool (zsystem)) | |
179 | sprintf (z, "sys/%s/C.", zsystem); | |
180 | else | |
181 | strcpy (z, "sys/DEFAULT/C."); | |
182 | return z; | |
183 | #endif /* SPOOLDIR_ULTRIX */ | |
184 | #if SPOOLDIR_TAYLOR | |
185 | static int c; | |
186 | static char *z; | |
187 | int cwant; | |
188 | ||
189 | cwant = strlen (zsystem) + sizeof "/C."; | |
190 | if (c < cwant) | |
191 | { | |
192 | xfree ((pointer) z); | |
193 | z = (char *) xmalloc (cwant); | |
194 | c = cwant; | |
195 | } | |
196 | sprintf (z, "%s/C.", zsystem); | |
197 | return z; | |
198 | #endif /* SPOOLDIR_TAYLOR */ | |
199 | } | |
200 | ||
201 | /* See whether a file name from the directory returned by | |
202 | zswork_directory is really a command for a particular system. | |
203 | Return the command grade. */ | |
204 | ||
205 | /*ARGSUSED*/ | |
206 | static boolean | |
207 | fswork_file (zsystem, zfile, pbgrade) | |
208 | const char *zsystem; | |
209 | const char *zfile; | |
210 | char *pbgrade; | |
211 | { | |
212 | #if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43 || SPOOLDIR_ULTRIX | |
213 | int cfilesys, csys; | |
214 | ||
215 | /* The file name should be C.ssssssgqqqq, where g is exactly one | |
216 | letter and qqqq is exactly four numbers. The system name may be | |
217 | truncated to six or seven characters. The system name of the | |
218 | file must match the system name we're looking for, since there | |
219 | could be work files for several systems in one directory. */ | |
220 | if (zfile[0] != 'C' || zfile[1] != '.') | |
221 | return FALSE; | |
222 | csys = strlen (zsystem); | |
223 | cfilesys = strlen (zfile) - 7; | |
224 | if (csys != cfilesys | |
225 | && (csys < 6 || (cfilesys != 6 && cfilesys != 7))) | |
226 | return FALSE; | |
227 | *pbgrade = zfile[cfilesys + 2]; | |
228 | return strncmp (zfile + 2, zsystem, cfilesys) == 0; | |
229 | #endif /* V2 || BSD42 || BSD43 || ULTRIX */ | |
230 | #if SPOOLDIR_BNU | |
231 | int clen; | |
232 | ||
233 | /* The file name should be C.ssssssgqqqq where g is exactly one | |
234 | letter and qqqq is exactly four numbers or letters. We don't | |
235 | check the system name, because it is guaranteed by the directory | |
236 | we are looking in and AIX uucp sets it to the local system rather | |
237 | than the remote one. */ | |
238 | if (zfile[0] != 'C' || zfile[1] != '.') | |
239 | return FALSE; | |
240 | clen = strlen (zfile); | |
241 | if (clen < 7) | |
242 | return FALSE; | |
243 | *pbgrade = zfile[clen - 5]; | |
244 | return TRUE; | |
245 | #endif /* SPOOLDIR_BNU */ | |
246 | #if SPOOLDIR_TAYLOR | |
247 | /* We don't keep the system name in the file name, since that | |
248 | forces truncation. Our file names are always C.gqqqq. */ | |
249 | *pbgrade = zfile[2]; | |
250 | return (zfile[0] == 'C' | |
251 | && zfile[1] == '.' | |
252 | && strlen (zfile) == 7); | |
253 | #endif /* SPOOLDIR_TAYLOR */ | |
254 | } | |
255 | ||
256 | /* A comparison function to look through the list of file names. */ | |
257 | ||
258 | static int iswork_cmp P((constpointer pkey, constpointer pdatum)); | |
259 | ||
260 | static int | |
261 | iswork_cmp (pkey, pdatum) | |
262 | constpointer pkey; | |
263 | constpointer pdatum; | |
264 | { | |
265 | const char * const *pzkey = (const char * const *) pkey; | |
266 | const char * const *pzdatum = (const char * const *) pdatum; | |
267 | ||
268 | return strcmp (*pzkey, *pzdatum); | |
269 | } | |
270 | ||
271 | /* See whether there is any work to do for a particular system. If | |
272 | any work is found, *pbgrade is set to highest grade found. */ | |
273 | ||
274 | /*ARGSUSED*/ | |
275 | boolean | |
276 | fsysdep_has_work (qsys, pbgrade) | |
277 | const struct ssysteminfo *qsys; | |
278 | char *pbgrade; | |
279 | { | |
280 | boolean fret; | |
281 | const char *zdir; | |
282 | DIR *qdir; | |
283 | struct dirent *qentry; | |
284 | ||
285 | fret = FALSE; | |
286 | *pbgrade = BGRADE_LOW; | |
287 | ||
288 | if (azSwork_files != NULL && iSwork_file < cSwork_files) | |
289 | { | |
290 | int i; | |
291 | ||
292 | fret = TRUE; | |
293 | for (i = iSwork_file; i < cSwork_files; i++) | |
294 | { | |
295 | char bgrade; | |
296 | ||
297 | (void) fswork_file (qsys->zname, azSwork_files[i], &bgrade); | |
298 | if (igradecmp (bgrade, *pbgrade) < 0) | |
299 | *pbgrade = bgrade; | |
300 | } | |
301 | } | |
302 | ||
303 | zdir = zswork_directory (qsys->zname); | |
304 | if (zdir == NULL) | |
305 | return FALSE; | |
306 | ||
307 | qdir = opendir ((char *) zdir); | |
308 | if (qdir == NULL) | |
309 | return FALSE; | |
310 | while ((qentry = readdir (qdir)) != NULL) | |
311 | { | |
312 | char bgrade; | |
313 | char *zname; | |
314 | ||
315 | /* If this is a work file and we haven't seen it before, return | |
316 | TRUE. Also, determine the grade to return. */ | |
317 | zname = qentry->d_name; | |
318 | if (fswork_file (qsys->zname, qentry->d_name, &bgrade) | |
319 | && (azSwork_files == NULL | |
320 | || bsearch ((pointer) &zname, | |
321 | (pointer) azSwork_files, | |
322 | cSwork_files, sizeof (char *), | |
323 | iswork_cmp) == NULL)) | |
324 | { | |
325 | fret = TRUE; | |
326 | if (igradecmp (bgrade, *pbgrade) < 0) | |
327 | *pbgrade = bgrade; | |
328 | } | |
329 | } | |
330 | closedir (qdir); | |
331 | return fret; | |
332 | } | |
333 | ||
334 | /* Initialize the work scan. We have to read all the files in the | |
335 | work directory, so that we can sort them by work grade. The bgrade | |
336 | argument is the minimum grade to consider. We don't want to return | |
337 | files that we have already considered; usysdep_get_work_free will | |
338 | clear the data out when we are done with the system. This returns | |
339 | FALSE on error. */ | |
340 | ||
341 | #define CWORKFILES (10) | |
342 | ||
343 | /*ARGSUSED*/ | |
344 | boolean | |
345 | fsysdep_get_work_init (qsys, bgrade) | |
346 | const struct ssysteminfo *qsys; | |
347 | int bgrade; | |
348 | { | |
349 | const char *zdir; | |
350 | DIR *qdir; | |
351 | struct dirent *qentry; | |
352 | int chad; | |
353 | int callocated; | |
354 | ||
355 | zdir = zswork_directory (qsys->zname); | |
356 | if (zdir == NULL) | |
357 | return FALSE; | |
358 | ||
359 | qdir = opendir ((char *) zdir); | |
360 | if (qdir == NULL) | |
361 | { | |
362 | if (errno != ENOENT) | |
363 | ulog (LOG_ERROR, "opendir (%s): %s", zdir, strerror (errno)); | |
364 | return FALSE; | |
365 | } | |
366 | ||
367 | chad = cSwork_files; | |
368 | callocated = cSwork_files; | |
369 | ||
370 | /* Sort the files we already know about so that we can check the new | |
371 | ones with bsearch. It would be faster to use a hash table, and | |
372 | the code should be probably be changed. The sort done at the end | |
373 | of this function does not suffice because it only includes the | |
374 | files added last time, and does not sort the entire array. Some | |
375 | (bad) qsort implementations are very slow when given a sorted | |
376 | array, which causes particularly bad effects here. */ | |
377 | if (chad > 0) | |
378 | qsort ((pointer) azSwork_files, chad, sizeof (char *), iswork_cmp); | |
379 | ||
380 | while ((qentry = readdir (qdir)) != NULL) | |
381 | { | |
382 | char bfilegrade; | |
383 | char *zname; | |
384 | ||
385 | zname = qentry->d_name; | |
386 | if (fswork_file (qsys->zname, qentry->d_name, &bfilegrade) | |
387 | && (azSwork_files == NULL | |
388 | || bsearch ((pointer) &zname, | |
389 | (pointer) azSwork_files, | |
390 | chad, sizeof (char *), | |
391 | iswork_cmp) == NULL)) | |
392 | { | |
393 | if (igradecmp (bgrade, bfilegrade) < 0) | |
394 | continue; | |
395 | ||
396 | DEBUG_MESSAGE1 (DEBUG_SPOOLDIR, | |
397 | "fsysdep_get_work_init: Found %s", | |
398 | qentry->d_name); | |
399 | ||
400 | if (cSwork_files >= callocated) | |
401 | { | |
402 | callocated += CWORKFILES; | |
403 | azSwork_files = | |
404 | (char **) xrealloc ((pointer) azSwork_files, | |
405 | callocated * sizeof (char *)); | |
406 | } | |
407 | ||
408 | azSwork_files[cSwork_files] = xstrdup (qentry->d_name); | |
409 | ++cSwork_files; | |
410 | } | |
411 | } | |
412 | ||
413 | closedir (qdir); | |
414 | ||
415 | /* Sorting the files alphabetically will get the grades in the | |
416 | right order, since all the file prefixes are the same. */ | |
417 | ||
418 | if (cSwork_files > chad) | |
419 | qsort ((pointer) (azSwork_files + chad), cSwork_files - chad, | |
420 | sizeof (char *), iswork_cmp); | |
421 | ||
422 | return TRUE; | |
423 | } | |
424 | ||
425 | /* Get the next work entry for a system. This must parse the next | |
426 | line in the next work file. The type of command is set into | |
427 | qcmd->bcmd; if there are no more commands we call | |
428 | fsysdep_get_work_init to rescan, in case any came in since the last | |
429 | call. If there are still no commands, qcmd->bcmd is set to 'H'. | |
430 | Each field in the structure is set to point to a spot in an | |
431 | malloced string. The only time we use the grade here is when | |
432 | calling fsysdep_get_work_init to rescan. */ | |
433 | ||
434 | boolean | |
435 | fsysdep_get_work (qsys, bgrade, qcmd) | |
436 | const struct ssysteminfo *qsys; | |
437 | int bgrade; | |
438 | struct scmd *qcmd; | |
439 | { | |
440 | const char *zdir; | |
441 | ||
442 | if (qSwork_file != NULL && qSwork_file->cdid >= qSwork_file->clines) | |
443 | qSwork_file = NULL; | |
444 | ||
445 | if (azSwork_files == NULL) | |
446 | { | |
447 | qcmd->bcmd = 'H'; | |
448 | return TRUE; | |
449 | } | |
450 | ||
451 | zdir = NULL; | |
452 | ||
453 | /* This loop continues until a line is returned. */ | |
454 | while (TRUE) | |
455 | { | |
456 | /* This loop continues until a file is opened and read in. */ | |
457 | while (qSwork_file == NULL) | |
458 | { | |
459 | FILE *e; | |
460 | struct ssfile *qfile; | |
461 | int iline, callocated; | |
462 | char *zline; | |
463 | const char *zname; | |
464 | ||
465 | /* Read all the lines of a command file into memory. */ | |
466 | ||
467 | do | |
468 | { | |
469 | if (iSwork_file >= cSwork_files) | |
470 | { | |
471 | /* Rescan the work directory. */ | |
472 | if (! fsysdep_get_work_init (qsys, bgrade)) | |
473 | return FALSE; | |
474 | if (iSwork_file >= cSwork_files) | |
475 | { | |
476 | qcmd->bcmd = 'H'; | |
477 | return TRUE; | |
478 | } | |
479 | } | |
480 | ||
481 | if (zdir == NULL) | |
482 | { | |
483 | zdir = zswork_directory (qsys->zname); | |
484 | if (zdir == NULL) | |
485 | return FALSE; | |
486 | } | |
487 | ||
488 | zname = zsappend (zdir, azSwork_files[iSwork_file]); | |
489 | ||
490 | ++iSwork_file; | |
491 | ||
492 | if (zname == NULL) | |
493 | return FALSE; | |
494 | ||
495 | e = fopen (zname, "r"); | |
496 | if (e == NULL) | |
497 | ulog (LOG_ERROR, "fopen (%s): %s", zname, | |
498 | strerror (errno)); | |
499 | } | |
500 | while (e == NULL); | |
501 | ||
502 | qfile = (struct ssfile *) xmalloc (sizeof (struct ssfile)); | |
503 | callocated = CFILELINES; | |
504 | iline = 0; | |
505 | ||
506 | while ((zline = zfgets (e, FALSE)) != NULL) | |
507 | { | |
508 | if (iline >= callocated) | |
509 | { | |
510 | /* The sizeof (struct ssfile) includes CFILELINES | |
511 | entries already, so using callocated * sizeof | |
512 | (struct ssline) will give us callocated * | |
513 | CFILELINES entries. */ | |
514 | qfile = | |
515 | ((struct ssfile *) | |
516 | xrealloc ((pointer) qfile, | |
517 | (sizeof (struct ssfile) + | |
518 | (callocated * sizeof (struct ssline))))); | |
519 | callocated += CFILELINES; | |
520 | } | |
521 | qfile->aslines[iline].zline = zline; | |
522 | qfile->aslines[iline].qfile = NULL; | |
523 | qfile->aslines[iline].ztemp = NULL; | |
524 | iline++; | |
525 | } | |
526 | ||
527 | if (fclose (e) != 0) | |
528 | ulog (LOG_ERROR, "fclose: %s", strerror (errno)); | |
529 | ||
530 | if (iline == 0) | |
531 | { | |
532 | /* There was nothing in the file; remove it and look | |
533 | for the next one. */ | |
534 | xfree ((pointer) qfile); | |
535 | if (remove (zname) != 0) | |
536 | ulog (LOG_ERROR, "remove (%s): %s", zname, | |
537 | strerror (errno)); | |
538 | } | |
539 | else | |
540 | { | |
541 | qfile->zfile = xstrdup (zname); | |
542 | qfile->clines = iline; | |
543 | qfile->cdid = 0; | |
544 | qSwork_file = qfile; | |
545 | } | |
546 | } | |
547 | ||
548 | /* This loop continues until all the lines from the current file | |
549 | are used up, or a line is returned. */ | |
550 | while (TRUE) | |
551 | { | |
552 | int iline; | |
553 | ||
554 | if (qSwork_file->cdid >= qSwork_file->clines) | |
555 | { | |
556 | /* We don't want to free qSwork_file here, since it must | |
557 | remain until all the lines have been completed. It | |
558 | is freed in fsysdep_did_work. */ | |
559 | qSwork_file = NULL; | |
560 | /* Go back to the main loop which finds another file. */ | |
561 | break; | |
562 | } | |
563 | ||
564 | iline = qSwork_file->cdid; | |
565 | ++qSwork_file->cdid; | |
566 | ||
567 | /* Now parse the line into a command. */ | |
568 | ||
569 | if (! fparse_cmd (qSwork_file->aslines[iline].zline, qcmd)) | |
570 | { | |
571 | ulog (LOG_ERROR, "Bad line in command file %s", | |
572 | qSwork_file->zfile); | |
573 | xfree ((pointer) qSwork_file->aslines[iline].zline); | |
574 | qSwork_file->aslines[iline].zline = NULL; | |
575 | continue; | |
576 | } | |
577 | ||
578 | if (qcmd->bcmd == 'S') | |
579 | { | |
580 | const char *zreal; | |
581 | ||
582 | zreal = zsysdep_spool_file_name (qsys, qcmd->ztemp); | |
583 | if (zreal == NULL) | |
584 | { | |
585 | xfree ((pointer) qSwork_file->aslines[iline].zline); | |
586 | qSwork_file->aslines[iline].zline = NULL; | |
587 | return FALSE; | |
588 | } | |
589 | ||
590 | qSwork_file->aslines[iline].ztemp = xstrdup (zreal); | |
591 | } | |
592 | ||
593 | qSwork_file->aslines[iline].qfile = qSwork_file; | |
594 | qcmd->pseq = (pointer)(&qSwork_file->aslines[iline]); | |
595 | ||
596 | return TRUE; | |
597 | } | |
598 | } | |
599 | } | |
600 | ||
601 | /* When a command has been complete, fsysdep_did_work is called. The | |
602 | sequence entry was set above to be the address of an aslines | |
603 | structure whose pfile entry points to the ssfile corresponding to | |
604 | this file. We can then check whether all the lines have been | |
605 | completed (they will have been if the pfile entry is NULL) and | |
606 | remove the file if they have been. This means that we only remove | |
607 | a command file if we manage to complete every transfer it specifies | |
608 | in a single UUCP session. I don't know if this is how regular UUCP | |
609 | works. */ | |
610 | ||
611 | boolean | |
612 | fsysdep_did_work (pseq) | |
613 | pointer pseq; | |
614 | { | |
615 | struct ssfile *qfile; | |
616 | struct ssline *qline; | |
617 | int i; | |
618 | ||
619 | qline = (struct ssline *) pseq; | |
620 | ||
621 | xfree ((pointer) qline->zline); | |
622 | qline->zline = NULL; | |
623 | ||
624 | qfile = qline->qfile; | |
625 | qline->qfile = NULL; | |
626 | ||
627 | /* Remove the temporary file, if there is one. It really doesn't | |
628 | matter if this fails, and not checking the return value lets us | |
629 | attempt to remove D.0 or whatever an unused temporary file is | |
630 | called without complaining. */ | |
631 | if (qline->ztemp != NULL) | |
632 | (void) remove (qline->ztemp); | |
633 | ||
634 | /* If not all the lines have been returned from bsysdep_get_work, | |
635 | we can't remove the file yet. */ | |
636 | if (qfile->cdid < qfile->clines) | |
637 | return TRUE; | |
638 | ||
639 | /* See whether all the commands have been completed. */ | |
640 | for (i = 0; i < qfile->clines; i++) | |
641 | if (qfile->aslines[i].qfile != NULL) | |
642 | return TRUE; | |
643 | ||
644 | /* All commands have finished. */ | |
645 | if (remove (qfile->zfile) != 0) | |
646 | { | |
647 | ulog (LOG_ERROR, "remove (%s): %s", qfile->zfile, | |
648 | strerror (errno)); | |
649 | return FALSE; | |
650 | } | |
651 | ||
652 | xfree ((pointer) qfile->zfile); | |
653 | xfree ((pointer) qfile); | |
654 | ||
655 | if (qfile == qSwork_file) | |
656 | qSwork_file = NULL; | |
657 | ||
658 | return TRUE; | |
659 | } | |
660 | ||
661 | /* Free up the results of a work scan, when we're done with this | |
662 | system. */ | |
663 | ||
664 | /*ARGSUSED*/ | |
665 | void | |
666 | usysdep_get_work_free (qsys) | |
667 | const struct ssysteminfo *qsys; | |
668 | { | |
669 | if (azSwork_files != NULL) | |
670 | { | |
671 | int i; | |
672 | ||
673 | for (i = 0; i < cSwork_files; i++) | |
674 | xfree ((pointer) azSwork_files[i]); | |
675 | xfree ((pointer) azSwork_files); | |
676 | azSwork_files = NULL; | |
677 | cSwork_files = 0; | |
678 | iSwork_file = 0; | |
679 | } | |
680 | if (qSwork_file != NULL) | |
681 | { | |
682 | int i; | |
683 | ||
684 | xfree ((pointer) qSwork_file->zfile); | |
685 | for (i = 0; i < qSwork_file->cdid; i++) | |
686 | { | |
687 | xfree ((pointer) qSwork_file->aslines[i].zline); | |
688 | xfree ((pointer) qSwork_file->aslines[i].ztemp); | |
689 | } | |
690 | for (i = qSwork_file->cdid; i < qSwork_file->clines; i++) | |
691 | xfree ((pointer) qSwork_file->aslines[i].zline); | |
692 | xfree ((pointer) qSwork_file); | |
693 | qSwork_file = NULL; | |
694 | } | |
695 | } | |
696 | \f | |
697 | /* Save the temporary file used by a send command, and return an | |
698 | informative message to mail to the requestor. This is called when | |
699 | a file transfer failed, to make sure that the potentially valuable | |
700 | file is not completely lost. */ | |
701 | ||
702 | const char * | |
703 | zsysdep_save_temp_file (pseq) | |
704 | pointer pseq; | |
705 | { | |
706 | struct ssline *qline = (struct ssline *) pseq; | |
707 | char *zto, *zslash; | |
708 | int cwant; | |
709 | static char *zbuf; | |
710 | static int cbuf; | |
711 | ||
712 | if (! fsysdep_file_exists (qline->ztemp)) | |
713 | return NULL; | |
714 | ||
715 | zslash = strrchr (qline->ztemp, '/'); | |
716 | if (zslash == NULL) | |
717 | zslash = qline->ztemp; | |
718 | else | |
719 | ++zslash; | |
720 | ||
721 | zto = (char *) alloca (sizeof PRESERVEDIR + 1 + strlen (zslash)); | |
722 | sprintf (zto, "%s/%s", PRESERVEDIR, zslash); | |
723 | ||
724 | /* We must make sure that the PRESERVEDIR directory exists, since | |
725 | fsysdep_move_file won't create it for us. */ | |
726 | ||
727 | if (! fsdirectory_exists (PRESERVEDIR)) | |
728 | { | |
729 | if (mkdir (PRESERVEDIR, IDIRECTORY_MODE) != 0) | |
730 | { | |
731 | ulog (LOG_ERROR, "mkdir (%s): %s", PRESERVEDIR, | |
732 | strerror (errno)); | |
733 | return "Could not create preservation directory"; | |
734 | } | |
735 | } | |
736 | ||
737 | if (! fsysdep_move_file (qline->ztemp, zto, 0, FALSE, | |
738 | (const char *) NULL)) | |
739 | return "Could not move file to preservation directory"; | |
740 | ||
741 | cwant = sizeof "File saved as\n\t" + strlen (zSpooldir) + 1 + strlen (zto); | |
742 | if (cwant > cbuf) | |
743 | { | |
744 | zbuf = (char *) xrealloc ((pointer) zbuf, cwant); | |
745 | cbuf = cwant; | |
746 | } | |
747 | ||
748 | sprintf (zbuf, "File saved as\n\t%s/%s", zSpooldir, zto); | |
749 | return zbuf; | |
750 | } | |
751 | \f | |
752 | /* Get the jobid of a work file. This is needed by uustat. */ | |
753 | ||
754 | const char * | |
755 | zsysdep_jobid (qsys, pseq) | |
756 | const struct ssysteminfo *qsys; | |
757 | pointer pseq; | |
758 | { | |
759 | return zsfile_to_jobid (qsys, ((struct ssline *) pseq)->qfile->zfile); | |
760 | } | |
761 | \f | |
762 | /* | |
763 | Local variables: | |
764 | mode:c | |
765 | End: | |
766 | */ |