aboutsummaryrefslogtreecommitdiffstats
path: root/net-p2p/dctc
diff options
context:
space:
mode:
authorlioux <lioux@FreeBSD.org>2002-08-05 02:03:54 +0800
committerlioux <lioux@FreeBSD.org>2002-08-05 02:03:54 +0800
commit0a088c5b4922cc986effdb7801f461d3d6b40cb4 (patch)
tree247715711e2577880629c2609ff380f6567c604a /net-p2p/dctc
parentbe106e898ed711d36fb33492cfa6ecc72c95372a (diff)
downloadfreebsd-ports-gnome-0a088c5b4922cc986effdb7801f461d3d6b40cb4.tar.gz
freebsd-ports-gnome-0a088c5b4922cc986effdb7801f461d3d6b40cb4.tar.zst
freebsd-ports-gnome-0a088c5b4922cc986effdb7801f461d3d6b40cb4.zip
o Update to 0.83.2
o Fix long standing issue with upload feature: client would freeze in semwait state. It was a pthread vs semaphore issue and a database lookup issue. Check PR for complete report o All patches are related to upload feature fix PR: 41323
Diffstat (limited to 'net-p2p/dctc')
-rw-r--r--net-p2p/dctc/Makefile20
-rw-r--r--net-p2p/dctc/distinfo2
-rw-r--r--net-p2p/dctc/files/lp_mutex.c122
-rw-r--r--net-p2p/dctc/files/patch-src::dc_manage.c77
-rw-r--r--net-p2p/dctc/files/patch-src::main.c23
-rw-r--r--net-p2p/dctc/files/patch-src::mydb.c28
-rw-r--r--net-p2p/dctc/files/patch-src::sema.c158
-rw-r--r--net-p2p/dctc/pkg-plist11
8 files changed, 434 insertions, 7 deletions
diff --git a/net-p2p/dctc/Makefile b/net-p2p/dctc/Makefile
index 45410abcd11e..6730b66747d2 100644
--- a/net-p2p/dctc/Makefile
+++ b/net-p2p/dctc/Makefile
@@ -6,7 +6,7 @@
#
PORTNAME= dctc
-PORTVERSION= 0.83.1
+PORTVERSION= 0.83.2
CATEGORIES= net
MASTER_SITES= http://ac2i.tzo.com/dctc/
DISTNAME= ${PORTNAME}-${PORTVERSION}
@@ -20,11 +20,12 @@ LIB_DEPENDS= db4.0:${PORTSDIR}/databases/db4 \
USE_GNOMENG= yes
USE_GNOME= glib12
USE_PERL5= yes
+USE_REINPLACE= yes
GNU_CONFIGURE= yes
CONFIGURE_ENV= CPPFLAGS="-I${LOCALBASE}/include \
${PTHREAD_CFLAGS}" \
LDFLAGS="-L${LOCALBASE}/lib -lgnugetopt \
- ${PTHREAD_LIBS}"
+ ${PTHREAD_LIBS:S/"//g}"
CONFIGURE_ARGS= --enable-manual-db-detect
MANCOMPRESSED= no
@@ -36,16 +37,25 @@ DOC_FILES= COPYING ChangeLog INSTALL README \
Documentation/BerkeleyDB \
Documentation/BerkeleyDB.nl \
Documentation/DCextensions/p2p_capabilities \
+ Documentation/DCextensions/p2p_capabilities.nl \
Documentation/DCextensions/search_by_content \
+ Documentation/DCextensions/search_by_content.nl \
Documentation/GDL.nl \
Documentation/GDL Documentation/VAR \
+ Documentation/LS_cache Documentation/UNODE.nl \
+ Documentation/VAR.nl \
Documentation/UNODE Documentation/Vshare \
Documentation/Vshare.nl \
Documentation/commands \
+ Documentation/commands.nl \
Documentation/programs.nl \
Documentation/programs.pl \
+ Documentation/output.nl \
Documentation/output Documentation/programs
+post-extract:
+ @${CP} ${FILESDIR}/lp_mutex.c ${WRKSRC}/src
+
post-patch:
.for file in ${DOC_FILES}
@${PERL} -pi -e 's|(hublist)|dc_\1|' ${WRKSRC}/${file}
@@ -59,16 +69,18 @@ post-patch:
${CONFIGURE_WRKSRC}/${CONFIGURE_SCRIPT}
@${PERL} -pi -e 's|/usr/bin/env perl|${PERL}|' \
${WRKSRC}/GDLjoiner
+ @${REINPLACE_CMD} -E -e 's|^(dctc_SOURCES.+)$$|\1 lp_mutex.c|; \
+ s|^(dctc_OBJECTS[^\\]+)(\\*)$$|\1 lp_mutex.o \2|' \
+ ${WRKSRC}/src/Makefile.in
pre-build:
@${ECHO_CMD} '#ifndef MSG_NOSIGNAL' >> ${CONFIGURE_WRKSRC}/config.h
@${ECHO_CMD} '# define MSG_NOSIGNAL 0' >> ${CONFIGURE_WRKSRC}/config.h
@${ECHO_CMD} '#endif' >> ${CONFIGURE_WRKSRC}/config.h
- @${ECHO_CMD} '#include <errno.h>' >> ${CONFIGURE_WRKSRC}/config.h
@${ECHO_CMD} '#ifndef ENODATA' >> ${CONFIGURE_WRKSRC}/config.h
@${ECHO_CMD} '# define ENODATA ENOMSG' >> ${CONFIGURE_WRKSRC}/config.h
@${ECHO_CMD} '#endif' >> ${CONFIGURE_WRKSRC}/config.h
- @${ECHO_CMD} '#include <sys/param.h>' >> ${CONFIGURE_WRKSRC}/config.h
+ @${ECHO_CMD} '#define HAVE_SYS_PARAM_H 1' >> ${CONFIGURE_WRKSRC}/config.h
do-install:
.ifndef(NOPORTDOCS)
diff --git a/net-p2p/dctc/distinfo b/net-p2p/dctc/distinfo
index 450dc5590c67..6d31a5f4b515 100644
--- a/net-p2p/dctc/distinfo
+++ b/net-p2p/dctc/distinfo
@@ -1 +1 @@
-MD5 (dctc-0.83.1.tar.gz) = c42e2712dab06a3b6a7fd9800215c495
+MD5 (dctc-0.83.2.tar.gz) = 70d0d6131223b98a34c814ecacd83b5e
diff --git a/net-p2p/dctc/files/lp_mutex.c b/net-p2p/dctc/files/lp_mutex.c
new file mode 100644
index 000000000000..2c76d0aaea55
--- /dev/null
+++ b/net-p2p/dctc/files/lp_mutex.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2000, 2001, 2002
+ * Mario Sergio Fujikawa Ferreira <lioux@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#include <stdlib.h>
+
+#ifdef _THREAD_SAFE
+# include <pthread.h>
+
+/*
+ * Use a mutex under BSD systems to avoid problems with semaphores
+ * blocking all the threads since BSD have MIT pthreads user space
+ * threads. If not BSD, use some stubs that do nothing. Since these
+ * stubs are empty, most modern compilers will simply add a NOP at
+ * the calling point.
+ */
+# if (defined(BSD) && (BSD >= 199103))
+int
+lp_mutex_init_ (pthread_mutex_t ** mutex,
+ const pthread_mutexattr_t *attr)
+{
+ pthread_mutex_t * mutex_temp;
+
+ if ( (mutex_temp = \
+ (pthread_mutex_t *) malloc (sizeof(pthread_mutex_t))) ) {
+
+ if ( (pthread_mutex_init(mutex_temp, attr)) == 0) {
+
+ (*mutex) = mutex_temp;
+ return (1);
+ } else {
+ return (0);
+ }
+ } else {
+ /* Not enough memory */
+ return (-1);
+ }
+}
+
+int
+lp_mutex_lock_ (pthread_mutex_t * mutex)
+{
+ if ( (pthread_mutex_lock(mutex)) == 0) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+int
+lp_mutex_unlock_ (pthread_mutex_t * mutex)
+{
+ if ( (pthread_mutex_unlock(mutex)) == 0) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+int
+lp_mutex_destroy_ (pthread_mutex_t ** mutex)
+{
+ if ( (pthread_mutex_destroy(*mutex)) == 0) {
+ free (*mutex);
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+# else /* !(defined(BSD) && (BSD >= 199103)) */
+
+int
+lp_mutex_init_ (pthread_mutex_t ** mutex,
+ const pthread_mutexattr_t *attr) {}
+
+int
+lp_mutex_lock_ (pthread_mutex_t * mutex) {}
+
+int
+lp_mutex_unlock_ (pthread_mutex_t * mutex) {}
+
+int
+lp_mutex_destroy_ (pthread_mutex_t ** mutex) {}
+
+# endif /* (defined(BSD) && (BSD >= 199103)) */
+
+#endif /* _THREAD_SAFE */
diff --git a/net-p2p/dctc/files/patch-src::dc_manage.c b/net-p2p/dctc/files/patch-src::dc_manage.c
new file mode 100644
index 000000000000..b9475fd2baf4
--- /dev/null
+++ b/net-p2p/dctc/files/patch-src::dc_manage.c
@@ -0,0 +1,77 @@
+--- src/dc_manage.c.orig Mon Jul 22 13:20:19 2002
++++ src/dc_manage.c Mon Jul 22 18:18:40 2002
+@@ -554,18 +554,6 @@
+
+ unconvert_path(fullpathname);
+
+- if(!file_in_db(fullpathname,&virtual)) /* is it a shared file ? */
+- {
+- GString *err_msg;
+-
+- err_msg=g_string_new("$Error ");
+- g_string_sprintfa(err_msg,"%s no more exists",fullpathname);
+- disp_msg(DEBUG_MSG,"com_up_get_process","file not found",err_msg->str,NULL);
+- send_dc_line(sck,err_msg->str,NULL);
+- g_string_free(err_msg,TRUE);
+- return 1;
+- }
+-
+ if(hide_absolute==0)
+ {
+ if(((unsigned char)fullpathname[0])==255)
+@@ -580,6 +568,18 @@
+ fullpathname[0]='/';
+ }
+
++ if(!file_in_db(fullpathname,&virtual)) /* is it a shared file ? */
++ {
++ GString *err_msg;
++
++ err_msg=g_string_new("$Error ");
++ g_string_sprintfa(err_msg,"%s no more exists",fullpathname);
++ disp_msg(DEBUG_MSG,"com_up_get_process","file not found",err_msg->str,NULL);
++ send_dc_line(sck,err_msg->str,NULL);
++ g_string_free(err_msg,TRUE);
++ return 1;
++ }
++
+ /* it is time to verify if a slot is available */
+ LOCK_WRITE(user_info);
+ if((dl_on==0)||(virtual!=0))
+@@ -743,18 +743,6 @@
+
+ unconvert_path(fullpathname);
+
+- if(!file_in_db(fullpathname,&virtual)) /* is it a shared file ? */
+- {
+- GString *err_msg;
+-
+- err_msg=g_string_new("$Error ");
+- g_string_sprintfa(err_msg,"%s no more exists",fullpathname);
+- disp_msg(DEBUG_MSG,"com_up_getfilelength_process","file not found",err_msg->str,NULL);
+- send_dc_line(sck,err_msg->str,NULL);
+- g_string_free(err_msg,TRUE);
+- return 1;
+- }
+-
+ if(hide_absolute==0)
+ {
+ if(((unsigned char)fullpathname[0])==255)
+@@ -769,6 +757,17 @@
+ fullpathname[0]='/';
+ }
+
++ if(!file_in_db(fullpathname,&virtual)) /* is it a shared file ? */
++ {
++ GString *err_msg;
++
++ err_msg=g_string_new("$Error ");
++ g_string_sprintfa(err_msg,"%s no more exists",fullpathname);
++ disp_msg(DEBUG_MSG,"com_up_getfilelength_process","file not found",err_msg->str,NULL);
++ send_dc_line(sck,err_msg->str,NULL);
++ g_string_free(err_msg,TRUE);
++ return 1;
++ }
+
+ if(send_file_length(sck,fullpathname,&file_len))
+ {
diff --git a/net-p2p/dctc/files/patch-src::main.c b/net-p2p/dctc/files/patch-src::main.c
new file mode 100644
index 000000000000..f3dbf9fc0e51
--- /dev/null
+++ b/net-p2p/dctc/files/patch-src::main.c
@@ -0,0 +1,23 @@
+--- src/main.c.orig Sun Aug 4 10:58:23 2002
++++ src/main.c Sun Aug 4 11:00:57 2002
+@@ -34,7 +34,12 @@
+ #include <sys/param.h>
+ #include <sys/utsname.h>
+ #include <sys/un.h>
++#if !(defined(BSD) && (BSD >= 199103))
+ #include <linux/sem.h> /* for the value of SEMVMX */
++#else
++#include <sys/ipc.h>
++#include <sys/sem.h> /* for the value of SEMVMX */
++#endif
+ #include <errno.h>
+ #include <getopt.h>
+ #include <string.h>
+@@ -1253,6 +1258,7 @@
+
+ char *virtual_share_path=NULL;
+
++ hide_absolute=1;
+ disp_msg(INFO_MSG,NULL,"Direct Connect Text Client v" VERSION ,NULL);
+
+ if(argc==1)
diff --git a/net-p2p/dctc/files/patch-src::mydb.c b/net-p2p/dctc/files/patch-src::mydb.c
new file mode 100644
index 000000000000..ab57f7bb2f50
--- /dev/null
+++ b/net-p2p/dctc/files/patch-src::mydb.c
@@ -0,0 +1,28 @@
+--- src/mydb.c.orig Mon Jul 22 13:48:07 2002
++++ src/mydb.c Mon Jul 22 19:21:42 2002
+@@ -1141,6 +1141,16 @@
+ int file_in_db(char *filename, int *virtual)
+ {
+ int i;
++ char *filename_internal;
++
++ if ((filename != NULL) && (filename[0]=='/'))
++ {
++ if(hide_absolute==0)
++ filename_internal=filename;
++ else
++ filename_internal=filename+1;
++ } else
++ filename_internal=filename;
+
+ G_LOCK(shared_info);
+ if(shared_info!=NULL)
+@@ -1151,7 +1161,7 @@
+
+ /* DB_ENTRY to compare */
+ de=&(g_array_index(shared_info,DB_ENTRY,i));
+- if(!strcmp(de->filename,filename))
++ if(!strcmp(de->filename,filename_internal))
+ {
+ *virtual=de->virtual;
+ G_UNLOCK(shared_info);
diff --git a/net-p2p/dctc/files/patch-src::sema.c b/net-p2p/dctc/files/patch-src::sema.c
new file mode 100644
index 000000000000..60ae0eb570c5
--- /dev/null
+++ b/net-p2p/dctc/files/patch-src::sema.c
@@ -0,0 +1,158 @@
+--- src/sema.c.orig Sun Jul 21 21:13:59 2002
++++ src/sema.c Mon Jul 22 19:30:15 2002
+@@ -22,6 +22,10 @@
+ # include <config.h>
+ #endif
+
++#ifdef HAVE_SYS_PARAM_H
++# include <sys/param.h>
++#endif
++
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -57,6 +61,11 @@
+ #include "uaddr.h"
+ #include "status.h"
+
++/* interval between busy wait tries measured in microseconds */
++#define MUTEX_BUSY_WAIT_TIME 5000
++
++pthread_mutex_t *semaphore_mutex = PTHREAD_MUTEX_INITIALIZER;
++
+ /***********************************************************************/
+ /* the following functions manage the bandwidth upload limit */
+ /* The system is build on 2 semaphores and 1 file */
+@@ -100,6 +109,8 @@
+
+ int semid;
+
++ lp_mutex_init_(&semaphore_mutex, NULL);
++
+ fd=open(keyfile,O_CREAT|O_WRONLY|O_EXCL,0600); /* create the file if not exists */
+ if(fd==-1)
+ {
+@@ -131,7 +142,11 @@
+ {
+ close(fd);
+ /* a key exist */
++#if !(defined(BSD) && (BSD >= 199103))
+ semid=semget(key,0,IPC_ALLOC);
++#else
++ semid=semget(key,0,IPC_STAT);
++#endif
+ if(semid==-1)
+ goto create_new_sema;
+ printf("current sema found.\n");
+@@ -293,8 +308,13 @@
+ void check_sema_master(int semid)
+ {
+ struct sembuf sb={0,-1,IPC_NOWAIT|SEM_UNDO}; /* master sema */
++ int result;
++
++ (void) lp_mutex_lock_(semaphore_mutex);
++ result = semop(semid,&sb,1);
++ (void) lp_mutex_unlock_(semaphore_mutex);
+
+- if(semop(semid,&sb,1)==0)
++ if (result==0)
+ {
+ /* to get slice, the function checks if the clock thread still runs */
+ create_sema_master(semid);
+@@ -308,15 +328,29 @@
+ /*******************************************/
+ void get_slice(int semid, SPD_SEMA semnum)
+ {
++#if !(defined(BSD) && (BSD >= 199103))
++ struct sembuf local={0,-1,0}; /* slave sema */
++#else
++ struct sembuf local={0,-1,0|IPC_NOWAIT}; /* slave sema */
++#endif
++ local.sem_num=semnum;
++
++ (void) lp_mutex_lock_(semaphore_mutex);
+ while(1)
+ {
+- struct sembuf local={0,-1,0}; /* slave sema */
+-
+- local.sem_num=semnum;
+- if(semop(semid,&local,1)==0)
+- {
+- /* we have what we want */
+- return;
++ switch (semop(semid,&local,1)) {
++ case 0: (void) lp_mutex_unlock_(semaphore_mutex);
++ /* we have what we want */
++ return;
++ break;
++ case -1: switch(errno) {
++ case EAGAIN: /* triggers busy wait */
++ case EINTR: /* interrupted by system call, try again */
++ pthread_yield();
++ usleep(MUTEX_BUSY_WAIT_TIME); /* busy wait with a small time out */
++ continue;
++ break;
++ }
+ }
+ }
+ }
+@@ -368,9 +402,26 @@
+ /******************************/
+ void lock_ul_slot_controler(int semid)
+ {
++#if !(defined(BSD) && (BSD >= 199103))
+ struct sembuf get_ul_ctrl={UL_SLOT_SEMA,-1,SEM_UNDO};
++#else
++ struct sembuf get_ul_ctrl={UL_SLOT_SEMA,-1,SEM_UNDO|IPC_NOWAIT};
++#endif
++
++ (void) lp_mutex_lock_(semaphore_mutex);
++repeat:
+ /* lock the UL slot controler */
+- semop(semid,&get_ul_ctrl,1);
++ if (semop(semid,&get_ul_ctrl,1)==-1)
++ switch(errno)
++ {
++ case EAGAIN: /* triggers busy wait */
++ case EINTR: /* interrupted by system call, try again */
++ pthread_yield();
++ usleep(MUTEX_BUSY_WAIT_TIME); /* busy wait with a small time out */
++ goto repeat;
++ break;
++ }
++ (void) lp_mutex_unlock_(semaphore_mutex);
+ }
+
+ /*********************************/
+@@ -526,11 +577,28 @@
+ perror("free_one_ul_slot");
+ }
+ #else
++# if !(defined(BSD) && (BSD >= 199103))
+ struct sembuf free_one_ul_slot_op={UL_SLOT_BUSY_SEMA,-1,SEM_UNDO};
+- if(semop(semid,&free_one_ul_slot_op,1)==-1)
+- {
+- perror("free_one_ul_slot");
++# else
++ struct sembuf free_one_ul_slot_op={UL_SLOT_BUSY_SEMA,-1,SEM_UNDO|IPC_NOWAIT};
++# endif
++
++ (void) lp_mutex_lock_(semaphore_mutex);
++repeat:
++ if(semop(semid,&free_one_ul_slot_op,1)==-1) {
++ switch(errno) {
++ case EAGAIN: /* triggers busy wait */
++ case EINTR: /* interrupted by system call, try again */
++ pthread_yield();
++ usleep(MUTEX_BUSY_WAIT_TIME); /* busy wait with a small time out */
++ goto repeat;
++ break;
++ default:
++ perror("free_one_ul_slot");
++ break;
++ }
+ }
++ (void) lp_mutex_unlock_(semaphore_mutex);
+ #endif
+ nb_local_ul--;
+ }
diff --git a/net-p2p/dctc/pkg-plist b/net-p2p/dctc/pkg-plist
index 8504ca80e83a..98c67b0c2130 100644
--- a/net-p2p/dctc/pkg-plist
+++ b/net-p2p/dctc/pkg-plist
@@ -1,20 +1,27 @@
bin/dc_hublist
bin/dctc
-%%PORTDOCS%%share/dctc/GDLjoiner
+share/dctc/GDLjoiner
%%PORTDOCS%%share/doc/dctc/COPYING
%%PORTDOCS%%share/doc/dctc/ChangeLog
%%PORTDOCS%%share/doc/dctc/Documentation/BerkeleyDB
%%PORTDOCS%%share/doc/dctc/Documentation/BerkeleyDB.nl
%%PORTDOCS%%share/doc/dctc/Documentation/DCextensions/p2p_capabilities
+%%PORTDOCS%%share/doc/dctc/Documentation/DCextensions/p2p_capabilities.nl
%%PORTDOCS%%share/doc/dctc/Documentation/DCextensions/search_by_content
+%%PORTDOCS%%share/doc/dctc/Documentation/DCextensions/search_by_content.nl
%%PORTDOCS%%share/doc/dctc/Documentation/GDL
%%PORTDOCS%%share/doc/dctc/Documentation/GDL.nl
+%%PORTDOCS%%share/doc/dctc/Documentation/LS_cache
%%PORTDOCS%%share/doc/dctc/Documentation/UNODE
+%%PORTDOCS%%share/doc/dctc/Documentation/UNODE.nl
%%PORTDOCS%%share/doc/dctc/Documentation/VAR
+%%PORTDOCS%%share/doc/dctc/Documentation/VAR.nl
%%PORTDOCS%%share/doc/dctc/Documentation/Vshare
%%PORTDOCS%%share/doc/dctc/Documentation/Vshare.nl
%%PORTDOCS%%share/doc/dctc/Documentation/commands
+%%PORTDOCS%%share/doc/dctc/Documentation/commands.nl
%%PORTDOCS%%share/doc/dctc/Documentation/output
+%%PORTDOCS%%share/doc/dctc/Documentation/output.nl
%%PORTDOCS%%share/doc/dctc/Documentation/programs
%%PORTDOCS%%share/doc/dctc/Documentation/programs.nl
%%PORTDOCS%%share/doc/dctc/Documentation/programs.pl
@@ -25,4 +32,4 @@ bin/dctc
%%PORTDOCS%%@dirrm share/doc/dctc/Documentation/DCextensions
%%PORTDOCS%%@dirrm share/doc/dctc/Documentation
%%PORTDOCS%%@dirrm share/doc/dctc
-%%PORTDOCS%%@dirrm share/dctc
+@dirrm share/dctc