mirror of
https://github.com/hanwckf/immortalwrt-mt798x.git
synced 2025-01-10 03:09:08 +08:00
ntlf9t: move packages to packages
feed
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
parent
2b0bacb188
commit
841ca52d24
@ -1,55 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015 OpenWrt-dist
|
||||
# Copyright (C) 2015 Jian Chang <aa65535@live.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ShadowVPN
|
||||
PKG_VERSION:=0.2.0
|
||||
PKG_RELEASE:=$(AUTORELESE)
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/aa65535/openwrt-shadowvpn/releases/download/v$(PKG_VERSION)
|
||||
PKG_HASH:=53b445cf47262f407bfef72d32bc6ca5d1341dcd3878ac2b4cd35ee030199dea
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILES:=COPYING
|
||||
PKG_MAINTAINER:=clowwindy <clowwindy42@gmail.com>
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ShadowVPN
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=A fast, safe VPN based on libsodium
|
||||
URL:=https://github.com/clowwindy/ShadowVPN
|
||||
DEPENDS:=+kmod-tun +ip
|
||||
endef
|
||||
|
||||
define Package/ShadowVPN/conffiles
|
||||
/etc/config/shadowvpn
|
||||
endef
|
||||
|
||||
define Package/ShadowVPN/install
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_DATA) ./files/shadowvpn.config $(1)/etc/config/shadowvpn
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/shadowvpn.init $(1)/etc/init.d/shadowvpn
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_DATA) ./files/shadowvpn.hotplug $(1)/etc/hotplug.d/iface/30-shadowvpn
|
||||
$(INSTALL_DIR) $(1)/etc/shadowvpn
|
||||
$(INSTALL_DATA) ./files/client_up.sh $(1)/etc/shadowvpn/client_up.sh
|
||||
$(INSTALL_DATA) ./files/client_down.sh $(1)/etc/shadowvpn/client_down.sh
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/shadowvpn $(1)/usr/bin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ShadowVPN))
|
@ -1,44 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2015 OpenWrt-dist
|
||||
# Copyright (C) 2015 Jian Chang <aa65535@live.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
# This script will be executed when client is down.
|
||||
# All key value pairs in ShadowVPN config file will be passed to this script
|
||||
# as environment variables, except password.
|
||||
|
||||
PID=$(cat $pidfile 2>/dev/null)
|
||||
loger() {
|
||||
echo "$(date '+%c') down.$1 ShadowVPN[$PID] $2"
|
||||
}
|
||||
|
||||
# Get uci setting
|
||||
route_mode=$(uci get shadowvpn.@shadowvpn[-1].route_mode_save 2>/dev/null)
|
||||
|
||||
# Turn off NAT over VPN
|
||||
iptables -t nat -D POSTROUTING -o $intf -j MASQUERADE
|
||||
iptables -D FORWARD -i $intf -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
iptables -D FORWARD -o $intf -j ACCEPT
|
||||
loger notice "Turn off NAT over $intf"
|
||||
|
||||
# Change routing table
|
||||
ip route del $server
|
||||
if [ "$route_mode" != 2 ]; then
|
||||
ip route del 0.0.0.0/1
|
||||
ip route del 128.0.0.0/1
|
||||
loger notice "Default route changed to original route"
|
||||
fi
|
||||
|
||||
# Remove route rules
|
||||
if [ -f /tmp/shadowvpn_routes ]; then
|
||||
sed -e "s/^/route del /" /tmp/shadowvpn_routes | ip -batch -
|
||||
loger notice "Route rules have been removed"
|
||||
fi
|
||||
|
||||
rm -rf /tmp/shadowvpn_routes
|
||||
|
||||
loger info "Script $0 completed"
|
@ -1,59 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2015 OpenWrt-dist
|
||||
# Copyright (C) 2015 Jian Chang <aa65535@live.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
# This script will be executed when client is up.
|
||||
# All key value pairs in ShadowVPN config file will be passed to this script
|
||||
# as environment variables, except password.
|
||||
|
||||
PID=$(cat $pidfile 2>/dev/null)
|
||||
loger() {
|
||||
echo "$(date '+%c') up.$1 ShadowVPN[$PID] $2"
|
||||
}
|
||||
|
||||
# Configure IP address and MTU of VPN interface
|
||||
ip addr add $net dev $intf
|
||||
ip link set $intf mtu $mtu
|
||||
ip link set $intf up
|
||||
|
||||
# Get original gateway
|
||||
gateway=$(ip route show 0/0 | sed -e 's/.* via \([^ ]*\).*/\1/')
|
||||
loger info "The default gateway: via $gateway"
|
||||
|
||||
# Get uci setting
|
||||
route_mode=$(uci get shadowvpn.@shadowvpn[-1].route_mode 2>/dev/null)
|
||||
route_file=$(uci get shadowvpn.@shadowvpn[-1].route_file 2>/dev/null)
|
||||
|
||||
# Save uci setting
|
||||
uci set shadowvpn.@shadowvpn[-1].route_mode_save=$route_mode
|
||||
uci commit shadowvpn
|
||||
|
||||
# Turn on NAT over VPN
|
||||
iptables -t nat -A POSTROUTING -o $intf -j MASQUERADE
|
||||
iptables -I FORWARD 1 -i $intf -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
iptables -I FORWARD 1 -o $intf -j ACCEPT
|
||||
loger notice "Turn on NAT over $intf"
|
||||
|
||||
# Change routing table
|
||||
suf="dev $intf"
|
||||
ip route add $server via $gateway
|
||||
if [ "$route_mode" != 2 ]; then
|
||||
ip route add 0.0.0.0/1 dev $intf
|
||||
ip route add 128.0.0.0/1 dev $intf
|
||||
loger notice "Default route changed to VPN tun"
|
||||
suf="via $gateway"
|
||||
fi
|
||||
|
||||
# Load route rules
|
||||
if [ "$route_mode" != 0 -a -f "$route_file" ]; then
|
||||
grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}" $route_file >/tmp/shadowvpn_routes
|
||||
sed -e "s/^/route add /" -e "s/$/ $suf/" /tmp/shadowvpn_routes | ip -batch -
|
||||
loger notice "Route rules have been loaded"
|
||||
fi
|
||||
|
||||
loger info "Script $0 completed"
|
@ -1,12 +0,0 @@
|
||||
|
||||
config shadowvpn
|
||||
option enable '0'
|
||||
option server '127.0.0.1'
|
||||
option port '1123'
|
||||
option password 'my_password'
|
||||
option concurrency '1'
|
||||
option net '10.7.0.2/24'
|
||||
option mtu '1432'
|
||||
option intf 'tun0'
|
||||
option route_mode '1'
|
||||
option route_file '/etc/chinadns_chnroute.txt'
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$ACTION" = ifup ] || exit 0
|
||||
|
||||
device=$(ip route show 0/0 | sed -e 's/.* dev \([^ ]*\).*/\1/')
|
||||
|
||||
[ -z "$device" -o "$DEVICE" = "$device" ] || exit 0
|
||||
|
||||
/etc/init.d/shadowvpn restart
|
||||
logger -t ShadowVPN "Restart ShadowVPN due to ifup of $INTERFACE ($DEVICE)"
|
@ -1,71 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2015 OpenWrt-dist
|
||||
# Copyright (C) 2015 Jian Chang <aa65535@live.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
START=90
|
||||
STOP=15
|
||||
|
||||
CONFIG=/var/etc/shadowvpn.conf
|
||||
|
||||
start_vpn() {
|
||||
local enable server port password concurrency mtu intf
|
||||
config_get_bool enable $1 enable
|
||||
[ "$enable" = 1 ] || return 0
|
||||
config_get server $1 server
|
||||
config_get port $1 port
|
||||
config_get user_token $1 user_token
|
||||
config_get password $1 password
|
||||
config_get concurrency $1 concurrency
|
||||
config_get net $1 net
|
||||
config_get mtu $1 mtu
|
||||
config_get intf $1 intf
|
||||
: ${server:?}
|
||||
: ${port:?}
|
||||
: ${password:?}
|
||||
: ${user_token:=0000000000000000}
|
||||
mkdir -p $(dirname $CONFIG)
|
||||
cat <<-EOF >$CONFIG
|
||||
server=$server
|
||||
port=$port
|
||||
password=$password
|
||||
mode=client
|
||||
concurrency=1
|
||||
net=${net:-10.7.0.2/24}
|
||||
mtu=${mtu:-1432}
|
||||
intf=${intf:-tun0}
|
||||
up=/etc/shadowvpn/client_up.sh
|
||||
down=/etc/shadowvpn/client_down.sh
|
||||
pidfile=/var/run/shadowvpn.pid
|
||||
logfile=/var/log/shadowvpn.log
|
||||
EOF
|
||||
if [ "$user_token" != "0000000000000000" ]; then
|
||||
echo "user_token=$user_token" >>$CONFIG
|
||||
fi
|
||||
/usr/bin/shadowvpn -c $CONFIG -s start
|
||||
}
|
||||
|
||||
start() {
|
||||
config_load shadowvpn
|
||||
config_foreach start_vpn shadowvpn
|
||||
}
|
||||
|
||||
stop() {
|
||||
/usr/bin/shadowvpn -c $CONFIG -s stop
|
||||
}
|
||||
|
||||
boot() {
|
||||
if [ ! -c "/dev/net/tun" ]; then
|
||||
mkdir -p /dev/net
|
||||
mknod /dev/net/tun c 10 200
|
||||
chmod 0666 /dev/net/tun
|
||||
fi
|
||||
until ip route show 0/0 | grep -q "^default"; do
|
||||
sleep 1
|
||||
done
|
||||
start
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index d8461de..9b3fcbd 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -1,6 +1,3 @@
|
||||
-EXTRA_DIST = \
|
||||
- autogen.sh \
|
||||
- README.md \
|
||||
- COPYING
|
||||
+EXTRA_DIST = autogen.sh
|
||||
|
||||
-SUBDIRS = src samples
|
||||
+SUBDIRS = src
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index dc562d4..f54171c 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -79,6 +79,6 @@ AC_ARG_ENABLE([analyze],
|
||||
|
||||
AM_CONDITIONAL(STATIC, test x"$static" = x"true")
|
||||
|
||||
-AC_CONFIG_FILES([Makefile src/Makefile samples/Makefile])
|
||||
+AC_CONFIG_FILES([Makefile src/Makefile])
|
||||
AC_CONFIG_SUBDIRS([libsodium])
|
||||
AC_OUTPUT
|
||||
diff --git a/libsodium/Makefile.am b/libsodium/Makefile.am
|
||||
index ee794b0..5a73134 100644
|
||||
--- a/libsodium/Makefile.am
|
||||
+++ b/libsodium/Makefile.am
|
||||
@@ -1,19 +1,8 @@
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
-EXTRA_DIST = \
|
||||
- autogen.sh \
|
||||
- libsodium.sln \
|
||||
- libsodium.vcxproj \
|
||||
- libsodium.vcxproj.filters \
|
||||
- LICENSE \
|
||||
- README.markdown \
|
||||
- THANKS
|
||||
+EXTRA_DIST = autogen.sh
|
||||
|
||||
-SUBDIRS = \
|
||||
- dist-build \
|
||||
- msvc-scripts \
|
||||
- src \
|
||||
- test
|
||||
+SUBDIRS = src
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = @PACKAGE_NAME@.pc
|
||||
diff --git a/libsodium/configure.ac b/libsodium/configure.ac
|
||||
index 21b8f10..281e3ff 100644
|
||||
--- a/libsodium/configure.ac
|
||||
+++ b/libsodium/configure.ac
|
||||
@@ -442,15 +442,10 @@ AH_VERBATIM([NDEBUG], [/* Always evaluate assert() calls */
|
||||
#endif])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
- dist-build/Makefile
|
||||
libsodium.pc
|
||||
- libsodium-uninstalled.pc
|
||||
- msvc-scripts/Makefile
|
||||
src/Makefile
|
||||
src/libsodium/Makefile
|
||||
src/libsodium/include/Makefile
|
||||
src/libsodium/include/sodium/version.h
|
||||
- test/default/Makefile
|
||||
- test/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
@ -1,51 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2014-2018 OpenWrt-dist
|
||||
# Copyright (C) 2014-2018 Jian Chang <aa65535@live.com>
|
||||
# Copyright (C) 2021 ImmortalWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=chinadns
|
||||
PKG_VERSION:=1.3.3
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/aa65535/ChinaDNS/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=74e53af32f8aa2ca7e63697385f12d89a06c486641556cfd8bc3f085d87e55ad
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/ChinaDNS-$(PKG_VERSION)
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=Jian Chang <aa65535@live.com>
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/chinadns
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Protect yourself against DNS poisoning in China.
|
||||
URL:=https://github.com/shadowsocks/ChinaDNS
|
||||
endef
|
||||
|
||||
define Package/chinadns/conffiles
|
||||
/usr/share/chinadns/chnroute.txt
|
||||
/usr/share/chinadns/iplist.txt
|
||||
endef
|
||||
|
||||
define Package/chinadns/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/chinadns $(1)/usr/bin/
|
||||
$(INSTALL_DIR) $(1)/usr/share/chinadns
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/share/chnroute.txt $(1)/usr/share/chinadns/
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/share/iplist.txt $(1)/usr/share/chinadns/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,chinadns))
|
@ -1,27 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=cpulimit-ng
|
||||
PKG_VERSION:=1.2
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/cpulimit-ng
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=CPU Usage Limiter for Linux
|
||||
endef
|
||||
|
||||
define Pacakge/cpulimit-ng/description
|
||||
cpulimit-ng is a simple program which attempts to limit the cpu
|
||||
usage of a process (expressed in percentage, not in cpu time).
|
||||
endef
|
||||
|
||||
define Package/cpulimit-ng/install
|
||||
$(INSTALL_DIR) $(1)/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/cpulimit-ng $(1)/bin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,cpulimit-ng))
|
@ -1,20 +0,0 @@
|
||||
###############################################################################
|
||||
# Gather all flags.
|
||||
#
|
||||
CFLAGS+=-DPOSIXLY_CORRECT -Wall -g
|
||||
|
||||
TARGET=cpulimit-ng
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
SOURCES = $(wildcard *.c)
|
||||
OBJS = $(patsubst %.c,%.o, $(SOURCES))
|
||||
|
||||
$(TARGET) : $(OBJS)
|
||||
$(CC) `for X in $(OBJS) ; do echo "$$X"; done` -o $(TARGET) $(LIBS) $(LDFLAGS)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(TARGET)
|
@ -1,47 +0,0 @@
|
||||
Cpulimit 1.2
|
||||
|
||||
=======
|
||||
About
|
||||
=======
|
||||
|
||||
Cpulimit is a program that attempts to limit the cpu usage of a process (expressed in percentage, not in cpu time). It is useful to control batch jobs, when you don't want they eat too much cpu. The goal it to not let a proces run for more than a specified time ratio. It does not act on the nice value or other scheduling priority stuff, but on the real cpu usage. Also, it is able to adapt itself to the overall system load, dynamically and quickly.
|
||||
The control of the used cpu amount is done sending properly SIGSTOP and SIGCONT POSIX signals to processes.
|
||||
All the children processes and threads of the specified process will share the same percent of cpu.
|
||||
|
||||
Developed by Angelo Marletta.
|
||||
Please send your feedback, bug reports, feature requests or just thanks :) to marlonx80@hotmail.com.
|
||||
|
||||
=====================
|
||||
Changelog since 1.1
|
||||
=====================
|
||||
|
||||
- reorganization of the code, splitted in more source files
|
||||
- cpu count detection, i.e. if you have 4 cpu, it is possible to limit up to 400%
|
||||
- in order to avoid deadlocks, cpulimit now prevents to limit itself
|
||||
- option --path eliminated, use --exe instead both for absolute path and file name
|
||||
- call setpriority() just once
|
||||
- no more segmentation fault when processes exit
|
||||
- no more memory corruption when processes exit
|
||||
- cpulimit exits if --lazy option is specified and the process terminates
|
||||
- target process can be created on-fly given command line
|
||||
- light and scalable algorithm for subprocesses detection and limitation
|
||||
- mac os support
|
||||
- minor enhancements and bugfixes
|
||||
|
||||
============================
|
||||
Get the latest source code
|
||||
============================
|
||||
|
||||
You can checkout the latest code from sourceforge Subversion repository, running:
|
||||
|
||||
svn checkout https://cpulimit.svn.sourceforge.net/svnroot/cpulimit cpulimit
|
||||
|
||||
Of course this is the development version, so you may experience bugs (please signal them and your soul will be saved!)
|
||||
|
||||
|
||||
==============
|
||||
Installation
|
||||
==============
|
||||
|
||||
Run 'make' and place the executable file 'cpulimit' wherever you want.
|
||||
Type 'cpulimit --help' to get documentation on available options.
|
@ -1,601 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a cpu limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2012, by: Gang Liu <gangban.lau@gmail.com>
|
||||
* Copyright (C) 2005-2008, by: Angelo Marletta <marlonx80@hotmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
*
|
||||
* This is a simple program to limit the cpu usage of a process
|
||||
* If you modify this code, send me a copy please
|
||||
*
|
||||
* Date: 30/8/2008
|
||||
* Version: 1.2 beta
|
||||
* Get the latest version at: http://cpulimit.sourceforge.net
|
||||
*
|
||||
* Changelog from 1.1:
|
||||
* - reorganization of the code, splitted in more source files
|
||||
* - cpu count detection, i.e. if you have 4 cpu, it is possible to limit up to 400%
|
||||
* - in order to avoid deadlocks, cpulimit now prevents to limit itself
|
||||
* - option --path eliminated, use --exe instead both for absolute path and file name
|
||||
* - call setpriority() just once in limit_process()
|
||||
* - no more segmentation fault when processes exit
|
||||
* - no more memory corruption when processes exit
|
||||
* - cpulimit exits if --lazy option is specified and the process terminates
|
||||
* - target process can be created on-fly given command line
|
||||
* - light and scalable algorithm for subprocesses detection and limitation
|
||||
* - mac os support
|
||||
* - minor enhancements and bugfixes
|
||||
*
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "process.h"
|
||||
#include "procutils.h"
|
||||
#include "list.h"
|
||||
|
||||
//some useful macro
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
//control time slot in microseconds
|
||||
//each slot is splitted in a working slice and a sleeping slice
|
||||
//TODO: make it adaptive, based on the actual system load
|
||||
#define TIME_SLOT 100000
|
||||
|
||||
#define MAX_PRIORITY -10
|
||||
|
||||
/* GLOBAL VARIABLES */
|
||||
|
||||
//the "family"
|
||||
struct process_family pf;
|
||||
//pid of cpulimit
|
||||
pid_t cpulimit_pid;
|
||||
//name of this program (maybe cpulimit...)
|
||||
char *program_name;
|
||||
|
||||
//number of cpu
|
||||
int NCPU;
|
||||
|
||||
/* CONFIGURATION VARIABLES */
|
||||
|
||||
//verbose mode
|
||||
int verbose = 0;
|
||||
//lazy mode (exits if there is no process)
|
||||
int lazy = 0;
|
||||
|
||||
static void *memrchr(const void *s, int c, size_t n)
|
||||
{
|
||||
const unsigned char *start = (const unsigned char*)s;
|
||||
const unsigned char *end = (const unsigned char*)s;
|
||||
|
||||
end+=n-1;
|
||||
|
||||
while(end>=start) {
|
||||
if(*end==c)
|
||||
return (void *)end;
|
||||
else
|
||||
end--;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//SIGINT and SIGTERM signal handler
|
||||
static void quit(int sig)
|
||||
{
|
||||
//let all the processes continue if stopped
|
||||
struct list_node *node = NULL;
|
||||
for (node=pf.members.first; node!= NULL; node=node->next) {
|
||||
struct process *p = (struct process*)(node->data);
|
||||
kill(p->pid, SIGCONT);
|
||||
process_close(p);
|
||||
}
|
||||
//free all the memory
|
||||
cleanup_process_family(&pf);
|
||||
//fix ^C little problem
|
||||
printf("\r");
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//return t1-t2 in microseconds (no overflow checks, so better watch out!)
|
||||
static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2)
|
||||
{
|
||||
return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec);
|
||||
}
|
||||
|
||||
static void print_usage(FILE *stream, int exit_code)
|
||||
{
|
||||
fprintf(stream, "Usage: %s [OPTIONS...] TARGET\n", program_name);
|
||||
fprintf(stream, " OPTIONS\n");
|
||||
fprintf(stream, " -l, --limit=N percentage of cpu allowed from 0 to %d (required)\n", 100*NCPU);
|
||||
fprintf(stream, " -v, --verbose show control statistics\n");
|
||||
fprintf(stream, " -z, --lazy exit if there is no target process, or if it dies\n");
|
||||
fprintf(stream, " -i, --ignore-children don't limit children processes\n");
|
||||
fprintf(stream, " -h, --help display this help and exit\n");
|
||||
fprintf(stream, " TARGET must be exactly one of these:\n");
|
||||
fprintf(stream, " -p, --pid=N pid of the process (implies -z)\n");
|
||||
fprintf(stream, " -e, --exe=FILE name of the executable program file or path name\n");
|
||||
fprintf(stream, " COMMAND [ARGS] run this command and limit it (implies -z)\n");
|
||||
fprintf(stream, "\nReport bugs to <marlonx80@hotmail.com>.\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static void increase_priority() {
|
||||
//find the best available nice value
|
||||
errno = 0; // clear errno first
|
||||
int old_priority = getpriority(PRIO_PROCESS, 0);
|
||||
if (errno)
|
||||
{
|
||||
perror("getpriority failed");
|
||||
return;
|
||||
}
|
||||
int priority = old_priority;
|
||||
while (priority > MAX_PRIORITY && setpriority(PRIO_PROCESS, 0, priority-1) == 0) {
|
||||
priority--;
|
||||
}
|
||||
if (priority != old_priority) {
|
||||
if (verbose) printf("Priority changed to %d\n", priority);
|
||||
}
|
||||
else {
|
||||
if (verbose) printf("Warning: Cannot change priority. Run as root or renice for best results.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the number of CPUs */
|
||||
static int get_ncpu() {
|
||||
int ncpu = -1;
|
||||
#ifdef _SC_NPROCESSORS_ONLN
|
||||
ncpu = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#elif defined __APPLE__
|
||||
int mib[2] = {CTL_HW, HW_NCPU};
|
||||
size_t len = sizeof(ncpu);
|
||||
sysctl(mib, 2, &ncpu, &len, NULL, 0);
|
||||
#endif
|
||||
return ncpu;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
static int check_proc()
|
||||
{
|
||||
struct statfs mnt;
|
||||
if (statfs("/proc", &mnt) < 0)
|
||||
return 0;
|
||||
if (mnt.f_type!=0x9fa0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void limit_process(pid_t pid, double limit, int ignore_children)
|
||||
{
|
||||
//slice of the slot in which the process is allowed to run
|
||||
struct timespec twork;
|
||||
//slice of the slot in which the process is stopped
|
||||
struct timespec tsleep;
|
||||
//when the last twork has started
|
||||
struct timeval startwork;
|
||||
//when the last twork has finished
|
||||
struct timeval endwork;
|
||||
//initialization
|
||||
memset(&twork, 0, sizeof(struct timespec));
|
||||
memset(&tsleep, 0, sizeof(struct timespec));
|
||||
memset(&startwork, 0, sizeof(struct timeval));
|
||||
memset(&endwork, 0, sizeof(struct timeval));
|
||||
//last working time in microseconds
|
||||
unsigned long workingtime = 0;
|
||||
//generic list item
|
||||
struct list_node *node;
|
||||
//counter
|
||||
int c = 0;
|
||||
|
||||
//get a better priority
|
||||
//increase_priority();
|
||||
|
||||
//build the family
|
||||
if (create_process_family(&pf, pid) == -1)
|
||||
{
|
||||
printf("create process family failed");
|
||||
return ;
|
||||
}
|
||||
if (ignore_children) {
|
||||
//delete any process with a different pid than the father
|
||||
node = pf.members.first;
|
||||
while (node!=NULL) {
|
||||
struct process *proc = (struct process*)(node->data);
|
||||
if (proc->pid != pid)
|
||||
{
|
||||
remove_process_from_family(&pf, proc->pid);
|
||||
node = pf.members.first;
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignore_children && verbose) printf("Members in the family owned by %d: %d\n", pf.father, pf.members.count);
|
||||
|
||||
//rate at which we are keeping active the processes (range 0-1)
|
||||
//1 means that the process are using all the twork slice
|
||||
double workingrate = -1;
|
||||
while(1) {
|
||||
if (!ignore_children && c%10==0) {
|
||||
//update the process family (checks only for new members)
|
||||
int new_children = update_process_family(&pf);
|
||||
if (verbose && new_children) {
|
||||
printf("%d new children processes detected (", new_children);
|
||||
int j;
|
||||
node = pf.members.last;
|
||||
for (j=0; j<new_children; j++) {
|
||||
printf("%d", ((struct process*)(node->data))->pid);
|
||||
if (j<new_children-1) printf(" ");
|
||||
node = node->previous;
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (pf.members.count==0) {
|
||||
if (verbose) printf("No more processes.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
//total cpu actual usage (range 0-1)
|
||||
//1 means that the processes are using 100% cpu
|
||||
double pcpu = -1;
|
||||
|
||||
//estimate how much the controlled processes are using the cpu in the working interval
|
||||
node = pf.members.first;
|
||||
while (node!=NULL) {
|
||||
struct process *proc = (struct process*)(node->data);
|
||||
if (proc->is_zombie) {
|
||||
//process is zombie, remove it from family
|
||||
fprintf(stderr,"Process %d is zombie!\n", proc->pid);
|
||||
remove_process_from_family(&pf, proc->pid);
|
||||
node = pf.members.first;
|
||||
continue;
|
||||
}
|
||||
if (process_monitor(proc) != 0) {
|
||||
//process is dead, remove it from family
|
||||
if (verbose) fprintf(stderr,"Process %d dead!\n", proc->pid);
|
||||
remove_process_from_family(&pf, proc->pid);
|
||||
node = pf.members.first;
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
if (proc->cpu_usage<0) {
|
||||
continue;
|
||||
}
|
||||
if (pcpu<0) pcpu = 0;
|
||||
pcpu += proc->cpu_usage;
|
||||
}
|
||||
|
||||
//adjust work and sleep time slices
|
||||
if (pcpu < 0) {
|
||||
//it's the 1st cycle, initialize workingrate
|
||||
pcpu = limit;
|
||||
workingrate = limit;
|
||||
twork.tv_nsec = TIME_SLOT*limit*1000;
|
||||
}
|
||||
else {
|
||||
//adjust workingrate
|
||||
workingrate = MIN(workingrate / pcpu * limit, 1);
|
||||
twork.tv_nsec = TIME_SLOT*1000*workingrate;
|
||||
}
|
||||
tsleep.tv_nsec = TIME_SLOT*1000-twork.tv_nsec;
|
||||
|
||||
if (verbose) {
|
||||
if (c%200==0)
|
||||
printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n");
|
||||
if (c%10==0 && c>0)
|
||||
printf("%0.2lf%%\t%6ld us\t%6ld us\t%0.2lf%%\n",pcpu*100,twork.tv_nsec/1000,tsleep.tv_nsec/1000,workingrate*100);
|
||||
}
|
||||
|
||||
//resume processes
|
||||
node = pf.members.first;
|
||||
while (node!=NULL) {
|
||||
struct process *proc = (struct process*)(node->data);
|
||||
if (kill(proc->pid,SIGCONT)!=0) {
|
||||
//process is dead, remove it from family
|
||||
if (verbose) fprintf(stderr,"Process %d dead!\n", proc->pid);
|
||||
remove_process_from_family(&pf, proc->pid);
|
||||
node = pf.members.first;
|
||||
continue;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
//now processes are free to run (same working slice for all)
|
||||
gettimeofday(&startwork, NULL);
|
||||
nanosleep(&twork,NULL);
|
||||
gettimeofday(&endwork, NULL);
|
||||
workingtime = timediff(&endwork,&startwork);
|
||||
|
||||
long delay = workingtime-twork.tv_nsec/1000;
|
||||
if (c>0 && delay>10000) {
|
||||
//delay is too much! signal to user?
|
||||
//fprintf(stderr, "%d %ld us\n", c, delay);
|
||||
}
|
||||
|
||||
if (tsleep.tv_nsec>0) {
|
||||
//stop only if tsleep>0, instead it's useless
|
||||
node=pf.members.first;
|
||||
while (node!=NULL) {
|
||||
struct process *proc = (struct process*)(node->data);
|
||||
if (kill(proc->pid,SIGSTOP)!=0) {
|
||||
//process is dead, remove it from family
|
||||
if (verbose) fprintf(stderr,"Process %d dead!\n", proc->pid);
|
||||
remove_process_from_family(&pf, proc->pid);
|
||||
node=pf.members.first;
|
||||
continue;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
//now the processes are sleeping
|
||||
nanosleep(&tsleep,NULL);
|
||||
}
|
||||
c++;
|
||||
}
|
||||
cleanup_process_family(&pf);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
//argument variables
|
||||
const char *exe = NULL;
|
||||
int perclimit = 0;
|
||||
int exe_ok = 0;
|
||||
int pid_ok = 0;
|
||||
int limit_ok = 0;
|
||||
pid_t pid = 0;
|
||||
int ignore_children = 0;
|
||||
|
||||
//get program name
|
||||
char *p=(char*)memrchr(argv[0],(unsigned int)'/',strlen(argv[0]));
|
||||
program_name = p==NULL?argv[0]:(p+1);
|
||||
//get current pid
|
||||
cpulimit_pid = getpid();
|
||||
//get cpu count
|
||||
NCPU = get_ncpu();
|
||||
|
||||
//parse arguments
|
||||
int next_option;
|
||||
int option_index = 0;
|
||||
//A string listing valid short options letters
|
||||
const char* short_options = "+p:e:l:vzih";
|
||||
//An array describing valid long options
|
||||
const struct option long_options[] = {
|
||||
{ "pid", required_argument, NULL, 'p' },
|
||||
{ "exe", required_argument, NULL, 'e' },
|
||||
{ "limit", required_argument, NULL, 'l' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "lazy", no_argument, NULL, 'z' },
|
||||
{ "ignore-children", no_argument, NULL, 'i' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
do {
|
||||
next_option = getopt_long(argc, argv, short_options,long_options, &option_index);
|
||||
switch(next_option) {
|
||||
case 'p':
|
||||
pid = atoi(optarg);
|
||||
pid_ok = 1;
|
||||
break;
|
||||
case 'e':
|
||||
exe = optarg;
|
||||
exe_ok = 1;
|
||||
break;
|
||||
case 'l':
|
||||
perclimit = atoi(optarg);
|
||||
limit_ok = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'z':
|
||||
lazy = 1;
|
||||
break;
|
||||
case 'i':
|
||||
ignore_children = 1;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(stdout, 1);
|
||||
break;
|
||||
case '?':
|
||||
print_usage(stderr, 1);
|
||||
break;
|
||||
case -1:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
} while(next_option != -1);
|
||||
|
||||
if (pid_ok && (pid<=1 || pid>=65536)) {
|
||||
fprintf(stderr,"Error: Invalid value for argument PID\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
if (pid!=0) {
|
||||
lazy = 1;
|
||||
}
|
||||
|
||||
if (!limit_ok) {
|
||||
fprintf(stderr,"Error: You must specify a cpu limit percentage\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
double limit = perclimit/100.0;
|
||||
if (limit<0 || limit >NCPU) {
|
||||
fprintf(stderr,"Error: limit must be in the range 0-%d00\n", NCPU);
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int command_mode = optind<argc;
|
||||
if (exe_ok + pid_ok + command_mode == 0) {
|
||||
fprintf(stderr,"Error: You must specify one target process, either by name, pid, or command line\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (exe_ok + pid_ok + command_mode > 1) {
|
||||
fprintf(stderr,"Error: You must specify exactly one target process, either by name, pid, or command line\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//all arguments are ok!
|
||||
signal(SIGINT, quit);
|
||||
signal(SIGTERM, quit);
|
||||
|
||||
//print the number of available cpu
|
||||
if (verbose) printf("%d cpu detected\n", NCPU);
|
||||
|
||||
#ifdef __linux__
|
||||
if (!check_proc()) {
|
||||
fprintf(stderr, "procfs is not mounted!\nAborting\n");
|
||||
exit(-2);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (command_mode) {
|
||||
int i;
|
||||
//executable file
|
||||
const char *cmd = argv[optind];
|
||||
//command line arguments
|
||||
char **cmd_args = (char**)malloc((argc-optind+1)*sizeof(char*));
|
||||
if (cmd_args==NULL) exit(2);
|
||||
for (i=0; i<argc-optind; i++) {
|
||||
cmd_args[i] = argv[i+optind];
|
||||
}
|
||||
cmd_args[i] = NULL;
|
||||
|
||||
if (verbose) {
|
||||
printf("Running command: '%s", cmd);
|
||||
for (i=1; i<argc-optind; i++) {
|
||||
printf(" %s", cmd_args[i]);
|
||||
}
|
||||
printf("'\n");
|
||||
}
|
||||
|
||||
int child = fork();
|
||||
if (child < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if (child > 0) {
|
||||
//parent code
|
||||
int limiter = fork();
|
||||
if (limiter < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if (limiter > 0) {
|
||||
//parent
|
||||
int status_process;
|
||||
int status_limiter;
|
||||
waitpid(child, &status_process, 0);
|
||||
waitpid(limiter, &status_limiter, 0);
|
||||
if (WIFEXITED(status_process)) {
|
||||
if (verbose) printf("Process %d terminated with exit status %d\n", child, (int)WEXITSTATUS(status_process));
|
||||
exit(WEXITSTATUS(status_process));
|
||||
}
|
||||
printf("Process %d terminated abnormally\n", child);
|
||||
exit(status_process);
|
||||
}
|
||||
else {
|
||||
//limiter code
|
||||
if (verbose) printf("Limiting process %d\n",child);
|
||||
limit_process(child, limit, ignore_children);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//target process code
|
||||
int ret = execvp(cmd, cmd_args);
|
||||
//if we are here there was an error, show it
|
||||
perror("Error");
|
||||
exit(ret);
|
||||
}
|
||||
}
|
||||
|
||||
while(1) {
|
||||
//look for the target process..or wait for it
|
||||
pid_t ret = 0;
|
||||
if (pid_ok) {
|
||||
//search by pid
|
||||
ret = look_for_process_by_pid(pid);
|
||||
if (ret == 0) {
|
||||
printf("No process found\n");
|
||||
}
|
||||
else if (ret < 0) {
|
||||
printf("Process found but you aren't allowed to control it\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
//search by file or path name
|
||||
ret = look_for_process_by_name(exe);
|
||||
if (ret == 0) {
|
||||
printf("No process found\n");
|
||||
}
|
||||
else if (ret < 0) {
|
||||
printf("Process found but you aren't allowed to control it\n");
|
||||
}
|
||||
else {
|
||||
pid = ret;
|
||||
}
|
||||
}
|
||||
if (ret > 0) {
|
||||
if (ret == cpulimit_pid) {
|
||||
printf("Process %d is cpulimit itself! Aborting to avoid deadlock\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
printf("Process %d found\n", pid);
|
||||
//control
|
||||
limit_process(pid, limit, ignore_children);
|
||||
}
|
||||
if (lazy) break;
|
||||
sleep(2);
|
||||
};
|
||||
|
||||
exit(0);
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a cpu limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2008, by: Angelo Marletta <marlonx80@hotmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
*
|
||||
* Dynamic list implementation
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#define EMPTYLIST NULL
|
||||
|
||||
void init_list(struct list *l,int keysize) {
|
||||
l->first=l->last=NULL;
|
||||
l->keysize=keysize;
|
||||
l->count=0;
|
||||
}
|
||||
|
||||
struct list_node *add_elem(struct list *l,void *elem) {
|
||||
struct list_node *newnode=(struct list_node*)malloc(sizeof(struct list_node));
|
||||
newnode->data=elem;
|
||||
newnode->previous=l->last;
|
||||
newnode->next=NULL;
|
||||
if (l->count==0) {
|
||||
l->first=l->last=newnode;
|
||||
}
|
||||
else {
|
||||
l->last->next=newnode;
|
||||
l->last=newnode;
|
||||
}
|
||||
l->count++;
|
||||
return newnode;
|
||||
}
|
||||
|
||||
void delete_node(struct list *l,struct list_node *node) {
|
||||
if (l->count==1) {
|
||||
l->first=l->last=NULL;
|
||||
}
|
||||
else if (node==l->first) {
|
||||
node->next->previous=NULL;
|
||||
l->first=node->next;
|
||||
}
|
||||
else if (node==l->last) {
|
||||
node->previous->next=NULL;
|
||||
l->last=node->previous;
|
||||
}
|
||||
else {
|
||||
node->previous->next=node->next;
|
||||
node->next->previous=node->previous;
|
||||
}
|
||||
l->count--;
|
||||
free(node);
|
||||
node = NULL;
|
||||
}
|
||||
|
||||
void destroy_node(struct list *l,struct list_node *node) {
|
||||
free(node->data);
|
||||
node->data=NULL;
|
||||
delete_node(l,node);
|
||||
}
|
||||
|
||||
int is_EMPTYLIST_list(struct list *l) {
|
||||
return (l->count==0?TRUE:FALSE);
|
||||
}
|
||||
|
||||
int get_list_count(struct list *l) {
|
||||
return l->count;
|
||||
}
|
||||
|
||||
void *first_elem(struct list *l) {
|
||||
return l->first->data;
|
||||
}
|
||||
|
||||
struct list_node *first_node(struct list *l) {
|
||||
return l->first;
|
||||
}
|
||||
|
||||
void *last_elem(struct list *l) {
|
||||
return l->last->data;
|
||||
}
|
||||
|
||||
struct list_node *last_node(struct list *l) {
|
||||
return l->last;
|
||||
}
|
||||
|
||||
struct list_node *xlocate_node(struct list *l,void *elem,int offset,int length) {
|
||||
struct list_node *tmp;
|
||||
tmp=l->first;
|
||||
while(tmp!=NULL) {
|
||||
if(!memcmp((char*)tmp->data+offset,elem,length==0?l->keysize:length)) return (tmp);
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return EMPTYLIST;
|
||||
}
|
||||
|
||||
struct list_node *locate_node(struct list *l,void *elem) {
|
||||
return(xlocate_node(l,elem,0,0));
|
||||
}
|
||||
|
||||
void *xlocate_elem(struct list *l,void *elem,int offset,int length) {
|
||||
struct list_node *node=xlocate_node(l,elem,offset,length);
|
||||
return(node==NULL?NULL:node->data);
|
||||
}
|
||||
|
||||
void *locate_elem(struct list *l,void *elem) {
|
||||
return(xlocate_elem(l,elem,0,0));
|
||||
}
|
||||
|
||||
void flush_list(struct list *l) {
|
||||
struct list_node *tmp;
|
||||
while(l->first!=EMPTYLIST) {
|
||||
tmp=l->first;
|
||||
l->first=l->first->next;
|
||||
free(tmp);
|
||||
tmp=NULL;
|
||||
}
|
||||
l->last=EMPTYLIST;
|
||||
l->count=0;
|
||||
}
|
||||
|
||||
void destroy_list(struct list *l) {
|
||||
struct list_node *tmp;
|
||||
while(l->first!=EMPTYLIST) {
|
||||
tmp=l->first;
|
||||
l->first=l->first->next;
|
||||
free(tmp->data);
|
||||
tmp->data=NULL;
|
||||
free(tmp);
|
||||
tmp=NULL;
|
||||
}
|
||||
l->last=EMPTYLIST;
|
||||
l->count=0;
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a cpu limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2008, by: Angelo Marletta <marlonx80@hotmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
*
|
||||
* Dynamic list interface
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LIST__
|
||||
|
||||
#define __LIST__
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
struct list_node {
|
||||
//pointer to the content of the node
|
||||
void *data;
|
||||
//pointer to previous node
|
||||
struct list_node *previous;
|
||||
//pointer to next node
|
||||
struct list_node *next;
|
||||
};
|
||||
|
||||
struct list {
|
||||
//first node
|
||||
struct list_node *first;
|
||||
//last node
|
||||
struct list_node *last;
|
||||
//size of the search key in bytes
|
||||
int keysize;
|
||||
//element count
|
||||
int count;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize a list, with a specified key size
|
||||
*/
|
||||
void init_list(struct list *l,int keysize);
|
||||
|
||||
/*
|
||||
* Add a new element at the end of the list
|
||||
* return the pointer to the new node
|
||||
*/
|
||||
struct list_node *add_elem(struct list *l,void *elem);
|
||||
|
||||
/*
|
||||
* Delete a node
|
||||
*/
|
||||
void delete_node(struct list *l,struct list_node *node);
|
||||
|
||||
/*
|
||||
* Delete a node from the list, even the content pointed by it
|
||||
* Use only when the content is a dynamically allocated pointer
|
||||
*/
|
||||
void destroy_node(struct list *l,struct list_node *node);
|
||||
|
||||
/*
|
||||
* Check whether a list is empty or not
|
||||
*/
|
||||
int is_empty_list(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the element count of the list
|
||||
*/
|
||||
int get_list_count(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the first element (content of the node) from the list
|
||||
*/
|
||||
void *first_elem(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the first node from the list
|
||||
*/
|
||||
struct list_node *first_node(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the last element (content of the node) from the list
|
||||
*/
|
||||
void *last_elem(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the last node from the list
|
||||
*/
|
||||
struct list_node *last_node(struct list *l);
|
||||
|
||||
/*
|
||||
* Search an element of the list by content
|
||||
* the comparison is done from the specified offset and for a specified length
|
||||
* if offset=0, the comparison starts from the address pointed by data
|
||||
* if length=0, default keysize is used for length
|
||||
* if the element is found, return the node address
|
||||
* else return NULL
|
||||
*/
|
||||
struct list_node *xlocate_node(struct list *l,void *elem,int offset,int length);
|
||||
|
||||
/*
|
||||
* The same of xlocate_node(), but return the content of the node
|
||||
*/
|
||||
void *xlocate_elem(struct list *l,void *elem,int offset,int length);
|
||||
|
||||
/*
|
||||
* The same of calling xlocate_node() with offset=0 and length=0
|
||||
*/
|
||||
struct list_node *locate_node(struct list *l,void *elem);
|
||||
|
||||
/*
|
||||
* The same of locate_node, but return the content of the node
|
||||
*/
|
||||
void *locate_elem(struct list *l,void *elem);
|
||||
|
||||
/*
|
||||
* Delete all the elements in the list
|
||||
*/
|
||||
void flush_list(struct list *l);
|
||||
|
||||
/*
|
||||
* Delete every element in the list, and free the memory pointed by all the node data
|
||||
*/
|
||||
void destroy_list(struct list *l);
|
||||
|
||||
#endif
|
@ -1,283 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a cpu limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2012, by: Gang Liu <gangban.lau@gmail.com>
|
||||
* Copyright (C) 2005-2008, by: Angelo Marletta <marlonx80@hotmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
//TODO: add documentation to public functions
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "process.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int get_proc_info(struct process *p, pid_t pid) {
|
||||
/* static char statfile[20];
|
||||
static char buffer[64];
|
||||
int ret;
|
||||
sprintf(statfile, "/proc/%d/stat", pid);
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (fd==NULL) return -1;
|
||||
fgets(buffer, sizeof(buffer), fd);
|
||||
fclose(fd);
|
||||
|
||||
char state;
|
||||
|
||||
int n = sscanf(buffer, "%d %s %c %d %d %d %d %d "
|
||||
"%lu %lu %lu %lu %lu %lu %lu "
|
||||
"%ld %ld %ld %ld %ld %ld "
|
||||
"%lu ",
|
||||
&p->pid,
|
||||
&p->command,
|
||||
&state,
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
|
||||
&utime,&stime,&cutime,&cstime,
|
||||
NULL,NULL,NULL,NULL,
|
||||
&starttime,
|
||||
);*/
|
||||
return 0;
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
int get_proc_info(struct process *p, pid_t pid) {
|
||||
int err;
|
||||
struct kinfo_proc *result = NULL;
|
||||
size_t length;
|
||||
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
|
||||
|
||||
/* We start by calling sysctl with result == NULL and length == 0.
|
||||
That will succeed, and set length to the appropriate length.
|
||||
We then allocate a buffer of that size and call sysctl again
|
||||
with that buffer.
|
||||
*/
|
||||
length = 0;
|
||||
err = sysctl(mib, 4, NULL, &length, NULL, 0);
|
||||
if (err == -1) {
|
||||
err = errno;
|
||||
}
|
||||
if (err == 0) {
|
||||
result = malloc(length);
|
||||
err = sysctl(mib, 4, result, &length, NULL, 0);
|
||||
if (err == -1)
|
||||
err = errno;
|
||||
if (err == ENOMEM) {
|
||||
free(result); /* clean up */
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
p->pid = result->kp_proc.p_pid;
|
||||
p->ppid = result->kp_eproc.e_ppid;
|
||||
p->starttime = result->kp_proc.p_starttime.tv_sec;
|
||||
p->last_jiffies = result->kp_proc.p_cpticks;
|
||||
//p_pctcpu
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
// TODO man 5 proc, scanf, see above get_proc_info
|
||||
static char * get_proc_stat_field(const char * statfile, int idx)
|
||||
{
|
||||
char buffer[1024];
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (fd==NULL)
|
||||
{
|
||||
perror("open process stat file failed");
|
||||
return NULL;
|
||||
}
|
||||
if (fgets(buffer, sizeof(buffer), fd) == NULL)
|
||||
{
|
||||
perror("read process stat file failed");
|
||||
fclose(fd);
|
||||
return NULL;
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
char *p = buffer;
|
||||
int slen = strlen(buffer);
|
||||
int sp = idx;
|
||||
while (sp-- && p != NULL && (p+1) < (buffer + slen))
|
||||
p = strchr(p+1, ' ');
|
||||
if (p==NULL || (p+1) >= (buffer + slen))
|
||||
{
|
||||
printf("process stat file format error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *q = strchr(p+1, ' ');
|
||||
if (q==NULL)
|
||||
{
|
||||
printf("process stat file format error");
|
||||
return NULL;
|
||||
}
|
||||
*q = '\0';
|
||||
char *item = (char *)malloc(strlen(p+1) + 1);
|
||||
if (item != NULL)
|
||||
{
|
||||
snprintf(item, strlen(p+1) + 1, "%s", p+1);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// returns the start time of a process (used with pid to identify a process)
|
||||
static unsigned long long get_starttime(pid_t pid)
|
||||
{
|
||||
#ifdef __linux__
|
||||
char file[20];
|
||||
snprintf(file, sizeof(file), "/proc/%d/stat", pid);
|
||||
//start time of the process
|
||||
char *tbuf = get_proc_stat_field(file, 21);
|
||||
if (tbuf == NULL)
|
||||
return -1;
|
||||
unsigned long long starttime = 0;
|
||||
sscanf(tbuf, "%llu", &starttime);
|
||||
free(tbuf);
|
||||
return starttime;
|
||||
#elif defined __APPLE__
|
||||
struct process proc;
|
||||
get_proc_info(&proc, pid);
|
||||
return proc.starttime;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int get_jiffies(struct process *proc) {
|
||||
#ifdef __linux__
|
||||
//user mode jiffies
|
||||
char *tbuf = get_proc_stat_field(proc->stat_file, 13);
|
||||
if (tbuf==NULL)
|
||||
return -1;
|
||||
unsigned long utime = 0;
|
||||
sscanf(tbuf, "%lu", &utime);
|
||||
free(tbuf);
|
||||
//kernel mode jiffies
|
||||
tbuf = get_proc_stat_field(proc->stat_file, 14);
|
||||
if (tbuf==NULL)
|
||||
return -1;
|
||||
unsigned long stime = 0;
|
||||
sscanf(tbuf, "%lu", &stime);
|
||||
free(tbuf);
|
||||
return utime+stime;
|
||||
#elif defined __APPLE__
|
||||
struct process proc2;
|
||||
get_proc_info(&proc2, proc->pid);
|
||||
return proc2.last_jiffies;
|
||||
#endif
|
||||
}
|
||||
|
||||
//return t1-t2 in microseconds (no overflow checks, so better watch out!)
|
||||
static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2)
|
||||
{
|
||||
return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec);
|
||||
}
|
||||
|
||||
/*static int*/ int process_update(struct process *proc) {
|
||||
//TODO: get any process statistic here
|
||||
//check that starttime is not changed(?), update jiffies, parent, zombie status
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_init(struct process *proc, int pid)
|
||||
{
|
||||
//general members
|
||||
proc->pid = pid;
|
||||
proc->starttime = get_starttime(pid);
|
||||
if (proc->starttime == -1)
|
||||
return -1;
|
||||
//printf("process starttime %d\n", proc->starttime);
|
||||
proc->cpu_usage = 0;
|
||||
memset(&(proc->last_sample), 0, sizeof(struct timeval));
|
||||
proc->last_jiffies = -1;
|
||||
proc->is_zombie = 0;
|
||||
//system dependent members
|
||||
#ifdef __linux__
|
||||
//TODO: delete these members for the sake of portability?
|
||||
//test /proc file descriptor for reading
|
||||
snprintf(proc->stat_file, sizeof(proc->stat_file), "/proc/%d/stat", pid);
|
||||
// FILE *fd = fopen(proc->stat_file, "r");
|
||||
// if (fd == NULL) return 1;
|
||||
// fclose(fd);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
//parameter in range 0-1
|
||||
#define ALFA 0.08
|
||||
|
||||
int process_monitor(struct process *proc)
|
||||
{
|
||||
int j = get_jiffies(proc);
|
||||
if (j<0) return -1; //error retrieving jiffies count (maybe the process is dead)
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
if (proc->last_jiffies==-1) {
|
||||
//store current time
|
||||
proc->last_sample.tv_sec = now.tv_sec;
|
||||
proc->last_sample.tv_usec = now.tv_usec;
|
||||
//store current jiffies
|
||||
proc->last_jiffies = j;
|
||||
//it's the first sample, cannot figure out the cpu usage
|
||||
proc->cpu_usage = -1;
|
||||
return 0;
|
||||
}
|
||||
//time from previous sample (in ns)
|
||||
long dt = timediff(&now, &(proc->last_sample));
|
||||
//how many jiffies in dt?
|
||||
double max_jiffies = dt * HZ / 1000000.0;
|
||||
double sample = (j - proc->last_jiffies) / max_jiffies;
|
||||
if (proc->cpu_usage == -1) {
|
||||
//initialization
|
||||
proc->cpu_usage = sample;
|
||||
}
|
||||
else {
|
||||
//usage adjustment
|
||||
proc->cpu_usage = (1-ALFA) * proc->cpu_usage + ALFA * sample;
|
||||
}
|
||||
|
||||
//store current time
|
||||
proc->last_sample.tv_sec = now.tv_sec;
|
||||
proc->last_sample.tv_usec = now.tv_usec;
|
||||
//store current jiffies
|
||||
proc->last_jiffies = j;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_close(struct process *proc)
|
||||
{
|
||||
if (kill(proc->pid,SIGCONT)!=0) {
|
||||
fprintf(stderr,"Process %d is already dead!\n", proc->pid);
|
||||
}
|
||||
proc->pid = 0;
|
||||
return 0;
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a cpu limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2008, by: Angelo Marletta <marlonx80@hotmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PROCESS_H
|
||||
|
||||
#define __PROCESS_H
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
//USER_HZ detection, from openssl code
|
||||
#ifndef HZ
|
||||
# if defined(_SC_CLK_TCK) \
|
||||
&& (!defined(OPENSSL_SYS_VMS) || __CTRL_VER >= 70000000)
|
||||
# define HZ ((double)sysconf(_SC_CLK_TCK))
|
||||
# else
|
||||
# ifndef CLK_TCK
|
||||
# ifndef _BSD_CLK_TCK_ /* FreeBSD hack */
|
||||
# define HZ 100.0
|
||||
# else /* _BSD_CLK_TCK_ */
|
||||
# define HZ ((double)_BSD_CLK_TCK_)
|
||||
# endif
|
||||
# else /* CLK_TCK */
|
||||
# define HZ ((double)CLK_TCK)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// process descriptor
|
||||
struct process {
|
||||
//pid of the process
|
||||
pid_t pid;
|
||||
//pid of the process
|
||||
pid_t ppid;
|
||||
//start time
|
||||
int starttime;
|
||||
//is member of the family?
|
||||
int member; //TODO: delete this field
|
||||
//total number of jiffies used by the process at time last_sample
|
||||
int last_jiffies;
|
||||
//timestamp when last_jiffies and cpu_usage was calculated
|
||||
struct timeval last_sample;
|
||||
//actual cpu usage estimation (value in range 0-1)
|
||||
double cpu_usage;
|
||||
//1 if the process is zombie
|
||||
int is_zombie;
|
||||
//absolute path of the executable file
|
||||
char command[PATH_MAX+1];
|
||||
|
||||
//system-dependent members
|
||||
//TODO: delete these members for the sake of portability?
|
||||
#ifdef __linux__
|
||||
//preallocate buffers for performance
|
||||
//name of /proc/PID/stat file
|
||||
char stat_file[20];
|
||||
//read buffer for /proc filesystem
|
||||
char buffer[1024];
|
||||
#endif
|
||||
};
|
||||
|
||||
int get_proc_info(struct process *p, pid_t pid);
|
||||
|
||||
int process_init(struct process *proc, pid_t pid);
|
||||
|
||||
int process_monitor(struct process *proc);
|
||||
|
||||
int process_close(struct process *proc);
|
||||
|
||||
#endif
|
@ -1,544 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a cpu limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2012, by: Gang Liu <gangban.lau@gmail.com>
|
||||
* Copyright (C) 2005-2008, by: Angelo Marletta <marlonx80@hotmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "procutils.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
/* PROCESS STATISTICS FUNCTIONS */
|
||||
|
||||
//deprecated
|
||||
// returns pid of the parent process
|
||||
static pid_t getppid_of(pid_t pid)
|
||||
{
|
||||
#ifdef __linux__
|
||||
char file[20];
|
||||
char buffer[1024];
|
||||
snprintf(file, sizeof(file), "/proc/%d/stat", pid);
|
||||
FILE *fd = fopen(file, "r");
|
||||
if (fd==NULL) return -1;
|
||||
if (fgets(buffer, sizeof(buffer), fd)==NULL)
|
||||
{
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
fclose(fd);
|
||||
char *p = buffer;
|
||||
p = memchr(p+1,')', sizeof(buffer) - (p-buffer));
|
||||
int sp = 2;
|
||||
while (sp--)
|
||||
p = memchr(p+1,' ',sizeof(buffer) - (p-buffer));
|
||||
//pid of the parent process
|
||||
pid_t ppid = atoi(p+1);
|
||||
return ppid;
|
||||
#elif defined __APPLE__
|
||||
struct process p;
|
||||
get_proc_info(&p, pid);
|
||||
return p.ppid;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
// detects whether a process is a kernel thread or not
|
||||
static int is_kernel_thread(pid_t pid)
|
||||
{
|
||||
char statfile[20];
|
||||
char buffer[64];
|
||||
int ret;
|
||||
snprintf(statfile, sizeof(statfile), "/proc/%d/statm", pid);
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (fd==NULL)
|
||||
{
|
||||
perror("open process statm file failed");
|
||||
return -1;
|
||||
}
|
||||
if (fgets(buffer, sizeof(buffer), fd)==NULL)
|
||||
{
|
||||
perror("read process statm file failed");
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
ret = strncmp(buffer,"0 0 0",3)==0;
|
||||
fclose(fd);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
//deprecated
|
||||
// returns 1 if pid is an existing pid, 0 otherwise
|
||||
static int process_exists(pid_t pid) {
|
||||
#ifdef __linux__
|
||||
char procdir[20];
|
||||
struct stat procstat;
|
||||
snprintf(procdir, sizeof(procdir), "/proc/%d", pid);
|
||||
return stat(procdir, &procstat)==0;
|
||||
#elif defined __APPLE__
|
||||
struct process p;
|
||||
return get_proc_info(&p, pid)==0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* PID HASH FUNCTIONS */
|
||||
|
||||
static int hash_process(struct process_family *f, struct process *p)
|
||||
{
|
||||
int ret;
|
||||
struct list **l = &(f->proctable[pid_hashfn(p->pid)]);
|
||||
if (*l == NULL) {
|
||||
//there is no process in this hashtable item
|
||||
//allocate the list
|
||||
*l = (struct list*)malloc(sizeof(struct list));
|
||||
init_list(*l, 4);
|
||||
add_elem(*l, p);
|
||||
ret = 0;
|
||||
f->count++;
|
||||
}
|
||||
else {
|
||||
//list already exists
|
||||
struct process *tmp = (struct process*)locate_elem(*l, p);
|
||||
if (tmp != NULL) {
|
||||
//update process info
|
||||
memcpy(tmp, p, sizeof(struct process));
|
||||
free(p);
|
||||
p = NULL;
|
||||
ret = 1;
|
||||
}
|
||||
else {
|
||||
//add new process
|
||||
add_elem(*l, p);
|
||||
ret = 0;
|
||||
f->count++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void unhash_process(struct process_family *f, pid_t pid) {
|
||||
//remove process from hashtable
|
||||
struct list **l = &(f->proctable[pid_hashfn(pid)]);
|
||||
if (*l == NULL)
|
||||
return; //nothing done
|
||||
struct list_node *node = locate_node(*l, &pid);
|
||||
if (node != NULL)
|
||||
destroy_node(*l, node);
|
||||
f->count--;
|
||||
}
|
||||
|
||||
static struct process *seek_process(struct process_family *f, pid_t pid)
|
||||
{
|
||||
struct list **l = &(f->proctable[pid_hashfn(pid)]);
|
||||
return (*l != NULL) ? (struct process*)locate_elem(*l, &pid) : NULL;
|
||||
}
|
||||
|
||||
/* PROCESS ITERATOR STUFF */
|
||||
|
||||
// creates an object that browse all running processes
|
||||
int init_process_iterator(struct process_iterator *i) {
|
||||
#ifdef __linux__
|
||||
//open a directory stream to /proc directory
|
||||
if ((i->dip = opendir("/proc")) == NULL) {
|
||||
perror("opendir");
|
||||
return -1;
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
|
||||
int err;
|
||||
struct kinfo_proc *result = NULL;
|
||||
size_t length;
|
||||
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
|
||||
|
||||
/* We start by calling sysctl with result == NULL and length == 0.
|
||||
That will succeed, and set length to the appropriate length.
|
||||
We then allocate a buffer of that size and call sysctl again
|
||||
with that buffer.
|
||||
*/
|
||||
length = 0;
|
||||
err = sysctl(mib, 4, NULL, &length, NULL, 0);
|
||||
if (err == -1) {
|
||||
err = errno;
|
||||
}
|
||||
if (err == 0) {
|
||||
result = malloc(length);
|
||||
err = sysctl(mib, 4, result, &length, NULL, 0);
|
||||
if (err == -1)
|
||||
err = errno;
|
||||
if (err == ENOMEM) {
|
||||
free(result); /* clean up */
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
i->procList = result;
|
||||
i->count = err == 0 ? length / sizeof *result : 0;
|
||||
i->c = 0;
|
||||
|
||||
#endif
|
||||
i->current = (struct process*)malloc(sizeof(struct process));
|
||||
if (i->current == NULL)
|
||||
{
|
||||
perror("malloc falied");
|
||||
closedir(i->dip);
|
||||
return -1;
|
||||
}
|
||||
memset(i->current, 0, sizeof(struct process));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// reads the next user process from /process
|
||||
// automatic closing if the end of the list is reached
|
||||
int read_next_process(struct process_iterator *i) {
|
||||
#ifdef __linux__
|
||||
pid_t pid = 0;
|
||||
//TODO read this to port to other systems: http://www.steve.org.uk/Reference/Unix/faq_8.html#SEC85
|
||||
//read in from /proc and seek for process dirs
|
||||
while ((i->dit = readdir(i->dip)) != NULL) {
|
||||
if(strtok(i->dit->d_name, "0123456789") != NULL)
|
||||
continue;
|
||||
pid = atoi(i->dit->d_name);
|
||||
if (is_kernel_thread(pid))
|
||||
{
|
||||
pid = 0;
|
||||
continue;
|
||||
}
|
||||
//return the first found process
|
||||
break;
|
||||
}
|
||||
if (pid == 0) {
|
||||
//no more processes
|
||||
closedir(i->dip);
|
||||
i->dip = NULL;
|
||||
free(i->current);
|
||||
i->current = NULL;
|
||||
return -1;
|
||||
}
|
||||
//read the executable link
|
||||
char statfile[20];
|
||||
snprintf(statfile, sizeof(statfile), "/proc/%d/cmdline",pid);
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (fd == NULL)
|
||||
{
|
||||
perror("open process cmdline file failed");
|
||||
return -1;
|
||||
}
|
||||
char buffer[1024];
|
||||
if (fgets(buffer, sizeof(buffer), fd)==NULL)
|
||||
{
|
||||
perror("read process cmdline file falied");
|
||||
fclose(fd);
|
||||
return -2;
|
||||
}
|
||||
fclose(fd);
|
||||
sscanf(buffer, "%s", (char*)&i->current->command);
|
||||
i->current->pid = pid;
|
||||
|
||||
#elif defined __APPLE__
|
||||
if (i->c >= i->count) {
|
||||
//no more processes
|
||||
free(i->procList);
|
||||
i->procList = NULL;
|
||||
free(i->current);
|
||||
i->current = NULL;
|
||||
return -1;
|
||||
}
|
||||
i->current->pid = i->procList[i->c].kp_proc.p_pid;
|
||||
strncpy(i->current->command, i->procList[i->c].kp_proc.p_comm, MAXCOMLEN);
|
||||
printf("%d %d %s\n", i->c, i->current->pid, i->current->command);//i->procList[i->c].kp_proc.p_comm);
|
||||
//printf("%d %d %s\n", i->c, i->current->pid, i->proc[i->c].kp_proc.p_comm);
|
||||
i->c++;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS */
|
||||
|
||||
// search for all the processes derived from father and stores them
|
||||
// in the process family struct
|
||||
int create_process_family(struct process_family *f, pid_t father)
|
||||
{
|
||||
//process iterator
|
||||
struct process_iterator iter;
|
||||
if (init_process_iterator(&iter) == -1)
|
||||
return -1;
|
||||
|
||||
//process list initialization (4 bytes key)
|
||||
init_list(&(f->members), 4);
|
||||
//hashtable initialization
|
||||
memset(&(f->proctable), 0, sizeof(f->proctable));
|
||||
f->count = 0;
|
||||
f->father = father;
|
||||
|
||||
int pid = 0;
|
||||
while (read_next_process(&iter)==0) {
|
||||
pid = iter.current->pid;
|
||||
//check if process belongs to the family
|
||||
int ppid = pid;
|
||||
//TODO: optimize adding also these parents, and continue if process is already present
|
||||
while(ppid!=1 && ppid!=father) {
|
||||
//pid_t f = getppid(ppid);
|
||||
ppid = getppid_of(ppid);
|
||||
//printf("p1 %d, p2 %d\n", f, ppid);
|
||||
}
|
||||
//allocate process descriptor
|
||||
struct process *p = (struct process*)malloc(sizeof(struct process));
|
||||
//init process
|
||||
if (process_init(p, pid) == -1)
|
||||
{
|
||||
printf("init process failed\n");
|
||||
free(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ppid==1) {
|
||||
//the init process
|
||||
p->member = 0;
|
||||
}
|
||||
else if (pid != getpid()) {
|
||||
//add to members (but exclude the current cpulimit process!)
|
||||
p->member = 1;
|
||||
add_elem(&(f->members), p);
|
||||
}
|
||||
//add to hashtable
|
||||
hash_process(f, p);
|
||||
}
|
||||
|
||||
if (iter.dip != NULL)
|
||||
closedir(iter.dip);
|
||||
if (iter.current != NULL)
|
||||
free(iter.current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// checks if there are new processes born in the specified family
|
||||
// if any they are added to the members list
|
||||
// the number of new born processes is returned
|
||||
int update_process_family(struct process_family *f)
|
||||
{
|
||||
//process iterator
|
||||
struct process_iterator iter;
|
||||
if (init_process_iterator(&iter) == -1)
|
||||
return -1;
|
||||
int ret = 0;
|
||||
int pid = 0;
|
||||
while (read_next_process(&iter)==0) {
|
||||
pid = iter.current->pid;
|
||||
struct process *newp = seek_process(f, pid);
|
||||
if (newp != NULL) continue; //already known //TODO: what if newp is a new process with the same PID??
|
||||
//the process is new, check if it belongs to the family
|
||||
int ppid = getppid_of(pid);
|
||||
//search the youngest known ancestor of the process
|
||||
struct process *ancestor = NULL;
|
||||
while((ancestor=seek_process(f, ppid))==NULL) {
|
||||
ppid = getppid_of(ppid);
|
||||
}
|
||||
if (ancestor == NULL) {
|
||||
//this should never happen! if does, find and correct the bug
|
||||
fprintf(stderr, "Fatal bug! Process %d is without parent\n", pid);
|
||||
exit(1);
|
||||
}
|
||||
//allocate and insert the process
|
||||
struct process *p = (struct process*)malloc(sizeof(struct process));
|
||||
//init process
|
||||
if (process_init(p, pid) == -1)
|
||||
{
|
||||
printf("init process failed\n");
|
||||
free(p);
|
||||
continue;
|
||||
}
|
||||
if (ancestor->member) {
|
||||
//add to members
|
||||
p->member = 1;
|
||||
add_elem(&(f->members), p);
|
||||
ret++;
|
||||
}
|
||||
else {
|
||||
//not a member
|
||||
p->member = 0;
|
||||
}
|
||||
//add to hashtable
|
||||
hash_process(f, p);
|
||||
}
|
||||
|
||||
if (iter.dip != NULL)
|
||||
closedir(iter.dip);
|
||||
if (iter.current != NULL)
|
||||
free(iter.current);
|
||||
|
||||
// remove non-member process if exited
|
||||
struct list pid_list;
|
||||
init_list(&pid_list, 0);
|
||||
int i;
|
||||
struct list_node *node = NULL;
|
||||
int size = sizeof(f->proctable) / sizeof(struct process*);
|
||||
for (i=0; i<size; i++) {
|
||||
if (f->proctable[i] != NULL) {
|
||||
for (node=f->proctable[i]->first; node!=NULL; node=node->next) {
|
||||
struct process *p = (struct process*)(node->data);
|
||||
if (!p->member && !process_exists(p->pid))
|
||||
add_elem(&pid_list, &p->pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (node=pid_list.first; node!=NULL; node=node->next) {
|
||||
pid_t * p = (pid_t *)(node->data);
|
||||
remove_process_from_family(f, *p);
|
||||
}
|
||||
flush_list(&pid_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// removes a process from the family by its pid
|
||||
void remove_process_from_family(struct process_family *f, pid_t pid)
|
||||
{
|
||||
struct list_node *node = locate_node(&(f->members), &pid);
|
||||
if (node != NULL) {
|
||||
// struct process *p = (struct process*)(node->data);
|
||||
// free(p->history);
|
||||
// p->history = NULL;
|
||||
delete_node(&(f->members), node);
|
||||
}
|
||||
unhash_process(f, pid);
|
||||
}
|
||||
|
||||
// free the heap memory used by a process family
|
||||
void cleanup_process_family(struct process_family *f)
|
||||
{
|
||||
int i;
|
||||
int size = sizeof(f->proctable) / sizeof(struct process*);
|
||||
for (i=0; i<size; i++) {
|
||||
if (f->proctable[i] != NULL) {
|
||||
//free() history for each process
|
||||
struct list_node *node = NULL;
|
||||
for (node=f->proctable[i]->first; node!=NULL; node=node->next) {
|
||||
// struct process *p = (struct process*)(node->data);
|
||||
// free(p->history);
|
||||
// p->history = NULL;
|
||||
}
|
||||
destroy_list(f->proctable[i]);
|
||||
free(f->proctable[i]);
|
||||
f->proctable[i] = NULL;
|
||||
}
|
||||
}
|
||||
flush_list(&(f->members));
|
||||
f->count = 0;
|
||||
f->father = 0;
|
||||
}
|
||||
|
||||
// look for a process by pid
|
||||
// search_pid : pid of the wanted process
|
||||
// return: pid of the found process, if it is found
|
||||
// 0, if it's not found
|
||||
// negative pid, if it is found but it's not possible to control it
|
||||
int look_for_process_by_pid(pid_t pid)
|
||||
{
|
||||
if (process_exists(pid))
|
||||
return (kill(pid,0)==0) ? pid : -pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// look for a process with a given name
|
||||
// process: the name of the wanted process. it can be an absolute path name to the executable file
|
||||
// or just the file name
|
||||
// return: pid of the found process, if it is found
|
||||
// 0, if it's not found
|
||||
// negative pid, if it is found but it's not possible to control it
|
||||
int look_for_process_by_name(const char *process_name)
|
||||
{
|
||||
//whether the variable process_name is the absolute path or not
|
||||
int is_absolute_path = process_name[0] == '/';
|
||||
//flag indicating if the a process with given name was found
|
||||
int found = 0;
|
||||
|
||||
//process iterator
|
||||
struct process_iterator iter;
|
||||
if (init_process_iterator(&iter) == -1)
|
||||
return -1;
|
||||
pid_t pid = 0;
|
||||
|
||||
printf("name\n");
|
||||
|
||||
while (read_next_process(&iter)==0) {
|
||||
pid = iter.current->pid;
|
||||
|
||||
int size = strlen(iter.current->command);
|
||||
|
||||
found = 0;
|
||||
if (is_absolute_path && strncmp(iter.current->command, process_name, size)==0 && size==strlen(process_name)) {
|
||||
//process found
|
||||
found = 1;
|
||||
}
|
||||
else {
|
||||
//process found
|
||||
if (strncmp(iter.current->command + size - strlen(process_name), process_name, strlen(process_name))==0) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (found==1) {
|
||||
if (kill(pid,SIGCONT)==0) {
|
||||
//process is ok!
|
||||
break;
|
||||
}
|
||||
else {
|
||||
//we don't have permission to send signal to that process
|
||||
//so, don't exit from the loop and look for another one with the same name
|
||||
found = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iter.dip != NULL)
|
||||
closedir(iter.dip);
|
||||
if (iter.current != NULL)
|
||||
free(iter.current);
|
||||
|
||||
if (found == 1) {
|
||||
//ok, the process was found
|
||||
return pid;
|
||||
}
|
||||
else if (found == 0) {
|
||||
//no process found
|
||||
return 0;
|
||||
}
|
||||
else if (found == -1) {
|
||||
//the process was found, but we haven't permission to control it
|
||||
return -pid;
|
||||
}
|
||||
//this MUST NOT happen
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,94 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a cpu limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2008, by: Angelo Marletta <marlonx80@hotmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PROCUTILS_H
|
||||
|
||||
#define __PROCUTILS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "process.h"
|
||||
|
||||
#define PIDHASH_SZ 1024
|
||||
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
|
||||
|
||||
// a hierarchy of processes
|
||||
struct process_family {
|
||||
//the (god)father of the process family
|
||||
pid_t father;
|
||||
//process list (father process is the first element)
|
||||
//elements are struct process
|
||||
struct list members;
|
||||
//non-members list
|
||||
//hashtable with all the processes (array of struct list of struct process)
|
||||
struct list *proctable[PIDHASH_SZ];
|
||||
//total process count
|
||||
int count;
|
||||
};
|
||||
|
||||
//TODO: use this object in proctable and delete member in struct process
|
||||
struct table_item {
|
||||
struct process *proc;
|
||||
//1 if the process is a member of the family
|
||||
int member;
|
||||
};
|
||||
|
||||
// object to enumerate running processes
|
||||
struct process_iterator {
|
||||
#ifdef __linux__
|
||||
DIR *dip;
|
||||
struct dirent *dit;
|
||||
#elif defined __APPLE__
|
||||
struct kinfo_proc *procList;
|
||||
int count;
|
||||
int c;
|
||||
#elif defined __hpux
|
||||
int count;
|
||||
#endif
|
||||
struct process *current;
|
||||
};
|
||||
|
||||
// searches for all the processes derived from father and stores them
|
||||
// in the process family struct
|
||||
int create_process_family(struct process_family *f, pid_t father);
|
||||
|
||||
// checks if there are new processes born in the specified family
|
||||
// if any they are added to the members list
|
||||
// the number of new born processes is returned
|
||||
int update_process_family(struct process_family *f);
|
||||
|
||||
// removes a process from the family by its pid
|
||||
void remove_process_from_family(struct process_family *f, pid_t pid);
|
||||
|
||||
// free the heap memory used by a process family
|
||||
void cleanup_process_family(struct process_family *f);
|
||||
|
||||
// searches a process given the name of the executable file, or its absolute path
|
||||
// returns the pid, or 0 if it's not found
|
||||
int look_for_process_by_name(const char *process_name);
|
||||
|
||||
// searches a process given its pid
|
||||
// returns the pid, or 0 if it's not found
|
||||
int look_for_process_by_pid(pid_t pid);
|
||||
|
||||
#endif
|
@ -1,24 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=cpulimit
|
||||
PKG_VERSION:=0.2
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/cpulimit
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=cpulimit
|
||||
URL:=https://github.com/opsengine/cpulimit.git
|
||||
endef
|
||||
|
||||
define Package/cpulimit/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/cpulimit $(1)/usr/bin/
|
||||
endef
|
||||
|
||||
|
||||
$(eval $(call BuildPackage,cpulimit))
|
@ -1,49 +0,0 @@
|
||||
BINDIR ?= $(PREFIX)/bin
|
||||
BIN_TARGET = cpulimit
|
||||
CC ?= gcc
|
||||
CFLAGS ?= -O2 -Wall -g -D_GNU_SOURCE
|
||||
HELP2MAN := $(shell which help2man)
|
||||
LIBS = list.o process_iterator.o process_group.o
|
||||
MAN_NAME := "CPU Utilization Limiter"
|
||||
MAN_SEC := 1
|
||||
MAN_SRC := $(shell git remote get-url origin)
|
||||
MAN_TARGET = $(BIN_TARGET).$(MAN_SEC)
|
||||
PREFIX ?= /usr/local
|
||||
STRIP := $(shell which strip)
|
||||
SUDO := $(shell which sudo)
|
||||
TARGETS = $(BIN_TARGET) $(MAN_TARGET)
|
||||
UNAME := $(shell uname)
|
||||
|
||||
ifeq ($(UNAME), FreeBSD)
|
||||
LIBS += -lkvm
|
||||
endif
|
||||
|
||||
all:: $(TARGETS) $(LIBS)
|
||||
|
||||
static:
|
||||
$(MAKE) all CFLAGS="$(CFLAGS) --static"
|
||||
|
||||
strip: $(BIN_TARGET)
|
||||
$(STRIP) $<
|
||||
|
||||
install: $(TARGETS)
|
||||
$(SUDO) install $^ $(BINDIR)
|
||||
|
||||
$(BIN_TARGET): cpulimit.c $(LIBS)
|
||||
$(CC) -o cpulimit cpulimit.c $(LIBS) $(CFLAGS)
|
||||
|
||||
$(MAN_TARGET): $(BIN_TARGET) $(HELP2MAN)
|
||||
$(HELP2MAN) -n $(MAN_NAME) -s $(MAN_SEC) -s $(MAN_SRC) -N ./$< > $@
|
||||
|
||||
process_iterator.o: process_iterator.c process_iterator.h
|
||||
$(CC) -c process_iterator.c $(CFLAGS)
|
||||
|
||||
list.o: list.c list.h
|
||||
$(CC) -c list.c $(CFLAGS)
|
||||
|
||||
process_group.o: process_group.c process_group.h process_iterator.o list.o
|
||||
$(CC) -c process_group.c $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o $(TARGETS)
|
||||
|
@ -1,560 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**************************************************************
|
||||
*
|
||||
* This is a simple program to limit the cpu usage of a process
|
||||
* If you modify this code, send me a copy please
|
||||
*
|
||||
* Get the latest version at: http://github.com/opsengine/cpulimit
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef __sun__
|
||||
#endif
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if defined(__APPLE__) || defined(__FREEBSD__)
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
#include "process_group.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifdef HAVE_SYS_SYSINFO_H
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "memrchr.c"
|
||||
#endif
|
||||
|
||||
//some useful macro
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
//control time slot in microseconds
|
||||
//each slot is splitted in a working slice and a sleeping slice
|
||||
//TODO: make it adaptive, based on the actual system load
|
||||
#define TIME_SLOT 100000
|
||||
|
||||
#define MAX_PRIORITY -10
|
||||
|
||||
#define VERSION "0.3"
|
||||
|
||||
/* GLOBAL VARIABLES */
|
||||
|
||||
//the "family"
|
||||
struct process_group pgroup;
|
||||
//pid of cpulimit
|
||||
pid_t cpulimit_pid;
|
||||
//name of this program (maybe cpulimit...)
|
||||
char *program_name;
|
||||
|
||||
//number of cpu
|
||||
int NCPU;
|
||||
|
||||
/* CONFIGURATION VARIABLES */
|
||||
|
||||
//verbose mode
|
||||
int verbose = 0;
|
||||
//lazy mode (exits if there is no process)
|
||||
int lazy = 0;
|
||||
|
||||
//SIGINT and SIGTERM signal handler
|
||||
static void quit(int sig) {
|
||||
//let all the processes continue if stopped
|
||||
struct list_node *node = NULL;
|
||||
if (pgroup.proclist != NULL) {
|
||||
for (node = pgroup.proclist->first; node != NULL; node = node->next) {
|
||||
struct process *p = (struct process *)(node->data);
|
||||
kill(p->pid, SIGCONT);
|
||||
}
|
||||
close_process_group(&pgroup);
|
||||
}
|
||||
//fix ^C little problem
|
||||
printf("\r");
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//return t1-t2 in microseconds (no overflow checks, so better watch out!)
|
||||
static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2) {
|
||||
return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec);
|
||||
}
|
||||
|
||||
static void print_usage(FILE *stream, int exit_code) {
|
||||
fprintf(stream, "Usage: %s [OPTIONS...] TARGET\n", program_name);
|
||||
fprintf(stream, " OPTIONS\n");
|
||||
fprintf(stream, " -l, --limit=N percentage of cpu allowed from 0 to %d (required)\n", 100*NCPU);
|
||||
fprintf(stream, " -v, --verbose show control statistics\n");
|
||||
fprintf(stream, " -V, --version show program version number\n");
|
||||
fprintf(stream, " -z, --lazy exit if there is no target process, or if it dies\n");
|
||||
fprintf(stream, " -i, --include-children limit also the children processes\n");
|
||||
fprintf(stream, " -m, --minimum-limited-cpu=M minimum percentage of cpu of target processes\n");
|
||||
fprintf(stream, " -h, --help display this help and exit\n");
|
||||
fprintf(stream, " TARGET must be exactly one of these:\n");
|
||||
fprintf(stream, " -p, --pid=N pid of the process (implies -z)\n");
|
||||
fprintf(stream, " -e, --exe=FILE name of the executable program file or path name\n");
|
||||
fprintf(stream, " COMMAND [ARGS] run this command and limit it (implies -z)\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static void print_version(FILE *stream, int exit_code) {
|
||||
fprintf(stream, "%s\n", VERSION);
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static void increase_priority() {
|
||||
//find the best available nice value
|
||||
int old_priority = getpriority(PRIO_PROCESS, 0);
|
||||
int priority = old_priority;
|
||||
while (setpriority(PRIO_PROCESS, 0, priority-1) == 0 && priority>MAX_PRIORITY) {
|
||||
priority--;
|
||||
}
|
||||
if (priority != old_priority) {
|
||||
if (verbose) {
|
||||
printf("Priority changed to %d\n", priority);
|
||||
}
|
||||
} else {
|
||||
if (verbose) {
|
||||
printf("Warning: Cannot change priority. Run as root or renice for best results.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the number of CPUs */
|
||||
static int get_ncpu() {
|
||||
int ncpu;
|
||||
#ifdef _SC_NPROCESSORS_ONLN
|
||||
ncpu = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#elif defined __APPLE__
|
||||
int mib[2] = {CTL_HW, HW_NCPU};
|
||||
size_t len = sizeof(ncpu);
|
||||
sysctl(mib, 2, &ncpu, &len, NULL, 0);
|
||||
#elif defined _GNU_SOURCE
|
||||
ncpu = get_nprocs();
|
||||
#else
|
||||
ncpu = -1;
|
||||
#endif
|
||||
return ncpu;
|
||||
}
|
||||
|
||||
int get_pid_max() {
|
||||
#ifdef __linux__
|
||||
//read /proc/sys/kernel/pid_max
|
||||
static char buffer[1024];
|
||||
FILE *fd = fopen("/proc/sys/kernel/pid_max", "r");
|
||||
if (fd==NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (fgets(buffer, sizeof(buffer), fd)==NULL) {
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
fclose(fd);
|
||||
return atoi(buffer);
|
||||
#else
|
||||
return 99998;
|
||||
#endif
|
||||
}
|
||||
|
||||
void limit_process(pid_t pid, double limit, int include_children, float minimum_cpu_usage) {
|
||||
//slice of the slot in which the process is allowed to run
|
||||
struct timespec twork;
|
||||
//slice of the slot in which the process is stopped
|
||||
struct timespec tsleep;
|
||||
//when the last twork has started
|
||||
struct timeval startwork;
|
||||
//when the last twork has finished
|
||||
struct timeval endwork;
|
||||
//initialization
|
||||
memset(&twork, 0, sizeof(struct timespec));
|
||||
memset(&tsleep, 0, sizeof(struct timespec));
|
||||
memset(&startwork, 0, sizeof(struct timeval));
|
||||
memset(&endwork, 0, sizeof(struct timeval));
|
||||
//last working time in microseconds
|
||||
unsigned long workingtime = 0;
|
||||
//generic list item
|
||||
struct list_node *node;
|
||||
//counter
|
||||
int c = 0;
|
||||
|
||||
//get a better priority
|
||||
increase_priority();
|
||||
|
||||
//build the family
|
||||
init_process_group(&pgroup, pid, include_children);
|
||||
|
||||
if (verbose) {
|
||||
printf("Members in the process group owned by %d: %d\n", pgroup.target_pid, pgroup.proclist->count);
|
||||
}
|
||||
|
||||
//rate at which we are keeping active the processes (range 0-1)
|
||||
//1 means that the process are using all the twork slice
|
||||
double workingrate = -1;
|
||||
while (1) {
|
||||
update_process_group(&pgroup);
|
||||
|
||||
if (pgroup.proclist->count==0) {
|
||||
if (verbose) {
|
||||
printf("No more processes.\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//total cpu actual usage (range 0-1)
|
||||
//1 means that the processes are using 100% cpu
|
||||
double pcpu = -1;
|
||||
|
||||
//estimate how much the controlled processes are using the cpu in the working interval
|
||||
for (node = pgroup.proclist->first; node != NULL; node = node->next) {
|
||||
struct process *proc = (struct process *)(node->data);
|
||||
if (proc->cpu_usage < 0) {
|
||||
continue;
|
||||
}
|
||||
if (pcpu < 0) {
|
||||
pcpu = 0;
|
||||
}
|
||||
pcpu += proc->cpu_usage;
|
||||
}
|
||||
|
||||
//adjust work and sleep time slices
|
||||
if (pcpu < 0) {
|
||||
//it's the 1st cycle, initialize workingrate
|
||||
pcpu = limit;
|
||||
workingrate = limit;
|
||||
twork.tv_nsec = TIME_SLOT * limit * 1000;
|
||||
} else {
|
||||
//adjust workingrate
|
||||
workingrate = MIN(workingrate / pcpu * limit, 1);
|
||||
twork.tv_nsec = TIME_SLOT * 1000 * workingrate;
|
||||
}
|
||||
tsleep.tv_nsec = TIME_SLOT * 1000 - twork.tv_nsec;
|
||||
|
||||
if (verbose) {
|
||||
if (c%200==0) {
|
||||
printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n");
|
||||
}
|
||||
if (c%10==0 && c>0) {
|
||||
printf("%0.2lf%%\t%6ld us\t%6ld us\t%0.2lf%%\n", pcpu*100, twork.tv_nsec/1000, tsleep.tv_nsec/1000, workingrate*100);
|
||||
}
|
||||
}
|
||||
|
||||
//resume processes
|
||||
node = pgroup.proclist->first;
|
||||
while (node != NULL) {
|
||||
struct list_node *next_node = node->next;
|
||||
struct process *proc = (struct process *)(node->data);
|
||||
if (kill(proc->pid,SIGCONT) != 0) {
|
||||
//process is dead, remove it from family
|
||||
if (verbose) {
|
||||
fprintf(stderr, "SIGCONT failed. Process %d dead!\n", proc->pid);
|
||||
}
|
||||
//remove process from group
|
||||
delete_node(pgroup.proclist, node);
|
||||
remove_process(&pgroup, proc->pid);
|
||||
}
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
//now processes are free to run (same working slice for all)
|
||||
gettimeofday(&startwork, NULL);
|
||||
nanosleep(&twork, NULL);
|
||||
gettimeofday(&endwork, NULL);
|
||||
workingtime = timediff(&endwork, &startwork);
|
||||
|
||||
long delay = workingtime - twork.tv_nsec/1000;
|
||||
if (c>0 && delay>10000) {
|
||||
//delay is too much! signal to user?
|
||||
//fprintf(stderr, "%d %ld us\n", c, delay);
|
||||
}
|
||||
|
||||
if (tsleep.tv_nsec>0) {
|
||||
//stop processes only if tsleep>0
|
||||
node = pgroup.proclist->first;
|
||||
while (node != NULL) {
|
||||
struct list_node *next_node = node->next;
|
||||
struct process *proc = (struct process *)(node->data);
|
||||
if (proc->cpu_usage > minimum_cpu_usage && kill(proc->pid,SIGSTOP)!=0) {
|
||||
//process is dead, remove it from family
|
||||
if (verbose) {
|
||||
fprintf(stderr, "SIGSTOP failed. Process %d dead!\n", proc->pid);
|
||||
}
|
||||
//remove process from group
|
||||
delete_node(pgroup.proclist, node);
|
||||
remove_process(&pgroup, proc->pid);
|
||||
}
|
||||
node = next_node;
|
||||
}
|
||||
//now the processes are sleeping
|
||||
nanosleep(&tsleep,NULL);
|
||||
}
|
||||
c++;
|
||||
}
|
||||
close_process_group(&pgroup);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
//argument variables
|
||||
const char *exe = NULL;
|
||||
int perclimit = 0;
|
||||
int exe_ok = 0;
|
||||
int pid_ok = 0;
|
||||
int limit_ok = 0;
|
||||
pid_t pid = 0;
|
||||
float minimum_cpu_usage=0;
|
||||
int include_children = 0;
|
||||
|
||||
//get program name
|
||||
#ifdef __sun__
|
||||
char *p = strrchr(argv[0], (unsigned int)'/');
|
||||
#else
|
||||
char *p = (char *)memrchr(argv[0], (unsigned int)'/', strlen(argv[0]));
|
||||
#endif
|
||||
program_name = p==NULL ? argv[0] : (p+1);
|
||||
//get current pid
|
||||
cpulimit_pid = getpid();
|
||||
//get cpu count
|
||||
NCPU = get_ncpu();
|
||||
|
||||
//parse arguments
|
||||
int next_option;
|
||||
int option_index = 0;
|
||||
//A string listing valid short options letters
|
||||
const char *short_options = "+p:e:l:vVzim:h";
|
||||
//An array describing valid long options
|
||||
const struct option long_options[] = {
|
||||
{ "pid", required_argument, NULL, 'p' },
|
||||
{ "exe", required_argument, NULL, 'e' },
|
||||
{ "limit", required_argument, NULL, 'l' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "lazy", no_argument, NULL, 'z' },
|
||||
{ "include-children", no_argument, NULL, 'i' },
|
||||
{ "minimum-limited-cpu", no_argument, NULL, 'm' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
do {
|
||||
next_option = getopt_long(argc, argv, short_options,long_options, &option_index);
|
||||
switch (next_option) {
|
||||
case 'p':
|
||||
pid = atoi(optarg);
|
||||
pid_ok = 1;
|
||||
break;
|
||||
case 'e':
|
||||
exe = optarg;
|
||||
exe_ok = 1;
|
||||
break;
|
||||
case 'l':
|
||||
perclimit = atoi(optarg);
|
||||
limit_ok = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'V':
|
||||
print_version(stdout, 0);
|
||||
break;
|
||||
case 'z':
|
||||
lazy = 1;
|
||||
break;
|
||||
case 'i':
|
||||
include_children = 1;
|
||||
break;
|
||||
case 'm':
|
||||
minimum_cpu_usage = atof(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(stdout, 1);
|
||||
break;
|
||||
case '?':
|
||||
print_usage(stderr, 1);
|
||||
break;
|
||||
case -1:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
} while (next_option != -1);
|
||||
|
||||
if (pid_ok && (pid <= 1 || pid >= get_pid_max())) {
|
||||
fprintf(stderr,"Error: Invalid value for argument PID\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
if (pid != 0) {
|
||||
lazy = 1;
|
||||
}
|
||||
|
||||
if (!limit_ok) {
|
||||
fprintf(stderr,"Error: You must specify a cpu limit percentage\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
double limit = perclimit / 100.0;
|
||||
if (limit<0 || limit >NCPU) {
|
||||
fprintf(stderr,"Error: limit must be in the range 0-%d00\n", NCPU);
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int command_mode = optind < argc;
|
||||
if (exe_ok + pid_ok + command_mode == 0) {
|
||||
fprintf(stderr,"Error: You must specify one target process, either by name, pid, or command line\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (exe_ok + pid_ok + command_mode > 1) {
|
||||
fprintf(stderr,"Error: You must specify exactly one target process, either by name, pid, or command line\n");
|
||||
print_usage(stderr, 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//all arguments are ok!
|
||||
signal(SIGINT, quit);
|
||||
signal(SIGTERM, quit);
|
||||
|
||||
//print the number of available cpu
|
||||
if (verbose) {
|
||||
printf("%d cpu detected\n", NCPU);
|
||||
}
|
||||
|
||||
if (command_mode) {
|
||||
int i;
|
||||
//executable file
|
||||
const char *cmd = argv[optind];
|
||||
//command line arguments
|
||||
char **cmd_args = (char **)malloc((argc-optind + 1) * sizeof(char *));
|
||||
if (cmd_args==NULL) {
|
||||
exit(2);
|
||||
}
|
||||
for (i=0; i<argc-optind; i++) {
|
||||
cmd_args[i] = argv[i+optind];
|
||||
}
|
||||
cmd_args[i] = NULL;
|
||||
|
||||
if (verbose) {
|
||||
printf("Running command: '%s", cmd);
|
||||
for (i=1; i<argc-optind; i++) {
|
||||
printf(" %s", cmd_args[i]);
|
||||
}
|
||||
printf("'\n");
|
||||
}
|
||||
|
||||
int child = fork();
|
||||
if (child < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (child == 0) {
|
||||
//target process code
|
||||
int ret = execvp(cmd, cmd_args);
|
||||
//if we are here there was an error, show it
|
||||
perror("Error");
|
||||
exit(ret);
|
||||
} else {
|
||||
//parent code
|
||||
free(cmd_args);
|
||||
int limiter = fork();
|
||||
if (limiter < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (limiter > 0) {
|
||||
//parent
|
||||
int status_process;
|
||||
int status_limiter;
|
||||
waitpid(child, &status_process, 0);
|
||||
waitpid(limiter, &status_limiter, 0);
|
||||
if (WIFEXITED(status_process)) {
|
||||
if (verbose) {
|
||||
printf("Process %d terminated with exit status %d\n", child, (int)WEXITSTATUS(status_process));
|
||||
}
|
||||
exit(WEXITSTATUS(status_process));
|
||||
}
|
||||
printf("Process %d terminated abnormally\n", child);
|
||||
exit(status_process);
|
||||
} else {
|
||||
//limiter code
|
||||
if (verbose) {
|
||||
printf("Limiting process %d\n",child);
|
||||
}
|
||||
limit_process(child, limit, include_children, minimum_cpu_usage);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
//look for the target process..or wait for it
|
||||
pid_t ret = 0;
|
||||
if (pid_ok) {
|
||||
//search by pid
|
||||
ret = find_process_by_pid(pid);
|
||||
if (ret == 0) {
|
||||
printf("No process found\n");
|
||||
} else if (ret < 0) {
|
||||
printf("Process found but you aren't allowed to control it\n");
|
||||
}
|
||||
} else {
|
||||
//search by file or path name
|
||||
ret = find_process_by_name(exe);
|
||||
if (ret == 0) {
|
||||
printf("No process found\n");
|
||||
} else if (ret < 0) {
|
||||
printf("Process found but you aren't allowed to control it\n");
|
||||
} else {
|
||||
pid = ret;
|
||||
}
|
||||
}
|
||||
if (ret > 0) {
|
||||
if (ret == cpulimit_pid) {
|
||||
printf("Target process %d is cpulimit itself! Aborting because it makes no sense\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
printf("Process %d found\n", pid);
|
||||
//control
|
||||
limit_process(pid, limit, include_children, minimum_cpu_usage);
|
||||
}
|
||||
if (lazy) {
|
||||
break;
|
||||
}
|
||||
sleep(2);
|
||||
};
|
||||
|
||||
exit(0);
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#define EMPTYLIST NULL
|
||||
|
||||
void init_list(struct list *l,int keysize) {
|
||||
l->first=l->last=NULL;
|
||||
l->keysize=keysize;
|
||||
l->count=0;
|
||||
}
|
||||
|
||||
struct list_node *add_elem(struct list *l,void *elem) {
|
||||
struct list_node *newnode=(struct list_node *)malloc(sizeof(struct list_node));
|
||||
newnode->data=elem;
|
||||
newnode->previous=l->last;
|
||||
newnode->next=NULL;
|
||||
if (l->count==0) {
|
||||
l->first=l->last=newnode;
|
||||
} else {
|
||||
l->last->next=newnode;
|
||||
l->last=newnode;
|
||||
}
|
||||
l->count++;
|
||||
return newnode;
|
||||
}
|
||||
|
||||
void delete_node(struct list *l,struct list_node *node) {
|
||||
if (l->count==1) {
|
||||
l->first=l->last=NULL;
|
||||
} else if (node==l->first) {
|
||||
node->next->previous=NULL;
|
||||
l->first=node->next;
|
||||
} else if (node==l->last) {
|
||||
node->previous->next=NULL;
|
||||
l->last=node->previous;
|
||||
} else {
|
||||
node->previous->next=node->next;
|
||||
node->next->previous=node->previous;
|
||||
}
|
||||
l->count--;
|
||||
free(node);
|
||||
}
|
||||
|
||||
void destroy_node(struct list *l,struct list_node *node) {
|
||||
free(node->data);
|
||||
node->data=NULL;
|
||||
delete_node(l,node);
|
||||
}
|
||||
|
||||
int is_empty_list(struct list *l) {
|
||||
return (l->count==0?TRUE:FALSE);
|
||||
}
|
||||
|
||||
int get_list_count(struct list *l) {
|
||||
return l->count;
|
||||
}
|
||||
|
||||
void *first_elem(struct list *l) {
|
||||
return l->first->data;
|
||||
}
|
||||
|
||||
struct list_node *first_node(struct list *l) {
|
||||
return l->first;
|
||||
}
|
||||
|
||||
void *last_elem(struct list *l) {
|
||||
return l->last->data;
|
||||
}
|
||||
|
||||
struct list_node *last_node(struct list *l) {
|
||||
return l->last;
|
||||
}
|
||||
|
||||
struct list_node *xlocate_node(struct list *l,void *elem,int offset,int length) {
|
||||
struct list_node *tmp;
|
||||
tmp=l->first;
|
||||
while (tmp!=NULL) {
|
||||
if (!memcmp((char *)tmp->data+offset,elem,length==0?l->keysize:length)) {
|
||||
return (tmp);
|
||||
}
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return EMPTYLIST;
|
||||
}
|
||||
|
||||
struct list_node *locate_node(struct list *l,void *elem) {
|
||||
return (xlocate_node(l,elem,0,0));
|
||||
}
|
||||
|
||||
void *xlocate_elem(struct list *l,void *elem,int offset,int length) {
|
||||
struct list_node *node=xlocate_node(l,elem,offset,length);
|
||||
return (node==NULL?NULL:node->data);
|
||||
}
|
||||
|
||||
void *locate_elem(struct list *l,void *elem) {
|
||||
return (xlocate_elem(l,elem,0,0));
|
||||
}
|
||||
|
||||
void clear_list(struct list *l) {
|
||||
while (l->first!=EMPTYLIST) {
|
||||
struct list_node *tmp;
|
||||
tmp=l->first;
|
||||
l->first=l->first->next;
|
||||
free(tmp);
|
||||
tmp=NULL;
|
||||
}
|
||||
l->last=EMPTYLIST;
|
||||
l->count=0;
|
||||
}
|
||||
|
||||
void destroy_list(struct list *l) {
|
||||
while (l->first!=EMPTYLIST) {
|
||||
struct list_node *tmp;
|
||||
tmp=l->first;
|
||||
l->first=l->first->next;
|
||||
free(tmp->data);
|
||||
tmp->data=NULL;
|
||||
free(tmp);
|
||||
tmp=NULL;
|
||||
}
|
||||
l->last=EMPTYLIST;
|
||||
l->count=0;
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __LIST__
|
||||
|
||||
#define __LIST__
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
struct list_node {
|
||||
//pointer to the content of the node
|
||||
void *data;
|
||||
//pointer to previous node
|
||||
struct list_node *previous;
|
||||
//pointer to next node
|
||||
struct list_node *next;
|
||||
};
|
||||
|
||||
struct list {
|
||||
//first node
|
||||
struct list_node *first;
|
||||
//last node
|
||||
struct list_node *last;
|
||||
//size of the search key in bytes
|
||||
int keysize;
|
||||
//element count
|
||||
int count;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize a list, with a specified key size
|
||||
*/
|
||||
void init_list(struct list *l,int keysize);
|
||||
|
||||
/*
|
||||
* Add a new element at the end of the list
|
||||
* return the pointer to the new node
|
||||
*/
|
||||
struct list_node *add_elem(struct list *l,void *elem);
|
||||
|
||||
/*
|
||||
* Delete a node
|
||||
*/
|
||||
void delete_node(struct list *l,struct list_node *node);
|
||||
|
||||
/*
|
||||
* Delete a node from the list, even the content pointed by it
|
||||
* Use only when the content is a dynamically allocated pointer
|
||||
*/
|
||||
void destroy_node(struct list *l,struct list_node *node);
|
||||
|
||||
/*
|
||||
* Check whether a list is empty or not
|
||||
*/
|
||||
int is_empty_list(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the element count of the list
|
||||
*/
|
||||
int get_list_count(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the first element (content of the node) from the list
|
||||
*/
|
||||
void *first_elem(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the first node from the list
|
||||
*/
|
||||
struct list_node *first_node(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the last element (content of the node) from the list
|
||||
*/
|
||||
void *last_elem(struct list *l);
|
||||
|
||||
/*
|
||||
* Return the last node from the list
|
||||
*/
|
||||
struct list_node *last_node(struct list *l);
|
||||
|
||||
/*
|
||||
* Search an element of the list by content
|
||||
* the comparison is done from the specified offset and for a specified length
|
||||
* if offset=0, the comparison starts from the address pointed by data
|
||||
* if length=0, default keysize is used for length
|
||||
* if the element is found, return the node address
|
||||
* else return NULL
|
||||
*/
|
||||
struct list_node *xlocate_node(struct list *l,void *elem,int offset,int length);
|
||||
|
||||
/*
|
||||
* The same of xlocate_node(), but return the content of the node
|
||||
*/
|
||||
void *xlocate_elem(struct list *l,void *elem,int offset,int length);
|
||||
|
||||
/*
|
||||
* The same of calling xlocate_node() with offset=0 and length=0
|
||||
*/
|
||||
struct list_node *locate_node(struct list *l,void *elem);
|
||||
|
||||
/*
|
||||
* The same of locate_node, but return the content of the node
|
||||
*/
|
||||
void *locate_elem(struct list *l,void *elem);
|
||||
|
||||
/*
|
||||
* Delete all the elements in the list
|
||||
*/
|
||||
void clear_list(struct list *l);
|
||||
|
||||
/*
|
||||
* Delete every element in the list, and free the memory pointed by all the node data
|
||||
*/
|
||||
void destroy_list(struct list *l);
|
||||
|
||||
#endif
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* Reverse memchr()
|
||||
* Find the last occurrence of 'c' in the buffer 's' of size 'n'.
|
||||
*/
|
||||
void *
|
||||
memrchr(s, c, n)
|
||||
const void *s;
|
||||
int c;
|
||||
size_t n;
|
||||
{
|
||||
if (n != 0) {
|
||||
const unsigned char *cp;
|
||||
cp = (unsigned char *)s + n;
|
||||
do {
|
||||
if (*(--cp) == (unsigned char)c) {
|
||||
return ((void *)cp);
|
||||
}
|
||||
} while (--n != 0);
|
||||
}
|
||||
return ((void *)0);
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined(__APPLE__) || defined(__FREEBSD__)
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __sun__
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
#include "process_iterator.h"
|
||||
#include "process_group.h"
|
||||
#include "list.h"
|
||||
|
||||
// look for a process by pid
|
||||
// search_pid : pid of the wanted process
|
||||
// return: pid of the found process, if successful
|
||||
// negative pid, if the process does not exist or if the signal fails
|
||||
int find_process_by_pid(pid_t pid) {
|
||||
return (kill(pid,0)==0) ? pid : -pid;
|
||||
}
|
||||
|
||||
// look for a process with a given name
|
||||
// process: the name of the wanted process. it can be an absolute path name to the executable file
|
||||
// or just the file name
|
||||
// return: pid of the found process, if it is found
|
||||
// 0, if it's not found
|
||||
// negative pid, if it is found but it's not possible to control it
|
||||
int find_process_by_name(const char *process_name) {
|
||||
//pid of the target process
|
||||
pid_t pid = -1;
|
||||
|
||||
//process iterator
|
||||
struct process_iterator it;
|
||||
struct process proc;
|
||||
struct process_filter filter;
|
||||
filter.pid = 0;
|
||||
filter.include_children = 0;
|
||||
init_process_iterator(&it, &filter);
|
||||
while (get_next_process(&it, &proc) != -1) {
|
||||
//process found
|
||||
if (strncmp(basename(proc.command), process_name, strlen(process_name))==0 && kill(pid,SIGCONT)==0) {
|
||||
//process is ok!
|
||||
pid = proc.pid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (close_process_iterator(&it) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
if (pid >= 0) {
|
||||
//ok, the process was found
|
||||
return pid;
|
||||
} else {
|
||||
//process not found
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int init_process_group(struct process_group *pgroup, int target_pid, int include_children) {
|
||||
//hashtable initialization
|
||||
memset(&pgroup->proctable, 0, sizeof(pgroup->proctable));
|
||||
pgroup->target_pid = target_pid;
|
||||
pgroup->include_children = include_children;
|
||||
pgroup->proclist = (struct list *)malloc(sizeof(struct list));
|
||||
init_list(pgroup->proclist, 4);
|
||||
memset(&pgroup->last_update, 0, sizeof(pgroup->last_update));
|
||||
update_process_group(pgroup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int close_process_group(struct process_group *pgroup) {
|
||||
int i;
|
||||
int size = sizeof(pgroup->proctable) / sizeof(struct process *);
|
||||
for (i=0; i<size; i++) {
|
||||
if (pgroup->proctable[i] != NULL) {
|
||||
//free() history for each process
|
||||
destroy_list(pgroup->proctable[i]);
|
||||
free(pgroup->proctable[i]);
|
||||
pgroup->proctable[i] = NULL;
|
||||
}
|
||||
}
|
||||
clear_list(pgroup->proclist);
|
||||
free(pgroup->proclist);
|
||||
pgroup->proclist = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void remove_terminated_processes(struct process_group *pgroup) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
//return t1-t2 in microseconds (no overflow checks, so better watch out!)
|
||||
static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2) {
|
||||
return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec);
|
||||
}
|
||||
|
||||
//parameter in range 0-1
|
||||
#define ALFA 0.08
|
||||
#define MIN_DT 20
|
||||
|
||||
void update_process_group(struct process_group *pgroup) {
|
||||
struct process_iterator it;
|
||||
struct process tmp_process;
|
||||
struct process_filter filter;
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
//time elapsed from previous sample (in ms)
|
||||
long dt = timediff(&now, &pgroup->last_update) / 1000;
|
||||
filter.pid = pgroup->target_pid;
|
||||
filter.include_children = pgroup->include_children;
|
||||
init_process_iterator(&it, &filter);
|
||||
clear_list(pgroup->proclist);
|
||||
init_list(pgroup->proclist, 4);
|
||||
|
||||
while (get_next_process(&it, &tmp_process) != -1) {
|
||||
// struct timeval t;
|
||||
// gettimeofday(&t, NULL);
|
||||
// printf("T=%ld.%ld PID=%d PPID=%d START=%d CPUTIME=%d\n", t.tv_sec, t.tv_usec, tmp_process.pid, tmp_process.ppid, tmp_process.starttime, tmp_process.cputime);
|
||||
int hashkey = pid_hashfn(tmp_process.pid);
|
||||
if (pgroup->proctable[hashkey] == NULL) {
|
||||
//empty bucket
|
||||
pgroup->proctable[hashkey] = malloc(sizeof(struct list));
|
||||
struct process *new_process = malloc(sizeof(struct process));
|
||||
tmp_process.cpu_usage = -1;
|
||||
memcpy(new_process, &tmp_process, sizeof(struct process));
|
||||
init_list(pgroup->proctable[hashkey], 4);
|
||||
add_elem(pgroup->proctable[hashkey], new_process);
|
||||
add_elem(pgroup->proclist, new_process);
|
||||
} else {
|
||||
//existing bucket
|
||||
struct process *p = (struct process *)locate_elem(pgroup->proctable[hashkey], &tmp_process);
|
||||
if (p == NULL) {
|
||||
//process is new. add it
|
||||
struct process *new_process = malloc(sizeof(struct process));
|
||||
tmp_process.cpu_usage = -1;
|
||||
memcpy(new_process, &tmp_process, sizeof(struct process));
|
||||
add_elem(pgroup->proctable[hashkey], new_process);
|
||||
add_elem(pgroup->proclist, new_process);
|
||||
} else {
|
||||
assert(tmp_process.pid == p->pid);
|
||||
assert(tmp_process.starttime == p->starttime);
|
||||
add_elem(pgroup->proclist, p);
|
||||
if (dt < MIN_DT) {
|
||||
continue;
|
||||
}
|
||||
//process exists. update CPU usage
|
||||
double sample = 1.0 * (tmp_process.cputime - p->cputime) / dt;
|
||||
if (p->cpu_usage == -1) {
|
||||
//initialization
|
||||
p->cpu_usage = sample;
|
||||
} else {
|
||||
//usage adjustment
|
||||
p->cpu_usage = (1.0-ALFA) * p->cpu_usage + ALFA * sample;
|
||||
}
|
||||
p->cputime = tmp_process.cputime;
|
||||
}
|
||||
}
|
||||
}
|
||||
close_process_iterator(&it);
|
||||
if (dt < MIN_DT) {
|
||||
return;
|
||||
}
|
||||
pgroup->last_update = now;
|
||||
}
|
||||
|
||||
int remove_process(struct process_group *pgroup, int pid) {
|
||||
int hashkey = pid_hashfn(pid);
|
||||
if (pgroup->proctable[hashkey] == NULL) {
|
||||
return 1; //nothing to delete
|
||||
}
|
||||
struct list_node *node = (struct list_node *)locate_node(pgroup->proctable[hashkey], &pid);
|
||||
if (node == NULL) {
|
||||
return 2;
|
||||
}
|
||||
delete_node(pgroup->proctable[hashkey], node);
|
||||
return 0;
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PROCESS_GROUP_H
|
||||
|
||||
#define __PROCESS_GROUP_H
|
||||
|
||||
#include "process_iterator.h"
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#define PIDHASH_SZ 1024
|
||||
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
|
||||
|
||||
struct process_group {
|
||||
//hashtable with all the processes (array of struct list of struct process)
|
||||
struct list *proctable[PIDHASH_SZ];
|
||||
struct list *proclist;
|
||||
pid_t target_pid;
|
||||
int include_children;
|
||||
struct timeval last_update;
|
||||
};
|
||||
|
||||
int init_process_group(struct process_group *pgroup, int target_pid, int include_children);
|
||||
|
||||
void update_process_group(struct process_group *pgroup);
|
||||
|
||||
int close_process_group(struct process_group *pgroup);
|
||||
|
||||
int find_process_by_pid(pid_t pid);
|
||||
|
||||
int find_process_by_name(const char *process_name);
|
||||
|
||||
int remove_process(struct process_group *pgroup, int pid);
|
||||
|
||||
#endif
|
@ -1,55 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __sun__
|
||||
#include <procfs.h>
|
||||
#elif !defined __APPLE__
|
||||
#include <sys/procfs.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include "process_iterator.h"
|
||||
|
||||
//See this link to port to other systems: http://www.steve.org.uk/Reference/Unix/faq_8.html#SEC85
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include "process_iterator_linux.c"
|
||||
|
||||
#elif defined __FreeBSD__
|
||||
|
||||
#include "process_iterator_freebsd.c"
|
||||
|
||||
#elif defined __APPLE__
|
||||
|
||||
#include "process_iterator_apple.c"
|
||||
|
||||
#elif defined __sun__
|
||||
|
||||
#include "process_iterator_solaris.c"
|
||||
|
||||
#else
|
||||
|
||||
#error Platform not supported
|
||||
|
||||
#endif
|
@ -1,97 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PROCESS_ITERATOR_H
|
||||
|
||||
#define __PROCESS_ITERATOR_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
|
||||
//USER_HZ detection, from openssl code
|
||||
#ifndef HZ
|
||||
#if defined(_SC_CLK_TCK) \
|
||||
&& (!defined(OPENSSL_SYS_VMS) || __CTRL_VER >= 70000000)
|
||||
#define HZ ((double)sysconf(_SC_CLK_TCK))
|
||||
#else
|
||||
#ifndef CLK_TCK
|
||||
#ifndef _BSD_CLK_TCK_ /* FreeBSD hack */
|
||||
#define HZ 100.0
|
||||
#else /* _BSD_CLK_TCK_ */
|
||||
#define HZ ((double)_BSD_CLK_TCK_)
|
||||
#endif
|
||||
#else /* CLK_TCK */
|
||||
#define HZ ((double)CLK_TCK)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <kvm.h>
|
||||
#endif
|
||||
|
||||
// process descriptor
|
||||
struct process {
|
||||
//pid of the process
|
||||
pid_t pid;
|
||||
//ppid of the process
|
||||
pid_t ppid;
|
||||
//start time (unix timestamp)
|
||||
int starttime;
|
||||
//cputime used by the process (in milliseconds)
|
||||
int cputime;
|
||||
//actual cpu usage estimation (value in range 0-1)
|
||||
double cpu_usage;
|
||||
//absolute path of the executable file
|
||||
char command[PATH_MAX+1];
|
||||
};
|
||||
|
||||
struct process_filter {
|
||||
int pid;
|
||||
int include_children;
|
||||
char program_name[PATH_MAX+1];
|
||||
};
|
||||
|
||||
struct process_iterator {
|
||||
#if defined __linux__ || defined __sun__
|
||||
DIR *dip;
|
||||
int boot_time;
|
||||
#elif defined __FreeBSD__
|
||||
kvm_t *kd;
|
||||
struct kinfo_proc *procs;
|
||||
int count;
|
||||
int i;
|
||||
#elif defined __APPLE__
|
||||
int i;
|
||||
int count;
|
||||
int *pidlist;
|
||||
#endif
|
||||
struct process_filter *filter;
|
||||
};
|
||||
|
||||
int init_process_iterator(struct process_iterator *i, struct process_filter *filter);
|
||||
|
||||
int get_next_process(struct process_iterator *i, struct process *p);
|
||||
|
||||
int close_process_iterator(struct process_iterator *i);
|
||||
|
||||
#endif
|
@ -1,154 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Author: Simon Sigurdhsson
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <libproc.h>
|
||||
|
||||
int unique_nonzero_ints(int *arr_in, int len_in, int *arr_out) {
|
||||
int *source = arr_in;
|
||||
if (arr_out == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (arr_in == arr_out) {
|
||||
source = malloc(sizeof(int)*len_in);
|
||||
memcpy(source, arr_in, sizeof(int)*len_in);
|
||||
memset(arr_out, -1, sizeof(int)*len_in);
|
||||
}
|
||||
int len_out = 0;
|
||||
int i, j;
|
||||
for (i=0; i<len_in; i++) {
|
||||
int found = 0;
|
||||
if (source[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
for (j=0; !found && j<len_out; j++) {
|
||||
found = (source[i] == arr_out[j]) ? 1 : 0;
|
||||
}
|
||||
if (!found) {
|
||||
arr_out[len_out++] = source[i];
|
||||
}
|
||||
}
|
||||
if (arr_in == arr_out) {
|
||||
free(source);
|
||||
}
|
||||
return len_out-1;
|
||||
}
|
||||
|
||||
int init_process_iterator(struct process_iterator *it, struct process_filter *filter) {
|
||||
it->i = 0;
|
||||
/* Find out how much to allocate for it->pidlist */
|
||||
if ((it->count = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0)) <= 0) {
|
||||
fprintf(stderr, "proc_listpids: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/* Allocate and populate it->pidlist */
|
||||
if ((it->pidlist = (int *)malloc((it->count)*sizeof(int))) == NULL) {
|
||||
fprintf(stderr, "malloc: %s\n", strerror(errno));
|
||||
}
|
||||
if ((it->count = proc_listpids(PROC_ALL_PIDS, 0, it->pidlist, it->count)) <= 0) {
|
||||
fprintf(stderr, "proc_listpids: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
it->count = unique_nonzero_ints(it->pidlist, it->count, it->pidlist);
|
||||
it->filter = filter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pti2proc(struct proc_taskallinfo *ti, struct process *process) {
|
||||
int bytes;
|
||||
process->pid = ti->pbsd.pbi_pid;
|
||||
process->ppid = ti->pbsd.pbi_ppid;
|
||||
process->starttime = ti->pbsd.pbi_start_tvsec;
|
||||
process->cputime = (ti->ptinfo.pti_total_user + ti->ptinfo.pti_total_system) / 1000000;
|
||||
bytes = strlen(ti->pbsd.pbi_comm);
|
||||
memcpy(process->command, ti->pbsd.pbi_comm, (bytes < PATH_MAX ? bytes : PATH_MAX) + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_process_pti(pid_t pid, struct proc_taskallinfo *ti) {
|
||||
int bytes;
|
||||
bytes = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, ti, sizeof(*ti));
|
||||
if (bytes <= 0) {
|
||||
if (!(errno & (EPERM | ESRCH))) {
|
||||
fprintf(stderr, "proc_pidinfo: %s\n", strerror(errno));
|
||||
}
|
||||
return -1;
|
||||
} else if (bytes < sizeof(ti)) {
|
||||
fprintf(stderr, "proc_pidinfo: too few bytes; expected %ld, got %d\n", sizeof(ti), bytes);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_next_process(struct process_iterator *it, struct process *p) {
|
||||
if (it->i == it->count) {
|
||||
return -1;
|
||||
}
|
||||
if (it->filter->pid != 0 && !it->filter->include_children) {
|
||||
struct proc_taskallinfo ti;
|
||||
if (get_process_pti(it->filter->pid, &ti) != 0) {
|
||||
it->i = it->count = 0;
|
||||
return -1;
|
||||
}
|
||||
it->i = it->count = 1;
|
||||
return pti2proc(&ti, p);
|
||||
}
|
||||
while (it->i < it->count) {
|
||||
struct proc_taskallinfo ti;
|
||||
if (get_process_pti(it->pidlist[it->i], &ti) != 0) {
|
||||
it->i++;
|
||||
continue;
|
||||
}
|
||||
if (ti.pbsd.pbi_flags & PROC_FLAG_SYSTEM) {
|
||||
it->i++;
|
||||
continue;
|
||||
}
|
||||
if (it->filter->pid != 0 && it->filter->include_children) {
|
||||
pti2proc(&ti, p);
|
||||
it->i++;
|
||||
if (p->pid != it->pidlist[it->i - 1]) { // I don't know why this can happen
|
||||
continue;
|
||||
}
|
||||
if (p->pid != it->filter->pid && p->ppid != it->filter->pid) {
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
} else if (it->filter->pid == 0) {
|
||||
pti2proc(&ti, p);
|
||||
it->i++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int close_process_iterator(struct process_iterator *it) {
|
||||
free(it->pidlist);
|
||||
it->pidlist = NULL;
|
||||
it->filter = NULL;
|
||||
it->count = 0;
|
||||
it->i = 0;
|
||||
return 0;
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
|
||||
int init_process_iterator(struct process_iterator *it, struct process_filter *filter) {
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
it->i = 0;
|
||||
/* Open the kvm interface, get a descriptor */
|
||||
if ((it->kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) {
|
||||
fprintf(stderr, "kvm_open: %s\n", errbuf);
|
||||
return -1;
|
||||
}
|
||||
/* Get the list of processes. */
|
||||
if ((it->procs = kvm_getprocs(it->kd, KERN_PROC_PROC, 0, &it->count)) == NULL) {
|
||||
kvm_close(it->kd);
|
||||
// fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(it->kd));
|
||||
return -1;
|
||||
}
|
||||
it->filter = filter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kproc2proc(kvm_t *kd, struct kinfo_proc *kproc, struct process *proc) {
|
||||
proc->pid = kproc->ki_pid;
|
||||
proc->ppid = kproc->ki_ppid;
|
||||
proc->cputime = kproc->ki_runtime / 1000;
|
||||
proc->starttime = kproc->ki_start.tv_sec;
|
||||
char **args = kvm_getargv(kd, kproc, sizeof(proc->command));
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(proc->command, args[0], strlen(args[0]) + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_single_process(kvm_t *kd, pid_t pid, struct process *process) {
|
||||
int count;
|
||||
struct kinfo_proc *kproc = kvm_getprocs(kd, KERN_PROC_PID, pid, &count);
|
||||
if (count == 0 || kproc == NULL) {
|
||||
// fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd));
|
||||
return -1;
|
||||
}
|
||||
kproc2proc(kd, kproc, process);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_next_process(struct process_iterator *it, struct process *p) {
|
||||
if (it->i == it->count) {
|
||||
return -1;
|
||||
}
|
||||
if (it->filter->pid != 0 && !it->filter->include_children) {
|
||||
if (get_single_process(it->kd, it->filter->pid, p) != 0) {
|
||||
it->i = it->count = 0;
|
||||
return -1;
|
||||
}
|
||||
it->i = it->count = 1;
|
||||
return 0;
|
||||
}
|
||||
while (it->i < it->count) {
|
||||
struct kinfo_proc *kproc = &(it->procs[it->i]);
|
||||
if (kproc->ki_flag & P_SYSTEM) {
|
||||
// skip system processes
|
||||
it->i++;
|
||||
continue;
|
||||
}
|
||||
if (it->filter->pid != 0 && it->filter->include_children) {
|
||||
kproc2proc(it->kd, kproc, p);
|
||||
it->i++;
|
||||
if (p->pid != it->filter->pid && p->ppid != it->filter->pid) {
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
} else if (it->filter->pid == 0) {
|
||||
kproc2proc(it->kd, kproc, p);
|
||||
it->i++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int close_process_iterator(struct process_iterator *it) {
|
||||
if (kvm_close(it->kd) == -1) {
|
||||
fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(it->kd));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,188 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cpulimit - a CPU limiter for Linux
|
||||
*
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
static int get_boot_time() {
|
||||
int uptime = 0;
|
||||
FILE *fp = fopen("/proc/uptime", "r");
|
||||
if (fp != NULL) {
|
||||
char buf[BUFSIZ];
|
||||
char *b = fgets(buf, BUFSIZ, fp);
|
||||
if (b == buf) {
|
||||
char *end_ptr;
|
||||
double upsecs = strtod(buf, &end_ptr);
|
||||
uptime = (int)upsecs;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
time_t now = time(NULL);
|
||||
return now - uptime;
|
||||
}
|
||||
|
||||
static int check_proc() {
|
||||
struct statfs mnt;
|
||||
if (statfs("/proc", &mnt) < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (mnt.f_type!=0x9fa0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int init_process_iterator(struct process_iterator *it, struct process_filter *filter) {
|
||||
if (!check_proc()) {
|
||||
fprintf(stderr, "procfs is not mounted!\nAborting\n");
|
||||
exit(-2);
|
||||
}
|
||||
//open a directory stream to /proc directory
|
||||
if ((it->dip = opendir("/proc")) == NULL) {
|
||||
perror("opendir");
|
||||
return -1;
|
||||
}
|
||||
it->filter = filter;
|
||||
it->boot_time = get_boot_time();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_process_info(pid_t pid, struct process *p) {
|
||||
static char buffer[1024];
|
||||
static char statfile[32];
|
||||
static char exefile[1024];
|
||||
p->pid = pid;
|
||||
//read stat file
|
||||
sprintf(statfile, "/proc/%d/stat", p->pid);
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (fd==NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (fgets(buffer, sizeof(buffer), fd)==NULL) {
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
fclose(fd);
|
||||
char *token = strtok(buffer, " ");
|
||||
int i;
|
||||
for (i=0; i<3; i++) {
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
p->ppid = atoi(token);
|
||||
for (i=0; i<10; i++) {
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
p->cputime = atoi(token) * 1000 / HZ;
|
||||
token = strtok(NULL, " ");
|
||||
p->cputime += atoi(token) * 1000 / HZ;
|
||||
for (i=0; i<7; i++) {
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
p->starttime = atoi(token) / sysconf(_SC_CLK_TCK);
|
||||
//read command line
|
||||
sprintf(exefile,"/proc/%d/cmdline", p->pid);
|
||||
fd = fopen(exefile, "r");
|
||||
if (fd==NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (fgets(buffer, sizeof(buffer), fd)==NULL) {
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
fclose(fd);
|
||||
strcpy(p->command, buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pid_t getppid_of(pid_t pid) {
|
||||
char statfile[20];
|
||||
char buffer[1024];
|
||||
sprintf(statfile, "/proc/%d/stat", pid);
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (fd==NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (fgets(buffer, sizeof(buffer), fd)==NULL) {
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
fclose(fd);
|
||||
char *token = strtok(buffer, " ");
|
||||
int i;
|
||||
for (i=0; i<3; i++) {
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
return atoi(token);
|
||||
}
|
||||
|
||||
static int is_child_of(pid_t child_pid, pid_t parent_pid) {
|
||||
int ppid = child_pid;
|
||||
while (ppid > 1 && ppid != parent_pid) {
|
||||
ppid = getppid_of(ppid);
|
||||
}
|
||||
return ppid == parent_pid;
|
||||
}
|
||||
|
||||
int get_next_process(struct process_iterator *it, struct process *p) {
|
||||
if (it->dip == NULL) {
|
||||
//end of processes
|
||||
return -1;
|
||||
}
|
||||
if (it->filter->pid != 0 && !it->filter->include_children) {
|
||||
int ret = read_process_info(it->filter->pid, p);
|
||||
//p->starttime += it->boot_time;
|
||||
closedir(it->dip);
|
||||
it->dip = NULL;
|
||||
if (ret != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
struct dirent *dit = NULL;
|
||||
//read in from /proc and seek for process dirs
|
||||
while ((dit = readdir(it->dip)) != NULL) {
|
||||
if (strtok(dit->d_name, "0123456789") != NULL) {
|
||||
continue;
|
||||
}
|
||||
p->pid = atoi(dit->d_name);
|
||||
if (it->filter->pid != 0 && it->filter->pid != p->pid && !is_child_of(p->pid, it->filter->pid)) {
|
||||
continue;
|
||||
}
|
||||
read_process_info(p->pid, p);
|
||||
//p->starttime += it->boot_time;
|
||||
break;
|
||||
}
|
||||
if (dit == NULL) {
|
||||
//end of processes
|
||||
closedir(it->dip);
|
||||
it->dip = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int close_process_iterator(struct process_iterator *it) {
|
||||
if (it->dip != NULL && closedir(it->dip) == -1) {
|
||||
perror("closedir");
|
||||
return 1;
|
||||
}
|
||||
it->dip = NULL;
|
||||
return 0;
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* process_iterator_solaris.c
|
||||
* Copyright (C) 2016 by Jim Mason <jmason at ibinx dot com>
|
||||
*
|
||||
* Adapted from process_iterator_linux.c
|
||||
* Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
int init_process_iterator(struct process_iterator *it, struct process_filter *filter) {
|
||||
// open a directory stream to /proc directory
|
||||
if (!(it->dip = opendir("/proc"))) {
|
||||
perror("opendir");
|
||||
return -1;
|
||||
}
|
||||
it->filter = filter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_process_info(pid_t pid, struct process *p) {
|
||||
psinfo_t psinfo;
|
||||
char statfile[32];
|
||||
|
||||
p->pid = pid;
|
||||
sprintf(statfile, "/proc/%ld/psinfo", (long)pid);
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (!fd) return -1;
|
||||
if (!fread(&psinfo, sizeof(psinfo), 1, fd)) {
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
p->ppid = psinfo.pr_ppid;
|
||||
p->cputime = psinfo.pr_time.tv_sec * 1.0e03 + psinfo.pr_time.tv_nsec / 1.0e06;
|
||||
p->starttime = psinfo.pr_start.tv_sec * 1.0e03 + psinfo.pr_start.tv_nsec / 1.0e06;
|
||||
strcpy(p->command, psinfo.pr_psargs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pid_t getppid_of(pid_t pid) {
|
||||
psinfo_t psinfo;
|
||||
char statfile[32];
|
||||
|
||||
sprintf(statfile, "/proc/%ld/psinfo", (long)pid);
|
||||
FILE *fd = fopen(statfile, "r");
|
||||
if (!fd) return -1;
|
||||
if (!fread(&psinfo, sizeof(psinfo), 1, fd)) {
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
return psinfo.pr_ppid;
|
||||
}
|
||||
|
||||
static int is_child_of(pid_t child_pid, pid_t parent_pid) {
|
||||
int ppid = child_pid;
|
||||
while(ppid > 1 && ppid != parent_pid)
|
||||
ppid = getppid_of(ppid);
|
||||
return ppid == parent_pid;
|
||||
}
|
||||
|
||||
int get_next_process(struct process_iterator *it, struct process *p) {
|
||||
if (!it->dip) {
|
||||
// end of processes
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (it->filter->pid != 0 && !it->filter->include_children) {
|
||||
int ret = read_process_info(it->filter->pid, p);
|
||||
closedir(it->dip);
|
||||
it->dip = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// read in from /proc and seek for process dirs
|
||||
struct dirent *dit;
|
||||
while ((dit = readdir(it->dip))) {
|
||||
p->pid = atoi(dit->d_name);
|
||||
if (it->filter->pid != 0 && it->filter->pid != p->pid && !is_child_of(p->pid, it->filter->pid)) continue;
|
||||
read_process_info(p->pid, p);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dit) {
|
||||
// end of processes
|
||||
closedir(it->dip);
|
||||
it->dip = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int close_process_iterator(struct process_iterator *it) {
|
||||
if (it->dip && closedir(it->dip) == -1) {
|
||||
perror("closedir");
|
||||
return 1;
|
||||
}
|
||||
it->dip = NULL;
|
||||
return 0;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2017 McMCC
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=dvb-firmware
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=2
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/dvb-firmware
|
||||
SECTION:=firmware
|
||||
CATEGORY:=Firmware
|
||||
TITLE:=dvb-firmware megapack
|
||||
endef
|
||||
|
||||
define Package/dvb-firmware/description
|
||||
dvb-firmware is specialised software that is both specific to some hardware
|
||||
and also integral for its proper functioning.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/dvb-firmware/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware
|
||||
$(CP) $(CURDIR)/files/* $(1)/lib/firmware/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,dvb-firmware))
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,41 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2008-2011 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=fcgiwrap
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_MAINTAINER:=Tobias Waldvogel <tobias.waldvogel@gmail.com>
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/fcgiwrap
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=FCGI wrapper for CGI
|
||||
DEPENDS:=+libpcre +spawn-fcgi +fcgi
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(TARGET_CC) \
|
||||
-I$(STAGING_DIR)/usr/include $(TARGET_CFLAGS) -Wall -Werror \
|
||||
-L$(STAGING_DIR)/usr/lib -lfcgi \
|
||||
-o$(PKG_BUILD_DIR)/fcgiwrap $(PKG_BUILD_DIR)/fcgiwrap.c
|
||||
endef
|
||||
|
||||
define Package/fcgiwrap/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fcgiwrap $(1)/usr/sbin/
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/fcgiwrap.init $(1)/etc/init.d/fcgiwrap
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,fcgiwrap))
|
@ -1,62 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#by guogh
|
||||
|
||||
USE_PROCD=1
|
||||
START=99
|
||||
|
||||
SPAWN_FCGI="/usr/bin/spawn-fcgi"
|
||||
DAEMON="/usr/sbin/fcgiwrap"
|
||||
NAME="fcgiwrap"
|
||||
|
||||
PIDFILE="/var/run/$NAME.pid"
|
||||
|
||||
FCGI_SOCKET="/tmp/$NAME.socket"
|
||||
FCGI_USER="www"
|
||||
FCGI_GROUP="www"
|
||||
FORK_NUM=2
|
||||
|
||||
start_service() {
|
||||
echo -e "Starting $NAME ..."
|
||||
#procd_set_param command $SPAWN_FCGI -u $FCGI_USER -g $FCGI_GROUP -s $FCGI_SOCKET -P $PIDFILE -F $FORK_NUM -f $DAEMON
|
||||
$SPAWN_FCGI -a 127.0.0.1 -p 9000 -f $DAEMON -F $FORK_NUM
|
||||
}
|
||||
|
||||
stop_service(){
|
||||
|
||||
PID=`pidof $NAME`
|
||||
#i=1
|
||||
#for p in $PID
|
||||
#do
|
||||
# if [ $i -eq 1 ]; then
|
||||
# let i++
|
||||
# continue
|
||||
# fi
|
||||
# echo -n "$p "
|
||||
#done
|
||||
#因为脚本执行时,第一个pid是脚本的,所以要去除
|
||||
if [ -n "`echo $PID | grep ' '`" ]; then
|
||||
SPID=${PID#* }
|
||||
echo -e "Kill $NAME (PID: $SPID)."
|
||||
kill -9 $SPID
|
||||
else
|
||||
echo -e "Warning: $NAME is not runing."
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
restart(){
|
||||
PID=`pidof $NAME`
|
||||
#因为脚本执行时,第一个pid是脚本的,所以要去除
|
||||
if [ -n "`echo $PID | grep ' '`" ]; then
|
||||
SPID=${PID#* }
|
||||
echo -e "Kill $NAME (PID: $SPID)."
|
||||
kill -9 $SPID
|
||||
else
|
||||
echo -e "Warning: $NAME is not runing."
|
||||
fi
|
||||
start_service
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,901 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2013 Grzegorz Nosek
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define NO_FCGI_DEFINES
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <fcgi_stdio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/wait.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
/* glibc doesn't seem to export it */
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#define UNIX_PATH_MAX 108
|
||||
#endif
|
||||
|
||||
extern char **environ;
|
||||
static char * const * inherited_environ;
|
||||
static const char **allowed_programs;
|
||||
static size_t allowed_programs_count;
|
||||
|
||||
static const char * blacklisted_env_vars[] = {
|
||||
"AUTH_TYPE",
|
||||
"CONTENT_LENGTH",
|
||||
"CONTENT_TYPE",
|
||||
"GATEWAY_INTERFACE",
|
||||
"PATH_INFO",
|
||||
"PATH_TRANSLATED",
|
||||
"QUERY_STRING",
|
||||
"REMOTE_ADDR",
|
||||
"REMOTE_HOST",
|
||||
"REMOTE_IDENT",
|
||||
"REMOTE_USER",
|
||||
"REQUEST_METHOD",
|
||||
"SCRIPT_NAME",
|
||||
"SERVER_NAME",
|
||||
"SERVER_PORT",
|
||||
"SERVER_PROTOCOL",
|
||||
"SERVER_SOFTWARE",
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int stderr_to_fastcgi = 0;
|
||||
|
||||
|
||||
#define FCGI_BUF_SIZE 4096
|
||||
|
||||
static int write_all(int fd, char *buf, size_t size)
|
||||
{
|
||||
size_t nleft = size;
|
||||
while (nleft > 0) {
|
||||
ssize_t nwritten = write(fd, buf, nleft);
|
||||
if (nwritten < 0)
|
||||
return nleft - size; /* zero or negative to indicate error */
|
||||
|
||||
buf += nwritten;
|
||||
nleft -= nwritten;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#define MAX_VA_SENTINEL INT_MIN
|
||||
|
||||
static int max_va(int p1, ...)
|
||||
{
|
||||
va_list va;
|
||||
int max = p1;
|
||||
int p;
|
||||
|
||||
va_start(va, p1);
|
||||
do {
|
||||
p = va_arg(va, int);
|
||||
if (p > max)
|
||||
max = p;
|
||||
} while (p != MAX_VA_SENTINEL);
|
||||
va_end(va);
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
enum reply_state_t {
|
||||
REPLY_STATE_INIT,
|
||||
REPLY_STATE_HEADER,
|
||||
REPLY_STATE_CR,
|
||||
REPLY_STATE_LF,
|
||||
REPLY_STATE_2CR,
|
||||
REPLY_STATE_2LF,
|
||||
REPLY_STATE_BODY,
|
||||
REPLY_STATE_MAX
|
||||
};
|
||||
|
||||
enum char_class_t {
|
||||
CC_NORMAL,
|
||||
CC_CR,
|
||||
CC_LF,
|
||||
CC_MAX
|
||||
};
|
||||
|
||||
#define ACTION_MASK (15 << 4)
|
||||
#define ACTION_EMIT 0
|
||||
#define ACTION_ERROR (1 << 4)
|
||||
#define ACTION_END (2 << 4)
|
||||
#define ACTION_SKIP (3 << 4)
|
||||
#define ACTION_EXTRA_CR (4 << 4)
|
||||
#define ACTION_EXTRA_LF (5 << 4)
|
||||
|
||||
static const unsigned char header_state_machine[REPLY_STATE_MAX][CC_MAX] = {
|
||||
[REPLY_STATE_INIT] = {
|
||||
[CC_NORMAL] = REPLY_STATE_HEADER,
|
||||
[CC_CR] = ACTION_ERROR,
|
||||
[CC_LF] = ACTION_ERROR,
|
||||
},
|
||||
[REPLY_STATE_HEADER] = {
|
||||
[CC_NORMAL] = REPLY_STATE_HEADER,
|
||||
[CC_CR] = REPLY_STATE_CR,
|
||||
[CC_LF] = REPLY_STATE_LF | ACTION_EXTRA_CR,
|
||||
},
|
||||
[REPLY_STATE_CR] = {
|
||||
[CC_NORMAL] = REPLY_STATE_HEADER | ACTION_EXTRA_LF,
|
||||
[CC_CR] = REPLY_STATE_CR | ACTION_SKIP,
|
||||
[CC_LF] = REPLY_STATE_LF,
|
||||
},
|
||||
[REPLY_STATE_LF] = {
|
||||
[CC_NORMAL] = REPLY_STATE_HEADER,
|
||||
[CC_CR] = REPLY_STATE_2CR,
|
||||
[CC_LF] = REPLY_STATE_2LF | ACTION_EXTRA_CR,
|
||||
},
|
||||
[REPLY_STATE_2CR] = {
|
||||
[CC_NORMAL] = REPLY_STATE_BODY | ACTION_EXTRA_LF,
|
||||
[CC_CR] = REPLY_STATE_CR | ACTION_SKIP,
|
||||
[CC_LF] = REPLY_STATE_2LF,
|
||||
},
|
||||
[REPLY_STATE_2LF] = {
|
||||
[CC_NORMAL] = REPLY_STATE_BODY | ACTION_END,
|
||||
[CC_CR] = REPLY_STATE_BODY | ACTION_END,
|
||||
[CC_LF] = REPLY_STATE_BODY | ACTION_END,
|
||||
},
|
||||
[REPLY_STATE_BODY] = {
|
||||
[CC_NORMAL] = REPLY_STATE_BODY | ACTION_END,
|
||||
[CC_CR] = REPLY_STATE_BODY | ACTION_END,
|
||||
[CC_LF] = REPLY_STATE_BODY | ACTION_END,
|
||||
},
|
||||
};
|
||||
|
||||
struct fcgi_context {
|
||||
int fd_stdin;
|
||||
int fd_stdout;
|
||||
int fd_stderr;
|
||||
unsigned int reply_state;
|
||||
pid_t cgi_pid;
|
||||
};
|
||||
|
||||
static void fcgi_finish(struct fcgi_context *fc, const char* msg)
|
||||
{
|
||||
if (fc->reply_state == REPLY_STATE_INIT) {
|
||||
FCGI_puts("Status: 502 Bad Gateway\nContent-type: text/plain\n");
|
||||
FCGI_printf("An error occurred while %s\n", msg);
|
||||
}
|
||||
|
||||
if (fc->fd_stdin >= 0) close(fc->fd_stdin);
|
||||
if (fc->fd_stdout >= 0) close(fc->fd_stdout);
|
||||
if (fc->fd_stderr >= 0) close(fc->fd_stderr);
|
||||
|
||||
if (fc->cgi_pid)
|
||||
kill(SIGTERM, fc->cgi_pid);
|
||||
}
|
||||
|
||||
static const char * fcgi_pass_fd(struct fcgi_context *fc, int *fdp, FCGI_FILE *ffp, char *buf, size_t bufsize)
|
||||
{
|
||||
ssize_t nread;
|
||||
char *p = buf;
|
||||
unsigned char cclass, next_state;
|
||||
|
||||
nread = read(*fdp, buf, bufsize);
|
||||
if (nread > 0) {
|
||||
while (p < buf + nread) {
|
||||
if (*p == '\r') {
|
||||
cclass = CC_CR;
|
||||
} else if (*p == '\n') {
|
||||
cclass = CC_LF;
|
||||
} else {
|
||||
cclass = CC_NORMAL;
|
||||
}
|
||||
next_state = header_state_machine[fc->reply_state][cclass];
|
||||
fc->reply_state = next_state & ~ACTION_MASK;
|
||||
switch(next_state & ACTION_MASK) {
|
||||
case ACTION_ERROR:
|
||||
return "parsing CGI reply";
|
||||
|
||||
case ACTION_END:
|
||||
goto out_of_loop;
|
||||
|
||||
case ACTION_SKIP:
|
||||
goto next_char;
|
||||
|
||||
case ACTION_EXTRA_CR:
|
||||
if (FCGI_fputc('\r', ffp) == EOF) return "writing CGI reply";
|
||||
break;
|
||||
|
||||
case ACTION_EXTRA_LF:
|
||||
if (FCGI_fputc('\n', ffp) == EOF) return "writing CGI reply";
|
||||
break;
|
||||
}
|
||||
if (FCGI_fputc(*p, ffp) == EOF) {
|
||||
return "writing CGI reply";
|
||||
}
|
||||
next_char:
|
||||
p++;
|
||||
}
|
||||
out_of_loop:
|
||||
if (p < buf + nread) {
|
||||
if (FCGI_fwrite(p, 1, buf + nread - p, ffp) != (size_t)(buf + nread - p)) {
|
||||
return "writing CGI reply";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nread < 0) {
|
||||
return "reading CGI reply";
|
||||
}
|
||||
close(*fdp);
|
||||
*fdp = -1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char * fcgi_pass_raw_fd(int *fdp, int fd_out, char *buf, size_t bufsize)
|
||||
{
|
||||
ssize_t nread;
|
||||
|
||||
nread = read(*fdp, buf, bufsize);
|
||||
if (nread > 0) {
|
||||
if (write_all(fd_out, buf, nread) != nread) {
|
||||
return "writing CGI reply";
|
||||
}
|
||||
} else {
|
||||
if (nread < 0) {
|
||||
return "reading CGI reply";
|
||||
}
|
||||
close(*fdp);
|
||||
*fdp = -1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool fcgi_pass_request(struct fcgi_context *fc)
|
||||
{
|
||||
char buf[FCGI_BUF_SIZE];
|
||||
ssize_t nread;
|
||||
|
||||
/* eat the whole request and pass it to CGI */
|
||||
while ((nread = FCGI_fread(buf, 1, sizeof(buf), FCGI_stdin)) > 0) {
|
||||
if (write_all(fc->fd_stdin, buf, nread) <= 0) {
|
||||
fcgi_finish(fc, "reading the request");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
close(fc->fd_stdin);
|
||||
fc->fd_stdin = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fcgi_pass(struct fcgi_context *fc)
|
||||
{
|
||||
char buf[FCGI_BUF_SIZE];
|
||||
fd_set rset;
|
||||
int maxfd = 1 + max_va(fc->fd_stdout, fc->fd_stderr, MAX_VA_SENTINEL);
|
||||
int nready;
|
||||
const char *err;
|
||||
|
||||
if (!fcgi_pass_request(fc))
|
||||
return;
|
||||
|
||||
/* now pass CGI reply back */
|
||||
while (fc->fd_stdout >= 0 || fc->fd_stderr >= 0) {
|
||||
FD_ZERO(&rset);
|
||||
if (fc->fd_stdout >= 0) FD_SET(fc->fd_stdout, &rset);
|
||||
if (fc->fd_stderr >= 0) FD_SET(fc->fd_stderr, &rset);
|
||||
nready = select(maxfd, &rset, NULL, NULL, NULL);
|
||||
if (nready < 0) {
|
||||
if (errno == EAGAIN) continue;
|
||||
fcgi_finish(fc, "waiting for CGI reply");
|
||||
return;
|
||||
}
|
||||
if (fc->fd_stdout >= 0 && FD_ISSET(fc->fd_stdout, &rset)) {
|
||||
err = fcgi_pass_fd(fc, &fc->fd_stdout, FCGI_stdout, buf, sizeof(buf));
|
||||
if (err) {
|
||||
fcgi_finish(fc, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (fc->fd_stderr >= 0 && FD_ISSET(fc->fd_stderr, &rset)) {
|
||||
if (stderr_to_fastcgi)
|
||||
err = fcgi_pass_fd(fc, &fc->fd_stderr, FCGI_stderr, buf, sizeof(buf));
|
||||
else
|
||||
err = fcgi_pass_raw_fd(&fc->fd_stderr, 2, buf, sizeof(buf));
|
||||
if (err) {
|
||||
fcgi_finish(fc, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fc->cgi_pid = 0;
|
||||
|
||||
fcgi_finish(fc, "reading CGI reply (no response received)");
|
||||
}
|
||||
|
||||
static int check_file_perms(const char *path)
|
||||
{
|
||||
struct stat ls;
|
||||
struct stat fs;
|
||||
|
||||
if (lstat(path, &ls) < 0) {
|
||||
return -ENOENT;
|
||||
} else if (S_ISREG(ls.st_mode)) {
|
||||
if (ls.st_mode & S_IXUSR) {
|
||||
return 0;
|
||||
} else {
|
||||
return -EACCES;
|
||||
}
|
||||
} else if (!S_ISLNK(ls.st_mode)) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (stat(path, &fs) < 0) {
|
||||
return -ENOENT;
|
||||
} else if (S_ISREG(fs.st_mode)) {
|
||||
if (fs.st_mode & S_IXUSR) {
|
||||
return 0;
|
||||
} else {
|
||||
return -EACCES;
|
||||
}
|
||||
} else {
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
static char *get_cgi_filename(void) /* and fixup environment */
|
||||
{
|
||||
int buflen = 1, docrootlen;
|
||||
char *buf = NULL;
|
||||
char *docroot, *scriptname, *p;
|
||||
|
||||
int rf_len;
|
||||
char *pathinfo = NULL;
|
||||
|
||||
if ((p = getenv("SCRIPT_FILENAME"))) {
|
||||
if (check_file_perms(p) != 0)
|
||||
goto err;
|
||||
return strdup(p);
|
||||
}
|
||||
|
||||
if ((p = getenv("DOCUMENT_ROOT"))) {
|
||||
docroot = p;
|
||||
docrootlen = strlen(p);
|
||||
buflen += docrootlen;
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((p = getenv("SCRIPT_NAME"))) {
|
||||
buflen += strlen(p);
|
||||
scriptname = p;
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
|
||||
buf = malloc(buflen);
|
||||
if (!buf) goto err;
|
||||
|
||||
strcpy(buf, docroot);
|
||||
strcpy(buf + docrootlen, scriptname);
|
||||
pathinfo = strdup(buf);
|
||||
if (!pathinfo) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
switch(check_file_perms(buf)) {
|
||||
case -EACCES:
|
||||
goto err;
|
||||
case 0:
|
||||
rf_len = strlen(buf);
|
||||
if (rf_len < buflen - 1) {
|
||||
setenv("PATH_INFO", pathinfo + rf_len, 1);
|
||||
setenv("SCRIPT_NAME", buf + docrootlen, 1);
|
||||
} else {
|
||||
unsetenv("PATH_INFO");
|
||||
}
|
||||
free(pathinfo);
|
||||
return buf;
|
||||
default:
|
||||
p = strrchr(buf, '/');
|
||||
if (!p) goto err;
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
free(pathinfo);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int blacklisted_env(const char *var_name, const char *var_name_end)
|
||||
{
|
||||
const char **p;
|
||||
|
||||
if (var_name_end - var_name > 4 && !strncmp(var_name, "HTTP", 4)) {
|
||||
/* HTTP_*, HTTPS */
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (p = blacklisted_env_vars; *p; p++) {
|
||||
if (!strcmp(var_name, *p)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void inherit_environment(void)
|
||||
{
|
||||
char * const * p;
|
||||
char *q;
|
||||
|
||||
for (p = inherited_environ; *p; p++) {
|
||||
q = strchr(*p, '=');
|
||||
if (!q) {
|
||||
fprintf(stderr, "Suspect value in environment: %s\n", *p);
|
||||
continue;
|
||||
}
|
||||
*q = 0;
|
||||
|
||||
if (!getenv(*p) && !blacklisted_env(*p, q)) {
|
||||
*q = '=';
|
||||
putenv(*p);
|
||||
}
|
||||
|
||||
*q = '=';
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_allowed_program(const char *program) {
|
||||
size_t i;
|
||||
if (!allowed_programs_count)
|
||||
return true;
|
||||
|
||||
for (i = 0; i < allowed_programs_count; i++) {
|
||||
if (!strcmp(allowed_programs[i], program))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void cgi_error(const char *message, const char *reason, const char *filename)
|
||||
{
|
||||
printf("Status: %s\r\nContent-Type: text/plain\r\n\r\n%s\r\n",
|
||||
message, message);
|
||||
fflush(stdout);
|
||||
if (filename) {
|
||||
fprintf(stderr, "%s (%s)\n", reason, filename);
|
||||
} else {
|
||||
fputs(reason, stderr);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
_exit(99);
|
||||
}
|
||||
|
||||
static void handle_fcgi_request(void)
|
||||
{
|
||||
int pipe_in[2];
|
||||
int pipe_out[2];
|
||||
int pipe_err[2];
|
||||
char *filename;
|
||||
char *last_slash;
|
||||
char *p;
|
||||
pid_t pid;
|
||||
|
||||
struct fcgi_context fc;
|
||||
|
||||
if (pipe(pipe_in) < 0) goto err_pipein;
|
||||
if (pipe(pipe_out) < 0) goto err_pipeout;
|
||||
if (pipe(pipe_err) < 0) goto err_pipeerr;
|
||||
|
||||
switch((pid = fork())) {
|
||||
case -1:
|
||||
goto err_fork;
|
||||
|
||||
case 0: /* child */
|
||||
close(pipe_in[1]);
|
||||
close(pipe_out[0]);
|
||||
close(pipe_err[0]);
|
||||
|
||||
dup2(pipe_in[0], 0);
|
||||
dup2(pipe_out[1], 1);
|
||||
dup2(pipe_err[1], 2);
|
||||
|
||||
close(pipe_in[0]);
|
||||
close(pipe_out[1]);
|
||||
close(pipe_err[1]);
|
||||
|
||||
close(FCGI_fileno(FCGI_stdout));
|
||||
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
filename = get_cgi_filename();
|
||||
inherit_environment();
|
||||
if (!filename)
|
||||
cgi_error("403 Forbidden", "Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?", NULL);
|
||||
|
||||
if (!is_allowed_program(filename))
|
||||
cgi_error("403 Forbidden", "The given script is not allowed to execute", filename);
|
||||
|
||||
p = getenv("FCGI_CHDIR");
|
||||
if (p == NULL) {
|
||||
last_slash = strrchr(filename, '/');
|
||||
if (!last_slash)
|
||||
cgi_error("403 Forbidden", "Script name must be a fully qualified path", filename);
|
||||
|
||||
*last_slash = 0;
|
||||
if (chdir(filename) < 0)
|
||||
cgi_error("403 Forbidden", "Cannot chdir to script directory", filename);
|
||||
|
||||
*last_slash = '/';
|
||||
} else if (strcmp(p, "-") != 0) {
|
||||
if (chdir(p) < 0) {
|
||||
cgi_error("403 Forbidden", "Cannot chdir to FCGI_CHDIR directory", p);
|
||||
}
|
||||
}
|
||||
|
||||
execl(filename, filename, (void *)NULL);
|
||||
cgi_error("502 Bad Gateway", "Cannot execute script", filename);
|
||||
|
||||
default: /* parent */
|
||||
close(pipe_in[0]);
|
||||
close(pipe_out[1]);
|
||||
close(pipe_err[1]);
|
||||
|
||||
fc.fd_stdin = pipe_in[1];
|
||||
fc.fd_stdout = pipe_out[0];
|
||||
fc.fd_stderr = pipe_err[0];
|
||||
fc.reply_state = REPLY_STATE_INIT;
|
||||
fc.cgi_pid = pid;
|
||||
|
||||
fcgi_pass(&fc);
|
||||
}
|
||||
return;
|
||||
|
||||
err_fork:
|
||||
close(pipe_err[0]);
|
||||
close(pipe_err[1]);
|
||||
|
||||
err_pipeerr:
|
||||
close(pipe_out[0]);
|
||||
close(pipe_out[1]);
|
||||
|
||||
err_pipeout:
|
||||
close(pipe_in[0]);
|
||||
close(pipe_in[1]);
|
||||
|
||||
err_pipein:
|
||||
|
||||
FCGI_puts("Status: 502 Bad Gateway\nContent-type: text/plain\n");
|
||||
FCGI_puts("System error");
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t sigint_received ;
|
||||
static void sigint_handler(int __attribute__((__unused__))dummy)
|
||||
{
|
||||
sigint_received = 1;
|
||||
FCGX_ShutdownPending(); // Or we could send SIGUSR1
|
||||
}
|
||||
|
||||
static void fcgiwrap_main(void)
|
||||
{
|
||||
struct sigaction a;
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
// Use sigaction for SIGINT so we can avoid SA_RESTART and actually react
|
||||
a.sa_handler = sigint_handler;
|
||||
a.sa_flags = 0;
|
||||
sigemptyset( &a.sa_mask );
|
||||
sigaction( SIGINT, &a, NULL );
|
||||
sigaction( SIGTERM, &a, NULL );
|
||||
|
||||
inherited_environ = environ;
|
||||
|
||||
while (FCGI_Accept() >= 0 && !sigint_received) {
|
||||
handle_fcgi_request();
|
||||
}
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t nrunning;
|
||||
|
||||
static void sigchld_handler(int dummy)
|
||||
{
|
||||
int status;
|
||||
|
||||
while ((dummy = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||
/* sanity check */
|
||||
if (nrunning > 0)
|
||||
nrunning--;
|
||||
|
||||
/* we _should_ print something about the exit code
|
||||
* but the sighandler context is _very_ bad for this
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static void prefork(int nchildren)
|
||||
{
|
||||
int startup = 1;
|
||||
|
||||
if (nchildren == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
|
||||
while (1) {
|
||||
while (nrunning < nchildren) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
return;
|
||||
} else if (pid != -1) {
|
||||
nrunning++;
|
||||
} else {
|
||||
if (startup) {
|
||||
fprintf(stderr, "Failed to prefork: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to fork: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
startup = 0;
|
||||
pause();
|
||||
}
|
||||
}
|
||||
|
||||
static int listen_on_fd(int fd) {
|
||||
int one = 1;
|
||||
|
||||
if (listen(fd, 511) < 0) {
|
||||
perror("Failed to listen");
|
||||
return -1;
|
||||
}
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0) {
|
||||
perror("Failed to enable SO_REUSEADDR");
|
||||
return -1;
|
||||
}
|
||||
if (dup2(fd, 0) < 0) {
|
||||
perror("Failed to move socket to fd 0");
|
||||
return -1;
|
||||
}
|
||||
if (close(fd) < 0) {
|
||||
perror("Failed to close original socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_socket(char *url, gid_t grp) {
|
||||
char *p = url;
|
||||
char *q;
|
||||
int fd;
|
||||
int port;
|
||||
size_t sockaddr_size;
|
||||
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_un sa_un;
|
||||
struct sockaddr_in sa_in;
|
||||
struct sockaddr_in6 sa_in6;
|
||||
} sa;
|
||||
|
||||
if (!strncmp(p, "unix:", sizeof("unix:") - 1)) {
|
||||
p += sizeof("unix:") - 1;
|
||||
|
||||
if (strlen(p) >= UNIX_PATH_MAX) {
|
||||
fprintf(stderr, "Socket path too long, exceeds %d characters\n",
|
||||
UNIX_PATH_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sockaddr_size = sizeof sa.sa_un;
|
||||
sa.sa_un.sun_family = AF_UNIX;
|
||||
strcpy(sa.sa_un.sun_path, p);
|
||||
} else if (!strncmp(p, "tcp:", sizeof("tcp:") - 1)) {
|
||||
p += sizeof("tcp:") - 1;
|
||||
|
||||
q = strchr(p, ':');
|
||||
if (!q) {
|
||||
goto invalid_url;
|
||||
}
|
||||
port = atoi(q+1);
|
||||
if (port <= 0 || port > 65535) {
|
||||
goto invalid_url;
|
||||
}
|
||||
sockaddr_size = sizeof sa.sa_in;
|
||||
sa.sa_in.sin_family = AF_INET;
|
||||
sa.sa_in.sin_port = htons(port);
|
||||
*q = 0;
|
||||
if (inet_pton(AF_INET, p, &sa.sa_in.sin_addr) < 1) {
|
||||
goto invalid_url;
|
||||
}
|
||||
} else if (!strncmp(p, "tcp6:[", sizeof("tcp6:[") - 1)) {
|
||||
p += sizeof("tcp6:[") - 1;
|
||||
q = strchr(p, ']');
|
||||
if (!q || !q[0] || q[1] != ':') {
|
||||
goto invalid_url;
|
||||
}
|
||||
port = atoi(q+2);
|
||||
if (port <= 0 || port > 65535) {
|
||||
goto invalid_url;
|
||||
}
|
||||
sockaddr_size = sizeof sa.sa_in6;
|
||||
sa.sa_in6.sin6_family = AF_INET6;
|
||||
sa.sa_in6.sin6_port = htons(port);
|
||||
*q = 0;
|
||||
if (inet_pton(AF_INET6, p, &sa.sa_in6.sin6_addr) < 1) {
|
||||
goto invalid_url;
|
||||
}
|
||||
} else {
|
||||
invalid_url:
|
||||
fprintf(stderr, "Valid socket URLs are:\n"
|
||||
"unix:/path/to/socket for Unix sockets\n"
|
||||
"tcp:dot.ted.qu.ad:port for IPv4 sockets\n"
|
||||
"tcp6:[ipv6_addr]:port for IPv6 sockets\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = socket(sa.sa.sa_family, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
perror("Failed to create socket");
|
||||
return -1;
|
||||
}
|
||||
if (bind(fd, &sa.sa, sockaddr_size) < 0) {
|
||||
perror("Failed to bind");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen_on_fd(fd) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sa.sa.sa_family == AF_UNIX && grp != -1) {
|
||||
chmod(sa.sa_un.sun_path, S_IRUSR | S_IWUSR | S_IXUSR |
|
||||
S_IRGRP | S_IWGRP | S_IXGRP);
|
||||
if (chown(sa.sa_un.sun_path, -1, grp))
|
||||
perror("Could not change owner of socket");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int nchildren = 1;
|
||||
char *socket_url = NULL;
|
||||
gid_t gid = -1;
|
||||
struct group *grp;
|
||||
int fd = 0;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:hfs:p:g:")) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
stderr_to_fastcgi++;
|
||||
break;
|
||||
case 'h':
|
||||
printf("Usage: %s [OPTION]\nInvokes CGI scripts as FCGI.\n\n"
|
||||
"Options are:\n"
|
||||
" -f\t\t\tSend CGI's stderr over FastCGI\n"
|
||||
" -c <number>\t\tNumber of processes to prefork\n"
|
||||
" -s <socket_url>\tSocket to bind to (say -s help for help)\n"
|
||||
" -h\t\t\tShow this help message and exit\n"
|
||||
" -p <path>\t\tRestrict execution to this script. (repeated options will be merged)\n"
|
||||
" -g group\t\tGrant this group access to unix sockets\n",
|
||||
argv[0]
|
||||
);
|
||||
return 0;
|
||||
case 'c':
|
||||
nchildren = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
socket_url = strdup(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
grp = getgrnam(optarg);
|
||||
if (grp == NULL) {
|
||||
printf("Group %s does not exist\n", optarg);
|
||||
abort();
|
||||
}
|
||||
gid = grp->gr_gid;
|
||||
break;
|
||||
case 'p':
|
||||
allowed_programs = realloc(allowed_programs, (allowed_programs_count + 1) * sizeof (char *));
|
||||
if (!allowed_programs)
|
||||
abort();
|
||||
allowed_programs[allowed_programs_count++] = strdup(optarg);
|
||||
break;
|
||||
case '?':
|
||||
if (optopt == 'c' || optopt == 's' || optopt == 'p')
|
||||
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
|
||||
else if (isprint(optopt))
|
||||
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
|
||||
else
|
||||
fprintf(stderr,
|
||||
"Unknown option character `\\x%x'.\n",
|
||||
optopt);
|
||||
return 1;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
if (sd_listen_fds(true) > 0) {
|
||||
/* systemd woke us up. we should never see more than one FD passed to us. */
|
||||
if (listen_on_fd(SD_LISTEN_FDS_START) < 0) {
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (socket_url) {
|
||||
fd = setup_socket(socket_url, gid);
|
||||
if (fd < 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
prefork(nchildren);
|
||||
fcgiwrap_main();
|
||||
|
||||
if (fd) {
|
||||
const char *p = socket_url;
|
||||
close(fd);
|
||||
|
||||
if (socket_url) {
|
||||
if (!strncmp(p, "unix:", sizeof("unix:") - 1)) {
|
||||
p += sizeof("unix:") - 1;
|
||||
unlink(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2014 nanpuyue <nanpuyue@gmail.com>
|
||||
# Copyright (C) 2017 Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=libdvbcsa
|
||||
PKG_BASE_VERSION:=1.1.0
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/glenvt18/libdvbcsa.git
|
||||
PKG_SOURCE_DATE:=2018-01-28
|
||||
PKG_SOURCE_VERSION:=2a1e61e569a621c55c2426f235f42c2398b7f18f
|
||||
PKG_MIRROR_HASH:=125c5d42fd1c73d3046ab9ee52d11d4c6495a2df45daa3eaf7bc5412dd91d586
|
||||
|
||||
PKG_VERSION:=$(PKG_BASE_VERSION)-$(PKG_SOURCE_DATE)-$(call version_abbrev,$(PKG_SOURCE_VERSION))
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILE:=COPYING
|
||||
PKG_MAINTAINER:=Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/libdvbcsa
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
TITLE:=DVB Common Scrambling Algorithm library
|
||||
URL:=https://www.videolan.org/developers/libdvbcsa.html
|
||||
endef
|
||||
|
||||
define Package/libdvbcsa/description
|
||||
libdvbcsa is a free implementation of the DVB Common Scrambling
|
||||
Algorithm - DVB/CSA - with encryption and decryption capabilities
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
(cd $(PKG_BUILD_DIR); ./bootstrap)
|
||||
$(call Build/Configure/Default)
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
$(CP) $(PKG_INSTALL_DIR)/* $(1)/
|
||||
endef
|
||||
|
||||
define Package/libdvbcsa/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libdvbcsa.so* $(1)/usr/lib/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,libdvbcsa))
|
@ -1,44 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016 Openwrt.org
|
||||
# Copyright (C) 2021 ImmortalWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=minieap
|
||||
PKG_VERSION:=0.93
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/updateing/minieap/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=41c976810c994d6125f6fe3cb1d978f7e257aa587ee32229364942a82621b273
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/minieap
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBNEMU:=Campus Network
|
||||
TITLE:=Extendable 802.1x client
|
||||
URL:=https://github.com/updateing/minieap
|
||||
endef
|
||||
|
||||
define Package/minieap/description
|
||||
Extendable 802.1x client with Ruijie v3 (v4) plugin.
|
||||
endef
|
||||
|
||||
define Package/minieap/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/local/sbin/minieap $(1)/usr/sbin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,minieap))
|
@ -1,13 +0,0 @@
|
||||
--- a/config.mk
|
||||
+++ b/config.mk
|
||||
@@ -17,8 +17,8 @@ PLUGIN_MODULES += if_impl_sockraw
|
||||
# PLUGIN_MODULES += ifaddrs
|
||||
|
||||
ENABLE_DEBUG := false
|
||||
-ENABLE_ICONV := true
|
||||
-ENABLE_GBCONV := false
|
||||
+ENABLE_ICONV := false
|
||||
+ENABLE_GBCONV := true
|
||||
STATIC_BUILD := false
|
||||
|
||||
# If your platform has iconv_* integrated into libc, change to false
|
@ -1,12 +0,0 @@
|
||||
--- a/packet_plugin/rjv3/packet_plugin_rjv3_priv.c
|
||||
+++ b/packet_plugin/rjv3/packet_plugin_rjv3_priv.c
|
||||
@@ -132,7 +132,8 @@ static void rjv3_set_hdd_serial(uint8_t* serial_buf, char* fake_serial) {
|
||||
memmove(serial_buf, fake_serial, strnlen(fake_serial, MAX_PROP_LEN));
|
||||
return;
|
||||
}
|
||||
-#ifdef __linux__
|
||||
+ PR_WARN("请使用 --fake-serial 选项手动指定硬盘序列号");
|
||||
+#if 0
|
||||
FILE* _fp = fopen("/etc/mtab", "r");
|
||||
char _line_buf[MAX_LINE_LEN] = {0};
|
||||
char* _line_buf_dev, *_line_buf_mountpoint;
|
@ -1,11 +0,0 @@
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -87,7 +87,7 @@ install: minieap minieap.1.gz minieap.service
|
||||
install -m 644 minieap.1.gz $(DESTDIR)$(PREFIX)/share/man/man1/
|
||||
install -d $(DESTDIR)$(SYSTEMDDIR)/system/
|
||||
install -m 644 minieap.service $(DESTDIR)$(SYSTEMDDIR)/system/
|
||||
- -systemctl enable minieap
|
||||
+ # -systemctl enable minieap
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
@ -1,39 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ngrokc
|
||||
PKG_VERSION:=1.54
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/dosgo/ngrok-c.git
|
||||
PKG_SOURCE_DATE:=2019-11-02
|
||||
PKG_SOURCE_VERSION:=6388b9d8e4d5fef018ee64dfd55795f10cc6aaad
|
||||
PKG_MIRROR_HASH:=a0f22073807e0ae7869cecce398e848800e5961e00d76a6185f0c1004609f093
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ngrokc
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=Secure tunnels to localhost (C++ port)
|
||||
URL:=https://github.com/dosgo/ngrok-c
|
||||
DEPENDS:=+libc +libpthread +libopenssl +libstdcpp
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
$(CP) $(PKG_BUILD_DIR)/Makefile.openssl $(PKG_BUILD_DIR)/Makefile
|
||||
endef
|
||||
|
||||
define Package/ngrokc/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ngrokc $(1)/usr/bin
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ngrokc))
|
@ -1,40 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=njit8021xclient
|
||||
PKG_BASE_VERSION:=2.0
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/bitdust/njit8021xclient.git
|
||||
PKG_SOURCE_DATE:=2018-11-24
|
||||
PKG_SOURCE_VERSION:=dd28c17f24275bbbf4c44504b832c0f1e6b9ae40
|
||||
PKG_MIRROR_HASH:=66e4f20ceeceaed457657b60ec0b390aab0d7ff380b0abe749738b8f4aa23556
|
||||
|
||||
PKG_VERSION:=$(PKG_BASE_VERSION)-$(PKG_SOURCE_DATE)-$(call version_abbrev,$(PKG_SOURCE_VERSION))
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/njit8021xclient
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Campus Network
|
||||
TITLE:=NJIT 802.1X client program
|
||||
DEPENDS:=+libopenssl +libpcap
|
||||
endef
|
||||
|
||||
define Package/njit8021xclient/description
|
||||
802.1X client from Nanjing Institude of Technology, compatable with
|
||||
H3C iNode 802.1X client. Support H3C/iNode's private authentication
|
||||
protocol V7.10.
|
||||
endef
|
||||
|
||||
define Package/njit8021xclient/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/njit-client $(1)/usr/sbin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,njit8021xclient))
|
@ -1,241 +0,0 @@
|
||||
menu "OSCam build options"
|
||||
depends on PACKAGE_oscam
|
||||
|
||||
config OSCAM_USE_LIBCRYPTO
|
||||
bool "Build with OpenSSL libcrypto"
|
||||
help
|
||||
"Use OpenSSL libcrypto instead of OSCam internal crypto functions"
|
||||
default y
|
||||
|
||||
config OSCAM_USE_LIBUSB
|
||||
bool
|
||||
default y
|
||||
|
||||
menu "Protocols"
|
||||
depends on PACKAGE_oscam
|
||||
|
||||
config OSCAM_MODULE_CAMD33
|
||||
bool "camd 3.3"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_CAMD35
|
||||
bool "camd 3.5 UDP"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_CAMD35_TCP
|
||||
bool "camd 3.5 TCP"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_NEWCAMD
|
||||
bool "newcamd"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_CCCAM
|
||||
bool "CCcam"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_CCCSHARE
|
||||
bool "CCcam share"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_GBOX
|
||||
bool "gbox"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_RADEGAST
|
||||
bool "radegast"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_SERIAL
|
||||
bool "Serial"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_CONSTCW
|
||||
bool "constant CW"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_PANDORA
|
||||
bool "Pandora"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_GHTTP
|
||||
bool "Ghttp"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_SCAM
|
||||
bool "scam"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Readers"
|
||||
depends on PACKAGE_oscam
|
||||
|
||||
config OSCAM_READER_NAGRA
|
||||
bool "Nagravision"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_IRDETO
|
||||
bool "Irdeto"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_CONAX
|
||||
bool "Conax"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_CRYPTOWORKS
|
||||
bool "Cryptoworks"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_SECA
|
||||
bool "Seca"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_VIACCESS
|
||||
bool "Viaccess"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_VIDEOGUARD
|
||||
bool "NDS Videoguard"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_DRE
|
||||
bool "DRE Crypt"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_TONGFANG
|
||||
bool "Tongfang"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_BULCRYPT
|
||||
bool "Bulcrypt"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_GRIFFIN
|
||||
bool "Griffin"
|
||||
default y
|
||||
|
||||
config OSCAM_READER_DGCRYPT
|
||||
bool "DGCrypt"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Card readers"
|
||||
depends on PACKAGE_oscam
|
||||
|
||||
config OSCAM_USE_PCSC
|
||||
bool "PCSC compatible readers"
|
||||
select OSCAM_USE_LIBUSB
|
||||
default y
|
||||
|
||||
config OSCAM_CARDREADER_PHOENIX
|
||||
bool "Phoenix/mouse USB readers"
|
||||
select OSCAM_USE_LIBUSB
|
||||
default y
|
||||
|
||||
config OSCAM_CARDREADER_SC8IN1
|
||||
bool "SC8in1"
|
||||
select OSCAM_USE_LIBUSB
|
||||
default y
|
||||
|
||||
config OSCAM_CARDREADER_MP35
|
||||
bool "AD-Teknik MP 3.6/USB Phoenix"
|
||||
select OSCAM_USE_LIBUSB
|
||||
default y
|
||||
|
||||
config OSCAM_CARDREADER_SMARGO
|
||||
bool "Argolis Smargo Smartreader"
|
||||
select OSCAM_USE_LIBUSB
|
||||
default y
|
||||
|
||||
config OSCAM_CARDREADER_STINGER
|
||||
bool "Stinger USB Dual Smartcard Reader"
|
||||
select OSCAM_USE_LIBUSB
|
||||
default y
|
||||
|
||||
config OSCAM_CARDREADER_DRECAS
|
||||
bool "DRECAS reader"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
comment "Addons"
|
||||
config OSCAM_HAVE_DVBAPI
|
||||
bool "DVB API"
|
||||
default y
|
||||
|
||||
config OSCAM_READ_SDT_CHARSETS
|
||||
bool "DVB API read-sdt charsets"
|
||||
default y
|
||||
|
||||
config OSCAM_IRDETO_GUESSING
|
||||
bool "Irdeto guessing"
|
||||
default y
|
||||
|
||||
config OSCAM_CS_ANTICASC
|
||||
bool "Anti cascading"
|
||||
default y
|
||||
|
||||
config OSCAM_WITH_DEBUG
|
||||
bool "Debug messages"
|
||||
default y
|
||||
|
||||
config OSCAM_MODULE_MONITOR
|
||||
bool "Monitor"
|
||||
default y
|
||||
|
||||
config OSCAM_WITH_LB
|
||||
bool "Loadbalancing"
|
||||
default y
|
||||
|
||||
config OSCAM_S_CACHEEX
|
||||
bool "Cache exchange"
|
||||
default y
|
||||
|
||||
config OSCAM_CW_CYCLE_CHECK
|
||||
bool "CW Cycle Check"
|
||||
default y
|
||||
|
||||
config OSCAM_LCDSUPPORT
|
||||
bool "LCD support"
|
||||
default n
|
||||
|
||||
config OSCAM_LEDSUPPORT
|
||||
bool "LED support"
|
||||
default n
|
||||
|
||||
config OSCAM_CLOCKFIX
|
||||
bool "Clockfix (disable on old systems!)"
|
||||
default y
|
||||
|
||||
config OSCAM_IPV6SUPPORT
|
||||
bool "IPv6 support (experimental)"
|
||||
default n
|
||||
|
||||
config OSCAM_WEBIF
|
||||
bool "Web Interface"
|
||||
default y
|
||||
|
||||
config OSCAM_WEBIF_LIVELOG
|
||||
bool "LiveLog"
|
||||
depends on OSCAM_WEBIF
|
||||
default y
|
||||
|
||||
config OSCAM_WEBIF_JQUERY
|
||||
bool "Jquery onboard (if disabled webload)"
|
||||
depends on OSCAM_WEBIF
|
||||
default y
|
||||
|
||||
config OSCAM_TOUCH
|
||||
bool "Touch Web Interface"
|
||||
depends on OSCAM_WEBIF
|
||||
default y
|
||||
|
||||
config OSCAM_WITH_SSL
|
||||
bool "SSL support"
|
||||
depends on OSCAM_WEBIF
|
||||
select OSCAM_USE_LIBCRYPTO
|
||||
default y
|
||||
|
||||
endmenu
|
@ -1,156 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016-2017 Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=oscam
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/nx111/oscam.git
|
||||
PKG_SOURCE_DATE:=2020-12-12
|
||||
PKG_SOURCE_VERSION:=aafda4bca3c347698ef1dc32f7ebeff76378d55a
|
||||
PKG_MIRROR_HASH:=d2cd4508ef80a3cbd8ef950e5446f2f754b339f179c4f774ef8660b39fd5c4c1
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILE:=COPYING
|
||||
PKG_MAINTAINER:=Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/oscam/config
|
||||
source "$(SOURCE)/Config.in"
|
||||
endef
|
||||
|
||||
define Package/oscam
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Open Source Conditional Access Modul
|
||||
URL:=http://www.streamboard.tv/oscam
|
||||
DEPENDS:=+OSCAM_USE_LIBCRYPTO:libopenssl +OSCAM_USE_LIBUSB:libusb-1.0 +OSCAM_USE_PCSC:pcscd
|
||||
endef
|
||||
|
||||
define Package/list-smargo
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=List Smargo readers
|
||||
URL:=http://www.streamboard.tv/oscam
|
||||
DEPENDS:=oscam @OSCAM_CARDREADER_SMARGO
|
||||
endef
|
||||
|
||||
CONFIGURE_CMD:=./config.sh
|
||||
CONFIGURE_ARGS+= \
|
||||
--restore \
|
||||
$(if $(CONFIG_OSCAM_WEBIF),--enable,--disable) WEBIF \
|
||||
$(if $(CONFIG_OSCAM_WEBIF_LIVELOG),--enable,--disable) WEBIF_LIVELOG \
|
||||
$(if $(CONFIG_OSCAM_WEBIF_JQUERY),--enable,--disable) WEBIF_JQUERY \
|
||||
$(if $(CONFIG_OSCAM_TOUCH),--enable,--disable) TOUCH \
|
||||
$(if $(CONFIG_OSCAM_WITH_SSL),--enable,--disable) WITH_SSL \
|
||||
$(if $(CONFIG_OSCAM_HAVE_DVBAPI),--enable,--disable) HAVE_DVBAPI \
|
||||
$(if $(CONFIG_OSCAM_READ_SDT_CHARSETS),--enable,--disable) READ_SDT_CHARSETS \
|
||||
$(if $(CONFIG_OSCAM_IRDETO_GUESSING),--enable,--disable) IRDETO_GUESSING \
|
||||
$(if $(CONFIG_OSCAM_CS_ANTICASC),--enable,--disable) CS_ANTICASC \
|
||||
$(if $(CONFIG_OSCAM_WITH_DEBUG),--enable,--disable) WITH_DEBUG \
|
||||
$(if $(CONFIG_OSCAM_MODULE_MONITOR),--enable,--disable) MODULE_MONITOR \
|
||||
$(if $(CONFIG_OSCAM_WITH_LB),--enable,--disable) WITH_LB \
|
||||
$(if $(CONFIG_OSCAM_CS_CACHEEX),--enable,--disable) CS_CACHEEX \
|
||||
$(if $(CONFIG_OSCAM_CW_CYCLE_CHECK),--enable,--disable) CW_CYCLE_CHECK \
|
||||
$(if $(CONFIG_OSCAM_LCDSUPPORT),--enable,--disable) LCDSUPPORT \
|
||||
$(if $(CONFIG_OSCAM_LEDSUPPORT),--enable,--disable) LEDSUPPORT \
|
||||
$(if $(CONFIG_OSCAM_CLOCKFIX),--enable,--disable) CLOCKFIX \
|
||||
$(if $(CONFIG_OSCAM_IPV6SUPPORT),--enable,--disable) IPV6SUPPORT \
|
||||
$(if $(CONFIG_OSCAM_MODULE_CAMD33),--enable,--disable) MODULE_CAMD33 \
|
||||
$(if $(CONFIG_OSCAM_MODULE_CAMD35),--enable,--disable) MODULE_CAMD35 \
|
||||
$(if $(CONFIG_OSCAM_MODULE_CAMD35_TCP),--enable,--disable) MODULE_CAMD35_TCP \
|
||||
$(if $(CONFIG_OSCAM_MODULE_NEWCAMD),--enable,--disable) MODULE_NEWCAMD \
|
||||
$(if $(CONFIG_OSCAM_MODULE_CCCAM),--enable,--disable) MODULE_CCCAM \
|
||||
$(if $(CONFIG_OSCAM_MODULE_CCCSHARE),--enable,--disable) MODULE_CCCSHARE \
|
||||
$(if $(CONFIG_OSCAM_MODULE_GBOX),--enable,--disable) MODULE_GBOX \
|
||||
$(if $(CONFIG_OSCAM_MODULE_RADEGAST),--enable,--disable) MODULE_RADEGAST \
|
||||
$(if $(CONFIG_OSCAM_MODULE_SCAM),--enable,--disable) MODULE_SCAM \
|
||||
$(if $(CONFIG_OSCAM_MODULE_SERIAL),--enable,--disable) MODULE_SERIAL \
|
||||
$(if $(CONFIG_OSCAM_MODULE_CONSTCW),--enable,--disable) MODULE_CONSTCW \
|
||||
$(if $(CONFIG_OSCAM_MODULE_PANDORA),--enable,--disable) MODULE_PANDORA \
|
||||
$(if $(CONFIG_OSCAM_MODULE_GHTTP),--enable,--disable) MODULE_GHTTP \
|
||||
$(if $(CONFIG_OSCAM_READER_NAGRA),--enable,--disable) READER_NAGRA \
|
||||
$(if $(CONFIG_OSCAM_READER_IRDETO),--enable,--disable) READER_IRDETO \
|
||||
$(if $(CONFIG_OSCAM_READER_CONAX),--enable,--disable) READER_CONAX \
|
||||
$(if $(CONFIG_OSCAM_READER_CRYPTOWORKS),--enable,--disable) READER_CRYPTOWORKS \
|
||||
$(if $(CONFIG_OSCAM_READER_SECA),--enable,--disable) READER_SECA \
|
||||
$(if $(CONFIG_OSCAM_READER_VIACCESS),--enable,--disable) READER_VIACCESS \
|
||||
$(if $(CONFIG_OSCAM_READER_VIDEOGUARD),--enable,--disable) READER_VIDEOGUARD \
|
||||
$(if $(CONFIG_OSCAM_READER_DRE),--enable,--disable) READER_DRE \
|
||||
$(if $(CONFIG_OSCAM_READER_TONGFANG),--enable,--disable) READER_TONGFANG \
|
||||
$(if $(CONFIG_OSCAM_READER_BULCRYPT),--enable,--disable) READER_BULCRYPT \
|
||||
$(if $(CONFIG_OSCAM_READER_GRIFFIN),--enable,--disable) READER_GRIFFIN \
|
||||
$(if $(CONFIG_OSCAM_READER_DGCRYPT),--enable,--disable) READER_DGCRYPT \
|
||||
$(if $(CONFIG_OSCAM_CARDREADER_PHOENIX),--enable,--disable) CARDREADER_PHOENIX \
|
||||
$(if $(CONFIG_OSCAM_CARDREADER_SC8IN1),--enable,--disable) CARDREADER_SC8IN1 \
|
||||
$(if $(CONFIG_OSCAM_CARDREADER_MP35),--enable,--disable) CARDREADER_MP35 \
|
||||
$(if $(CONFIG_OSCAM_CARDREADER_SMARGO),--enable,--disable) CARDREADER_SMARGO \
|
||||
$(if $(CONFIG_OSCAM_CARDREADER_STINGER),--enable,--disable) CARDREADER_STINGER \
|
||||
$(if $(CONFIG_OSCAM_CARDREADER_DRECAS),--enable,--disable) CARDREADER_DRECAS \
|
||||
--disable CARDREADER_INTERNAL_AZBOX \
|
||||
--disable CARDREADER_INTERNAL_COOLAPI \
|
||||
--disable CARDREADER_INTERNAL_COOLAPI2 \
|
||||
--disable CARDREADER_INTERNAL_SCI \
|
||||
--disable CARDREADER_DB2COM \
|
||||
--disable CARDREADER_STAPI \
|
||||
--disable CARDREADER_STAPI5
|
||||
|
||||
ifeq ($(CONFIG_OSCAM_USE_LIBUSB),y)
|
||||
MAKE_FLAGS += USE_LIBUSB=1
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_OSCAM_USE_PCSC),y)
|
||||
MAKE_FLAGS += USE_PCSC=1
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_OSCAM_USE_LIBCRYPTO),y)
|
||||
MAKE_FLAGS += USE_LIBCRYPTO=1
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_OSCAM_WITH_SSL),y)
|
||||
MAKE_FLAGS += USE_SSL=1
|
||||
endif
|
||||
|
||||
MAKE_FLAGS += \
|
||||
CONF_DIR=/etc/oscam \
|
||||
OSCAM_BIN=Distribution/oscam \
|
||||
LIST_SMARGO_BIN=Distribution/list-smargo
|
||||
|
||||
define Package/oscam/conffiles
|
||||
/etc/oscam/
|
||||
endef
|
||||
|
||||
define Package/oscam/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/Distribution/oscam $(1)/usr/bin/oscam
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/oscam
|
||||
# $(CP) $(PKG_BUILD_DIR)/Distribution/doc/example/* $(1)/etc/oscam/
|
||||
$(INSTALL_CONF) ./files/oscam.conf $(1)/etc/oscam/oscam.conf
|
||||
$(INSTALL_CONF) ./files/oscam.user $(1)/etc/oscam/oscam.user
|
||||
$(INSTALL_CONF) ./files/oscam.dvbapi $(1)/etc/oscam/oscam.dvbapi
|
||||
$(INSTALL_CONF) ./files/oscam.server $(1)/etc/oscam/oscam.server
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/oscam.init $(1)/etc/init.d/oscam
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/share/oscam
|
||||
$(INSTALL_BIN) ./files/oscam-watchdog.sh $(1)/usr/share/oscam/oscam-watchdog.sh
|
||||
|
||||
endef
|
||||
|
||||
define Package/list-smargo/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/Distribution/list-smargo $(1)/usr/bin/list-smargo
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,oscam))
|
||||
$(eval $(call BuildPackage,list-smargo))
|
@ -1,31 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
sleeptime=60
|
||||
logfile="/var/log/oscam.log"
|
||||
OSCAM_PATH=/usr/bin
|
||||
enable=$(uci get oscam.config.enabled 2>/dev/null)
|
||||
|
||||
oscam_log(){
|
||||
logrow=$(grep -c "" ${logfile})
|
||||
if [ $logrow -ge 500 ];then
|
||||
cat /dev/null > ${logfile}
|
||||
echo "$curtime Log条数超限,清空处理!" >> ${logfile}
|
||||
fi
|
||||
}
|
||||
|
||||
while [ $enable -eq 1 ];
|
||||
do
|
||||
oscam_log
|
||||
curtime=`date "+%H:%M:%S"`
|
||||
echo "$curtime online! "
|
||||
|
||||
if ! pidof oscam>/dev/null; then
|
||||
service_start ${OSCAM_PATH}/oscam -b -r 2 -u
|
||||
echo "$curtime 重启服务!" >> ${logfile}
|
||||
fi
|
||||
|
||||
sleep ${sleeptime}
|
||||
continue
|
||||
done
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
# oscam.conf generated automatically by Streamboard OSCAM 1.20-unstable_svn SVN r11390
|
||||
# Read more: http://www.streamboard.tv/svn/oscam/trunk/Distribution/doc/txt/oscam.conf.txt
|
||||
|
||||
[global]
|
||||
disablelog = 1
|
||||
logfile = /var/log/oscam/oscam.log
|
||||
nice = 0
|
||||
maxlogsize = 1000
|
||||
preferlocalcards = 1
|
||||
lb_mode = 3
|
||||
lb_min_ecmcount = 8
|
||||
|
||||
[cache]
|
||||
|
||||
[dvbapi]
|
||||
enabled = 1
|
||||
au = 1
|
||||
pmt_mode = 4
|
||||
request_mode = 1
|
||||
listen_port = 9000
|
||||
delayer = 80
|
||||
user = TVH
|
||||
boxtype = pc
|
||||
|
||||
[camd33]
|
||||
port = 44444
|
||||
serverip = 127.0.0.1
|
||||
nocrypt = 127.0.0.1
|
||||
|
||||
[cccam]
|
||||
port = 12000
|
||||
nodeid = 178EC950108E1442
|
||||
version = 2.3.0
|
||||
reshare = 1
|
||||
ignorereshare = 1
|
||||
stealth = 1
|
||||
|
||||
[webif]
|
||||
httpport = 8888
|
||||
httpuser = oscam
|
||||
httppwd = oscam
|
||||
httpshowmeminfo = 1
|
||||
httpshowuserinfo = 1
|
||||
httpshowecminfo = 1
|
||||
httpshowloadinfo = 1
|
||||
httpallowed = 0.0.0.0-255.255.255.255
|
||||
aulow = 120
|
||||
httputf8
|
@ -1,31 +0,0 @@
|
||||
P: 0500:040620 # NTV+ (36Е)
|
||||
P: 0500:041200 # NTV+ (36Е)
|
||||
P: 0500:060A00 # NTV+ (36E)
|
||||
P: 0500:060C00 # NTV+ (36E)
|
||||
P: 0500:023100 # trk football (Shara)(5Е)
|
||||
P: 0500:041200 # trk football (Shara)(5Е)
|
||||
P: 0500:041700 # Dorcel TV (13Е)
|
||||
P: 0500:042300 # rtvi (13Е)
|
||||
P: 0500:042700 # SCT, S1-7-HQ,HD (13Е)
|
||||
P: 0500:042800 # Absat/BisTV (13Е)
|
||||
P: 0500:043800 # REDLIGHT HD, Redlight Premium & Daring! TV (13Е)
|
||||
P: 0100:000068 # Cyfra+ 13e
|
||||
P: 09CD:0 # Sky 13e
|
||||
P: 1803:007001 # Polsat (13Е)
|
||||
P: 1803:007101 # Polsat (13Е)
|
||||
P: 1803:000000 # Polsat (13Е)
|
||||
P: 090D:0 # yes 4w
|
||||
P: 090F:0 # viasat baltic 5e
|
||||
|
||||
# EMU
|
||||
P: 2600:000000 # BISS
|
||||
P: 0500:023800 # srg (EMU)(13Е)
|
||||
P: 0E00:000000 # PowerVU
|
||||
P: 0500:007400
|
||||
P: 0D00:000000
|
||||
P: 0D05:000000
|
||||
P: 0D02:000000
|
||||
P: 1801:000000
|
||||
|
||||
# Ignor
|
||||
I:0
|
@ -1,45 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
OSCAM_PATH=/usr/bin
|
||||
|
||||
[ -f /tmp/oscam ] &&
|
||||
{
|
||||
OSCAM_PATH=/tmp
|
||||
[ -x /tmp/oscam ] || chmod +x /tmp/oscam
|
||||
}
|
||||
|
||||
start() {
|
||||
enable=$(uci get oscam.config.enabled 2>/dev/null)
|
||||
kill -9 $(ps | grep oscam-watchdog.sh | grep -v "grep" | awk '{print $1}') >/dev/null 2>&1
|
||||
if [ $enable -eq 1 ]; then
|
||||
/etc/init.d/pcscd enable
|
||||
/etc/init.d/pcscd start
|
||||
if pidof oscam >/dev/null; then
|
||||
kill $(pidof oscam) >/dev/null 2>&1 || killall -9 oscam >/dev/null 2>&1
|
||||
sleep 1
|
||||
fi
|
||||
echo "enable"
|
||||
[ -d /var/log/oscam ] || mkdir -p /var/log/oscam
|
||||
service_start ${OSCAM_PATH}/oscam -b -r 2 -u
|
||||
nohup /usr/share/oscam/oscam-watchdog.sh > /var/log/oscam.log 2>&1 &
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
enable=$(uci get oscam.config.enabled 2>/dev/null)
|
||||
if [ $enable -ne 1 ]; then
|
||||
echo "stop!"
|
||||
kill -9 $(ps | grep oscam-watchdog.sh | grep -v "grep" | awk '{print $1}') >/dev/null 2>&1
|
||||
kill $(pidof oscam) >/dev/null 2>&1 || killall -9 oscam >/dev/null 2>&1
|
||||
/etc/init.d/pcscd stop
|
||||
/etc/init.d/pcscd disable
|
||||
fi
|
||||
}
|
||||
|
||||
restart(){
|
||||
stop
|
||||
sleep 2
|
||||
start
|
||||
echo "oscam Server has restarted."
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# oscam.server generated automatically by Streamboard OSCAM 1.20-unstable_svn SVN r11401
|
||||
# Read more: http://www.streamboard.tv/svn/oscam/trunk/Distribution/doc/txt/oscam.server.txt
|
||||
|
||||
[reader]
|
||||
label = emulator
|
||||
protocol = emu
|
||||
device = emulator
|
||||
caid = 0D00,0D02,090F,0500,1801,0604,2600,FFFF,0E00
|
||||
detect = cd
|
||||
ident = 0D00:000000,000004,000010,000014,000020,0000C0,0000C4,0000C8,0000CC;0D02:000000,00008C,0000A0,0000A4,0000A8;090F:000000;0500:000000,030B00,023800,021110,007400,007800;1801:000000,007301,001101;0604:000000;2600:000000;FFFF:000000;0E00:000000
|
||||
group = 1
|
||||
emmcache = 2,3,2,0
|
||||
emu_auproviders = 0500:030B00;0604:010200;0E00:000000
|
||||
|
@ -1,27 +0,0 @@
|
||||
# oscam.user generated automatically by Streamboard OSCAM 1.20-unstable_svn SVN r11401
|
||||
# Read more: http://www.streamboard.tv/svn/oscam/trunk/Distribution/doc/txt/oscam.user.txt
|
||||
|
||||
[account]
|
||||
user = tvheadend_x
|
||||
pwd = tvheadend_x
|
||||
monlevel = 4
|
||||
au = 1
|
||||
group = 1
|
||||
max_connections = 100
|
||||
cccreshare = 1
|
||||
|
||||
[account]
|
||||
user = user1
|
||||
pwd = user1
|
||||
monlevel = 4
|
||||
au = 1
|
||||
group = 1
|
||||
max_connections = 100
|
||||
cccreshare = 1
|
||||
|
||||
[account]
|
||||
user = monitor
|
||||
pwd = monitor
|
||||
monlevel = 4
|
||||
group = 1
|
||||
|
@ -1,149 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015-2018 wongsyrone
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=pcap-dnsproxy
|
||||
PKG_BASE_VERSION:=0.4.9.13
|
||||
PKG_RELEASE:=$(AUTORELESE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/1715173329/Pcap_DNSProxy.git
|
||||
PKG_SOURCE_DATE:=2019-05-05
|
||||
PKG_SOURCE_VERSION:=bc9f540d9febc5f61d24d583dbdbcc858dd817e3
|
||||
PKG_MIRROR_HASH:=416cea47ef5662c32111c56eeaaaaec4b338e6eddfe98fca0a0d854e00653dc3
|
||||
|
||||
PKG_VERSION:=$(PKG_BASE_VERSION)-$(PKG_SOURCE_DATE)-$(call version_abbrev,$(PKG_SOURCE_VERSION))
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=Chengr28 <chengr28@gmail.com>
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PCAP_DNSPROXY_LIBSODIUM \
|
||||
CONFIG_PCAP_DNSPROXY_LIBPCAP \
|
||||
CONFIG_PCAP_DNSPROXY_TLS \
|
||||
CONFIG_PCAP_DNSPROXY_LISTENPORT
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
TARGET_CXXFLAGS += -Wall -Wextra
|
||||
TARGET_CXXFLAGS += $(FPIC)
|
||||
|
||||
# redef CFLAGS and CXXFLAGS, replace -O* with -O3
|
||||
TARGET_CFLAGS := $(filter-out -O%,$(TARGET_CFLAGS)) -O3
|
||||
TARGET_CXXFLAGS := $(filter-out -O%,$(TARGET_CXXFLAGS)) -O3
|
||||
|
||||
# CXX standard
|
||||
TARGET_CXXFLAGS += -std=c++14
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DPLATFORM_OPENWRT=ON \
|
||||
-DENABLE_LIBSODIUM=$(if $(CONFIG_PCAP_DNSPROXY_LIBSODIUM),ON,OFF) \
|
||||
-DENABLE_PCAP=$(if $(CONFIG_PCAP_DNSPROXY_LIBPCAP),ON,OFF) \
|
||||
-DENABLE_TLS=$(if $(CONFIG_PCAP_DNSPROXY_TLS),ON,OFF)
|
||||
|
||||
define Package/pcap-dnsproxy/config
|
||||
config PCAP_DNSPROXY_LIBPCAP
|
||||
bool "Build with libpcap support.(Strongly recommended)"
|
||||
default y
|
||||
help
|
||||
LibPcap is for packet capture, Pcap_DNSProxy takes advantage
|
||||
of it to detect poisoned DNS reply.
|
||||
|
||||
We strongly recommend to keep it as-is.
|
||||
|
||||
config PCAP_DNSPROXY_LIBSODIUM
|
||||
bool "Build with libsodium support.(Recommended)"
|
||||
default y
|
||||
help
|
||||
LibSodium is for DNSCurve/DNSCrypt protocol support.
|
||||
|
||||
We recommend to keep it as-is unless you do NOT
|
||||
need this protocol anymore.
|
||||
|
||||
config PCAP_DNSPROXY_TLS
|
||||
bool "Build with TLS support.(Recommended)"
|
||||
default y
|
||||
help
|
||||
We recommend to keep it as-is.
|
||||
|
||||
config PCAP_DNSPROXY_LISTENPORT
|
||||
int "Listen Port, should NOT be 53"
|
||||
default 1053
|
||||
help
|
||||
You can customize the listen port of Pcap_DNSProxy.
|
||||
Note that you should NOT set the value to 53, which
|
||||
conflicts with DNSMasq in OpenWrt.
|
||||
endef
|
||||
|
||||
define Package/pcap-dnsproxy
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=A local DNS server based on LibPcap
|
||||
URL:=https://github.com/chengr28/Pcap_DNSProxy
|
||||
DEPENDS:=+libpthread +libstdcpp +libevent2-core \
|
||||
+PCAP_DNSPROXY_LIBPCAP:libpcap \
|
||||
+PCAP_DNSPROXY_LIBSODIUM:libsodium \
|
||||
+PCAP_DNSPROXY_TLS:libopenssl
|
||||
endef
|
||||
|
||||
define Package/pcap-dnsproxy/conffiles
|
||||
/etc/pcap-dnsproxy/Config.conf
|
||||
/etc/pcap-dnsproxy/Hosts.conf
|
||||
/etc/pcap-dnsproxy/IPFilter.conf
|
||||
/etc/pcap-dnsproxy/Routing.txt
|
||||
/etc/pcap-dnsproxy/WhiteList.txt
|
||||
endef
|
||||
|
||||
define Package/pcap-dnsproxy/postinst
|
||||
#!/bin/sh
|
||||
# check if we are on real system
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
echo "Be sure to set configuration file(s) before rebooting your router."
|
||||
/etc/init.d/pcap-dnsproxy enable
|
||||
fi
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Package/pcap-dnsproxy/prerm
|
||||
#!/bin/sh
|
||||
# check if we are on real system
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
echo "Stopping service and removing rc.d symlink for pcap-dnsproxy"
|
||||
/etc/init.d/pcap-dnsproxy stop
|
||||
/etc/init.d/pcap-dnsproxy disable
|
||||
fi
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Package/pcap-dnsproxy/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/Pcap_DNSProxy $(1)/usr/sbin/Pcap_DNSProxy
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_DATA) ./files/pcap-dnsproxy.config $(1)/etc/config/pcap-dnsproxy
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/pcap-dnsproxy.procd.init $(1)/etc/init.d/pcap-dnsproxy
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_BIN) ./files/pcap-dnsproxy.hotplug $(1)/etc/hotplug.d/iface/99-pcap-dnsproxy
|
||||
$(INSTALL_DIR) $(1)/etc/pcap-dnsproxy
|
||||
$(SED) 's,^\xEF\xBB\xBF,,g' $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/*
|
||||
$(SED) 's,\x0D,,g' $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/*
|
||||
$(SED) 's,Listen Port = 53,Listen Port = $(CONFIG_PCAP_DNSPROXY_LISTENPORT),g' $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/Config.ini
|
||||
$(SED) 's,Log Maximum Size = 8MB,Log Maximum Size = 50KB,g' $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/Config.ini
|
||||
$(SED) 's,Operation Mode = Private,Operation Mode = Server,g' $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/Config.ini
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/Config.ini $(1)/etc/pcap-dnsproxy/Config.conf
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/Hosts.ini $(1)/etc/pcap-dnsproxy/Hosts.conf
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/IPFilter.ini $(1)/etc/pcap-dnsproxy/IPFilter.conf
|
||||
$(INSTALL_CONF) $(PKG_BUILD_DIR)/Source/Auxiliary/ExampleConfig/Routing.txt $(1)/etc/pcap-dnsproxy/Routing.txt
|
||||
$(INSTALL_CONF) ./files/configs/WhiteList.txt $(1)/etc/pcap-dnsproxy/WhiteList.txt
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,pcap-dnsproxy))
|
@ -1,4 +0,0 @@
|
||||
[Local Hosts]
|
||||
## China mainland domains
|
||||
## Notice: Due to increasing ipk size, we will not ship this domain list anymore
|
||||
## Please download from https://github.com/chengr28/Pcap_DNSProxy/tree/master/Source/Auxiliary/ExampleConfig
|
@ -1,4 +0,0 @@
|
||||
|
||||
config pcap-dnsproxy
|
||||
option enabled '0'
|
||||
|
@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
# get config entity via UCI
|
||||
enabled=$(uci -q get pcap-dnsproxy.@pcap-dnsproxy[0].enabled)
|
||||
[ "1" = "$enabled" ] || [ "on" = "$enabled" ] || [ "true" = "$enabled" ] || exit 0
|
||||
[ "$INTERFACE" = wan ] || exit 0
|
||||
# We only handle 'ifup' and 'ifdown' events
|
||||
[ "$ACTION" = ifup ] || [ "$ACTION" = ifdown ] || exit 1
|
||||
# Exit if we don't have logger, this should not happen
|
||||
[ -x /usr/bin/logger ] || exit 2
|
||||
|
||||
# only start if boot_delay is done
|
||||
[ -f /tmp/pcap-dnsproxy.hotplug ] || exit 0
|
||||
|
||||
case "$ACTION" in
|
||||
ifup)
|
||||
# Restart, the default delay is 5 secs
|
||||
# This hotplug script should be the last to execute
|
||||
# due to high load on router
|
||||
logger -p daemon.info -t "Pcap_DNSProxy" \
|
||||
"Start request sent due to '$ACTION' of '$INTERFACE'"
|
||||
/etc/init.d/pcap-dnsproxy start
|
||||
;;
|
||||
ifdown)
|
||||
# Shutdown
|
||||
logger -p daemon.info -t "Pcap_DNSProxy" \
|
||||
"Shutdown request sent due to '$ACTION' of '$INTERFACE'"
|
||||
/etc/init.d/pcap-dnsproxy stop
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
@ -1,107 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2016-2017 wongsyrone
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
START=95
|
||||
USE_PROCD=1
|
||||
#PROCD_DEBUG=1
|
||||
|
||||
extra_command "flush" "Flush DNS cache stored in Pcap_DNSProxy and DNSMasq"
|
||||
extra_command "libver" "Print library version Pcap_DNSProxy linked to"
|
||||
extra_command "status" "Show the running status of Pcap_DNSProxy"
|
||||
|
||||
PROG=/usr/sbin/Pcap_DNSProxy
|
||||
CONFDIR=/etc/pcap-dnsproxy
|
||||
HOTPLUGFILE=/tmp/pcap-dnsproxy.hotplug
|
||||
ERRLOG=/tmp/pcap-dnsproxy-error.log
|
||||
|
||||
config_load "pcap-dnsproxy"
|
||||
|
||||
parse_pcap_dnsproxy()
|
||||
{
|
||||
config_get ENABLED "$section" "enabled"
|
||||
}
|
||||
|
||||
config_foreach parse_pcap_dnsproxy 'pcap-dnsproxy'
|
||||
|
||||
shutdown() {
|
||||
rm -f $HOTPLUGFILE
|
||||
stop
|
||||
}
|
||||
|
||||
start_service() {
|
||||
if [ "1" = "$ENABLED" ] || [ "on" = "$ENABLED" ] || [ "true" = "$ENABLED" ]; then
|
||||
[ $(ps|grep ${PROG}|grep -v grep|wc -l) -ge 1 ] && {
|
||||
echo "Pcap_DNSProxy is already running, no need to start again"
|
||||
exit 1
|
||||
}
|
||||
[ -f "$ERRLOG" ] && {
|
||||
echo "Removing previous ${ERRLOG##*/}"
|
||||
rm -f "$ERRLOG" >/dev/null 2>&1
|
||||
}
|
||||
# do NOT use daemon code inside pcap-dnsproxy, use start-stop-daemon instead
|
||||
# procd requires running in Foreground
|
||||
procd_open_instance
|
||||
procd_set_param command $PROG --config-path $CONFDIR --disable-daemon --log-file $ERRLOG
|
||||
procd_set_param file $CONFDIR/Config.conf
|
||||
procd_append_param file $CONFDIR/Hosts.conf
|
||||
procd_append_param file $CONFDIR/IPFilter.conf
|
||||
procd_append_param file $CONFDIR/Routing.txt
|
||||
procd_append_param file $CONFDIR/WhiteList.txt
|
||||
procd_set_param user root # run service as user root
|
||||
procd_set_param stdout 1 # forward stdout of the command to logd
|
||||
procd_set_param stderr 1 # same for stderr
|
||||
procd_set_param limits nofile="unlimited"
|
||||
[ -e /proc/sys/kernel/core_pattern ] && {
|
||||
procd_append_param limits core="unlimited"
|
||||
}
|
||||
procd_close_instance
|
||||
# create hotplug mark, it will update the last-modified date if the file exists
|
||||
touch $HOTPLUGFILE
|
||||
# wait to check error log file
|
||||
sleep 1s
|
||||
[ -f "$ERRLOG" ] \
|
||||
&& echo "WARNING: ${ERRLOG##*/} exists, check its content and other config files in ${CONFDIR}"
|
||||
else
|
||||
echo "Pcap_DNSProxy is disabled, please check /etc/config/pcap-dnsproxy for more info"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
rm -rf "/tmp/pcap_dnsproxy_fifo"
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "pcap-dnsproxy"
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
stop
|
||||
sleep 3s
|
||||
start
|
||||
}
|
||||
|
||||
flush() {
|
||||
if [ $(ps|grep ${PROG}|grep -v grep|wc -l) -ge 1 ]; then
|
||||
local _PID=$(pidof ${PROG##*/})
|
||||
$PROG --flush-dns
|
||||
logger -p daemon.notice -t "Pcap_DNSProxy[$_PID]" "Flush message sent"
|
||||
else
|
||||
echo "Pcap_DNSProxy is not running, I can NOT flush DNS cache for you."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
libver() {
|
||||
$PROG --lib-version
|
||||
}
|
||||
|
||||
status() {
|
||||
if [ $(ps|grep ${PROG}|grep -v grep|wc -l) -ge 1 ]; then
|
||||
echo "Pcap_DNSProxy is running, PID is $(pidof ${PROG##*/})"
|
||||
else
|
||||
echo "Pcap_DNSProxy is NOT running"
|
||||
fi
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
--- a/Source/Pcap_DNSProxy/Platform.h
|
||||
+++ b/Source/Pcap_DNSProxy/Platform.h
|
||||
@@ -379,7 +379,7 @@
|
||||
#define SODIUM_STATIC
|
||||
#endif
|
||||
#if defined(ENABLE_LIBSODIUM)
|
||||
- #include "..\\Dependency\\LibSodium\\Include_Windows\\sodium.h"
|
||||
+ #include "LibSodium\\Include_Windows\\sodium.h"
|
||||
#endif
|
||||
|
||||
//WinPcap header, always enabled(Windows)
|
||||
@@ -393,7 +393,7 @@
|
||||
#define HAVE_REMOTE //WinPcap preprocessor definitions
|
||||
#endif
|
||||
#if defined(ENABLE_PCAP)
|
||||
- #include "..\\Dependency\\WinPcap\\Include\\pcap.h"
|
||||
+ #include "WinPcap\\Include\\pcap.h"
|
||||
#endif
|
||||
|
||||
//Windows API headers
|
||||
@@ -575,13 +575,13 @@
|
||||
#ifndef ENABLE_TLS
|
||||
#define ENABLE_TLS
|
||||
#endif
|
||||
- #include "../Dependency/OpenSSL/openssl/bio.h"
|
||||
- #include "../Dependency/OpenSSL/openssl/conf.h"
|
||||
- #include "../Dependency/OpenSSL/openssl/err.h"
|
||||
- #include "../Dependency/OpenSSL/openssl/ssl.h"
|
||||
- #include "../Dependency/OpenSSL/openssl/x509v3.h"
|
||||
- #pragma comment(lib, "../Dependency/OpenSSL/LibCrypto_macOS.a")
|
||||
- #pragma comment(lib, "../Dependency/OpenSSL/LibSSL_macOS.a")
|
||||
+ #include "OpenSSL/openssl/bio.h"
|
||||
+ #include "OpenSSL/openssl/conf.h"
|
||||
+ #include "OpenSSL/openssl/err.h"
|
||||
+ #include "OpenSSL/openssl/ssl.h"
|
||||
+ #include "OpenSSL/openssl/x509v3.h"
|
||||
+ #pragma comment(lib, "OpenSSL/LibCrypto_macOS.a")
|
||||
+ #pragma comment(lib, "OpenSSL/LibSSL_macOS.a")
|
||||
#else
|
||||
#if defined(ENABLE_TLS)
|
||||
#include <openssl/bio.h>
|
@ -1,59 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016-2018 SCUT Router Term
|
||||
#
|
||||
# This is free software, licensed under the GNU Affero General Public License v3.
|
||||
# See /COPYING for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=scutclient
|
||||
PKG_BASE_VERSION:=3.1.2
|
||||
PKG_RELEASE:=$(AUTORELESE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/scutclient/scutclient.git
|
||||
PKG_SOURCE_DATE:=2020-11-29
|
||||
PKG_SOURCE_VERSION:=36128216c63f8954371e64d78ff30bca5e73a882
|
||||
PKG_MIRROR_HASH:=16be6312e7ca2e1b0201c2d2f7e01dbb6173fb9b13c93707ff272f992d4b3bff
|
||||
|
||||
PKG_VERSION:=$(PKG_BASE_VERSION)-$(PKG_SOURCE_DATE)-$(call version_abbrev,$(PKG_SOURCE_VERSION))
|
||||
|
||||
PKG_MAINTAINER:=Scutclient Project
|
||||
PKG_LICENSE:=AGPL-3.0
|
||||
PKG_LICENSE_FILE:=COPYING
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/scutclient
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Campus Network
|
||||
TITLE:=SCUT Dr.com client
|
||||
URL:=https://github.com/scutclient/scutclient
|
||||
endef
|
||||
|
||||
define Package/scutclient/description
|
||||
Support SCUT private authentication protocol.
|
||||
endef
|
||||
|
||||
define Package/scutclient/conffiles
|
||||
/etc/config/scutclient
|
||||
endef
|
||||
|
||||
define Package/scutclient/install
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/openwrt/files/scutclient.config $(1)/etc/config/scutclient
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/openwrt/files/scutclient.init $(1)/etc/init.d/scutclient
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/openwrt/files/scutclient.hotplug $(1)/etc/hotplug.d/iface/99-scutclient
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/scutclient $(1)/usr/bin
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,scutclient))
|
@ -1,33 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=sysuh3c
|
||||
PKG_RELEASE:=$(AUTORELESE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/haswelliris/h3c.git
|
||||
PKG_SOURCE_DATE:=2019-03-01
|
||||
PKG_SOURCE_VERSION:=8a3e0b5a9a5d989e7d8b2105d09a394c3663e016
|
||||
PKG_MIRROR_HASH:=693fd9f81242edb3459a1298f4c850984e59fb44ef6fb4a40fdfcdd3c14acfdb
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/sysuh3c
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Campus Network
|
||||
TITLE:=H3C client
|
||||
endef
|
||||
|
||||
define Package/sysuh3c/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/h3c $(1)/usr/sbin/sysuh3c
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./files/sysuh3c.config $(1)/etc/config/sysuh3c
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/sysuh3c.init $(1)/etc/init.d/sysuh3c
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,sysuh3c))
|
@ -1,6 +0,0 @@
|
||||
|
||||
config login
|
||||
option blockstartup '1'
|
||||
option enable '0'
|
||||
option method 'xor'
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@sysuh3c[-1]
|
||||
add ucitrack sysuh3c
|
||||
set ucitrack.@sysuh3c[-1].init=sysuh3c
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
@ -1,43 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
START=70
|
||||
|
||||
run_h3c()
|
||||
{
|
||||
local enable
|
||||
config_get_bool enable $1 enable
|
||||
|
||||
if [ "$enable" == 1 ]; then
|
||||
local username
|
||||
local password
|
||||
local method
|
||||
local ifname
|
||||
local blockstartup
|
||||
|
||||
config_get username $1 username
|
||||
config_get password $1 password
|
||||
config_get method $1 method
|
||||
config_get ifname $1 ifname
|
||||
config_get_bool blockstartup $1 blockstartup
|
||||
|
||||
if [ "$blockstartup" == 1 ]; then
|
||||
while ! sysuh3c -u $username -p $password -i $ifname -m $method ; do
|
||||
echo sysuh3c: process exited unexpectedly, restarting..
|
||||
sleep 1
|
||||
done
|
||||
else
|
||||
sleep 5
|
||||
sysuh3c -u $username -p $password -i $ifname -m $method &
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
config_load sysuh3c
|
||||
config_foreach run_h3c login
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
killall sysuh3c >/dev/null 2>&1
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2017 Yu Wang <wangyucn@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the MIT.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=udp2raw-tunnel
|
||||
PKG_VERSION:=20200818.0
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/wangyu-/udp2raw-tunnel/tar.gz/$(PKG_VERSION)?
|
||||
PKG_HASH:=712b0cb819555cb374206e95005b0ca6b4af86c74d572e0570630f67dfeea313
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=Yu Wang
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/udp2raw-tunnel
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Tunnel which turns UDP Traffic into Encrypted FakeTCP/UDP/ICMP Traffic
|
||||
URL:=https://github.com/wangyu-/udp2raw-tunnel
|
||||
DEPENDS:=+libstdcpp +libpthread +librt
|
||||
endef
|
||||
|
||||
define Package/udp2raw-tunnel/description
|
||||
udp2raw-tunnel is a tunnel which turns UDP Traffic into Encrypted FakeTCP/UDP/ICMP Traffic by using Raw Socket.
|
||||
endef
|
||||
|
||||
MAKE_FLAGS += cross
|
||||
|
||||
define Build/Prepare
|
||||
$(PKG_UNPACK)
|
||||
sed -i 's/cc_cross=.*/cc_cross=$(TARGET_CXX)/g' $(PKG_BUILD_DIR)/makefile
|
||||
sed -i '/\*gitversion/d' $(PKG_BUILD_DIR)/makefile
|
||||
echo 'const char *gitversion = "$(PKG_VERSION)";' > $(PKG_BUILD_DIR)/git_version.h
|
||||
$(Build/Patch)
|
||||
endef
|
||||
|
||||
define Package/udp2raw-tunnel/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/udp2raw_cross $(1)/usr/bin/udp2raw
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,udp2raw-tunnel))
|
Loading…
x
Reference in New Issue
Block a user