Compare commits

..

No commits in common. "master" and "maint/1.4" have entirely different histories.

238 changed files with 5779 additions and 4099 deletions

View file

@ -3,8 +3,8 @@ name: abicheck
env: env:
build_options: -Dbuildtype=debug -Denable-true-color=yes -Dwith-proxy=yes -Dc_args=-DPERL_EUPXS_ALWAYS_EXPORT build_options: -Dbuildtype=debug -Denable-true-color=yes -Dwith-proxy=yes -Dc_args=-DPERL_EUPXS_ALWAYS_EXPORT
prefix: /usr/local prefix: /usr/local
apt_build_deps: ninja-build libutf8proc-dev libperl-dev libotr5-dev libglib2.0-dev apt_build_deps: ninja-build libutf8proc-dev libperl-dev libotr5-dev
get_pip_build_deps: pip3 install 'setuptools<66'; pip3 install wheel; pip3 install 'meson<0.59.0' get_pip_build_deps: pip3 install setuptools; pip3 install wheel; pip3 install 'meson<0.59.0'
getabidef_def: getabidef() { awk '$1=="#define" && $2=="IRSSI_ABI_VERSION" { print $3 }' "$1"/include/irssi/src/common.h; } getabidef_def: getabidef() { awk '$1=="#define" && $2=="IRSSI_ABI_VERSION" { print $3 }' "$1"/include/irssi/src/common.h; }
jobs: jobs:
build-base-ref: build-base-ref:
@ -17,7 +17,7 @@ jobs:
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt update; sudo apt install $apt_build_deps sudo apt install $apt_build_deps
eval "$get_pip_build_deps" eval "$get_pip_build_deps"
- name: checkout base ref - name: checkout base ref
uses: actions/checkout@main uses: actions/checkout@main
@ -36,8 +36,8 @@ jobs:
base_abi=$(getabidef base$prefix) base_abi=$(getabidef base$prefix)
echo base abi : $base_abi echo base abi : $base_abi
./base$prefix/bin/irssi --version ./base$prefix/bin/irssi --version
echo base_abi=$base_abi >> $GITHUB_OUTPUT echo "::set-output name=base_abi::$base_abi"
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: base.inst name: base.inst
path: base path: base
@ -52,7 +52,7 @@ jobs:
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt update; sudo apt install $apt_build_deps sudo apt install $apt_build_deps
eval "$get_pip_build_deps" eval "$get_pip_build_deps"
- name: checkout merge ref - name: checkout merge ref
uses: actions/checkout@main uses: actions/checkout@main
@ -70,8 +70,8 @@ jobs:
merge_abi=$(getabidef merge$prefix) merge_abi=$(getabidef merge$prefix)
echo merge abi : $merge_abi echo merge abi : $merge_abi
./merge$prefix/bin/irssi --version ./merge$prefix/bin/irssi --version
echo merge_abi=$merge_abi >> $GITHUB_OUTPUT echo "::set-output name=merge_abi::$merge_abi"
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: merge.inst name: merge.inst
path: merge path: merge
@ -87,14 +87,14 @@ jobs:
steps: steps:
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt update; sudo apt install abigail-tools sudo apt install abigail-tools
- name: fetch base build - name: fetch base build
uses: actions/download-artifact@v4 uses: actions/download-artifact@v2
with: with:
name: base.inst name: base.inst
path: base path: base
- name: fetch merge build - name: fetch merge build
uses: actions/download-artifact@v4 uses: actions/download-artifact@v2
with: with:
name: merge.inst name: merge.inst
path: merge path: merge
@ -103,7 +103,7 @@ jobs:
abipkgdiff -l base merge >abipkgdiff.out && diff_ret=0 || diff_ret=$? abipkgdiff -l base merge >abipkgdiff.out && diff_ret=0 || diff_ret=$?
echo "diff_ret=$diff_ret" >> $GITHUB_ENV echo "diff_ret=$diff_ret" >> $GITHUB_ENV
cat abipkgdiff.out cat abipkgdiff.out
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
path: abipkgdiff.out path: abipkgdiff.out
- run: | - run: |

View file

@ -5,50 +5,27 @@ on:
pull_request: pull_request:
name: Check Irssi name: Check Irssi
env: env:
apt_build_deps: ninja-build libutf8proc-dev libperl-dev libotr5-dev libglib2.0-dev apt_build_deps: libutf8proc-dev libperl-dev libotr5-dev
apt_build_deps_meson: ninja-build
apt_build_deps_autotools: autoconf automake libtool
get_pip_build_deps_meson: pip3 install setuptools${setuptools_ver}; pip3 install wheel; pip3 install meson${meson_ver} get_pip_build_deps_meson: pip3 install setuptools${setuptools_ver}; pip3 install wheel; pip3 install meson${meson_ver}
build_options_meson: -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes -Dwith-otr=yes build_options_meson: -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes -Dwith-otr=yes
build_options_configure: --with-proxy=module --with-bot --with-perl=module --with-otr=module
prefix: ~/irssi-build prefix: ~/irssi-build
jobs: jobs:
dist: dist:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
meson_ver: <0.63.0
setuptools_ver: <66
steps: steps:
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt update && sudo apt install $apt_build_deps sudo apt update && sudo apt install $apt_build_deps $apt_build_deps_autotools
eval "$get_pip_build_deps_meson"
patch ~/.local/lib/python3.12/site-packages/pkg_resources/__init__.py <<- PATCH
--- __init__.py 2024-12-16 20:37:46.733230351 +0100
+++ __init__.py 2024-12-16 20:38:42.479554540 +0100
@@ -2188,7 +2188,8 @@ def resolve_egg_link(path):
return next(dist_groups, ())
-register_finder(pkgutil.ImpImporter, find_on_path)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_finder(pkgutil.ImpImporter, find_on_path)
if hasattr(importlib_machinery, 'FileFinder'):
register_finder(importlib_machinery.FileFinder, find_on_path)
@@ -2345,7 +2346,8 @@ def file_ns_handler(importer, path_item,
return subpath
-register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
register_namespace_handler(zipimport.zipimporter, file_ns_handler)
if hasattr(importlib_machinery, 'FileFinder'):
PATCH
- uses: actions/checkout@main - uses: actions/checkout@main
- name: make dist - name: make dist
run: | run: |
./utils/make-dist.sh # make dist
- uses: actions/upload-artifact@v4 ./autogen.sh $build_options_configure
make dist
- uses: actions/upload-artifact@v2
with: with:
path: irssi-*.tar.gz path: irssi-*.tar.gz
retention-days: 1 retention-days: 1
@ -61,21 +38,24 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-22.04, ubuntu-latest] os: [ubuntu-18.04, ubuntu-latest]
builder: [meson, configure]
compiler: [clang, gcc] compiler: [clang, gcc]
flags: [regular] flags: [regular]
setuptools_ver: [<66]
include: include:
- os: ubuntu-22.04 - os: ubuntu-18.04
meson_ver: ==0.53.2 builder: meson
meson_ver: ==0.49.2
setuptools_ver: <51 setuptools_ver: <51
- os: ubuntu-latest - os: ubuntu-latest
meson_ver: <0.63.0 builder: meson
meson_ver: <0.60.0
- os: ubuntu-latest - os: ubuntu-latest
builder: meson
flags: meson-latest FAILURE-OK flags: meson-latest FAILURE-OK
steps: steps:
- name: fetch dist - name: fetch dist
uses: actions/download-artifact@v4 uses: actions/download-artifact@v2
- name: set PATH - name: set PATH
run: | run: |
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
@ -84,8 +64,8 @@ jobs:
meson_ver: ${{ matrix.meson_ver }} meson_ver: ${{ matrix.meson_ver }}
setuptools_ver: ${{ matrix.setuptools_ver }} setuptools_ver: ${{ matrix.setuptools_ver }}
run: | run: |
sudo apt update && sudo apt install $apt_build_deps sudo apt update && sudo apt install $apt_build_deps $apt_build_deps_${{ matrix.builder }}
eval "$get_pip_build_deps_meson" eval "$get_pip_build_deps_${{ matrix.builder }}"
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
- name: unpack archive - name: unpack archive
run: tar xaf artifact/irssi-*.tar.gz run: tar xaf artifact/irssi-*.tar.gz
@ -96,12 +76,31 @@ jobs:
meson Build $build_options_meson --prefix=${prefix/\~/~} meson Build $build_options_meson --prefix=${prefix/\~/~}
ninja -C Build ninja -C Build
ninja -C Build install ninja -C Build install
if: ${{ matrix.builder == 'meson' }}
- name: build and install with Makefile
run: |
# make install
cd irssi-*/
mkdir Build
cd Build
../configure $build_options_configure --prefix=${prefix/\~/~} --enable-always-build-tests
make CFLAGS="-Wall -Werror -Werror=declaration-after-statement"
make install
if: ${{ matrix.builder == 'configure' }}
- name: run tests with Makefile
run: |
# make check
cd irssi-*/Build
make -C tests -sk check
find -name test-suite.log -exec cat {} +
if: ${{ matrix.builder == 'configure' }}
- name: run tests with Meson - name: run tests with Meson
run: | run: |
# ninja test # ninja test
cd irssi-*/ cd irssi-*/
ninja -C Build test ninja -C Build test
find -name testlog.txt -exec sed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} + find -name testlog.txt -exec sed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} +
if: ${{ matrix.builder == 'meson' }}
- name: run launch test - name: run launch test
env: env:
TERM: xterm TERM: xterm
@ -116,10 +115,6 @@ jobs:
^set -clear log_open_string ^set -clear log_open_string
^set log_timestamp * ^set log_timestamp *
^window log on ^window log on
load irc
load dcc
load flood
load notifylist
load perl load perl
load otr load otr
load proxy load proxy
@ -146,7 +141,7 @@ jobs:
meson_ver: ${{ matrix.meson_ver }} meson_ver: ${{ matrix.meson_ver }}
setuptools_ver: ${{ matrix.setuptools_ver }} setuptools_ver: ${{ matrix.setuptools_ver }}
run: | run: |
sudo apt update && sudo apt install $apt_build_deps sudo apt update && sudo apt install $apt_build_deps $apt_build_deps_meson
eval "$get_pip_build_deps_meson" eval "$get_pip_build_deps_meson"
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
- name: build and install with meson - name: build and install with meson
@ -168,10 +163,6 @@ jobs:
^set -clear log_open_string ^set -clear log_open_string
^set log_timestamp * ^set log_timestamp *
^window log on ^window log on
load irc
load dcc
load flood
load notifylist
load perl load perl
load otr load otr
load proxy load proxy

View file

@ -44,7 +44,7 @@ jobs:
dry-run: false dry-run: false
sanitizer: ${{ matrix.sanitizer }} sanitizer: ${{ matrix.sanitizer }}
- name: Upload Crash - name: Upload Crash
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v1
if: failure() && steps.build.outcome == 'success' if: failure() && steps.build.outcome == 'success'
with: with:
name: ${{ matrix.sanitizer }}-artifacts name: ${{ matrix.sanitizer }}-artifacts

View file

@ -22,8 +22,8 @@ jobs:
| |
CLANG_FORMAT=clang-format-14 git-clang-format-14 --diff FETCH_HEAD HEAD | tee git-clang-format.diff CLANG_FORMAT=clang-format-14 git-clang-format-14 --diff FETCH_HEAD HEAD | tee git-clang-format.diff
cmp -s <(echo no modified files to format) git-clang-format.diff || cmp -s <(echo -n) git-clang-format.diff cmp -s <(echo no modified files to format) git-clang-format.diff || cmp -s <(echo -n) git-clang-format.diff
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v1
if: failure() if: failure()
with: with:
name: git-clang-format.diff name: git-clang-format.diff
path: git-clang-format.diff path: git-clang-format.diff

View file

@ -1,32 +0,0 @@
name: Format meson files
on:
push:
pull_request:
permissions: {}
jobs:
muon-meson-fmt:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
with:
persist-credentials: false
# Build from source because Ubuntu 24.04 apt only has muon 0.2.0.
# Newer muons seem to format differently.
- name: Build muon from source
run: |
git clone --depth 1 --branch 0.5.0 https://github.com/muon-build/muon /tmp/muon
cd /tmp/muon
./bootstrap.sh build
build/muon-bootstrap setup build
build/muon-bootstrap -C build samu
sudo build/muon -C build install
- name: Run muon fmt
run: |
find . -name meson.build -print0 | xargs -0 muon fmt -c .muon_fmt.ini -i
git diff --exit-code

View file

@ -1,104 +0,0 @@
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
name: Check Irssi on Solaris
env:
get_pip_build_deps_meson: pip3 install setuptools${setuptools_ver}; pip3 install wheel
prefix: ~/irssi-build
jobs:
dist:
runs-on: ubuntu-latest
env:
setuptools_ver: <66
steps:
- name: prepare required software
run: |
sudo apt update && sudo apt install $apt_build_deps
eval "$get_pip_build_deps_meson"
patch ~/.local/lib/python3.12/site-packages/pkg_resources/__init__.py <<- PATCH
--- __init__.py 2024-12-16 20:37:46.733230351 +0100
+++ __init__.py 2024-12-16 20:38:42.479554540 +0100
@@ -2188,7 +2188,8 @@ def resolve_egg_link(path):
return next(dist_groups, ())
-register_finder(pkgutil.ImpImporter, find_on_path)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_finder(pkgutil.ImpImporter, find_on_path)
if hasattr(importlib_machinery, 'FileFinder'):
register_finder(importlib_machinery.FileFinder, find_on_path)
@@ -2345,7 +2346,8 @@ def file_ns_handler(importer, path_item,
return subpath
-register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
register_namespace_handler(zipimport.zipimporter, file_ns_handler)
if hasattr(importlib_machinery, 'FileFinder'):
PATCH
- uses: actions/checkout@main
- name: make dist
run: |
./utils/make-dist.sh
- uses: actions/upload-artifact@v4
with:
path: irssi-*.tar.gz
retention-days: 1
install:
runs-on: ubuntu-latest
needs: dist
steps:
- name: fetch dist
uses: actions/download-artifact@v4
- name: Test in Solaris
uses: vmactions/solaris-vm@v1
with:
usesh: true
sync: rsync
release: "11.4-gcc"
prepare: |
pkg update --accept || echo 1:$?
pkg install meson || echo 2:$?
pkgutil -y -i curl || echo 3:$?
pkgutil -y -i gtar || echo 4:$?
pkgutil -y -i findutils || echo 5:$?
run: |
set -ex
export PKG_CONFIG_PATH=/usr/lib/64/pkgconfig
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
gtar xzf artifact/irssi-*.tar.gz
# ninja install
cd irssi-*/
meson Build -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes --prefix=$HOME/irssi-build
ninja -C Build
ninja -C Build install
# ninja test
ninja -C Build test
gfind -name testlog.txt -exec gsed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} +
export TERM=xterm
# automated irssi launch test
cd
mkdir irssi-test
echo 'echo automated irssi launch test
^set settings_autosave off
^set -clear log_close_string
^set -clear log_day_changed
^set -clear log_open_string
^set log_timestamp *
^window log on
load irc
load dcc
load flood
load notifylist
load perl
load otr
load proxy
^quit' > irssi-test/startup
irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl
cat irc.log.*

View file

@ -1,79 +0,0 @@
on:
push:
branches:
- master
pull_request:
name: Build Irssi Termux package
jobs:
termux-package:
runs-on: ubuntu-latest
steps:
- name: checkout termux-packages
uses: actions/checkout@main
with:
repository: termux/termux-packages
- name: checkout irssi
uses: actions/checkout@main
with:
path: src.irssi.git
- name: download termux docker container
uses: docker://termux/package-builder:latest
- name: create irssi build receipe
run: |
mkdir packages/irssi-an
cat << 'BUILD_SH' > packages/irssi-an/build.sh
TERMUX_PKG_HOMEPAGE=https://irssi.org/
TERMUX_PKG_DESCRIPTION="Terminal based IRC client"
TERMUX_PKG_LICENSE="GPL-2.0"
TERMUX_PKG_MAINTAINER="@irssi"
TERMUX_PKG_VERSION=@VERSION@
TERMUX_PKG_REVISION=@REVISION@
TERMUX_PKG_SRCURL=git+file:///home/builder/termux-packages/src.irssi.git
TERMUX_PKG_AUTO_UPDATE=true
TERMUX_PKG_DEPENDS="glib, libandroid-glob, libiconv, libotr, ncurses, openssl, perl, utf8proc"
TERMUX_PKG_BREAKS="irssi"
TERMUX_PKG_REPLACES="irssi"
TERMUX_MESON_PERL_CROSS_FILE=$TERMUX_PKG_TMPDIR/meson-perl-cross-$TERMUX_ARCH.txt
TERMUX_PKG_EXTRA_CONFIGURE_ARGS="
-Dfhs-prefix=$TERMUX_PREFIX
--cross-file $TERMUX_MESON_PERL_CROSS_FILE
"
termux_step_pre_configure() {
LDFLAGS+=" -landroid-glob"
# Make build log less noisy.
CFLAGS+=" -Wno-compound-token-split-by-macro"
local perl_version=$(. $TERMUX_SCRIPTDIR/packages/perl/build.sh; echo $TERMUX_PKG_VERSION)
cat << MESON_PERL_CROSS >$TERMUX_MESON_PERL_CROSS_FILE
[properties]
perl_version = '$perl_version'
perl_ccopts = ['-I$TERMUX_PREFIX/include', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64', '-I$TERMUX_PREFIX/lib/perl5/$perl_version/${TERMUX_ARCH}-android/CORE']
perl_ldopts = ['-Wl,-E', '-I$TERMUX_PREFIX/include', '-L$TERMUX_PREFIX/lib/perl5/$perl_version/${TERMUX_ARCH}-android/CORE', '-lperl', '-lm', '-ldl']
perl_archname = '${TERMUX_ARCH}-android'
perl_installsitearch = '$TERMUX_PREFIX/lib/perl5/site_perl/$perl_version/${TERMUX_ARCH}-android'
perl_installvendorarch = ''
perl_inc = ['$TERMUX_PREFIX/lib/perl5/site_perl/$perl_version/${TERMUX_ARCH}-android', '$TERMUX_PREFIX/lib/perl5/site_perl/$perl_version', '$TERMUX_PREFIX/lib/perl5/$perl_version/${TERMUX_ARCH}-android', '$TERMUX_PREFIX/lib/perl5/$perl_version']
MESON_PERL_CROSS
}
BUILD_SH
version=$(awk '/^v/ { $0=$1; gsub(/^v/,""); gsub(/-head/,"dev"); gsub(/-/,""); print; exit }' src.irssi.git/NEWS)
version=$version+g$(git -C src.irssi.git rev-parse --short HEAD)
sed -i \
-e "s:@VERSION@:$version:" \
-e "s:@REVISION@:$GITHUB_RUN_NUMBER:" \
packages/irssi-an/build.sh
git -C src.irssi.git tag v$version
- name: prepare output folder
run: |
install -m a+rwx -d output
- name: build irssi package
run: |
sudo ./scripts/run-docker.sh ./build-package.sh -I irssi-an
- uses: actions/upload-artifact@v4
with:
name: irssi-termux-pkg
path: output/irssi-an*.deb

View file

@ -1,20 +0,0 @@
on:
push:
branches:
- master
jobs:
rebuild-pages:
if: github.repository == 'irssi/irssi'
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.PAT_TOKEN }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: 'irssi.github.io',
workflow_id: 'pages.yml',
ref: 'main'
})

View file

@ -1,75 +0,0 @@
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
name: Check Irssi on Void Linux glibc
jobs:
dist:
runs-on: ubuntu-latest
container: ghcr.io/void-linux/void-glibc:latest
steps:
- name: prepare required software
run: |
xbps-install -Syu xbps || :
xbps-install -Syu
xbps-install -Sy git findutils python3-setuptools tar xz gzip
- uses: actions/checkout@main
- name: make dist
run: |
git config --global --add safe.directory /__w/irssi/irssi
./utils/make-dist.sh
- uses: actions/upload-artifact@v4
with:
path: irssi-*.tar.gz
retention-days: 1
install:
runs-on: ubuntu-latest
container: ghcr.io/void-linux/void-glibc:latest
needs: dist
steps:
- name: prepare required software
run: |
xbps-install -Syu xbps || :
xbps-install -Syu
xbps-install -Sy meson base-devel libglib-devel libutf8proc-devel ncurses-devel ncurses-base openssl-devel libotr-devel libgcrypt-devel tar findutils curl
- name: fetch dist
uses: actions/download-artifact@v4
- name: Setup local annotations
uses: irssi-import/actions-irssi/problem-matchers@master
- name: Test on Void Linux glibc
run: |
set -ex
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
tar xzf artifact/irssi-*.tar.gz
# ninja install
cd irssi-*/
meson Build -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes --prefix=$HOME/irssi-build --buildtype debugoptimized
ninja -C Build
ninja -C Build install
# ninja test
ninja -C Build test
find -name testlog.txt -exec sed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} +
export TERM=xterm
# automated irssi launch test
cd
mkdir irssi-test
echo 'echo automated irssi launch test
^set settings_autosave off
^set -clear log_close_string
^set -clear log_day_changed
^set -clear log_open_string
^set log_timestamp *
^window log on
load irc
load dcc
load flood
load notifylist
load perl
load otr
load proxy
^quit' > irssi-test/startup
export LC_CTYPE=C.utf8
irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl
cat irc.log.*

3
.gitignore vendored
View file

@ -86,6 +86,3 @@ src/fe-fuzz/oom-*
Build Build
subprojects/* subprojects/*
!subprojects/*.wrap !subprojects/*.wrap
Irssi-Dist
setup.cfg
*.egg-info

View file

@ -1,14 +0,0 @@
# Irssi configuration for muon fmt
max_line_len = 108
indent_style = space
indent_size = 2
#indent_by = ' '
space_array = true
kwargs_force_multiline = true
wide_colon = true
no_single_comma_function = true
insert_final_newline = true
sort_files = false
group_arg_value = true
sticky_parens = true
continuation_indent = true

View file

@ -1,13 +0,0 @@
workflow:
steps:
- branch_package:
source_project: home:ailin_nemui:irssi-git-an
source_package: irssi-git-an
target_project: home:ailin_nemui:CI
- set_flags:
flags:
- type: publish
status: enable
project: home:ailin_nemui:CI
filters:
event: pull_request

64
INSTALL
View file

@ -4,15 +4,11 @@
To compile Irssi you need: To compile Irssi you need:
- meson-0.53 build system with ninja-1.8 or greater - meson-0.49 build system with ninja-1.5 or greater
- pkg-config (or compatible)
- glib-2.32 or greater - glib-2.32 or greater
- openssl (for ssl support) - openssl (for ssl support)
- perl-5.8 or greater (for building, and optionally Perl scripts) - perl-5.8 or greater (for building, and optionally Perl scripts)
(n.b a complete perl is needed, including ExtUtils::Embed and xsubpp)
- terminfo or ncurses (for text frontend) - terminfo or ncurses (for text frontend)
- utf8proc (optional, for additional char width calculation)
- libgcrypt (for OTR)
For most people, this should work just fine: For most people, this should work just fine:
@ -21,12 +17,21 @@ For most people, this should work just fine:
su su
ninja -C Build install ninja -C Build install
meson options For the moment, autotools is also supported:
These options can be given to meson. ./autogen.sh (for people who just cloned the repository)
./configure (if this script already exists, skip ./autogen.sh)
make
su
make install (not _really_ required except for perl support)
configure options
These options can be given to meson or ./configure.
The first syntax is for meson, the 2nd for ./configure
For a complete list of options, run For a complete list of options, run
meson configure meson configure / ./configure --help
--prefix --prefix
@ -34,28 +39,33 @@ meson options
YES, you can install Irssi WITHOUT ROOT permissions YES, you can install Irssi WITHOUT ROOT permissions
by using --prefix=/home/dir by using --prefix=/home/dir
-Dwith-proxy=yes -Dwith-proxy=yes / --with-proxy
Build the Irssi proxy (see startup-HOWTO). Build the Irssi proxy (see startup-HOWTO).
-Dwith-perl=[yes|no] -Dwith-perl=[yes|no] / --with-perl=[yes|no|module]
Enable Perl support Enable Perl support
yes enable builtin (default) yes enable builtin (default)
no disable no disable
module enable as module
-Dwith-perl-lib=[site|vendor|DIR] -Dwith-perl-lib=[site|vendor|DIR] / --with-perl-lib=[site|vendor|DIR]
Specify installation dir for Perl libraries Specify installation dir for Perl libraries
site install in dir for site-specific modules (default) site install in dir for site-specific modules (default)
vendor install in dir for vendor-specific modules vendor install in dir for vendor-specific modules
DIR install in DIR DIR install in DIR
-Dwith-bot=yes [N/A] / --with-socks
Build with socks library
-Dwith-bot=yes / --with-bot
Build irssi-bot Build irssi-bot
-Dwithout-textui=yes -Dwithout-textui=yes / --without-textui
Build without text frontend Build without text frontend
@ -72,18 +82,31 @@ the -Dc_args and -Dc_link_args options variable, eg.:
Perl support generates most of the problems. There's quite a many Perl support generates most of the problems. There's quite a many
things that can go wrong: things that can go wrong:
- Compiling fails if you compile irssi with GCC in a system that has
perl compiled with some other C compiler. Very common problem with
non-Linux/BSD systems. You'll need to edit src/perl/*/Makefile files
and remove the parameters that gcc doesn't like. Mostly you'll just
need to keep the -I and -D parameters and add -fPIC.
- If there's any weird crashing at startup, you might have older irssi's - If there's any weird crashing at startup, you might have older irssi's
perl libraries installed somewhere, and you should remove those. perl libraries installed somewhere, and you should remove those.
- If meson complains that it doesn't find some perl stuff, you're - Dynamic libraries don't want to work with some systems, so if your
system complains about some missing symbol in Irssi.so file, configure
irssi with --with-perl-staticlib option (NOT same as --with-perl=static).
- If configure complains that it doesn't find some perl stuff, you're
probably missing libperl.so or libperl.a. In debian, you'll need to do probably missing libperl.so or libperl.a. In debian, you'll need to do
apt-get install libperl-dev apt-get install libperl-dev
- For unprivileged home directory installations, you probably do not want
to specify --with-perl-lib=(site|vendor). Instead, you can use the
default perl installation target (below the irssi prefix). If you are
using local::lib you can also choose to install there by specifying
--with-perl-lib=$PERL_LOCAL_LIB_ROOT/lib/perl5
You can verify that the perl module is loaded and working with "/LOAD" You can verify that the perl module is loaded and working with "/LOAD"
command. It should print something like: command. It should print something like:
Module Type Submodules Module Type Submodules
... ...
perl dynamic fe core perl static core fe
System specific notes System specific notes
@ -111,7 +134,16 @@ would call:
Getting perl scripting to work needs a few things: Getting perl scripting to work needs a few things:
- TODO - configure with --with-perl-staticlib
- libperl.dll is required in linking and running irssi, it's normally
located somewhere around /usr/lib/perl5/5.6.1/cygwin/CORE/libperl5_6_1.dll
copy it to eg. /usr/bin/libperl.dll
- -DUSEIMPORTLIB is needed to be defined while compiling src/perl directory.
It doesn't hurt to be defined everywhere, so configure irssi with:
CFLAGS='-DUSEIMPORTLIB' ./configure --with-perl-staticlib
Apple MacOS / Darwin Apple MacOS / Darwin

View file

