summaryrefslogtreecommitdiffstats
path: root/gnu/libexec/uucp/libunix/spool.c
blob: b14b5605a09341778182a6ddac00a6bb7d98ebcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
/* spool.c
   Find a file in the spool directory.

   Copyright (C) 1991, 1992, 1993 Ian Lance Taylor

   This file is part of the Taylor UUCP package.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

   The author of the program may be contacted at ian@airs.com or
   c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
   */

#include "uucp.h"

#if USE_RCS_ID
const char spool_rcsid[] = "$FreeBSD$";
#endif

#include "uudefs.h"
#include "sysdep.h"
#include "system.h"

/* There are several types of files that go in the spool directory,
   and they go into various different subdirectories.  Whenever the
   system name LOCAL appears below, it means whatever the local system
   name is.

   Command files
   These contain instructions for uucico indicating what files to transfer
   to and from what systems.  Each line of a work file is a command
   beginning with S, R, X, or E.
   #if ! SPOOLDIR_TAYLOR
   They are named C.ssssssgqqqq, where ssssss is the system name to
   transfer to or from, g is the grade and qqqq is the sequence number.
   #if SPOOLDIR_V2
   They are put in the spool directory.
   #elif SPOOLDIR_BSD42 || SPOOLDIR_BSD43
   They are put in the directory "C.".
   #elif SPOOLDIR_HDB
   They are put in a directory named for the system for which they were
   created.
   #elif SPOOLDIR_ULTRIX
   If the directory sys/ssssss exists, they are put in the directory
   sys/ssssss/C; otherwise, they are put in the directory sys/DEFAULT/C.
   #elif SPOOLDIR_SVR4
   They are put in the directory sys/g, where sys is the system name
   and g is the grade.
   #endif
   #else SPOOLDIR_TAYLOR
   They are named C.gqqqq, where g is the grade and qqqq is the
   sequence number, and are placed in the directory ssssss/C. where
   ssssss is the system name to transfer to or from.  The sequence
   number for a C. file is actually a long string; it is not based on
   the sequence number file, but is generated via a process which
   attempts to produce a unique string each time it is run.
   #endif

   Data files
   There are files to be transferred to other systems.  Some files to
   be transferred may not be in the spool directory, depending on how
   uucp was invoked.  Data files are named in work files, so it is
   never necessary to look at them directly (except to remove old ones);
   it is only necessary to create them.  These means that the many
   variations in naming are inconsequential.
   #if ! SPOOLDIR_TAYLOR
   They are named D.ssssssgqqqq where ssssss is a system name (which
   may be LOCAL for locally initiated transfers or a remote system for
   remotely initiated transfers, except that HDB appears to use the
   system the file is being transferred to), g is the grade and qqqq
   is the sequence number.  Some systems use a trailing subjob ID
   number, but we currently do not.  The grade is not important, and
   some systems do not use it.  If the data file is to become an
   execution file on another system the grade (if present) will be
   'X'.  Otherwise Ultrix appears to use 'b'; the uux included with
   gnuucp 1.0 appears to use 'S'; SCO does not appear to use a grade,
   although it does use a subjob ID number.
   #if SPOOLDIR_V2
   They are put in the spool directory.
   #elif SPOOLDIR_BSD42
   If the name begins with D.LOCAL, the file is put in the directory
   D.LOCAL.  Otherwise the file is put in the directory D..
   #elif SPOOLDIR_BSD43
   If the name begins with D.LOCALX, the file is put in the directory
   D.LOCALX.  Otherwise if the name begins with D.LOCAL, the file is
   put in the directory D.LOCAL Otherwise the file is put in the
   directory "D.".
   #elif SPOOLDIR_HDB
   They are put in a directory named for the system for which they
   were created.
   #elif SPOOLDIR_ULTRIX
   Say the file is being transferred to system REMOTE.  If the
   directory sys/REMOTE exists, then if the file begins with D.LOCALX
   it is put in sys/REMOTE/D.LOCALX, if the file begins with D.LOCAL
   it is put in sys/REMOTE/D.LOCAL, and otherwise it is put in
   "sys/REMOTE/D.".  If the directory sys/REMOTE does not exist, the
   same applies except that DEFAULT is used instead of REMOTE.
   #elif SPOOLDIR_SVR4
   They are put in the directory sys/g, where sys is the system name
   and g is the grade.
   #endif
   #else SPOOLDIR_TAYLOR
   If the file is to become an executable file on another system it is
   named D.Xqqqq, otherwise it is named D.qqqq where in both cases
   qqqq is a sequence number.  If the corresponding C. file is in
   directory ssssss/C., a D.X file is placed in ssssss/D.X and a D.
   file is placed in "ssssss/D.".
   #endif

   Execute files
   These are files that specify programs to be executed.  They are
   created by uux, perhaps as run on another system.  These names are
   important, because a file transfer done to an execute file name
   causes an execution to occur.  The name is X.ssssssgqqqq, where
   ssssss is the requesting system, g is the grade, and qqqq is a
   sequence number.
   #if SPOOLDIR_V2 || SPOOLDIR_BSD42
   These files are placed in the spool directory.
   #elif SPOOLDIR_BSD43
   These files are placed in the directory X..
   #elif SPOOLDIR_HDB || SPOOLDIR_SVR4
   These files are put in a directory named for the system for which
   the files were created.
   #elif SPOOLDIR_ULTRIX
   If there is a spool directory (sys/ssssss) for the requesting
   system, the files are placed in sys/ssssss/X.; otherwise, the files
   are placed in "sys/DEFAULT/X.".
   #elif SPOOLDIR_TAYLOR
   The system name is automatically truncated to seven characters when
   a file is created.  The files are placed in the subdirectory X. of
   a directory named for the system for which the files were created.
   #endif

   Temporary receive files
   These are used when receiving files from another system.  They are
   later renamed to the final name.  The actual name is unimportant,
   although it generally begins with TM..
   #if SPOOLDIR_V2 || SPOOLDIR_BSD42
   These files are placed in the spool directory.
   #elif SPOOLDIR_BSD43 || SPOOLDIR_ULTRIX || SPOOLDIR_TAYLOR
   These files are placed in the directory .Temp.
   #elif SPOOLDIR_HDB || SPOOLDIR_SVR4
   These files are placed in a directory named for the system for
   which they were created.
   #endif

   System status files
   These are used to record when the last call was made to the system
   and what the status is.  They are used to prevent frequent recalls
   to a system which is not responding.  I will not attempt to
   recreate the format of these exactly, since they are not all that
   important.  They will be put in the directory .Status, as in HDB,
   and they use the system name as the name of the file.

   Sequence file
   This is used to generate a unique sequence number.  It contains an
   ASCII number.
   #if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43
   The file is named SEQF and is kept in the spool directory.
   #elif SPOOLDIR_HDB || SPOOLDIR_SVR4
   A separate sequence file is kept for each system in the directory
   .Sequence with the name of the system.
   #elif SPOOLDIR_ULTRIX
   Each system with a file sys/ssssss has a sequence file in
   sys/ssssss/.SEQF.  Other systems use sys/DEFAULT/.SEQF.
   #else SPOOLDIR_TAYLOR
   A sequence file named SEQF is kept in the directory ssssss for each
   system.
   #endif
   */

