cntrl.c revision 462be471126495414a94f9fa35e16c02dc462c04
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include "uucp.h"
#include "log.h"
static void stmesg();
static int nospace();
struct Proto {
char P_id;
int (*P_turnon)();
int (*P_rdmsg)();
int (*P_wrmsg)();
int (*P_rddata)();
int (*P_wrdata)();
int (*P_turnoff)();
};
extern char _Protocol[];
extern char *findProto();
extern char uuxqtarg[];
#ifdef D_PROTOCOL
#endif /* D_PROTOCOL */
#ifdef X_PROTOCOL
#endif /* X_PROTOCOL */
#ifdef E_PROTOCOL
#endif /* E_PROTOCOL */
#ifdef F_PROTOCOL
#endif /* F_PROTOCOL */
extern int imsg();
extern int omsg();
extern int turnoff();
extern long strtol();
#ifdef E_PROTOCOL
#endif /* E_PROTOCOL */
#ifdef D_PROTOCOL
#endif /* D_PROTOCOL */
#ifdef X_PROTOCOL
#endif /* X_PROTOCOL */
#ifdef F_PROTOCOL
#endif /* F_PROTOCOL */
'\0'
};
#define YES "Y"
#define NO "N"
/*
* failure messages
*/
#define EM_MAX 10
/* EM_ "N8" */ /* placeholder*/
/* EM_ "N9" */ /* placeholder*/
char *Em_msg[] = {
"COPY FAILED (reason not given by remote)",
"local access to file denied",
"system error - bad uucp command generated",
"remote system can't create temp file",
"can't seek to checkpoint",
"COPY FAILED (reason not given by remote)", /* placeholder */
"COPY FAILED (reason not given by remote)", /* placeholder */
"file exceeds ulimit of receiving system",
"forwarding error"
};
char *mf;
char Dfile[MAXFULLNAME];
int statfopt;
/*
* Create restart point filename
*/
static void
char *fileid;
char *dfile;
int direct; /* indicates a direct delivery temp file nameneeded */
{
char *p;
/*
* If the file is direct delivery, then its name is:
*
*
* in the target directory. We create this by replacing the
* name of the target file with the D.nnnnnn name from the
* work vector, and then overwriting the D. with .P
*/
if (direct) {
p++;
*p++ = '.';
*p = 'P'; /* replace beginning with .P */
return;
}
}
*p = 'P';
return;
}
/*
* execute the conversation between the two machines
* after both programs are running.
* returns:
* SUCCESS -> ok
* FAIL -> failed
*/
int
cntrl()
{
char * p;
long startp; /* checkpoint restart point */
long actualsize; /* actual file size */
long im;
long lfilemode;
int status;
int i, narg;
int ret;
extern int uuxqtflag; /* set if received X. or D. file */
Wfile[0] = '\0';
top:
statfopt = 0;
*Jobid = '\0';
/*
* get work
*/
pfFindFile();
goto process;
}
/*
* We used to check for corrupt workfiles here (narg < 5),
* but we were doing it wrong, and besides, anlwrk.c is the
* appropriate place to do it.
*/
/* log destination node, user and file name */
/* log source node, file owner, file name, mod time and size */
/* cannot read spool or original file */
scWrite(); /* log the security violation */
goto top;
} else {
/* ensure original file is publicly readable */
/* access denied */
scWrite(); /* log the security violation */
goto top;
}
}
}
}
/* Check whether remote's ulimit is exceeded */
if (SizeCheck) {
/* remote ulimit exceeded */
scWrite();
goto top;
}
}
}
/* log destination node, user and file name */
/* log source node, file owner, file name, mod time and size */
** requested is needed for some remote execution.
*/
/* now change Wrkdir back to what it was
** just being paranoid.
*/
/* access denied */
filename);
scWrite(); /* log the security violation */
goto top;
}
/*
* If we are not going to spool the file in the spool
* directory, just use the destination file name. If we
* are not supporting restart, wipe out the target file.
* else:
*
* If restart is enabled, make up the Point file name
* as the file to open, else use the TM style name.
*
* If we run into a spool name of "D.0", this implies
* that someone forgot to install the new uucp and
* uux commands. Such jobs will not be checkpointed.
*/
if (noSpool()) {
}
else
}
else {
}
/*
* If the spool file exists, it better have the right owner
* and permissions!
*/
"bad spool file ownership/permissions");
goto top;
}
}
/* can not create temp */
if (noSpool())
else
}
/*
* Send the W_POINT value to the other side.
*/
if (Restart) {
}
/*
* find a good start point. Take care of simple
* underflow and the signed nature of longs.
*/
startp = 0;
if(startp)
{
if(startp < 0)
else
}
goto top;
}
}
Seqn++;
}
/* Build up the message itself */
msg[0] = '\0';
for (i = 1; i < narg; i++) {
}
goto process;
}
/*
* role is slave
*/
switch (msg[0]) {
case RQSTCMPT:
if (i < 0 || i > EM_MAX)
i = 0;
}
}
goto top;
case HUP:
(*Turnoff)();
return(0);
}
goto top;
}
/*
* get work
*/
goto process;
}
/* Note that Wfile is the first C. to process at top
* set above by iswrk() call
*/
if (uuxqtflag) {
uuxqtflag = 0;
}
acInit("xfer");
goto top;
case XUUCP:
/*
* slave part
* No longer accepted
*/
goto top;
case SNDFILE:
/*
* MASTER section of SNDFILE
*/
{
if (i < 0 || i > EM_MAX)
i = 0;
/* if remote is out of tmp space, then just hang up */
scWrite(); /* something is wrong on other side,
log the security violation */
Seqn++;
goto top;
}
/*
* send file
*/
/*
* If checkpoint restart is enabled, seek to the
* starting point in the file. We use hex because
* C doesn't support unsigned long directly.
*/
if (Restart) {
if(startp < 0)
else
else
errno = 0;
(*Turnoff)();
Seqn++;
return(FAIL);
}
}
}
(void) millitick(); /* start msec timer */
scStime(); /* log start transfer time for security log */
/* (ret != 0) implies the trammission error occurred.
If checkpoint protocol is available then the next
transfer will restart from the breakpoint of the file,
otherwise from the beginning of the file */
/* the second millitick() returns the duration between
the first and second call.
writes "PARTIAL FILE to the transfer log indicating
a transmission error. */
acInc(); /* increment job size in accounting log */
pfEndXfer();
scEtime(); /* log end transfer time for security log */
Seqn++;
if (ret != 0) {
pfEndfile("PARTIAL FILE");
(*Turnoff)();
return(FAIL);
}
/* loop depending on the size of the file */
/* give an extra try for each megabyte */
break; /* got message */
}
if (ret != 0) {
(*Turnoff)();
return(FAIL);
}
goto process;
}
/*
* SLAVE section of SNDFILE
*/
/*
* request to receive file
* check permissions
*/
/* log destination node, user and file name */
/* log source node, file owner, file name, mod time and size */
/* Check for bad request */
if (i < W_MIN) {
bad work file */
goto top;
}
/* SLAVE gets the original filesize from sender (MASTER) */
/* This will be used to check the length of the P. file */
if (Restart) {
} else {
actualsize = -1;
}
}
send data to this file(directory) */
scWrite(); /* log security violation */
goto top;
}
if (noSpool()) {
if (! Restart)
}
else
}
else {
}
/*
* If the spool file exists, it better have the right owner
* and permissions!
*/
goto top;
}
}
goto top;
}
Seqn++;
goto top;
}
/*
* find a good start point. Take care of simple underflow
* and the signed nature of longs.
*/
startp = 0;
if(startp)
{
if(startp < 0)
else
}
Seqn++;
goto top;
}
}
else
(void) millitick(); /* start msec timer */
scStime(); /* log start transfer time for security log */
/* (ret != 0) implies the trammission error occurred.
If checkpoint protocol is available then the next
recieve will restart from the breakpoint of the file,
otherwise from the beginning of the file */
/* the second millitick() returns the duration between
the first and second call.
writes "PARTIAL FILE to the transfer log indicating
a transmission error. */
pfEndXfer();
scEtime(); /* log end transfer time for security log */
Seqn++;
if (ret != 0) {
pfEndfile("PARTIAL FILE");
goto top;
}
(*Turnoff)();
return(FAIL);
}
(*Turnoff)();
return(FAIL);
}
(*Turnoff)();
return(FAIL);
}
}
/* copy to user directory */
/*
* See if spool file and target file in the same file system
*/
ret = 0;
{
*p = '\0';
*p = '/';
}
{
/*
* if we are not already in the right file, and
* it is theoretically in the same file system,
* link it there...
*/
{
scWrite();
}
else
}
else
status = 0; /* all done */
}
else
if (status == 0) {
if (lfilemode <= 0)
else
else
} else {
scWrite(); /* log the security violation */
if (status == 0)
}
uuxqtflag = 1;
goto top;
case RCVFILE:
/*
* MASTER section of RCVFULE
*/
if (i < 0 || i > EM_MAX)
i = 0;
scWrite(); /* something is wrong on other side,
log the security violation */
goto top;
}
/* MASTER gets the original filesize from sender (SLAVE) */
/* This will be used to check the length of the P. file */
if (Restart) {
*fsize = '\0';
if (*fsize != '\0') {
} else {
actualsize = -1;
}
}
/*
* receive file
*/
(void) millitick(); /* start msec timer */
scStime();
/* (ret != 0) implies the trammission error occurred.
If checkpoint protocol is available then the next
recieve will restart from the breakpoint of the file,
otherwise from the beginning of the file */
/* the second millitick() returns the duration between
the first and second call.
writes "PARTIAL FILE to the transfer log indicating
a transmission error. */
pfEndXfer();
scEtime();
if (ret != 0) {
pfEndfile("PARTIAL FILE");
goto top;
}
(*Turnoff)();
return(FAIL);
}
(*Turnoff)();
return(FAIL);
}
(*Turnoff)();
return(FAIL);
}
}
/*
* See if spool file and target file in the same file system
*/
ret = 0;
{
*p = '\0';
*p = '/';
}
{
/*
* if we are not already in the right file, and
* it is theoretically in the same file system,
* link it there...
*/
{
scWrite();
}
else
}
else
status = 0; /* all done */
}
else
if (status == 0) {
if (lfilemode <= 0)
else
else
} else {
scWrite(); /* log the security violation */
}
uuxqtflag = 1;
goto top;
}
/*
* SLAVE section of RCVFILE
* (request to send file)
*/
/* check permissions */
/* log destination node, user and file name */
/* log source node, file owner, file name, mod time and size */
/* Check for bad request */
if (i < 5) {
bad work file */
goto top;
}
}
/* remote can't request data from my system */
scWrite(); /* log the security violation */
goto top;
}
read my file */
scWrite(); /* log the security violation */
goto top;
}
retrive my file */
scWrite(); /* log the security violation */
goto top;
}
/* Check whether remote's ulimit is exceeded */
if (SizeCheck) {
/* remote ulimit exceeded */
scWrite();
goto top;
}
}
/*
* ok to send file
*/
if (Restart && i >= 10) {
errno = 0;
goto top;
}
if(startp < 0)
else
else
}
}
if (Restart)
else
Seqn++;
(void) millitick(); /* start msec timer */
scStime();
/* (ret != 0) implies the trammission error occurred.
If checkpoint protocol is available then the next
transfer will restart from the breakpoint of the file,
otherwise from the beginning of the file */
/* the second millitick() returns the duration between
the first and second call.
writes "PARTIAL FILE to the transfer log indicating
a transmission error. */
pfEndXfer();
scEtime();
if (ret != 0) {
pfEndfile("PARTIAL FILE");
(*Turnoff)();
return(FAIL);
}
/* loop depending on the size of the file */
/* give an extra try for each megabyte */
/* stbuf set in fstat several lines back */
break; /* got message */
}
if (ret != 0) {
(*Turnoff)();
return(FAIL);
}
goto process;
}
(*Turnoff)();
return(FAIL);
}
/*
* read message
* returns:
* 0 -> success
* FAIL -> failure
*/
int
char *msg, c;
{
char str[50];
return(FAIL);
}
if (c != '\0' && msg[0] != c) {
return(FAIL);
}
return(0);
}
/*
* write a message
* returns:
* 0 -> ok
* FAIL -> ng
*/
int
wmesg(m, s)
char *s, m;
{
}
/*
* mail results of command
* return:
* none
*/
void
char *msgcode;
{
int i;
char *msg;
return;
if (*msgcode == 'Y')
msg = "copy succeeded";
else {
if (i < 1 || i > EM_MAX)
i = 0;
}
if(statfopt){
return;
}
return;
}
/*
* local notify
* return:
* none
*/
void
{
if(statfopt){
return;
}
return;
}
/*ARGSUSED*/
static void
stmesg(f, m)
char *f, *m;
{
#ifdef notdef
#endif
#ifdef notdef
/*
* This code is a giant security hole.
* No checking is done on what file is
* written and chmod'ed. For now we
* just ifdef this out.
*/
return;
}
td /= 60;
td /= 60;
#endif
}
/*
* converse with the remote machine, agree upon a
* protocol (if possible) and start the protocol.
* return:
* SUCCESS -> successful protocol selection
* FAIL -> can't find common or open failed
*/
int
startup(void)
{
extern void blptcl();
extern int fptcl();
/* no protocol match */
return(FAIL);
} else {
/* got protocol match */
}
} else {
return(FAIL);
} else {
}
}
}
/*
* choose a protocol from the input string (str)
* and return the found letter.
* Use the MASTER string (valid) for order of selection.
* return:
* '\0' -> no acceptable protocol
* any character -> the chosen protocol
*/
int
{
char *l;
for (l = valid; *l != '\0'; l++) {
*str = *l;
/* also update string with parms */
return(SUCCESS);
}
}
return(FAIL);
}
/*
* build a string of the letters of the available
* protocols and return the string (str). The string consists of protocols
* that are specified in the Systems and Devices files. If nothing was
* specified in those files, then the string is the list of protocols from
* our Ptble.
*
* str = place to put the protocol list
* length = size of buffer at str
*
* return:
* a pointer to string (str)
*/
void
char *str;
{
struct Proto *p;
char *validPtr;
/* Build list of valid protocols. */
validPtr++, p++);
/* Build _Protocol */
return;
}
/*
* set up the six routines (Rdmg. Wrmsg, Rddata
* Wrdata, Turnon, Turnoff) for the desired protocol.
* returns:
* SUCCESS -> ok
* FAIL -> no find or failed to open
*/
int
stptcl(c)
char *c;
{
struct Proto *p;
if (*c == p->P_id) {
/*
* found protocol
* set routine
*/
if ((*Turnon)() != 0)
break;
pfPtcl(c);
return(SUCCESS);
}
}
return(FAIL);
}
/*
* unlink D. file
* returns:
* none
*/
void
char *file;
{
return;
}
/*
* notify receiver of arrived file
* returns:
* none
*/
void
{
char mbuf[200];
if (!opt)
return;
return;
}
/*
* Check to see if there is space for file
*/
/*ARGSUSED*/
static int
char *name;
#ifdef NOUSTAT
{return(FALSE);}
#else
{
#ifdef STATFS
#else
#endif
return(TRUE);
#ifdef RT
#else
#endif
{
#ifdef STATFS
#else
#endif
return(TRUE);
#ifdef STATFS
/*
* Use 512-byte blocks, because that's the unit "ustat" tends
* to work in.
*/
#else
#endif
{
return(TRUE);
}
#ifdef STATFS
/*
* The test for "> 0" is there because the @$%#@#@$ NFS
* protocol doesn't pass the number of free files over the
* wire, so "statfs" on an NFS file system always returns -1.
*/
#else
#endif
{
return(TRUE);
}
}
return(FALSE);
}
#endif
#ifdef V7USTAT
int
int dev;
{
return(-1);
return(-1);
return(0);
}
#endif /* V7USTAT */