@ -1,35 +0,0 @@
global-include meson.build
recursive-include src *.c *.h meson.build
recursive-include src/perl *.c *.h *.xs *.pm *.pl typemap meson.build
recursive-include src/fe-fuzz *.c *.h *.txt meson.build
recursive-include tests *.c meson.build
include meson_options.txt
include subprojects/*.wrap
# prune subprojects/*
include utils/*.pl utils/*.sh
exclude utils/make-dist.sh
include irssi.conf
include themes/*.theme
include docs/*.1 docs/*.txt docs/*.html
include docs/help/in/[a-z]*.in
include scripts/*.pl scripts/examples/*.pl
include irssi-icon.png
include NEWS
include INSTALL
include TODO
include ChangeLog
include .clang-format
# prune Build
# prune dist
prune *.egg-info
# ignore fuzz-support/fuzz.diff
# ignore utils/clang-format-xs/*

35
Makefile.am Normal file
View file

@ -0,0 +1,35 @@
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
# create default-config.h
BUILT_SOURCES = default-config.h default-theme.h irssi-version.h
CLEANFILES = default-config.h default-theme.h
@MAINTAINER_MODE_TRUE@.PHONY: irssi-version.h
default-config.h: $(srcdir)/irssi.conf
$(srcdir)/utils/file2header.sh $(srcdir)/irssi.conf default_config > default-config.h
default-theme.h: $(srcdir)/themes/default.theme
$(srcdir)/utils/file2header.sh $(srcdir)/themes/default.theme default_theme > default-theme.h
irssi-version.h:
VERSION="$(VERSION)" $(srcdir)/utils/irssi-version.sh $(srcdir) | \
cmp -s - $@ || VERSION="$(VERSION)" $(srcdir)/utils/irssi-version.sh $(srcdir) >$@
SUBDIRS = src tests docs scripts themes utils
confdir = $(sysconfdir)
conf_DATA = irssi.conf
pkgconfig_DATA = irssi-1.pc
pkginclude_HEADERS = irssi-config.h irssi-version.h
EXTRA_DIST = \
ChangeLog \
autogen.sh \
README.md \
$(conf_DATA) \
irssi-icon.png \
meson.build \
meson_options.txt

2
NEWS
View file

@ -1,5 +1,3 @@
v1.5-head 202x-xx-xx The Irssi team <staff@irssi.org>
v1.4.5 2023-10-03 The Irssi team <staff@irssi.org> v1.4.5 2023-10-03 The Irssi team <staff@irssi.org>
+ Add workaround for Perl 5.38.0 bug that breaks the Irssi + Add workaround for Perl 5.38.0 bug that breaks the Irssi
locale and glyph rendering (scripts.irssi.org#857, #1498) locale and glyph rendering (scripts.irssi.org#857, #1498)

View file

@ -17,7 +17,7 @@ available.
#### Development source installation #### Development source installation
[Ninja](https://ninja-build.org/) 1.8 and [Meson](https://mesonbuild.com/) 0.53 [Ninja](https://ninja-build.org/) 1.5 and [Meson](https://mesonbuild.com/) 0.49
``` ```
git clone https://github.com/irssi/irssi git clone https://github.com/irssi/irssi
@ -29,7 +29,7 @@ ninja -C Build && sudo ninja -C Build install
#### Release source installation #### Release source installation
* Download [release](https://github.com/irssi/irssi/releases) * Download [release](https://github.com/irssi/irssi/releases)
* Verify signature * [Verify](https://irssi.org/download/#release-sources) signature
``` ```
tar xJf irssi-*.tar.xz tar xJf irssi-*.tar.xz
cd irssi-* cd irssi-*
@ -41,15 +41,15 @@ ninja -C Build && sudo ninja -C Build install
- [glib-2.32](https://wiki.gnome.org/Projects/GLib) or greater - [glib-2.32](https://wiki.gnome.org/Projects/GLib) or greater
- [openssl](https://www.openssl.org/) - [openssl](https://www.openssl.org/)
- [perl-5.8](https://www.perl.org/) or greater (for perl support) - [perl-5.6](https://www.perl.org/) or greater (for perl support)
- terminfo or ncurses (for text frontend) - terminfo or ncurses (for text frontend)
#### See the [INSTALL](INSTALL) file for details #### See the [INSTALL](INSTALL) file for details
## [Documentation](https://irssi.org/documentation/) ## [Documentation](https://irssi.org/documentation/)
* [New users guide](https://irssi.org/New-users/) * [Frequently Asked Questions](https://irssi.org/documentation/faq)
* [Questions and Answers](https://irssi.org/documentation/qna/) * [Startup How-To](https://irssi.org/documentation/startup)
* Check the built-in `/HELP`, it has all the details on command syntax * Check the built-in `/HELP`, it has all the details on command syntax
## [Themes](https://irssi-import.github.io/themes/) ## [Themes](https://irssi-import.github.io/themes/)
@ -62,7 +62,7 @@ ninja -C Build && sudo ninja -C Build install
Please report security issues to staff@irssi.org. Thanks! Please report security issues to staff@irssi.org. Thanks!
## [Bugs](https://github.com/irssi/irssi/issues) / Suggestions / Contributing ## [Bugs](https://github.com/irssi/irssi/issues) / Suggestions / [Contributing](https://irssi.org/development/)
Check the GitHub issues if it is already listed in there; if not, open Check the GitHub issues if it is already listed in there; if not, open
an issue on GitHub or send a mail to [staff@irssi.org](mailto:staff@irssi.org). an issue on GitHub or send a mail to [staff@irssi.org](mailto:staff@irssi.org).

67
autogen.sh Executable file
View file

@ -0,0 +1,67 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
PKG_NAME="Irssi"
srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.
mydir=`pwd`
if test ! -f "$srcdir"/configure.ac; then
echo -n "**Error**: Directory \`$srcdir' does not look like the"
echo " top-level $PKG_NAME directory"
exit 1
fi
cd "$srcdir"
# create help files
echo "Creating help files..."
perl utils/syntax.pl
echo "Creating ChangeLog..."
git log > ChangeLog
if test "$?" -ne 0; then
echo "**Error**: ${PKG_NAME} Autogen must be run in a git clone, cannot proceed."
exit 1
fi
files=`echo docs/help/in/*.in|sed -e 's,docs/help/in/Makefile.in ,,' -e 's,docs/help/in/,!,g' -e 's/\.in /.in ?/g'`
cat docs/help/in/Makefile.am.gen|sed "s/@HELPFILES@/$files/g"|sed 's/?/\\?/g'|tr '!?' '\t\n' > docs/help/in/Makefile.am
files=`echo $files|sed 's/\.in//g'`
cat docs/help/Makefile.am.gen|sed "s/@HELPFILES@/$files/g"|sed 's/?/\\?/g'|tr '!?' '\t\n' > docs/help/Makefile.am
if test x$NOCONFIGURE = x && test -z "$*"; then
echo "**Warning**: I am going to run \`configure' with no arguments."
echo "If you wish to pass any to it, please specify them on the"
echo \`$0\'" command line."
echo
fi
rm -f aclocal.m4
echo "Running autoreconf ..."
autoreconf -i || exit $?
# make sure perl hashes have correct length
find src/perl -name '*.c' -o -name '*.xs' -exec grep -n hv_store {} + | perl -l -ne 'if (/"(\w+)",\s*(\d+)/ && $2 != length $1) { $X=1; print "Incorrect key length in $_" } END { exit $X }'
cd "$mydir"
conf_flags="--enable-maintainer-mode"
if test x$NOCONFIGURE = x; then
echo Running "$srcdir"/configure $conf_flags "$@" ...
"$srcdir"/configure $conf_flags "$@" \
&& echo Now type \`make\' to compile $PKG_NAME || exit 1
else
echo Skipping configure process.
fi
if grep -q '==\|\[\[' "$srcdir"/build-aux/test-driver; then
echo
echo "************************************************************************"
echo "**Warning**: your build is not portable, please do not make dist"
echo " see https://bugzilla.opensuse.org/show_bug.cgi?id=1076146"
echo "************************************************************************"
fi

821
configure.ac Normal file
View file

@ -0,0 +1,821 @@
AC_INIT(irssi, 1.4.5)
AC_CONFIG_SRCDIR([src])
AC_CONFIG_AUX_DIR(build-aux)
AC_PREREQ(2.50)
AC_CONFIG_HEADERS([irssi-config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.9 no-define foreign subdir-objects nostdinc])
AM_SILENT_RULES([yes])
AM_MAINTAINER_MODE
AC_PROG_CC
AC_PROG_CPP
AM_PROG_LIBTOOL
AC_PATH_PROG(sedpath, sed)
AC_PATH_PROG(perlpath, perl)
PKG_INSTALLDIR
AC_CHECK_HEADERS(unistd.h dirent.h sys/ioctl.h sys/resource.h)
# check posix headers..
AC_CHECK_HEADERS(sys/socket.h sys/time.h sys/utsname.h)
AC_SYS_LARGEFILE
AC_ARG_WITH(socks,
[ --with-socks Build with socks support],
if test x$withval = xno; then
want_socks=no
else
want_socks=yes
fi,
want_socks=no)
AC_ARG_WITH(textui,
[ --without-textui Build without text frontend],
if test x$withval = xno; then
want_textui=no
else
want_textui=yes
fi,
want_textui=yes)
AC_ARG_WITH(bot,
[ --with-bot Build irssi-bot],
if test x$withval = xno; then
want_irssibot=no
else
want_irssibot=yes
fi,
want_irssibot=no)
AC_ARG_WITH(fuzzer,
[ --with-fuzzer Build irssi-fuzzer],
if test x$withval = xno; then
want_irssifuzzer=no
else
want_irssifuzzer=yes
fi,
want_irssifuzzer=no)
AC_ARG_WITH(fuzzer-lib,
[ --with-fuzzer-lib Specify path to fuzzer library],
fuzzerlibpath="$withval")
AC_ARG_WITH(proxy,
[ --with-proxy Build irssi-proxy],
if test x$withval = xno; then
want_irssiproxy=no
else
want_irssiproxy=yes
fi,
want_irssiproxy=no)
AC_ARG_WITH(modules,
[ --with-modules Specify what modules to build in binary],
if test x$withval != xyes -a x$withval != xno; then
build_modules="$withval"
fi)
if test "x$prefix" != "xNONE"; then
prefix=`eval echo $prefix`
PERL_MM_PARAMS="INSTALLDIRS=perl INSTALL_BASE=$prefix"
perl_set_use_lib=yes
perl_prefix_note=yes
fi
AC_ARG_WITH(perl-staticlib,
[ --with-perl-staticlib Specify that we want to link perl libraries
statically in irssi, default is no],
if test x$withval = xno; then
want_staticperllib=no
else
want_staticperllib=yes
fi,
want_staticperllib=no)
AC_ARG_WITH(perl-lib,
[ --with-perl-lib=[perl|site|vendor|DIR] Specify where to install the
Perl libraries for irssi, default is site],
if test "x$withval" = xyes; then
want_perl=yes
elif test "x$withval" = xno; then
want_perl=no
elif test "x$withval" = xperl; then
want_perl=yes
perl_prefix_note=no
PERL_MM_PARAMS="INSTALLDIRS=perl"
perl_set_use_lib=no
elif test "x$withval" = xsite; then
want_perl=yes
perl_prefix_note=no
PERL_MM_PARAMS=""
perl_set_use_lib=no
elif test "x$withval" = xvendor; then
want_perl=yes
perl_prefix_note=no
if test -z "`$perlpath -v|grep '5\.0'`"; then
PERL_MM_PARAMS="INSTALLDIRS=vendor"
else
PERL_MM_PARAMS="INSTALLDIRS=perl PREFIX=`$perlpath -e 'use Config; print $Config{prefix}'`"
fi
perl_set_use_lib=no
else
want_perl=yes
perl_prefix_note=no
PERL_MM_PARAMS="INSTALLDIRS=perl LIB=$withval"
perl_set_use_lib=yes
fi,
want_perl=yes)
AC_ARG_WITH(perl,
[ --with-perl[=yes|no|module] Build with Perl support - also specifies
if it should be built into main irssi binary
(static, default) or as module],
if test x$withval = xyes; then
want_perl=static
elif test x$withval = xstatic; then
want_perl=static
elif test x$withval = xmodule; then
want_perl=module
else
want_perl=no
fi,
want_perl=static)
AC_ARG_WITH(otr,
[ --with-otr[=yes|no|static] Build with OTR support - also specifies
if it should be built into the main irssi
binary (static) or as a module (default)],
if test x$withval = xyes; then
want_otr=module
elif test x$withval = xstatic; then
want_otr=static
elif test x$withval = xmodule; then
want_otr=module
else
want_otr=no
fi,
want_otr=no)
AC_ARG_ENABLE(true-color,
[ --enable-true-color Build with true color support in terminal],
if test x$enableval = xno ; then
want_truecolor=no
else
want_truecolor=yes
fi,
want_truecolor=no)
AC_ARG_ENABLE(gregex,
[ --disable-gregex Build without GRegex (fall back to regex.h)],
if test x$enableval = xno ; then
want_gregex=no
else
want_gregex=yes
fi,
want_gregex=yes)
AC_ARG_ENABLE(utf8proc,
[ --disable-utf8proc Build without Julia's utf8proc],
if test x$enableval = xno ; then
want_utf8proc=no
else
want_utf8proc=yes
fi,
want_utf8proc=yes)
AC_ARG_WITH(capsicum,
[ --with-capsicum Build with Capsicum support],
if test x$withval = xno; then
want_capsicum=no
else
want_capsicum=yes
fi,
want_capsicum=yes)
dnl **
dnl ** just some generic stuff...
dnl **
dnl * OS specific options
case "$host_os" in
hpux*)
CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED"
;;
*)
;;
esac
AC_SEARCH_LIBS([socket], [network socket])
AC_SEARCH_LIBS([inet_addr], [nsl])
dnl * gcc specific options
if test "x$ac_cv_prog_gcc" = "xyes"; then
CFLAGS="$CFLAGS -Wall"
fi
AC_CHECK_TYPE(socklen_t, ,
[AC_DEFINE([socklen_t], [int], [Define to 'int' if <sys/socket.h> doesn't define.])], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
])
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(off_t)
if test $ac_cv_sizeof_off_t = 8; then
offt_64bit=yes
else
offt_64bit=no
fi
dnl **
dnl ** check for socks
dnl **
if test "x$want_socks" = "xyes"; then
AC_CHECK_LIB(socks, connect, [
AC_DEFINE(HAVE_SOCKS,, Build with socks support)
LIBS="$LIBS -lsocks"
AC_CHECK_HEADER(socks.h, [
AC_DEFINE(HAVE_SOCKS_H)
CFLAGS="$CFLAGS -DSOCKS"
AC_MSG_RESULT(["socks5 library found, building with it"])
], [
AC_MSG_RESULT(["socks4 library found, building with it"])
CFLAGS="$CFLAGS -Dconnect=Rconnect -Dgetsockname=Rgetsockname -Dgetpeername=Rgetpeername -Dbind=Rbind -Daccept=Raccept -Dlisten=Rlisten -Dselect=Rselect"
])
])
fi
dnl **
dnl ** fe-text checks
dnl **
for try in 1 2; do
if test $try = 1; then
glib_modules=gmodule
else
echo "*** trying without -lgmodule"
glib_modules=
fi
AM_PATH_GLIB_2_0(2.32.0,,, $glib_modules)
if test "$GLIB_LIBS"; then
if test $glib_modules = gmodule; then
AC_DEFINE(HAVE_GMODULE)
have_gmodule=yes
fi
break
fi
done
if test -z "$GLIB_LIBS"; then
echo
echo "*** If you don't have GLIB, you can get it from ftp://ftp.gtk.org/pub/glib/"
echo "*** We recommend you get the latest stable GLIB 2 version."
echo "*** Compile and install it, and make sure pkg-config finds it,"
echo "*** by adding the path where the .pc file is located to PKG_CONFIG_PATH"
echo -n "*** Or alternatively install your distribution's package"
if test -f /etc/debian_version; then
echo :
echo "*** sudo apt-get install libglib2.0-dev"
elif test -f /etc/redhat-release; then
echo " (glib2-devel)"
else
echo .
fi
echo
AC_ERROR([GLIB is required to build irssi.])
fi
LIBS="$LIBS $GLIB_LIBS"
GLIB_TESTS
dnl **
dnl ** OpenSSL checks
dnl **
PKG_CHECK_MODULES([OPENSSL], [openssl], [
CFLAGS="$CFLAGS $OPENSSL_CFLAGS"
LIBS="$LIBS $OPENSSL_LIBS"
], [
AC_CHECK_LIB([ssl], [SSL_library_init], [
LIBS="$LIBS -lssl -lcrypto"
], [
AC_MSG_ERROR([The OpenSSL library was not found])
])
])
dnl **
dnl ** utf8proc
dnl **
if test "x$want_utf8proc" != "xno"; then
AC_CHECK_HEADER([utf8proc.h], [
AC_CHECK_LIB([utf8proc], [utf8proc_version], [
want_utf8proc=yes
AC_DEFINE(HAVE_LIBUTF8PROC,, [Define to 1 if you have the `utf8proc' library (-lutf8proc).])
LIBS="$LIBS -lutf8proc"
], [
want_utf8proc="no, library not found"
])
], [
want_utf8proc="no, library header not found"
])
fi
dnl **
dnl ** curses checks
dnl **
if test "x$want_textui" != "xno"; then
TEXTUI_NO_LIBS="$LIBS"
LIBS=
AC_SEARCH_LIBS([setupterm], [tinfo ncursesw ncurses terminfo], [want_textui=yes], [
AC_ERROR(Terminfo not found - install libncurses-dev or ncurses-devel package)
want_textui="no, Terminfo not found"
])
TEXTUI_LIBS="$LIBS"
AC_SUBST(TEXTUI_LIBS)
LIBS="$TEXTUI_NO_LIBS"
AC_CHECK_HEADER([term.h], [
AC_DEFINE(HAVE_TERM_H, [], [Define to 1 if you have the `term.h' header.])
])
fi
dnl **
dnl ** irssifuzzer checks
dnl **
if test "$want_irssifuzzer" != "no"; then
dnl * we need to build with -fsanitize-coverage=trace-pc-guard
dnl * otherwise fuzzer won't be very successful at finding bugs :)
if test -z "$SANFLAGS"; then
SANFLAGS="-g -fsanitize=address -fsanitize-coverage=trace-pc-guard"
fi
CFLAGS="$CFLAGS $SANFLAGS"
CXXFLAGS="$CXXFLAGS $SANFLAGS"
AC_MSG_CHECKING(for fuzzer library)
if test -z "$fuzzerlibpath"; then
AC_MSG_RESULT([not found, building without fuzzer front end])
want_irssifuzzer=no
else
FUZZER_LIBS="$fuzzerlibpath"
AC_SUBST(FUZZER_LIBS)
fi
fi
dnl **
dnl ** perl checks
dnl **
if test "$want_perl" != "no"; then
AC_MSG_CHECKING(for working Perl support)
if test -z "$perlpath"; then
perl_check_error="perl binary not found"
else
PERL_CFLAGS=`$perlpath -MExtUtils::Embed -e ccopts 2>/dev/null`
fi
if test "x$ac_cv_prog_gcc" = "xyes" -a -z "`echo $host_os|grep 'bsd\|linux'`"; then
dnl * several systems have Perl compiled with native compiler
dnl * but irssi is being compiled with GCC. Here we try to
dnl * fix those command line options a bit so GCC won't
dnl * complain about them. Normally there's only few options
dnl * that we want to keep:
dnl * -Ddefine -Uundef -I/path -fopt -mopt -iwithsysroot
PERL_CFLAGS=`echo $PERL_CFLAGS | $perlpath -pe 's/^(.* )?-@<:@^DUIifm@:>@@<:@^ @:>@+/\1/g; s/^(.* )?\+@<:@^ @:>@+/\1/g'`
PERL_EXTRA_OPTS="CCCDLFLAGS=\"-fPIC\""
AC_SUBST(PERL_EXTRA_OPTS)
fi
if test -z "$PERL_CFLAGS"; then
if test -n "$perl_check_error"; then
perl_check_error="Error getting perl CFLAGS"
fi
AC_MSG_RESULT([not found, building without Perl])
want_perl=no
else
PERL_LDFLAGS=`$perlpath -MExtUtils::Embed -e ldopts 2>/dev/null`
dnl * remove all database stuffs
dnl * nsl is already in ldflags
dnl * libc is of course linked without needing -lc
dnl * -rdynamic must not be in LIBADD line
for word in -ldb -ldbm -lndbm -lgdbm -lc -rdynamic; do
PERL_LDFLAGS=`echo $PERL_LDFLAGS | $sedpath -e "s/$word //" -e "s/$word$//"`
done
case "$host_os" in
linux*)
PERL_LDFLAGS=`echo $PERL_LDFLAGS | $sedpath -e 's/-lposix //' -e 's/-lposix$//'`
;;
hpux*)
if test "x$ac_cv_prog_gcc" = "xyes"; then
PERL_CFLAGS=`echo $PERL_CFLAGS | $sedpath -e 's/-Ae //' -e 's/-Ae$//'`
PERL_LDFLAGS=`echo $PERL_LDFLAGS | $sedpath -e 's/-Ae //' -e 's/-Ae$//'`
fi
;;
*)
;;
esac
dnl * check that perl's ldflags actually work
echo "#include <EXTERN.h>" > conftest.c
echo "#include <perl.h>" >> conftest.c
echo "int main(){perl_alloc(); return 0;}" >> conftest.c
$CC $CFLAGS $PERL_CFLAGS conftest.c -o conftest $LDFLAGS $PERL_LDFLAGS 2> perl.error.tmp > /dev/null
if test ! -s conftest -a "x$ignore_perl_errors" = "x"; then
perl_check_error="Error linking with perl libraries: $PERL_LDFLAGS: `cat perl.error.tmp`"
AC_MSG_RESULT([error linking with perl libraries, building without Perl])
want_perl=no
fi
rm -f perl.error.tmp
fi
if test "x$want_perl" != "xno"; then
AC_MSG_RESULT(ok)
if test "x$want_perl" = "xstatic"; then
dnl * building with static perl support
dnl * all PERL_LDFLAGS linking is done in fe-text
PERL_LINK_FLAGS="$PERL_LDFLAGS"
PERL_LINK_LIBS="../perl/libperl_core_static.la"
PERL_FE_LINK_LIBS="../perl/libfe_perl_static.la"
PERL_LDFLAGS=
AC_DEFINE(HAVE_STATIC_PERL)
dnl * build only static library of perl module
perl_module_lib=
perl_module_fe_lib=
perl_static_lib=libperl_core_static.la
perl_static_fe_lib=libfe_perl_static.la
else
dnl * build dynamic library of perl module
perl_module_lib=libperl_core.la
perl_module_fe_lib=libfe_perl.la
perl_static_lib=
perl_static_fe_lib=
fi
if test "x$want_staticperllib" = "xyes"; then
PERL_MM_PARAMS="$PERL_MM_PARAMS LINKTYPE=static"
PERL_LINK_LIBS="$PERL_LINK_LIBS ../perl/common/blib/arch/auto/Irssi/Irssi.a ../perl/irc/blib/arch/auto/Irssi/Irc/Irc.a ../perl/ui/blib/arch/auto/Irssi/UI/UI.a ../perl/textui/blib/arch/auto/Irssi/TextUI/TextUI.a"
PERL_STATIC_LIBS=1
else
PERL_STATIC_LIBS=0
fi
# remove any prefix from PERL_MM_OPT
PERL_MM_OPT=`perl -MText::ParseWords -e 'sub qu{$_=shift;s{^(.*?)=(.*)$}{($a,$b)=($1,$2);$b=~s/"/\\\\"/g;qq{$a="$b"}}ge if /@<:@\s"@:>@/;$_} local $,=" "; print map qu($_), grep !/^(INSTALL_BASE|PREFIX)=/, shellwords(@ARGV)' "$PERL_MM_OPT"`
# figure out the correct @INC path - we'll need to do this
# through MakeMaker since it's difficult to get it right
# otherwise.
$perlpath -MExtUtils::MakeMaker -e 'WriteMakefile(NAME => "test", MAKEFILE => "Makefile.test", FIRST_MAKEFILE => "/dev/null", NO_META => 1, NO_MYMETA => 1);' $PERL_MM_PARAMS >/dev/null
echo 'show-INSTALLDIRS:' >> Makefile.test
echo ' @echo $(INSTALLDIRS)' >> Makefile.test
perl_INSTALLDIRS=`$am_make -s -f Makefile.test show-INSTALLDIRS`
if test "x$perl_INSTALLDIRS" = "xsite"; then
perl_library_dir="site default"
perl_INSTALL_VAR=INSTALLSITEARCH
elif test "x$perl_INSTALLDIRS" = "xvendor"; then
perl_library_dir="vendor default"
perl_INSTALL_VAR=INSTALLVENDORARCH
else
perl_library_dir="module default"
perl_INSTALL_VAR=INSTALLARCHLIB
fi
echo 'show-ARCHLIB:' >> Makefile.test
echo ' @echo $('"$perl_INSTALL_VAR"')' >> Makefile.test
perl_use_lib=`$am_make -s -f Makefile.test show-ARCHLIB`
rm -f Makefile.test
if test "x$perl_set_use_lib" = "xyes"; then
if $perlpath -e 'exit ! grep $_ eq $ARGV@<:@0@:>@, grep /^\//, @INC' "$perl_use_lib"; then
perl_library_dir="other path in @INC"
perl_set_use_lib=no
else
perl_library_dir="prepends to @INC with /set perl_use_lib"
PERL_USE_LIB="$perl_use_lib"
fi
fi
AC_SUBST(perl_module_lib)
AC_SUBST(perl_static_lib)
AC_SUBST(perl_module_fe_lib)
AC_SUBST(perl_static_fe_lib)
AC_SUBST(PERL_LINK_FLAGS)
AC_SUBST(PERL_LINK_LIBS)
AC_SUBST(PERL_FE_LINK_LIBS)
AC_SUBST(PERL_LDFLAGS)
AC_SUBST(PERL_CFLAGS)
AC_SUBST(PERL_USE_LIB)
AC_SUBST(PERL_MM_OPT)
AC_SUBST(PERL_MM_PARAMS)
AC_SUBST(PERL_STATIC_LIBS)
fi
fi
dnl **
dnl ** check for capsicum
dnl **
if test "x$want_capsicum" = "xyes"; then
AC_CHECK_LIB(c, cap_enter, [
AC_CHECK_LIB(nv, nvlist_create, [
AC_DEFINE(HAVE_CAPSICUM,, Build with Capsicum support)
LIBS="$LIBS -lnv"
], [
want_capsicum="no, nvlist_create not found"
])
], [
want_capsicum="no, cap_enter not found"
])
fi
dnl **
dnl ** OTR checks
dnl **
have_otr=no
if test "x$want_otr" != "xno"; then
AM_PATH_LIBGCRYPT(1:1.2.0, [], [AC_ERROR(libgcrypt 1.2.0 or newer is required.)])
AM_PATH_LIBOTR(4.1.0, [], [AC_ERROR([libotr 4.1.0 or newer is required.])])
OTR_CFLAGS="$LIBOTR_CFLAGS $LIBGCRYPT_CFLAGS"
OTR_LDFLAGS="$LIBOTR_LIBS $LIBGCRYPT_LIBS"
AC_SUBST(otr_module_lib)
AC_SUBST(otr_static_lib)
if test "x$want_otr" != "xno"; then
if test "x$want_otr" = "xstatic"; then
otr_module_lib=
otr_static_lib=libotr_core_static.la
OTR_LINK_LIBS="../otr/libotr_core_static.la"
OTR_LINK_FLAGS="$OTR_LDFLAGS"
AC_DEFINE(HAVE_STATIC_OTR)
else
otr_module_lib=libotr_core.la
otr_static_lib=
fi
fi
AC_SUBST(otr_module_lib)
AC_SUBST(otr_static_lib)
AC_SUBST(OTR_CFLAGS)
AC_SUBST(OTR_LDFLAGS)
AC_SUBST(OTR_LINK_LIBS)
AC_SUBST(OTR_LINK_FLAGS)
have_otr=yes
fi
dnl ** check what we want to build
AM_CONDITIONAL(BUILD_TEXTUI, test "$want_textui" = "yes")
AM_CONDITIONAL(BUILD_IRSSIBOT, test "$want_irssibot" = "yes")
AM_CONDITIONAL(BUILD_IRSSIFUZZER, test "$want_irssifuzzer" = "yes")
AM_CONDITIONAL(BUILD_IRSSIPROXY, test "$want_irssiproxy" = "yes")
AM_CONDITIONAL(HAVE_PERL, test "$want_perl" != "no")
AM_CONDITIONAL(HAVE_CAPSICUM, test "x$want_capsicum" = "xyes")
AM_CONDITIONAL(USE_GREGEX, test "x$want_gregex" = "xyes")
AM_CONDITIONAL(HAVE_OTR, test "x$have_otr" != "xno")
# move LIBS to PROG_LIBS so they're not tried to be used when linking eg. perl libraries
PROG_LIBS=$LIBS
LIBS=
AC_SUBST(PROG_LIBS)
dnl **
dnl ** Keep all the libraries here so each frontend doesn't need to
dnl ** keep track of them all
dnl **
dnl ** (these could be made configurable)
CHAT_MODULES="irc"
irc_MODULES="dcc flood notifylist"
if test -n "$build_modules"; then
irc_MODULES="$irc_MODULES $build_modules"
fi
dnl ****************************************
AC_SUBST(CHAT_MODULES)
AC_SUBST(irc_MODULES)
CORE_LIBS="../core/libcore.a ../lib-config/libirssi_config.a"
FE_COMMON_LIBS=""
CHAT_LIBS=""
for c in $CHAT_MODULES; do
CHAT_LIBS="$CHAT_LIBS ../$c/lib$c.a ../$c/core/lib${c}_core.a"
if test -f $srcdir/src/fe-common/$c/module.h; then
FE_COMMON_LIBS="$FE_COMMON_LIBS../fe-common/$c/libfe_common_$c.a "
fi
for s in `eval echo \\$${c}_MODULES`; do
CHAT_LIBS="$CHAT_LIBS ../$c/$s/lib${c}_$s.a"
if test -f $srcdir/src/fe-common/$c/$s/module.h; then
FE_COMMON_LIBS="$FE_COMMON_LIBS../fe-common/$c/$s/libfe_${c}_$s.a "
fi
done
done
FE_COMMON_LIBS="$FE_COMMON_LIBS../fe-common/core/libfe_common_core.a"
dnl ** common libraries needed by frontends
COMMON_NOUI_LIBS="$CHAT_LIBS $CORE_LIBS"
COMMON_LIBS="$FE_COMMON_LIBS $COMMON_NOUI_LIBS"
AC_SUBST(COMMON_NOUI_LIBS)
AC_SUBST(COMMON_LIBS)
if test "x$want_truecolor" = "xyes"; then
AC_DEFINE([TERM_TRUECOLOR], [], [true color support in terminal])
else
want_truecolor=no
fi
if test "x$want_gregex" = "xyes"; then
AC_DEFINE([USE_GREGEX], [], [use GRegex for regular expressions])
else
want_gregex=no
fi
AC_DEFINE([FHS_PREFIX], [""], [Alternate filesystem prefix for Termux])
AH_TEMPLATE(HAVE_GMODULE)
AH_TEMPLATE(HAVE_SOCKS_H, [misc..])
AH_TEMPLATE(HAVE_STATIC_PERL)
AH_TEMPLATE(HAVE_STATIC_OTR)
AH_TEMPLATE(PRIuUOFF_T, [printf()-format for uoff_t, eg. "u" or "lu" or "llu"])
AH_TEMPLATE(UOFF_T_INT, [What type should be used for uoff_t])
AH_TEMPLATE(UOFF_T_LONG)
AH_TEMPLATE(UOFF_T_LONG_LONG)
AC_CONFIG_FILES([
Makefile
src/Makefile
src/core/Makefile
src/irc/Makefile
src/irc/core/Makefile
src/irc/dcc/Makefile
src/irc/notifylist/Makefile
src/irc/proxy/Makefile
src/irc/flood/Makefile
src/fe-common/Makefile
src/fe-common/core/Makefile
src/fe-common/irc/Makefile
src/fe-common/irc/dcc/Makefile
src/fe-common/irc/notifylist/Makefile
src/fe-fuzz/Makefile
src/fe-fuzz/irc/Makefile
src/fe-fuzz/irc/core/Makefile
src/fe-fuzz/fe-common/Makefile
src/fe-fuzz/fe-common/core/Makefile
src/fe-none/Makefile
src/fe-text/Makefile
src/lib-config/Makefile
src/perl/Makefile
src/perl/common/Makefile.PL
src/perl/irc/Makefile.PL
src/perl/ui/Makefile.PL
src/perl/textui/Makefile.PL
src/otr/Makefile
scripts/Makefile
scripts/examples/Makefile
tests/Makefile
tests/fe-common/Makefile
tests/fe-common/core/Makefile
tests/fe-text/Makefile
tests/irc/Makefile
tests/irc/core/Makefile
tests/irc/flood/Makefile
docs/Makefile
docs/help/Makefile
docs/help/in/Makefile
utils/Makefile
themes/Makefile
irssi-1.pc
])
dnl ** make the paths like include headers later
AC_CONFIG_LINKS([irssi/irssi-config.h:irssi-config.h])
AC_LINK_FILES([$srcdir/src],[irssi/src])
AC_OUTPUT
$LN_S ../irssi-version.h irssi/irssi-version.h
dnl ** for building from objdir
old_dir=`pwd` && cd $srcdir && whole_dir=`pwd` && cd $old_dir
if test "x$old_dir" != "x$whole_dir"; then
$LN_S $srcdir/irssi-version.h irssi-version.h
if test "x$want_perl" != "xno"; then
subdirfiles=""
for i in $whole_dir/src/perl/common $whole_dir/src/perl/irc $whole_dir/src/perl/ui $whole_dir/src/perl/textui; do
subdirfiles=`echo $subdirfiles $i/typemap $i/*.h $i/*.pm $i/*.xs`
done
for file in $whole_dir/src/perl/module.h $subdirfiles; do
link=`echo $file|$sedpath "s?$whole_dir/??"`
rm -f $link
$LN_S $file $link
done
fi
fi
echo
echo "Building text frontend ........... : $want_textui"
echo "Building irssi bot ............... : $want_irssibot"
echo "Building irssi proxy ............. : $want_irssiproxy"
if test "x$have_gmodule" = "xyes"; then
echo "Building with module support ..... : yes"
else
echo "Building with module support : NO!! /LOAD will not work!"
echo " - You're missing gmodule (comes with glib) for some reason,"
echo " or it doesn't work in your system."
fi
if test "x$want_perl" = "xstatic"; then
echo "Building with Perl support ....... : static (in irssi binary)"
elif test "x$want_perl" = "xmodule"; then
echo "Building with Perl support ....... : module"
else
if test -z "$perl_check_error"; then
echo "Building with Perl support ....... : no"
else
echo "Building with Perl support ....... : NO!"
echo " - $perl_check_error"
if test -f /etc/debian_version; then
echo " - Try: sudo apt-get install libperl-dev"
elif test -f /etc/redhat-release; then
echo " - Try installing perl-devel"
fi
fi
fi
if test "x$want_perl" != "xno" -a "x$perl_mod_error" != "x"; then
echo " - NOTE: Perl support will be compiled statically to irssi, not as"
echo " a module as requested. Reason:"
echo " $perl_mod_error"
if test -f /etc/debian_version; then
echo " - Try: sudo apt-get install libperl-dev"
fi
fi
if test "x$want_perl" != "xno"; then
echo "Perl library directory ........... : ($perl_library_dir - $perl_use_lib)"
if test "x$perl_prefix_note" = "xyes"; then
echo " - NOTE: This was automatically set to the same directory you gave with"
echo " --prefix. If you want the perl libraries to install to their 'correct'"
echo " path, you'll need to give --with-perl-lib=site option to configure."
echo " Anyway, installing perl to this directory should work just as well."
fi
fi
echo "Install prefix ................... : $prefix"
echo
echo "Building with 64bit DCC support .. : $offt_64bit"
echo "Building with true color support.. : $want_truecolor"
echo "Building with GRegex ............. : $want_gregex"
echo "Building with Capsicum ........... : $want_capsicum"
echo "Building with utf8proc ........... : $want_utf8proc"
if test "x$want_otr" = "xstatic"; then
echo "Building with OTR support ........ : static (in irssi binary)"
elif test "x$want_otr" = "xmodule"; then
echo "Building with OTR support ........ : module"
else
echo "Building with OTR support ........ : no"
fi
echo
echo "If there are any problems, read the INSTALL file."

21
docs/Makefile.am Normal file
View file

@ -0,0 +1,21 @@
man_MANS = \
irssi.1
doc_DATA = \
capsicum.txt \
design.html \
design.txt \
formats.txt \
manual.txt \
faq.html \
faq.txt \
perl.txt \
signals.txt \
special_vars.txt \
startup-HOWTO.html \
startup-HOWTO.txt
EXTRA_DIST = $(doc_DATA) $(man_MANS) \
meson.build
SUBDIRS = help

View file

@ -1,110 +0,0 @@
<base href='https://irssi.org/New-users/'>
<h1>New users guide</h1>
<section id="new-to-irc">
<h2>New to IRC</h2>
<p>Internet Relay Chat was created in 1988 and has hardly changed. It can be used to exchange text messages (one message = single line) with other people, either privately (called query, PM, private message, MSG) or in a room (channel). Pictures are shared by uploading them to a temporary host like <a class="reference external" href="https://pomf.lain.la/">https://pomf.lain.la/</a> and then pasting the HTTP links. Code snippets or longer texts are shared by pasting them to a Pastebin like <a class="reference external" href="https://paste.opensuse.org/">https://paste.opensuse.org/</a> and then sharing the HTTP link.</p>
<p>IRC does not have message history. You can only receive replies while your computer is turned on and connected to the channel you want to follow. Some people run their IRC programs on remote servers for that reason.</p>
<p>IRC is organised into networks. Each network consists of many servers. It (mostly) does not matter which server you connect to as long as it belongs to the network you want to use. Irssi supports connections to many networks at the same time.</p>
<p>Each network contains many channels, rooms that are often dedicated to discussing a specific topic. You can find many channels on <a class="reference external" href="https://netsplit.de/">https://netsplit.de/</a> or using a search engine with the keyword “IRC”. Irssi supports joining many channels at the same time.</p>
<p>There is a rather large IRC network catering to free and open-source software and peer directed projects at <a class="reference external" href="https://libera.chat/">https://libera.chat/</a> and a smaller one at <a class="reference external" href="https://www.oftc.net/">https://www.oftc.net/</a> many free software projects still have support channels on these IRC networks (although some have moved to Matrix or proprietary platforms like Discord).</p>
</section>
<section id="first-start">
<h2>First start</h2>
<p>After (compiling and) installing Irssi, to start it, open a shell (Terminal) and type:</p>
<div class="highlight-default notranslate"><div><pre>irssi
</pre></div>
</div>
<p>You should be greeted by a blinking cursor behind <code class="docutils literal notranslate">[(status)]</code>. You are now in the status window of Irssi. Window is the Irssi name for what you might nowadays call a “Web browser tab”.</p>
<p>If youre confused about what you are seeing on the Irssi screen, you can find an annotated screenshot of it at <a class="reference internal" href="../User-interface/">User interface</a>.</p>
<p>If you want, you can pick a nick name (handle) that will be shown to others reading your messages now, by typing</p>
<div class="highlight-default notranslate"><div><pre>/set nick whatyouwant
</pre></div>
</div>
<p>Each command or message can be sent by pressing Enter. Commands in Irssi start with a <code class="docutils literal notranslate">/</code>. If there is no <code class="docutils literal notranslate">/</code>, then the line that you wrote will be sent as a message to the channel that you have open, for everyone to see.</p>
<section id="leaving">
<h3>Leaving</h3>
<p>Type <code class="docutils literal notranslate">/quit</code> to get out of Irssi.</p>
</section>
</section>
<section id="connecting-to-a-network">
<h2>Connecting to a network</h2>
<p>Irssi comes with some predefined networks. You can see the current list of networks by typing</p>
<div class="highlight-default notranslate"><div><pre>/network
</pre></div>
</div>
<p>(the list will be shown in your status window)</p>
<p>To connect to one of the networks in the list, type <code class="docutils literal notranslate">/connect networkname</code>, for example:</p>
<div class="highlight-default notranslate"><div><pre>/connect liberachat
</pre></div>
</div>
<p>You should see several messages scroll by. After a while, you should be connected to the Libera Chat network.</p>
<div class="admonition attention">
<p class="admonition-title">Attention</p>
<p>Irssi version 1.2 or older may be lacking the liberachat network entry. See <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberachat">https://github.com/shabble/irssi-docs/wiki/liberachat</a> for how to add it.</p>
</div>
<section id="nickname-registration">
<h3>Nickname registration</h3>
<p>Many IRC networks (but not all) offer a way to register a user account. Sometimes (but not on all networks) the account registration also includes reserving a nick for you. <em>How</em> to register also differs by network. Some <em>channels</em> only allow users with registered accounts to join them, so it may be very important for you to register a user account.</p>
<p>User accounts are always specific to a network.</p>
<p>For the Libera Chat network, you can find instructions how to register and set up your account with Irssi on <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberachat#configure-sasl-automated-log-in">https://github.com/shabble/irssi-docs/wiki/liberachat#configure-sasl-automated-log-in</a></p>
</section>
</section>
<section id="joining-a-channel">
<h2>Joining a channel</h2>
<p>Once you are connected to a network, you can join channels by typing <code class="docutils literal notranslate">/join #channelname</code>, for example:</p>
<div class="highlight-default notranslate"><div><pre>/join #irssi
</pre></div>
</div>
<p>Now, a new window will open and you can send messages to the channel.</p>
<section id="changing-windows">
<h3>Changing windows</h3>
<p>You can change between windows using the <code class="docutils literal notranslate">Ctrl</code>+<code class="docutils literal notranslate">n</code> or <code class="docutils literal notranslate">Ctrl</code>+<code class="docutils literal notranslate">p</code> keys, orif your terminal is configured properlyusing <code class="docutils literal notranslate">Alt</code>+<code class="docutils literal notranslate">1</code>, <code class="docutils literal notranslate">Alt</code>+<code class="docutils literal notranslate">2</code>, … See <a class="reference internal" href="../documentation/help/bind_-list/">bind -list</a> for a list of all default key bindings.</p>
</section>
<section id="removing-clutter">
<h3>Removing clutter</h3>
<p>By default, Irssi shows when someone joins or leaves a channel. These messages can waste a lot of lines and obscure the actual chat. To hide them, type</p>
<div class="highlight-default notranslate"><div><pre>/window hidelevel +joins +parts +quits
</pre></div>
</div>
<p>To get them back</p>
<div class="highlight-default notranslate"><div><pre>/window hidelevel -joins -parts -quits
</pre></div>
</div>
<p>If you want to hide them by default, <code class="docutils literal notranslate">/set window_default_hidelevel hidden joins parts quits</code></p>
</section>
</section>
<section id="adding-a-new-network">
<h2>Adding a new network</h2>
<p>If you want to join a network that is not there, you first need to find at least one server of that network. Lets say you have found the room <a class="reference external" href="https://netsplit.de/channels/details.php?room=%23hackint&amp;net=hackint">#hackint</a> on netsplit.de and want to join it. Then you can find that the <a class="reference external" href="https://netsplit.de/servers/?net=hackint">server</a> is irc.hackint.org, port 6697, SSL (TLS) on. To add it to Irssi, use the commands:</p>
<div class="highlight-default notranslate"><div><pre>/network add hackint
/server add -tls -network hackint irc.hackint.org 6697
</pre></div>
</div>
<p>Then, you can connect to the newly added network with</p>
<div class="highlight-default notranslate"><div><pre>/connect hackint
</pre></div>
</div>
<section id="multiple-networks">
<h3>Multiple networks</h3>
<p>If you are connected to multiple networks, you can change which one you are “talking” to (which one to send commands) by using the <code class="docutils literal notranslate">Ctrl</code>+<code class="docutils literal notranslate">x</code> key in the status window.</p>
</section>
</section>
<section id="on-line-help">
<h2>On-line help</h2>
<p>Most /commands have a help page, you can read it with</p>
<div class="highlight-default notranslate"><div><pre>/help commandname
</pre></div>
</div>
<p>or <a class="reference internal" href="../documentation/help/">on-line</a>.</p>
<p>The settings that can be changed with /SET are described on <a class="reference internal" href="../documentation/settings/">Settings Documentation</a> the settingshelp <a class="reference internal" href="#about-scripts">script</a> can be used to read it from within <code class="docutils literal notranslate">/help</code></p>
</section>
<section id="about-scripts">
<h2>About Scripts</h2>
<p>You can enhance your Irssi by installing scripts. Many Perl scripts written by other Irssi users can be found on <a class="reference external" href="https://scripts.irssi.org/">https://scripts.irssi.org/</a></p>
<p>Most of them should be compatible with Irssi 1.4 (but some may not, also see the Full Change log for some incompatible ones)</p>
</section>
<section id="about-themes">
<h2>About Themes</h2>
<p>Irssis look can be thoroughly changed with themes. Many themes created by other Irssi users can be found on <a class="reference external" href="https://themes.irssi.org/">https://themes.irssi.org/</a></p>
<p>If you want to modify the look of Irssi yourself, the <em>default</em> theme which can be found in your <code class="docutils literal notranslate">~/.irssi</code> folder is a good starting point. It also has a few comments explaining what some of the abstracts are used for</p>
</section>

View file

@ -1,193 +0,0 @@
# New users guide #
## New to IRC ##
Internet Relay Chat was created in 1988 and has hardly changed. It can be used
to exchange text messages (one message = single line) with other people, either
privately (called query, PM, private message, MSG) or in a room (channel).
Pictures are shared by uploading them to a temporary host like [1]https://
pomf.lain.la/ and then pasting the HTTP links. Code snippets or longer texts
are shared by pasting them to a Pastebin like [2]https://paste.opensuse.org/
and then sharing the HTTP link.
IRC does not have message history. You can only receive replies while your
computer is turned on and connected to the channel you want to follow. Some
people run their IRC programs on remote servers for that reason.
IRC is organised into networks. Each network consists of many servers. It
(mostly) does not matter which server you connect to as long as it belongs to
the network you want to use. Irssi supports connections to many networks at the
same time.
Each network contains many channels, rooms that are often dedicated to
discussing a specific topic. You can find many channels on [3]https://
netsplit.de/ or using a search engine with the keyword “IRC”. Irssi supports
joining many channels at the same time.
There is a rather large IRC network catering to free and open-source software
and peer directed projects at [4]https://libera.chat/ and a smaller one at [5]
https://www.oftc.net/ many free software projects still have support channels
on these IRC networks (although some have moved to Matrix or proprietary
platforms like Discord).
## First start ##
After (compiling and) installing Irssi, to start it, open a shell (Terminal)
and type:
irssi
You should be greeted by a blinking cursor behind [(status)]. You are now in
the status window of Irssi. Window is the Irssi name for what you might
nowadays call a “Web browser tab”.
If youre confused about what you are seeing on the Irssi screen, you can find
an annotated screenshot of it at [6]User interface.
If you want, you can pick a nick name (handle) that will be shown to others
reading your messages now, by typing
/set nick whatyouwant
Each command or message can be sent by pressing Enter. Commands in Irssi start
with a /. If there is no /, then the line that you wrote will be sent as a
message to the channel that you have open, for everyone to see.
### Leaving ###
Type /quit to get out of Irssi.
## Connecting to a network ##
Irssi comes with some predefined networks. You can see the current list of
networks by typing
/network
(the list will be shown in your status window)
To connect to one of the networks in the list, type /connect networkname, for
example:
/connect liberachat
You should see several messages scroll by. After a while, you should be
connected to the Libera Chat network.
Attention
Irssi version 1.2 or older may be lacking the liberachat network entry. See [7]
https://github.com/shabble/irssi-docs/wiki/liberachat for how to add it.
### Nickname registration ###
Many IRC networks (but not all) offer a way to register a user account.
Sometimes (but not on all networks) the account registration also includes
reserving a nick for you. How to register also differs by network. Some
channels only allow users with registered accounts to join them, so it may be
very important for you to register a user account.
User accounts are always specific to a network.
For the Libera Chat network, you can find instructions how to register and set
up your account with Irssi on [8]https://github.com/shabble/irssi-docs/wiki/
liberachat#configure-sasl-automated-log-in
## Joining a channel ##
Once you are connected to a network, you can join channels by typing /join #
channelname, for example:
/join #irssi
Now, a new window will open and you can send messages to the channel.
### Changing windows ###
You can change between windows using the Ctrl+n or Ctrl+p keys, orif your
terminal is configured properlyusing Alt+1, Alt+2, … See [9]bind -list for a
list of all default key bindings.
### Removing clutter ###
By default, Irssi shows when someone joins or leaves a channel. These messages
can waste a lot of lines and obscure the actual chat. To hide them, type
/window hidelevel +joins +parts +quits
To get them back
/window hidelevel -joins -parts -quits
If you want to hide them by default, /set window_default_hidelevel hidden joins
parts quits
## Adding a new network ##
If you want to join a network that is not there, you first need to find at
least one server of that network. Lets say you have found the room [10]#
hackint on netsplit.de and want to join it. Then you can find that the [11]
server is irc.hackint.org, port 6697, SSL (TLS) on. To add it to Irssi, use the
commands:
/network add hackint
/server add -tls -network hackint irc.hackint.org 6697
Then, you can connect to the newly added network with
/connect hackint
### Multiple networks ###
If you are connected to multiple networks, you can change which one you are
“talking” to (which one to send commands) by using the Ctrl+x key in the status
window.
## On-line help ##
Most /commands have a help page, you can read it with
/help commandname
or [12]on-line.
The settings that can be changed with /SET are described on [13]Settings
Documentation the settingshelp [14]script can be used to read it from within
/help
## About Scripts ##
You can enhance your Irssi by installing scripts. Many Perl scripts written by
other Irssi users can be found on [15]https://scripts.irssi.org/
Most of them should be compatible with Irssi 1.4 (but some may not, also see
the Full Change log for some incompatible ones)
## About Themes ##
Irssis look can be thoroughly changed with themes. Many themes created by
other Irssi users can be found on [16]https://themes.irssi.org/
If you want to modify the look of Irssi yourself, the default theme which can
be found in your ~/.irssi folder is a good starting point. It also has a few
comments explaining what some of the abstracts are used for
References:
[1] https://pomf.lain.la/
[2] https://paste.opensuse.org/
[3] https://netsplit.de/
[4] https://libera.chat/
[5] https://www.oftc.net/
[6] https://irssi.org/User-interface/
[7] https://github.com/shabble/irssi-docs/wiki/liberachat
[8] https://github.com/shabble/irssi-docs/wiki/liberachat#configure-sasl-automated-log-in
[9] https://irssi.org/documentation/help/bind_-list/
[10] https://netsplit.de/channels/details.php?room=%23hackint&net=hackint
[11] https://netsplit.de/servers/?net=hackint
[12] https://irssi.org/documentation/help/
[13] https://irssi.org/documentation/settings/
[14] https://irssi.org/New-users/#about-scripts
[15] https://scripts.irssi.org/
[16] https://themes.irssi.org/

View file

@ -9,13 +9,13 @@ To make Irssi enter capability mode on startup, add
capsicum = "yes"; capsicum = "yes";
awaylog_file = "~/irclogs/away.log"; awaylog_file = "~/irclogs/away.log";
to your ~/.irssi/config in the settings/core section, and restart the to your ~/.irssi/config and restart the client. Alternatively you can
client. Alternatively you can enter it "by hand", using the enter it "by hand", using the "/capsicum enter" command. From the security
"/capsicum enter" command. From the security point of view it's strongly point of view it's strongly preferable to use the former method, to avoid
preferable to use the former method, to avoid establishing connections establishing connections without the sandbox protection; the "/capsicum"
without the sandbox protection; the "/capsicum" command is only intended command is only intended for experimentation, and in cases where you need
for experimentation, and in cases where you need to do something that's not to do something that's not possible in capability mode - run scripts,
possible in capability mode - run scripts, for example - before continuing. for example - before continuing.
There is no way to leave the capability mode, apart from exiting Irssi. There is no way to leave the capability mode, apart from exiting Irssi.
When running in capability mode, there are certain restrictions - Irssi When running in capability mode, there are certain restrictions - Irssi

View file

@ -162,4 +162,4 @@ server reconnections and irc network splits</li>
<li>placing channels and queries in windows</li> <li>placing channels and queries in windows</li>
<li>nick completion</li> <li>nick completion</li>
<li>printing infomation of some events</li> <li>printing infomation of some events</li>
</ul> </ul>

View file

@ -78,4 +78,4 @@
<h3 id="q-how-to-pronounce-irssi">Q: How to pronounce Irssi?</h3> <h3 id="q-how-to-pronounce-irssi">Q: How to pronounce Irssi?</h3>
<p>A: Check <a href="/assets/irssi.wav">here</a></p> <p>A: Check <a href="/assets/irssi.wav">here</a></p>

13
docs/help/Makefile.am.gen Normal file
View file

@ -0,0 +1,13 @@
# Makefile.am is autogenerated by autogen.sh from Makefile.am.gen
helpdir = $(datadir)/irssi/help
help_DATA = \
@HELPFILES@
EXTRA_DIST = \
Makefile.am.gen \
$(help_DATA) \
meson.build
SUBDIRS = in

View file

@ -0,0 +1,5 @@
# Makefile.am is autogenerated by autogen.sh from Makefile.am.gen
EXTRA_DIST = \
Makefile.am.gen \
@HELPFILES@

View file

@ -17,15 +17,13 @@ Details:
Adds or removes a binding; the binding itself is case-sensitive and may Adds or removes a binding; the binding itself is case-sensitive and may
contain as many characters as you want. contain as many characters as you want.
Key bindings are case sensitive so uppercase letters mean you also have Uppercase characters usually indicate that you need to keep the shift-key
to use the shift key, except for ctrl which does not support shift but pressed to use the binding.
the keys must always be typed in uppercase.
%9Examples:%9 %9Examples:%9
/BIND /BIND
/BIND meta-c /CLEAR /BIND meta-c /CLEAR
/BIND meta-C /CYCLE
/BIND meta-q change_window 16 /BIND meta-q change_window 16
/BIND -delete meta-y /BIND -delete meta-y
/BIND ^W^C /WINDOW NEW HIDE /BIND ^W^C /WINDOW NEW HIDE

View file

@ -20,10 +20,9 @@
MODES A channel mode is modified. MODES A channel mode is modified.
MSGS Private messages. MSGS Private messages.
NICKS A nickname changes to another nickname. NICKS A nickname changes to another nickname.
NOTICES Private notices. NOTICES Notices sent from a nickname.
PARTS A nickname leaves a channel. PARTS A nickname leaves a channel.
PUBLIC Public messages in a channel. PUBLIC Public messages in a channel.
PUBNOTICES Public notices in a channel.
QUITS A nickname disconnects from IRC. QUITS A nickname disconnects from IRC.
SNOTES Notices sent from a server. SNOTES Notices sent from a server.
TOPICS A channel topic is modified. TOPICS A channel topic is modified.

View file

@ -5,7 +5,7 @@
%9Parameters:%9 %9Parameters:%9
The server to search on and the remote server to search on; if no arguments The server to search on and the remote sever to search on; if no arguments
are given, the active server will be used. are given, the active server will be used.
%9Description:%9 %9Description:%9

View file

@ -36,8 +36,8 @@
-cmdmax: Specifies the maximum number of commands to perform before -cmdmax: Specifies the maximum number of commands to perform before
starting the internal flood protection. starting the internal flood protection.
-sasl_mechanism Specifies the mechanism to use for the SASL authentication. -sasl_mechanism Specifies the mechanism to use for the SASL authentication.
Irssi supports: PLAIN, EXTERNAL, SCRAM-SHA-1, SCRAM-SHA-256 At the moment irssi only supports the 'plain' and the
and SCRAM-SHA-512 'external' mechanisms.
Use '' to disable the authentication. Use '' to disable the authentication.
-sasl_username Specifies the username to use during the SASL authentication. -sasl_username Specifies the username to use during the SASL authentication.
-sasl_password Specifies the password to use during the SASL authentication. -sasl_password Specifies the password to use during the SASL authentication.

View file

@ -20,10 +20,10 @@
%9Description:%9 %9Description:%9
Manipulate the text in the window to go to the given line number, or Manipulate the text in the window to go to a to the given line number, or
clear the buffers. clear the buffers.
The timestamp format is '[dd[.mm] | -<days ago>] hh:mi[:ss]'. The timestamp format is format is '[dd[.mm] | -<days ago>] hh:mi[:ss]'.
%9Examples:%9 %9Examples:%9

View file

@ -15,6 +15,7 @@
%9Examples:%9 %9Examples:%9
/TOGGLE resolve_prefer_ipv6
/TOGGLE channels_rejoin_unavailable ON /TOGGLE channels_rejoin_unavailable ON
%9See also:%9 SET %9See also:%9 SET

View file

@ -74,5 +74,5 @@
/WINDOW HIDELEVEL ^JOINS ^PARTS ^QUITS /WINDOW HIDELEVEL ^JOINS ^PARTS ^QUITS
/WINDOW LOGFILE ~/logs/notices.log /WINDOW LOGFILE ~/logs/notices.log
%9See also:%9 JOIN, LEVELS, LOG, QUERY, SET window_default_level, SET window_default_hidelevel %9See also:%9 JOIN, LEVELS, LOG, QUERY

View file

@ -116,7 +116,6 @@ install_data(
'whowas', 'whowas',
'window', 'window',
), ),
install_dir : helpdir, install_dir : helpdir)
)
# subdir('in') # subdir('in')

View file

@ -373,6 +373,9 @@
After connected to server, Irssi can automatically change your user After connected to server, Irssi can automatically change your user
mode. You can set it with /SET usermode <mode>, default is +i. mode. You can set it with /SET usermode <mode>, default is +i.
/SET resolve_prefer_ipv6 - If ON, prefer IPv6 for hosts that
have both v4 and v6 addresses.
5.5 Automatic reconnecting 5.5 Automatic reconnecting
If you get disconnected from server, Irssi will try to reconnect If you get disconnected from server, Irssi will try to reconnect

View file

@ -13,7 +13,6 @@ install_data(
'startup-HOWTO.html', 'startup-HOWTO.html',
'startup-HOWTO.txt', 'startup-HOWTO.txt',
), ),
install_dir : docdir, install_dir : docdir)
)
subdir('help') subdir('help')

View file

@ -205,12 +205,6 @@ Window::command(cmd)
Windowitem::command(cmd) Windowitem::command(cmd)
Send a command `cmd' (in current channel). The '/' char isn't needed. Send a command `cmd' (in current channel). The '/' char isn't needed.
version() - return client release date and time (format YYYYMMDD.hhmm)
parse_special(cmd, data="", flags=0)
Server::parse_special(cmd, data="", flags=0)
Windowitem::parse_special(cmd, data="", flags=0)
evaluate a string with special vars
*** Themes *** Themes
@ -522,8 +516,6 @@ Connect->{}
address - Address where we connected (irc.blah.org) address - Address where we connected (irc.blah.org)
port - Port where we connected port - Port where we connected
chatnet - Chat network chatnet - Chat network
chosen_family - IP family chosen to connect to
ipaddr - IP address connected to
password - Password we used in connection. password - Password we used in connection.
wanted_nick - Nick which we would prefer to use wanted_nick - Nick which we would prefer to use

View file

@ -1,52 +0,0 @@
<base href='https://irssi.org/documentation/qna/multi/'>
<h1>Right-aligned nicks</h1>
<p>To create a “tabular” effect of the chat view, or to align nick names in a column, you can use Irssis theme/format system. The basic commands are the following:</p>
<div class="highlight-default notranslate"><div><pre>/format own_msg {ownmsgnick $2 {ownnick $[-9]0}}$1
/format own_msg_channel {ownmsgnick $3 {ownnick $[-9]0}{msgchannel $1}}$2
/format pubmsg_me {pubmsgmenick $2 {menick $[-9]0}}$1
/format pubmsg_me_channel {pubmsgmenick $3 {menick $[-9]0}{msgchannel $1}}$2
/format pubmsg_hilight {pubmsghinick $0 $3 $[-9]1}$2
/format pubmsg_hilight_channel {pubmsghinick $0 $4 $[-9]1{msgchannel $2}}$3
/format pubmsg {pubmsgnick $2 {pubnick $[-9]0}}$1
/format pubmsg_channel {pubmsgnick $3 {pubnick $[-9]0}{msgchannel $1}}$2
</pre></div>
</div>
<p>These are copied from the default themes default values, which are responsible for displaying your own messages sent to a channel (<code class="docutils literal notranslate">own_msg</code>) as well as received messages (<code class="docutils literal notranslate">pubmsg</code>) and the two basic highlightings (<code class="docutils literal notranslate">me</code> and <code class="docutils literal notranslate">hilight</code>).</p>
<p>Then, in front of the argument that contains the nick name (<code class="docutils literal notranslate">$0</code> in most cases, but <code class="docutils literal notranslate">$1</code> in <code class="docutils literal notranslate">pubmsg_hilight</code>), an alignment modifier (see <a class="reference internal" href="../../settings/#a-b">Appendix B: Special Variables and Expandos</a>) has been added: <code class="docutils literal notranslate">[-9]</code>. This means that the nicks will be right-aligned and truncated to 9 characters.</p>
<p><strong>Note</strong>: Modifiers <em>only</em> work in the <code class="docutils literal notranslate">/format</code> section of a theme (this may change in the future)</p>
<p>There are also some scripts that try to do the alignment for you, like: <code class="docutils literal notranslate">nm</code>, <code class="docutils literal notranslate">nm2</code>.</p>
<p>There are also some nice themes that extend the alignment to further formats, like: <a class="reference external" href="https://github.com/ronilaukkarinen/weed">weed</a>.</p>
<h1>Automatic log-in to NickServ</h1>
<p>Please check here =&gt; <a class="reference internal" href="../../manual/automation/#automatic-log-in-to-nickserv">Automatic log-in to NickServ</a></p>
<h1>CertFP Log-in</h1>
<p>CertFP, short for Certificate Finger Print, is another method to log you in to NickServ. Instead of a password, it uses a <a class="reference external" href="https://en.wikipedia.org/wiki/Client_certificate">Client Certificate</a>.</p>
<p>In order to use it, you</p>
<ul class="simple">
<li><p>first need a certificate,</p></li>
<li><p>then configure Irssi to use this certificate,</p></li>
<li><p>and finally register the certificate with NickServ.</p></li>
</ul>
<p>Irssi does not have built-in certificate management commands, so you need to use an external tool like <code class="docutils literal notranslate">openssl</code> to create the certificate.</p>
<p>A step-by-step guide for the Libera Chat network can be found here =&gt; <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberachat_certfp">https://github.com/shabble/irssi-docs/wiki/liberachat_certfp</a></p>
<p>It is necessary that the certificate be available as a file; PKCS#11 is not supported.</p>
<h1>Tor (The Onion Router)</h1>
<p><a class="reference external" href="https://www.torproject.org/">Tor</a> is an overlay network for anonymous communication. It operates a local <a class="reference external" href="https://en.wikipedia.org/wiki/SOCKS">SOCKS</a> proxy for applications to use.</p>
<p>Unfortunately, Irssi currently does not support SOCKS proxies natively. As a workaround, you can install the <a class="reference external" href="https://github.com/rofl0r/proxychains-ng">ProxyChains-NG</a> program (note, it must be the NG version).</p>
<p>Afterwards, you can launch Irssi like this:</p>
<div class="highlight-default notranslate"><div><pre>proxychains4 irssi
</pre></div>
</div>
<p>Now your connections will go through the Proxy configured in ProxyChains-NG (Tor by default).</p>
<p>IRC networks may have different requirements to be able to connect via Tor. For the Libera Chat network, you will first need to set up <a class="reference internal" href="../certfp/">CertFP Log-in</a> using a clearnet connection, and then connect to their <a class="reference external" href="https://libera.chat/guides/connect#accessing-liberachat-via-tor">Onion Service</a> <code class="docutils literal notranslate">palladium.libera.chat</code>. More detailed instructions can be found here =&gt; <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberator">https://github.com/shabble/irssi-docs/wiki/liberator</a></p>
<h1>The following signatures were invalid: EXPKEYSIG</h1>
<p>If you see such a message</p>
<div class="highlight-default notranslate"><div><pre>Err:4 home:/ailin_nemui:/irssi-an InRelease
The following signatures were invalid: EXPKEYSIG EDB7AED941EEDB57 home:ailin_nemui OBS Project &lt;home:ailin_nemui@build.opensuse.org&gt;
</pre></div>
</div>
<p>this means that the automatic signing key used by the Open Build Service expired. OBS renews the key periodically, but Debian does not support this.</p>
<section id="fix">
<h2>Fix</h2>
<p>Download the key again, following the regular OBS instructions. If it still does not work, verify if there is a second expired copy of the key in <code class="docutils literal notranslate">/etc/apt/trusted.gpg.d</code> or in <code class="docutils literal notranslate">apt-key list</code> and remove it as well.</p>
</section>

View file

@ -1,111 +0,0 @@
# Right-aligned nicks #
To create a “tabular” effect of the chat view, or to align nick names in a
column, you can use Irssis theme/format system. The basic commands are the
following:
/format own_msg {ownmsgnick $2 {ownnick $[-9]0}}$1
/format own_msg_channel {ownmsgnick $3 {ownnick $[-9]0}{msgchannel $1}}$2
/format pubmsg_me {pubmsgmenick $2 {menick $[-9]0}}$1
/format pubmsg_me_channel {pubmsgmenick $3 {menick $[-9]0}{msgchannel $1}}$2
/format pubmsg_hilight {pubmsghinick $0 $3 $[-9]1}$2
/format pubmsg_hilight_channel {pubmsghinick $0 $4 $[-9]1{msgchannel $2}}$3
/format pubmsg {pubmsgnick $2 {pubnick $[-9]0}}$1
/format pubmsg_channel {pubmsgnick $3 {pubnick $[-9]0}{msgchannel $1}}$2
These are copied from the default themes default values, which are responsible
for displaying your own messages sent to a channel (own_msg) as well as
received messages (pubmsg) and the two basic highlightings (me and hilight).
Then, in front of the argument that contains the nick name ($0 in most cases,
but $1 in pubmsg_hilight), an alignment modifier (see [1]Appendix B: Special
Variables and Expandos) has been added: [-9]. This means that the nicks will be
right-aligned and truncated to 9 characters.
Note: Modifiers only work in the /format section of a theme (this may change in
the future)
There are also some scripts that try to do the alignment for you, like: nm,
nm2.
There are also some nice themes that extend the alignment to further formats,
like: [2]weed.
# Automatic log-in to NickServ #
Please check here => [3]Automatic log-in to NickServ
# CertFP Log-in #
CertFP, short for Certificate Finger Print, is another method to log you in to
NickServ. Instead of a password, it uses a [4]Client Certificate.
In order to use it, you
• first need a certificate,
• then configure Irssi to use this certificate,
• and finally register the certificate with NickServ.
Irssi does not have built-in certificate management commands, so you need to
use an external tool like openssl to create the certificate.
A step-by-step guide for the Libera Chat network can be found here => [5]https:
//github.com/shabble/irssi-docs/wiki/liberachat_certfp
It is necessary that the certificate be available as a file; PKCS#11 is not
supported.
# Tor (The Onion Router) #
[6]Tor is an overlay network for anonymous communication. It operates a local
[7]SOCKS proxy for applications to use.
Unfortunately, Irssi currently does not support SOCKS proxies natively. As a
workaround, you can install the [8]ProxyChains-NG program (note, it must be the
NG version).
Afterwards, you can launch Irssi like this:
proxychains4 irssi
Now your connections will go through the Proxy configured in ProxyChains-NG
(Tor by default).
IRC networks may have different requirements to be able to connect via Tor. For
the Libera Chat network, you will first need to set up [9]CertFP Log-in using a
clearnet connection, and then connect to their [10]Onion Service
palladium.libera.chat. More detailed instructions can be found here => [11]
https://github.com/shabble/irssi-docs/wiki/liberator
# The following signatures were invalid: EXPKEYSIG #
If you see such a message
Err:4 home:/ailin_nemui:/irssi-an InRelease
The following signatures were invalid: EXPKEYSIG EDB7AED941EEDB57 home:ailin_nemui OBS Project <home:ailin_nemui@build.opensuse.org>
this means that the automatic signing key used by the Open Build Service
expired. OBS renews the key periodically, but Debian does not support this.
## Fix ##
Download the key again, following the regular OBS instructions. If it still
does not work, verify if there is a second expired copy of the key in /etc/apt/
trusted.gpg.d or in apt-key list and remove it as well.
References:
[1] https://irssi.org/documentation/settings/#a-b
[2] https://github.com/ronilaukkarinen/weed
[3] https://irssi.org/documentation/manual/automation/#automatic-log-in-to-nickserv
[4] https://en.wikipedia.org/wiki/Client_certificate
[5] https://github.com/shabble/irssi-docs/wiki/liberachat_certfp
[6] https://www.torproject.org/
[7] https://en.wikipedia.org/wiki/SOCKS
[8] https://github.com/rofl0r/proxychains-ng
[9] https://irssi.org/documentation/qna/certfp/
[10] https://libera.chat/guides/connect#accessing-liberachat-via-tor
[11] https://github.com/shabble/irssi-docs/wiki/liberator

View file

@ -94,8 +94,6 @@ $A .. $Z is important.
$winname window name $winname window name
$itemname like $T, but use item's visible_name which may be $itemname like $T, but use item's visible_name which may be
different (eg. $T = !12345chan, $itemname = !chan) different (eg. $T = !12345chan, $itemname = !chan)
$abiversion IRSSI_ABI_VERSION
https://github.com/irssi/irssi/wiki/irssi_abi_version
For example, assume you have the following alias: For example, assume you have the following alias:

View file

@ -515,12 +515,12 @@ Ctrl-X - set the next server in list active
<p><strong>SOCKS</strong></p> <p><strong>SOCKS</strong></p>
<p>Using <a href="https://github.com/rofl0r/proxychains-ng">proxychains-ng</a> is recommended for using irssi with a socks proxy.</p> <p>Irssi can be compiled with socks support (<code>--with-socks</code> option to configure), which requires “dante” and routes all connections through the proxy specified in the system-wide /etc/socks.conf. This method is known to have issues in Mac OS X.</p>
<p>Irssi does not support socks proxy natively.</p>
<p>Note that <code>/SET proxy</code> settings dont have anything to do with socks.</p> <p>Note that <code>/SET proxy</code> settings dont have anything to do with socks.</p>
<p>Using <a href="https://github.com/rofl0r/proxychains-ng">proxychains-ng</a> is recommended over recompiling irssi.</p>
<p><strong>Others</strong></p> <p><strong>Others</strong></p>
<p>IRC bouncers usually work like IRC servers, and want a password. You can give it with:</p> <p>IRC bouncers usually work like IRC servers, and want a password. You can give it with:</p>
@ -683,4 +683,4 @@ Ctrl-X - set the next server in list active
/STATUSBAR &lt;name&gt; REMOVE &lt;item&gt; /STATUSBAR &lt;name&gt; REMOVE &lt;item&gt;
</code></pre></div></div> </code></pre></div></div>
<p>For statusbar scripts, the item name is usually equivalent to the script name. The documentation of the script ought to tell you if this is not the case. For example, to add mail.pl before the window activity item, use: <code>/STATUSBAR window ADD -before act mail</code>.</p> <p>For statusbar scripts, the item name is usually equivalent to the script name. The documentation of the script ought to tell you if this is not the case. For example, to add mail.pl before the window activity item, use: <code>/STATUSBAR window ADD -before act mail</code>.</p>

View file

@ -578,12 +578,15 @@ Irssi proxy works fine with other IRC clients as well.
SOCKS SOCKS
Using [4]proxychains-ng is recommended for using irssi with a socks proxy. Irssi can be compiled with socks support (--with-socks option to configure),
which requires “dante” and routes all connections through the proxy specified
Irssi does not support socks proxy natively. in the system-wide /etc/socks.conf. This method is known to have issues in Mac
OS X.
Note that /SET proxy settings dont have anything to do with socks. Note that /SET proxy settings dont have anything to do with socks.
Using [4]proxychains-ng is recommended over recompiling irssi.
Others Others
IRC bouncers usually work like IRC servers, and want a password. You can give IRC bouncers usually work like IRC servers, and want a password. You can give

20
irssi-1.pc.in Normal file
View file

@ -0,0 +1,20 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
prog_libs="@PROG_LIBS@"
common_libs="@COMMON_LIBS@"
perl_link_libs="@PERL_LINK_LIBS@"
perl_fe_link_libs="@PERL_FE_LINK_LIBS@"
perl_link_flags="@PERL_LINK_FLAGS@"
chat_modules="@CHAT_MODULES@"
irc_modules="@irc_MODULES@"
Name: Irssi
Description: Irssi chat client
Version: @PACKAGE_VERSION@
Cflags: -I${includedir} @OPENSSL_CFLAGS@
Requires: glib-2.0

208
m4/glib-2.0.m4 Normal file
View file

@ -0,0 +1,208 @@
# Configure paths for GLIB
# Owen Taylor 1997-2001
dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject or
dnl gthread is specified in MODULES, pass to pkg-config
dnl
AC_DEFUN([AM_PATH_GLIB_2_0],
[dnl
dnl Get the cflags and libraries from pkg-config
dnl
AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program],
, enable_glibtest=yes)
pkg_config_args=glib-2.0
for module in . $4
do
case "$module" in
gmodule)
pkg_config_args="$pkg_config_args gmodule-2.0"
;;
gmodule-no-export)
pkg_config_args="$pkg_config_args gmodule-no-export-2.0"
;;
gobject)
pkg_config_args="$pkg_config_args gobject-2.0"
;;
gthread)
pkg_config_args="$pkg_config_args gthread-2.0"
;;
esac
done
PKG_PROG_PKG_CONFIG([0.7])
no_glib=""
if test "x$PKG_CONFIG" = x ; then
no_glib=yes
PKG_CONFIG=no
fi
min_glib_version=ifelse([$1], ,2.0.0,$1)
AC_MSG_CHECKING(for GLIB - version >= $min_glib_version)
if test "x$PKG_CONFIG" != xno ; then
## don't try to run the test against uninstalled libtool libs
if $PKG_CONFIG --uninstalled $pkg_config_args; then
echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH"
enable_glibtest=no
fi
if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then
:
else
no_glib=yes
fi
fi
if test x"$no_glib" = x ; then
GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0`
GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args`
GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args`
glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
if test "x$enable_glibtest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $GLIB_CFLAGS"
LIBS="$GLIB_LIBS $LIBS"
dnl
dnl Now check if the installed GLIB is sufficiently new. (Also sanity
dnl checks the results of pkg-config to some extent)
dnl
rm -f conf.glibtest
AC_TRY_RUN([
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
int
main ()
{
int major, minor, micro;
char *tmp_version;
system ("touch conf.glibtest");
/* HP/UX 9 (%@#!) writes to sscanf strings */
tmp_version = g_strdup("$min_glib_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_glib_version");
exit(1);
}
if ((glib_major_version != $glib_config_major_version) ||
(glib_minor_version != $glib_config_minor_version) ||
(glib_micro_version != $glib_config_micro_version))
{
printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n",
$glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
glib_major_version, glib_minor_version, glib_micro_version);
printf ("*** was found! If pkg-config was correct, then it is best\n");
printf ("*** to remove the old version of GLib. You may also be able to fix the error\n");
printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
printf("*** required on your system.\n");
printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n");
printf("*** to point to the correct configuration files\n");
}
else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
(glib_minor_version != GLIB_MINOR_VERSION) ||
(glib_micro_version != GLIB_MICRO_VERSION))
{
printf("*** GLIB header files (version %d.%d.%d) do not match\n",
GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
printf("*** library (version %d.%d.%d)\n",
glib_major_version, glib_minor_version, glib_micro_version);
}
else
{
if ((glib_major_version > major) ||
((glib_major_version == major) && (glib_minor_version > minor)) ||
((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
{
return 0;
}
else
{
printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
glib_major_version, glib_minor_version, glib_micro_version);
printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
major, minor, micro);
printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
printf("***\n");
printf("*** If you have already installed a sufficiently new version, this error\n");
printf("*** probably means that the wrong copy of the pkg-config shell script is\n");
printf("*** being found. The easiest way to fix this is to remove the old version\n");
printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n");
printf("*** correct copy of pkg-config. (In this case, you will have to\n");
printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
printf("*** so that the correct libraries are found at run-time))\n");
}
}
return 1;
}
],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
if test "x$no_glib" = x ; then
AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version))
ifelse([$2], , :, [$2])
else
AC_MSG_RESULT(no)
if test "$PKG_CONFIG" = "no" ; then
echo "*** A new enough version of pkg-config was not found."
echo "*** See http://www.freedesktop.org/software/pkgconfig/"
else
if test -f conf.glibtest ; then
:
else
echo "*** Could not run GLIB test program, checking why..."
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $GLIB_CFLAGS"
LIBS="$LIBS $GLIB_LIBS"
AC_TRY_LINK([
#include <glib.h>
#include <stdio.h>
], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding GLIB or finding the wrong"
echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occurred. This usually means GLIB is incorrectly installed."])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
GLIB_CFLAGS=""
GLIB_LIBS=""
GLIB_GENMARSHAL=""
GOBJECT_QUERY=""
GLIB_MKENUMS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
AC_SUBST(GLIB_GENMARSHAL)
AC_SUBST(GOBJECT_QUERY)
AC_SUBST(GLIB_MKENUMS)
rm -f conf.glibtest
])

