Ejemplo n.º 1
0
int main(int argc, char **argv)
{
	if (getuid() == 0)
		libmail_changeuidgid(MAILUID, MAILGID);
			/* Drop root privileges */
	if (chdir(courierdir()) < 0)
	{
		perror("courierdir");
		return (1);
	}

	if (argc > 1)
	{
		if (strcmp(argv[1], "stop") == 0)
		{
			stop();
			return (0);
		}
		if (strcmp(argv[1], "start") == 0)
		{
			return (start());
		}
		if (strcmp(argv[1], "restart") == 0)
		{
			return (restart());
		}
	}
	fprintf(stderr, "Usage: %s (stop|restart|start)\n", argv[0]);
	return (1);
}
Ejemplo n.º 2
0
Archivo: pcpd.c Proyecto: zixia/nospam
static int callback_cache_search(uid_t u, gid_t g, const char *dir, void *vp)
{
	struct relogin_struct *rs=(struct relogin_struct *)vp;
	time_t login_time, now;
	int reset_flag;
	char *token=NULL;

	login_time=rs->when;
	time(&now);

	reset_flag= login_time <= now - TIMEOUT;

	if (reset_flag)
	{
		if (rs->needauthtoken)
		{
			token=authtoken_create(rs->userid, now);
			if (!token)
			{
				syslog(LOG_ALERT,
				       "pcpd: authtoken_create() failed.");
				return (1);
			}
		}
		maildir_cache_start();
	}

	libmail_changeuidgid(u, g);

	if (chdir(dir) < 0)
	{
		maildir_cache_cancel();
		syslog(LOG_NOTICE, "pcpd: chdir(%s) failed.", dir);
		return (-1);
	}

	alarm(0);
	if (reset_flag)
	{
		maildir_cache_save(rs->userid, now, dir, u, g);
		if (rs->needauthtoken)
		{
			printf("102 %s logged in.\n", token);
			free(token);
		}
	}
	else if (rs->needauthtoken)	/* Not a proxy connection */
		printf("200 Ok\n");
	return (0);
}
Ejemplo n.º 3
0
static void setuidgid(const char *userarg,
		      const char *grouparg)
{
	if (grouparg)
	{
	gid_t gid = 0;
	struct group *gr;
	
		if (isid(grouparg))
			gid=atoi(grouparg);
		else if ((gr=getgrnam(grouparg)) == 0)
		{
			fprintf(stderr, "Group not found: %s\n", grouparg);
			exit(1);
		}
		else	gid=gr->gr_gid;

		libmail_changegroup(gid);
	}

	if (userarg)
	{
	uid_t	uid;

		if (isid(userarg))
		{
			uid=atoi(userarg);
			libmail_changeuidgid(uid, getgid());
		}
		else
		{
		gid_t	g=getgid(), *gp=0;

			if (grouparg)	gp= &g;
			libmail_changeusername(userarg, gp);
		}
	}
}
Ejemplo n.º 4
0
int auth_callback_default(struct authinfo *ainfo)
{
	if (ainfo->address == NULL)
	{
		fprintf(stderr, "WARN: No address!!\n");
		return (-1);
	}

	if (ainfo->sysusername)
		libmail_changeusername(ainfo->sysusername,
				       &ainfo->sysgroupid);
	else if (ainfo->sysuserid)
		libmail_changeuidgid(*ainfo->sysuserid,
				     ainfo->sysgroupid);
	else
	{
		fprintf(stderr, "WARN: %s: No UID/GID!!\n", ainfo->address);
		return (-1);
	}

	if (!ainfo->homedir)
	{
		errno=EINVAL;
		fprintf(stderr, "WARN: %s: No homedir!!\n", ainfo->address);
		return (1);
	}

	if (chdir(ainfo->homedir))
	{
		fprintf(stderr, "WARN: %s: chdir(%s) failed!!\n",
			ainfo->address, ainfo->homedir);
		perror("WARN: error");
		return (1);
	}

	return 0;
}
Ejemplo n.º 5
0
static void fax(struct moduledel *p)
{
	struct	ctlfile ctf;
	unsigned nreceipients=p->nreceipients;
	const char *host=p->host;
	const char *receipient;
	unsigned nrecipient=(unsigned)atol(p->receipients[0]);
	int pipefd[2];
	pid_t child_proc;
	int faxopts;
	int n_cover_pages;
	FILE *fp;

	struct faxconv_err_args err_args;

	struct sort_file_list *page_list, *pp;


#if     HAVE_SETPGRP
#if     SETPGRP_VOID
        setpgrp();
#else
        setpgrp(0, 0);
#endif
#else
#if     HAVE_SETPGID
        setpgid(0, 0);
#endif
#endif

	if (comgetfaxopts(host, &faxopts))
	{
		clog_msg_start_err();
		clog_msg_str("courierfax: FATAL: invalid host");
		clog_msg_send();
		exit(1);
	}

	putenv(faxopts & FAX_LOWRES ? "FAXRES=lo":"FAXRES=hi");

	if (nreceipients != 1)
	{
		clog_msg_start_err();
		clog_msg_str("courierfax: FATAL: # receipients must be 1");
		clog_msg_send();
		exit(1);
	}

	receipient=p->receipients[1];
	nrecipient=(unsigned)atol(p->receipients[0]);

	if (ctlfile_openi(p->inum, &ctf, 0))
		clog_msg_errno();

	/* Convert message to fax format, use a child process */

	signal(SIGTERM, faxabort);

	if (pipe(pipefd) < 0)
	{
		clog_msg_errno();
	}

	child_proc=fork();
	if (child_proc < 0)
	{
		clog_msg_errno();
		return;
	}

	if (child_proc == 0)
	{
		const char *fn;

		close(0);
		if (open("/dev/null", O_RDONLY) != 0)
			clog_msg_errno();

		close(pipefd[0]);
		close(1);
		if (dup(pipefd[1]) != 1)
		{
			perror("dup");
			exit(1);
		}
		close(2);
		if (dup(pipefd[1]) != 2)
		{
			fprintf(stderr, "ERROR: dup failed\n");
			exit(1);
		}
		close(pipefd[1]);

		libmail_changeuidgid(MAILUID, MAILGID);

		fn=qmsgsdatname(p->inum);

		if (faxconvert(fn, faxopts, &n_cover_pages))
			exit (1);

		if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "w")) == NULL ||
		    fprintf(fp, "%d\n", n_cover_pages) < 0 ||
		    fflush(fp) < 0)
			exit(1);
		fclose(fp);
		exit(0);
	}

	close(pipefd[1]);

	err_args.ctf= &ctf;
	err_args.nreceip=nrecipient;

	if (read_childerrmsg(child_proc, pipefd[0],
			     &faxconvert_cleanup, &err_args))
	{
		ctlfile_close(&ctf);
		return;
	}

	/* Hit it */

	if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "r")) == NULL ||
	    fscanf(fp, "%d", &n_cover_pages) != 1)
	{
		if (fp)
			fclose(fp);

		ctlfile_append_reply(err_args.ctf,
				     err_args.nreceip,
				     "Internal error: cannot read number of cover pages",
				     COMCTLFILE_DELFAIL, 0);
		ctlfile_close(&ctf);
		exit(0);
	}

	page_list=read_dir_sort_filenames(FAXTMPDIR, FAXTMPDIR "/");

	if (!page_list)
	{
		clog_msg_start_err();
		clog_msg_str("courierfax: INTERNAL ERROR - no pages to xmit.");
		clog_msg_send();
		exit(1);
	}

	/* Keep trying until the modem line is unlocked */

	do
	{
		if (pipe(pipefd) < 0)
		{
			clog_msg_errno();
		}

		child_proc=fork();
		if (child_proc < 0)
		{
			clog_msg_errno();
			return;
		}

		if (child_proc == 0)
		{
			unsigned page_cnt=0;
			char **argvec;

			close(pipefd[0]);
			close(0);
			if (open("/dev/null", O_RDONLY) != 0)
			{
				perror("/dev/null");
				exit(1);
			}
			close(1);
			if (dup(pipefd[1]) != 1)
			{
				perror("dup");
				exit(1);
			}
			close(2);
			if (dup(pipefd[1]) != 2)
			{
				fprintf(stderr, "ERROR: dup failed\n");
				exit(1);
			}
			close(pipefd[1]);

			for (pp=page_list; pp; pp=pp->next)
				++page_cnt;

#if 0
			while (page_list)
			{
				unlink(page_list->filename);
				page_list=page_list->next;
			}

			exit(0);
#endif

			argvec=(char **)courier_malloc(sizeof(char *)*
						       (page_cnt+10));

			argvec[0]=SENDFAX;
			argvec[1]="-v";
			argvec[2]="-r";

			page_cnt=3;

			if (faxopts & FAX_LOWRES)
				argvec[page_cnt++]="-n";

			argvec[page_cnt++]=(char *)receipient;

			while (page_list)
			{
				argvec[page_cnt++]=page_list->filename;
				page_list=page_list->next;
			}
			argvec[page_cnt]=0;
			execv(SENDFAX, argvec);
			perror(SENDFAX);
			exit(1);
		}
		close(pipefd[1]);

		err_args.ctf= &ctf;
		err_args.nreceip=nrecipient;
		err_args.file_list=page_list;
		err_args.is_locked=0;
		err_args.n_cover_pages=n_cover_pages;

		if (read_childerrmsg(child_proc, pipefd[0],
				     &faxsend_cleanup, &err_args) == 0)
		{
			size_t npages=0;
			char fmtbuf[NUMBUFSIZE];
			char fmtbuf1[NUMBUFSIZE];
			char fmtbuf2[NUMBUFSIZE+100];

			for (pp=page_list; pp; pp=pp->next)
				++npages;

			libmail_str_size_t(npages, fmtbuf);
			libmail_str_size_t(n_cover_pages, fmtbuf1);

			sprintf(fmtbuf2,
				"%s pages - including %s cover page(s)"
				" - sent by fax.", fmtbuf, fmtbuf1);

			ctlfile_append_reply(&ctf, (unsigned)
					     nrecipient,
					     fmtbuf2,
					     COMCTLFILE_DELSUCCESS, " l");
			break;
		}
	} while (err_args.is_locked);

	ctlfile_close(&ctf);
	rmdir_contents(FAXTMPDIR);
}
Ejemplo n.º 6
0
int main(int argc, char **argv)
{
    if (argc > 1 && strcmp(argv[1], "--version") == 0)
    {
        printf("%s\n", COURIER_COPYRIGHT);
        exit(0);
    }

    if (chdir(courierdir()))
    {
        perror("chdir");
        return (1);
    }
    if (argc < 2)	return (0);

    if (strcmp(argv[1], "stop") == 0)
    {
        int	fd;

        trigger(TRIGGER_STOP);

        /* Wait until the exclusive lock goes away: */

        signal(SIGHUP, SIG_DFL);
        if ((fd=open(TMPDIR "/courierd.lock", O_RDWR|O_CREAT, 0600))
                < 0)	clog_msg_errno();

        alarm(15);	/* But abort after 15 seconds. */

        ll_lock_ex(fd);
        return (0);
    }

    if (strcmp(argv[1], "restart") == 0)
    {
        trigger(TRIGGER_RESTART);
        return (0);
    }

    if (strcmp(argv[1], "flush") == 0)
    {
        ino_t	n;
        struct	ctlfile	ctf;

        if (getuid())
        {
            /*
            ** We'll fail trying to open the pipe anyway, but let's
            ** give a meaningful error message now.
            */
            fprintf(stderr,
                    "courier flush can be executed only by the superuser.\n");
            exit(1);
        }

        if (argc < 3)
        {
            trigger(TRIGGER_FLUSH);	/* Everything */
            exit(0);
        }

        if (comparseqid(argv[2], &n) == 0 &&
                ctlfile_openi(n, &ctf, 1) == 0)
        {
            int c=ctlfile_searchfirst(&ctf, COMCTLFILE_MSGID);

            if (c >= 0 && strcmp(ctf.lines[c]+1, argv[2]) == 0)
            {
                char	*s=courier_malloc(sizeof(TRIGGER_FLUSHMSG)+1+
                                          strlen(argv[2]));

                strcat(strcat(strcpy(s, TRIGGER_FLUSHMSG),
                              argv[2]), "\n");
                trigger(s);
                ctlfile_close(&ctf);
                return (0);
            }
            ctlfile_close(&ctf);
        }
        fprintf(stderr, "No such message.\n");
        exit(1);
        return (1);
    }

    /* Might as well... */

    if (strcmp(argv[1], "start") == 0)
    {
        pid_t	p;
        int	waitstat;
        char	dummy;

        /*
        ** Ok, courierd will close file descriptor 3 when it starts, so we
        ** put a pipe on there, and wait for it to close.
        */
        int	pipefd[2];

        close(3);
        if (open("/dev/null", O_RDONLY) != 3 || pipe(pipefd))
        {
            fprintf(stderr, "Cannot open pipe\n");
            exit(1);
        }

        if (getuid())
        {
            /*
            ** We'll fail trying to execute courierd anyway, but let's
            ** give a meaningful error message now.
            */
            fprintf(stderr, "courier start can be executed only by the superuser.\n");
            return (1);
        }
        signal(SIGCHLD, SIG_DFL);
        while ((p=fork()) == -1)
        {
            perror("fork");
            sleep(10);
        }
        if (p == 0)
        {
            dup2(pipefd[1], 3);
            close(pipefd[1]);
            close(pipefd[0]);
            while ((p=fork()) == -1)
            {
                perror("fork");
                sleep(10);
            }
            if (p == 0)
            {
                /*
                ** stdin from the bitbucket.  stdout to
                ** /dev/null, or the bitbucket.
                */

                signal(SIGHUP, SIG_IGN);
                close(0);
                open("/dev/null", O_RDWR);
                dup2(0, 1);
                dup2(0, 2);
                /* See if we can disconnect from the terminal */

#ifdef	TIOCNOTTY
                {
                    int fd=open("/dev/tty", O_RDWR);

                    if (fd >= 0)
                    {
                        ioctl(fd, TIOCNOTTY, 0);
                        close(fd);
                    }
                }
#endif
                /* Remove any process groups */

#if	HAVE_SETPGRP
#if	SETPGRP_VOID
                setpgrp();
#else
                setpgrp(0, 0);
#endif
#endif
                execl( DATADIR "/courierctl.start",
                       "courierctl.start", (char *)0);
                perror("exec");
                _exit(1);
            }
            _exit(0);
        }
        close(pipefd[1]);
        while (wait(&waitstat) != p)
            ;
        if (read(pipefd[0], &dummy, 1) < 0)
            ; /* ignore */
        close(pipefd[0]);
        close(3);
        return (0);
    }

    if (strcmp(argv[1], "clear") == 0 && argc > 2)
    {
        libmail_changeuidgid(MAILUID, MAILGID);

        if (strcmp(argv[2], "all") == 0)
        {
            courier_clear_all();
        }
        else
        {
            track_save(argv[2], TRACK_ADDRACCEPTED);
            printf("%s cleared.\n", argv[2]);
        }
        return (0);
    }

    if (argc > 2 && strcmp(argv[1], "show") == 0 &&
            strcmp(argv[2], "all") == 0)
    {
        libmail_changeuidgid(MAILUID, MAILGID);
        courier_show_all();
    }

    return (0);
}
Ejemplo n.º 7
0
int main(int argc, char **argv)
{
struct moduledel *p;

	clog_open_syslog("courierlocal");

	if (chdir(courier_home=getenv("COURIER_HOME")))
		clog_msg_errno();

	if (atol(getenv("MAXRCPT")) > 1)
	{
		clog_msg_start_err();
		clog_msg_str("Invalid configuration in config, set MAXRCPT=1");
		clog_msg_send();
		exit(1);
	}

	module_init(0);

	module_delivery_timeout(config_readtime("localtimeout", 15*60));

	while ((p=module_getdel()) != NULL)
	{
	unsigned delid=atol(p->delid);
	unsigned rcptnum;
	struct ctlfile ctf;
	int	pipe1[2], pipe2[2];
	pid_t	pid;
	int datfd;
	struct stat stat_buf;

		pid=module_fork(delid, 0);
		if (pid < 0)
		{
			clog_msg_prerrno();
			module_completed(delid, delid);
			continue;
		}

		if (pid)	continue;

#if     HAVE_SETPGRP
#if     SETPGRP_VOID
		setpgrp();
#else
		setpgrp(0, 0);
#endif
#endif

		if (p->nreceipients != 1)
		{
			clog_msg_start_err();
			clog_msg_str("Invalid message from courierd.");
			clog_msg_send();
			_exit(0);
		}

		rcptnum=atol(p->receipients[0]);
		if (ctlfile_openi(p->inum, &ctf, 0))
		{
			clog_msg_errno();
			_exit(0);
		}

		if (pipe(pipe1) < 0 || pipe(pipe2) < 0
		    || (pid=fork()) < 0)
		{
			clog_msg_prerrno();
			ctlfile_append_reply(&ctf, rcptnum,
				"Can't run courierdeliver.",
				COMCTLFILE_DELDEFERRED, 0);
			ctlfile_close(&ctf);
			_exit(0);
			return (0);
		}

		if ((datfd=open(qmsgsdatname(p->inum), O_RDONLY)) < 0)
		{
			clog_msg_prerrno();
			ctlfile_append_reply(&ctf, rcptnum,
					     "Unable to read message file.",
					     COMCTLFILE_DELDEFERRED, 0);
			ctlfile_close(&ctf);
			_exit(0);
			return (0);
		}

		if (pid == 0)
		{
		const char *host, *homedir, *maildir, *quota;
		char	*buf, *s;

		char	*username, *ext;
		uid_t	u;
		gid_t	g;

			close(pipe1[0]);
			close(pipe2[0]);
			dup2(pipe2[1], 2);
			close(pipe2[1]);
			dup2(pipe1[1], 1);
			close(pipe1[1]);
			close(0);
			if (dup(datfd) != 0)
			{
				clog_msg_start_err();
				clog_msg_str("Unable to read message file.");
				clog_msg_send();
				_exit(EX_TEMPFAIL);
			}
			close(ctf.fd);
			close(datfd);

			/* Contents of host: */
			/* acct!ext!uid!gid!homedir!maildir!quota */

			host=p->host;

			buf=strdup(host);
			if (!buf)
			{
				clog_msg_prerrno();
				_exit(EX_TEMPFAIL);
			}

			s=strchr(buf, '!');
			username=buf;
			if (s)	*s++=0;
			ext=s;
			if (s)	s=strchr(s, '!');
			if (s)	*s++=0;

			u=0;
			while (s && *s != '!')
			{
				if (isdigit((int)(unsigned char)*s))
					u=u*10 + (*s - '0');
				++s;
			}
			if (s)	*s++=0;
			g=0;
			while (s && *s != '!')
			{
				if (isdigit((int)(unsigned char)*s))
					g=g*10 + (*s - '0');
				++s;
			}

			if (s)	*s++=0;

			homedir=s;

			if (s)	s=strchr(s, '!');
			if (s)	*s++=0;

			maildir=s;

			if (s)	s=strchr(s, '!');
			if (s)	*s++=0;

			quota=s;
			
			if (!s)
			{
				clog_msg_start_err();
				clog_msg_str("Invalid local recipient address.");
				clog_msg_send();
				_exit(EX_TEMPFAIL);
			}

			if (chdir(homedir))
			{
				clog_msg_str(homedir);
				clog_msg_str(": ");
				clog_msg_prerrno();
				_exit(EX_TEMPFAIL);
			}

			libmail_changeuidgid(u, g);

			execl( MODULEDIR "/local/courierdeliver",
				"courierdeliver",
				username,
				homedir,
				ext,
				ctf.receipients[rcptnum],
				verp_getsender(&ctf, ctf.receipients[rcptnum]),
				quota,
				maildir,
				(const char *)0);

			clog_msg_start_err();
			clog_msg_prerrno();
			clog_msg_send();
			_exit(EX_TEMPFAIL);
		}

		close(pipe1[1]);
		close(pipe2[1]);

		libmail_changeuidgid(MAILUID, MAILGID);
		if (fstat(datfd, &stat_buf) == 0)
			ctf.msgsize=stat_buf.st_size;

		close(datfd);
		wait_delivery(pid, &ctf, rcptnum, pipe2[0], pipe1[0],
				p->host, p->receipients[1]);
		ctlfile_close(&ctf);
		_exit(0);
	}
	return (0);
}
Ejemplo n.º 8
0
int courierbmain()
{
    fd_set	fds, fdc;
    struct	mybuf trigger_buf;

    clog_open_syslog("courierd");
    rw_init_verbose(1);
    if (rw_init_courier(0))	return (1);
    drvinfo::init();

    libmail_changeuidgid(MAILUID, MAILGID);
    signal(SIGPIPE, SIG_IGN);

    respawnlo=config_time_respawnlo();
    respawnhi=config_time_respawnhi();

    retryalpha=config_time_retryalpha();
    retrybeta=config_retrybeta();
    retrygamma=config_time_retrygamma();
    retrymaxdelta=config_retrymaxdelta();
    flushtime=0;
    delaytime=config_time_submitdelay();

    queuefill=config_time_queuefill();
    nextqueuefill=0;

    purgedir(MSGQDIR);
    purgedir(MSGSDIR);
    rmdir(MSGQDIR);
    mkdir(MSGQDIR, 0755);
    trackpurge();

    if ((triggerw=open(triggername, O_WRONLY, 0)) < 0 ||
            (triggerr=open(triggername, O_RDONLY, 0)) < 0)
        clog_msg_errno();

    time(&start_time);

    courierbstart=start_time;

    msgq::init(queuehi);

    shutdown_flag=0;
    FD_ZERO(&fds);

    unsigned nd;
    int	maxfd=triggerr;

    FD_SET(maxfd, &fds);
    mybuf_init(&trigger_buf, triggerr);

    for (nd=0; nd<drvinfo::nmodules; nd++)
    {
        int	fd=drvinfo::modules[nd].module_from.fd;

        if (fd > maxfd)	maxfd=fd;
        FD_SET(fd, &fds);
    }

    ++maxfd;

    time_t	current_time, next_time, shutdown_time;

    current_time=start_time;

    shutdown_time=0;

    msgq::queuescan();	// Initial queue scan

    int	doscantmp=1;

////////////////////////////////////////////////////////////////////////////
//
// Main loop:
//
// A) Scan tmp for new messages.
//
// B) Schedule messages for delivery, when their time comes.
//
// C) Update statistics.
//
// D) Stop scheduling messages when restart signal received.
//
// E) Restart if there's no activity for 5 mins after we've been running
//    for respawnlo amount of times.
//
// F) When we've been running for respawnhi amount of time, stop scheduling
//    messages, restart when all deliveries have been completed.
//
// G) Receive delivery completion messages from modules.
//
////////////////////////////////////////////////////////////////////////////
    for (;;)
    {
        msgq	*mp;

        if (shutdown_flag)
            doscantmp=0;

        if (doscantmp)
            doscantmp=msgq::tmpscan();

        if (shutdown_flag && msgq::inprogress == 0)
            break;

        if (current_time >= start_time + respawnhi && !shutdown_flag)
        {
            clog_msg_start_info();
            clog_msg_str("SHUTDOWN: respawnhi limit reached.");
            clog_msg_send();
            shutdown_flag=1;
            continue;
        }

        if (diskspacelow() && msgq::queuehead &&
                msgq::queuehead->nextsenddel <= current_time)
        {
            clog_msg_start_err();
            clog_msg_str("Low on disk space.");
            clog_msg_send();
            for (mp=msgq::queuehead; mp &&
                    mp->nextsenddel <= current_time + 300;
                    mp=mp->next)
                mp->nextsenddel=current_time+300;
        }

        if (!shutdown_flag)
        {
            while ((mp=msgq::queuehead) != 0 &&
                    mp->nextsenddel <= current_time)
            {
                mp->removewq();
                mp->start_message();
            }
        }

        if (nextqueuefill && nextqueuefill <= current_time)
        {
            nextqueuefill=0;
            if (!shutdown_flag)
            {
                msgq::queuescan();
            }

        }

        next_time=0;
        if ( msgq::queuehead && msgq::queuehead->nextsenddel
                > current_time)
            next_time=msgq::queuehead->nextsenddel;
        if (!shutdown_flag && msgq::inprogress == 0 &&
                shutdown_time == 0)
        {
            shutdown_time=current_time + 5 * 60;
            if (shutdown_time < start_time + respawnlo)
                shutdown_time=start_time + respawnlo;
        }

        if (shutdown_time && (next_time == 0 ||
                              shutdown_time < next_time))
            next_time=shutdown_time;

        if (nextqueuefill)
        {
            /* Or, wake up next time we need to refill the queue */

            if (next_time == 0 || nextqueuefill < next_time)
            {
                next_time=nextqueuefill;
            }
        }

        fdc=fds;

        struct	timeval	tv;

        if (next_time)
        {
            tv.tv_sec= next_time > current_time ?
                       next_time - current_time:0;
            tv.tv_usec=0;
        }

#if 1
        {
            char buf[40];

            clog_msg_start_info();
            clog_msg_str("Waiting.  shutdown time=");
            strcpy(buf, shutdown_time ? ctime(&shutdown_time):"none\n");
            *strchr(buf, '\n')=0;
            clog_msg_str(buf);

            clog_msg_str(", wakeup time=");
            strcpy(buf, next_time ? ctime(&next_time):"none\n");
            *strchr(buf, '\n')=0;
            clog_msg_str(buf);
            clog_msg_str(", queuedelivering=");
            clog_msg_int(msgq::queuedelivering);
            clog_msg_str(", inprogress=");
            clog_msg_int(msgq::inprogress);
            clog_msg_send();
        }
#endif

        while (select(maxfd, &fdc, (fd_set *)0, (fd_set *)0,
                      (next_time && doscantmp == 0 ?
                       &tv:(struct timeval *)0)) < 0)
        {
            if (errno != EINTR)	clog_msg_errno();
        }
        time(&current_time);
        if (shutdown_time)
        {
            if (current_time >= shutdown_time &&
                    msgq::inprogress == 0)
            {
                clog_msg_start_info();
                clog_msg_str("SHUTDOWN: respawnlo limit reached, system inactive.");
                clog_msg_send();
                shutdown_flag=1;
            }
            shutdown_time=0;
        }

        /* Handle commands sent via the trigger pipe */

        if (FD_ISSET(triggerr, &fdc))
        {
            unsigned	l;
            char	cmdbuf[256];
            int	c;

            do
            {
                l=0;
                do
                {
                    c=mybuf_get(&trigger_buf);
                    if (l < sizeof(cmdbuf)-1)
                        cmdbuf[l++]=c;
                } while (c != '\n');
                cmdbuf[l]=0;

                if (strcmp(cmdbuf, TRIGGER_NEWMSG) == 0)
                    doscantmp=1;
                else if (strcmp(cmdbuf, TRIGGER_RESTART) == 0)
                {
                    shutdown_flag=1;
                    clog_msg_start_info();
                    clog_msg_str("SHUTDOWN: Restarting...");
                    clog_msg_send();
                }
                else if (strcmp(cmdbuf, TRIGGER_STOP) == 0)
                {
                    clog_msg_start_info();
                    clog_msg_str("SHUTDOWN: Stopping...");
                    clog_msg_send();
                    _exit(99);
                }
                else if (strcmp(cmdbuf, TRIGGER_FLUSH) == 0)
                {
                    flushtime=current_time;
                    for (mp=msgq::queuehead; mp;
                            mp=mp->next)
                        mp->nextsenddel=current_time;
                }
                else if (strncmp(cmdbuf, TRIGGER_FLUSHMSG,
                                 sizeof(TRIGGER_FLUSHMSG)-1) == 0)
                {
                    char *p;
                    ino_t	n;

                    if ((p=strchr(cmdbuf, '\n')) != 0)
                        *p=0;

                    p=cmdbuf+sizeof(TRIGGER_FLUSHMSG)-1;
                    while (*p == ' ')	++p;
                    if (comparseqid(p, &n) == 0 &&
                            !shutdown_flag)
                        msgq::flushmsg(n, p);
                }
            } while (mybuf_more(&trigger_buf));
        }

        for (nd=0; nd<drvinfo::nmodules; nd++)
        {
            struct mybuf *p= &drvinfo::modules[nd].module_from;
            size_t	delnum;
            int	c;

            if (!FD_ISSET(p->fd, &fdc))	continue;
            do
            {
                delnum=0;
                while (errno=0, ((c=mybuf_get(p)) != '\n'))
                {
                    if (c < 0)
                    {
                        if (errno == EINTR)
                            continue;

                        clog_msg_start_err();
                        clog_msg_str("MODULE ");
                        clog_msg_str(
                            drvinfo::modules[nd]
                            .module->name);
                        clog_msg_str(" ABORTED.");
                        clog_msg_send();
                        _exit(1);
                    }
                    if (c >= '0' && c <= '9')
                        delnum=delnum * 10 + (c-'0');
                }
                msgq::completed(drvinfo::modules[nd], delnum);
            } while (mybuf_more(p));
            if (!shutdown_flag)	shutdown_time=0;
        }
    }

    close(triggerr);
    close(triggerw);

    drvinfo::cleanup();
    return (0);
}
Ejemplo n.º 9
0
Archivo: pcpd.c Proyecto: zixia/nospam
int main(int argc, char **argv)
{
	int argn=1;
	static const char * const authvars[]={NULL};

	signal(SIGPIPE, SIG_IGN);
	umask(022);

	if (argn >= argc)
	{
		struct PCP *pcp;

		pcp=open_calendar(NULL);

		mainloop(pcp);
		exit(0);
	}

	maildir_cache_init(TIMEOUT * 2, CACHEDIR, LOCALCACHEOWNER, authvars);

	if (strcmp(argv[argn], "start") == 0)
	{
		struct group *gr;

		if (chdir(CALENDARDIR) < 0)
		{
			perror(CALENDARDIR);
			exit(1);
		}
		gr=getgrnam(MAILGROUP);

		if (!gr)
		{
			fprintf(stderr, "Unknown group: %s\n", MAILGROUP);
			exit(1);
		}

		authtoken_init();
		libmail_changeuidgid(getuid(), gr->gr_gid);
		start();
	}
	else if (strcmp(argv[argn], "login") == 0 ||
		 strcmp(argv[argn], "slogin") == 0)
	{
		struct PCP *pcp;
		int flag;
		struct group *gr;

		gr=getgrnam(MAILGROUP);

		if (!gr)
		{
			fprintf(stderr, "Unknown group: %s\n", MAILGROUP);
			exit(1);
		}
		libmail_changeuidgid(getuid(), gr->gr_gid);

		if (chdir(CALENDARDIR) < 0)
		{
			perror(CALENDARDIR);
			exit(1);
		}

		authtoken_init();
		userid=login(strcmp(argv[argn], "login"), &flag);

		pcp=pcp_open_dir(".", userid);

		if (pcp && flag && pcp_cleanup(pcp))
		{
			pcp_close(pcp);
			syslog(LOG_CRIT, "pcpd: pcp_cleanup failed");
			pcp=NULL;
		}

		if (!pcp)
		{
			syslog(LOG_CRIT, "pcpd: pcp_open_dir failed");
			perror("pcp_open_dir");
			exit(1);
		}

		mainloop(pcp);
		exit(0);
	}
	else if (strcmp(argv[argn], "stop") == 0)
	{
		if (chdir(CALENDARDIR) < 0)
		{
			perror(CALENDARDIR);
			exit(1);
		}
		ll_daemon_stop(LOCKFILE, PIDFILE);
		exit(0);
	}
	else if (strcmp(argv[argn], "open") == 0)
	{
		++argn;
		if (argn < argc)
		{
			struct PCP *pcp;

			pcp=open_calendar(argv[argn]);

			mainloop(pcp);
			exit(0);
		}
	}
	fprintf(stderr, "Usage: %s (start|stop|open [path])\n", argv[0]);
	exit(1);
	return (0);
}
Ejemplo n.º 10
0
Archivo: pcpd.c Proyecto: zixia/nospam
static int callback_login(struct userid_callback *a, void *vp)
{
	struct userid_info *uinfo=(struct userid_info *)vp;
	struct stat stat_buf;
	time_t t;
	char curdir[1024];
	char *token=NULL;

	if (stat(a->homedir, &stat_buf) < 0)
		return (-1);

	if (stat_buf.st_mode & S_ISVTX)
	{
		errno=EAGAIN;
		return (1);
	}

	time(&t);
	if (!uinfo->isproxy)
	{
		token=authtoken_create(uinfo->userid, t);
		if (!token)
		{
			syslog(LOG_NOTICE, "pcpd: authtoken_create() failed.");
			maildir_cache_cancel();
			return (1);
		}
	}

	maildir_cache_start();

	libmail_changeuidgid(a->uid, getgid());

	if (chdir(a->homedir) < 0)
	{
		free(token);
		syslog(LOG_NOTICE, "pcpd: chdir(%s) failed.", a->homedir);
		maildir_cache_cancel();
		exit(1);
	}

	if (chdir(a->maildir && *a->maildir ? a->maildir:"Maildir") < 0)
	{
		free(token);
		syslog(LOG_NOTICE, "pcpd: chdir(Maildir) failed.");
		maildir_cache_cancel();
		exit(1);
	}

	mkdir("calendar", 0700);
	if (chdir("calendar") < 0)
	{
		free(token);
		syslog(LOG_NOTICE, "pcpd: chdir(Maildir) failed.");
		maildir_cache_cancel();
		exit(1);
	}

	curdir[sizeof(curdir)-1]=0;
	if (getcwd(curdir, sizeof(curdir)-1) == 0)
	{
		syslog(LOG_NOTICE, "pcpd: getcwd() failed.");
		maildir_cache_cancel();
		exit(1);
	}

	maildir_cache_save(uinfo->userid, t, curdir, a->uid, getgid());

	alarm(0);
	if (!uinfo->isproxy)
	{
		printf("102 %s logged in.\n", token);
		free(token);
	}
	return (0);
}
Ejemplo n.º 11
0
static void esmtpparent()
{
unsigned i;
fd_set	fdc, fds;
time_t	current_time;

	libmail_changeuidgid(MAILUID, MAILGID);
	module_init(&terminated_child);

	if ((info=(struct esmtpchildinfo *)malloc(sizeof(*info)*
		module_nchildren)) == 0)
		clog_msg_errno();
	for (i=0; i<module_nchildren; i++)
	{
		info[i].pid= -1;
		info[i].cmdpipe= -1;
		info[i].host=0;
		info[i].pendel=0;
	}
	if (pipe(completionpipe) < 0)
		clog_msg_errno();

	if ((childresultpipe=fdopen(completionpipe[0], "r")) == 0)
		clog_msg_errno();
	FD_ZERO(&fdc);
	FD_SET(0, &fdc);
	FD_SET(completionpipe[0], &fdc);
	mybuf_init(&courierdbuf, 0);
	mybuf_init(&childbuf, completionpipe[0]);

	module_blockset();
	time(&current_time);

	for (;;)
	{
	time_t	wait_time;
	struct	timeval	tv;

		wait_time=0;
		for (i=0; i<module_nchildren; i++)
		{
			if (!ESMTP_IDLE(&info[i]))	continue;
			if (info[i].termtime <= current_time)
			{
				close(info[i].cmdpipe);
				info[i].cmdpipe= -1;
				continue;
			}

			if (wait_time == 0 || info[i].termtime < wait_time)
				wait_time=info[i].termtime;
		}

		if (wait_time)
		{
			tv.tv_sec= wait_time - current_time;
			tv.tv_usec=0;
		}

		fds=fdc;

		module_blockclr();
                while (select(completionpipe[0]+1, &fds, (fd_set *)0, (fd_set *)0,
                                (wait_time ? &tv:(struct timeval *)0)) < 0)
                {
                        if (errno != EINTR)     clog_msg_errno();
                }

		module_blockset();
		time(&current_time);

		if (FD_ISSET(completionpipe[0], &fds))
		{
		char	*line;

			do
			{
			pid_t	p;

				line=module_getline( &call_mybuf_get,
						&childbuf);

				if (parse_ack(line, &i, &p) ||
					i >= module_nchildren ||
					(p == info[i].pid &&
						!ESMTP_BUSY(&info[i])))
				{
					clog_msg_start_err();
					clog_msg_str("INVALID message from child process.");
					clog_msg_send();
					_exit(0);
				}
				if (p != info[i].pid)	continue;
				info[i].isbusy=0;
				info[i].termtime=current_time + esmtpkeepalive;
				if (info[i].pendel)
				{
					free(info[i].pendel);
					info[i].pendel=0;
				}

				module_completed(i, module_delids[i]);
			} while (mybuf_more(&childbuf));
		}

		if (!FD_ISSET(0, &fds))	continue;

		do
		{
		char	**cols;
		const char *hostp;
		size_t	hostplen;
		time_t	misctime;
		unsigned j;
		char	*line;

			line=module_getline( &call_mybuf_get, &courierdbuf);
			if (!line)
			{
				module_restore();

				/*
				** If all processes are idle, wait for them
				** to finish normally.  Otherwise, kill
				** the processes.
				*/

				for (j=0; j<module_nchildren; j++)
					if (ESMTP_BUSY(&info[j]))
						break;

				if (j < module_nchildren)
				{
					for (j=0; j<module_nchildren; j++)
						if (info[j].pid > 0)
							kill(info[j].pid,
								SIGTERM);
				}
				else
				{
				int	waitstat;

					for (j=0; j<module_nchildren; j++)
					{
						if (info[j].cmdpipe > 0)
						{
							close(info[j].cmdpipe);
							info[j].cmdpipe= -1;
						}
					}
					while (wait(&waitstat) != -1 ||
						errno == EINTR)
						;
				}
				_exit(0);
			}

			cols=module_parsecols(line);

			if (!cols)	_exit(0);

			hostp=MODULEDEL_HOST(cols);
			for (hostplen=0; hostp[hostplen] &&
				hostp[hostplen] != '\t'; hostplen++)
				;

			for (i=0; i<module_nchildren; i++)
			{
				if (!ESMTP_IDLE(&info[i])) continue;
				if (memcmp(info[i].host, hostp, hostplen) == 0
					&& info[i].host[hostplen] == 0)
					break;
			}

			if (i < module_nchildren)	/* Reuse a process */
			{
				send_child(i, line, cols);
				continue;
			}

			for (i=0; i<module_nchildren; i++)
				if (ESMTP_NOCHILD(&info[i]))	break;

			if (i < module_nchildren)	/* We can fork */
			{
				start_child(i, line, cols);
				send_child(i, line, cols);
				continue;
			}

			/*
			** Find a process that's been idled the longest,
			** and reuse that one.
			*/

			misctime=0;
			j=0;
			for (i=0; i<module_nchildren; i++)
			{
				if (ESMTP_IDLE(&info[i]) &&
					(misctime == 0 || misctime >
						info[i].termtime))
				{
					j=i;
					misctime=info[i].termtime;
				}
			}
			if (misctime)
			{
				if (info[j].pendel)
				{
					clog_msg_start_err();
					clog_msg_str("INTERNAL ERROR: unexpected scheduled delivery.");
					clog_msg_send();
					_exit(1);
				}

				info[j].pendel=strcpy(
					courier_malloc(strlen(line)+1),
					line);
				close(info[j].cmdpipe);
				info[j].cmdpipe= -1;
				continue;
			}

			/* The ONLY remaining possibility is something in
			** the TERMINATING stage, without another delivery
			** already scheduled for that slot.
			*/

			for (i=0; i<module_nchildren; i++)
			{
				if (ESMTP_TERMINATING(&info[i]) &&
					info[i].pendel == 0)
					break;
			}

			if (i < module_nchildren)
			{
				info[i].pendel=strcpy(
					courier_malloc(strlen(line)+1),
					line);
				continue;
			}

			clog_msg_start_err();
			clog_msg_str("INTERNAL ERROR: unexpected delivery.");
			clog_msg_send();
			_exit(1);
		} while (mybuf_more(&courierdbuf));
	}
}