|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T l
Length: 11210 (0x2bca) Types: TextFile Names: »loc_parent.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« └─⟦e5a54fb17⟧ └─⟦this⟧ »pp-5.0/Chans/822-local/loc_parent.c«
/* loc_parent.c: local delivery channel - parent process */ # ifndef lint static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/822-local/RCS/loc_parent.c,v 5.0 90/09/20 15:44:59 pp Exp Locker: pp $"; # endif /* * $Header: /cs/research/pp/hubris/pp-beta/Chans/822-local/RCS/loc_parent.c,v 5.0 90/09/20 15:44:59 pp Exp Locker: pp $ * * $Log: loc_parent.c,v $ * Revision 5.0 90/09/20 15:44:59 pp * rcsforce : 5.0 public release * */ /* Works as parent & child. New child for each message. Child does actual delivery of message, parent interacts with PP. */ #include "util.h" #include "retcode.h" #include "prm.h" #include "q.h" #include "dr.h" #include "qmgr.h" #include <isode/logger.h> #include <sys/stat.h> #include <sys/file.h> #include <signal.h> #include "loc_user.h" #ifndef USRPATH #define USRPATH "." #endif extern char *mquedir; extern char *quedfldir; extern CHAN *ch_nm2struct (); extern char *mboxname; extern char *delim1; extern char *delim2; extern char *hdr_822_bp; extern char *ad_getlocal (); extern void chan_init(), err_abrt(), rd_end(); CHAN *mychan; static char *this_msg; static int initproc (); static int douser (); static int deliver (); static void dirinit (); static struct type_Qmgr_DeliveryStatus *process (); Q_struct Qstruct; static char env_user[LINESIZE]; static char env_shell[LINESIZE]; static char env_home[LINESIZE]; int restrict = 0; char env_path[LINESIZE]; char *envp[] = { env_user, env_shell, env_home, env_path, NULLCP }; char *usrpathname = USRPATH; long message_size; int firstSuccessDR, firstFailDR; char *local_user; /* --------------------- Begin Routines --------------------------------- */ main (argc, argv) int argc; char **argv; { char *p; if (p = rindex(argv[0], '/')) p++; else p = argv[0]; /* -- Init the channel - and find out who we are -- */ chan_init (p); dirinit (); #ifdef PP_DEBUG if (argc > 1 && strcmp (argv[1], "debug") == 0) debug_channel_control (argc, argv, initproc, process, NULLIFP); else #endif channel_control (argc, argv, initproc, process, NULLIFP); exit (0); } static int initproc (arg) struct type_Qmgr_Channel *arg; { char *p; p = qb2str (arg); PP_TRACE (("initproc (%s)", p)); if ((mychan = ch_nm2struct (p)) == NULLCHAN) err_abrt (RP_PARM, "Channel '%s' not known", p); PP_NOTICE (("Starting %s (%s)", mychan -> ch_name, mychan -> ch_show)); if (lexequ (mychan -> ch_info, "restricted") == 0) restrict = 1; else restrict = 0; (void) signal (SIGCHLD, SIG_DFL); if (p) free (p); return OK; } static struct type_Qmgr_DeliveryStatus *process (arg) struct type_Qmgr_ProcMsg *arg; { struct type_Qmgr_UserList *up; struct prm_vars prm; Q_struct *qp = &Qstruct; ADDR *ad_sendr = NULL, *ad_recip = NULL; char msgq[FILNSIZE]; int ad_count, retval; bzero ((char *)&prm, sizeof prm); bzero ((char *)qp, sizeof *qp); firstFailDR = TRUE; firstSuccessDR = TRUE; if (this_msg) free (this_msg); this_msg = qb2str (arg -> qid); PP_NOTICE (("Processing msg %s", this_msg)); (void) sprintf (msgq, "%s%s", mquedir, this_msg); delivery_init (arg -> users); retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); if (rp_isbad (retval)) { PP_LOG (LLOG_EXCEPTIONS, ("rd_msg err: %s", this_msg)); return delivery_setallstate (int_Qmgr_status_messageFailure, "Can't read message"); } for (up = arg -> users; up; up = up -> next) douser (up -> RecipientId -> parm, ad_recip, msgq); rd_end(); prm_free (&prm); q_free (qp); return deliverystate; } /* Change into pp queue space */ static void dirinit () { PP_TRACE (("dirinit ()")); if (chdir (quedfldir) < 0) err_abrt (RP_LIO, "Uanble to change directory to '%s'", quedfldir); } /* * process one extension-id for this message */ static int douser (rno, ad_recip, msgd) int rno; ADDR *ad_recip; char *msgd; { ADDR *ap; PP_TRACE (("douser (%d, ad_recip, %s)", rno, msgd)); for (ap = ad_recip; ap ; ap = ap->ad_next) { if (rno != ap -> ad_no) continue; if (lchan_acheck (ap, mychan, 1, NULLVP) == NOTOK) return; else { deliver (ap, msgd); return; } } PP_LOG (LLOG_EXCEPTIONS, ("user not recipient of %s", this_msg)); delivery_setstate (rno, int_Qmgr_status_messageFailure, "user is not a recipient"); } static char *formatdir = NULLCP; /* Do the delivery */ static int deliver (ap, msgd) ADDR *ap; char *msgd; { char buffer[BUFSIZ], filename[FILNSIZE]; int hdr_fd, body_fd, retval; LocUser *loc; char *cp; PP_TRACE (("deliver msgd=%s", msgd)); if (local_user) free(local_user); if ((local_user = ad_getlocal (ap -> ad_r822adr, AD_822_TYPE)) == NULLCP) { (void) sprintf (buffer, "User %s not local!", ap -> ad_r822adr); PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer)); delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR); set_1dr (&Qstruct, ap -> ad_no, DRR_UNABLE_TO_TRANSFER, DRD_UA_UNAVAILABLE, buffer); wr_q2dr (&Qstruct, this_msg); return RP_USER; } if ((loc = tb_getlocal (local_user, mychan)) == NULL) { (void) sprintf (buffer, "User %s not registerd in channel table %s", local_user, mychan -> ch_name); PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer)); delivery_set (ap -> ad_no, (firstFailDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); firstFailDR = FALSE; set_1dr (&Qstruct, ap -> ad_no, DRR_UNABLE_TO_TRANSFER, DRD_UA_UNAVAILABLE, buffer); wr_q2dr (&Qstruct, this_msg); return RP_USER; } PP_TRACE (("Found entry for '%s' uid '%s' directory '%s' mailbox '%s'", ap -> ad_r822adr, loc -> username ? loc -> username : local_user, loc -> directory, loc -> mailbox)); if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) { PP_LOG (LLOG_EXCEPTIONS, ("Can't locate message %s", this_msg)); delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, "Can't find the message"); return RP_MECH; } if (rp_isbad (retval = msg_rinit (formatdir))) { PP_LOG (LLOG_EXCEPTIONS, ("msg_rinit can't init %s", formatdir)); delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, "can't read the body"); return RP_MECH; } if (msg_rfile (filename) != RP_OK) { PP_LOG (LLOG_EXCEPTIONS, ("Can't initialise hdr")); delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, "No message header"); msg_rend (); return RP_MECH; } if (cp = rindex (filename, '/')) cp ++; else cp = filename; if (lexnequ (cp, hdr_822_bp, strlen (hdr_822_bp)) != 0) { PP_LOG (LLOG_EXCEPTIONS, ("Bad header type, %s", cp)); delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR); set_1dr (&Qstruct, ap -> ad_no, DRR_UNABLE_TO_TRANSFER, DRD_IMPLICITCONV_NOTREGISTERED, "Header of message is not RFC-822 based"); wr_q2dr (&Qstruct, this_msg); msg_rend (); return RP_MECH; } if ((hdr_fd = open (filename, O_RDONLY, 0)) < 0) { PP_SLOG (LLOG_EXCEPTIONS, filename, ("Can't open file")); (void) sprintf (buffer, "Can't open file %s", filename); delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, buffer); return RP_MECH; } switch (msg_rfile (filename)) { case RP_OK: if ((body_fd = open (filename, O_RDONLY, 0)) < 0) { PP_SLOG (LLOG_EXCEPTIONS, filename, ("Can't open file")); (void) sprintf (buffer, "Can't open file %s", filename); delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, buffer); (void) close (hdr_fd); msg_rend (); return RP_MECH; } break; case RP_DONE: PP_NOTICE (("Message with header part only")); if ((body_fd = open ("/dev/null", O_RDONLY, 0)) < 0) { PP_SLOG (LLOG_EXCEPTIONS, "/dev/null", ("Can't open file")); delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); (void) close (hdr_fd); msg_rend (); return RP_MECH; } break; default: PP_LOG (LLOG_EXCEPTIONS, ("Can't initialise body")); delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, "Can't initialise body"); (void) close (hdr_fd); msg_rend (); return RP_MECH; } if (msg_rfile (filename) != RP_DONE) { PP_LOG (LLOG_EXCEPTIONS, ("Extra body parts in message %s", this_msg)); delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR); set_1dr (&Qstruct, ap -> ad_no, DRR_UNABLE_TO_TRANSFER, DRD_IMPLICITCONV_NOTREGISTERED, "Extra body part that has not been converted to 822"); wr_q2dr (&Qstruct, this_msg); (void) close (hdr_fd); (void) close (body_fd); msg_rend (); return RP_USER; } msg_rend (); /* set up the env */ (void) sprintf (env_home, "HOME=%s", loc -> home ? loc -> home : (loc -> directory ? loc -> directory : ".")); (void) sprintf (env_shell, "SHELL=%s", loc -> shell ? loc -> shell : "/bin/sh"); (void) sprintf (env_user, "USER=%s", loc -> username ? loc -> username : local_user); (void) sprintf (env_path, "PATH=%s", USRPATH); message_size = Qstruct.msgsize; retval = child_process (loc, hdr_fd, body_fd); (void) close (hdr_fd); (void) close (body_fd); switch (retval) { case int_Qmgr_status_negativeDR: { char buf[LINESIZE]; (void) sprintf (buf, "Delivery to %s (%d) failed", loc -> username ? loc -> username : local_user, loc -> uid); set_1dr (&Qstruct, ap -> ad_no, DRR_TRANSFER_FAILURE, DRD_UA_UNAVAILABLE, buf); wr_q2dr (&Qstruct, this_msg); delivery_set (ap -> ad_no, (firstFailDR == TRUE) ? retval : int_Qmgr_status_failureSharedDR); firstFailDR = FALSE; free_loc_user (loc); return RP_MECH; } break; case int_Qmgr_status_success: break; case int_Qmgr_status_mtaFailure: case int_Qmgr_status_messageFailure: case int_Qmgr_status_mtaAndMessageFailure: delivery_set (ap -> ad_no, retval); free_loc_user (loc); return RP_MECH; case NOTOK: default: PP_LOG (LLOG_EXCEPTIONS, ("child process failed")); delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, "Child process failed"); free_loc_user (loc); return RP_MECH; } if (loc -> username) PP_NOTICE ((">>> local : Message delivered to %s (%s)", local_user, loc -> username)); else PP_NOTICE ((">>> local: Message delivered to %s (id %d/%d)", local_user, loc -> uid, loc -> gid)); free_loc_user (loc); if (ap -> ad_usrreq == AD_USR_CONFIRM || ap -> ad_mtarreq == AD_MTA_CONFIRM || ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { set_1dr (&Qstruct, ap -> ad_no, DRR_NO_REASON, -1, NULLCP); wr_q2dr (&Qstruct, this_msg); delivery_set (ap -> ad_no, (firstSuccessDR == TRUE) ? int_Qmgr_status_positiveDR : int_Qmgr_status_successSharedDR); } else { (void) wr_ad_status (ap, AD_STAT_DONE); delivery_set (ap -> ad_no, int_Qmgr_status_success); } return RP_OK; }