28
m4/glibtests.m4 Normal file
View file

@ -0,0 +1,28 @@
dnl GLIB_TESTS
dnl
AC_DEFUN([GLIB_TESTS],
[
AC_ARG_ENABLE(installed-tests,
AS_HELP_STRING([--enable-installed-tests],
[Enable installation of some test cases]),
[case ${enableval} in
yes) ENABLE_INSTALLED_TESTS="1" ;;
no) ENABLE_INSTALLED_TESTS="" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;;
esac])
AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1")
AC_ARG_ENABLE(always-build-tests,
AS_HELP_STRING([--enable-always-build-tests],
[Enable always building tests during 'make all']),
[case ${enableval} in
yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;;
no) ENABLE_ALWAYS_BUILD_TESTS="" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;;
esac])
AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1")
if test "$ENABLE_INSTALLED_TESTS" = "1"; then
AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME)
AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME)
fi
])

143
m4/libgcrypt.m4 Normal file
View file

@ -0,0 +1,143 @@
# libgcrypt.m4 - Autoconf macros to detect libgcrypt
# Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Last-changed: 2014-10-02
dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
dnl with the API version to also check the API compatibility. Example:
dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using
dnl this features allows to prevent build against newer versions of libgcrypt
dnl with a changed API.
dnl
dnl If a prefix option is not used, the config script is first
dnl searched in $SYSROOT/bin and then along $PATH. If the used
dnl config script does not match the host specification the script
dnl is added to the gpg_config_script_warn variable.
dnl
AC_DEFUN([AM_PATH_LIBGCRYPT],
[ AC_REQUIRE([AC_CANONICAL_HOST])
AC_ARG_WITH(libgcrypt-prefix,
AC_HELP_STRING([--with-libgcrypt-prefix=PFX],
[prefix where LIBGCRYPT is installed (optional)]),
libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="")
if test x"${LIBGCRYPT_CONFIG}" = x ; then
if test x"${libgcrypt_config_prefix}" != x ; then
LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config"
else
case "${SYSROOT}" in
/*)
if test -x "${SYSROOT}/bin/libgcrypt-config" ; then
LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config"
fi
;;
'')
;;
*)
AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.])
;;
esac
fi
fi
AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
tmp=ifelse([$1], ,1:1.2.0,$1)
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'`
min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
else
req_libgcrypt_api=0
min_libgcrypt_version="$tmp"
fi
AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version)
ok=no
if test "$LIBGCRYPT_CONFIG" != "no" ; then
req_major=`echo $min_libgcrypt_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
req_minor=`echo $min_libgcrypt_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
req_micro=`echo $min_libgcrypt_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
major=`echo $libgcrypt_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $libgcrypt_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
micro=`echo $libgcrypt_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
if test "$major" -gt "$req_major"; then
ok=yes
else
if test "$major" -eq "$req_major"; then
if test "$minor" -gt "$req_minor"; then
ok=yes
else
if test "$minor" -eq "$req_minor"; then
if test "$micro" -ge "$req_micro"; then
ok=yes
fi
fi
fi
fi
fi
fi
if test $ok = yes; then
AC_MSG_RESULT([yes ($libgcrypt_config_version)])
else
AC_MSG_RESULT(no)
fi
if test $ok = yes; then
# If we have a recent libgcrypt, we should also check that the
# API is compatible
if test "$req_libgcrypt_api" -gt 0 ; then
tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
if test "$tmp" -gt 0 ; then
AC_MSG_CHECKING([LIBGCRYPT API version])
if test "$req_libgcrypt_api" -eq "$tmp" ; then
AC_MSG_RESULT([okay])
else
ok=no
AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp])
fi
fi
fi
fi
if test $ok = yes; then
LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
ifelse([$2], , :, [$2])
libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
if test x"$libgcrypt_config_host" != xnone ; then
if test x"$libgcrypt_config_host" != x"$host" ; then
AC_MSG_WARN([[
***
*** The config script $LIBGCRYPT_CONFIG was
*** built for $libgcrypt_config_host and thus may not match the
*** used host $host.
*** You may want to use the configure option --with-libgcrypt-prefix
*** to specify a matching config script or use \$SYSROOT.
***]])
gpg_config_script_warn="$gpg_config_script_warn libgcrypt"
fi
fi
else
LIBGCRYPT_CFLAGS=""
LIBGCRYPT_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(LIBGCRYPT_CFLAGS)
AC_SUBST(LIBGCRYPT_LIBS)
])

134
m4/libotr.m4 Normal file
View file

@ -0,0 +1,134 @@
dnl
dnl Off-the-Record Messaging library
dnl Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov
dnl <otr@cypherpunks.ca>
dnl
dnl This library is free software; you can redistribute it and/or
dnl modify it under the terms of version 2.1 of the GNU Lesser General
dnl Public License as published by the Free Software Foundation.
dnl
dnl This library is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl Lesser General Public License for more details.
dnl
dnl You should have received a copy of the GNU Lesser General Public
dnl License along with this library; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
dnl
dnl AM_PATH_LIBOTR([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for libotr, and define LIBOTR_CFLAGS and LIBOTR_LIBS as appropriate.
dnl enables arguments --with-libotr-prefix=
dnl --with-libotr-inc-prefix=
dnl
dnl You must already have found libgcrypt with AM_PATH_LIBGCRYPT
dnl
dnl Adapted from alsa.m4, originally by
dnl Richard Boulton <richard-alsa@tartarus.org>
dnl Christopher Lansdown <lansdoct@cs.alfred.edu>
dnl Jaroslav Kysela <perex@suse.cz>
AC_DEFUN([AM_PATH_LIBOTR],
[dnl Save the original CFLAGS, LDFLAGS, and LIBS
libotr_save_CFLAGS="$CFLAGS"
libotr_save_LDFLAGS="$LDFLAGS"
libotr_save_LIBS="$LIBS"
libotr_found=yes
dnl
dnl Get the cflags and libraries for libotr
dnl
AC_ARG_WITH(libotr-prefix,
[ --with-libotr-prefix=PFX Prefix where libotr is installed(optional)],
[libotr_prefix="$withval"], [libotr_prefix=""])
AC_ARG_WITH(libotr-inc-prefix,
[ --with-libotr-inc-prefix=PFX Prefix where libotr includes are (optional)],
[libotr_inc_prefix="$withval"], [libotr_inc_prefix=""])
dnl Add any special include directories
AC_MSG_CHECKING(for libotr CFLAGS)
if test "$libotr_inc_prefix" != "" ; then
LIBOTR_CFLAGS="$LIBOTR_CFLAGS -I$libotr_inc_prefix"
CFLAGS="$CFLAGS $LIBOTR_CFLAGS"
fi
AC_MSG_RESULT($LIBOTR_CFLAGS)
dnl add any special lib dirs
AC_MSG_CHECKING(for libotr LIBS)
if test "$libotr_prefix" != "" ; then
LIBOTR_LIBS="$LIBOTR_LIBS -L$libotr_prefix"
LDFLAGS="$LDFLAGS $LIBOTR_LIBS"
fi
dnl add the libotr library
LIBOTR_LIBS="$LIBOTR_LIBS -lotr"
LIBS="$LIBOTR_LIBS $LIBS"
AC_MSG_RESULT($LIBOTR_LIBS)
dnl Check for a working version of libotr that is of the right version.
min_libotr_version=ifelse([$1], ,3.0.0,$1)
no_libotr=""
libotr_min_major_version=`echo $min_libotr_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
libotr_min_minor_version=`echo $min_libotr_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
libotr_min_sub_version=`echo $min_libotr_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
AC_MSG_CHECKING(for libotr headers version $libotr_min_major_version.x >= $min_libotr_version)
AC_LANG_SAVE
AC_LANG_C
AC_TRY_COMPILE([
#include <stdlib.h>
#include <libotr/version.h>
], [
# if(OTRL_VERSION_MAJOR != $libotr_min_major_version)
# error not present
# else
# if(OTRL_VERSION_MINOR > $libotr_min_minor_version)
exit(0);
# else
# if(OTRL_VERSION_MINOR < $libotr_min_minor_version)
# error not present
# endif
# if(OTRL_VERSION_SUB < $libotr_min_sub_version)
# error not present
# endif
# endif
# endif
exit(0);
],
[AC_MSG_RESULT(found.)],
[AC_MSG_RESULT(not present.)
ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libotr not found.)])
libotr_found=no]
)
AC_LANG_RESTORE
dnl Now that we know that we have the right version, let's see if we have the library and not just the headers.
AC_CHECK_LIB([otr], [otrl_message_receiving],,
[ifelse([$3], , [AC_MSG_ERROR(No linkable libotr was found.)])
libotr_found=no],
$LIBGCRYPT_LIBS
)
LDFLAGS="$libotr_save_LDFLAGS"
LIBS="$libotr_save_LIBS"
if test "x$libotr_found" = "xyes" ; then
ifelse([$2], , :, [$2])
else
LIBOTR_CFLAGS=""
LIBOTR_LIBS=""
ifelse([$3], , :, [$3])
fi
dnl That should be it. Now just export our symbols:
AC_SUBST(LIBOTR_CFLAGS)
AC_SUBST(LIBOTR_LIBS)
])

275
m4/pkg.m4 Normal file
View file

@ -0,0 +1,275 @@
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 12 (pkg-config-0.29.2)
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
dnl 02111-1307, USA.
dnl
dnl As a special exception to the GNU General Public License, if you
dnl distribute this file as part of a program that contains a
dnl configuration script generated by Autoconf, you may include it under
dnl the same distribution terms that you use for the rest of that
dnl program.
dnl PKG_PREREQ(MIN-VERSION)
dnl -----------------------
dnl Since: 0.29
dnl
dnl Verify that the version of the pkg-config macros are at least
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
dnl installed version of pkg-config, this checks the developer's version
dnl of pkg.m4 when generating configure.
dnl
dnl To ensure that this macro is defined, also add:
dnl m4_ifndef([PKG_PREREQ],
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29.2])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
dnl ----------------------------------
dnl Since: 0.16
dnl
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
dnl first found in the path. Checks that the version of pkg-config found
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
dnl used since that's the first version where most current features of
dnl pkg-config existed.
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
if test -n "$PKG_CONFIG"; then
_pkg_min_version=m4_default([$1], [0.9.0])
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
fi[]dnl
])dnl PKG_PROG_PKG_CONFIG
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------------------------------
dnl Since: 0.18
dnl
dnl Check to see whether a particular set of modules exists. Similar to
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
dnl
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
dnl only at the first occurence in configure.ac, so if the first place
dnl it's called might be skipped (such as if it is within an "if", you
dnl have to call PKG_CHECK_EXISTS manually
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
m4_default([$2], [:])
m4_ifvaln([$3], [else
$3])dnl
fi])
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
dnl ---------------------------------------------
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
dnl pkg_failed based on the result.
m4_define([_PKG_CONFIG],
[if test -n "$$1"; then
pkg_cv_[]$1="$$1"
elif test -n "$PKG_CONFIG"; then
PKG_CHECK_EXISTS([$3],
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes ],
[pkg_failed=yes])
else
pkg_failed=untried
fi[]dnl
])dnl _PKG_CONFIG
dnl _PKG_SHORT_ERRORS_SUPPORTED
dnl ---------------------------
dnl Internal check to see if pkg-config supports short errors.
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi[]dnl
])dnl _PKG_SHORT_ERRORS_SUPPORTED
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl --------------------------------------------------------------
dnl Since: 0.4.0
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
AC_DEFUN([PKG_CHECK_MODULES],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
AC_MSG_CHECKING([for $2])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
_PKG_TEXT
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
AC_MSG_RESULT([yes])
$3
fi[]dnl
])dnl PKG_CHECK_MODULES
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl ---------------------------------------------------------------------
dnl Since: 0.29
dnl
dnl Checks for existence of MODULES and gathers its build flags with
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
dnl and VARIABLE-PREFIX_LIBS from --libs.
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
dnl configure.ac.
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
_save_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
PKG_CHECK_MODULES($@)
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
])dnl PKG_CHECK_MODULES_STATIC
dnl PKG_INSTALLDIR([DIRECTORY])
dnl -------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable pkgconfigdir as the location where a module
dnl should install pkg-config .pc files. By default the directory is
dnl $libdir/pkgconfig, but the default can be changed by passing
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
dnl parameter.
AC_DEFUN([PKG_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
m4_pushdef([pkg_description],
[pkg-config installation directory @<:@]pkg_default[@:>@])
AC_ARG_WITH([pkgconfigdir],
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
[with_pkgconfigdir=]pkg_default)
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
])dnl PKG_INSTALLDIR
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
dnl --------------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
dnl module should install arch-independent pkg-config .pc files. By
dnl default the directory is $datadir/pkgconfig, but the default can be
dnl changed by passing DIRECTORY. The user can override through the
dnl --with-noarch-pkgconfigdir parameter.
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
m4_pushdef([pkg_description],
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
AC_ARG_WITH([noarch-pkgconfigdir],
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
[with_noarch_pkgconfigdir=]pkg_default)
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
])dnl PKG_NOARCH_INSTALLDIR
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------
dnl Since: 0.28
dnl
dnl Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])dnl PKG_CHECK_VAR

View file

@ -1,115 +1,84 @@
project( project('irssi', 'c',
'irssi', version : '1.4.5',
'c', meson_version : '>=0.49',
version : '1.5-head', default_options : ['warning_level=1'])
meson_version : '>=0.53',
default_options : [ 'warning_level=1' ],
)
############################ ############################
############################ ############################
glib_internal_version = 'glib-2.74.7' # keep this in sync with subprojects/glib.wrap glib_internal_version = 'glib-2.58.3' # keep this in sync with subprojects/glib.wrap
glib_pcre2_internal_version = 'pcre2-10.40'
glib_libffi_internal_version = 'libffi'
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
rootinc = include_directories('.') rootinc = include_directories('.')
dep = [ ] dep = []
textui_dep = [ ] textui_dep = []
need_dl_cross_link = false need_dl_cross_link = false
need_dl_cross_link_main = false
dl_cross_irssi_main = [ ]
# The Android environment requires that all modules are linked to each other. # The Android environment requires that all modules are linked to each other.
# See https://github.com/android/ndk/issues/201 # See https://github.com/android/ndk/issues/201
if host_machine.system() == 'android' if host_machine.system() == 'android'
need_dl_cross_link = true need_dl_cross_link = true
elif host_machine.system() == 'cygwin'
need_dl_cross_link = true
need_dl_cross_link_main = true
endif endif
includedir = get_option('includedir') includedir = get_option('includedir')
incdir = 'irssi' incdir = 'irssi'
moduledir = get_option('libdir') / incdir / 'modules' moduledir = get_option('libdir') / incdir / 'modules'
helpdir = get_option('datadir') / incdir / 'help' helpdir = get_option('datadir') / incdir / 'help'
themedir = get_option('datadir') / incdir / 'themes' themedir = get_option('datadir') / incdir / 'themes'
scriptdir = get_option('datadir') / incdir / 'scripts' scriptdir = get_option('datadir') / incdir / 'scripts'
docdir = get_option('docdir') != '' ? get_option('docdir') : (get_option('datadir') / 'doc' / incdir) docdir = get_option('docdir') != '' ? get_option('docdir') : (get_option('datadir') / 'doc' / incdir)
want_textui = get_option('without-textui') != 'yes' want_textui = get_option('without-textui') != 'yes'
want_bot = get_option('with-bot') == 'yes' want_bot = get_option('with-bot') == 'yes'
want_fuzzer = get_option('with-fuzzer') == 'yes' want_fuzzer = get_option('with-fuzzer') == 'yes'
fuzzer_lib = get_option('with-fuzzer-lib') fuzzer_lib = get_option('with-fuzzer-lib')
fuzzer_link_language = get_option('fuzzer-link-language') fuzzer_link_language = get_option('fuzzer-link-language')
want_proxy = get_option('with-proxy') == 'yes' want_proxy = get_option('with-proxy') == 'yes'
want_truecolor = get_option('enable-true-color') == 'yes'
want_gregex = get_option('disable-gregex') != 'yes'
require_capsicum = get_option('with-capsicum') == 'yes' require_capsicum = get_option('with-capsicum') == 'yes'
want_capsicum = get_option('with-capsicum') != 'no' want_capsicum = get_option('with-capsicum') != 'no'
require_libutf8proc = get_option('disable-utf8proc') == 'no' require_libutf8proc = get_option('disable-utf8proc') == 'no'
want_libutf8proc = get_option('disable-utf8proc') != 'yes' want_libutf8proc = get_option('disable-utf8proc') != 'yes'
require_perl = get_option('with-perl') == 'yes' require_perl = get_option('with-perl') == 'yes'
want_perl = get_option('with-perl') != 'no' want_perl = get_option('with-perl') != 'no'
with_perl_lib = get_option('with-perl-lib') with_perl_lib = get_option('with-perl-lib')
require_otr = get_option('with-otr') == 'yes' require_otr = get_option('with-otr') == 'yes'
want_otr = get_option('with-otr') != 'no' want_otr = get_option('with-otr') != 'no'
want_glib_internal = get_option('install-glib') != 'no' want_glib_internal = get_option('install-glib') != 'no'
require_glib_internal = get_option('install-glib') == 'force' require_glib_internal = get_option('install-glib') == 'force'
want_static_dependency = get_option('static-dependency') == 'yes' want_static_dependency = get_option('static-dependency') == 'yes'
package_version = get_option('PACKAGE_VERSION') != '' ? get_option('PACKAGE_VERSION') : meson.project_version() package_version = get_option('PACKAGE_VERSION') != '' ? get_option('PACKAGE_VERSION') : meson.project_version()
fs = import('fs')
if fs.exists('config.status') or fs.exists('irssi-version.h') or fs.exists('default-config.h') or fs.exists('default-theme.h') or fs.exists('src/perl/irssi-core.pl.h') or fs.exists('src/perl/perl-signals-list.h') or fs.exists('irssi-config.h')
error('this tree has been configured with autotools, cannot proceed')
endif
UNSET = '=INVALID=' UNSET = '=INVALID='
UNSET_ARR = [ UNSET ] UNSET_ARR = [UNSET]
chat_modules = [ 'irc' ] chat_modules = ['irc']
run_command( run_command('mkdir', meson.current_build_dir() / incdir)
'mkdir', run_command('ln', '-s', meson.current_source_dir() / 'src', meson.current_build_dir() / incdir)
meson.current_build_dir() / incdir, run_command('ln', '-s', meson.current_build_dir() / 'irssi-config.h', meson.current_build_dir() / incdir)
check : false, run_command('ln', '-s', meson.current_build_dir() / 'irssi-version.h', meson.current_build_dir() / incdir)
)
run_command(
'ln',
'-s', meson.current_source_dir() / 'src',
meson.current_build_dir() / incdir,
check : false,
)
run_command(
'ln',
'-s', meson.current_build_dir() / 'irssi-config.h',
meson.current_build_dir() / incdir,
check : false,
)
run_command(
'ln',
'-s', meson.current_build_dir() / 'irssi-version.h',
meson.current_build_dir() / incdir,
check : false,
)
def_moduledir = '-D' + 'MODULEDIR' + '="' + (get_option('prefix') / moduledir) + '"' def_moduledir = '-D' + 'MODULEDIR' + '="' + (get_option('prefix') / moduledir) + '"'
def_sysconfdir = '-D' + 'SYSCONFDIR' + '="' + (get_option('prefix') / get_option('sysconfdir')) + '"' def_sysconfdir = '-D' + 'SYSCONFDIR' + '="' + (get_option('prefix') / get_option('sysconfdir')) + '"'
def_helpdir = '-D' + 'HELPDIR' + '="' + (get_option('prefix') / helpdir) + '"' def_helpdir = '-D' + 'HELPDIR' + '="' + (get_option('prefix') / helpdir) + '"'
def_themesdir = '-D' + 'THEMESDIR' + '="' + (get_option('prefix') / themedir) + '"' def_themesdir = '-D' + 'THEMESDIR' + '="' + (get_option('prefix') / themedir) + '"'
def_scriptdir = '-D' + 'SCRIPTDIR' + '="' + (get_option('prefix') / scriptdir) + '"' def_scriptdir = '-D' + 'SCRIPTDIR' + '="' + (get_option('prefix') / scriptdir) + '"'
def_suppress_printf_fallback = '-D' + 'SUPPRESS_PRINTF_FALLBACK' def_suppress_printf_fallback = '-D' + 'SUPPRESS_PRINTF_FALLBACK'
module_suffix = [ ]
perl_module_suffix = [ ] module_suffix = []
perl_module_suffix = []
# Meson uses the wrong module extensions on Mac. # Meson uses the wrong module extensions on Mac.
# https://gitlab.gnome.org/GNOME/glib/issues/520 # https://gitlab.gnome.org/GNOME/glib/issues/520
if [ 'darwin', 'ios' ].contains(host_machine.system()) if ['darwin', 'ios'].contains(host_machine.system())
module_suffix = 'so' module_suffix = 'so'
perl_module_suffix = 'bundle' perl_module_suffix = 'bundle'
endif endif
@ -118,20 +87,13 @@ endif
# Help files # # Help files #
############## ##############
build_perl = find_program( build_perl = find_program('perl', native : true)
'perl',
native : true,
)
if meson.is_cross_build() if meson.is_cross_build()
cross_perl = find_program('perl') cross_perl = find_program('perl')
else else
cross_perl = build_perl cross_perl = build_perl
endif endif
run_command( run_command(build_perl, files('utils/syntax.pl'))
build_perl,
files('utils/syntax.pl'),
check : true,
)
################### ###################
# irssi-version.h # # irssi-version.h #
@ -139,12 +101,12 @@ run_command(
env = find_program('env') env = find_program('env')
irssi_version_sh = find_program('utils/irssi-version.sh') irssi_version_sh = find_program('utils/irssi-version.sh')
irssi_version_h = custom_target( irssi_version_h = custom_target('irssi-version.h',
'irssi-version.h',
build_by_default : true, build_by_default : true,
build_always_stale : true, build_always_stale : true,
capture : true, capture : true,
command : [ env, 'VERSION=' + meson.project_version(), irssi_version_sh, meson.current_source_dir() ], command : [env, 'VERSION=' + meson.project_version(),
irssi_version_sh, meson.current_source_dir()],
output : 'irssi-version.h', output : 'irssi-version.h',
install : true, install : true,
install_dir : includedir / incdir, install_dir : includedir / incdir,
@ -155,24 +117,22 @@ irssi_version_h = custom_target(
#################### ####################
file2header = find_program('utils/file2header.sh') file2header = find_program('utils/file2header.sh')
default_config_h = custom_target( default_config_h = custom_target('default-config.h',
'default-config.h',
input : files('irssi.conf'), input : files('irssi.conf'),
output : 'default-config.h', output : 'default-config.h',
capture : true, capture : true,
command : [ file2header, '@INPUT@', 'default_config' ], command : [file2header, '@INPUT@', 'default_config'],
) )
################### ###################
# default-theme.h # # default-theme.h #
################### ###################
default_theme_h = custom_target( default_theme_h = custom_target('default-theme.h',
'default-theme.h',
input : files('themes/default.theme'), input : files('themes/default.theme'),
output : 'default-theme.h', output : 'default-theme.h',
capture : true, capture : true,
command : [ file2header, '@INPUT@', 'default_theme' ], command : [file2header, '@INPUT@', 'default_theme'],
) )
################ ################
@ -181,18 +141,12 @@ default_theme_h = custom_target(
#### inet_addr #### #### inet_addr ####
inet_addr_found = false inet_addr_found = false
foreach inet_addr_provider : [ '', 'nsl' ] foreach inet_addr_provider : ['', 'nsl']
prov_lib = [ ] prov_lib = []
if inet_addr_provider != '' if inet_addr_provider != ''
prov_lib += cc.find_library( prov_lib += cc.find_library(inet_addr_provider, required : false)
inet_addr_provider,
required : false,
)
endif endif
if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function( if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function('inet_addr', dependencies : prov_lib)
'inet_addr',
dependencies : prov_lib,
)
dep += prov_lib dep += prov_lib
inet_addr_found = true inet_addr_found = true
break break
@ -204,18 +158,12 @@ endif
#### socket #### #### socket ####
socket_found = false socket_found = false
foreach socket_provider : [ '', 'socket', 'network' ] foreach socket_provider : ['', 'socket', 'network']
prov_lib = [ ] prov_lib = []
if socket_provider != '' if socket_provider != ''
prov_lib += cc.find_library( prov_lib += cc.find_library(socket_provider, required : false)
socket_provider,
required : false,
)
endif endif
if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function( if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function('socket', dependencies : prov_lib)
'socket',
dependencies : prov_lib,
)
dep += prov_lib dep += prov_lib
socket_found = true socket_found = true
break break
@ -225,7 +173,7 @@ if not socket_found
error('socket not found') error('socket not found')
endif endif
built_src = [ ] built_src = []
glib_internal = false glib_internal = false
message('*** If you don\'t have GLib, you can run meson ... -Dinstall-glib=yes') message('*** If you don\'t have GLib, you can run meson ... -Dinstall-glib=yes')
message('*** to download and build it automatically') message('*** to download and build it automatically')
@ -233,82 +181,59 @@ message('*** Or alternatively install your distribution\'s package')
message('*** On Debian: sudo apt-get install libglib2.0-dev') message('*** On Debian: sudo apt-get install libglib2.0-dev')
message('*** On Redhat: dnf install glib2-devel') message('*** On Redhat: dnf install glib2-devel')
if not require_glib_internal if not require_glib_internal
glib_dep = dependency( glib_dep = dependency('glib-2.0', version : '>=2.32', required : not want_glib_internal, static : want_static_dependency, include_type : 'system')
'glib-2.0',
version : '>=2.32',
required : not want_glib_internal,
static : want_static_dependency,
include_type : 'system',
)
else else
glib_dep = dependency( glib_dep = dependency('', required : false)
'',
required : false,
)
endif endif
if not glib_dep.found() if not glib_dep.found()
glib_internal = true glib_internal = true
meson_cmd = find_program('meson') meson_cmd = find_program('meson')
ninja = find_program('ninja') ninja = find_program('ninja')
glib_internal_download_t = custom_target( glib_internal_download_t = custom_target('glib-internal-download',
'glib-internal-download',
command : [ meson_cmd, 'subprojects', 'download', 'glib', '--sourcedir', meson.current_source_dir() ], command : [ meson_cmd, 'subprojects', 'download', 'glib', '--sourcedir', meson.current_source_dir() ],
console : true, console : true,
output : [ 'glib-internal-download' ], output : ['glib-internal-download'],
) )
glib_internal_dependencies = [ glib_internal_dependencies = [
dependency('threads'), dependency('threads'),
] ]
glib_internal_configure_args = [ ] glib_internal_configure_args = []
glib_internal_usr_local = false glib_internal_usr_local = false
if not cc.has_function('iconv_open') if not cc.has_function('iconv_open')
prov_lib = cc.find_library( prov_lib = cc.find_library('iconv', required : false)
'iconv',
required : false,
)
if not prov_lib.found() if not prov_lib.found()
prov_lib = cc.find_library( prov_lib = cc.find_library('iconv', dirs : '/usr/local/lib')
'iconv',
dirs : '/usr/local/lib',
)
glib_internal_usr_local = true glib_internal_usr_local = true
endif endif
if cc.has_function('libiconv_open', dependencies : prov_lib)
glib_internal_configure_args += '-Diconv=gnu'
else
glib_internal_configure_args += '-Diconv=native'
endif
glib_internal_dependencies += prov_lib glib_internal_dependencies += prov_lib
endif endif
if not cc.has_function('ngettext') if not cc.has_function('ngettext')
prov_lib = cc.find_library( prov_lib = cc.find_library('intl', required : false)
'intl',
required : false,
)
if not prov_lib.found() if not prov_lib.found()
prov_lib = cc.find_library( prov_lib = cc.find_library('intl', dirs : '/usr/local/lib')
'intl',
dirs : '/usr/local/lib',
)
glib_internal_usr_local = true glib_internal_usr_local = true
endif endif
glib_internal_dependencies += prov_lib glib_internal_dependencies += prov_lib
endif endif
if glib_internal_usr_local if glib_internal_usr_local
glib_internal_configure_args += [ '-Dc_args=-I/usr/local/include', '-Dc_link_args=-L/usr/local/lib' ] glib_internal_configure_args += ['-Dc_args=-I/usr/local/include', '-Dc_link_args=-L/usr/local/lib']
endif endif
if not cc.has_function('getxattr') or not cc.has_header('sys/xattr.h') if not cc.has_function('getxattr') or not cc.has_header('sys/xattr.h')
if cc.has_header_symbol('attr/xattr.h', 'getxattr') if cc.has_header_symbol('attr/xattr.h', 'getxattr')
prov_lib = cc.find_library( prov_lib = cc.find_library('xattr', required : false)
'xattr',
required : false,
)
else else
prov_lib = dependency( prov_lib = dependency('', required : false)
'',
required : false,
)
endif endif
if prov_lib.found() if prov_lib.found()
glib_internal_dependencies += prov_lib glib_internal_dependencies += prov_lib
@ -317,41 +242,23 @@ if not glib_dep.found()
endif endif
endif endif
glib_internal_configure_t = custom_target( glib_internal_configure_t = custom_target('glib-internal-configure',
'glib-internal-configure', command : [ meson_cmd, 'setup', '--prefix=/irssi-glib-internal',
command : [
meson_cmd,
'setup',
'--prefix=/irssi-glib-internal',
'--buildtype=' + get_option('buildtype'), '--buildtype=' + get_option('buildtype'),
'-Dlibmount=disabled', '-Dlibmount=false', '-Dselinux=false', '-Ddefault_library=static', '-Dinternal_pcre=true',
'-Dselinux=disabled',
'-Ddefault_library=static',
'-Dforce_fallback_for=pcre2,libffi',
glib_internal_configure_args, glib_internal_configure_args,
(meson.current_build_dir() / 'build-subprojects' / 'glib'), (meson.current_build_dir() / 'build-subprojects' / 'glib'),
(meson.current_source_dir() / 'subprojects' / glib_internal_version), (meson.current_source_dir() / 'subprojects' / glib_internal_version) ],
],
console : true, console : true,
output : [ 'glib-internal-configure' ], output : ['glib-internal-configure'],
depends : glib_internal_download_t, depends : glib_internal_download_t,)
) glib_internal_build_t = custom_target('glib-internal-build',
glib_internal_build_t = custom_target( command : [ ninja, '-C', meson.current_build_dir() / 'build-subprojects' / 'glib',
'glib-internal-build',
command : [
ninja,
'-C', meson.current_build_dir() / 'build-subprojects' / 'glib',
'subprojects' / glib_libffi_internal_version / 'src' / 'libffi.a',
'subprojects' / glib_pcre2_internal_version / 'libpcre2-8.a',
'glib' / 'libglib-2.0.a', 'glib' / 'libglib-2.0.a',
'gmodule' / 'libgmodule-2.0.a', 'gmodule' / 'libgmodule-2.0.a'],
'gobject' / 'libgobject-2.0.a',
'gio' / 'libgio-2.0.a',
],
console : true, console : true,
output : [ 'glib-internal-build' ], output : ['glib-internal-build'],
depends : glib_internal_configure_t, depends : glib_internal_configure_t,)
)
glib_dep = declare_dependency( glib_dep = declare_dependency(
dependencies : glib_internal_dependencies, dependencies : glib_internal_dependencies,
sources : glib_internal_build_t, sources : glib_internal_build_t,
@ -360,84 +267,32 @@ if not glib_dep.found()
'-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version), '-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version),
'-isystem' + (meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib'), '-isystem' + (meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib'),
], ],
link_args : [ link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib' / 'libglib-2.0.a' ],
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'subprojects' / glib_pcre2_internal_version / 'libpcre2-8.a',
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib' / 'libglib-2.0.a',
],
) )
built_src += glib_internal_build_t built_src += glib_internal_build_t
libdl_dep = [ ] libdl_dep = []
prov_lib = cc.find_library( prov_lib = cc.find_library('dl', required : false)
'dl', if prov_lib.found() and cc.has_function('dlopen', dependencies : prov_lib)
required : false,
)
if prov_lib.found() and cc.has_function(
'dlopen',
dependencies : prov_lib,
)
libdl_dep += prov_lib libdl_dep += prov_lib
endif endif
gmodule_dep = declare_dependency( gmodule_dep = declare_dependency(sources : glib_internal_build_t,
sources : glib_internal_build_t,
dependencies : libdl_dep, dependencies : libdl_dep,
compile_args : [ compile_args : [
'-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'gmodule'), '-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'gmodule'),
], ],
link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gmodule' / 'libgmodule-2.0.a' ], link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gmodule' / 'libgmodule-2.0.a' ],
) )
gobject_dep = declare_dependency(
sources : glib_internal_build_t,
compile_args : [
'-isystem' + (meson.current_build_dir() / 'build-subprojects' / 'glib'),
],
link_args : [
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'subprojects' / glib_libffi_internal_version / 'src' / 'libffi.a',
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gobject' / 'libgobject-2.0.a',
],
)
gio_dep = declare_dependency(
sources : glib_internal_build_t,
dependencies : cc.find_library('z'),
compile_args : [
'-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'gio'),
'-isystem' + (meson.current_build_dir() / 'build-subprojects' / 'glib'),
],
link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gio' / 'libgio-2.0.a' ],
)
else else
gmodule_dep = dependency( gmodule_dep = dependency('gmodule-2.0', static : want_static_dependency, include_type : 'system')
'gmodule-2.0',
static : want_static_dependency,
include_type : 'system',
)
gobject_dep = dependency(
'gobject-2.0',
static : want_static_dependency,
include_type : 'system',
)
gio_dep = dependency(
'gio-2.0',
static : want_static_dependency,
include_type : 'system',
)
endif endif
dep += glib_dep dep += glib_dep
dep += gmodule_dep dep += gmodule_dep
dep += gobject_dep
dep += gio_dep
if glib_internal and want_static_dependency and want_fuzzer if glib_internal and want_static_dependency and want_fuzzer
openssl_proj = subproject( openssl_proj = subproject('openssl', default_options : ['default_library=static', 'asm=disabled'])
'openssl',
default_options : [ 'default_library=static', 'asm=disabled' ],
)
openssl_dep = openssl_proj.get_variable('openssl_dep') openssl_dep = openssl_proj.get_variable('openssl_dep')
else else
openssl_dep = dependency( openssl_dep = dependency('openssl', static : want_static_dependency, include_type : 'system')
'openssl',
static : want_static_dependency,
include_type : 'system',
)
endif endif
dep += openssl_dep dep += openssl_dep
@ -446,16 +301,10 @@ dep += openssl_dep
############ ############
have_libutf8proc = false have_libutf8proc = false
libutf8proc = [ ] libutf8proc = []
if want_libutf8proc if want_libutf8proc
libutf8proc = cc.find_library( libutf8proc = cc.find_library('utf8proc', required : require_libutf8proc)
'utf8proc', have_libutf8proc = cc.has_function('utf8proc_version', dependencies : libutf8proc)
required : require_libutf8proc,
)
have_libutf8proc = cc.has_function(
'utf8proc_version',
dependencies : libutf8proc,
)
if have_libutf8proc if have_libutf8proc
dep += libutf8proc dep += libutf8proc
endif endif
@ -470,15 +319,9 @@ endif
if want_textui if want_textui
setupterm_found = false setupterm_found = false
foreach setupterm_provider : [ 'tinfo', 'ncursesw', 'ncurses', 'terminfo' ] foreach setupterm_provider : ['tinfo', 'ncursesw', 'ncurses', 'terminfo']
prov_lib = cc.find_library( prov_lib = cc.find_library(setupterm_provider, required : false)
setupterm_provider, if prov_lib.found() and cc.has_function('setupterm', dependencies : prov_lib)
required : false,
)
if prov_lib.found() and cc.has_function(
'setupterm',
dependencies : prov_lib,
)
textui_dep += prov_lib textui_dep += prov_lib
setupterm_found = true setupterm_found = true
break break
@ -495,20 +338,15 @@ endif
have_perl = false have_perl = false
if want_perl if want_perl
perl_cflags = [ ] perl_cflags = []
perl_ldflags = [ ] perl_ldflags = []
perl_rpath_flags = [ ] perl_rpath_flags = []
perl_rpath = '' perl_rpath = ''
#### ccopts #### #### ccopts ####
perl_ccopts = meson.get_cross_property('perl_ccopts', UNSET_ARR) perl_ccopts = meson.get_cross_property('perl_ccopts', UNSET_ARR)
if perl_ccopts == UNSET_ARR if perl_ccopts == UNSET_ARR
res = run_command( res = run_command(cross_perl, '-MExtUtils::Embed', '-e', 'ccopts')
cross_perl,
'-MExtUtils::Embed',
'-e', 'ccopts',
check : true,
)
perl_ccopts = res.stdout().strip().split() perl_ccopts = res.stdout().strip().split()
endif endif
foreach fl : perl_ccopts foreach fl : perl_ccopts
@ -525,15 +363,10 @@ if want_perl
#### ldopts #### #### ldopts ####
perl_ldopts = meson.get_cross_property('perl_ldopts', UNSET_ARR) perl_ldopts = meson.get_cross_property('perl_ldopts', UNSET_ARR)
if perl_ldopts == UNSET_ARR if perl_ldopts == UNSET_ARR
res = run_command( res = run_command(cross_perl, '-MExtUtils::Embed', '-e', 'ldopts')
cross_perl,
'-MExtUtils::Embed',
'-e', 'ldopts',
check : true,
)
perl_ldopts = res.stdout().strip().split() perl_ldopts = res.stdout().strip().split()
endif endif
skip_libs = [ '-ldb', '-ldbm', '-lndbm', '-lgdbm', '-lc', '-lposix', '-rdynamic' ] skip_libs = ['-ldb', '-ldbm', '-lndbm', '-lgdbm', '-lc', '-lposix', '-rdynamic']
foreach fl : perl_ldopts foreach fl : perl_ldopts
if not fl.startswith('-A') and not skip_libs.contains(fl) if not fl.startswith('-A') and not skip_libs.contains(fl)
if fl.startswith('-Wl,-rpath,') if fl.startswith('-Wl,-rpath,')
@ -547,26 +380,18 @@ if want_perl
perl_version = meson.get_cross_property('perl_version', UNSET) perl_version = meson.get_cross_property('perl_version', UNSET)
if perl_version == UNSET if perl_version == UNSET
perl_version = run_command( perl_version = run_command(cross_perl, '-V::version:').stdout().split('\'')[1]
cross_perl,
'-V::version:',
check : true,
).stdout().split('\'')[1]
endif endif
# disable clang warning # disable clang warning
if perl_version.version_compare('<5.35.2') if perl_version.version_compare('<5.35.2')
perl_cflags += cc.get_supported_arguments('-Wno-compound-token-split-by-macro') perl_cflags += cc.get_supported_arguments('-Wno-compound-token-split-by-macro')
endif endif
perl_dep = declare_dependency( perl_dep = declare_dependency(compile_args : perl_cflags, link_args : perl_ldflags,
compile_args : perl_cflags, version : perl_version)
link_args : perl_ldflags,
version : perl_version,
)
#### ####
if not cc.links( if not cc.links('''
'''
#include <EXTERN.h> #include <EXTERN.h>
#include <perl.h> #include <perl.h>
int main() int main()
@ -574,10 +399,8 @@ int main()
perl_alloc(); perl_alloc();
return 0; return 0;
} }
''', ''', args : perl_cflags + perl_ldflags + perl_rpath_flags,
args : perl_cflags + perl_ldflags + perl_rpath_flags, name : 'working Perl support')
name : 'working Perl support',
)
if require_perl if require_perl
error('error linking with perl libraries') error('error linking with perl libraries')
else else
@ -586,15 +409,9 @@ int main()
else else
xsubpp_file_c = meson.get_cross_property('perl_xsubpp', UNSET) xsubpp_file_c = meson.get_cross_property('perl_xsubpp', UNSET)
if xsubpp_file_c == UNSET if xsubpp_file_c == UNSET
xsubpp_file_c = run_command( xsubpp_file_c = run_command(build_perl, '-MExtUtils::ParseXS', '-e($r = $INC{"ExtUtils/ParseXS.pm"}) =~ s{ParseXS\\.pm$}{xsubpp}; print $r').stdout()
build_perl,
'-MExtUtils::ParseXS',
'-e($r = $INC{"ExtUtils/ParseXS.pm"}) =~ s{ParseXS\\.pm$}{xsubpp}; print $r',
check : true,
).stdout()
endif endif
xsubpp = generator( xsubpp = generator(build_perl,
build_perl,
output : '@BASENAME@.c', output : '@BASENAME@.c',
capture : true, capture : true,
arguments : [ xsubpp_file_c, '@EXTRA_ARGS@', '@INPUT@' ], arguments : [ xsubpp_file_c, '@EXTRA_ARGS@', '@INPUT@' ],
@ -602,44 +419,31 @@ int main()
xsubpp_file = files(xsubpp_file_c) xsubpp_file = files(xsubpp_file_c)
if with_perl_lib == 'module' if with_perl_lib == 'module'
perl_install_base = run_command( perl_install_base = run_command(build_perl, '-MText::ParseWords=shellwords', '-e', 'grep { s/^INSTALL_BASE=// && print && exit } shellwords $ENV{PERL_MM_OPT}').stdout()
build_perl,
'-MText::ParseWords=shellwords',
'-e', 'grep { s/^INSTALL_BASE=// && print && exit } shellwords $ENV{PERL_MM_OPT}',
check : true,
).stdout()
if perl_install_base == '' if perl_install_base == ''
with_perl_lib = '' with_perl_lib = ''
endif endif
endif endif
if with_perl_lib == '' if with_perl_lib == ''
if get_option('prefix') in [ '/usr/local', 'C:/' ] if get_option('prefix') in ['/usr/local', 'C:/']
with_perl_lib = 'site' with_perl_lib = 'site'
elif get_option('prefix') in [ '/usr' ] elif get_option('prefix') in ['/usr']
with_perl_lib = 'vendor' with_perl_lib = 'vendor'
endif endif
endif endif
perlmoddir = '' perlmoddir = ''
if with_perl_lib in [ 'site', 'vendor', 'module' ] if with_perl_lib in ['site', 'vendor', 'module']
set_perl_use_lib = false set_perl_use_lib = false
perl_library_dir = with_perl_lib + ' default' perl_library_dir = with_perl_lib + ' default'
if with_perl_lib in [ 'site', 'vendor' ] if with_perl_lib in ['site', 'vendor']
perlmoddir = meson.get_cross_property('perl_install' + with_perl_lib + 'arch', UNSET) perlmoddir = meson.get_cross_property('perl_install' + with_perl_lib + 'arch', UNSET)
if perlmoddir == UNSET if perlmoddir == UNSET
perlmoddir = run_command( perlmoddir = run_command(cross_perl, '-V::install' + with_perl_lib + 'arch:').stdout().split('\'')[1]
cross_perl,
'-V::install' + with_perl_lib + 'arch:',
check : true,
).stdout().split('\'')[1]
endif endif
elif with_perl_lib == 'module' elif with_perl_lib == 'module'
perl_archname = meson.get_cross_property('perl_archname', UNSET) perl_archname = meson.get_cross_property('perl_archname', UNSET)
if perl_archname == UNSET if perl_archname == UNSET
perl_archname = run_command( perl_archname = run_command(cross_perl, '-V::archname:').stdout().split('\'')[1]
cross_perl,
'-V::archname:',
check : true,
).stdout().split('\'')[1]
endif endif
perlmoddir = perl_install_base / 'lib' / 'perl5' / perl_archname perlmoddir = perl_install_base / 'lib' / 'perl5' / perl_archname
endif endif
@ -660,12 +464,7 @@ int main()
if set_perl_use_lib if set_perl_use_lib
perl_inc = meson.get_cross_property('perl_inc', UNSET_ARR) perl_inc = meson.get_cross_property('perl_inc', UNSET_ARR)
if perl_inc == UNSET_ARR if perl_inc == UNSET_ARR
set_perl_use_lib = run_command( set_perl_use_lib = run_command(cross_perl, '-e', 'exit ! grep $_ eq $ARGV[0], grep /^\\//, @INC', perl_use_lib).returncode() != 0
cross_perl,
'-e', 'exit ! grep $_ eq $ARGV[0], grep /^\\//, @INC',
perl_use_lib,
check : false,
).returncode() != 0
else else
set_perl_use_lib = not perl_inc.contains(perl_use_lib) set_perl_use_lib = not perl_inc.contains(perl_use_lib)
endif endif
@ -691,20 +490,8 @@ endif
have_otr = false have_otr = false
if want_otr if want_otr
libgcrypt = dependency( libgcrypt = dependency('libgcrypt', version : '>=1.2.0', required : require_otr, static : want_static_dependency, include_type : 'system')
'libgcrypt', libotr = dependency('libotr', version : '>=4.1.0', required : require_otr, static : want_static_dependency, include_type : 'system')
version : '>=1.2.0',
required : require_otr,
static : want_static_dependency,
include_type : 'system',
)
libotr = dependency(
'libotr',
version : '>=4.1.0',
required : require_otr,
static : want_static_dependency,
include_type : 'system',
)
if libgcrypt.found() and libotr.found() if libgcrypt.found() and libotr.found()
dep += libgcrypt dep += libgcrypt
dep += libotr dep += libotr
@ -718,19 +505,9 @@ endif
have_capsicum = false have_capsicum = false
if want_capsicum if want_capsicum
if cc.has_function( if cc.has_function('cap_enter', dependencies : cc.find_library('c'))
'cap_enter', libnv = cc.find_library('nv', required : require_capsicum)
dependencies : cc.find_library('c'), nvlist_create_found = libnv.found() and cc.has_function('nvlist_create', dependencies : libnv, prefix : '#include <sys/nv.h>')
)
libnv = cc.find_library(
'nv',
required : require_capsicum,
)
nvlist_create_found = libnv.found() and cc.has_function(
'nvlist_create',
dependencies : libnv,
prefix : '#include <sys/nv.h>',
)
if nvlist_create_found if nvlist_create_found
dep += libnv dep += libnv
have_capsicum = true have_capsicum = true
@ -747,14 +524,11 @@ if want_capsicum
endif endif
# dependency helper sets # dependency helper sets
dep_cflagsonly = [ ] dep_cflagsonly = []
foreach d : dep foreach d : dep
dep_cflagsonly += d.partial_dependency( dep_cflagsonly += d.partial_dependency(includes : true, compile_args : true)
includes : true,
compile_args : true,
)
endforeach endforeach
dl_cross_dep = [ ] dl_cross_dep = []
if need_dl_cross_link if need_dl_cross_link
dl_cross_dep = dep dl_cross_dep = dep
endif endif
@ -765,19 +539,12 @@ endif
conf = configuration_data() conf = configuration_data()
conf.set( conf.set('HAVE_CAPSICUM', have_capsicum, description : 'Build with Capsicum support')
'HAVE_CAPSICUM',
have_capsicum,
description : 'Build with Capsicum support',
)
conf.set('HAVE_GMODULE', true) conf.set('HAVE_GMODULE', true)
conf.set('TERM_TRUECOLOR', true) conf.set('HAVE_SOCKS', false, description : 'Build with socks support')
conf.set('USE_GREGEX', true) conf.set('TERM_TRUECOLOR', want_truecolor, description : 'true color support in terminal')
conf.set10( conf.set('USE_GREGEX', want_gregex, description : 'use GRegex for regular expressions')
'_DARWIN_USE_64_BIT_INODE', conf.set10('_DARWIN_USE_64_BIT_INODE', true, description : 'Enable large inode numbers on Mac OS X 10.5.')
true,
description : 'Enable large inode numbers on Mac OS X 10.5.',
)
conf.set_quoted('FHS_PREFIX', get_option('fhs-prefix')) conf.set_quoted('FHS_PREFIX', get_option('fhs-prefix'))
headers = [ headers = [
@ -791,110 +558,29 @@ headers = [
] ]
foreach h : headers foreach h : headers
if cc.has_header(h) if cc.has_header(h)
conf.set( conf.set('HAVE_' + h.underscorify().to_upper(), 1, description : 'Define to 1 if you have the <' + h + '> header file.')
'HAVE_' + h.underscorify().to_upper(),
1,
description : 'Define to 1 if you have the <' + h + '> header file.',
)
endif endif
endforeach endforeach
if want_textui and conf.get('HAVE_TERM_H', 0) == 1
if cc.links(
'''
#include <stdio.h>
#include <term.h>
int main (void) {
return tputs("x", 1, putchar);
}
''',
args : '-pedantic-errors',
dependencies : textui_dep,
name : 'Curses working',
)
# ok
else
has_curses_h = cc.has_header('curses.h')
if has_curses_h and cc.links(
'''
#include <curses.h>
#include <term.h>
int main (void) {
return tputs("x", 1, putchar);
}
''',
args : '-pedantic-errors',
dependencies : textui_dep,
name : 'Curses working with curses.h',
)
conf.set(
'NEED_CURSES_H',
1,
description : 'tputs needs curses.h',
)
else
if has_curses_h and cc.links(
'''
#include <curses.h>
#include <term.h>
int char_putchar (char c) {
return putchar(c);
}
int main (void) {
return tputs("x", 1, char_putchar);
}
''',
args : '-pedantic-errors',
dependencies : textui_dep,
name : 'Curses with tputs third argument arg char',
)
conf.set(
'NEED_CURSES_H',
1,
description : 'tputs needs curses.h',
)
conf.set(
'TPUTS_SVR4',
1,
description : 'third argument of tputs has the type int (*)(char)',
)
else
error('could not link terminfo')
endif
endif
endif
endif
conf.set('HAVE_LIBUTF8PROC', have_libutf8proc) conf.set('HAVE_LIBUTF8PROC', have_libutf8proc)
conf.set_quoted('PACKAGE_VERSION', package_version) conf.set_quoted('PACKAGE_VERSION', package_version)
conf.set_quoted('PACKAGE_TARNAME', meson.project_name()) conf.set_quoted('PACKAGE_TARNAME', meson.project_name())
configure_file( configure_file(output : 'irssi-config.h',
output : 'irssi-config.h',
configuration : conf, configuration : conf,
install_dir : includedir / incdir, install_dir : includedir / incdir)
)
########## ##########
# CFLAGS # # CFLAGS #
########## ##########
#### warnings #### #### warnings ####
add_project_arguments( add_project_arguments(cc.get_supported_arguments('-Werror=declaration-after-statement'), language : 'c')
cc.get_supported_arguments('-Werror=declaration-after-statement'),
language : 'c',
)
#### personality #### #### personality ####
add_project_arguments( add_project_arguments(cc.get_supported_arguments('-fno-strict-aliasing'), language : 'c')
cc.get_supported_arguments('-fno-strict-aliasing'),
language : 'c',
)
if get_option('buildtype').contains('debug') if get_option('buildtype').contains('debug')
add_project_arguments( add_project_arguments(cc.get_supported_arguments('-fno-omit-frame-pointer'), language : 'c')
cc.get_supported_arguments('-fno-omit-frame-pointer'),
language : 'c',
)
endif endif
if want_fuzzer if want_fuzzer
@ -902,10 +588,7 @@ if want_fuzzer
if not cc.has_argument('-fsanitize=fuzzer-no-link') if not cc.has_argument('-fsanitize=fuzzer-no-link')
error('compiler does not support -fsanitize=fuzzer-no-link, try clang?') error('compiler does not support -fsanitize=fuzzer-no-link, try clang?')
endif endif
add_project_arguments( add_project_arguments('-fsanitize=fuzzer-no-link', language : 'c')
'-fsanitize=fuzzer-no-link',
language : 'c',
)
endif endif
if fuzzer_link_language != 'c' if fuzzer_link_language != 'c'
add_languages(fuzzer_link_language) add_languages(fuzzer_link_language)
@ -917,7 +600,7 @@ endif
############## ##############
pc = import('pkgconfig') pc = import('pkgconfig')
pc_requires = [ ] pc_requires = []
if not glib_internal if not glib_internal
pc_requires += glib_dep pc_requires += glib_dep
endif endif
@ -932,14 +615,15 @@ if signalsfile.startswith('/')
else else
signalsfile = '${prefix}' / signalsfile signalsfile = '${prefix}' / signalsfile
endif endif
pc.generate( pc.generate(filebase : 'irssi-1',
filebase : 'irssi-1',
name : 'Irssi', name : 'Irssi',
description : 'Irssi chat client', description : 'Irssi chat client',
version : package_version, version : package_version,
requires : pc_requires, requires : pc_requires,
variables : [ 'irssimoduledir=${libdir}' / incdir / 'modules', 'signalsfile=' + signalsfile ], variables : [
) 'irssimoduledir=${libdir}' / incdir / 'modules',
'signalsfile=' + signalsfile
])
########### ###########
# irssi.1 # # irssi.1 #
@ -979,6 +663,8 @@ if have_perl
endif endif
message('Install prefix ................... : ' + get_option('prefix')) message('Install prefix ................... : ' + get_option('prefix'))
message('') message('')
message('Building with true color support.. : ' + want_truecolor.to_string('yes', 'no'))
message('Building with GRegex ............. : ' + want_gregex.to_string('yes', 'no'))
message('Building with Capsicum ........... : ' + have_capsicum.to_string('yes', 'no')) message('Building with Capsicum ........... : ' + have_capsicum.to_string('yes', 'no'))
message('Building with utf8proc ........... : ' + have_libutf8proc.to_string('yes', 'no')) message('Building with utf8proc ........... : ' + have_libutf8proc.to_string('yes', 'no'))
message('Building with OTR support ........ : ' + have_otr.to_string('yes', 'no')) message('Building with OTR support ........ : ' + have_otr.to_string('yes', 'no'))

View file

@ -7,6 +7,8 @@ option('with-proxy', type : 'combo', description : 'Build irssi-proxy',
option('with-perl-lib', type : 'string', description : 'Specify where to install the Perl libraries for Irssi') option('with-perl-lib', type : 'string', description : 'Specify where to install the Perl libraries for Irssi')
option('with-perl', type : 'combo', description : 'Build with Perl support', choices : ['auto', 'yes', 'no']) option('with-perl', type : 'combo', description : 'Build with Perl support', choices : ['auto', 'yes', 'no'])
option('with-otr', type : 'combo', description : 'Build with OTR support', choices : ['auto', 'yes', 'no']) option('with-otr', type : 'combo', description : 'Build with OTR support', choices : ['auto', 'yes', 'no'])
option('enable-true-color', type : 'combo', description : 'Build with true color support in terminal', choices : ['no', 'yes'])
option('disable-gregex', type : 'combo', description : 'Build without GRegex (fall back to regex.h)', choices : ['no', 'yes'])
option('disable-utf8proc', type : 'combo', description : 'Build without Julia\'s utf8proc', choices : ['auto', 'yes', 'no']) option('disable-utf8proc', type : 'combo', description : 'Build without Julia\'s utf8proc', choices : ['auto', 'yes', 'no'])
option('with-capsicum', type : 'combo', description : 'Build with Capsicum support', choices : ['auto', 'yes', 'no']) option('with-capsicum', type : 'combo', description : 'Build with Capsicum support', choices : ['auto', 'yes', 'no'])
option('static-dependency', type : 'combo', description : 'Request static dependencies', choices : ['no', 'yes']) option('static-dependency', type : 'combo', description : 'Request static dependencies', choices : ['no', 'yes'])

18
scripts/Makefile.am Normal file
View file

@ -0,0 +1,18 @@
SUBDIRS = examples
scriptdir = $(datadir)/irssi/scripts
script_DATA = \
autoop.pl \
autorejoin.pl \
buf.pl \
dns.pl \
kills.pl \
mail.pl \
mlock.pl \
quitmsg.pl \
scriptassist.pl \
usercount.pl
EXTRA_DIST = $(script_DATA) \
meson.build

View file

@ -5,7 +5,7 @@ use Irssi;
use strict; use strict;
use vars qw($VERSION %IRSSI); use vars qw($VERSION %IRSSI);
$VERSION = "1.11"; $VERSION = "1.10";
%IRSSI = ( %IRSSI = (
authors => 'Timo Sirainen & Jostein Kjønigsen', authors => 'Timo Sirainen & Jostein Kjønigsen',
name => 'autoop', name => 'autoop',
@ -98,11 +98,10 @@ sub load_autoops {
%opnicks = (); %opnicks = ();
open(CONF, "<", "$file") or return; open(CONF, "<", "$file") or return;
while (my $line = <CONF>) { while (my $line = <CONF>) {
chomp($line); if ($line !=~ /^\s*$/) {
if ($line !~ /^\s*$/) { cmd_autoop($line);
cmd_autoop($line); $count++;
$count++; }
}
} }
close(CONF); close(CONF);

View file

@ -0,0 +1,8 @@
scriptdir = $(datadir)/irssi/scripts
script_DATA = \
command.pl \
msg-event.pl \
redirect.pl
EXTRA_DIST = $(script_DATA)

View file

@ -1,6 +1,6 @@
use strict; use strict;
use vars qw($VERSION %IRSSI); use vars qw($VERSION %IRSSI);
$VERSION = "2.93"; $VERSION = "2.92";
%IRSSI = ( %IRSSI = (
authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei", authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei",
contact => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl", contact => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl",
@ -63,8 +63,8 @@ sub cmd_print_help {
"/MAILBOX SHOW\n". "/MAILBOX SHOW\n".
" - Shows a list of the defined mailboxes.\n\n". " - Shows a list of the defined mailboxes.\n\n".
"Use the following commands to change the behaviour:\n\n". "Use the following commands to change the behaviour:\n\n".
"/SET MAILDIR_MODE on|off\n". "/SET MAILDIRMODE on|off\n".
" - If maildir_mode is on, the mailboxes in the list are assumed to be ". " - If maildirmode is on, the mailboxes in the list are assumed to be ".
"directories. Otherwise they are assumed to be spool files.\n". "directories. Otherwise they are assumed to be spool files.\n".
" Default: off.\n". " Default: off.\n".
"/SET MAIL_OLDNOTNEW on|off\n". "/SET MAIL_OLDNOTNEW on|off\n".

View file

@ -11,5 +11,4 @@ install_data(
'scriptassist.pl', 'scriptassist.pl',
'usercount.pl', 'usercount.pl',
), ),
install_dir : scriptdir, install_dir : scriptdir)
)

View file

@ -5,7 +5,7 @@
use strict; use strict;
our $VERSION = '2023111700'; our $VERSION = '2022053100';
our %IRSSI = ( our %IRSSI = (
authors => 'Stefan \'tommie\' Tomanek', authors => 'Stefan \'tommie\' Tomanek',
contact => 'stefan@pico.ruhr.de', contact => 'stefan@pico.ruhr.de',
@ -22,8 +22,6 @@ our ($forked, %remote_db, $have_gpg, @complist);
use Irssi 20020324; use Irssi 20020324;
use CPAN::Meta::YAML; use CPAN::Meta::YAML;
use LWP::UserAgent; use LWP::UserAgent;
use Hash::Util qw(lock_ref_keys);
use JSON::PP;
use POSIX; use POSIX;
use version; use version;
@ -45,7 +43,7 @@ sub show_help {
/scriptassist info <scripts> /scriptassist info <scripts>
Display information about <scripts> Display information about <scripts>
/scriptassist ratings <scripts|all> /scriptassist ratings <scripts|all>
Retrieve the average ratings of the scripts Retrieve the average ratings of the the scripts
/scriptassist top <num> /scriptassist top <num>
Retrieve the first <num> top rated scripts Retrieve the first <num> top rated scripts
/scriptassist new <num> /scriptassist new <num>
@ -201,163 +199,87 @@ sub get_unknown {
} }
sub get_names { sub get_names {
my ($sname, $db, $votes) = @_; my ($sname, $db) = shift;
$sname =~ s/\s+$//; $sname =~ s/\s+$//;
my $ext = 'pl'; # default extension $sname =~ s/\.pl$//;
if ($sname =~ s/\.(\w{2,3})$//) { my $plname = "$sname.pl";
$ext = $1;
}
my $plname = "$sname.$ext";
$sname =~ s/^.*\///; $sname =~ s/^.*\///;
my $xname = $sname; my $xname = $sname;
$xname =~ s/\W/_/g; $xname =~ s/\W/_/g;
my $pname = "${xname}::"; my $pname = "${xname}::";
if ($xname ne $sname || $sname =~ /_/) { if ($xname ne $sname || $sname =~ /_/) {
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
if ($db && exists $db->{$plname}) { if ($db && exists $db->{"$sname.pl"}) {
# $found = 1; # $found = 1;
} elsif (-e $dir.$plname || -e $dir."autorun/".$plname) { } elsif (-e $dir.$plname || -e $dir."$sname.pl" || -e $dir."autorun/$sname.pl") {
# $found = 1; # $found = 1;
} else { } else {
# not found # not found
my $pat = $xname; $pat =~ y/_/?/; my $pat = $xname; $pat =~ y/_/?/;
my $re = "\Q$xname"; $re =~ s/\Q_/./g; my $re = "\Q$xname"; $re =~ s/\Q_/./g;
if ($db) { if ($db) {
my ($cand) = grep /^$re\.\Q$ext\E$/, sort keys %$db; my ($cand) = grep /^$re\.pl$/, sort keys %$db;
if ($cand) { if ($cand) {
return get_names($cand, $db, $votes); return get_names($cand, $db);
} }
} }
my ($cand) = glob "'$dir$pat.$ext' '${dir}autorun/$pat.$ext'"; my ($cand) = glob "'$dir$pat.pl' '${dir}autorun/$pat.pl'";
if ($cand) { if ($cand) {
$cand =~ s/^.*\///; $cand =~ s/^.*\///;
return get_names($cand, $db, $votes); return get_names($cand, $db);
} }
} }
} }
my ($script_stash, $script_irssi, $script_db, $local_version); ($sname, $plname, $pname, $xname)
$script_db = $db->{$plname} if $db && exists $db->{$plname};
if (lc $ext eq 'pl') {
$script_stash = $Irssi::Script::{$pname};
}
elsif (lc $ext eq 'py' && is_python_loaded()) {
my $filename;
capture_print_text_command(
'py list',
sub {
for my $line (@_[ 1 .. $#_ ]) {
my ($script, $fn) = split ' ', $line, 2;
if ($script eq $sname) {
$filename = $fn;
}
}
});
if (defined $filename) {
my $filename_quoted = $filename;
$filename_quoted =~ s/[\\']/\\$&/g;
capture_print_text_command(
# make sure the command line stays short
'py exec ' .
(join ';', split /\n/, <<PYTHON
import ast as A, types as _, json
i = 'IRSSI'
v = '__version__'
T = isinstance
f = '$filename_quoted'
a = lambda _: T(_, A.Assign)
n = lambda _: T(_, A.Name)
y = lambda _: _.id
t = lambda _: list(map(y, filter(n, _.targets)))
C = lambda e: lambda _: a(_) and t(_) == [e]
O = _.SimpleNamespace(value=A.Constant(None))
P = A.parse(open(f).read(), filename=f)
f = lambda e: A.literal_eval(next(filter(C(e), P.body), O).value)
print(json.dumps({ i: f(i), v: f(v) }))
PYTHON
),
sub {
eval {
my $doc = decode_json("@_");
$script_stash = { IRSSI => $doc->{IRSSI}, VERSION => \($doc->{__version__}) };
};
}
);
}
}
if (defined $script_stash) {
$script_irssi = $script_stash->{IRSSI};
$local_version = ${$script_stash->{VERSION}}
if $script_stash->{VERSION};
}
lock_ref_keys({
sname => $ext eq 'pl' ? $sname : $plname,
plname => $plname,
pname => $pname,
xname => $xname,
stash => $script_stash,
irssi => $script_irssi,
db => $script_db,
db_version => ($script_db ? $script_db->{version} : undef),
local_version => $local_version,
($votes ? (votes => $votes->{$plname}) : ()),
})
} }
sub script_info { sub script_info {
my ($scripts) = @_; my ($scripts) = @_;
my %result; my %result;
my $xml = get_scripts(); my $xml = get_scripts();
my $py = is_python_loaded();
foreach (@{$scripts}) { foreach (@{$scripts}) {
my %r; my ($sname, $plname, $pname) = get_names($_, $xml);
my $n = get_names($_, $xml); next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} ));
next unless (defined $n->{db} || defined $n->{irssi}); $result{$sname}{version} = get_remote_version($sname, $xml);
$r{version} = $n->{db_version};
my @headers = ('authors', 'contact', 'description', 'license', 'source'); my @headers = ('authors', 'contact', 'description', 'license', 'source');
foreach my $entry (@headers) { foreach my $entry (@headers) {
$r{$entry} = $n->{irssi}{$entry}; $result{$sname}{$entry} = $Irssi::Script::{$pname}{IRSSI}{$entry};
if ($n->{db} && defined $n->{db}{$entry}) { if (defined $xml->{$plname}{$entry}) {
$r{$entry} = $n->{db}{$entry}; $result{$sname}{$entry} = $xml->{$plname}{$entry};
} }
} }
if ($n->{db} && $n->{db}{signature_available}) { if ($xml->{$plname}{signature_available}) {
$r{signature_available} = 1; $result{$sname}{signature_available} = 1;
} }
if ($n->{db} && defined $n->{db}{modules}) { if (defined $xml->{$plname}{modules}) {
my $modules = $n->{db}{modules}; my $modules = $xml->{$plname}{modules};
foreach my $mod (split(/ /, $modules)) { foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0; my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1; $mod = $1 if $1;
$r{modules}{$mod}{optional} = $opt; $result{$sname}{modules}{$mod}{optional} = $opt;
$r{modules}{$mod}{installed} = module_exist($mod); $result{$sname}{modules}{$mod}{installed} = module_exist($mod);
} }
} elsif ($n->{irssi} && defined $n->{irssi}{modules}) { } elsif (defined $Irssi::Script::{$pname}{IRSSI}{modules}) {
my $modules = $n->{irssi}{modules}; my $modules = $Irssi::Script::{$pname}{IRSSI}{modules};
foreach my $mod (split(/ /, $modules)) { foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0; my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1; $mod = $1 if $1;
$r{modules}{$mod}{optional} = $opt; $result{$sname}{modules}{$mod}{optional} = $opt;
$r{modules}{$mod}{installed} = module_exist($mod); $result{$sname}{modules}{$mod}{installed} = module_exist($mod);
} }
} }
if (!$py && $n->{db} && $n->{db}{language} eq 'Python') { # py # if (defined $xml->{$plname}{depends}) {
$r{modules}{'irssi-python module'}{installed} = 0; # my $depends = $xml->{$plname}{depends};
}
# if (defined $n->{db}{depends}) {
# my $depends = $n->{db}{depends};
# foreach my $dep (split(/ /, $depends)) { # foreach my $dep (split(/ /, $depends)) {
# $r{depends}{$dep}{installed} = 1; #(defined ${ 'Irssi::Script::'.$dep }); # $result{$sname}{depends}{$dep}{installed} = 1; #(defined ${ 'Irssi::Script::'.$dep });
# } # }
# } # }
$result{$n->{sname}} = \%r;
} }
return \%result; return \%result;
} }
sub get_rate_url { sub get_rate_url {
my ($src) = @_; my ($src) = @_;
if (ref $src) { ($src) = grep { $_ } map { $_->{source} } values %$src; }
die("No script source address found\n") unless $src;
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30); my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
$ua->agent('ScriptAssist/'.$VERSION); $ua->agent('ScriptAssist/'.$VERSION);
my $request = HTTP::Request->new('GET', $src); my $request = HTTP::Request->new('GET', $src);
@ -366,9 +288,6 @@ sub get_rate_url {
my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), ''; my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
die("Fetching ratings location failed: $error"); die("Fetching ratings location failed: $error");
} }
if (my $error = $response->header('X-Died')) {
die("$error\n");
}
my $votes_url; my $votes_url;
for my $tag ($response->content() =~ /<script([^>]*)>/g) { for my $tag ($response->content() =~ /<script([^>]*)>/g) {
my $attr = " $tag "; my $attr = " $tag ";
@ -380,7 +299,7 @@ sub get_rate_url {
} }
$request = HTTP::Request->new('GET', $votes_url); $request = HTTP::Request->new('GET', $votes_url);
$response = $ua->request($request); $response = $ua->request($request);
if (!$response->is_success || $response->header('X-Died')) { if (!$response->is_success) {
my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), ''; my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
die("Fetching ratings failed: $error"); die("Fetching ratings failed: $error");
} }
@ -392,16 +311,16 @@ sub get_rate_url {
sub rate_script { sub rate_script {
my ($script, $stars) = @_; my ($script, $stars) = @_;
my $xml = get_scripts(); my $xml = get_scripts();
my $votes = get_rate_url($xml); my $votes = get_rate_url(map { $_->{source} } values %$xml);
my $n = get_names($script, $xml, $votes); my ($sname, $plname, $pname) = get_names($script, $xml);
die "Script $script not found\n" unless $n->{votes}; die "Script $script not found\n" unless $votes->{$plname};
return $n->{votes}{u} return $votes->{$plname}{u}
} }
sub get_ratings { sub get_ratings {
my ($scripts, $limit) = @_; my ($scripts, $limit) = @_;
my $xml = get_scripts(); my $xml = get_scripts();
my $votes = get_rate_url($xml); my $votes = get_rate_url(map { $_->{source} } values %$xml);
foreach (keys %{$votes}) { foreach (keys %{$votes}) {
if ($xml->{$_}) { if ($xml->{$_}) {
$xml->{$_}{votes} = $votes->{$_}{v}; $xml->{$_}{votes} = $votes->{$_}{v};
@ -410,9 +329,9 @@ sub get_ratings {
my %result; my %result;
if (@{$scripts}) { if (@{$scripts}) {
foreach (@{$scripts}) { foreach (@{$scripts}) {
my $n = get_names($_, $xml); my ($sname, $plname, $pname) = get_names($_, $xml);
next unless ($n->{db} || $n->{irssi}); next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} ));
$result{$n->{plname}} = [$n->{db}{votes}]; $result{$plname} = [$xml->{$plname}{votes}];
} }
} else { } else {
my @keys = sort { $xml->{$b}{votes} <=> $xml->{$a}{votes} my @keys = sort { $xml->{$b}{votes} <=> $xml->{$a}{votes}
@ -452,22 +371,16 @@ sub debug_scripts {
my ($scripts) = @_; my ($scripts) = @_;
my %result; my %result;
my $xml = get_scripts(); my $xml = get_scripts();
my $py = is_python_loaded();
foreach (@{$scripts}) { foreach (@{$scripts}) {
my %r; my ($sname, $plname) = get_names($_, $xml);
my $n = get_names($_, $xml); if (defined $xml->{$plname}{modules}) {
if ($n->{db} && defined $n->{db}{modules}) { my $modules = $xml->{$plname}{modules};
my $modules = $n->{db}{modules};
foreach my $mod (split(/ /, $modules)) { foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0; my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1; $mod = $1 if $1;
$r{$mod}{optional} = $opt; $result{$sname}{$mod}{optional} = $opt;
$r{$mod}{installed} = module_exist($mod); $result{$sname}{$mod}{installed} = module_exist($mod);
} }
$result{$n->{sname}} = \%r;
}
if (!$py && $n->{db} && $n->{db}{language} eq 'Python') { # py
$result{$n->{sname}}{'irssi-python module'}{installed} = 0;
} }
} }
return(\%result); return(\%result);
@ -478,11 +391,11 @@ sub install_scripts {
my %success; my %success;
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
foreach (@{$scripts}) { foreach (@{$scripts}) {
my $n = get_names($_, $xml); my ($sname, $plname, $pname) = get_names($_, $xml);
if ($n->{stash} && (-e $dir.$n->{plname})) { if (get_local_version($sname) && (-e $dir.$plname)) {
$success{$n->{sname}}{installed} = -2; $success{$sname}{installed} = -2;
} else { } else {
$success{$n->{sname}} = download_script($n->{sname}, $xml); $success{$sname} = download_script($sname, $xml);
} }
} }
return \%success; return \%success;
@ -493,24 +406,24 @@ sub update_scripts {
$list = loaded_scripts() if ($list->[0] eq "all" || scalar(@$list) == 0); $list = loaded_scripts() if ($list->[0] eq "all" || scalar(@$list) == 0);
my %status; my %status;
foreach (@{$list}) { foreach (@{$list}) {
my $n = get_names($_, $database); my ($sname) = get_names($_, $database);
my $local = $n->{local_version}; my $local = get_local_version($sname);
my $remote = $n->{db_version}; my $remote = get_remote_version($sname, $database);
next if $local eq '' || $remote eq ''; next if $local eq '' || $remote eq '';
if (compare_versions($local, $remote) eq "older") { if (compare_versions($local, $remote) eq "older") {
$status{$n->{sname}} = download_script($n->{sname}, $database); $status{$sname} = download_script($sname, $database);
} else { } else {
$status{$n->{sname}}{installed} = -2; $status{$sname}{installed} = -2;
} }
$status{$n->{sname}}{remote} = $remote; $status{$sname}{remote} = $remote;
$status{$n->{sname}}{local} = $local; $status{$sname}{local} = $local;
} }
return \%status; return \%status;
} }
sub search_scripts { sub search_scripts {
my ($query, $database) = @_; my ($query, $database) = @_;
$query =~ s/\.pl\Z//; # pl $query =~ s/\.pl\Z//;
my %result; my %result;
foreach (sort keys %{$database}) { foreach (sort keys %{$database}) {
my %entry = %{$database->{$_}}; my %entry = %{$database->{$_}};
@ -519,7 +432,7 @@ sub search_scripts {
$string .= $entry{description} if defined $entry{description}; $string .= $entry{description} if defined $entry{description};
if ($string =~ /$query/i) { if ($string =~ /$query/i) {
my $name = $_; my $name = $_;
$name =~ s/\.pl$//; # pl $name =~ s/\.pl$//;
if (defined $entry{description}) { if (defined $entry{description}) {
$result{$name}{desc} = $entry{description}; $result{$name}{desc} = $entry{description};
} else { } else {
@ -530,7 +443,7 @@ sub search_scripts {
} else { } else {
$result{$name}{authors} = ""; $result{$name}{authors} = "";
} }
if (get_names($name, $database)->{stash}) { if (get_local_version($name)) {
$result{$name}{installed} = 1; $result{$name}{installed} = 1;
} else { } else {
$result{$name}{installed} = 0; $result{$name}{installed} = 0;
@ -618,8 +531,8 @@ sub print_unknown {
my $text .= "The command '/".$cmd."' is provided by the script '".$data->{$cmd}{$_}{name}."'.\n"; my $text .= "The command '/".$cmd."' is provided by the script '".$data->{$cmd}{$_}{name}."'.\n";
$text .= "This script is currently not installed on your system.\n"; $text .= "This script is currently not installed on your system.\n";
$text .= "If you want to install the script, enter\n"; $text .= "If you want to install the script, enter\n";
my $n = get_names($_); my ($name) = get_names($_);
$text .= " %U/script install ".$n->{sname}."%U "; $text .= " %U/script install ".$name."%U ";
my $output = draw_box("ScriptAssist", $text, "'".$_."' missing", 1); my $output = draw_box("ScriptAssist", $text, "'".$_."' missing", 1);
print CLIENTCRAP $output; print CLIENTCRAP $output;
} }
@ -628,10 +541,10 @@ sub print_unknown {
sub check_autorun { sub check_autorun {
my ($script) = @_; my ($script) = @_;
my $n = get_names($script); my (undef, $plname) = get_names($script);
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
if (-e $dir."/autorun/".$n->{plname}) { if (-e $dir."/autorun/".$plname) {
if (readlink($dir."/autorun/".$n->{plname}) eq "../".$n->{plname}) { if (readlink($dir."/autorun/".$plname) eq "../".$plname) {
return 1; return 1;
} }
} }
@ -669,15 +582,14 @@ sub print_info {
my $line; my $line;
foreach my $script (sort keys(%data)) { foreach my $script (sort keys(%data)) {
my ($local, $autorun); my ($local, $autorun);
my $n = get_names($script); if (get_local_version($script)) {
if ($n->{stash}) {
$line .= "%go%n "; $line .= "%go%n ";
$local = $n->{local_version}; $local = get_local_version($script);
} else { } else {
$line .= "%ro%n "; $line .= "%ro%n ";
$local = undef; $local = undef;
} }
if ($n->{stash} || check_autorun($script)) { if (defined $local || check_autorun($script)) {
$autorun = "no"; $autorun = "no";
$autorun = "yes" if check_autorun($script); $autorun = "yes" if check_autorun($script);
} else { } else {
@ -731,7 +643,7 @@ sub print_ratings {
my @table; my @table;
foreach my $script (sort {$data{$b}{rating}<=>$data{$a}{rating}} keys(%data)) { foreach my $script (sort {$data{$b}{rating}<=>$data{$a}{rating}} keys(%data)) {
my @line; my @line;
if (get_names($script)->{stash}) { if (get_local_version($script)) {
push @line, "%go%n"; push @line, "%go%n";
} else { } else {
push @line, "%yo%n"; push @line, "%yo%n";
@ -748,13 +660,13 @@ sub print_new {
my @table; my @table;
foreach (sort {$list->{$b}{modified} cmp $list->{$a}{modified}} keys %$list) { foreach (sort {$list->{$b}{modified} cmp $list->{$a}{modified}} keys %$list) {
my @line; my @line;
my $n = get_names($_); my ($name) = get_names($_);
if ($n->{stash}) { if (get_local_version($name)) {
push @line, "%go%n"; push @line, "%go%n";
} else { } else {
push @line, "%yo%n"; push @line, "%yo%n";
} }
push @line, "%9".$n->{sname}."%9"; push @line, "%9".$name."%9";
push @line, $list->{$_}{modified}; push @line, $list->{$_}{modified};
push @table, \@line; push @table, \@line;
} }
@ -766,23 +678,14 @@ sub print_debug {
my $line; my $line;
foreach my $script (sort keys %data) { foreach my $script (sort keys %data) {
$line .= "%ro%n %9".$script."%9 failed to load\n"; $line .= "%ro%n %9".$script."%9 failed to load\n";
my $py = $data{$script}{'irssi-python module'}; $line .= " Make sure you have the following perl modules installed:\n";
if ($py) { # py
$line .= " You are attempting to load a Python script!\n";
} else {
$line .= " Make sure you have the following perl modules installed:\n";
}
foreach (sort keys %{$data{$script}}) { foreach (sort keys %{$data{$script}}) {
if ( $data{$script}{$_}{installed} == 1 ) { if ( $data{$script}{$_}{installed} == 1 ) {
$line .= " %g->%n ".$_." (found)"; $line .= " %g->%n ".$_." (found)";
} else { } else {
$line .= " %r->%n ".$_." (not found)\n"; $line .= " %r->%n ".$_." (not found)\n";
$line .= " [This module is optional]\n" if $data{$script}{$_}{optional}; $line .= " [This module is optional]\n" if $data{$script}{$_}{optional};
if ($py) { # py $line .= " [Try /scriptassist cpan ".$_."]";
$line .= " [If you have it installed, try: /load python]";
} else {
$line .= " [Try /scriptassist cpan ".$_."]";
}
} }
$line .= "\n"; $line .= "\n";
} }
@ -792,13 +695,7 @@ sub print_debug {
sub load_script { sub load_script {
my ($script) = @_; my ($script) = @_;
if ($script =~ s/\.py$//i) { # py Irssi::command('script load '.$script);
if (is_python_loaded()) {
Irssi::command('py load '.$script);
}
} else {
Irssi::command('script load '.$script); # pl
}
} }
sub print_install { sub print_install {
@ -818,7 +715,7 @@ sub print_install {
} else { } else {
load_script($script) unless (lc($script) eq lc($IRSSI{name})); load_script($script) unless (lc($script) eq lc($IRSSI{name}));
} }
if (get_names($script)->{stash} && not lc($script) eq lc($IRSSI{name})) { if (get_local_version($script) && not lc($script) eq lc($IRSSI{name})) {
$line .= "%go%n %9".$script."%9 installed\n"; $line .= "%go%n %9".$script."%9 installed\n";
push @installed, $script; push @installed, $script;
} elsif (lc($script) eq lc($IRSSI{name})) { } elsif (lc($script) eq lc($IRSSI{name})) {
@ -854,14 +751,16 @@ sub list_sbitems {
my ($scripts) = @_; my ($scripts) = @_;
my $text; my $text;
foreach (@$scripts) { foreach (@$scripts) {
my $n = get_names($_); next unless exists $Irssi::Script::{"${_}::"};
next unless $n->{irssi}{sbitems}; next unless exists $Irssi::Script::{"${_}::"}{IRSSI};
my $header = $Irssi::Script::{"${_}::"}{IRSSI};
next unless $header->{sbitems};
$text .= '%9"'.$_.'"%9 provides the following statusbar item(s):'."\n"; $text .= '%9"'.$_.'"%9 provides the following statusbar item(s):'."\n";
$text .= ' ->'.$_."\n" foreach (split / /, $n->{irssi}{sbitems}); $text .= ' ->'.$_."\n" foreach (split / /, $header->{sbitems});
} }
return unless $text; return unless $text;
$text .= "\n"; $text .= "\n";
$text .= "Enter '/statusbar additem <item> window' to add an item."; $text .= "Enter '/statusbar window add <item>' to add an item.";
print CLIENTCRAP draw_box('ScriptAssist', $text, 'sbitems', 1); print CLIENTCRAP draw_box('ScriptAssist', $text, 'sbitems', 1);
} }
@ -939,12 +838,14 @@ sub print_update {
sub contact_author { sub contact_author {
my ($script) = @_; my ($script) = @_;
my $n = get_names($script); my ($sname, $plname, $pname) = get_names($script);
if ($n->{irssi} && defined $n->{irssi}{contact}) { return unless exists $Irssi::Script::{$pname};
my @ads = split(/ |,/, $n->{irssi}{contact}); my $header = $Irssi::Script::{$pname}{IRSSI};
if ($header && defined $header->{contact}) {
my @ads = split(/ |,/, $header->{contact});
my $address = $ads[0]; my $address = $ads[0];
$address .= '?subject='.$script; $address .= '?subject='.$script;
$address .= '_'.$n->{local_version} if $n->{local_version}; $address .= '_'.get_local_version($script) if defined get_local_version($script);
call_openurl($address) if $address =~ /[\@:]/; call_openurl($address) if $address =~ /[\@:]/;
} }
} }
@ -973,10 +874,6 @@ sub get_scripts {
$error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), ''; $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
next; next;
} }
if (my $died = $response->header('X-Died')) {
$error = $died;
next;
}
$fetched = 1; $fetched = 1;
my $data = $response->content(); my $data = $response->content();
my $src = $site; my $src = $site;
@ -1032,6 +929,20 @@ sub get_scripts {
return $remote_db{db}; return $remote_db{db};
} }
sub get_remote_version {
my ($script, $database) = @_;
my $plname = (get_names($script, $database))[1];
return $database->{$plname}{version};
}
sub get_local_version {
my ($script) = @_;
my $pname = (get_names($script))[2];
return unless exists $Irssi::Script::{$pname};
my $vref = $Irssi::Script::{$pname}{VERSION};
return $vref ? $$vref : undef;
}
sub compare_versions { sub compare_versions {
my ($ver1, $ver2) = @_; my ($ver1, $ver2) = @_;
for ($ver1, $ver2) { for ($ver1, $ver2) {
@ -1048,42 +959,11 @@ sub compare_versions {
return 'equal'; return 'equal';
} }
sub is_python_loaded {
!! grep { $_->{cmd} eq 'py' } Irssi::commands
}
my @print_text_capture;
sub capture_print_text {
my ($dest, $text, $plain) = @_;
push @print_text_capture, $plain;
Irssi::signal_stop;
}
sub capture_print_text_command {
my ($command, $sub) = @_;
Irssi::signal_add_first('print text', 'capture_print_text');
@print_text_capture = ();
Irssi::command($command);
my @capture = @print_text_capture;
Irssi::signal_remove('print text', 'capture_print_text');
@print_text_capture = ();
$sub->(@capture);
}
sub loaded_scripts { sub loaded_scripts {
my @modules; my @modules;
foreach (sort grep(s/::$//, keys %Irssi::Script::)) { # pl foreach (sort grep(s/::$//, keys %Irssi::Script::)) {
push @modules, $_; push @modules, $_;
} }
if (is_python_loaded()) {
capture_print_text_command(
'py list', sub {
for my $line (@_[ 1 .. $#_ ]) {
my ($script, $file) = split ' ', $line, 2;
push @modules, "$script.py";
}
});
}
return \@modules; return \@modules;
} }
@ -1091,9 +971,9 @@ sub check_scripts {
my ($data) = @_; my ($data) = @_;
my %versions; my %versions;
foreach (@{loaded_scripts()}) { foreach (@{loaded_scripts()}) {
my $n = get_names($_, $data); my ($sname) = get_names($_, $data);
my $remote = $n->{db_version}; my $remote = get_remote_version($sname, $data);
my $local = $n->{local_version}; my $local = get_local_version($sname);
my $state; my $state;
if ($local && $remote) { if ($local && $remote) {
$state = compare_versions($local, $remote); $state = compare_versions($local, $remote);
@ -1106,9 +986,9 @@ sub check_scripts {
$remote = '/'; $remote = '/';
} }
if ($state) { if ($state) {
$versions{$n->{sname}}{state} = $state; $versions{$sname}{state} = $state;
$versions{$n->{sname}}{remote} = $remote; $versions{$sname}{remote} = $remote;
$versions{$n->{sname}}{local} = $local; $versions{$sname}{local} = $local;
} }
} }
return \%versions; return \%versions;
@ -1116,40 +996,40 @@ sub check_scripts {
sub download_script { sub download_script {
my ($script, $xml) = @_; my ($script, $xml) = @_;
my $n = get_names($script, $xml); my ($sname, $plname) = get_names($script, $xml);
my $site = $n->{db}{source};
my %result; my %result;
my $site = $xml->{$plname}{source};
$result{installed} = 0; $result{installed} = 0;
$result{signed} = 0; $result{signed} = 0;
my $dir = Irssi::get_irssi_dir(); my $dir = Irssi::get_irssi_dir();
my $ua = LWP::UserAgent->new(env_proxy => 1, keep_alive => 1, timeout => 30); my $ua = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
$ua->agent('ScriptAssist/'.2003020803); $ua->agent('ScriptAssist/'.2003020803);
my $request = HTTP::Request->new('GET', $site.'/scripts/'.$n->{plname}); my $request = HTTP::Request->new('GET', $site.'/scripts/'.$script.'.pl');
my $response = $ua->request($request); my $response = $ua->request($request);
if ($response->is_success() && !$response->header('X-Died')) { if ($response->is_success()) {
my $file = $response->content(); my $file = $response->content();
mkdir $dir.'/scripts/' unless (-e $dir.'/scripts/'); mkdir $dir.'/scripts/' unless (-e $dir.'/scripts/');
open(my $f, '>', $dir.'/scripts/'.$n->{plname}.'.new'); open(my $F, '>', $dir.'/scripts/'.$plname.'.new');
print $f $file; print $F $file;
close($f); close($F);
if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) { if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) {
my $ua2 = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30); my $ua2 = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
$ua->agent('ScriptAssist/'.2003020803); $ua->agent('ScriptAssist/'.2003020803);
my $request2 = HTTP::Request->new('GET', $site.'/signatures/'.$n->{plname}.'.asc'); my $request2 = HTTP::Request->new('GET', $site.'/signatures/'.$plname.'.asc');
my $response2 = $ua->request($request2); my $response2 = $ua->request($request2);
if ($response2->is_success() && !$response->header('X-Died')) { if ($response2->is_success()) {
my $sig_dir = $dir.'/scripts/signatures/'; my $sig_dir = $dir.'/scripts/signatures/';
mkdir $sig_dir unless (-e $sig_dir); mkdir $sig_dir unless (-e $sig_dir);
open(my $s, '>', $sig_dir.$n->{plname}.'.asc'); open(my $S, '>', $sig_dir.$plname.'.asc');
my $file2 = $response2->content(); my $file2 = $response2->content();
print $s $file2; print $S $file2;
close($s); close($S);
my $sig; my $sig;
foreach (1..2) { foreach (1..2) {
# FIXME gpg needs two rounds to load the key # FIXME gpg needs two rounds to load the key
my $gpg = new GnuPG(); my $gpg = new GnuPG();
eval { eval {
$sig = $gpg->verify( file => $dir.'/scripts/'.$n->{plname}.'.new', signature => $sig_dir.$n->{plname}.'.asc' ); $sig = $gpg->verify( file => $dir.'/scripts/'.$plname.'.new', signature => $sig_dir.$plname.'.asc' );
}; };
} }
if (defined $sig->{user}) { if (defined $sig->{user}) {
@ -1175,8 +1055,8 @@ sub download_script {
if ($result{installed}) { if ($result{installed}) {
my $old_dir = "$dir/scripts/old/"; my $old_dir = "$dir/scripts/old/";
mkdir $old_dir unless (-e $old_dir); mkdir $old_dir unless (-e $old_dir);
rename "$dir/scripts/".$n->{plname}, "$old_dir/".$n->{plname}.".old" if -e "$dir/scripts/".$n->{plname}; rename "$dir/scripts/$plname", "$old_dir/$plname.old" if -e "$dir/scripts/$plname";
rename "$dir/scripts/".$n->{plname}.".new", "$dir/scripts/".$n->{plname}; rename "$dir/scripts/$plname.new", "$dir/scripts/$plname";
} }
return \%result; return \%result;
} }
@ -1203,23 +1083,23 @@ sub print_check {
sub toggle_autorun { sub toggle_autorun {
my ($script) = @_; my ($script) = @_;
my $n = get_names($script); my ($sname, $plname) = get_names($script);
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
mkdir $dir."autorun/" unless (-e $dir."autorun/"); mkdir $dir."autorun/" unless (-e $dir."autorun/");
return unless (-e $dir.$n->{plname}); return unless (-e $dir.$plname);
if (-e $dir."/autorun/".$n->{plname}) { if (-e $dir."/autorun/".$plname) {
if (readlink($dir."/autorun/".$n->{plname}) eq "../".$n->{plname}) { if (readlink($dir."/autorun/".$plname) eq "../".$plname) {
if (unlink($dir."/autorun/".$n->{plname})) { if (unlink($dir."/autorun/".$plname)) {
print CLIENTCRAP "%R>>%n Autorun of ".$n->{sname}." disabled"; print CLIENTCRAP "%R>>%n Autorun of ".$sname." disabled";
} else { } else {
print CLIENTCRAP "%R>>%n Unable to delete link"; print CLIENTCRAP "%R>>%n Unable to delete link";
} }
} else { } else {
print CLIENTCRAP "%R>>%n ".$dir."/autorun/".$n->{plname}." is not a correct link"; print CLIENTCRAP "%R>>%n ".$dir."/autorun/".$plname." is not a correct link";
} }
} else { } else {
if (symlink("../".$n->{plname}, $dir."/autorun/".$n->{plname})) { if (symlink("../".$plname, $dir."/autorun/".$plname)) {
print CLIENTCRAP "%R>>%n Autorun of ".$n->{sname}." enabled"; print CLIENTCRAP "%R>>%n Autorun of ".$sname." enabled";
} else { } else {
print CLIENTCRAP "%R>>%n Unable to create autorun link"; print CLIENTCRAP "%R>>%n Unable to create autorun link";
} }
@ -1298,9 +1178,9 @@ sub cmd_help {
sub sig_command_script_load { sub sig_command_script_load {
my ($script, $server, $witem) = @_; my ($script, $server, $witem) = @_;
my $n = get_names($script); my ($sname, $plname, $pname, $xname) = get_names($script);
if ( $n->{stash} ) { if ( exists $Irssi::Script::{$pname} ) {
if (my $code = ("Irssi::Script::".$n->{pname})->can('pre_unload')) { if (my $code = "Irssi::Script::${pname}"->can('pre_unload')) {
print CLIENTCRAP "%R>>%n Triggering pre_unload function of $script..."; print CLIENTCRAP "%R>>%n Triggering pre_unload function of $script...";
$code->(); $code->();
} }

27
src/Makefile.am Normal file
View file

@ -0,0 +1,27 @@
if BUILD_TEXTUI
TEXTUI=fe-text
endif
if BUILD_IRSSIBOT
BOTUI=fe-none
endif
if BUILD_IRSSIFUZZER
FUZZERUI=fe-fuzz
endif
if HAVE_PERL
PERLDIR=perl
endif
if HAVE_OTR
OTRDIR=otr
endif
pkginc_srcdir=$(pkgincludedir)/src
pkginc_src_HEADERS = \
common.h
SUBDIRS = lib-config core irc fe-common $(PERLDIR) $(OTRDIR) $(TEXTUI) $(BOTUI) $(FUZZERUI)
EXTRA_DIST = meson.build

View file

@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
#define IRSSI_ABI_VERSION 58 #define IRSSI_ABI_VERSION 46
#define DEFAULT_SERVER_ADD_PORT 6667 #define DEFAULT_SERVER_ADD_PORT 6667
#define DEFAULT_SERVER_ADD_TLS_PORT 6697 #define DEFAULT_SERVER_ADD_TLS_PORT 6697
@ -37,8 +37,9 @@
#include <fcntl.h> #include <fcntl.h>
#include <glib.h> #include <glib.h>
#include <gmodule.h> #ifdef HAVE_GMODULE
#include <gio/gio.h> # include <gmodule.h>
#endif
typedef guint64 uoff_t; typedef guint64 uoff_t;
#define PRIuUOFF_T G_GUINT64_FORMAT #define PRIuUOFF_T G_GUINT64_FORMAT

122
src/core/Makefile.am Normal file
View file

@ -0,0 +1,122 @@
noinst_LIBRARIES = libcore.a
AM_CPPFLAGS = \
-I$(top_builddir) \
$(GLIB_CFLAGS) \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DMODULEDIR=\""$(libdir)/irssi/modules"\"
if USE_GREGEX
regex_impl=iregex-gregex.c
else
regex_impl=iregex-regexh.c
endif
libcore_a_SOURCES = \
args.c \
channels.c \
channels-setup.c \
commands.c \
chat-commands.c \
chat-protocols.c \
chatnets.c \
core.c \
expandos.c \
ignore.c \
levels.c \
line-split.c \
log.c \
log-away.c \
masks.c \
misc.c \
modules.c \
modules-load.c \
net-disconnect.c \
net-nonblock.c \
net-sendbuffer.c \
network.c \
network-openssl.c \
nicklist.c \
nickmatch-cache.c \
pidwait.c \
queries.c \
rawlog.c \
recode.c \
refstrings.c \
servers.c \
servers-reconnect.c \
servers-setup.c \
session.c \
settings.c \
signals.c \
special-vars.c \
utf8.c \
$(regex_impl) \
wcwidth.c \
wcwidth-wrapper.c \
tls.c \
write-buffer.c
if HAVE_CAPSICUM
libcore_a_SOURCES += \
capsicum.c
endif
structure_headers = \
channel-rec.h \
channel-setup-rec.h \
chatnet-rec.h \
query-rec.h \
server-rec.h \
server-setup-rec.h \
server-connect-rec.h \
window-item-rec.h
pkginc_coredir=$(pkgincludedir)/src/core
pkginc_core_HEADERS = \
args.h \
capsicum.h \
channels.h \
channels-setup.h \
commands.h \
chat-protocols.h \
chatnets.h \
core.h \
expandos.h \
ignore.h \
levels.h \
line-split.h \
log.h \
masks.h \
misc.h \
module.h \
modules.h \
modules-load.h \
net-disconnect.h \
net-nonblock.h \
net-sendbuffer.h \
network.h \
network-openssl.h \
nick-rec.h \
nicklist.h \
nickmatch-cache.h \
pidwait.h \
queries.h \
rawlog.h \
recode.h \
refstrings.h \
servers.h \
servers-reconnect.h \
servers-setup.h \
session.h \
settings.h \
signals.h \
special-vars.h \
utf8.h \
iregex.h \
window-item-def.h \
tls.h \
write-buffer.h \
$(structure_headers)
EXTRA_DIST = meson.build

View file

@ -227,7 +227,8 @@ void channels_setup_init(void)
setupchannels = NULL; setupchannels = NULL;
source_host_ok = FALSE; source_host_ok = FALSE;
signal_add("setup reread channels", (SIGNAL_FUNC) channels_read_config); signal_add("setup reread", (SIGNAL_FUNC) channels_read_config);
signal_add("irssi init read settings", (SIGNAL_FUNC) channels_read_config);
} }
void channels_setup_deinit(void) void channels_setup_deinit(void)
@ -235,5 +236,6 @@ void channels_setup_deinit(void)
while (setupchannels != NULL) while (setupchannels != NULL)
channel_setup_destroy(setupchannels->data); channel_setup_destroy(setupchannels->data);
signal_remove("setup reread channels", (SIGNAL_FUNC) channels_read_config); signal_remove("setup reread", (SIGNAL_FUNC) channels_read_config);
signal_remove("irssi init read settings", (SIGNAL_FUNC) channels_read_config);
} }

View file

@ -30,7 +30,6 @@
#include <irssi/src/core/servers-setup.h> #include <irssi/src/core/servers-setup.h>
#include <irssi/src/core/servers-reconnect.h> #include <irssi/src/core/servers-reconnect.h>
#include <irssi/src/core/channels.h> #include <irssi/src/core/channels.h>
#include <irssi/src/core/chatnets.h>
#include <irssi/src/core/queries.h> #include <irssi/src/core/queries.h>
#include <irssi/src/core/window-item-def.h> #include <irssi/src/core/window-item-def.h>
#include <irssi/src/core/rawlog.h> #include <irssi/src/core/rawlog.h>
@ -92,7 +91,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
return NULL; return NULL;
} }
if (strchr(addr, '/') != NULL && chatnet_find(addr) == NULL) if (strchr(addr, '/') != NULL)
conn->unix_socket = TRUE; conn->unix_socket = TRUE;
/* TLS options are handled in server_create_conn_opt ... -> server_setup_fill_optlist */ /* TLS options are handled in server_create_conn_opt ... -> server_setup_fill_optlist */
@ -101,11 +100,10 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
host = g_hash_table_lookup(optlist, "host"); host = g_hash_table_lookup(optlist, "host");
if (host != NULL && *host != '\0') { if (host != NULL && *host != '\0') {
IPADDR ip4 = { 0 }; IPADDR ip4, ip6;
IPADDR ip6 = { 0 };
if (net_gethostbyname_first_ips(host, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, &ip4, if (net_gethostbyname(host, &ip4, &ip6) == 0)
&ip6) == 0) server_connect_own_ip_save(conn, &ip4, &ip6);
server_connect_own_ip_save(conn, &ip4, &ip6);
} }
cmd_params_free(free_arg); cmd_params_free(free_arg);

View file

@ -47,7 +47,7 @@ int chat_protocol_lookup(const char *name)
g_return_val_if_fail(name != NULL, -1); g_return_val_if_fail(name != NULL, -1);
rec = chat_protocol_find(name); rec = chat_protocol_find(name);
return rec == NULL ? -1 : rec->not_initialized ? CHAT_PROTOCOL_NOT_INITIALIZED : rec->id; return rec == NULL ? -1 : rec->id;
} }
CHAT_PROTOCOL_REC *chat_protocol_find(const char *name) CHAT_PROTOCOL_REC *chat_protocol_find(const char *name)
@ -99,22 +99,6 @@ CHAT_PROTOCOL_REC *chat_protocol_find_net(GHashTable *optlist)
return NULL; return NULL;
} }
static void chat_protocol_destroy(CHAT_PROTOCOL_REC *rec)
{
g_return_if_fail(rec != NULL);
chat_protocols = g_slist_remove(chat_protocols, rec);
if (default_proto == rec) {
chat_protocol_set_default(chat_protocols == NULL ? NULL : chat_protocols->data);
}
signal_emit("chat protocol destroyed", 1, rec);
g_free(rec->name);
g_free(rec);
}
/* Register new chat protocol. */ /* Register new chat protocol. */
CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec) CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec)
{ {
@ -124,11 +108,7 @@ CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec)
g_return_val_if_fail(rec != NULL, NULL); g_return_val_if_fail(rec != NULL, NULL);
newrec = chat_protocol_find(rec->name); newrec = chat_protocol_find(rec->name);
if (newrec != NULL && newrec->not_initialized) { created = newrec == NULL;
chat_protocol_destroy(newrec);
newrec = NULL;
}
created = newrec == NULL;
if (newrec == NULL) { if (newrec == NULL) {
newrec = g_new0(CHAT_PROTOCOL_REC, 1); newrec = g_new0(CHAT_PROTOCOL_REC, 1);
chat_protocols = g_slist_append(chat_protocols, newrec); chat_protocols = g_slist_append(chat_protocols, newrec);
@ -151,6 +131,23 @@ CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec)
return newrec; return newrec;
} }
static void chat_protocol_destroy(CHAT_PROTOCOL_REC *rec)
{
g_return_if_fail(rec != NULL);
chat_protocols = g_slist_remove(chat_protocols, rec);
if (default_proto == rec) {
chat_protocol_set_default(chat_protocols == NULL ? NULL :
chat_protocols->data);
}
signal_emit("chat protocol destroyed", 1, rec);
g_free(rec->name);
g_free(rec);
}
/* Unregister chat protocol. */ /* Unregister chat protocol. */
void chat_protocol_unregister(const char *name) void chat_protocol_unregister(const char *name)
{ {
@ -194,6 +191,15 @@ static CHANNEL_SETUP_REC *create_channel_setup(void)
return g_new0(CHANNEL_SETUP_REC, 1); return g_new0(CHANNEL_SETUP_REC, 1);
} }
static SERVER_CONNECT_REC *create_server_connect(void)
{
return g_new0(SERVER_CONNECT_REC, 1);
}
static void destroy_server_connect(SERVER_CONNECT_REC *conn)
{
}
/* Return "unknown chat protocol" record. Used when protocol name is /* Return "unknown chat protocol" record. Used when protocol name is
specified but it isn't registered yet. */ specified but it isn't registered yet. */
CHAT_PROTOCOL_REC *chat_protocol_get_unknown(const char *name) CHAT_PROTOCOL_REC *chat_protocol_get_unknown(const char *name)
@ -212,10 +218,8 @@ CHAT_PROTOCOL_REC *chat_protocol_get_unknown(const char *name)
rec->create_chatnet = create_chatnet; rec->create_chatnet = create_chatnet;
rec->create_server_setup = create_server_setup; rec->create_server_setup = create_server_setup;
rec->create_channel_setup = create_channel_setup; rec->create_channel_setup = create_channel_setup;
/*
rec->create_server_connect = create_server_connect; rec->create_server_connect = create_server_connect;
rec->destroy_server_connect = destroy_server_connect; rec->destroy_server_connect = destroy_server_connect;
*/
newrec = chat_protocol_register(rec); newrec = chat_protocol_register(rec);
g_free(rec); g_free(rec);

