cvs commit: ports/mail/p5-qpsmtpd/files

Doug Barton dougb at
Thu Dec 31 22:30:33 UTC 2009

Glen Barber wrote:
> I have attached two diffs of the rc script,  however I have run into a
> few issues with both.

First, please understand that I do appreciate you taking a look at
this, so please don't take my comments below as criticism.

It seems to me that perhaps you're not really that familiar with shell
scripting, and you're certainly not familiar with the rc.d system, but
that's ok, we're here to help. :)  If you haven't already, please read
the article at
and perhaps even the articles it references. I think that will be a
big help for you.

I've attached a diff for a script that works, please test it and if
you're satisfied I will commit it for you. However, there is
apparently an additional problem with the port because when I
installed it the "smtpd" user was not created. If that is mandatory
for the script to work it should be added by the port. I could get it
started if I specified another unprivileged user/group in rc.conf.local.

I will try to address your questions in line, then explain a little
more about what my suggested version of the script does at the end.

> The first diff still uses 'stop_cmd(){kill `cat $pidfile`}' for the
> following reasons:
>   - adding ': qpsmtpd_pidfile="$pidfile"' would never create
> /var/run/, 

It's up to the process to create its own pidfile.

> thus the rc script would never find it to kill
> the process. 

If you allow the user to specify the pid file's location (which
frankly I think is not usually necessary) you have to set
pidfile=${name}_pidfile in the script _after_ load_rc_config and the
setting of the default values. For most cases, hard-coding the pidfile
into the script is sufficient.

The other problem that you're running into is that when you have a
service that uses an interpreted language (like perl, python, ruby,
etc.) you usually have to use the command_interpreter option in rc.d.

> To work around this, I added the pidfile creation to
> start_cmd().

Yeah, don't do that. :)  Since the existence of the pid directory is a
PRErequisite for the thing to start properly, it needs to be in the
start_precmd. You did this part right in your original version, FYI.

>   - as a side effect of the above workaround, stopping the process
> would kill the PID, however leave the pidfile.  As a second
> workaround, I have kept the stop_cmd() function, and forcibly removed
> the pidfile after the process was killed.

Also not necessary, see below.

> The second replaces the pidfile line with this:
>   [ -z "$pidfile" ] && pidfile="/var/run/${name}.pid"
> and adds a command_args line, however the pidfile is still not cleaned
> after stopping the service, so stop_cmd() is used again.  Is there a
> more correct way to clean up the pidfile that what I have attached?

Yeah, more confusion that's not needed. :)

The script I attached does the following:
1. Adds a $FreeBSD cvs id
2. Changes the rcorder to REQUIRE: LOGIN. This is usually the way to
do it for ports scripts, but since this service runs as an
unprivileged user it's mandatory.
3. Adds the shutdown KEYWORD. Since this script is starting a
persistent service, you want to shut it down cleanly.
4. Adds descriptions for the variables the way they are done in the
example in the porter's handbook.
5. No quotes are needed around /etc/rc.subr
6. Adds command_interpreter (also adds this to the sub list in the
7. Removes the start/stop methods
8. Renames the prestart method to match the convention.
9. Shrinks the prestart method down to just creating and updating
permissions on /var/run/qpsmtpd
10. Moves load_rc_config down
11. Properly sets the defaults for the options. (FYI, in your patch
you used: ': foo="bar"', spend a few minutes thinking about why that's
bad.) :)
12. Adds a command_args variable with the right options.

The beauty of the rc.d system is that it does a lot for you in the
background. Of course, that's also one reason it's so hard to learn
how to use. :)




	Improve the effectiveness of your Internet presence with
	a domain name makeover!

-------------- next part --------------
? work
Index: Makefile
RCS file: /home/pcvs/ports/mail/p5-qpsmtpd/Makefile,v
retrieving revision 1.16
diff -u -r1.16 Makefile
--- Makefile	26 Dec 2009 22:20:35 -0000	1.16
+++ Makefile	31 Dec 2009 22:18:04 -0000
@@ -36,6 +36,7 @@
 USE_RC_SUBR=	qpsmtpd
 SUB_FILES+=	pkg-message
Index: files/
RCS file: /home/pcvs/ports/mail/p5-qpsmtpd/files/,v
retrieving revision 1.2
diff -u -r1.2
--- files/	10 Dec 2009 05:07:07 -0000	1.2
+++ files/	31 Dec 2009 22:18:04 -0000
@@ -1,100 +1,56 @@
+# $FreeBSD$
 # PROVIDE: qpsmtpd
