This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / gnu / libexec / uucp / uucico / xcmd.c
CommitLineData
41c799d4
C
1/* xcmd.c
2 Routines to handle work requests.
3
4 Copyright (C) 1991, 1992 Ian Lance Taylor
5
6 This file is part of the Taylor UUCP package.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 The author of the program may be contacted at ian@airs.com or
23 c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24 */
25
26#include "uucp.h"
27
28#if USE_RCS_ID
29const char xcmd_rcsid[] = "$Id: xcmd.c,v 1.1 1993/08/04 19:36:35 jtc Exp $";
30#endif
31
32#include <errno.h>
33
34#include "uudefs.h"
35#include "uuconf.h"
36#include "system.h"
37#include "prot.h"
38#include "trans.h"
39\f
40/* Local functions. */
41
42static boolean flocal_xcmd_request P((struct stransfer *qtrans,
43 struct sdaemon *qdaemon));
44static boolean flocal_xcmd_await_reply P((struct stransfer *qtrans,
45 struct sdaemon *qdaemon,
46 const char *zdata, size_t cdata));
47static boolean fremote_xcmd_reply P((struct stransfer *qtrans,
48 struct sdaemon *qdaemon));
49\f
50/* Handle a local work request. We just set up the request for
51 transmission. */
52
53boolean
54flocal_xcmd_init (qdaemon, qcmd)
55 struct sdaemon *qdaemon;
56 struct scmd *qcmd;
57{
58 struct stransfer *qtrans;
59
60 qtrans = qtransalc (qcmd);
61 qtrans->psendfn = flocal_xcmd_request;
62
63 return fqueue_local (qdaemon, qtrans);
64}
65
66/* Send the execution request to the remote system. */
67
68static boolean
69flocal_xcmd_request (qtrans, qdaemon)
70 struct stransfer *qtrans;
71 struct sdaemon *qdaemon;
72{
73 size_t clen;
74 char *zsend;
75 boolean fret;
76
77 ulog (LOG_NORMAL, "Requesting work: %s to %s", qtrans->s.zfrom,
78 qtrans->s.zto);
79
80 /* We send the string
81 X from to user options
82 We put a dash in front of options. */
83 clen = (strlen (qtrans->s.zfrom) + strlen (qtrans->s.zto)
84 + strlen (qtrans->s.zuser) + strlen (qtrans->s.zoptions) + 7);
85 zsend = zbufalc (clen);
86 sprintf (zsend, "X %s %s %s -%s", qtrans->s.zfrom, qtrans->s.zto,
87 qtrans->s.zuser, qtrans->s.zoptions);
88
89 fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
90 qtrans->iremote);
91 ubuffree (zsend);
92 if (! fret)
93 {
94 utransfree (qtrans);
95 return FALSE;
96 }
97
98 qtrans->fcmd = TRUE;
99 qtrans->precfn = flocal_xcmd_await_reply;
100
101 return fqueue_receive (qdaemon, qtrans);
102}
103
104/* Get a reply to an execution request from the remote system. */
105
106/*ARGSUSED*/
107static boolean
108flocal_xcmd_await_reply (qtrans, qdaemon, zdata, cdata)
109 struct stransfer *qtrans;
110 struct sdaemon *qdaemon;
111 const char *zdata;
112 size_t cdata;
113{
114 qtrans->precfn = NULL;
115
116 if (zdata[0] != 'X'
117 || (zdata[1] != 'Y' && zdata[1] != 'N'))
118 {
119 ulog (LOG_ERROR, "Bad response to work request");
120 utransfree (qtrans);
121 return FALSE;
122 }
123
124 if (zdata[1] == 'N')
125 {
126 ulog (LOG_ERROR, "%s: work request denied", qtrans->s.zfrom);
127 (void) fmail_transfer (FALSE, qtrans->s.zuser, (const char *) NULL,
128 "work request denied",
129 qtrans->s.zfrom, qdaemon->qsys->uuconf_zname,
130 qtrans->s.zto, (const char *) NULL,
131 (const char *) NULL);
132 }
133
134 (void) fsysdep_did_work (qtrans->s.pseq);
135 utransfree (qtrans);
136
137 return TRUE;
138}
139\f
140/* Handle a remote work request. This just queues up the requests for
141 later processing. */
142
143boolean
144fremote_xcmd_init (qdaemon, qcmd, iremote)
145 struct sdaemon *qdaemon;
146 struct scmd *qcmd;
147 int iremote;
148{
149 const struct uuconf_system *qsys;
150 const char *zexclam;
151 const struct uuconf_system *qdestsys;
152 struct uuconf_system sdestsys;
153 char *zdestfile;
154 boolean fmkdirs;
155 struct stransfer *qtrans;
156 char *zuser;
157 char aboptions[5];
158 char *zfrom;
159 boolean fret;
160 char *zfile;
161
162 ulog (LOG_NORMAL, "Work requested: %s to %s", qcmd->zfrom,
163 qcmd->zto);
164
165 qsys = qdaemon->qsys;
166
167 zexclam = strchr (qcmd->zto, '!');
168 if (zexclam == NULL
169 || zexclam == qcmd->zto
170 || strncmp (qdaemon->zlocalname, qcmd->zto,
171 (size_t) (zexclam - qcmd->zto)) == 0)
172 {
173 const char *zconst;
174
175 /* The files are supposed to be copied to the local system. */
176 qdestsys = NULL;
177 if (zexclam == NULL)
178 zconst = qcmd->zto;
179 else
180 zconst = zexclam + 1;
181
182 zdestfile = zsysdep_local_file (zconst, qsys->uuconf_zpubdir);
183 if (zdestfile == NULL)
184 return FALSE;
185
186 zuser = NULL;
187 fmkdirs = strchr (qcmd->zoptions, 'f') != NULL;
188 }
189 else
190 {
191 size_t clen;
192 char *zcopy;
193 int iuuconf;
194 char *zoptions;
195
196 clen = zexclam - qcmd->zto;
197 zcopy = zbufalc (clen + 1);
198 memcpy (zcopy, qcmd->zto, clen);
199 zcopy[clen] = '\0';
200
201 iuuconf = uuconf_system_info (qdaemon->puuconf, zcopy, &sdestsys);
202 if (iuuconf == UUCONF_NOT_FOUND)
203 {
204 if (! funknown_system (qdaemon->puuconf, zcopy, &sdestsys))
205 {
206 ulog (LOG_ERROR, "%s: System not found", zcopy);
207 ubuffree (zcopy);
208 qtrans = qtransalc (qcmd);
209 qtrans->psendfn = fremote_xcmd_reply;
210 qtrans->pinfo = (pointer) "XN";
211 qtrans->iremote = iremote;
212 return fqueue_remote (qdaemon, qtrans);
213 }
214 }
215 else if (iuuconf != UUCONF_SUCCESS)
216 {
217 ulog_uuconf (LOG_ERROR, qdaemon->puuconf, iuuconf);
218 ubuffree (zcopy);
219 return FALSE;
220 }
221
222 ubuffree (zcopy);
223
224 qdestsys = &sdestsys;
225 zdestfile = zbufcpy (zexclam + 1);
226
227 zuser = zbufalc (strlen (qdestsys->uuconf_zname)
228 + strlen (qcmd->zuser) + sizeof "!");
229 sprintf (zuser, "%s!%s", qdestsys->uuconf_zname, qcmd->zuser);
230 zoptions = aboptions;
231 *zoptions++ = 'C';
232 if (strchr (qcmd->zoptions, 'd') != NULL)
233 *zoptions++ = 'd';
234 if (strchr (qcmd->zoptions, 'm') != NULL)
235 *zoptions++ = 'm';
236 *zoptions = '\0';
237 fmkdirs = TRUE;
238 }
239
240 /* At this point we prepare to confirm the remote request. We could
241 actually fork here and let the child spool up the requests. */
242 qtrans = qtransalc (qcmd);
243 qtrans->psendfn = fremote_xcmd_reply;
244 qtrans->pinfo = (pointer) "XY";
245 qtrans->iremote = iremote;
246 if (! fqueue_remote (qdaemon, qtrans))
247 {
248 ubuffree (zdestfile);
249 ubuffree (zuser);
250 return FALSE;
251 }
252
253 /* Now we have to process each source file. The source
254 specification may or may use wildcards. */
255 zfrom = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir);
256 if (zfrom == NULL)
257 {
258 ubuffree (zdestfile);
259 ubuffree (zuser);
260 return FALSE;
261 }
262
263 if (! fsysdep_wildcard_start (zfrom))
264 {
265 ubuffree (zfrom);
266 ubuffree (zdestfile);
267 ubuffree (zuser);
268 return FALSE;
269 }
270
271 fret = TRUE;
272
273 while ((zfile = zsysdep_wildcard (zfrom)) != NULL)
274 {
275 char *zto;
276 char abtname[CFILE_NAME_LEN];
277
278 if (! fsysdep_file_exists (zfile))
279 {
280 ulog (LOG_ERROR, "%s: no such file", zfile);
281 continue;
282 }
283
284 /* Make sure the remote system is permitted to read the
285 specified file. */
286 if (! fin_directory_list (zfile, qsys->uuconf_pzremote_send,
287 qsys->uuconf_zpubdir, TRUE, TRUE,
288 (const char *) NULL))
289 {
290 ulog (LOG_ERROR, "%s: not permitted to send", zfile);
291 break;
292 }
293
294 if (qdestsys != NULL)
295 {
296 /* We really should get the original grade here. */
297 zto = zsysdep_data_file_name (qdestsys, qdaemon->zlocalname,
298 BDEFAULT_UUCP_GRADE, FALSE,
299 abtname, (char *) NULL,
300 (char *) NULL);
301 if (zto == NULL)
302 {
303 fret = FALSE;
304 break;
305 }
306 }
307 else
308 {
309 zto = zsysdep_add_base (zdestfile, zfile);
310 if (zto == NULL)
311 {
312 fret = FALSE;
313 break;
314 }
315 /* We only accept a local destination if the remote system
316 has the right to create files there. */
317 if (! fin_directory_list (zto, qsys->uuconf_pzremote_receive,
318 qsys->uuconf_zpubdir, TRUE, FALSE,
319 (const char *) NULL))
320 {
321 ulog (LOG_ERROR, "%s: not permitted to receive", zto);
322 ubuffree (zto);
323 break;
324 }
325 }
326
327 /* Copy the file either to the final destination or to the
328 spool directory. */
329 if (! fcopy_file (zfile, zto, qdestsys == NULL, fmkdirs))
330 {
331 ubuffree (zto);
332 break;
333 }
334
335 ubuffree (zto);
336
337 /* If there is a destination system, queue it up. */
338 if (qdestsys != NULL)
339 {
340 struct scmd ssend;
341 char *zjobid;
342
343 ssend.bcmd = 'S';
344 ssend.pseq = NULL;
345 ssend.zfrom = zfile;
346 ssend.zto = zdestfile;
347 ssend.zuser = zuser;
348 ssend.zoptions = aboptions;
349 ssend.ztemp = abtname;
350 ssend.imode = ixsysdep_file_mode (zfile);
351 ssend.znotify = "";
352 ssend.cbytes = -1;
353 ssend.zcmd = NULL;
354 ssend.ipos = 0;
355
356 zjobid = zsysdep_spool_commands (qdestsys, BDEFAULT_UUCP_GRADE,
357 1, &ssend);
358 if (zjobid == NULL)
359 break;
360 ubuffree (zjobid);
361 }
362
363 ubuffree (zfile);
364 }
365
366 if (zfile != NULL)
367 ubuffree (zfile);
368
369 (void) fsysdep_wildcard_end ();
370
371 ubuffree (zdestfile);
372 if (qdestsys != NULL)
373 (void) uuconf_system_free (qdaemon->puuconf, &sdestsys);
374
375 ubuffree (zfrom);
376 ubuffree (zuser);
377
378 return fret;
379}
380
381/* Reply to a remote work request. */
382
383static boolean
384fremote_xcmd_reply (qtrans, qdaemon)
385 struct stransfer *qtrans;
386 struct sdaemon *qdaemon;
387{
388 boolean fret;
389
390 fret = (*qdaemon->qproto->pfsendcmd) (qdaemon,
391 (const char *) qtrans->pinfo,
392 qtrans->ilocal,
393 qtrans->iremote);
394 utransfree (qtrans);
395 return fret;
396}