View file

@ -35,8 +35,6 @@ void *chat_protocol_check_cast(void *object, int type_pos, const char *id);
((object) == NULL ? chat_protocol_get_default() : \ ((object) == NULL ? chat_protocol_get_default() : \
chat_protocol_find_id((object)->chat_type)) chat_protocol_find_id((object)->chat_type))
#define CHAT_PROTOCOL_NOT_INITIALIZED -2
/* Register new chat protocol. */ /* Register new chat protocol. */
CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec); CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec);

View file

@ -24,13 +24,12 @@
#include <irssi/src/core/special-vars.h> #include <irssi/src/core/special-vars.h>
#include <irssi/src/lib-config/iconfig.h> #include <irssi/src/lib-config/iconfig.h>
#include <irssi/src/core/settings.h> #include <irssi/src/core/settings.h>
#include <irssi/src/core/misc.h>
#include <irssi/src/core/chat-protocols.h> #include <irssi/src/core/chat-protocols.h>
#include <irssi/src/core/chatnets.h> #include <irssi/src/core/chatnets.h>
#include <irssi/src/core/servers.h> #include <irssi/src/core/servers.h>
GSList *chatnets, *chatnets_unavailable; /* list of available chat networks */ GSList *chatnets; /* list of available chat networks */
static void chatnet_config_save(CHATNET_REC *chatnet) static void chatnet_config_save(CHATNET_REC *chatnet)
{ {
@ -61,9 +60,8 @@ static void chatnet_config_remove(CHATNET_REC *chatnet)
void chatnet_create(CHATNET_REC *chatnet) void chatnet_create(CHATNET_REC *chatnet)
{ {
g_return_if_fail(chatnet != NULL); g_return_if_fail(chatnet != NULL);
g_return_if_fail(!CHAT_PROTOCOL(chatnet)->not_initialized);
chatnet->type = module_get_uniq_id("CHATNET", 0); chatnet->type = module_get_uniq_id("CHATNET", 0);
if (g_slist_find(chatnets, chatnet) == NULL) if (g_slist_find(chatnets, chatnet) == NULL)
chatnets = g_slist_append(chatnets, chatnet); chatnets = g_slist_append(chatnets, chatnet);
@ -114,21 +112,6 @@ CHATNET_REC *chatnet_find(const char *name)
return NULL; return NULL;
} }
gboolean chatnet_find_unavailable(const char *name)
{
CHAT_PROTOCOL_REC *proto;
if (i_slist_find_icase_string(chatnets_unavailable, name) != NULL)
return TRUE;
proto = CHAT_PROTOCOL(chatnet_find(name));
if (proto == NULL || proto->not_initialized)
return TRUE;
return FALSE;
}
static void sig_connected(SERVER_REC *server) static void sig_connected(SERVER_REC *server)
{ {
CHATNET_REC *rec; CHATNET_REC *rec;
@ -153,23 +136,15 @@ static void chatnet_read(CONFIG_NODE *node)
return; return;
type = config_node_get_str(node, "type", NULL); type = config_node_get_str(node, "type", NULL);
if (type == NULL) { proto = type == NULL ? NULL : chat_protocol_find(type);
proto = chat_protocol_get_default();
} else {
proto = chat_protocol_find(type);
}
if (proto == NULL) { if (proto == NULL) {
/* protocol not loaded */ proto = type == NULL ? chat_protocol_get_default() :
if (i_slist_find_icase_string(chatnets_unavailable, node->key) == NULL) chat_protocol_get_unknown(type);
chatnets_unavailable =
g_slist_append(chatnets_unavailable, g_strdup(node->key));
return;
} else if (type == NULL) {
iconfig_node_set_str(node, "type", proto->name);
} }
if (type == NULL)
iconfig_node_set_str(node, "type", proto->name);
rec = proto->create_chatnet(); rec = proto->create_chatnet();
rec->type = module_get_uniq_id("CHATNET", 0); rec->type = module_get_uniq_id("CHATNET", 0);
rec->chat_type = proto->id; rec->chat_type = proto->id;
@ -192,12 +167,6 @@ static void read_chatnets(void)
while (chatnets != NULL) while (chatnets != NULL)
chatnet_destroy(chatnets->data); chatnet_destroy(chatnets->data);
while (chatnets_unavailable != NULL) {
char *name = chatnets_unavailable->data;
chatnets_unavailable = g_slist_remove(chatnets_unavailable, name);
g_free(name);
}
node = iconfig_node_traverse("chatnets", FALSE); node = iconfig_node_traverse("chatnets", FALSE);
if (node != NULL) { if (node != NULL) {
tmp = config_node_first(node->value); tmp = config_node_first(node->value);
@ -211,7 +180,8 @@ void chatnets_init(void)
chatnets = NULL; chatnets = NULL;
signal_add_first("event connected", (SIGNAL_FUNC) sig_connected); signal_add_first("event connected", (SIGNAL_FUNC) sig_connected);
signal_add("setup reread chatnets", (SIGNAL_FUNC) read_chatnets); signal_add("setup reread", (SIGNAL_FUNC) read_chatnets);
signal_add_first("irssi init read settings", (SIGNAL_FUNC) read_chatnets);
} }
void chatnets_deinit(void) void chatnets_deinit(void)
@ -219,5 +189,6 @@ void chatnets_deinit(void)
module_uniq_destroy("CHATNET"); module_uniq_destroy("CHATNET");
signal_remove("event connected", (SIGNAL_FUNC) sig_connected); signal_remove("event connected", (SIGNAL_FUNC) sig_connected);
signal_remove("setup reread chatnets", (SIGNAL_FUNC) read_chatnets); signal_remove("setup reread", (SIGNAL_FUNC) read_chatnets);
signal_remove("irssi init read settings", (SIGNAL_FUNC) read_chatnets);
} }

View file

@ -25,8 +25,6 @@ void chatnet_destroy(CHATNET_REC *chatnet);
/* Find the chat network by name */ /* Find the chat network by name */
CHATNET_REC *chatnet_find(const char *name); CHATNET_REC *chatnet_find(const char *name);
/* Check if this chatnet is unavailable because the protocol is not loaded */
gboolean chatnet_find_unavailable(const char *name);
void chatnets_init(void); void chatnets_init(void);
void chatnets_deinit(void); void chatnets_deinit(void);

View file

@ -68,7 +68,6 @@ void wcwidth_wrapper_deinit(void);
int irssi_gui; int irssi_gui;
int irssi_init_finished; int irssi_init_finished;
int sighup_received; int sighup_received;
int sigterm_received;
time_t client_start_time; time_t client_start_time;
static char *irssi_dir, *irssi_config_file; static char *irssi_dir, *irssi_config_file;
@ -90,11 +89,6 @@ static void sig_hup(int signo)
sighup_received = TRUE; sighup_received = TRUE;
} }
static void sig_term(int signo)
{
sigterm_received = TRUE;
}
static void read_settings(void) static void read_settings(void)
{ {
static int signals[] = { static int signals[] = {
@ -119,15 +113,8 @@ static void read_settings(void)
sigaction(SIGHUP, &act, NULL); sigaction(SIGHUP, &act, NULL);
for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) { for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) {
if (find_substr(ignores, signames[n])) { act.sa_handler = find_substr(ignores, signames[n]) ?
act.sa_handler = SIG_IGN; SIG_IGN : SIG_DFL;
} else {
/* set default handlers */
if (signals[n] == SIGTERM)
act.sa_handler = sig_term;
else
act.sa_handler = SIG_DFL;
}
sigaction(signals[n], &act, NULL); sigaction(signals[n], &act, NULL);
} }
@ -236,13 +223,6 @@ static void sig_irssi_init_finished(void)
irssi_init_finished = TRUE; irssi_init_finished = TRUE;
} }
static void reread_setup(void)
{
signal_emit("setup reread chatnets", 0);
signal_emit("setup reread servers", 0);
signal_emit("setup reread channels", 0);
}
void core_init(void) void core_init(void)
{ {
dialog_type_queue = NULL; dialog_type_queue = NULL;
@ -289,16 +269,13 @@ void core_init(void)
settings_add_str("misc", "ignore_signals", ""); settings_add_str("misc", "ignore_signals", "");
settings_add_bool("misc", "override_coredump_limit", FALSE); settings_add_bool("misc", "override_coredump_limit", FALSE);
settings_add_bool("misc", "quit_on_hup", FALSE); settings_add_bool("misc", "quit_on_hup", FALSE);
settings_add_str("misc", "autoload_modules", "irc dcc flood notifylist perl otr"); settings_add_str("misc", "autoload_modules", "perl otr");
#ifdef HAVE_SYS_RESOURCE_H #ifdef HAVE_SYS_RESOURCE_H
getrlimit(RLIMIT_CORE, &orig_core_rlimit); getrlimit(RLIMIT_CORE, &orig_core_rlimit);
#endif #endif
read_settings(); read_settings();
signal_add("setup changed", (SIGNAL_FUNC) read_settings); signal_add("setup changed", (SIGNAL_FUNC) read_settings);
signal_add("setup reread", (SIGNAL_FUNC) reread_setup);
signal_add("irssi init read settings", (SIGNAL_FUNC) reread_setup);
signal_add_last("chat protocol created", (SIGNAL_FUNC) reread_setup);
signal_add("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished); signal_add("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished);
settings_check(); settings_check();
@ -311,9 +288,6 @@ void core_deinit(void)
module_uniq_destroy("WINDOW ITEM TYPE"); module_uniq_destroy("WINDOW ITEM TYPE");
signal_remove("setup changed", (SIGNAL_FUNC) read_settings); signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
signal_remove("setup reread", (SIGNAL_FUNC) reread_setup);
signal_remove("irssi init read settings", (SIGNAL_FUNC) reread_setup);
signal_remove("chat protocol created", (SIGNAL_FUNC) reread_setup);
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished); signal_remove("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished);
wcwidth_wrapper_deinit(); wcwidth_wrapper_deinit();

View file

@ -14,7 +14,6 @@
extern int irssi_gui; extern int irssi_gui;
extern int irssi_init_finished; /* TRUE after "irssi init finished" signal is sent */ extern int irssi_init_finished; /* TRUE after "irssi init finished" signal is sent */
extern int sighup_received; /* TRUE after received SIGHUP. */ extern int sighup_received; /* TRUE after received SIGHUP. */
extern int sigterm_received; /* TRUE after received SIGTERM. */
extern time_t client_start_time; extern time_t client_start_time;
void core_preinit(const char *path); void core_preinit(const char *path);

99
src/core/iregex-regexh.c Normal file
View file

@ -0,0 +1,99 @@
#include <irssi/src/core/iregex.h>
Regex *
i_regex_new (const gchar *pattern,
GRegexCompileFlags compile_options,
GRegexMatchFlags match_options,
GError **error)
{
Regex *regex;
char *errbuf;
int cflags;
int errcode, errbuf_len;
regex = g_new0(Regex, 1);
cflags = REG_EXTENDED;
if (compile_options & G_REGEX_CASELESS)
cflags |= REG_ICASE;
if (compile_options & G_REGEX_MULTILINE)
cflags |= REG_NEWLINE;
if (match_options & G_REGEX_MATCH_NOTBOL)
cflags |= REG_NOTBOL;
if (match_options & G_REGEX_MATCH_NOTEOL)
cflags |= REG_NOTEOL;
errcode = regcomp(regex, pattern, cflags);
if (errcode != 0) {
errbuf_len = regerror(errcode, regex, 0, 0);
errbuf = g_malloc(errbuf_len);
regerror(errcode, regex, errbuf, errbuf_len);
g_set_error(error, G_REGEX_ERROR, errcode, "%s", errbuf);
g_free(errbuf);
g_free(regex);
return NULL;
} else {
return regex;
}
}
void
i_regex_unref (Regex *regex)
{
regfree(regex);
g_free(regex);
}
gboolean
i_regex_match (const Regex *regex,
const gchar *string,
GRegexMatchFlags match_options,
MatchInfo **match_info)
{
int groups;
int eflags;
g_return_val_if_fail(regex != NULL, FALSE);
if (match_info != NULL) {
groups = 1 + regex->re_nsub;
*match_info = g_new0(MatchInfo, groups);
} else {
groups = 0;
}
eflags = 0;
if (match_options & G_REGEX_MATCH_NOTBOL)
eflags |= REG_NOTBOL;
if (match_options & G_REGEX_MATCH_NOTEOL)
eflags |= REG_NOTEOL;
return regexec(regex, string, groups, groups ? *match_info : NULL, eflags) == 0;
}
gboolean
i_match_info_fetch_pos (const MatchInfo *match_info,
gint match_num,
gint *start_pos,
gint *end_pos)
{
if (start_pos != NULL)
*start_pos = match_info[match_num].rm_so;
if (end_pos != NULL)
*end_pos = match_info[match_num].rm_eo;
return TRUE;
}
gboolean
i_match_info_matches (const MatchInfo *match_info)
{
g_return_val_if_fail(match_info != NULL, FALSE);
return match_info[0].rm_so != -1;
}
void
i_match_info_free (MatchInfo *match_info)
{
g_free(match_info);
}

View file

@ -3,10 +3,20 @@
#include <irssi/src/common.h> #include <irssi/src/common.h>
#ifdef USE_GREGEX
#include <glib.h> #include <glib.h>
typedef GRegex Regex; typedef GRegex Regex;
typedef struct _MatchInfo MatchInfo; typedef struct _MatchInfo MatchInfo;
#else
#include <regex.h>
typedef regex_t Regex;
typedef regmatch_t MatchInfo;
#endif
gboolean gboolean
i_match_info_matches (const MatchInfo *match_info); i_match_info_matches (const MatchInfo *match_info);

View file

@ -19,17 +19,14 @@
*/ */
#include "module.h" #include "module.h"
#include <irssi/src/core/misc.h>
#include <irssi/src/core/levels.h> #include <irssi/src/core/levels.h>
/* the order of these levels must match the bits in levels.h */ /* the order of these levels must match the bits in levels.h */
static const char *levels[] = { static const char *levels[] = {
/* clang-format off */
"CRAP", "CRAP",
"MSGS", "MSGS",
"PUBLICS", "PUBLICS",
"NOTICES", "NOTICES",
"PUBNOTICES",
"SNOTES", "SNOTES",
"CTCPS", "CTCPS",
"ACTIONS", "ACTIONS",
@ -49,7 +46,6 @@ static const char *levels[] = {
"CLIENTERRORS", "CLIENTERRORS",
"HILIGHTS", "HILIGHTS",
NULL NULL
/* clang-format on */
}; };
int level_get(const char *level) int level_get(const char *level)
@ -170,7 +166,8 @@ char *bits2level(int bits)
if (str->len > 0) if (str->len > 0)
g_string_truncate(str, str->len-1); g_string_truncate(str, str->len-1);
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }

View file

@ -13,27 +13,26 @@ enum {
MSGLEVEL_MSGS = 0x0000002, MSGLEVEL_MSGS = 0x0000002,
MSGLEVEL_PUBLIC = 0x0000004, MSGLEVEL_PUBLIC = 0x0000004,
MSGLEVEL_NOTICES = 0x0000008, MSGLEVEL_NOTICES = 0x0000008,
MSGLEVEL_PUBNOTICES = 0x0000010, MSGLEVEL_SNOTES = 0x0000010,
MSGLEVEL_SNOTES = 0x0000020, MSGLEVEL_CTCPS = 0x0000020,
MSGLEVEL_CTCPS = 0x0000040, MSGLEVEL_ACTIONS = 0x0000040,
MSGLEVEL_ACTIONS = 0x0000080, MSGLEVEL_JOINS = 0x0000080,
MSGLEVEL_JOINS = 0x0000100, MSGLEVEL_PARTS = 0x0000100,
MSGLEVEL_PARTS = 0x0000200, MSGLEVEL_QUITS = 0x0000200,
MSGLEVEL_QUITS = 0x0000400, MSGLEVEL_KICKS = 0x0000400,
MSGLEVEL_KICKS = 0x0000800, MSGLEVEL_MODES = 0x0000800,
MSGLEVEL_MODES = 0x0001000, MSGLEVEL_TOPICS = 0x0001000,
MSGLEVEL_TOPICS = 0x0002000, MSGLEVEL_WALLOPS = 0x0002000,
MSGLEVEL_WALLOPS = 0x0004000, MSGLEVEL_INVITES = 0x0004000,
MSGLEVEL_INVITES = 0x0008000, MSGLEVEL_NICKS = 0x0008000,
MSGLEVEL_NICKS = 0x0010000, MSGLEVEL_DCC = 0x0010000,
MSGLEVEL_DCC = 0x0020000, MSGLEVEL_DCCMSGS = 0x0020000,
MSGLEVEL_DCCMSGS = 0x0040000, MSGLEVEL_CLIENTNOTICE = 0x0040000,
MSGLEVEL_CLIENTNOTICE = 0x0080000, MSGLEVEL_CLIENTCRAP = 0x0080000,
MSGLEVEL_CLIENTCRAP = 0x0100000, MSGLEVEL_CLIENTERROR = 0x0100000,
MSGLEVEL_CLIENTERROR = 0x0200000, MSGLEVEL_HILIGHT = 0x0200000,
MSGLEVEL_HILIGHT = 0x0400000,
MSGLEVEL_ALL = 0x07fffff, MSGLEVEL_ALL = 0x03fffff,
MSGLEVEL_NOHILIGHT = 0x1000000, /* Don't highlight this message */ MSGLEVEL_NOHILIGHT = 0x1000000, /* Don't highlight this message */
MSGLEVEL_NO_ACT = 0x2000000, /* Don't trigger channel activity */ MSGLEVEL_NO_ACT = 0x2000000, /* Don't trigger channel activity */

View file

@ -1,13 +1,18 @@
# this file is part of irssi # this file is part of irssi
if want_gregex
regex_impl = files('iregex-gregex.c')
else
regex_impl = files('iregex-regexh.c')
endif
if have_capsicum if have_capsicum
core_capsicum_source = files('capsicum.c') core_capsicum_source = files('capsicum.c')
else else
core_capsicum_source = [ ] core_capsicum_source = []
endif endif
libcore_a = static_library( libcore_a = static_library('core',
'core',
files( files(
'args.c', 'args.c',
'channels-setup.c', 'channels-setup.c',
@ -19,7 +24,6 @@ libcore_a = static_library(
'core.c', 'core.c',
'expandos.c', 'expandos.c',
'ignore.c', 'ignore.c',
'iregex-gregex.c',
'levels.c', 'levels.c',
'line-split.c', 'line-split.c',
'log-away.c', 'log-away.c',
@ -54,6 +58,7 @@ libcore_a = static_library(
'write-buffer.c', 'write-buffer.c',
) )
+ core_capsicum_source + core_capsicum_source
+ regex_impl
+ [ + [
default_config_h, default_config_h,
irssi_version_h, irssi_version_h,
@ -64,8 +69,7 @@ libcore_a = static_library(
def_moduledir, def_moduledir,
def_sysconfdir, def_sysconfdir,
], ],
dependencies : dep, dependencies : dep)
)
install_headers( install_headers(
files( files(
@ -124,5 +128,4 @@ install_headers(
'window-item-def.h', 'window-item-def.h',
'write-buffer.h', 'write-buffer.h',
), ),
subdir : incdir / 'src' / 'core', subdir : incdir / 'src' / 'core')
)

View file

@ -135,15 +135,6 @@ GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *defaul
} }
#endif #endif
#if GLIB_CHECK_VERSION(2, 76, 0)
/* nothing */
#else
gchar *g_string_free_and_steal(GString *string)
{
return g_string_free(string, FALSE);
}
#endif
int find_substr(const char *list, const char *item) int find_substr(const char *list, const char *item)
{ {
const char *ptr; const char *ptr;
@ -270,7 +261,8 @@ char *gslistptr_to_string(GSList *list, int offset, const char *delimiter)
list = list->next; list = list->next;
} }
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -288,7 +280,8 @@ char *i_slist_to_string(GSList *list, const char *delimiter)
list = list->next; list = list->next;
} }
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }

View file

@ -26,12 +26,6 @@ long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2) G_GNUC_DEPRECATE
GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *default_tz); GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *default_tz);
#endif #endif
#if GLIB_CHECK_VERSION(2, 76, 0)
/* nothing */
#else
gchar *g_string_free_and_steal(GString *string);
#endif
GSList *i_slist_find_string(GSList *list, const char *key); GSList *i_slist_find_string(GSList *list, const char *key);
GSList *i_slist_find_icase_string(GSList *list, const char *key); GSList *i_slist_find_icase_string(GSList *list, const char *key);
GList *i_list_find_string(GList *list, const char *key); GList *i_list_find_string(GList *list, const char *key);