/* Given the name of a file as specified in a UUCP command, and the
   system for which this file has been created, return where to find
   it in the spool directory.  The file will begin with C. (a command
   file), D. (a data file) or X. (an execution file).  Under
   SPOOLDIR_SVR4 we need to know the grade of the file created by the
   local system; this is the bgrade argument, which is -1 for a file
   from a remote system.  */

/*ARGSUSED*/
char *
zsfind_file (zsimple, zsystem, bgrade)
     const char *zsimple;
     const char *zsystem;
     int bgrade;
{
  /* zsysdep_spool_commands calls this with TMPXXX which we must treat
     as a C. file.  */
  if ((zsimple[0] != 'T'
       || zsimple[1] != 'M'
       || zsimple[2] != 'P')
      && ! fspool_file (zsimple))
    {
      ulog (LOG_ERROR, "Unrecognized file name %s", zsimple);
      return NULL;
    }

#if ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 && ! SPOOLDIR_TAYLOR
  if (*zsimple == 'X')
    {
      static char *zbuf;
      static size_t cbuf;
      size_t clen, cwant;

      /* Files beginning with X. are execute files.  It is important
	 for security reasons that we know the system which created
	 the X. file.  This is easy under SPOOLDIR_HDB or
	 SPOOLDIR_SVR4 SPOOLDIR_TAYLOR, because the file will be in a
	 directory named for the system.  Under other schemes, we must
	 get the system name from the X. file name.  To prevent
	 security violations, we set the system name directly here;
	 this will cause problems if the maximum file name length is
	 too short, but hopefully no problem will occur since any
	 System V systems will be using HDB or SVR4 or TAYLOR.  */
      clen = strlen (zsimple);
      if (clen < 5)
	{
	  ulog (LOG_ERROR, "Bad file name (too short) %s", zsimple);
	  return NULL;
	}
      cwant = strlen (zsystem) + 8;
      if (cwant > cbuf)
	{
	  zbuf = (char *) xrealloc ((pointer) zbuf, cwant);
	  cbuf = cwant;
	}
      sprintf (zbuf, "X.%s%s", zsystem, zsimple + clen - 5);
      zsimple = zbuf;
    }
#endif /* ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 && ! SPOOLDIR_TAYLOR */

#if SPOOLDIR_V2
  /* V2 never uses subdirectories.  */
  return zbufcpy (zsimple);
#endif /* SPOOLDIR_V2 */

#if SPOOLDIR_HDB
  /* HDB always uses the system name as a directory.  */
  return zsysdep_in_dir (zsystem, zsimple);
#endif /* SPOOLDIR_HDB */

#if SPOOLDIR_SVR4
  /* SVR4 uses grade directories within the system directory for local
     command and data files.  */
  if (bgrade < 0 || *zsimple == 'X')
    return zsysdep_in_dir (zsystem, zsimple);
  else
    {
      char abgrade[2];

      abgrade[0] = bgrade;
      abgrade[1] = '\0';
      return zsappend3 (zsystem, abgrade, zsimple);
    }
#endif /* SPOOLDIR_SVR4 */

#if ! SPOOLDIR_V2 && ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4
  switch (*zsimple)
    {
    case 'C':
    case 'T':
#if SPOOLDIR_BSD42 || SPOOLDIR_BSD43
      return zsysdep_in_dir ("C.", zsimple);
#endif /* SPOOLDIR_BSD42 || SPOOLDIR_BSD43 */
#if SPOOLDIR_ULTRIX
      if (fsultrix_has_spool (zsystem))
	return zsappend4 ("sys", zsystem, "C.", zsimple);
      else
	return zsappend4 ("sys", "DEFAULT", "C.", zsimple);
#endif /* SPOOLDIR_ULTRIX */
#if SPOOLDIR_TAYLOR
      return zsappend3 (zsystem, "C.", zsimple);
#endif /* SPOOLDIR_TAYLOR */

    case 'D':
#if SPOOLDIR_BSD42 || SPOOLDIR_BSD43
      {
	size_t c;
	boolean ftruncated;
      
	/* D.LOCAL in D.LOCAL/, others in D./.  If BSD43, D.LOCALX in
	   D.LOCALX/.  */
	ftruncated = TRUE;
	if (strncmp (zsimple + 2, zSlocalname, strlen (zSlocalname)) == 0)
	  {
	    c = strlen (zSlocalname);
	    ftruncated = FALSE;
	  }
	else if (strncmp (zsimple + 2, zSlocalname, 7) == 0)
	  c = 7;
	else if (strncmp (zsimple + 2, zSlocalname, 6) == 0)
	  c = 6;
	else
	  c = 0;
#if SPOOLDIR_BSD43
	if (c > 0 && zsimple[c + 2] == 'X')
	  c++;
#endif /* SPOOLDIR_BSD43 */
	if (c > 0)
	  {
	    char *zalloc;

	    zalloc = zbufalc (c + 3);
	    memcpy (zalloc, zsimple, c + 2);
	    zalloc[c + 2] = '\0';

	    /* If we truncated the system name, and there is no existing
	       directory with the truncated name, then just use D..  */
	    if (! ftruncated || fsysdep_directory (zalloc))
	      {
		char *zret;

		zret = zsysdep_in_dir (zalloc, zsimple);
		ubuffree (zalloc);
		return zret;
	      }
	    ubuffree (zalloc);
	  }
	return zsysdep_in_dir ("D.", zsimple);
      }
#endif /* SPOOLDIR_BSD42 || SPOOLDIR_BSD43 */
#if SPOOLDIR_ULTRIX
      {
	size_t c;
	boolean ftruncated;
	char *zfree;
	const char *zdir;
	char *zret;
      
	/* D.LOCALX in D.LOCALX/, D.LOCAL in D.LOCAL/, others in D./.  */
	ftruncated = TRUE;
	if (strncmp (zsimple + 2, zSlocalname, strlen (zSlocalname)) == 0)
	  {
	    c = strlen (zSlocalname);
	    ftruncated = FALSE;
	  }
	else if (strncmp (zsimple + 2, zSlocalname, 7) == 0)
	  c = 7;
	else if (strncmp (zsimple + 2, zSlocalname, 6) == 0)
	  c = 6;
	else
	  c = 0;
	if (c > 0 && zsimple[c + 2] == 'X')
	  ++c;
	if (c > 0)
	  {
	    zfree = zbufalc (c + 3);
	    memcpy (zfree, zsimple, c + 2);
	    zfree[c + 2] = '\0';
	    zdir = zfree;

	    /* If we truncated the name, and there is no directory for
	       the truncated name, then don't use it.  */
	    if (ftruncated)
	      {
		char *zlook;

		zlook = zsappend3 ("sys",
				   (fsultrix_has_spool (zsystem)
				    ? zsystem
				    : "DEFAULT"),
				   zdir);
		if (! fsysdep_directory (zlook))
		  zdir = "D.";
		ubuffree (zlook);
	      }
	  }
	else
	  {
	    zfree = NULL;
	    zdir = "D.";
	  }
      
	zret = zsappend4 ("sys",
			  (fsultrix_has_spool (zsystem)
			   ? zsystem
			   : "DEFAULT"),
			  zdir,
			  zsimple);
	ubuffree (zfree);
	return zret;
      }
#endif /* SPOOLDIR_ULTRIX */
#if SPOOLDIR_TAYLOR
      if (zsimple[2] == 'X')
	return zsappend3 (zsystem, "D.X", zsimple);
      else
	return zsappend3 (zsystem, "D.", zsimple);
#endif /* SPOOLDIR_TAYLOR */


    case 'X':
#if SPOOLDIR_BSD42
      return zbufcpy (zsimple);
#endif
#if SPOOLDIR_BSD43
      return zsysdep_in_dir ("X.", zsimple);
#endif
#if SPOOLDIR_ULTRIX
      return zsappend4 ("sys",
			(fsultrix_has_spool (zsystem)
			 ? zsystem
			 : "DEFAULT"),
			"X.",
			zsimple);
#endif
#if SPOOLDIR_TAYLOR
      return zsappend3 (zsystem, "X.", zsimple);
#endif
    }

  /* This is just to avoid warnings; it will never be executed.  */
  return NULL;
#endif /* ! SPOOLDIR_V2 && ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 */
}
OpenPOWER on IntegriCloud