rtfd.c

来自「ftam等标准协议服务器和客户端的源代码。」· C语言 代码 · 共 485 行

C
485
字号
/* rtfd.c - RT-file transfer utility -- responder */#ifndef	lintstatic char *rcsid = "$Header: /xtel/isode/isode/others/rtf/RCS/rtfd.c,v 9.0 1992/06/16 12:48:07 isode Rel $";#endif/*  * $Header: /xtel/isode/isode/others/rtf/RCS/rtfd.c,v 9.0 1992/06/16 12:48:07 isode Rel $ * * * $Log: rtfd.c,v $ * Revision 9.0  1992/06/16  12:48:07  isode * Release 8.0 * *//* *				  NOTICE * *    Acquisition, use, and distribution of this module and related *    materials are subject to the restrictions of a license agreement. *    Consult the Preface in the User's Manual for the full terms of *    this agreement. * */#include "RTF-types.h"#include "rtf.h"#include <pwd.h>#ifdef	SYS5struct passwd *getpwnam ();#include <crypt.h>#endif#ifndef	ANON#define	ANON	"ftp"#endif/*    DATA */static int debug = 0;static char *myname = "rtfd";static int    fd;static int    nbytes;static char  *destination;int	downtrans (), uptrans ();/*    MAIN *//* ARGSUSED */main (argc, argv, envp)int	argc;char  **argv,      **envp;{    int	    guest,	    sd,	    result,	    turn;    register char *cp,		  *user;    register struct passwd *pw;    struct RtSAPstart   rtss;    register struct RtSAPstart *rts = &rtss;    struct RtSAPindication  rtis;    register struct RtSAPindication *rti = &rtis;    register struct RtSAPabort   *rta = &rti -> rti_abort;    struct type_RTF_Request *req;    if (myname = rindex (argv[0], '/'))	myname++;    if (myname == NULL || *myname == NULL)	myname = argv[0];    isodetailor (myname, 0);    if (debug = isatty (fileno (stderr)))	ll_dbinit (pgm_log, myname);    else	ll_hdinit (pgm_log, myname);    advise (LLOG_NOTICE, NULLCP, "starting");    if (RtBInit (argc, argv, rts, rti) == NOTOK)	rts_adios (rta, "(RtB)initialization fails");    advise (LLOG_NOTICE, NULLCP,	    "RT-BEGIN.INDICATION: <%d, %s, %s, <%d, %s>, 0x%x>",	    rts -> rts_sd, rts -> rts_mode == RTS_TWA ? "twa" : "monologue",	    rts -> rts_turn == RTS_RESPONDER ? "responder" : "initiator",	    ntohs (rts -> rts_port),	    saddr2str (&rts -> rts_initiator.rta_addr),	    rts -> rts_data);    sd = rts -> rts_sd;    if (rts -> rts_data == NULLPE) {	advise (LLOG_EXCEPTIONS, NULLCP, "rejected -- no user-data parameter");reject: ;	if (RtBeginResponse (sd, RTS_REJECT, NULLPE, rti) == NOTOK)	    rts_adios (rta, "RT-BEGIN.RESPONSE (reject)");	exit (1);    }    req = NULL;    if (decode_RTF_Request (rts -> rts_data, 1, NULLIP, NULLVP, &req)	    == NOTOK) {	advise (LLOG_EXCEPTIONS, NULLCP,		"rejected -- error decoding request: %s", PY_pepy);	goto reject;    }    PLOGP (pgm_log,RTF_Request, rts -> rts_data, "Request", 1);    if (qb_pullup (req -> user) == NOTOK) {no_mem: ;        advise (LLOG_EXCEPTIONS, NULLCP, "rejected -- out of memory");	goto reject;    }    if (qb_pullup (req -> password) == NOTOK)	goto no_mem;    if ((cp = qb2str (req -> file)) == NULL)	goto no_mem;    guest = 0;    advise (LLOG_NOTICE, NULLCP, "%s: %s \"%s\"",	    user = req -> user -> qb_forw -> qb_data,	    (turn = rts -> rts_turn) == RTS_RESPONDER ? "get" : "put", cp);    if (strcmp (cp, "ANON") == 0 || strcmp (user, ANON) == 0) {	if ((pw = getpwnam (ANON)) && pw -> pw_uid == 0)	    pw = NULL;	guest = 1;    }    else	pw = baduser (NULLCP, user) ? NULL : getpwnam (user);    if (pw == NULL) {	advise (LLOG_EXCEPTIONS, NULLCP, "rejected -- no such user");no_validate: ;	if (RtBeginResponse (sd, RTS_VALIDATE, NULLPE, rti) == NOTOK)	    rts_adios (rta, "RT-BEGIN.RESPONSE (validate)");	exit (1);    }    if (*pw -> pw_passwd == NULL	    || (!guest && strcmp (crypt (req -> password -> qb_forw -> qb_data,					 pw -> pw_passwd), pw -> pw_passwd))) {	advise (LLOG_EXCEPTIONS, NULLCP,		"authentication failure for \"%s\"%s requesting %s of \"%s\"",		user, guest ? " (guest)" : "",		(turn = rts -> rts_turn) == RTS_RESPONDER ? "get" : "put",		cp);	goto no_validate;    }        if (chdir (pw -> pw_dir) == NOTOK) {	advise (LLOG_EXCEPTIONS, pw -> pw_dir,		"unable to change directory to");no_dice: ;        if (RtBeginResponse (sd, RTS_BUSY, NULLPE, rti) == NOTOK)	    rts_adios (rta, "RT-BEGIN.RESPONSE (busy)");	exit (1);    }    if (guest && chroot (pw -> pw_dir) == NOTOK) {	advise (LLOG_EXCEPTIONS, pw -> pw_dir,		"unable to change root to");	goto no_dice;    }    (void) setgid (pw -> pw_gid);#ifndef	SYS5    (void) initgroups (pw -> pw_name, pw -> pw_gid);#endif    (void) setuid (pw -> pw_uid);    (void) umask (0022);    if (turn == RTS_RESPONDER) {	if ((fd = open (cp, O_RDONLY, 0x00)) == NOTOK) {	    advise (LLOG_EXCEPTIONS, cp, "rejected -- unable to open");	    goto reject;	}	free (cp);    }    else	destination = cp;    free_RTF_Request (req);    RTSFREE (rts);    if (RtBeginResponse (sd, RTS_ACCEPT, NULLPE, rti) == NOTOK)	rts_adios (rta, "RT-BEGIN.RESPONSE (accept)");    if (turn == RTS_RESPONDER) {	if (RtSetDownTrans (sd, downtrans, rti) == NOTOK)	    rts_adios (rta, "set DownTrans upcall");	if (RtTransferRequest (sd, NULLPE, NOTOK, rti) == NOTOK)	    rts_adios (rta, "RT-TRANSFER.REQUEST");	if (nbytes == 0)	    advise (LLOG_NOTICE, NULLCP, "transfer complete");	else	    timer (nbytes);	(void) close (fd);    }    else	if (RtSetUpTrans (sd, uptrans, rti) == NOTOK)	    rts_adios (rta, "set UpTrans upcall");    for (;;) {	switch (result = RtWaitRequest (sd, NOTOK, rti)) {	    case NOTOK:	    case OK:	    case DONE:	        break;	    default:		adios (NULLCP, "unknown return from RtWaitRequest=%d",		       result);	}	switch (rti -> rti_type) {	    case RTI_TURN:	        {		    register struct RtSAPturn *rtu = &rti -> rti_turn;		    if (rtu -> rtu_please) {			if (RtGTurnRequest (sd, rti) == NOTOK)			    rts_adios (rta, "RT-TURN-GIVE.REQUEST");		    }		    else			adios (NULLCP, "protocol screw-up");		}		continue;	    case RTI_TRANSFER:		{#ifndef	lint		    register struct RtSAPtransfer *rtt = &rti -> rti_transfer;#endif		    if (nbytes == 0)			advise (LLOG_NOTICE, NULLCP, "transfer complete");		    else			timer (nbytes);		}		continue;	    case RTI_ABORT:		{		    register struct RtSAPabort *rtb = &rti -> rti_abort;		    if (rtb -> rta_peer)			rts_adios (rtb, "RT-U-ABORT.INDICATION");		    if (RTS_FATAL (rtb -> rta_reason))			rts_adios (rtb, "RT-P-ABORT.INDICATION");		    rts_advise (rtb, "RT-P-ABORT.INDICATION");		}		break;	    case RTI_CLOSE:		{#ifndef	lint		    register struct RtSAPclose *rtc = &rti -> rti_close;#endif		    advise (LLOG_NOTICE, NULLCP, "RT-END.INDICATION");		    if (RtEndResponse (sd, rti) == NOTOK)			rts_adios (rta, "RT-END.RESPONSE");		}		break;	    case RTI_FINISH:		adios (NULLCP, "unexpected indication type=%d",		       rti -> rti_type);	    default:		adios (NULLCP, "unknown indication type=%d", rti -> rti_type);	    }	break;    }    exit (0);}/*     TRANSFER *//* ARGSUSED */static int  downtrans (sd, base, len, size, ssn, ack, rti)int	sd;char  **base;int    *len,	size;long	ssn,	ack;struct RtSAPindication *rti;{    register int    cc;    int	    n;    register char *dp,		  *ep;    static int bsize;    static char *bp = NULL;    if (base == NULLVP) {#ifdef	DEBUG	advise (LLOG_DEBUG, NULLCP, "RT-PLEASE.INDICATION: %d", size);#endif	return OK;    }    if (bp == NULL) {	struct stat st;	if (fstat (fd, &st) == NOTOK)	    return rtsaplose (rti, RTS_TRANSFER, destination,			      "unable to fstat");#ifdef	MAXBSIZE	bsize = st.st_blksize > 0 ? st.st_blksize : BUFSIZ;#else	bsize = BUFSIZ;#endif	if (size == 0)	/* no checkpointing... */	    n = st.st_size;	else	    if ((n = bsize) > size)		n = size;	if ((bp = malloc ((unsigned) n)) == NULL)	    return rtsaplose (rti, RTS_CONGEST, NULLCP, "out of memory");#ifdef	DEBUG	advise (LLOG_DEBUG, NULLCP, "Selecting block size of %d", n);	advise (LLOG_DEBUG, NULLCP,		"  based on blksize of %d and RTTR size of %d",		bsize, size);#endif	bsize = n;	timer (nbytes = 0);    }    *base = NULLCP, *len = 0;    for (ep = (dp = bp) + (cc = bsize); dp < ep; dp += n, cc -= n) {	switch (n = read (fd, dp, cc)) {	    case NOTOK:	        return rtsaplose (rti, RTS_TRANSFER, "failed", "read");	    default:		continue;	    case OK:		break;	}	break;    }    if ((cc = dp - bp) > 0) {	*base = bp, *len = cc;	nbytes += cc;    }    return OK;}/*  *//* ARGSUSED */static int  uptrans (sd, type, addr, rti)int	sd;int	type;caddr_t	addr;struct RtSAPindication *rti;{    switch (type) {	case SI_DATA:	    {		register struct qbuf *qb = (struct qbuf *) addr;		register struct qbuf *qp;		for (qp = qb -> qb_forw; qp != qb; qp = qp -> qb_forw)		    if (write (fd, qp -> qb_data, qp -> qb_len) !=qp -> qb_len)			return rtsaplose (rti, RTS_TRANSFER, "failed","write");		    else			nbytes += qp -> qb_len;	    }	    break;	case SI_SYNC:	    {#ifdef	DEBUG		register struct SSAPsync *sn = (struct SSAPsync *) addr;		advise (LLOG_DEBUG, NULLCP, "S-MINOR-SYNC.INDICATION: %ld",			sn -> sn_ssn);#endif	    }	    break;	case SI_ACTIVITY:	    {		register struct SSAPactivity *sv = (struct SSAPactivity *)addr;		switch (sv -> sv_type) {		    case SV_START:#ifdef	DEBUG			advise (LLOG_DEBUG, NULLCP,				"S-ACTIVITY-START.INDICATION");#endif		        if ((fd = creat (destination, 0666)) == NOTOK) {			    advise (LLOG_EXCEPTIONS, destination,				    "unable to create");			    return rtsaplose (rti, RTS_TRANSFER, destination,					      "unable to create");			}			timer (nbytes = 0);		        break;		    case SV_INTRIND:		    case SV_DISCIND:			advise (LLOG_EXCEPTIONS, NULLCP,				"activity %s: %s",				sv -> sv_type == SV_INTRIND ? "interrupted"							    : "discarded",				SReportString (sv -> sv_reason));			remove (destination);			break;		    case SV_ENDIND:#ifdef	DEBUG			advise (LLOG_DEBUG, NULLCP,				"S-ACTIVITY-END.INDICATION");#endif			if (close (fd) == NOTOK)			    return rtsaplose (rti, RTS_TRANSFER, destination,					      "close failed on");			break;		    default:			return rtsaplose (rti, RTS_TRANSFER, NULLCP,				       "unexpected activity indication=0x%x",				       sv -> sv_type);		}	    }	    break;	case SI_REPORT:	    {		register struct SSAPreport *sp = (struct SSAPreport *) addr;		if (!sp -> sp_peer)		    return rtsaplose (rti, RTS_TRANSFER, NULLCP,			     "unexpected provider-initiated exception report");		advise (LLOG_EXCEPTIONS, NULLCP,			"exception: %s", SReportString (sp -> sp_reason));		remove (destination);	    }	    break;	default:	    return rtsaplose (rti, RTS_TRANSFER, NULLCP,			      "unknown uptrans type=0x%x", type);    }    return OK;}/*  */static	remove (file)char   *file;{    struct stat st;    if (stat (file, &st) != NOTOK	    && (st.st_mode & S_IFMT) == S_IFREG	    && unlink (file) == NOTOK)	advise (LLOG_EXCEPTIONS, file, "unable to unlink");}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?