View file

@ -27,6 +27,8 @@
#include <irssi/src/core/commands.h> #include <irssi/src/core/commands.h>
#include <irssi/src/core/misc.h> #include <irssi/src/core/misc.h>
#ifdef HAVE_GMODULE
/* Returns the module name without path, "lib" prefix or ".so" suffix */ /* Returns the module name without path, "lib" prefix or ".so" suffix */
static char *module_get_name(const char *path, int *start, int *end) static char *module_get_name(const char *path, int *start, int *end)
{ {
@ -42,7 +44,7 @@ static char *module_get_name(const char *path, int *start, int *end)
if (name == NULL) if (name == NULL)
name = path; name = path;
if (strncmp(name, "lib", 3) == 0 || strncmp(name, "cyg", 3) == 0) if (strncmp(name, "lib", 3) == 0)
name += 3; name += 3;
module_name = g_strdup(name); module_name = g_strdup(name);
@ -102,41 +104,10 @@ static char *module_get_sub(const char *name, const char *root)
return g_strdup(name); return g_strdup(name);
} }
static GModule *module_open(const char *name) static GModule *module_open(const char *name, int *found)
{ {
GModule *module;
#if GLIB_CHECK_VERSION(2, 75, 0)
/* in this version of glib, g_module_open knows how to construct system-dependent module
file names, and g_module_build_path is deprecated. */
char *path;
if (g_path_is_absolute(name) || *name == '~' ||
(*name == '.' && name[1] == G_DIR_SEPARATOR))
path = g_strdup(name);
else {
/* first try from home dir */
path = g_strdup_printf("%s/modules/%s", get_irssi_dir(), name);
module = g_module_open(path, (GModuleFlags) 0);
g_free(path);
if (module != NULL) {
return module;
}
/* module not found from home dir, try global module dir */
path = g_strdup_printf("%s/%s", MODULEDIR, name);
}
module = g_module_open(path, (GModuleFlags) 0);
g_free(path);
return module;
#else /* GLib < 2.75.0 */
/* in this version of glib, we build the module path with g_module_build_path.
unfortunately, this is broken on Darwin when compiled with meson. */
struct stat statbuf; struct stat statbuf;
GModule *module;
char *path, *str; char *path, *str;
if (g_path_is_absolute(name) || *name == '~' || if (g_path_is_absolute(name) || *name == '~' ||
@ -151,6 +122,7 @@ static GModule *module_open(const char *name)
if (stat(path, &statbuf) == 0) { if (stat(path, &statbuf) == 0) {
module = g_module_open(path, (GModuleFlags) 0); module = g_module_open(path, (GModuleFlags) 0);
g_free(path); g_free(path);
*found = TRUE;
return module; return module;
} }
@ -159,11 +131,10 @@ static GModule *module_open(const char *name)
path = g_module_build_path(MODULEDIR, name); path = g_module_build_path(MODULEDIR, name);
} }
*found = stat(path, &statbuf) == 0;
module = g_module_open(path, (GModuleFlags) 0); module = g_module_open(path, (GModuleFlags) 0);
g_free(path); g_free(path);
return module; return module;
#endif
} }
static char *module_get_func(const char *rootmodule, const char *submodule, static char *module_get_func(const char *rootmodule, const char *submodule,
@ -182,7 +153,8 @@ static char *module_get_func(const char *rootmodule, const char *submodule,
signal_emit("module error", 4, GINT_TO_POINTER(error), text, \ signal_emit("module error", 4, GINT_TO_POINTER(error), text, \
rootmodule, submodule) rootmodule, submodule)
/* Returns 1 if ok, 0 if not */ /* Returns 1 if ok, 0 if error in module and
-1 if module wasn't found */
static int module_load_name(const char *path, const char *rootmodule, static int module_load_name(const char *path, const char *rootmodule,
const char *submodule, int silent) const char *submodule, int silent)
{ {
@ -196,15 +168,15 @@ static int module_load_name(const char *path, const char *rootmodule,
gpointer value1, value2 = NULL; gpointer value1, value2 = NULL;
char *versionfunc, *initfunc, *deinitfunc; char *versionfunc, *initfunc, *deinitfunc;
int module_abi_version = 0; int module_abi_version = 0;
int valid; int found;
gmodule = module_open(path); gmodule = module_open(path, &found);
if (gmodule == NULL) { if (gmodule == NULL) {
if (!silent) { if (!silent || found) {
module_error(MODULE_ERROR_LOAD, g_module_error(), module_error(MODULE_ERROR_LOAD, g_module_error(),
rootmodule, submodule); rootmodule, submodule);
} }
return 0; return found ? 0 : -1;
} }
/* get the module's irssi abi version and bail out on mismatch */ /* get the module's irssi abi version and bail out on mismatch */
@ -231,12 +203,12 @@ static int module_load_name(const char *path, const char *rootmodule,
/* get the module's init() and deinit() functions */ /* get the module's init() and deinit() functions */
initfunc = module_get_func(rootmodule, submodule, "init"); initfunc = module_get_func(rootmodule, submodule, "init");
deinitfunc = module_get_func(rootmodule, submodule, "deinit"); deinitfunc = module_get_func(rootmodule, submodule, "deinit");
valid = g_module_symbol(gmodule, initfunc, &value1) && found = g_module_symbol(gmodule, initfunc, &value1) &&
g_module_symbol(gmodule, deinitfunc, &value2); g_module_symbol(gmodule, deinitfunc, &value2);
g_free(initfunc); g_free(initfunc);
g_free(deinitfunc); g_free(deinitfunc);
if (!valid) { if (!found) {
module_error(MODULE_ERROR_INVALID, NULL, module_error(MODULE_ERROR_INVALID, NULL,
rootmodule, submodule); rootmodule, submodule);
g_module_close(gmodule); g_module_close(gmodule);
@ -340,7 +312,7 @@ static int module_load_full(const char *path, const char *rootmodule,
/* check if the given module exists.. */ /* check if the given module exists.. */
try_prefixes = g_strcmp0(rootmodule, submodule) == 0; try_prefixes = g_strcmp0(rootmodule, submodule) == 0;
status = module_load_name(path, rootmodule, submodule, try_prefixes); status = module_load_name(path, rootmodule, submodule, try_prefixes);
if (status <= 0 && try_prefixes) { if (status == -1 && try_prefixes) {
/* nope, try loading the module_core, /* nope, try loading the module_core,
fe_module, etc. */ fe_module, etc. */
status = module_load_prefixes(path, rootmodule, status = module_load_prefixes(path, rootmodule,
@ -423,6 +395,15 @@ static void module_file_deinit_gmodule(MODULE_FILE_REC *file)
g_module_close(file->gmodule); g_module_close(file->gmodule);
} }
#else /* !HAVE_GMODULE - modules are not supported */
int module_load(const char *path, char **prefixes)
{
return FALSE;
}
#endif
void module_file_unload(MODULE_FILE_REC *file) void module_file_unload(MODULE_FILE_REC *file)
{ {
MODULE_REC *root; MODULE_REC *root;
@ -433,8 +414,10 @@ void module_file_unload(MODULE_FILE_REC *file)
if (file->initialized) if (file->initialized)
signal_emit("module unloaded", 2, file->root, file); signal_emit("module unloaded", 2, file->root, file);
#ifdef HAVE_GMODULE
if (file->gmodule != NULL) if (file->gmodule != NULL)
module_file_deinit_gmodule(file); module_file_deinit_gmodule(file);
#endif
g_free(file->name); g_free(file->name);
g_free(file->defined_module_name); g_free(file->defined_module_name);

View file

@ -16,7 +16,13 @@
#define MODULE_DATA(rec) \ #define MODULE_DATA(rec) \
g_hash_table_lookup((rec)->module_data, MODULE_NAME) g_hash_table_lookup((rec)->module_data, MODULE_NAME)
#define MODULE_IS_STATIC(rec) ((rec)->gmodule == NULL)
#ifdef HAVE_GMODULE
# define MODULE_IS_STATIC(rec) \
((rec)->gmodule == NULL)
#else
# define MODULE_IS_STATIC(rec) TRUE
#endif
#define MODULE_ABICHECK(fn_modulename) \ #define MODULE_ABICHECK(fn_modulename) \
void fn_modulename ## _abicheck(int *version) \ void fn_modulename ## _abicheck(int *version) \
@ -39,7 +45,9 @@ typedef struct {
char *defined_module_name; char *defined_module_name;
void (*module_deinit) (void); void (*module_deinit) (void);
#ifdef HAVE_GMODULE
GModule *gmodule; /* static, if NULL */ GModule *gmodule; /* static, if NULL */
#endif
unsigned int initialized:1; unsigned int initialized:1;
} MODULE_FILE_REC; } MODULE_FILE_REC;

View file

@ -21,8 +21,6 @@
#include "module.h" #include "module.h"
#include <irssi/src/core/network.h> #include <irssi/src/core/network.h>
#include <sys/select.h>
/* when quitting, wait for max. 5 seconds before forcing to close the socket */ /* when quitting, wait for max. 5 seconds before forcing to close the socket */
#define MAX_QUIT_CLOSE_WAIT 5 #define MAX_QUIT_CLOSE_WAIT 5

View file

@ -22,94 +22,86 @@
#include <signal.h> #include <signal.h>
#include <irssi/src/core/network.h> #include <irssi/src/core/pidwait.h>
#include <irssi/src/core/net-nonblock.h> #include <irssi/src/core/net-nonblock.h>
typedef struct { /* nonblocking gethostbyname(), ip (IPADDR) + error (int, 0 = not error) is
GResolverNameLookupFlags flags; written to pipe when found PID of the resolver child is returned */
NetGethostbynameContinuationFunc cont; int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int reverse_lookup)
void *cont_data;
} NET_GETHOSTBYNAME_CALLBACK_DATA;
static void net_gethostbyname_callback(GResolver *resolver, GAsyncResult *result,
NET_GETHOSTBYNAME_CALLBACK_DATA *data)
{ {
/* GList<GInetAddress> */ RESOLVED_IP_REC rec;
GList *ailist; const char *errorstr;
GError *error; int pid;
RESOLVED_IP_REC *iprec;
error = NULL; (void) reverse_lookup; /* Kept for API backward compatibility */
#if GLIB_CHECK_VERSION(2, 59, 0)
ailist = g_resolver_lookup_by_name_with_flags_finish(resolver, result, &error);
#else
/* compatibility code for old GLib */
ailist = g_resolver_lookup_by_name_finish(resolver, result, &error);
if (error == NULL && data->flags) {
GList *ll, *lll;
for (ll = ailist; ll != NULL; ll = lll) {
GInetAddress *address;
GSocketFamily family;
address = G_INET_ADDRESS(ll->data);
family = g_inet_address_get_family(address);
lll = ll->next;
if ((data->flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY &&
family == G_SOCKET_FAMILY_IPV6) ||
(data->flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY &&
family == G_SOCKET_FAMILY_IPV4)) {
g_object_unref(address);
ailist = g_list_delete_link(ailist, ll);
}
}
if (ailist == NULL) {
g_set_error(&error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
data->flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY ?
"IPv4 address not found for host" :
"IPv6 address not found for host");
}
}
#endif
iprec = g_new0(RESOLVED_IP_REC, 1);
if (error != NULL) {
iprec->error = error;
} else {
iprec->ailist = ailist;
}
g_object_unref(resolver);
resolved_ip_ref(iprec);
data->cont(iprec, data->cont_data);
g_free(data);
}
/* nonblocking gethostbyname() */
GCancellable *net_gethostbyname_nonblock(const char *addr, GResolverNameLookupFlags flags,
NetGethostbynameContinuationFunc cont, void *cont_data)
{
GResolver *resolver;
GCancellable *cancellable;
NET_GETHOSTBYNAME_CALLBACK_DATA *data;
g_return_val_if_fail(addr != NULL, FALSE); g_return_val_if_fail(addr != NULL, FALSE);
resolver = g_resolver_get_default(); pid = fork();
cancellable = g_cancellable_new(); if (pid > 0) {
data = g_new0(NET_GETHOSTBYNAME_CALLBACK_DATA, 1); /* parent */
data->flags = flags; pidwait_add(pid);
data->cont = cont; return pid;
data->cont_data = cont_data; }
#if GLIB_CHECK_VERSION(2, 59, 0)
g_resolver_lookup_by_name_with_flags_async(resolver, addr, flags, cancellable, if (pid != 0) {
(GAsyncReadyCallback) net_gethostbyname_callback, /* failed! */
data); g_warning("net_connect_thread(): fork() failed! "
#else "Using blocking resolving");
/* compatibility code for old GLib */ }
g_resolver_lookup_by_name_async(resolver, addr, cancellable,
(GAsyncReadyCallback) net_gethostbyname_callback, data); /* child */
#endif srand(time(NULL));
return cancellable;
memset(&rec, 0, sizeof(rec));
rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6);
if (rec.error == 0) {
errorstr = NULL;
} else {
errorstr = net_gethosterror(rec.error);
rec.errlen = errorstr == NULL ? 0 : strlen(errorstr)+1;
}
i_io_channel_write_block(pipe, &rec, sizeof(rec));
if (rec.errlen != 0)
i_io_channel_write_block(pipe, (void *) errorstr, rec.errlen);
if (pid == 0)
_exit(99);
/* we used blocking lookup */
return 0;
}
/* get the resolved IP address */
int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
{
rec->error = -1;
rec->errorstr = NULL;
fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK);
/* get ip+error */
if (i_io_channel_read_block(pipe, rec, sizeof(*rec)) == -1) {
rec->errorstr = g_strdup_printf("Host name lookup: %s",
g_strerror(errno));
return -1;
}
if (rec->error) {
/* read error string, if we can't read everything for some
reason, just ignore it. */
rec->errorstr = g_malloc0(rec->errlen+1);
i_io_channel_read_block(pipe, rec->errorstr, rec->errlen);
}
return 0;
}
/* Kill the resolver child */
void net_disconnect_nonblock(int pid)
{
g_return_if_fail(pid > 0);
kill(pid, SIGKILL);
} }

View file

@ -3,10 +3,20 @@
#include <irssi/src/core/network.h> #include <irssi/src/core/network.h>
typedef void (*NetGethostbynameContinuationFunc)(RESOLVED_IP_REC *, void *); typedef struct {
IPADDR ip4, ip6; /* resolved ip addresses */
int error; /* error, 0 = no error, -1 = error: */
int errlen; /* error text length */
char *errorstr; /* error string - dynamically allocated, you'll
need to free() it yourself unless it's NULL */
} RESOLVED_IP_REC;
/* nonblocking gethostbyname(), Cancellable of the resolver child is returned. */ /* nonblocking gethostbyname(), PID of the resolver child is returned. */
GCancellable *net_gethostbyname_nonblock(const char *addr, GResolverNameLookupFlags flags, int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int reverse_lookup);
NetGethostbynameContinuationFunc cont, void *cont_data); /* get the resolved IP address. returns -1 if some error occurred with read() */
int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec);
/* Kill the resolver child */
void net_disconnect_nonblock(int pid);
#endif #endif

View file

@ -28,7 +28,6 @@
#include <irssi/src/core/tls.h> #include <irssi/src/core/tls.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/objects.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#include <openssl/pem.h> #include <openssl/pem.h>
@ -752,49 +751,44 @@ static void set_server_temporary_key_info(TLS_REC *tls, SSL *ssl)
#ifdef SSL_get_server_tmp_key #ifdef SSL_get_server_tmp_key
/* Show ephemeral key information. */ /* Show ephemeral key information. */
EVP_PKEY *ephemeral_key = NULL; EVP_PKEY *ephemeral_key = NULL;
/* OPENSSL_NO_EC is for solaris 11.3 (2016), github ticket #598 */
#ifndef OPENSSL_NO_EC
EC_KEY *ec_key = NULL;
#endif
char *ephemeral_key_algorithm = NULL; char *ephemeral_key_algorithm = NULL;
char *cname = NULL;
int nid;
g_return_if_fail(tls != NULL); g_return_if_fail(tls != NULL);
g_return_if_fail(ssl != NULL); g_return_if_fail(ssl != NULL);
if (SSL_get_server_tmp_key(ssl, &ephemeral_key)) { if (SSL_get_server_tmp_key(ssl, &ephemeral_key)) {
int keytype = EVP_PKEY_id(ephemeral_key); switch (EVP_PKEY_id(ephemeral_key)) {
switch (keytype) { case EVP_PKEY_DH:
case EVP_PKEY_DH: tls_rec_set_ephemeral_key_algorithm(tls, "DH");
tls_rec_set_ephemeral_key_algorithm(tls, "DH"); tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key));
tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); break;
break;
/* OPENSSL_NO_EC is for solaris 11.3 (2016), github ticket #598 */
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
case EVP_PKEY_EC: { case EVP_PKEY_EC:
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) ec_key = EVP_PKEY_get1_EC_KEY(ephemeral_key);
char cname[50]; nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
EVP_PKEY_get_group_name(ephemeral_key, cname, sizeof(cname), NULL); EC_KEY_free(ec_key);
#else cname = (char *)OBJ_nid2sn(nid);
EC_KEY *ec_key = NULL; ephemeral_key_algorithm = g_strdup_printf("ECDH: %s", cname);
char *cname = NULL;
int nid;
ec_key = EVP_PKEY_get1_EC_KEY(ephemeral_key); tls_rec_set_ephemeral_key_algorithm(tls, ephemeral_key_algorithm);
nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)); tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key));
EC_KEY_free(ec_key);
cname = (char *) OBJ_nid2sn(nid);
#endif
ephemeral_key_algorithm = g_strdup_printf("ECDH: %s", cname);
tls_rec_set_ephemeral_key_algorithm(tls, ephemeral_key_algorithm); g_free_and_null(ephemeral_key_algorithm);
tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); break;
g_free_and_null(ephemeral_key_algorithm);
break;
}
#endif #endif
default: default:
tls_rec_set_ephemeral_key_algorithm(tls, OBJ_nid2ln(keytype)); tls_rec_set_ephemeral_key_algorithm(tls, "Unknown");
tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key));
break; break;
} }
EVP_PKEY_free(ephemeral_key); EVP_PKEY_free(ephemeral_key);