-# BEFORE: securelevel
+# KEYWORD: shutdown
+# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
+# to enable this service:
+# qpsmtpd_enable (bool):	Set to NO by default
+#		Set it to YES to enable qpsmtpd
+# qpsmtpd_user (string):	Set to "smtpd" by default
+#		The user to run qpsmtpd-forkserver as
+# qpsmtpd_group (string):	Set to "smtpd" by default
+#		The group the pid dir will be chowned to
+# qpsmtpd_port (int):		Set to 2525 by default
+#		The port it should listen on
+# qpsmtpd_max_per_ip (int):	Set to 3 by default
+#		Max connections per IP
+# qpsmtpd_max_connections (int): Set to 15 by default
+#		Maximum total connections
+# qpsmtpd_listen_on (address):	Set to by default
+# 		IP address to listen on
-#qpsmtpd_user = the user to run qpsmtpd-forkserver under
-#qpsmtpd_group = the group the pid dir will be chowned to
-#qpsmtpd_port = the port it should listen on
-#qpsmtpd_max_per_ip = max connections per IP
-#qpsmtpd_max_connections = maximum total connections
-#qpsmtpd_listen_on = IP to listen on
-. "/etc/rc.subr"
+. /etc/rc.subr
-load_rc_config $name
-    #exits if no user is specified
-    if [ -z $qpsmtpd_user ]; then
-	echo "qpsmtpd_user not set"
-	exit 1
-    fi
-    #exits if no group is specified
-    if [ -z $qpsmtpd_group ]; then
-	echo "qpsmtpd_group not set"
-	exit 1
-    fi
-    #sets it to the default if the port is not specified
-    if [ -z $qpsmtpd_port ]; then
-	qpsmtpd_port="2525"
-    fi
-    #set it to the default max per ip
-    if [ -z $qpsmtpd_max_per_ip ]; then
-	qpsmtpd_max_per_ip="5"
-    fi
-    #set it do the max number of connections total
-    if [ -z $qpsmtpd_max_connections ]; then
-	qpsmtpd_max_connections="15"
-    fi
-    #set the default listen on to everything
-    if [ -z $qpsmtpd_listen_on ]; then
-	qpsmtpd_listen_on=""
-    fi
-    if [ ! -d /var/run/qpsmtpd/ ] ; then
-	mkdir /var/run/qpsmtpd
-    fi
-    chown $qpsmtpd_user:$qpsmtpd_group /var/run/qpsmtpd    
+	[ -d /var/run/qpsmtpd ] || mkdir /var/run/qpsmtpd
+	chown $qpsmtpd_user:$qpsmtpd_group /var/run/qpsmtpd
-	if [ -e $pidfile ]; then
-		echo "$name already running as PID `cat $pidfile`."
-		exit 1
-	else
-		eval $command \
-		-p $qpsmtpd_port \
-		-c $qpsmtpd_max_connections \
-		-u $qpsmtpd_user \
-		-m $qpsmtpd_max_per_ip \
-		-l $qpsmtpd_listen_on \
-		--pid-file $pidfile \
-		-d \
-		&& echo "$name started as PID `cat $pidfile`." \
-		|| echo "Failed to start $name"
-	fi
+load_rc_config $name
-	if [ -e $pidfile ]; then
-		kill `cat $pidfile` \
-		&& echo "$name stopped." \
-		|| echo "Could not stop `cat $pidfile`."
-	else
-		echo "Cannot find $pidfile - $name not running?"
-		exit 1
-	fi
+: ${qpsmtpd_enable="NO"}
+: ${qpsmtpd_user="smtpd"}
+: ${qpsmtpd_group="smtpd"}
+: ${qpsmtpd_port="2525"}
+: ${qpsmtpd_max_per_ip="3"}
+: ${qpsmtpd_max_connections="15"}
+: ${qpsmtpd_listen_on=""}
+command_args="-d -p $qpsmtpd_port -c $qpsmtpd_max_connections -u $qpsmtpd_user -m $qpsmtpd_max_per_ip -l $qpsmtpd_listen_on --pid-file $pidfile"
 run_rc_command "$1"

More information about the freebsd-ports mailing list