9303 chat: this statement may fall through
[unleashed.git] / usr / src / cmd / bnu / cntrl.c
blob50b968cde454ac264a9dba5e35a7506a06afd2b4
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 #include "uucp.h"
32 #include "log.h"
34 void notify(), lnotify(), unlinkdf(), arrived();
35 static void stmesg();
36 static int nospace();
38 struct Proto {
39 char P_id;
40 int (*P_turnon)();
41 int (*P_rdmsg)();
42 int (*P_wrmsg)();
43 int (*P_rddata)();
44 int (*P_wrdata)();
45 int (*P_turnoff)();
48 extern char _Protocol[];
49 extern char *findProto();
51 extern char uuxqtarg[];
53 extern int gturnon(), gturnoff();
54 extern int grdmsg(), grddata();
55 extern int gwrmsg(), gwrdata();
57 extern int wmesg(), rmesg(), expfile(), putinpub(), stptcl();
58 extern void setline(), TMname(), cleanup(), pfEndfile(), statlog(), mailst();
60 #ifdef D_PROTOCOL
61 extern int dturnon(), dturnoff();
62 extern int drdmsg(), drddata();
63 extern int dwrmsg(), dwrdata();
64 #endif /* D_PROTOCOL */
66 #ifdef X_PROTOCOL
67 extern int xturnon(), xturnoff();
68 extern int xrdmsg(), xrddata();
69 extern int xwrmsg(), xwrdata();
70 #endif /* X_PROTOCOL */
72 #ifdef E_PROTOCOL
73 extern int eturnon(), eturnoff();
74 extern int erdmsg(), erddata();
75 extern int ewrmsg(), ewrdata();
76 extern int trdmsg(), twrmsg();
77 extern int trddata(), twrdata();
78 #endif /* E_PROTOCOL */
80 #ifdef F_PROTOCOL
81 extern int fturnon(), fturnoff();
82 extern int frdmsg(), frddata();
83 extern int fwrmsg(), fwrdata();
84 #endif /* F_PROTOCOL */
86 extern int imsg();
87 extern int omsg();
88 extern int turnoff();
89 extern long strtol();
91 struct Proto Ptbl[]={
92 {'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff},
93 {'G', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff},
95 #ifdef E_PROTOCOL
96 {'e', eturnon, erdmsg, ewrmsg, erddata, ewrdata, eturnoff},
97 {'t', eturnon, trdmsg, twrmsg, trddata, twrdata, eturnoff},
98 #endif /* E_PROTOCOL */
100 #ifdef D_PROTOCOL
101 {'d', dturnon, drdmsg, dwrmsg, drddata, dwrdata, dturnoff},
102 #endif /* D_PROTOCOL */
104 #ifdef X_PROTOCOL
105 {'x', xturnon, xrdmsg, xwrmsg, xrddata, xwrdata, xturnoff},
106 #endif /* X_PROTOCOL */
108 #ifdef F_PROTOCOL
109 {'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff},
110 #endif /* F_PROTOCOL */
111 '\0'
114 #define VALIDSIZE sizeof(Ptbl)/sizeof(struct Proto)
116 int (*Rdmsg)()=imsg, (*Rddata)();
117 int (*Wrmsg)()=omsg, (*Wrdata)();
118 int (*Turnon)(), (*Turnoff)()=turnoff;
121 #define YES "Y"
122 #define NO "N"
124 #define TBUFSIZE 128 /* temporary buffer size */
125 #define FLENRADIX (16) /* output radix for file start point */
128 * failure messages
130 #define EM_MAX 10
131 #define EM_LOCACC "N1" /* local access to file denied */
132 #define EM_RMTACC "N2" /* remote access to file/path denied */
133 #define EM_BADUUCP "N3" /* a bad uucp command was generated */
134 #define EM_NOTMP "N4" /* remote error - can't create temp */
135 #define EM_RMTCP "N5" /* can't copy to remote directory - file in public */
136 #define EM_LOCCP "N6" /* can't copy on local system */
137 #define EM_SEEK "N7" /* can't seek to checkpoint */
138 /* EM_ "N8" */ /* placeholder*/
139 /* EM_ "N9" */ /* placeholder*/
140 #define EM_ULIMIT "N10" /* receiver ulimit exceeded */
142 char *Em_msg[] = {
143 "COPY FAILED (reason not given by remote)",
144 "local access to file denied",
145 "remote access to path/file denied",
146 "system error - bad uucp command generated",
147 "remote system can't create temp file",
148 "can't copy to file/directory - file left in PUBDIR/user/file",
149 "can't copy to file/directory - file left in PUBDIR/user/file",
150 "can't seek to checkpoint",
151 "COPY FAILED (reason not given by remote)", /* placeholder */
152 "COPY FAILED (reason not given by remote)", /* placeholder */
153 "file exceeds ulimit of receiving system",
154 "forwarding error"
158 #define XUUCP 'X' /* execute uucp (string) */
159 #define SLTPTCL 'P' /* select protocol (string) */
160 #define USEPTCL 'U' /* use protocol (character) */
161 #define RCVFILE 'R' /* receive file (string) */
162 #define SNDFILE 'S' /* send file (string) */
163 #define RQSTCMPT 'C' /* request complete (string - yes | no) */
164 #define HUP 'H' /* ready to hangup (string - yes | no) */
165 #define RESET 'X' /* reset line modes */
167 #define W_MAX 10 /* maximum number of C. files per line */
168 #define W_MIN 7 /* min number of entries */
169 #define W_TYPE wrkvec[0]
170 #define W_FILE1 wrkvec[1]
171 #define W_FILE2 wrkvec[2]
172 #define W_USER wrkvec[3]
173 #define W_OPTNS wrkvec[4]
174 #define W_DFILE wrkvec[5]
175 #define W_MODE wrkvec[6]
176 #define W_NUSER wrkvec[7]
177 #define W_SFILE wrkvec[8]
178 #define W_RDFILE wrkvec[8]
179 #define W_POINT wrkvec[9]
180 #define W_FSIZE wrkvec[9]
181 #define W_RFILE wrkvec[5]
182 #define W_XFILE wrkvec[5]
183 char *mf;
185 #define RMESG(m, s) if (rmesg(m, s) != 0) {(*Turnoff)(); return(FAIL);}
186 #define RAMESG(s) if (rmesg('\0', s) != 0) {(*Turnoff)(); return(FAIL);}
187 #define WMESG(m, s) if(wmesg(m, s) != 0) {(*Turnoff)(); return(FAIL);}
189 char Wfile[MAXFULLNAME] = {'\0'};
190 char Dfile[MAXFULLNAME];
192 char *wrkvec[W_MAX+1];
193 int statfopt;
196 * Create restart point filename
199 static void
200 Pname(fileid, dfile, direct)
201 char *fileid;
202 char *dfile;
203 int direct; /* indicates a direct delivery temp file nameneeded */
205 char *p;
208 * If the file is direct delivery, then its name is:
210 * /dir/dir/dir/.Pnnnnnnnn
212 * in the target directory. We create this by replacing the
213 * name of the target file with the D.nnnnnn name from the
214 * work vector, and then overwriting the D. with .P
217 if (direct) {
218 if (p = strrchr(dfile, '/')) { /* find the last slash */
219 p++;
220 strcpy(p, fileid); /* append D.nnnnn name to dir */
221 *p++ = '.';
222 *p = 'P'; /* replace beginning with .P */
223 DEBUG(7, "Point file (direct) =%s\n", dfile);
224 return;
227 strcpy(dfile, RemSpool);
228 strcat(dfile, "/");
229 p = dfile + strlen(Dfile);
230 strcat(dfile, fileid);
231 *p = 'P';
232 DEBUG(7, "Point file=%s\n", dfile);
233 return;
238 * execute the conversation between the two machines
239 * after both programs are running.
240 * returns:
241 * SUCCESS -> ok
242 * FAIL -> failed
245 cntrl()
247 FILE * fp;
248 struct stat stbuf;
249 char * p;
250 long startp; /* checkpoint restart point */
251 long actualsize; /* actual file size */
252 long im;
253 long lfilemode;
254 mode_t filemode;
255 int status;
256 int i, narg;
257 int mailopt, ntfyopt;
258 int ret;
259 char tbuf[TBUFSIZE];
260 char rqstr[BUFSIZ]; /* contains the current request message */
261 char msg[BUFSIZ];
262 char filename[MAXFULLNAME], wrktype;
263 char fsize[NAMESIZE]; /* holds file size/checkpoint string */
264 char localname[MAXFULLNAME]; /* real local system name */
265 char Recspool[MAXFULLNAME]; /* spool area for slave uucico */
266 static pid_t pnum;
267 extern int uuxqtflag; /* set if received X. or D. file */
269 pnum = getpid();
270 Wfile[0] = '\0';
271 (void) sprintf(Recspool, "%s/%s", SPOOL, Rmtname);
272 top:
273 (void) strcpy(User, Uucp);
274 statfopt = 0;
275 *Jobid = '\0';
276 DEBUG(4, "*** TOP *** - Role=%d, ", Role);
277 setline(RESET);
278 if (Role == MASTER) {
281 * get work
283 pfFindFile();
284 if ((narg = gtwvec(Wfile, wrkvec, W_MAX)) == 0) {
285 acEnd(COMPLETE); /*stop collecting accounting log */
286 WMESG(HUP, ""); /* I(master) am done. want me to quit? */
287 RMESG(HUP, msg);
288 goto process;
290 DEBUG(7, "Wfile - %s,", Wfile);
291 strncpy(Jobid, BASENAME(Wfile, '/')+2, NAMESIZE);
292 Jobid[NAMESIZE-1] = '\0';
293 DEBUG(7, "Jobid = %s\n", Jobid);
294 wrktype = W_TYPE[0];
295 pfFound(Jobid, W_OPTNS, Nstat.t_qtime);
296 mailopt = strchr(W_OPTNS, 'm') != NULL;
297 statfopt = strchr(W_OPTNS, 'o') != NULL;
298 ntfyopt = strchr(W_OPTNS, 'n') != NULL;
300 uucpname(localname); /* get real local machine name */
301 acDojob(Jobid, localname, W_USER);
302 scRequser(W_USER); /* log requestor user id */
305 * We used to check for corrupt workfiles here (narg < 5),
306 * but we were doing it wrong, and besides, anlwrk.c is the
307 * appropriate place to do it.
310 (void) sprintf(User, "%s", W_USER);
311 if (wrktype == SNDFILE ) {
312 (void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Myname,
313 W_FILE1, Rmtname, W_FILE2, User);
315 /* log destination node, user and file name */
317 scDest(Rmtname,NOTAVAIL,W_FILE2);
319 /* log source node, file owner, file name, mod time and size */
321 scSrc(Myname,scOwn(W_FILE1),W_FILE1,scMtime(W_FILE1)
322 ,scSize(W_FILE1));
324 logent(rqstr, "REQUEST");
325 CDEBUG(1, "Request: %s\n", rqstr);
326 mf = W_SFILE;
327 (void) strcpy(filename, W_FILE1);
328 expfile(filename);
329 (void) strcpy(Dfile, W_DFILE);
330 if ( (fp = fopen(Dfile, "r")) == NULL) {
331 if ( (fp = fopen(filename, "r")) == NULL) {
332 /* cannot read spool or original file */
333 unlinkdf(Dfile);
334 lnotify(User, rqstr, "can't access");
335 (void) sprintf(msg, "CAN'T READ %s %d",
336 filename, errno);
337 logent(msg, "FAILED");
338 CDEBUG(1, "Failed: Can't Read %s\n", filename);
339 scWrite(); /* log the security violation */
340 goto top;
341 } else {
342 /* ensure original file is publicly readable */
343 if ( !F_READANY(fileno(fp)) ) {
344 /* access denied */
345 logent("DENIED", "ACCESS");
346 unlinkdf(W_DFILE);
347 lnotify(User, rqstr, "access denied");
348 CDEBUG(1, "Failed: Access Denied\n%s", "");
349 scWrite(); /* log the security violation */
350 goto top;
355 if (Restart && !(fstat(fileno(fp), &stbuf))) {
356 (void) sprintf(fsize, "0x%lx", stbuf.st_size);
357 W_FSIZE = fsize; /* set file size in vector */
360 /* Check whether remote's ulimit is exceeded */
361 if (SizeCheck) {
362 if (((stbuf.st_size-1)/512 + 1) > RemUlimit) {
363 /* remote ulimit exceeded */
364 unlinkdf(Dfile);
365 lnotify(User, rqstr, "remote ulimit exceeded");
366 logent("DENIED", "REMOTE ULIMIT EXCEEDED");
367 CDEBUG(1, "Denied: remote ulimit exceeded %s\n", filename);
368 scWrite();
369 (void) fclose(fp);
370 goto top;
375 if (wrktype == RCVFILE) {
376 (void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Rmtname,
377 W_FILE1, Myname, W_FILE2, User);
379 /* log destination node, user and file name */
381 scDest(Myname,NOTAVAIL,W_FILE2);
383 /* log source node, file owner, file name, mod time and size */
385 scSrc(Rmtname,NOTAVAIL,W_FILE1,NOTAVAIL,NOTAVAIL);
387 logent(rqstr, "REQUEST");
388 CDEBUG(1, "Request: %s\n", rqstr);
389 mf = W_RFILE;
390 (void) strcpy(filename, W_FILE2);
392 /* change Wrkdir to SPOOL/Rmtname in case the file being
393 ** requested is needed for some remote execution.
396 (void) strcpy(Wrkdir, Recspool);
397 expfile(filename);
399 /* now change Wrkdir back to what it was
400 ** just being paranoid.
403 (void) strcpy(Wrkdir, RemSpool);
404 if (chkperm(W_FILE1, filename, strchr(W_OPTNS, 'd'))) {
406 /* access denied */
407 logent("DENIED", "ACCESS");
408 lnotify(User, rqstr, "access denied");
409 CDEBUG(1, "Failed: Access Denied--File: %s\n",
410 filename);
411 scWrite(); /* log the security violation */
412 goto top;
416 * If we are not going to spool the file in the spool
417 * directory, just use the destination file name. If we
418 * are not supporting restart, wipe out the target file.
419 * else:
421 * If restart is enabled, make up the Point file name
422 * as the file to open, else use the TM style name.
424 * If we run into a spool name of "D.0", this implies
425 * that someone forgot to install the new uucp and
426 * uux commands. Such jobs will not be checkpointed.
430 if (Restart && (strlen(W_RDFILE) > (size_t) 6)) {
431 if (noSpool()) {
432 strcpy(Dfile, filename); /* use Dest file directly */
433 Pname(W_RDFILE, Dfile, TRUE);
435 else
436 Pname(W_RDFILE, Dfile, FALSE);
438 else {
439 TMname(Dfile, pnum); /* get TM file name */
440 unlink(Dfile);
444 * If the spool file exists, it better have the right owner
445 * and permissions!
448 if (Restart && noSpool()) {
449 if ((! stat(Dfile, &stbuf)) &&
450 ((stbuf.st_mode != (DFILEMODE|S_IFREG)) ||
451 ((stbuf.st_gid != UUCPGID) ||
452 (stbuf.st_uid != UUCPUID)))) {
453 lnotify(User, rqstr,
454 "bad spool file ownership/permissions");
455 logent("BAD DESTFILE OWNER/PERMS", "FAIL");
456 CDEBUG(1, "Failed: bad dest file owner/perms 0%o; fail\n", stbuf.st_mode);
457 goto top;
460 if ( ((fp = fopen(Dfile, "a+")) == NULL)
461 || nospace(Dfile)) {
463 /* can not create temp */
464 if (noSpool())
465 logent("CAN'T CREATE/OPEN DEST FILE", "FAILED");
466 else
467 logent("CAN'T CREATE TM FILE", "FAILED");
468 CDEBUG(1, "Failed: No Space!\n%s", "");
469 unlinkdf(Dfile);
470 assert(Ct_CREATE, Dfile, nospace(Dfile),
471 __FILE__, __LINE__);
472 cleanup(FAIL);
476 * Send the W_POINT value to the other side.
479 if (Restart) {
480 if (fstat (fileno(fp), &stbuf)) {
481 logent("CAN'T STAT DFILE", "START FROM BEGINNING");
482 stbuf.st_size = 0L;
486 * find a good start point. Take care of simple
487 * underflow and the signed nature of longs.
490 DEBUG(7, "Dfile length 0x%lx\n", stbuf.st_size);
491 startp = stbuf.st_size - (stbuf.st_size % BUFSIZ);
492 if((stbuf.st_size >= 0) && (startp < 0))
493 startp = 0;
495 if(startp)
497 if(startp < 0)
498 sprintf(tbuf,"start=0x%lx", startp);
499 else
500 sprintf(tbuf,"start=%ld", startp);
502 logent(tbuf, "RESTART");
505 sprintf(fsize, "0x%lx", startp);
506 W_POINT = fsize; /* set start point in vector */
507 if (lseek(fileno(fp), startp, 0) == -1) {
508 WMESG(SNDFILE, EM_SEEK);
509 logent("CAN'T SEEK", "DENIED");
510 CDEBUG(1, "Failed, Can't seek in Dfile\n%s", "");
511 unlinkdf(Dfile);
512 goto top;
514 fp->_cnt = 0;
515 fp->_ptr = fp->_base;
518 Seqn++;
519 chmod(Dfile, DFILEMODE); /* no peeking! */
520 chown(Dfile, UUCPUID, UUCPGID);
523 DEBUG(4, "wrktype - %c\n ", wrktype);
525 /* Build up the message itself */
527 msg[0] = '\0';
528 for (i = 1; i < narg; i++) {
529 (void) strcat(msg, " ");
530 (void) strcat(msg, wrkvec[i]);
533 WMESG(wrktype, msg); /* I(master) am sending you our work file */
534 RMESG(wrktype, msg); /* I(master) am waiting for your response */
535 goto process;
539 * role is slave
542 RAMESG(msg); /* I(slave) am waiting for our work file */
544 process:
546 DEBUG(4, " PROCESS: msg - %s\n", msg);
547 switch (msg[0]) {
549 case RQSTCMPT:
550 DEBUG(4, "%s\n", "RQSTCMPT:");
551 if (msg[1] == 'N') {
552 i = atoi(&msg[2]);
553 if (i < 0 || i > EM_MAX)
554 i = 0;
555 logent(Em_msg[i], "REQUESTED");
557 if (Role == MASTER) {
558 notify(mailopt, W_USER, rqstr, Rmtname, &msg[1]);
560 pfEndfile(""); /* "" indicates the file transfer completely */
561 goto top;
563 case HUP:
564 DEBUG(4, "%s\n", "HUP:");
565 if (msg[1] == 'Y') {
566 WMESG(HUP, YES); /* let's quit */
567 (*Turnoff)();
568 Rdmsg = imsg;
569 Wrmsg = omsg;
570 Turnoff = turnoff;
571 return(0);
574 if (msg[1] == 'N') {
575 ASSERT(Role == MASTER, Wr_ROLE, "", Role);
576 Role = SLAVE;
577 scReqsys(Rmtname); /* log requestor system */
578 chremdir(Rmtname);
579 goto top;
583 * get work
585 if ( (switchRole() == FALSE) || !iswrk(Wfile) ) {
586 DEBUG(5, "SLAVE-switchRole (%s)\n",
587 switchRole() ? "TRUE" : "FALSE");
588 WMESG(HUP, YES); /* let's quit */
589 RMESG(HUP, msg);
590 goto process;
593 /* Note that Wfile is the first C. to process at top
594 * set above by iswrk() call
596 if (uuxqtflag) {
597 xuuxqt(uuxqtarg);
598 uuxqtflag = 0;
600 WMESG(HUP, NO); /* don't quit. I(slave) have more to do */
601 Role = MASTER;
602 uucpname(localname); /* get real local machine name */
603 scReqsys(localname); /* log requestor system */
604 acInit("xfer");
605 goto top;
607 case XUUCP:
609 * slave part
610 * No longer accepted
613 WMESG(XUUCP, NO);
614 goto top;
616 case SNDFILE:
619 * MASTER section of SNDFILE
621 DEBUG(4, "%s\n", "SNDFILE:");
622 if (msg[1] == 'N')
624 i = atoi(&msg[2]);
625 if (i < 0 || i > EM_MAX)
626 i = 0;
627 logent(Em_msg[i], "REQUEST");
628 notify(mailopt, W_USER, rqstr, Rmtname, &msg[1]);
629 ASSERT(Role == MASTER, Wr_ROLE, "", Role);
630 (void) fclose(fp);
631 /* if remote is out of tmp space, then just hang up */
632 ASSERT(i != 4, Em_msg[4], Rmtname, i); /* EM_NOTMP */
633 unlinkdf(W_DFILE);
634 scWrite(); /* something is wrong on other side,
635 log the security violation */
636 Seqn++;
637 goto top;
640 if (msg[1] == 'Y') {
643 * send file
645 ASSERT(Role == MASTER, Wr_ROLE, "", Role);
646 if (fstat(fileno(fp), &stbuf)) /* never fail but .. */
647 stbuf.st_size = 0; /* for time loop calculation */
650 * If checkpoint restart is enabled, seek to the
651 * starting point in the file. We use hex because
652 * C doesn't support unsigned long directly.
655 if (Restart) {
656 if((startp = strtol(&msg[2], (char **) 0, FLENRADIX))) {
657 CDEBUG(1, "Restart point=0x%lx\n", startp);
658 if(startp < 0)
659 sprintf(tbuf,"start=0x%lx", startp);
660 else
661 sprintf(tbuf,"start=%ld", startp);
662 p = tbuf + strlen(tbuf);
663 if (stbuf.st_size < 0)
664 sprintf(p,", length=0x%lx", stbuf.st_size);
665 else
666 sprintf(p,", length=%ld", stbuf.st_size);
668 logent(tbuf, "RESTART");
669 errno = 0;
670 if (lseek(fileno(fp), startp, 0) == -1) {
671 logent(strerror(errno), "FSEEK ERROR");
672 (void) fclose(fp);
673 (*Turnoff)();
674 Seqn++;
675 return(FAIL);
677 fp->_cnt = 0;
678 fp->_ptr = fp->_base;
681 (void) millitick(); /* start msec timer */
682 pfStrtXfer(MCHAR, SNDFILE);
683 scStime(); /* log start transfer time for security log */
685 /* (ret != 0) implies the trammission error occurred.
686 If checkpoint protocol is available then the next
687 transfer will restart from the breakpoint of the file,
688 otherwise from the beginning of the file */
690 ret = (*Wrdata)(fp, Ofn);
692 /* the second millitick() returns the duration between
693 the first and second call.
694 writes "PARTIAL FILE to the transfer log indicating
695 a transmission error. */
697 statlog( "->", getfilesize(), millitick(),
698 (ret) ? "PARTIAL FILE" : "" );
700 acInc(); /* increment job size in accounting log */
701 pfEndXfer();
702 scEtime(); /* log end transfer time for security log */
703 Seqn++;
704 (void) fclose(fp);
705 if (ret != 0) {
706 pfEndfile("PARTIAL FILE");
707 acEnd(PARTIAL); /*stop collecting accounting log */
708 (*Turnoff)();
709 return(FAIL);
712 /* loop depending on the size of the file */
713 /* give an extra try for each megabyte */
714 for (im = stbuf.st_size >> 10; im >= 0; --im) {
715 if ((ret = rmesg(RQSTCMPT, msg)) == 0)
716 break; /* got message */
718 if (ret != 0) {
719 (*Turnoff)();
720 return(FAIL);
722 unlinkdf(W_DFILE);
723 goto process;
727 * SLAVE section of SNDFILE
729 ASSERT(Role == SLAVE, Wr_ROLE, "", Role);
732 * request to receive file
733 * check permissions
735 i = getargs(msg, wrkvec, W_MAX);
737 scRequser(W_USER); /* log requestor user id */
739 /* log destination node, user and file name */
741 scDest(Myname,NOTAVAIL,W_FILE2);
743 /* log source node, file owner, file name, mod time and size */
745 scSrc(Rmtname,NOTAVAIL,W_FILE1,NOTAVAIL,NOTAVAIL);
747 /* Check for bad request */
748 if (i < W_MIN) {
749 WMESG(SNDFILE, EM_BADUUCP); /* you(remote master) gave me
750 bad work file */
751 logent("DENIED", "TOO FEW ARGS IN SLAVE SNDFILE");
752 goto top;
754 /* SLAVE gets the original filesize from sender (MASTER) */
755 /* This will be used to check the length of the P. file */
756 if (Restart) {
757 if (W_FSIZE && (*W_FSIZE != '\0')) {
758 actualsize = strtol(W_FSIZE, (char **) 0, FLENRADIX);
759 CDEBUG(7, "Actual File Length %ld\n", actualsize);
760 } else {
761 actualsize = -1;
762 CDEBUG(7, "Actual File Length Not Provided\n%s", "");
766 mf = W_SFILE;
767 (void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Rmtname,
768 W_FILE1, Myname, W_FILE2, W_USER);
769 logent(rqstr, "REMOTE REQUESTED");
770 DEBUG(4, "msg - %s\n", msg);
771 CDEBUG(1, "Remote Requested: %s\n", rqstr);
772 (void) strcpy(filename, W_FILE2);
773 expfile(filename);
774 DEBUG(4, "SLAVE - filename: %s\n", filename);
775 if (chkpth(filename, CK_WRITE)
776 || chkperm(W_FILE1, filename, strchr(W_OPTNS, 'd'))) {
777 WMESG(SNDFILE, EM_RMTACC); /* you(remote master) can't
778 send data to this file(directory) */
779 logent("DENIED", "PERMISSION");
780 CDEBUG(1, "Failed: Access Denied\n%s", "");
781 scWrite(); /* log security violation */
782 goto top;
784 (void) sprintf(User, "%s", W_USER);
786 DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
790 if (Restart && (strlen(W_DFILE) > (size_t) 6)) {
791 if (noSpool()) {
792 strcpy(Dfile, filename); /* use Dest file directly */
793 Pname(W_DFILE, Dfile, TRUE);
794 if (! Restart)
795 unlink(Dfile);
797 else
798 Pname(W_DFILE, Dfile, FALSE);
800 else {
801 TMname(Dfile, pnum); /* get TM file name */
802 unlink(Dfile);
806 * If the spool file exists, it better have the right owner
807 * and permissions!
810 if (Restart && noSpool()) {
811 if ((! stat(Dfile, &stbuf)) &&
812 ((stbuf.st_mode != (DFILEMODE|S_IFREG)) ||
813 ((stbuf.st_gid != UUCPGID) ||
814 (stbuf.st_uid != UUCPUID)))) {
815 WMESG(SNDFILE, EM_NOTMP); /* I(slave) see bad perms */
816 logent("BAD DESTFILE OWNER/PERMS", "FAILED");
817 CDEBUG(1, "Failed: bad dest file owner/perms 0%o\n", stbuf.st_mode);
818 goto top;
821 if ( ((fp = fopen(Dfile, "a+")) == NULL) || nospace(Dfile) ) {
822 WMESG(SNDFILE, EM_NOTMP); /* I(slave) can't create TM file */
823 logent("CAN'T OPEN", "DENIED");
824 CDEBUG(1, "Failed: Can't Create Temp File\n%s", "");
825 unlinkdf(Dfile);
826 goto top;
828 chmod(Dfile, DFILEMODE); /* no peeking! */
829 chown(Dfile, UUCPUID, UUCPGID);
830 if (Restart && (strlen(W_DFILE) > (size_t) 6)) {
831 if(fstat(fileno(fp), &stbuf)) {
832 WMESG(SNDFILE, EM_NOTMP);
833 logent("CAN'T STAT", "DENIED");
834 CDEBUG(1, "Failed: Can't Stat Temp File\n%s", "");
835 unlinkdf(Dfile);
836 Seqn++;
837 goto top;
840 * find a good start point. Take care of simple underflow
841 * and the signed nature of longs.
844 DEBUG(7, "Dfile length 0x%lx\n", stbuf.st_size);
845 startp = stbuf.st_size - (stbuf.st_size % BUFSIZ);
846 if((stbuf.st_size >= 0) && (startp < 0))
847 startp = 0;
849 if(startp)
851 if(startp < 0)
852 sprintf(tbuf,"start=0x%lx", startp);
853 else
854 sprintf(tbuf,"start=%ld", startp);
856 logent(tbuf, "RESTART");
859 sprintf(tbuf, "%s 0x%lx", YES, startp);
860 if (lseek(fileno(fp), startp, 0) == -1) {
861 WMESG(SNDFILE, EM_SEEK);
862 logent("CAN'T SEEK", "DENIED");
863 CDEBUG(1, "Failed, Can't seek in Dfile\n%s", "");
864 unlinkdf(Dfile);
865 Seqn++;
866 goto top;
868 fp->_cnt = 0;
869 fp->_ptr = fp->_base;
870 CDEBUG(1," restart msg %s\n", tbuf);
871 WMESG(SNDFILE, tbuf);
873 else
874 WMESG(SNDFILE, YES); /* I(slave) clear to send */
875 (void) millitick(); /* start msec timer */
876 pfStrtXfer(SCHAR, RCVFILE);
877 scStime(); /* log start transfer time for security log */
878 /* (ret != 0) implies the trammission error occurred.
879 If checkpoint protocol is available then the next
880 recieve will restart from the breakpoint of the file,
881 otherwise from the beginning of the file */
883 setline(RCVFILE);
884 ret = (*Rddata)(Ifn, fp);
885 setline(SNDFILE);
887 /* the second millitick() returns the duration between
888 the first and second call.
889 writes "PARTIAL FILE to the transfer log indicating
890 a transmission error. */
892 statlog( "<-", getfilesize(), millitick(),
893 (ret) ? "PARTIAL FILE" : "" );
895 pfEndXfer();
896 scEtime(); /* log end transfer time for security log */
897 Seqn++;
899 if (ret != 0) {
900 pfEndfile("PARTIAL FILE");
901 (void) fclose(fp);
902 if ( ret == EFBIG ) {
903 WMESG(RQSTCMPT, EM_ULIMIT);
904 logent("FILE EXCEEDS ULIMIT","FAILED");
905 CDEBUG(1, "Failed: file size exceeds ulimit%s\n", "");
906 goto top;
908 (*Turnoff)();
909 logent("INPUT FAILURE", "IN SEND/SLAVE MODE");
910 return(FAIL);
912 if (Restart && (actualsize != -1)) {
913 if (fstat(fileno(fp), &stbuf)) {
914 (void) fclose(fp);
915 unlinkdf(Dfile);
916 (*Turnoff)();
917 logent("CAN'T STAT PFILE", "FAILED");
918 return(FAIL);
920 if (stbuf.st_size != actualsize) {
921 (void) fclose(fp);
922 unlinkdf(Dfile);
923 (*Turnoff)();
924 logent("RECEIVED SIZE NOT EQUAL TO ACTUAL SIZE", "FAILED");
925 CDEBUG(1, "Failed: receive size %ld ", stbuf.st_size);
926 CDEBUG(1, "not equal to actual size %ld\n", actualsize);
927 return(FAIL);
930 (void) fclose(fp);
932 /* copy to user directory */
933 ntfyopt = strchr(W_OPTNS, 'n') != NULL;
936 * See if spool file and target file in the same file system
939 ret = 0;
940 if (p = strrchr(Dfile, '/'))
942 *p = '\0';
943 ret = PREFIX(Dfile, filename);
944 *p = '/';
947 if (noSpool() && ret)
950 * if we are not already in the right file, and
951 * it is theoretically in the same file system,
952 * link it there...
955 if(strcmp (filename, Dfile)) {
956 unlink(filename);
957 if(link(Dfile, filename))
959 logent("FAILED", "MOVE");
960 scWrite();
961 putinpub(filename, Dfile, BASENAME(W_USER,'!'));
963 else
964 DEBUG(7, "linked Point file to %s\n", filename);
965 unlink(Dfile);
967 else
968 DEBUG(7, "Point file and %s the same\n", filename);
969 status = 0; /* all done */
971 else
972 status = xmv(Dfile, filename);
974 scSize(Dfile); /* log source file size */
975 WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
976 if (status == 0) {
977 sscanf(W_MODE, "%lo", &lfilemode);
978 if (lfilemode <= 0)
979 filemode = PUB_FILEMODE;
980 else
981 filemode = (mode_t)lfilemode;
982 if (PREFIX(RemSpool, filename))
983 chmod(filename, DFILEMODE);
984 else
985 chmod(filename, (filemode & LEGALMODE) | PUB_FILEMODE);
986 arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
987 } else {
988 logent("FAILED", "COPY");
989 scWrite(); /* log the security violation */
990 status = putinpub(filename, Dfile,
991 BASENAME(W_USER, '!'));
992 DEBUG(4, "->PUBDIR %d\n", status);
993 if (status == 0)
994 arrived(ntfyopt, filename, W_NUSER,
995 Rmtname, User);
997 pfEndfile(""); /* "" indicates the file transfer completely */
998 if ( W_FILE2[1] == '.' &&
999 (W_FILE2[0] == XQTPRE || W_FILE2[0] == DATAPRE) )
1000 uuxqtflag = 1;
1001 goto top;
1003 case RCVFILE:
1006 * MASTER section of RCVFULE
1008 DEBUG(4, "%s\n", "RCVFILE:");
1009 if (msg[1] == 'N') {
1010 i = atoi(&msg[2]);
1011 if (i < 0 || i > EM_MAX)
1012 i = 0;
1013 logent(Em_msg[i], "REQUEST");
1014 notify(mailopt, W_USER, rqstr, Rmtname, &msg[1]);
1015 ASSERT(Role == MASTER, Wr_ROLE, "", Role);
1016 (void) fclose(fp);
1017 unlinkdf(Dfile);
1018 scWrite(); /* something is wrong on other side,
1019 log the security violation */
1020 goto top;
1023 if (msg[1] == 'Y') {
1025 /* MASTER gets the original filesize from sender (SLAVE) */
1026 /* This will be used to check the length of the P. file */
1027 if (Restart) {
1028 *fsize = '\0';
1029 sscanf(&msg[2], "%*o %s", fsize);
1030 if (*fsize != '\0') {
1031 actualsize = strtol(fsize, (char **) 0, FLENRADIX);
1032 CDEBUG(7, "Actual File Length %ld\n", actualsize);
1033 } else {
1034 actualsize = -1;
1035 CDEBUG(7, "Actual File Length Not Provided\n%s", "");
1040 * receive file
1042 ASSERT(Role == MASTER, Wr_ROLE, "", Role);
1043 (void) millitick(); /* start msec timer */
1044 pfStrtXfer(MCHAR, SNDFILE);
1045 scStime();
1046 /* (ret != 0) implies the trammission error occurred.
1047 If checkpoint protocol is available then the next
1048 recieve will restart from the breakpoint of the file,
1049 otherwise from the beginning of the file */
1051 ret = (*Rddata)(Ifn, fp);
1053 /* the second millitick() returns the duration between
1054 the first and second call.
1055 writes "PARTIAL FILE to the transfer log indicating
1056 a transmission error. */
1058 statlog( "<-", getfilesize(), millitick(),
1059 (ret) ? "PARTIAL FILE" : "" );
1060 pfEndXfer();
1061 scEtime();
1062 if (ret != 0) {
1063 pfEndfile("PARTIAL FILE");
1064 (void) fclose(fp);
1065 if ( ret == EFBIG ) {
1066 WMESG(RQSTCMPT, EM_ULIMIT);
1067 logent("FILE EXCEEDS ULIMIT","FAILED");
1068 CDEBUG(1, "Failed: file size exceeds ulimit%s\n", "");
1069 goto top;
1071 (*Turnoff)();
1072 logent("INPUT FAILURE", "IN RECEIVE/MASTER MODE");
1073 return(FAIL);
1075 if (Restart && (actualsize != -1)) {
1076 if (fstat(fileno(fp), &stbuf)) {
1077 (void) fclose(fp);
1078 unlinkdf(Dfile);
1079 (*Turnoff)();
1080 logent("CAN'T STAT PFILE", "FAILED");
1081 return(FAIL);
1083 if (stbuf.st_size != actualsize) {
1084 (void) fclose(fp);
1085 unlinkdf(Dfile);
1086 (*Turnoff)();
1087 logent("RECEIVED SIZE NOT EQUAL TO ACTUAL SIZE", "FAILED");
1088 CDEBUG(1, "Failed: receive size %ld ", stbuf.st_size);
1089 CDEBUG(1, "not equal to actual size %ld\n", actualsize);
1090 return(FAIL);
1093 (void) fclose(fp);
1096 * See if spool file and target file in the same file system
1099 ret = 0;
1100 if (p = strrchr(Dfile, '/'))
1102 *p = '\0';
1103 ret = PREFIX(Dfile, filename);
1104 *p = '/';
1107 if (noSpool() && ret)
1110 * if we are not already in the right file, and
1111 * it is theoretically in the same file system,
1112 * link it there...
1115 if(strcmp (filename, Dfile)) {
1116 unlink(filename);
1117 if(link(Dfile, filename))
1119 logent("FAILED", "MOVE");
1120 scWrite();
1121 putinpub(filename, Dfile, W_USER);
1123 else
1124 DEBUG(7, "linked Point file to %s\n", filename);
1125 unlink(Dfile);
1127 else
1128 DEBUG(7, "Point file and %s the same\n", filename);
1129 status = 0; /* all done */
1131 else
1132 status = xmv(Dfile, filename);
1134 WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
1135 notify(mailopt, W_USER, rqstr, Rmtname,
1136 status ? EM_LOCCP : YES);
1137 if (status == 0) {
1138 sscanf(&msg[2], "%lo", &lfilemode);
1139 if (lfilemode <= 0)
1140 filemode = PUB_FILEMODE;
1141 else
1142 filemode = (mode_t)lfilemode;
1143 if (PREFIX(RemSpool, filename))
1144 chmod(filename, DFILEMODE);
1145 else
1146 chmod(filename, (filemode & LEGALMODE) | PUB_FILEMODE);
1147 } else {
1148 logent("FAILED", "COPY");
1149 scWrite(); /* log the security violation */
1150 putinpub(filename, Dfile, W_USER);
1152 pfEndfile(""); /* "" indicates the file transfer completely */
1153 if ( W_FILE2[1] == '.' &&
1154 (W_FILE2[0] == XQTPRE || W_FILE2[0] == DATAPRE) )
1155 uuxqtflag = 1;
1156 goto top;
1160 * SLAVE section of RCVFILE
1161 * (request to send file)
1163 ASSERT(Role == SLAVE, Wr_ROLE, "", Role);
1165 /* check permissions */
1166 i = getargs(msg, wrkvec, W_MAX);
1168 scRequser(W_USER); /* log requestor user id */
1170 /* log destination node, user and file name */
1172 scDest(Rmtname,NOTAVAIL,W_FILE2);
1174 /* log source node, file owner, file name, mod time and size */
1176 scSrc(Myname,scOwn(W_FILE1),W_FILE1,scMtime(W_FILE1),scSize(W_FILE1));
1177 /* Check for bad request */
1178 if (i < 5) {
1179 WMESG(RCVFILE, EM_BADUUCP); /* you(remote master) gave me
1180 bad work file */
1181 logent("DENIED", "TOO FEW ARGS IN SLAVE RCVFILE");
1182 goto top;
1185 (void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Myname,
1186 W_FILE1, Rmtname, W_FILE2, W_USER);
1187 logent(rqstr, "REMOTE REQUESTED");
1188 CDEBUG(1, "Remote Requested: %s\n", rqstr);
1189 mf = W_RFILE;
1190 DEBUG(4, "msg - %s\n", msg);
1191 DEBUG(4, "W_FILE1 - %s\n", W_FILE1);
1192 (void) strcpy(filename, W_FILE1);
1193 expfile(filename);
1194 if (DIRECTORY(filename)) {
1195 (void) strcat(filename, "/");
1196 (void) strcat(filename, BASENAME(W_FILE2, '/'));
1198 (void) sprintf(User, "%s", W_USER);
1200 if (requestOK() == FALSE) {
1201 /* remote can't request data from my system */
1202 WMESG(RCVFILE, EM_RMTACC);
1203 logent("DENIED", "REQUESTING");
1204 CDEBUG(1, "Failed: Access Denied\n%s", "");
1205 scWrite(); /* log the security violation */
1206 goto top;
1208 DEBUG(4, "requestOK for Loginuser - %s\n", Loginuser);
1210 if ((fp = fopen(filename, "r")) == NULL) {
1211 WMESG(RCVFILE, EM_RMTACC); /* you(remote master) can't
1212 read my file */
1213 logent("CAN'T OPEN", "DENIED");
1214 CDEBUG(1, "Failed: Can't Open %s\n", filename);
1215 scWrite(); /* log the security violation */
1216 goto top;
1219 if (chkpth(filename, CK_READ) || !F_READANY(fileno(fp))) {
1220 WMESG(RCVFILE, EM_RMTACC); /* you(remote master) can't
1221 retrive my file */
1222 logent("DENIED", "PERMISSION");
1223 CDEBUG(1, "Failed: Access Denied\n%s", "");
1224 scWrite(); /* log the security violation */
1225 fclose(fp);
1226 goto top;
1228 DEBUG(4, "chkpth ok Loginuser - %s\n", Loginuser);
1230 ASSERT(fstat(fileno(fp), &stbuf) == 0, Ct_STAT,
1231 filename, errno);
1233 /* Check whether remote's ulimit is exceeded */
1234 if (SizeCheck) {
1235 if (((stbuf.st_size-1)/512 + 1) > RemUlimit) {
1236 /* remote ulimit exceeded */
1237 WMESG(RCVFILE, EM_ULIMIT);
1238 logent("DENIED", "REMOTE ULIMIT EXCEEDED");
1239 CDEBUG(1, "Denied: remote ulimit exceeded %s\n", filename);
1240 scWrite();
1241 (void) fclose(fp);
1242 goto top;
1247 * ok to send file
1250 if (Restart && i >= 10) {
1251 if (startp = strtol(W_POINT, (char **) 0, FLENRADIX)) {
1252 CDEBUG(1,"Restart point=0x%lx\n", startp);
1253 errno = 0;
1254 if (lseek(fileno(fp), startp, 0) == -1) {
1255 WMESG(RCVFILE, EM_SEEK);
1256 logent(strerror(errno), "FSEEK ERROR");
1257 (void) fclose(fp);
1258 goto top;
1260 fp->_cnt = 0;
1261 fp->_ptr = fp->_base;
1262 if(startp < 0)
1263 sprintf(tbuf,"start=0x%lx", startp);
1264 else
1265 sprintf(tbuf,"start=%ld", startp);
1266 p = tbuf + strlen(tbuf);
1267 if (stbuf.st_size < 0)
1268 sprintf(p,", length=0x%lx", stbuf.st_size);
1269 else
1270 sprintf(p,", length=%ld", stbuf.st_size);
1272 logent(tbuf, "RESTART");
1276 if (Restart)
1277 (void) sprintf(msg, "%s %lo 0x%lx", YES,
1278 (long) (stbuf.st_mode & LEGALMODE),
1279 (long) stbuf.st_size);
1280 else
1281 (void) sprintf(msg, "%s %lo", YES,
1282 (long) (stbuf.st_mode & LEGALMODE));
1283 WMESG(RCVFILE, msg); /* I(slave) send you my file now */
1284 Seqn++;
1285 (void) millitick(); /* start msec timer */
1286 scStime();
1287 pfStrtXfer(SCHAR, SNDFILE);
1288 /* (ret != 0) implies the trammission error occurred.
1289 If checkpoint protocol is available then the next
1290 transfer will restart from the breakpoint of the file,
1291 otherwise from the beginning of the file */
1293 ret = (*Wrdata)(fp, Ofn);
1295 /* the second millitick() returns the duration between
1296 the first and second call.
1297 writes "PARTIAL FILE to the transfer log indicating
1298 a transmission error. */
1300 statlog( "->", getfilesize(), millitick(),
1301 (ret) ? "PARTIAL FILE" : "" );
1302 pfEndXfer();
1303 scEtime();
1305 (void) fclose(fp);
1306 if (ret != 0) {
1307 pfEndfile("PARTIAL FILE");
1308 (*Turnoff)();
1309 return(FAIL);
1312 /* loop depending on the size of the file */
1313 /* give an extra try for each megabyte */
1314 /* stbuf set in fstat several lines back */
1315 for (im = stbuf.st_size >> 10; im >= 0; --im) {
1316 if ((ret = rmesg(RQSTCMPT, msg)) == 0)
1317 break; /* got message */
1319 if (ret != 0) {
1320 (*Turnoff)();
1321 return(FAIL);
1323 goto process;
1325 (*Turnoff)();
1326 return(FAIL);
1332 * read message
1333 * returns:
1334 * 0 -> success
1335 * FAIL -> failure
1338 rmesg(c, msg)
1339 char *msg, c;
1341 char str[50];
1343 DEBUG(4, "rmesg - '%c' ", c);
1344 if ((*Rdmsg)(msg, Ifn) != 0) {
1345 DEBUG(4, "got %s\n", "FAIL");
1346 (void) sprintf(str, "expected '%c' got FAIL", c);
1347 logent(str, "BAD READ");
1348 return(FAIL);
1350 if (c != '\0' && msg[0] != c) {
1351 DEBUG(4, "got %s\n", msg);
1352 (void) sprintf(str, "expected '%c' got %s", c, msg);
1353 logent(str, "BAD READ");
1354 return(FAIL);
1356 DEBUG(4, "got %s\n", msg);
1357 return(0);
1362 * write a message
1363 * returns:
1364 * 0 -> ok
1365 * FAIL -> ng
1368 wmesg(m, s)
1369 char *s, m;
1371 CDEBUG(4, "wmesg '%c'", m);
1372 CDEBUG(4, "%s\n", s);
1373 return((*Wrmsg)(m, s, Ofn));
1378 * mail results of command
1379 * return:
1380 * none
1382 void
1383 notify(mailopt, user, msgin, sys, msgcode)
1384 char *user, *msgin, *sys;
1385 char *msgcode;
1387 int i;
1388 char str[BUFSIZ];
1389 char *msg;
1391 DEBUG(4,"mailopt %d, ", mailopt);
1392 DEBUG(4,"statfopt %d\n", statfopt);
1393 if (statfopt == 0 && mailopt == 0 && *msgcode == 'Y')
1394 return;
1395 if (*msgcode == 'Y')
1396 msg = "copy succeeded";
1397 else {
1398 i = atoi(msgcode + 1);
1399 if (i < 1 || i > EM_MAX)
1400 i = 0;
1401 msg = Em_msg[i];
1403 if(statfopt){
1404 stmesg(msgin, msg);
1405 return;
1407 (void) sprintf(str, "REQUEST: %s\n(SYSTEM: %s) %s\n",
1408 msgin, sys, msg);
1409 mailst(user, msg, str, "", "");
1410 return;
1414 * local notify
1415 * return:
1416 * none
1418 void
1419 lnotify(user, msgin, mesg)
1420 char *user, *msgin, *mesg;
1422 char mbuf[BUFSIZ];
1424 if(statfopt){
1425 stmesg(msgin, mesg);
1426 return;
1428 (void) sprintf(mbuf, "REQUEST: %s\n(SYSTEM: %s) %s\n",
1429 msgin, Myname, mesg);
1430 mailst(user, mesg, mbuf, "", "");
1431 return;
1434 /*ARGSUSED*/
1435 static void
1436 stmesg(f, m)
1437 char *f, *m;
1439 #ifdef notdef
1440 FILE *Cf;
1441 time_t clock;
1442 long td, th, tm, ts;
1443 #endif
1444 char msg[BUFSIZ];
1446 DEBUG(4,"STMES %s\n",mf);
1447 sprintf(msg, "STMESG - %s", mf);
1448 logent("DENIED", msg);
1449 #ifdef notdef
1451 * This code is a giant security hole.
1452 * No checking is done on what file is
1453 * written and chmod'ed. For now we
1454 * just ifdef this out.
1456 if((Cf = fopen(mf, "a+")) == NULL){
1457 chmod(mf, PUB_FILEMODE);
1458 return;
1460 (void) time(&clock);
1461 (void) fprintf(Cf, "uucp job: %s (%s) ", Jobid, timeStamp());
1462 td = clock - Nstat.t_qtime;
1463 ts = td%60;
1464 td /= 60;
1465 tm = td%60;
1466 td /= 60;
1467 th = td;
1468 (void) fprintf(Cf, "(%ld:%ld:%ld)\n%s\n%s\n\n", th, tm, ts, f, m);
1469 (void) fclose(Cf);
1470 chmod(mf, PUB_FILEMODE);
1471 #endif
1475 * converse with the remote machine, agree upon a
1476 * protocol (if possible) and start the protocol.
1477 * return:
1478 * SUCCESS -> successful protocol selection
1479 * FAIL -> can't find common or open failed
1482 startup(void)
1484 extern void blptcl();
1485 extern int fptcl();
1486 char msg[BUFSIZ], str[BUFSIZ];
1488 Rdmsg = imsg;
1489 Wrmsg = omsg;
1490 Turnoff = turnoff;
1491 blptcl(str);
1492 if (Role == MASTER) {
1493 RMESG(SLTPTCL, msg);
1494 if ( fptcl(&msg[1], str) == FAIL) {
1495 /* no protocol match */
1496 WMESG(USEPTCL, NO);
1497 return(FAIL);
1498 } else {
1499 /* got protocol match */
1500 WMESG(USEPTCL, &msg[1]);
1501 return(stptcl(&msg[1]));
1503 } else {
1504 WMESG(SLTPTCL, str);
1505 RMESG(USEPTCL, msg);
1506 if ( fptcl(&msg[1], str) == FAIL ) {
1507 return(FAIL);
1508 } else {
1509 return(stptcl(&msg[1]));
1515 * choose a protocol from the input string (str)
1516 * and return the found letter.
1517 * Use the MASTER string (valid) for order of selection.
1518 * return:
1519 * '\0' -> no acceptable protocol
1520 * any character -> the chosen protocol
1523 fptcl(str, valid)
1524 char *str, *valid;
1526 char *l;
1528 DEBUG(9, "Slave protocol list(%s)\n", str);
1529 DEBUG(9, "Master protocol list(%s)\n", valid);
1531 for (l = valid; *l != '\0'; l++) {
1532 if ( strchr(str, *l) != NULL) {
1533 *str = *l;
1534 *(str+1) = '\0';
1535 /* also update string with parms */
1536 strcpy(_Protocol, findProto(_Protocol, *str));
1537 return(SUCCESS);
1540 return(FAIL);
1544 * build a string of the letters of the available
1545 * protocols and return the string (str). The string consists of protocols
1546 * that are specified in the Systems and Devices files. If nothing was
1547 * specified in those files, then the string is the list of protocols from
1548 * our Ptble.
1550 * str = place to put the protocol list
1551 * length = size of buffer at str
1553 * return:
1554 * a pointer to string (str)
1556 void
1557 blptcl(str)
1558 char *str;
1560 struct Proto *p;
1561 char *validPtr;
1563 /* Build list of valid protocols. */
1564 for (validPtr = str, p = Ptbl; (*validPtr = p->P_id) != NULLCHAR;
1565 validPtr++, p++);
1567 /* Build _Protocol */
1568 (void) protoString(str); /* Get desired protocols. */
1569 return;
1573 * set up the six routines (Rdmg. Wrmsg, Rddata
1574 * Wrdata, Turnon, Turnoff) for the desired protocol.
1575 * returns:
1576 * SUCCESS -> ok
1577 * FAIL -> no find or failed to open
1580 stptcl(c)
1581 char *c;
1583 struct Proto *p;
1585 for (p = Ptbl; p->P_id != '\0'; p++) {
1586 if (*c == p->P_id) {
1589 * found protocol
1590 * set routine
1592 Rdmsg = p->P_rdmsg;
1593 Wrmsg = p->P_wrmsg;
1594 Rddata = p->P_rddata;
1595 Wrdata = p->P_wrdata;
1596 Turnon = p->P_turnon;
1597 Turnoff = p->P_turnoff;
1598 if ((*Turnon)() != 0)
1599 break;
1600 CDEBUG(4, "Proto started %c\n", *c);
1601 pfPtcl(c);
1602 return(SUCCESS);
1605 CDEBUG(4, "Proto start-fail %c\n", *c);
1606 return(FAIL);
1610 * unlink D. file
1611 * returns:
1612 * none
1614 void
1615 unlinkdf(file)
1616 char *file;
1618 if (strlen(file) > (size_t) 6)
1619 (void) unlink(file);
1620 return;
1624 * notify receiver of arrived file
1625 * returns:
1626 * none
1628 void
1629 arrived(opt, file, nuser, rmtsys, rmtuser)
1630 char *file, *nuser, *rmtsys, *rmtuser;
1632 char mbuf[200];
1634 if (!opt)
1635 return;
1636 (void) sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser);
1637 mailst(nuser, mbuf, mbuf, "", "");
1638 return;
1643 * Check to see if there is space for file
1646 #define FREESPACE 50 /* Minimum freespace in blocks to permit transfer */
1647 #define FREENODES 5 /* Minimum number of inodes to permit transfer */
1649 /*ARGSUSED*/
1650 static int
1651 nospace(name)
1652 char *name;
1653 #ifdef NOUSTAT
1654 {return(FALSE);}
1655 #else
1657 struct stat statb;
1658 #ifdef STATFS
1659 struct statfs statfsb;
1660 #else
1661 struct ustat ustatb;
1662 #endif
1664 if( stat(name, &statb) < 0 )
1665 return(TRUE);
1666 #ifdef RT
1667 if( (statb.st_mode|S_IFMT) == S_IFREG ||
1668 (statb.st_mode|S_IFMT) == S_IFEXT ||
1669 (statb.st_mode&S_IFMT) == S_IF1EXT )
1670 #else
1671 if( (statb.st_mode&S_IFMT) == S_IFREG )
1672 #endif
1674 #ifdef STATFS
1675 if( statfs(name, &statfsb)<0 )
1676 #else
1677 if( ustat(statb.st_dev, &ustatb)<0 )
1678 #endif
1679 return(TRUE);
1680 #ifdef STATFS
1682 * Use 512-byte blocks, because that's the unit "ustat" tends
1683 * to work in.
1685 if( ((statfsb.f_bavail*statfsb.f_bsize)/512) < FREESPACE )
1686 #else
1687 if( ustatb.f_tfree < FREESPACE )
1688 #endif
1690 logent("FREESPACE IS LOW","REMOTE TRANSFER DENIED - ");
1691 return(TRUE);
1693 #ifdef STATFS
1695 * The test for "> 0" is there because the @$%#@#@$ NFS
1696 * protocol doesn't pass the number of free files over the
1697 * wire, so "statfs" on an NFS file system always returns -1.
1699 if( statfsb.f_ffree > 0
1700 && statfsb.f_ffree < FREENODES )
1701 #else
1702 if( ustatb.f_tinode < FREENODES )
1703 #endif
1705 logent("TOO FEW INODES","REMOTE TRANSFER DENIED - ");
1706 return(TRUE);
1709 return(FALSE);
1711 #endif
1713 #ifdef V7USTAT
1715 ustat(dev, ustat)
1716 int dev;
1717 struct ustat *ustat;
1719 FILE *dfp, *popen();
1720 char *fval, buf[BUFSIZ];
1722 sprintf(buf, "%s %d %d 2>&1", V7USTAT, major(dev), minor(dev));
1723 if ((dfp = popen(buf, "r")) == NULL)
1724 return(-1);
1725 fval = fgets(buf, sizeof(buf), dfp);
1726 if (pclose(dfp) != 0
1727 || fval == NULL
1728 || sscanf(buf, "%d %d", &ustat->f_tfree, &ustat->f_tinode) != 2)
1729 return(-1);
1730 return(0);
1732 #endif /* V7USTAT */