View file

@ -81,14 +81,27 @@ int i_io_channel_read_block(GIOChannel *channel, void *data, int len)
return received < len ? -1 : 0; return received < len ? -1 : 0;
} }
IPADDR ip4_any = { AF_INET, IPADDR ip4_any = {
AF_INET,
#if defined(IN6ADDR_ANY_INIT) #if defined(IN6ADDR_ANY_INIT)
IN6ADDR_ANY_INIT IN6ADDR_ANY_INIT
#else #else
{ INADDR_ANY } { INADDR_ANY }
#endif #endif
}; };
int net_ip_compare(IPADDR *ip1, IPADDR *ip2)
{
if (ip1->family != ip2->family)
return 0;
if (ip1->family == AF_INET6)
return memcmp(&ip1->ip, &ip2->ip, sizeof(ip1->ip)) == 0;
return memcmp(&ip1->ip, &ip2->ip, 4) == 0;
}
static void sin_set_ip(union sockaddr_union *so, const IPADDR *ip) static void sin_set_ip(union sockaddr_union *so, const IPADDR *ip)
{ {
if (ip == NULL) { if (ip == NULL) {
@ -379,119 +392,95 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
return 0; return 0;
} }
void resolved_ip_ref(RESOLVED_IP_REC *iprec) /* Get IP addresses for host, both IPv4 and IPv6 if possible.
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
{ {
iprec->refcount++; union sockaddr_union *so;
} struct addrinfo hints, *ai, *ailist;
int ret, count_v4, count_v6, use_v4, use_v6;
int resolved_ip_unref(RESOLVED_IP_REC *iprec)
{
if (--iprec->refcount > 0) {
return TRUE;
}
g_resolver_free_addresses(iprec->ailist);
if (iprec->error != NULL) {
g_error_free(iprec->error);
}
g_free(iprec);
return FALSE;
}
/* Get IP addresses for host, both IPv4 and IPv6 if possible. */
static RESOLVED_IP_REC *net_gethostbyname(const char *addr, GResolverNameLookupFlags flags)
{
/* GList<GInetAddress> */
GList *ailist;
GError *error;
GResolver *resolver;
RESOLVED_IP_REC *iprec;
g_return_val_if_fail(addr != NULL, NULL);
error = NULL;
resolver = g_resolver_get_default();
#if GLIB_CHECK_VERSION(2, 59, 0)
ailist = g_resolver_lookup_by_name_with_flags(resolver, addr, flags, NULL, &error);
#else
/* compatibility code for old GLib */
ailist = g_resolver_lookup_by_name(resolver, addr, NULL, &error);
if (error == NULL && flags) {
GList *ll, *lll;
for (ll = ailist; ll != NULL; ll = lll) {
GInetAddress *address;
GSocketFamily family;
address = G_INET_ADDRESS(ll->data);
family = g_inet_address_get_family(address);
lll = ll->next;
if ((flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY &&
family == G_SOCKET_FAMILY_IPV6) ||
(flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY &&
family == G_SOCKET_FAMILY_IPV4)) {
g_object_unref(address);
ailist = g_list_delete_link(ailist, ll);
}
}
if (ailist == NULL) {
g_set_error(&error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY ?
"IPv4 address not found for host" :
"IPv6 address not found for host");
}
}
#endif
iprec = g_new0(RESOLVED_IP_REC, 1);
if (error != NULL) {
iprec->error = error;
} else {
iprec->ailist = ailist;
}
g_object_unref(resolver);
resolved_ip_ref(iprec);
return iprec;
}
int net_gethostbyname_first_ips(const char *addr, GResolverNameLookupFlags flags, IPADDR *ip4,
IPADDR *ip6)
{
RESOLVED_IP_REC *iprec;
#ifdef HAVE_CAPSICUM #ifdef HAVE_CAPSICUM
if (capsicum_enabled()) if (capsicum_enabled())
return (capsicum_net_gethostbyname(addr, ip4, ip6)); return (capsicum_net_gethostbyname(addr, ip4, ip6));
#endif #endif
iprec = net_gethostbyname(addr, flags); g_return_val_if_fail(addr != NULL, -1);
if (iprec->error == NULL) {
GList *curr;
for (curr = iprec->ailist; curr; curr = curr->next) { memset(ip4, 0, sizeof(IPADDR));
unsigned short family; memset(ip6, 0, sizeof(IPADDR));
GInetAddress *addr;
addr = curr->data; memset(&hints, 0, sizeof(struct addrinfo));
family = g_inet_address_get_family(addr); hints.ai_socktype = SOCK_STREAM;
if (ip4->family == 0 && family == AF_INET) { hints.ai_flags = AI_ADDRCONFIG;
ip4->family = AF_INET;
memcpy(&ip4->ip, g_inet_address_to_bytes(addr), sizeof(ip4->ip));
} else if (ip6->family == 0 && family == AF_INET6) {
ip6->family = AF_INET6;
memcpy(&ip6->ip, g_inet_address_to_bytes(addr), sizeof(ip6->ip));
}
}
resolved_ip_unref(iprec); /* save error to host_error for later use */
return 0; ret = getaddrinfo(addr, NULL, &hints, &ailist);
} else { if (ret != 0)
resolved_ip_unref(iprec); return ret;
return -1;
/* count IPs */
count_v4 = count_v6 = 0;
for (ai = ailist; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family == AF_INET)
count_v4++;
else if (ai->ai_family == AF_INET6)
count_v6++;
} }
if (count_v4 == 0 && count_v6 == 0)
return HOST_NOT_FOUND; /* shouldn't happen? */
/* if there are multiple addresses, return random one */
use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4;
use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6;
count_v4 = count_v6 = 0;
for (ai = ailist; ai != NULL; ai = ai->ai_next) {
so = (union sockaddr_union *) ai->ai_addr;
if (ai->ai_family == AF_INET) {
if (use_v4 == count_v4)
sin_get_ip(so, ip4);
count_v4++;
} else if (ai->ai_family == AF_INET6) {
if (use_v6 == count_v6)
sin_get_ip(so, ip6);
count_v6++;
}
}
freeaddrinfo(ailist);
return 0;
}
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name)
{
union sockaddr_union so;
int host_error;
char hostname[NI_MAXHOST];
g_return_val_if_fail(ip != NULL, -1);
g_return_val_if_fail(name != NULL, -1);
*name = NULL;
memset(&so, 0, sizeof(so));
sin_set_ip(&so, ip);
/* save error to host_error for later use */
host_error = getnameinfo((struct sockaddr *)&so, sizeof(so),
hostname, sizeof(hostname),
NULL, 0,
NI_NAMEREQD);
if (host_error != 0)
return host_error;
*name = g_strdup(hostname);
return 0;
} }
int net_ip2host(IPADDR *ip, char *host) int net_ip2host(IPADDR *ip, char *host)
@ -502,6 +491,8 @@ int net_ip2host(IPADDR *ip, char *host)
int net_host2ip(const char *host, IPADDR *ip) int net_host2ip(const char *host, IPADDR *ip)
{ {
unsigned long addr;
if (strchr(host, ':') != NULL) { if (strchr(host, ':') != NULL) {
/* IPv6 */ /* IPv6 */
ip->family = AF_INET6; ip->family = AF_INET6;
@ -510,8 +501,16 @@ int net_host2ip(const char *host, IPADDR *ip)
} else { } else {
/* IPv4 */ /* IPv4 */
ip->family = AF_INET; ip->family = AF_INET;
if (inet_pton(AF_INET, host, &ip->ip) == 0) #ifdef HAVE_INET_ATON
if (inet_aton(host, &ip->ip.s_addr) == 0)
return -1; return -1;
#else
addr = inet_addr(host);
if (addr == INADDR_NONE)
return -1;
memcpy(&ip->ip, &addr, 4);
#endif
} }
return 0; return 0;
@ -530,6 +529,29 @@ int net_geterror(GIOChannel *handle)
return data; return data;
} }
/* get error of net_gethostname() */
const char *net_gethosterror(int error)
{
g_return_val_if_fail(error != 0, NULL);
if (error == EAI_SYSTEM) {
return strerror(errno);
} else {
return gai_strerror(error);
}
}
/* return TRUE if host lookup failed because it didn't exist (ie. not
some error with name server) */
int net_hosterror_notfound(int error)
{
#ifdef EAI_NODATA /* NODATA is deprecated */
return error != 1 && (error == EAI_NONAME || error == EAI_NODATA);
#else
return error != 1 && (error == EAI_NONAME);
#endif
}
/* Get name of TCP service */ /* Get name of TCP service */
char *net_getservbyport(int port) char *net_getservbyport(int port)
{ {

View file

@ -1,12 +1,15 @@
#ifndef IRSSI_CORE_NETWORK_H #ifndef IRSSI_CORE_NETWORK_H
#define IRSSI_CORE_NETWORK_H #define IRSSI_CORE_NETWORK_H
#ifdef HAVE_SOCKS_H
#include <socks.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> # include <sys/socket.h>
#include <netinet/in.h> # include <netinet/in.h>
#include <netdb.h> # include <netdb.h>
#include <arpa/inet.h> # include <arpa/inet.h>
#include <irssi/src/common.h>
#ifndef AF_INET6 #ifndef AF_INET6
# ifdef PF_INET6 # ifdef PF_INET6
@ -16,31 +19,11 @@
# endif # endif
#endif #endif
#if GLIB_CHECK_VERSION(2, 59, 0)
/* nothing */
#else
/* compatibility code for old GLib */
typedef enum {
G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT = 0,
G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY = 1 << 0,
G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY = 1 << 1,
} GResolverNameLookupFlags;
#endif
struct _IPADDR { struct _IPADDR {
unsigned short family; unsigned short family;
struct in6_addr ip; struct in6_addr ip;
}; };
typedef struct {
int refcount;
/* GList<GInetAddress> */
GList *ailist; /* needs to be freed */
GError *error; /* needs to be freed */
} RESOLVED_IP_REC;
/* maxmimum string length of IP address */ /* maxmimum string length of IP address */
#define MAX_IP_LEN INET6_ADDRSTRLEN #define MAX_IP_LEN INET6_ADDRSTRLEN
@ -50,7 +33,9 @@ extern IPADDR ip4_any;
GIOChannel *i_io_channel_new(int handle); GIOChannel *i_io_channel_new(int handle);
/* OTR */ /* Returns 1 if IPADDRs are the same. */
/* Deprecated since it is unused. It will be deleted in a later release. */
int net_ip_compare(IPADDR *ip1, IPADDR *ip2) G_GNUC_DEPRECATED;
int i_io_channel_write_block(GIOChannel *channel, void *data, int len); int i_io_channel_write_block(GIOChannel *channel, void *data, int len);
int i_io_channel_read_block(GIOChannel *channel, void *data, int len); int i_io_channel_read_block(GIOChannel *channel, void *data, int len);
@ -79,9 +64,18 @@ int net_receive(GIOChannel *handle, char *buf, int len);
/* Transmit data, return number of bytes sent, -1 = error */ /* Transmit data, return number of bytes sent, -1 = error */
int net_transmit(GIOChannel *handle, const char *data, int len); int net_transmit(GIOChannel *handle, const char *data, int len);
/* Get the first IP address for host, both IPv4 and IPv6 if possible. */ /* Get IP addresses for host, both IPv4 and IPv6 if possible.
int net_gethostbyname_first_ips(const char *addr, GResolverNameLookupFlags flags, IPADDR *ip4, If ip->family is 0, the address wasn't found.
IPADDR *ip6); Returns 0 = ok, others = error code for net_gethosterror() */
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6);
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name);
/* get error of net_gethostname() */
const char *net_gethosterror(int error);
/* return TRUE if host lookup failed because it didn't exist (ie. not
some error with name server) */
int net_hosterror_notfound(int error);
/* Get socket address/port */ /* Get socket address/port */
int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port); int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port);
@ -100,7 +94,4 @@ char *net_getservbyport(int port);
int is_ipv4_address(const char *host); int is_ipv4_address(const char *host);
int is_ipv6_address(const char *host); int is_ipv6_address(const char *host);
void resolved_ip_ref(RESOLVED_IP_REC *iprec);
int resolved_ip_unref(RESOLVED_IP_REC *iprec);
#endif #endif

View file

@ -12,7 +12,6 @@ char *proxy_string, *proxy_string_after, *proxy_password;
unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */ unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */
unsigned short chosen_family; /* family actually chosen during name resolution */ unsigned short chosen_family; /* family actually chosen during name resolution */
char *ipaddr;
char *tag; /* try to keep this tag when connected to server */ char *tag; /* try to keep this tag when connected to server */
char *address; char *address;
int port; int port;
@ -45,8 +44,6 @@ unsigned int unix_socket:1; /* Connect using named unix socket */
unsigned int use_tls:1; /* this connection uses TLS */ unsigned int use_tls:1; /* this connection uses TLS */
unsigned int tls_verify:1; unsigned int tls_verify:1;
unsigned int no_connect:1; /* don't connect() at all, it's done by plugin */ unsigned int no_connect:1; /* don't connect() at all, it's done by plugin */
int last_connected; unsigned short last_failed_family; /* #641: if we failed to connect to ipv6, try ipv4 and vice versa */
int last_failed;
RESOLVED_IP_REC *resolved_host;
char *channels; char *channels;
char *away_reason; char *away_reason;

View file

@ -21,8 +21,10 @@ unsigned int no_reconnect:1; /* Don't reconnect to server */
NET_SENDBUF_REC *handle; NET_SENDBUF_REC *handle;
int readtag; /* input tag */ int readtag; /* input tag */
GCancellable *connect_cancellable; /* for net_gethostbyname_return() */
GIOChannel *connect_pipe[2];
int connect_tag; int connect_tag;
int connect_pid;
RAWLOG_REC *rawlog; RAWLOG_REC *rawlog;
GHashTable *module_data; GHashTable *module_data;

View file

@ -120,10 +120,6 @@ static int server_reconnect_timeout(void)
if (server->connect_tag != -1) { if (server->connect_tag != -1) {
g_source_remove(server->connect_tag); g_source_remove(server->connect_tag);
server->connect_tag = -1; server->connect_tag = -1;
} else if (server->connect_cancellable != NULL) {
g_cancellable_cancel(server->connect_cancellable);
g_object_unref(server->connect_cancellable);
server->connect_cancellable = NULL;
} }
server->connection_lost = TRUE; server->connection_lost = TRUE;
server_connect_failed(server, "Timeout"); server_connect_failed(server, "Timeout");
@ -172,8 +168,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
server_connect_ref(dest); server_connect_ref(dest);
dest->type = module_get_uniq_id("SERVER CONNECT", 0); dest->type = module_get_uniq_id("SERVER CONNECT", 0);
dest->reconnection = src->reconnection; dest->reconnection = src->reconnection;
dest->last_connected = src->last_connected; dest->last_failed_family = src->last_failed_family;
dest->last_failed = src->last_failed;
dest->proxy = g_strdup(src->proxy); dest->proxy = g_strdup(src->proxy);
dest->proxy_port = src->proxy_port; dest->proxy_port = src->proxy_port;
dest->proxy_string = g_strdup(src->proxy_string); dest->proxy_string = g_strdup(src->proxy_string);
@ -212,10 +207,6 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
dest->own_ip6 = g_new(IPADDR, 1); dest->own_ip6 = g_new(IPADDR, 1);
memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR)); memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR));
} }
dest->resolved_host = src->resolved_host;
if (dest->resolved_host != NULL) {
resolved_ip_ref(dest->resolved_host);
}
dest->channels = g_strdup(src->channels); dest->channels = g_strdup(src->channels);
dest->away_reason = g_strdup(src->away_reason); dest->away_reason = g_strdup(src->away_reason);

View file

@ -58,8 +58,7 @@ static void save_ips(IPADDR *ip4, IPADDR *ip6,
static void get_source_host_ip(void) static void get_source_host_ip(void)
{ {
const char *hostname; const char *hostname;
IPADDR ip4 = { 0 }; IPADDR ip4, ip6;
IPADDR ip6 = { 0 };
if (source_host_ok) if (source_host_ok)
return; return;
@ -67,28 +66,25 @@ static void get_source_host_ip(void)
/* FIXME: This will block! */ /* FIXME: This will block! */
hostname = settings_get_str("hostname"); hostname = settings_get_str("hostname");
source_host_ok = *hostname != '\0' && source_host_ok = *hostname != '\0' &&
net_gethostbyname_first_ips(hostname, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, net_gethostbyname(hostname, &ip4, &ip6) == 0;
&ip4, &ip6) == 0;
if (source_host_ok) { if (source_host_ok)
save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6); save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6);
} else { else {
g_free_and_null(source_host_ip4); g_free_and_null(source_host_ip4);
g_free_and_null(source_host_ip6); g_free_and_null(source_host_ip6);
} }
} }
static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host, static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host,
IPADDR **own_ip4, IPADDR **own_ip6) IPADDR **own_ip4, IPADDR **own_ip6)
{ {
IPADDR ip4 = { 0 }; IPADDR ip4, ip6;
IPADDR ip6 = { 0 };
if (*own_ip4 == NULL && *own_ip6 == NULL) { if (*own_ip4 == NULL && *own_ip6 == NULL) {
/* resolve the IP */ /* resolve the IP */
if (net_gethostbyname_first_ips(own_host, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, if (net_gethostbyname(own_host, &ip4, &ip6) == 0)
&ip4, &ip6) == 0) save_ips(&ip4, &ip6, own_ip4, own_ip6);
save_ips(&ip4, &ip6, own_ip4, own_ip6);
} }
server_connect_own_ip_save(conn, *own_ip4, *own_ip6); server_connect_own_ip_save(conn, *own_ip4, *own_ip6);
@ -309,13 +305,6 @@ static SERVER_CONNECT_REC *create_addr_conn(int chat_type, const char *address,
proto = chat_type >= 0 ? chat_protocol_find_id(chat_type) : proto = chat_type >= 0 ? chat_protocol_find_id(chat_type) :
chat_protocol_get_default(); chat_protocol_get_default();
if (proto == NULL) {
signal_stop();
return NULL;
}
g_return_val_if_fail(proto != NULL, NULL);
conn = proto->create_server_connect(); conn = proto->create_server_connect();
server_connect_ref(conn); server_connect_ref(conn);
@ -457,7 +446,6 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
{ {
SERVER_SETUP_REC *rec; SERVER_SETUP_REC *rec;
CHATNET_REC *chatnetrec; CHATNET_REC *chatnetrec;
CHAT_PROTOCOL_REC *proto;
char *server, *chatnet, *family; char *server, *chatnet, *family;
int port; int port;
char *value = NULL; char *value = NULL;
@ -478,40 +466,23 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
rec = NULL; rec = NULL;
if (chatnet != NULL) { chatnetrec = chatnet == NULL ? NULL : chatnet_find(chatnet);
chatnetrec = chatnet_find(chatnet); if (chatnetrec == NULL && chatnet != NULL) {
if (chatnetrec != NULL) { /* chat network not found, create it. */
proto = CHAT_PROTOCOL(chatnetrec); chatnetrec = chat_protocol_get_default()->create_chatnet();
} else { chatnetrec->chat_type = chat_protocol_get_default()->id;
/* chat network not found, create it. */ chatnetrec->name = g_strdup(chatnet);
if (chatnet_find_unavailable(chatnet)) { chatnet_create(chatnetrec);
/* no protocols loaded, skip loading servers */
return NULL;
}
proto = chat_protocol_get_default();
chatnetrec = proto->create_chatnet();
chatnetrec->chat_type = chat_protocol_get_default()->id;
chatnetrec->name = g_strdup(chatnet);
chatnet_create(chatnetrec);
}
} else {
chatnetrec = NULL;
proto = chat_protocol_get_default();
if (proto == NULL) {
/* no protocols loaded, skip loading servers */
return NULL;
}
} }
family = config_node_get_str(node, "family", ""); family = config_node_get_str(node, "family", "");
rec = proto->create_server_setup(); rec = CHAT_PROTOCOL(chatnetrec)->create_server_setup();
rec->type = module_get_uniq_id("SERVER SETUP", 0); rec->type = module_get_uniq_id("SERVER SETUP", 0);
rec->chat_type = proto->id; rec->chat_type = CHAT_PROTOCOL(chatnetrec)->id;
rec->chatnet = chatnetrec == NULL ? NULL : g_strdup(chatnetrec->name); rec->chatnet = chatnetrec == NULL ? NULL : g_strdup(chatnetrec->name);
rec->family = g_ascii_strcasecmp(family, "inet6") == 0 ? rec->family = g_ascii_strcasecmp(family, "inet6") == 0 ? AF_INET6 :
AF_INET6 : (g_ascii_strcasecmp(family, "inet") == 0 ? AF_INET : 0);
(g_ascii_strcasecmp(family, "inet") == 0 ? AF_INET : 0);
rec->address = g_strdup(server); rec->address = g_strdup(server);
rec->password = g_strdup(config_node_get_str(node, "password", NULL)); rec->password = g_strdup(config_node_get_str(node, "password", NULL));
@ -788,7 +759,8 @@ void servers_setup_init(void)
read_settings(); read_settings();
signal_add("setup changed", (SIGNAL_FUNC) read_settings); signal_add("setup changed", (SIGNAL_FUNC) read_settings);
signal_add("setup reread servers", (SIGNAL_FUNC) read_servers); signal_add("setup reread", (SIGNAL_FUNC) read_servers);
signal_add("irssi init read settings", (SIGNAL_FUNC) read_servers);
} }
void servers_setup_deinit(void) void servers_setup_deinit(void)
@ -801,7 +773,8 @@ void servers_setup_deinit(void)
server_setup_destroy(setupservers->data); server_setup_destroy(setupservers->data);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings); signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
signal_remove("setup reread servers", (SIGNAL_FUNC) read_servers); signal_remove("setup reread", (SIGNAL_FUNC) read_servers);
signal_remove("irssi init read settings", (SIGNAL_FUNC) read_servers);
module_uniq_destroy("SERVER SETUP"); module_uniq_destroy("SERVER SETUP");
} }

View file

@ -51,16 +51,20 @@ void server_connect_failed(SERVER_REC *server, const char *msg)
g_source_remove(server->connect_tag); g_source_remove(server->connect_tag);
server->connect_tag = -1; server->connect_tag = -1;
} }
if (server->connect_cancellable != NULL) {
g_cancellable_cancel(server->connect_cancellable);
g_object_unref(server->connect_cancellable);
server->connect_cancellable = NULL;
}
if (server->handle != NULL) { if (server->handle != NULL) {
net_sendbuffer_destroy(server->handle, TRUE); net_sendbuffer_destroy(server->handle, TRUE);
server->handle = NULL; server->handle = NULL;
} }
if (server->connect_pipe[0] != NULL) {
g_io_channel_shutdown(server->connect_pipe[0], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[0]);
g_io_channel_shutdown(server->connect_pipe[1], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[1]);
server->connect_pipe[0] = NULL;
server->connect_pipe[1] = NULL;
}
server_unref(server); server_unref(server);
} }
@ -130,7 +134,8 @@ static char *server_create_tag(SERVER_CONNECT_REC *conn)
} }
g_free(tag); g_free(tag);
tag = g_string_free(str, FALSE); tag = str->str;
g_string_free(str, FALSE);
return tag; return tag;
} }
@ -152,7 +157,7 @@ static void server_connect_callback_init(SERVER_REC *server, GIOChannel *handle)
error = net_geterror(handle); error = net_geterror(handle);
if (error != 0) { if (error != 0) {
server->connection_lost = TRUE; server->connection_lost = TRUE;
server->connrec->last_failed = server->connrec->last_connected; server->connrec->last_failed_family = server->connrec->chosen_family;
server_connect_failed(server, g_strerror(error)); server_connect_failed(server, g_strerror(error));
return; return;
} }
@ -173,7 +178,7 @@ static void server_connect_callback_init_ssl(SERVER_REC *server, GIOChannel *han
error = irssi_ssl_handshake(handle); error = irssi_ssl_handshake(handle);
if (error == -1) { if (error == -1) {
server->connection_lost = TRUE; server->connection_lost = TRUE;
server->connrec->last_failed = server->connrec->last_connected; server->connrec->last_failed_family = server->connrec->chosen_family;
server_connect_failed(server, NULL); server_connect_failed(server, NULL);
return; return;
} }
@ -207,18 +212,13 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
g_return_if_fail(ip != NULL || unix_socket != NULL); g_return_if_fail(ip != NULL || unix_socket != NULL);
if (ip != NULL) {
server->connrec->chosen_family = ip->family;
net_ip2host(ip, ipaddr);
server->connrec->ipaddr = g_strdup(ipaddr);
}
signal_emit("server connecting", 2, server, ip); signal_emit("server connecting", 2, server, ip);
if (server->connrec->no_connect) if (server->connrec->no_connect)
return; return;
if (ip != NULL) { if (ip != NULL) {
server->connrec->chosen_family = ip->family;
own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4; own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4;
port = server->connrec->proxy != NULL ? port = server->connrec->proxy != NULL ?
server->connrec->proxy_port : server->connrec->port; server->connrec->proxy_port : server->connrec->port;
@ -255,12 +255,12 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
server->connection_lost = TRUE; server->connection_lost = TRUE;
if (ip != NULL) { if (ip != NULL) {
server->connrec->last_failed = server->connrec->last_connected; server->connrec->last_failed_family = ip->family;
} }
server_connect_failed(server, errmsg2 ? errmsg2 : errmsg); server_connect_failed(server, errmsg2 ? errmsg2 : errmsg);
g_free(errmsg2); g_free(errmsg2);
} else { } else {
server->connrec->last_failed = 0; server->connrec->last_failed_family = 0;
if (!server->connrec->use_tls) if (!server->connrec->use_tls)
server->handle = net_sendbuffer_create(handle, 0); server->handle = net_sendbuffer_create(handle, 0);
if (server->connrec->use_tls) if (server->connrec->use_tls)
@ -272,47 +272,48 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
} }
} }
static int server_start_connect_resolve(SERVER_REC *server); static void server_connect_callback_readpipe(SERVER_REC *server)
static void server_connect_use_resolved(SERVER_REC *server)
{ {
IPADDR *ip; RESOLVED_IP_REC iprec;
IPADDR *ip;
const char *errormsg; const char *errormsg;
RESOLVED_IP_REC *iprec = server->connrec->resolved_host;
if (iprec->error != NULL) { g_source_remove(server->connect_tag);
/* error */ server->connect_tag = -1;
net_gethostbyname_return(server->connect_pipe[0], &iprec);
g_io_channel_shutdown(server->connect_pipe[0], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[0]);
g_io_channel_shutdown(server->connect_pipe[1], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[1]);
server->connect_pipe[0] = NULL;
server->connect_pipe[1] = NULL;
/* figure out if we should use IPv4 or v6 address */
if (iprec.error != 0) {
/* error */
ip = NULL; ip = NULL;
} else if (server->connrec->family == AF_INET) {
/* force IPv4 connection */
ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4;
} else if (server->connrec->family == AF_INET6) {
/* force IPv6 connection */
ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6;
} else { } else {
GList *curr; /* pick the one that was found. if both were found:
int i; 1. disprefer the last one that failed
2. prefer ipv4 over ipv6 unless resolve_prefer_ipv6 is set
curr = iprec->ailist; */
i = 0; if (iprec.ip4.family == 0 ||
while (i < server->connrec->last_failed) { (iprec.ip6.family != 0 &&
if (curr != NULL) { (server->connrec->last_failed_family == AF_INET ||
curr = curr->next; (settings_get_bool("resolve_prefer_ipv6") &&
i++; server->connrec->last_failed_family != AF_INET6)))) {
} ip = &iprec.ip6;
/* curr is different now */
if (curr == NULL) {
resolved_ip_unref(server->connrec->resolved_host);
server->connrec->resolved_host = NULL;
server->connrec->last_failed = 0;
/* retry resolve */
server_start_connect_resolve(server);
return;
}
}
if (curr != NULL) {
GInetAddress *addr;
addr = curr->data;
server->connrec->last_connected = i + 1;
ip = g_new0(IPADDR, 1);
ip->family = g_inet_address_get_family(addr);
memcpy(&ip->ip, g_inet_address_to_bytes(addr), sizeof(ip->ip));
} else { } else {
ip = NULL; ip = &iprec.ip4;
} }
} }
@ -321,69 +322,28 @@ static void server_connect_use_resolved(SERVER_REC *server)
server_real_connect(server, ip, NULL); server_real_connect(server, ip, NULL);
errormsg = NULL; errormsg = NULL;
} else { } else {
if (iprec->error->code == G_RESOLVER_ERROR_NOT_FOUND) { if (iprec.error == 0 || net_hosterror_notfound(iprec.error)) {
/* IP wasn't found for the host, don't try to /* IP wasn't found for the host, don't try to
reconnect back to this server */ reconnect back to this server */
server->dns_error = TRUE; server->dns_error = TRUE;
} }
errormsg = iprec->error->message; if (iprec.error == 0) {
if (errormsg == NULL) /* forced IPv4 or IPv6 address but it wasn't found */
errormsg = "Host lookup failed"; errormsg = server->connrec->family == AF_INET ?
"IPv4 address not found for host" :
"IPv6 address not found for host";
} else {
/* gethostbyname() failed */
errormsg = iprec.errorstr != NULL ? iprec.errorstr :
"Host lookup failed";
}
server->connection_lost = TRUE; server->connection_lost = TRUE;
/* clear the error in resolved_host */
server->connrec->resolved_host = NULL;
server_connect_failed(server, errormsg); server_connect_failed(server, errormsg);
resolved_ip_unref(iprec);
} }
g_free(ip); g_free(iprec.errorstr);
}
static void server_connect_callback_resolved(RESOLVED_IP_REC *iprec, SERVER_REC *server)
{
if (server->connect_cancellable != NULL) {
g_object_unref(server->connect_cancellable);
server->connect_cancellable = NULL;
}
if (server->connrec->resolved_host != NULL) {
resolved_ip_unref(server->connrec->resolved_host);
}
server->connrec->resolved_host = iprec;
if (iprec->error == NULL && iprec->ailist == NULL) {
server->connection_lost = TRUE;
server->dns_error = TRUE;
server_connect_failed(server, "Host lookup failed");
} else {
server_connect_use_resolved(server);
}
}
static int server_start_connect_resolve(SERVER_REC *server)
{
const char *connect_address;
GResolverNameLookupFlags net_gethostbyname_flags;
connect_address =
server->connrec->proxy != NULL ? server->connrec->proxy : server->connrec->address;
net_gethostbyname_flags = G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT;
if (server->connrec->family == AF_INET) {
net_gethostbyname_flags = G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY;
} else if (server->connrec->family == AF_INET6) {
net_gethostbyname_flags = G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY;
}
if (server->connrec->resolved_host == NULL) {
server->connect_cancellable = net_gethostbyname_nonblock(
connect_address, net_gethostbyname_flags,
(NetGethostbynameContinuationFunc) server_connect_callback_resolved, server);
return FALSE;
} else {
return TRUE;
}
} }
SERVER_REC *server_connect(SERVER_CONNECT_REC *conn) SERVER_REC *server_connect(SERVER_CONNECT_REC *conn)
@ -435,6 +395,9 @@ void server_connect_init(SERVER_REC *server)
/* starts connecting to server */ /* starts connecting to server */
int server_start_connect(SERVER_REC *server) int server_start_connect(SERVER_REC *server)
{ {
const char *connect_address;
int fd[2];
g_return_val_if_fail(server != NULL, FALSE); g_return_val_if_fail(server != NULL, FALSE);
if (!server->connrec->unix_socket && server->connrec->port <= 0) if (!server->connrec->unix_socket && server->connrec->port <= 0)
return FALSE; return FALSE;
@ -452,17 +415,30 @@ int server_start_connect(SERVER_REC *server)
/* connect with unix socket */ /* connect with unix socket */
server_real_connect(server, NULL, server->connrec->address); server_real_connect(server, NULL, server->connrec->address);
} else { } else {
int already_resolved;
/* resolve host name */ /* resolve host name */
already_resolved = server_start_connect_resolve(server); if (pipe(fd) != 0) {
g_warning("server_connect(): pipe() failed.");
g_free(server->tag);
g_free(server->nick);
return FALSE;
}
server->connect_pipe[0] = i_io_channel_new(fd[0]);
server->connect_pipe[1] = i_io_channel_new(fd[1]);
connect_address = server->connrec->proxy != NULL ?
server->connrec->proxy : server->connrec->address;
server->connect_pid =
net_gethostbyname_nonblock(connect_address,
server->connect_pipe[1], 0);
server->connect_tag =
i_input_add(server->connect_pipe[0], I_INPUT_READ,
(GInputFunction) server_connect_callback_readpipe, server);
server->connect_time = time(NULL); server->connect_time = time(NULL);
lookup_servers = g_slist_append(lookup_servers, server); lookup_servers = g_slist_append(lookup_servers, server);
signal_emit("server looking", 1, server); signal_emit("server looking", 1, server);
if (already_resolved) {
server_connect_use_resolved(server);
}
} }
return TRUE; return TRUE;
} }
@ -501,9 +477,8 @@ void server_disconnect(SERVER_REC *server)
if (server->connect_tag != -1) { if (server->connect_tag != -1) {
/* still connecting to server.. */ /* still connecting to server.. */
server_connect_failed(server, NULL); if (server->connect_pid != -1)
return; net_disconnect_nonblock(server->connect_pid);
} else if (server->connect_cancellable != NULL) {
server_connect_failed(server, NULL); server_connect_failed(server, NULL);
return; return;
} }
@ -662,7 +637,6 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
g_free_not_null(conn->proxy_string_after); g_free_not_null(conn->proxy_string_after);
g_free_not_null(conn->proxy_password); g_free_not_null(conn->proxy_password);
g_free_not_null(conn->ipaddr);
g_free_not_null(conn->tag); g_free_not_null(conn->tag);
g_free_not_null(conn->address); g_free_not_null(conn->address);
g_free_not_null(conn->chatnet); g_free_not_null(conn->chatnet);
@ -670,10 +644,6 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
g_free_not_null(conn->own_ip4); g_free_not_null(conn->own_ip4);
g_free_not_null(conn->own_ip6); g_free_not_null(conn->own_ip6);
if (conn->resolved_host != NULL) {
resolved_ip_unref(conn->resolved_host);
}
g_free_not_null(conn->password); g_free_not_null(conn->password);
g_free_not_null(conn->nick); g_free_not_null(conn->nick);
g_free_not_null(conn->username); g_free_not_null(conn->username);
@ -794,6 +764,7 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto)
void servers_init(void) void servers_init(void)
{ {
settings_add_bool("server", "resolve_prefer_ipv6", FALSE);
lookup_servers = servers = NULL; lookup_servers = servers = NULL;
signal_add("chat protocol deinit", (SIGNAL_FUNC) sig_chat_protocol_deinit); signal_add("chat protocol deinit", (SIGNAL_FUNC) sig_chat_protocol_deinit);

View file

@ -2,7 +2,6 @@
#define IRSSI_CORE_SERVERS_H #define IRSSI_CORE_SERVERS_H
#include <irssi/src/core/modules.h> #include <irssi/src/core/modules.h>
#include <irssi/src/core/network.h>
/* Returns SERVER_REC if it's server, NULL if it isn't. */ /* Returns SERVER_REC if it's server, NULL if it isn't. */
#define SERVER(server) \ #define SERVER(server) \

View file

@ -673,6 +673,18 @@ GSList *settings_get_sorted(void)
return list; return list;
} }
void sig_term(int n)
{
/* if we get SIGTERM after this, just die instead of coming back here. */
signal(SIGTERM, SIG_DFL);
/* quit from all servers too.. */
signal_emit("command quit", 1, "");
/* and die */
raise(SIGTERM);
}
/* Yes, this is my own stupid checksum generator, some "real" algorithm /* Yes, this is my own stupid checksum generator, some "real" algorithm
would be nice but would just take more space without much real benefit */ would be nice but would just take more space without much real benefit */
static unsigned int file_checksum(const char *fname) static unsigned int file_checksum(const char *fname)
@ -793,6 +805,8 @@ static void init_configfile(void)
signal_emit("gui dialog", 2, "error", str); signal_emit("gui dialog", 2, "error", str);
g_free(str); g_free(str);
} }
signal(SIGTERM, sig_term);
} }
int settings_reread(const char *fname) int settings_reread(const char *fname)

View file

@ -88,7 +88,8 @@ static char *get_argument(char **cmd, char **arglist)
} }
if (str->len > 0) g_string_truncate(str, str->len-1); if (str->len > 0) g_string_truncate(str, str->len-1);
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -411,7 +412,8 @@ char *get_alignment(const char *text, int align, int flags, char pad)
} }
} }
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -602,7 +604,8 @@ char *parse_special_string(const char *cmd, SERVER_REC *server, void *item,
} }
g_strfreev(arglist); g_strfreev(arglist);
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }

View file

@ -0,0 +1,3 @@
SUBDIRS = core irc
EXTRA_DIST = meson.build

View file

@ -0,0 +1,73 @@
noinst_LIBRARIES = libfe_common_core.a
AM_CPPFLAGS = \
-I$(top_builddir) \
$(GLIB_CFLAGS) \
-DHELPDIR=\""$(datadir)/irssi/help"\" \
-DTHEMESDIR=\""$(datadir)/irssi/themes"\"
libfe_common_core_a_SOURCES = \
chat-completion.c \
command-history.c \
completion.c \
fe-channels.c \
fe-common-core.c \
fe-core-commands.c \
fe-exec.c \
fe-expandos.c \
fe-help.c \
fe-ignore.c \
fe-ignore-messages.c \
fe-log.c \
fe-messages.c \
fe-modules.c \
fe-queries.c \
fe-server.c \
fe-settings.c \
fe-tls.c \
formats.c \
hilight-text.c \
keyboard.c \
module-formats.c \
printtext.c \
fe-recode.c \
themes.c \
window-activity.c \
window-commands.c \
window-items.c \
windows-layout.c \
fe-windows.c
if HAVE_CAPSICUM
libfe_common_core_a_SOURCES += \
fe-capsicum.c
endif
pkginc_fe_common_coredir=$(pkgincludedir)/src/fe-common/core
pkginc_fe_common_core_HEADERS = \
command-history.h \
chat-completion.h \
completion.h \
fe-capsicum.h \
fe-channels.h \
fe-common-core.h \
fe-core-commands.h \
fe-exec.h \
fe-messages.h \
fe-queries.h \
fe-settings.h \
fe-tls.h \
formats.h \
hilight-text.h \
keyboard.h \
module-formats.h \
module.h \
printtext.h \
fe-recode.h \
themes.h \
window-activity.h \
window-items.h \
windows-layout.h \
fe-windows.h
EXTRA_DIST = meson.build

View file

@ -261,12 +261,7 @@ static const char *command_history_prev_int(WINDOW_REC *window, const char *text
if (*text != '\0' && if (*text != '\0' &&
(pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) { (pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) {
/* save the old entry to history */ /* save the old entry to history */
if (pos != NULL && settings_get_bool("command_history_editable")) { command_history_add(history, text);
history_entry_destroy(pos->data);
pos->data = history_entry_new(history, text);
} else {
command_history_add(history, text);
}
} }
return history->pos == NULL ? text : ((HISTORY_ENTRY_REC *)history->pos->data)->text; return history->pos == NULL ? text : ((HISTORY_ENTRY_REC *)history->pos->data)->text;
@ -297,12 +292,7 @@ static const char *command_history_next_int(WINDOW_REC *window, const char *text
if (*text != '\0' && if (*text != '\0' &&
(pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) { (pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) {
/* save the old entry to history */ /* save the old entry to history */
if (pos != NULL && settings_get_bool("command_history_editable")) { command_history_add(history, text);
history_entry_destroy(pos->data);
pos->data = history_entry_new(history, text);
} else {
command_history_add(history, text);
}
} }
return history->pos == NULL ? "" : ((HISTORY_ENTRY_REC *)history->pos->data)->text; return history->pos == NULL ? "" : ((HISTORY_ENTRY_REC *)history->pos->data)->text;
} }
@ -477,7 +467,6 @@ void command_history_init(void)
{ {
settings_add_int("history", "max_command_history", 100); settings_add_int("history", "max_command_history", 100);
settings_add_bool("history", "window_history", FALSE); settings_add_bool("history", "window_history", FALSE);
settings_add_bool("history", "command_history_editable", FALSE);
special_history_func_set(special_history_func); special_history_func_set(special_history_func);

View file

@ -111,7 +111,8 @@ char *auto_word_complete(const char *line, int *pos)
*pos = startpos+strlen(replace); *pos = startpos+strlen(replace);
g_string_insert(result, startpos, replace); g_string_insert(result, startpos, replace);
ret = g_string_free_and_steal(result); ret = result->str;
g_string_free(result, FALSE);
} }
g_free(word); g_free(word);
@ -289,7 +290,8 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i
g_free_not_null(last_line); g_free_not_null(last_line);
last_line = g_strdup(result->str); last_line = g_strdup(result->str);
ret = g_string_free_and_steal(result); ret = result->str;
g_string_free(result, FALSE);
/* free the data */ /* free the data */
g_free(data); g_free(data);

View file

@ -646,7 +646,7 @@ void fe_channels_init(void)
command_bind("channel modify", NULL, (SIGNAL_FUNC) cmd_channel_modify); command_bind("channel modify", NULL, (SIGNAL_FUNC) cmd_channel_modify);
command_bind("channel remove", NULL, (SIGNAL_FUNC) cmd_channel_remove); command_bind("channel remove", NULL, (SIGNAL_FUNC) cmd_channel_remove);
command_bind("channel list", NULL, (SIGNAL_FUNC) cmd_channel_list); command_bind("channel list", NULL, (SIGNAL_FUNC) cmd_channel_list);
command_bind_first("names", NULL, (SIGNAL_FUNC) cmd_names); command_bind("names", NULL, (SIGNAL_FUNC) cmd_names);
command_bind("cycle", NULL, (SIGNAL_FUNC) cmd_cycle); command_bind("cycle", NULL, (SIGNAL_FUNC) cmd_cycle);
command_set_options("channel add", "auto noauto -bots -botcmd"); command_set_options("channel add", "auto noauto -bots -botcmd");

View file

@ -166,7 +166,7 @@ void fe_common_core_init(void)
settings_add_bool("lookandfeel", "use_msgs_window", FALSE); settings_add_bool("lookandfeel", "use_msgs_window", FALSE);
g_get_charset(&str); g_get_charset(&str);
settings_add_str("lookandfeel", "term_charset", str); settings_add_str("lookandfeel", "term_charset", str);
settings_add_str("lookandfeel", "glib_log_domains", "all -glib-gio:debug"); settings_add_str("lookandfeel", "glib_log_domains", "all");
themes_init(); themes_init();
theme_register(fecommon_core_formats); theme_register(fecommon_core_formats);
@ -258,19 +258,13 @@ void fe_common_core_deinit(void)
g_log_set_default_handler(logger_old, NULL); g_log_set_default_handler(logger_old, NULL);
} }
static gboolean glib_domain_wanted(const char *domain, const char *level) static gboolean glib_domain_wanted(const char *domain)
{ {
const char *domains; const char *domains;
char *c, *cur; char *c, *cur;
int len = 0; int len = 0;
int print_it = 0; /* -1 for exclude, 0 for undecided, 1 for include */ int print_it = 0; /* -1 for exclude, 0 for undecided, 1 for include */
int incl; int incl;
char *domainlevel, *alllevel, *starlevel, *domainstar;
domainlevel = g_strdup_printf("%s:%s", domain, level);
alllevel = g_strdup_printf("all:%s", level);
starlevel = g_strdup_printf("*:%s", level);
domainstar = g_strdup_printf("%s:*", domain);
/* Go through each item in glib_log_domains setting to determine whether /* Go through each item in glib_log_domains setting to determine whether
* or not we want to print message from this domain */ * or not we want to print message from this domain */
@ -293,10 +287,8 @@ static gboolean glib_domain_wanted(const char *domain, const char *level)
} }
/* If we got a valid item, process it */ /* If we got a valid item, process it */
if (len > 0 && (!strncasecmp(domain, c, len) || !strncasecmp("all", c, len) || if (len > 0 && (!strncmp(domain, c, len) || !strncasecmp("all", c, len) ||
!strncmp("*", c, len) || !strncasecmp(domainstar, c, len) || !strncmp("*", c, len)))
!strncasecmp(domainlevel, c, len) ||
!strncasecmp(alllevel, c, len) || !strncasecmp(starlevel, c, len)))
print_it = incl; print_it = incl;
/* Go past any spaces towards the next item */ /* Go past any spaces towards the next item */
@ -308,11 +300,6 @@ static gboolean glib_domain_wanted(const char *domain, const char *level)
len = 0; len = 0;
} while (*c != '\0' && print_it != -1); } while (*c != '\0' && print_it != -1);
g_free(domainlevel);
g_free(alllevel);
g_free(starlevel);
g_free(domainstar);
return (print_it == 1); return (print_it == 1);
} }
@ -346,7 +333,7 @@ static void i_log_func(const char *log_domain, GLogLevelFlags log_level, const c
domain = (log_domain ? log_domain : "default"); domain = (log_domain ? log_domain : "default");
/* Only print the message if we decided to */ /* Only print the message if we decided to */
if (!glib_domain_wanted(domain, reason)) if (!glib_domain_wanted(domain))
return; return;
if (windows == NULL) if (windows == NULL)

View file

@ -57,7 +57,6 @@ static int skip_next_printtext;
static char *log_theme_name; static char *log_theme_name;
static char **autolog_ignore_targets; static char **autolog_ignore_targets;
static GTimeZone *utc;
static char *log_colorizer_strip(const char *str) static char *log_colorizer_strip(const char *str)
{ {
@ -214,7 +213,8 @@ static char *log_items_get_list(LOG_REC *log)
if(rec->servertag != NULL) if(rec->servertag != NULL)
g_string_append_printf(str, " (%s)", rec->servertag); g_string_append_printf(str, " (%s)", rec->servertag);
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -547,7 +547,7 @@ static void log_line(TEXT_DEST_REC *dest, const char *text)
char *val; char *val;
if ((val = g_hash_table_lookup(dest->meta, "time")) != NULL) { if ((val = g_hash_table_lookup(dest->meta, "time")) != NULL) {
GDateTime *time; GDateTime *time;
if ((time = g_date_time_new_from_iso8601(val, utc)) != NULL) { if ((time = g_date_time_new_from_iso8601(val, NULL)) != NULL) {
t = g_date_time_to_unix(time); t = g_date_time_to_unix(time);
g_date_time_unref(time); g_date_time_unref(time);
} }
@ -745,7 +745,6 @@ void fe_log_init(void)
{ {
autoremove_tag = g_timeout_add(60000, (GSourceFunc) sig_autoremove, NULL); autoremove_tag = g_timeout_add(60000, (GSourceFunc) sig_autoremove, NULL);
skip_next_printtext = FALSE; skip_next_printtext = FALSE;
utc = g_time_zone_new_utc();
settings_add_bool("log", "awaylog_colors", TRUE); settings_add_bool("log", "awaylog_colors", TRUE);
settings_add_bool("log", "autolog", FALSE); settings_add_bool("log", "autolog", FALSE);
@ -813,7 +812,6 @@ void fe_log_deinit(void)
if (autolog_ignore_targets != NULL) if (autolog_ignore_targets != NULL)
g_strfreev(autolog_ignore_targets); g_strfreev(autolog_ignore_targets);
g_time_zone_unref(utc);
g_free_not_null(autolog_path); g_free_not_null(autolog_path);
g_free_not_null(log_theme_name); g_free_not_null(log_theme_name);
} }

View file

@ -133,7 +133,8 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
} }
} }
ret = g_string_free_and_steal(str); ret = str->str;
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -729,8 +730,9 @@ static void sig_nicklist_new(CHANNEL_REC *channel, NICK_REC *nick)
n++; n++;
} while (printnick_exists(firstnick, nick, newnick->str)); } while (printnick_exists(firstnick, nick, newnick->str));
g_hash_table_insert(printnicks, nick, g_string_free_and_steal(newnick)); g_hash_table_insert(printnicks, nick, newnick->str);
g_free(nickhost); g_string_free(newnick, FALSE);
g_free(nickhost);
} }
static void sig_nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick) static void sig_nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick)

View file

@ -29,6 +29,8 @@
#include <irssi/src/fe-common/core/printtext.h> #include <irssi/src/fe-common/core/printtext.h>
#ifdef HAVE_GMODULE
static void sig_module_error(void *number, const char *data, static void sig_module_error(void *number, const char *data,
const char *rootmodule, const char *submodule) const char *rootmodule, const char *submodule)
{ {
@ -271,3 +273,22 @@ void fe_modules_deinit(void)
command_unbind("load", (SIGNAL_FUNC) cmd_load); command_unbind("load", (SIGNAL_FUNC) cmd_load);
command_unbind("unload", (SIGNAL_FUNC) cmd_unload); command_unbind("unload", (SIGNAL_FUNC) cmd_unload);
} }
#else /* !HAVE_GMODULE */
static void cmd_load(const char *data)
{
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
"Dynamic modules loading not supported");
}
void fe_modules_init(void)
{
command_bind("load", NULL, (SIGNAL_FUNC) cmd_load);
}
void fe_modules_deinit(void)
{
command_unbind("load", (SIGNAL_FUNC) cmd_load);
}
#endif

Some files were not shown because too many files have changed in this diff Show more