diff --git a/.gitmodules b/.gitmodules index 9ce1218..3b93ee2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "libwired"] path = libwired - url = https://github.com/nark/libwired + url = https://github.com/profdrluigi/libwired branch = master diff --git a/Makefile b/Makefile index a081f60..16c4f0e 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ WD_MAINTAINER = 0 WD_USER = nark WD_GROUP = daemon -DISTFILES = INSTALL LICENSE NEWS README Makefile Makefile.in \ +DISTFILES = INSTALL LICENSE NEWS README.md Makefile Makefile.in \ config.guess config.status config.h.in config.sub configure \ configure.in install-sh libwired man run thirdparty wired SUBDIRS = libwired @@ -149,6 +149,19 @@ install-wired: $(INSTALL) -m 644 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/banner.png $(installdir)/; \ fi + if [ ! -f $(installdir)/robo.png ]; then \ + $(INSTALL) -m 644 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/robo.png $(installdir)/; \ + fi + + @if [ ! -p $(installdir)/WiredBot ]; then \ + if [ -e $(installdir)/WiredBot ]; then \ + echo "Error: $(installdir)/WiredBot exists and is not a named pipe"; \ + exit 1; \ + fi; \ + mkfifo -m 660 $(installdir)/WiredBot; \ + chown $(WD_USER):$(WD_GROUP) $(installdir)/WiredBot; \ + fi + $(INSTALL) -m 644 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/wired.xml $(installdir)/ $(INSTALL) -m 755 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/wired $(installdir)/ $(INSTALL) -m 755 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/wiredctl $(installdir)/ diff --git a/Makefile.in b/Makefile.in index 963ebcb..59174b0 100755 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,7 @@ WD_MAINTAINER = @WD_MAINTAINER@ WD_USER = @WD_USER@ WD_GROUP = @WD_GROUP@ -DISTFILES = INSTALL LICENSE NEWS README Makefile Makefile.in \ +DISTFILES = INSTALL LICENSE NEWS README.md Makefile Makefile.in \ config.guess config.status config.h.in config.sub configure \ configure.in install-sh libwired man run thirdparty wired SUBDIRS = libwired @@ -149,6 +149,19 @@ install-wired: $(INSTALL) -m 644 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/banner.png $(installdir)/; \ fi + if [ ! -f $(installdir)/robo.png ]; then \ + $(INSTALL) -m 644 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/robo.png $(installdir)/; \ + fi + + @if [ ! -p $(installdir)/WiredBot ]; then \ + if [ -e $(installdir)/WiredBot ]; then \ + echo "Error: $(installdir)/WiredBot exists and is not a named pipe"; \ + exit 1; \ + fi; \ + mkfifo -m 660 $(installdir)/WiredBot; \ + chown $(WD_USER):$(WD_GROUP) $(installdir)/WiredBot; \ + fi + $(INSTALL) -m 644 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/wired.xml $(installdir)/ $(INSTALL) -m 755 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/wired $(installdir)/ $(INSTALL) -m 755 -o $(WD_USER) -g $(WD_GROUP) $(rundir)/wiredctl $(installdir)/ diff --git a/README.md b/README.md index c2e8aeb..c699881 100755 --- a/README.md +++ b/README.md @@ -19,16 +19,24 @@ These are usually distributed with operating systems. **Debian/Ubuntu** - sudo apt-get install -y build-essential autoconf git libsqlite3-dev libxml2-dev libssl-dev zlib1g-dev + sudo apt-get install -y build-essential autoconf screen git libsqlite3-dev libxml2-dev libssl-dev zlib1g-dev autotools-dev automake + +**Archlinux** + + sudo pacman -Sy base-devel autoconf screen git sqlite3 libxml2 zlib **CentOS 7** - sudo yum -y install git libtool openssl-devel sqlite-devel.x86_64 libxml2-devel zlib-devel autoconf gcc make + sudo yum -y install screen git libtool openssl-devel sqlite-devel.x86_64 libxml2-devel zlib-devel autoconf gcc make **CentOS 8 / Fedora 28/29/30/31 (and probably even older versions of Fedora)** - sudo yum -y install git libtool openssl-devel sqlite-devel libxml2-devel zlib-devel autoconf gcc make + sudo yum -y install screen git libtool openssl-devel sqlite-devel libxml2-devel zlib-devel autoconf gcc make +**openSUSE Leap 42.3 (and probably other Versions)** + + sudo zypper install -t pattern devel_basis + sudo zypper install screen git sqlite3-devel libxml2-devel libz1 openssl-devel ### Getting started @@ -36,7 +44,7 @@ Installing Wired Server from sources will be done using the Autotools standard ( ##### 1. Get Wired Server sources via Terminal (git must be installed!): - git clone https://github.com/nark/wired wired + git clone https://github.com/ProfDrLuigi/wired wired Then move to the `wired` directory: @@ -44,8 +52,7 @@ Then move to the `wired` directory: Initialize and update submodules repositories: - git submodule update --init --recursive --remote - + git clone https://github.com/ProfDrLuigi/libwired libwired libwired/bootstrap Then check that the `libwired` directory was not empty and `configure` file exists. @@ -54,10 +61,14 @@ Then check that the `libwired` directory was not empty and `configure` file exis During the configuration, scripts will check that your environment fills the requirements described at the top of this document. You will be warned if any of the required component is missing on your operating system. -To start configuration, use the following command: +To start configuration for Intel/AMD, use the following command: ./configure +To start configuration for arm64, use the following command: + + ./configure --build=aarch64 --host=aarch64 + Wired Server is designed to be installed into `/usr/local` by default. To change this, run: ./configure --prefix=/path @@ -73,6 +84,8 @@ If you installed OpenSSL in a non-standard path, use the following command examp Use `./configure --help` in order to display more options. + + ##### 4. Compile source code: On GNU-like unices, type: @@ -96,65 +109,183 @@ Or, on BSD-like unices, type: This will require write permissions to `/usr/local/`, or whatever directory you set as the prefix above. Depending of your OS setup, you may require to use `sudo`. -##### 6. Running Wired Server +### WiredBot: file announcements and local chat messages -To start an installed Wired server, run: +Wired Server includes a virtual chat user named **WiredBot**. It can announce +new files and folders from a watched directory and can accept chat messages +from local programs through a named pipe. Both inputs use the same configurable +name, status and icon and post to the public chat like a regular user. - /usr/local/wired/wiredctl start +#### Installed files -By default a user with the login "admin" and no password is created. Use Wired Client or Wire to connect to your newly installed Wired Server. +`make install` prepares these resources in the Wired installation directory: -### Running on Docker +* `robo.png` — the default WiredBot icon. +* `WiredBot` — a named pipe (FIFO), owned by the configured Wired user and + group with mode `0660`. -Pull and run the container: +Existing copies are preserved during updates. Installation stops with an error +instead of overwriting `WiredBot` if that path exists but is not a named pipe. - docker run --name wired -d -p 4871:4871 -v /path/to/yours/files:/files wired2/wired:2.5 +The shipped configuration refers to both resources but keeps the bot disabled +until it is explicitly enabled: -* the `-p` option maps the container port (`4871`) to whatever the port you want to use on your host machine. If you want `wired` to be available on another you can use: `10000:4871` and Docker will translate it. -* the `-v` option maps items of the container file system with your local file system. You can change the first value of the pair to adjust to your server files configuration. Wired Server will look into the `/files` path of the container to index and server your files. +```ini +watch enabled = no +watch pipe = WiredBot +watch icon = robo.png +``` -If you want Docker to start the container automatically for you, add the `--restart always` argument as follow: +#### Complete configuration example - docker run --name wired --restart always -d -p 4871:4871 -v /path/to/yours/files:/files wired2/wired:2.5 +Add or edit the following settings in `/etc/wired.conf`: -Start/stop the container: +```ini +# Enable the virtual user, directory watcher and local message pipe. +watch enabled = yes - docker stop wired - docker start wired - -Remove the container: +# Optional directory monitored recursively for new files and folders. +watch path = files/Uploads - docker rm wired - -It could be useful to backup and restore container files such as `database.sqlite3` or `wired.conf`. You can do that do using the `docker cp` command. - -From container to host: - - docker cp wired:/user/local/wired/database.sqlite3 /path/to/your/database.sqlite3 +# Message used for file and folder announcements. +watch message = New stuff has arrived: $FILE ($SIZE) -From host to container: +# Local FIFO used by scripts and other local processes. +watch pipe = WiredBot - docker cp /path/to/your/database.sqlite3 wired:/user/local/wired/database.sqlite3 - -Build the image locally: +# Identity shown in the public chat user list. +watch name = WiredBot +watch status = Watching for new files +watch icon = robo.png +``` - cd wired/ - docker build --tag wired:2.5 . - -Tag the image: - - docker tag wired2/wired:2.5 - -Push to Docker Hub: - - docker push wired2/wired:2.5 +Relative paths are resolved from the Wired installation directory. Absolute +paths may also be used. After changing the configuration, validate and reload +it without restarting the server: -### Get More +```sh +/wiredctl configtest +/wiredctl reload +``` -If you are interested in the Wired project, check the Website at [http://wired.read-write.fr/](http://wired.read-write.fr) +For example, with Wired installed in `/opt/wired`: -### Troubleshootings +```sh +/opt/wired/wiredctl configtest +/opt/wired/wiredctl reload +``` + +#### Directory watcher behavior + +When `watch path` is configured, the server scans that directory recursively: + +* Items already present when the server starts or reloads its configuration + form the initial baseline and are not announced. +* A new file is announced only after its size and modification time have + stopped changing. +* A newly copied directory is announced once as a directory. Files and nested + directories already arriving inside it are added to the baseline silently + and are not announced individually. +* Files created later inside an already known directory are announced normally. +* Invisible paths are ignored. + +The announcement template supports these placeholders: + +* `$FILE` — path relative to `watch path`. +* `$SIZE` — formatted file size; for a directory this becomes `folder`. + +Examples: + +```ini +watch message = New stuff has arrived: $FILE +``` + +```ini +watch message = New item: $FILE ($SIZE) +``` + +#### Sending messages from Debian programs + +Every newline-terminated line written to the FIFO becomes one public-chat +message from WiredBot. With Wired installed in `/opt/wired`, use: + +```sh +echo "Hello World." > /opt/wired/WiredBot +``` + +Multiple lines produce multiple chat messages: + +```sh +printf 'First message\nSecond message\n' > /opt/wired/WiredBot +``` + +Programs running as another Unix user require write permission through the +FIFO's owner or group. Prefer adding that user to the configured Wired group +instead of making the pipe world-writable. -This implementation of the Wired 2.0 protocol is not compliant with the version of the protocol distributed by Zanka Software, for several deep technical reasons. +Messages may contain HTML supported by Wired Client. Two convenience aliases +are also accepted: +* `...` creates a neutral message container. +* `...` renders its contents in bold. + +For example: + +```sh +echo '☹️ Hello' > /opt/wired/WiredBot +``` + +This is delivered as: + +```html +☹️ Hello +``` + +HTML display must be enabled in the receiving Wired Client. Because FIFO input +may contain HTML, grant write access only to trusted local users and services. +Messages larger than 64 KiB are discarded. + +#### Changing the bot identity + +The virtual user's appearance is controlled entirely through `wired.conf`: + +```ini +watch name = Wired Server +watch status = File notifications +watch icon = robo.png +``` + +The icon may use a relative path below the Wired installation directory or an +absolute path. Identity changes take effect after `wiredctl reload` and are +broadcast to connected clients. + +#### Disabling WiredBot + +To remove the virtual user from the public chat and stop both the directory +watcher and FIFO processing, set: + +```ini +watch enabled = no +``` + +Then reload the configuration. The FIFO may remain in the installation +directory so it is immediately available the next time the bot is enabled. + +##### 6. Running Wired Server + +By default a user with the login "admin" and no password is created. Use Wired Client or Wire to connect to your newly installed Wired Server. + +Wired is compiled as foreground Task in Debug mode. Thats why you nee to run it in a screen-Session. +If you run it in Daemon Mode your CPU will going crazy after some time (100% usage). + +To start an installed Wired server, run: + + ./wiredctl start + +### Get More + +If you are interested in the Wired project, check the Website at [https://wired.read-write.fr/](https://wired.read-write.fr) + +### Troubleshootings +This implementation of the Wired 2.0/2.5 protocol is not compliant with the version of the protocol distributed by Zanka Software, for several deep technical reasons. diff --git a/config.h b/config.h index 15d8ee0..bdc08b0 100644 --- a/config.h +++ b/config.h @@ -95,7 +95,7 @@ #define WD_VERSION "2.5" /* Subversion revision */ -#define WI_REVISION "2.5.2" +#define WI_REVISION "2.5.3" /* SQLite does not support backup */ #define WI_SQLITE_SUPPORTS_BACKUP 1 diff --git a/config.sub b/config.sub index 1f31816..38f3d03 100755 --- a/config.sub +++ b/config.sub @@ -1,42 +1,42 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +# Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2003-08-18' +# shellcheck disable=SC2006,SC2268 # see below for rationale -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +timestamp='2021-10-27' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - +# along with this program; if not, see . +# # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -52,15 +52,21 @@ timestamp='2003-08-18' # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -70,8 +76,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright 1992-2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -83,23 +88,23 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" + echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. - echo $1 - exit 0;; + echo "$1" + exit ;; * ) break ;; @@ -114,984 +119,1181 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +# shellcheck disable=SC2162 +saved_IFS=$IFS +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + zephyr*) + basic_machine=$field1-unknown + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac ;; - -clix*) - basic_machine=clipper-intergraph + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` +esac + +# Decode 1-component or ad-hoc basic machines +case $basic_machine in + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - -lynx*) - os=-lynxos + op50n) + cpu=hppa1.1 + vendor=oki ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + op60c) + cpu=hppa1.1 + vendor=oki ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + ibm*) + cpu=i370 + vendor=ibm ;; - -psos*) - os=-psos + orion105) + cpu=clipper + vendor=highlevel ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | msp430 \ - | ns16k | ns32k \ - | openrisc | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ - | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xscale | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | m32r-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | msp430-* \ - | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ - | xtensa-* \ - | ymp-* \ - | z8k-*) - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att + cpu=m68000 + vendor=att ;; 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 + cpu=we32k + vendor=att ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec + bluegene*) + cpu=powerpc + vendor=ibm + basic_os=cnk ;; decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 + cpu=pdp10 + vendor=dec + basic_os=tops10 ;; decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 + cpu=pdp10 + vendor=dec + basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 + cpu=m68k + vendor=motorola ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd + dpx2*) + cpu=m68k + vendor=bull + basic_os=sysv3 ;; encore | umax | mmax) - basic_machine=ns32k-encore + cpu=ns32k + vendor=encore ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} ;; fx2800) - basic_machine=i860-alliant + cpu=i860 + vendor=alliant ;; genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 + cpu=ns32k + vendor=ns ;; h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp + cpu=m68000 + vendor=hp ;; hp9k3[2-9][0-9]) - basic_machine=m68k-hp + cpu=m68k + vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} ;; iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) + cpu=mips + vendor=sgi + case $basic_os in + irix*) ;; *) - os=-irix4 + basic_os=irix4 ;; esac ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos + cpu=m68000 + vendor=convergent ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint ;; news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) + cpu=mips + vendor=sony + basic_os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) ;; - -ns2*) - os=-nextstep2 + ns2*) + basic_os=nextstep2 ;; *) - os=-nextstep3 + basic_os=nextstep3 ;; esac ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; np1) - basic_machine=np1-gould - ;; - nv1) - basic_machine=nv1-cray - os=-unicosmp - ;; - nsr-tandem) - basic_machine=nsr-tandem + cpu=np1 + vendor=gould ;; op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - or32 | or32-*) - basic_machine=or32-unknown - os=-coff - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k + cpu=hppa1.1 + vendor=oki + basic_os=proelf ;; pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; pbd) - basic_machine=sparc-tti + cpu=sparc + vendor=tti ;; pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc + cpu=m68k + vendor=tti ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + pc532) + cpu=ns32k + vendor=pc532 ;; pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + cpu=pn + vendor=gould ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + power) + cpu=power + vendor=ibm ;; ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff + cpu=i386 + vendor=ibm ;; rm[46]00) - basic_machine=mips-siemens + cpu=mips + vendor=siemens ;; rtpc | rtpc-*) - basic_machine=romp-ibm + cpu=romp + vendor=ibm ;; - s390 | s390-*) - basic_machine=s390-ibm + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} ;; - s390x | s390x-*) - basic_machine=s390x-ibm + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks ;; - sa29200) - basic_machine=a29k-amd - os=-udi + tower | tower-32) + cpu=m68k + vendor=ncr ;; - sb1) - basic_machine=mipsisa64sb1-unknown + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown + w65) + cpu=w65 + vendor=wdc ;; - sei) - basic_machine=mips-sei - os=-seiux + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf ;; - sequent) - basic_machine=i386-sequent + none) + cpu=none + vendor=none ;; - sh) - basic_machine=sh-hitachi - os=-hms + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine ;; - sh64) - basic_machine=sh64-unknown + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks + + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read cpu vendor <&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb | arc32 | arc64 \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | loongarch32 | loongarch64 | loongarchx32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r3 | mipsisa32r3el \ + | mipsisa32r5 | mipsisa32r5el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r3 | mipsisa64r3el \ + | mipsisa64r5 | mipsisa64r5el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv32be | riscv64 | riscv64be \ + | rl78 | romp | rs6000 | rx \ + | s390 | s390x \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | thumbv7* \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1099,177 +1301,215 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if test x$basic_os != x then + +# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` + ;; + os2-emx) + kernel=os2 + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` + ;; + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read kernel os <&2 - exit 1 + # No normalization, but not necessarily accepted, that comes below. ;; esac + else # Here we handle the default operating systems that come with various machines. @@ -1282,228 +1522,363 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +kernel= +case $cpu-$vendor in + score-*) + os=elf + ;; + spu-*) + os=elf + ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + kernel=linux + os=gnu ;; arm*-semi) - os=-aout + os=aout + ;; + c4x-* | tic4x-*) + os=coff + ;; + c8051-*) + os=elf + ;; + clipper-intergraph) + os=clix + ;; + hexagon-*) + os=elf + ;; + tic54x-*) + os=coff + ;; + tic55x-*) + os=coff + ;; + tic6x-*) + os=coff ;; - c4x-* | tic4x-*) - os=-coff - ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout + ;; + mep-*) + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 + ;; + pru-*) + os=elf ;; *-be) - os=-beos + os=beos ;; *-ibm) - os=-aix + os=aix + ;; + *-knuth) + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna + os=luna ;; - *-next ) - os=-nextstep + *-next) + os=nextstep ;; *-sequent) - os=-ptx + os=ptx ;; *-crds) - os=-unos + os=unos ;; *-ns) - os=-genix + os=genix ;; i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac + fi +# Now, validate our (potentially fixed-up) OS. +case $os in + # Sometimes we do "kernel-libc", so those need to count as OSes. + musl* | newlib* | relibc* | uclibc*) + ;; + # Likewise for "kernel-abi" + eabi* | gnueabi*) + ;; + # VxWorks passes extra cpu info in the 4th filed. + simlinux | simwindows | spe) + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ + | os9* | macos* | osx* | ios* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | mint* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ + | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ + | fiwix* ) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + none) + ;; + *) + echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ + | linux-musl* | linux-relibc* | linux-uclibc* ) + ;; + uclinux-uclibc* ) + ;; + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + vxworks-simlinux | vxworks-simwindows | vxworks-spe) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) vendor=acorn ;; - -sunos*) + *-sunos*) vendor=sun ;; - -aix*) + *-cnk* | *-aix*) vendor=ibm ;; - -beos*) + *-beos*) vendor=be ;; - -hpux*) + *-hpux*) vendor=hp ;; - -mpeix*) + *-mpeix*) vendor=hp ;; - -hiux*) + *-hiux*) vendor=hitachi ;; - -unos*) + *-unos*) vendor=crds ;; - -dgux*) + *-dgux*) vendor=dg ;; - -luna*) + *-luna*) vendor=omron ;; - -genix*) + *-genix*) vendor=ns ;; - -mvs* | -opened*) + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) vendor=ibm ;; - -ptx*) + *-os400*) + vendor=ibm + ;; + s390-* | s390x-*) + vendor=ibm + ;; + *-ptx*) vendor=sequent ;; - -vxsim* | -vxworks* | -windiss*) + *-tpf*) + vendor=ibm + ;; + *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; - -aux*) + *-aux*) vendor=apple ;; - -hms*) + *-hms*) vendor=hitachi ;; - -mpw* | -macos*) + *-mpw* | *-macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; - -vos*) + *-vos*) vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os -exit 0 +echo "$cpu-$vendor-${kernel:+$kernel-}$os" +exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/configure.in b/configure.ac similarity index 100% rename from configure.in rename to configure.ac diff --git a/libwired b/libwired deleted file mode 160000 index df759f4..0000000 --- a/libwired +++ /dev/null @@ -1 +0,0 @@ -Subproject commit df759f4215040cea6c4bd2b67ba86824c144d463 diff --git a/man/wired.conf.5 b/man/wired.conf.5 index d93770e..ecac487 100755 --- a/man/wired.conf.5 +++ b/man/wired.conf.5 @@ -76,6 +76,38 @@ Example: description = My Wired Server Path to the files directory. .Pp Example: files = files +.It Va watch path +Path to a directory that is recursively monitored for new files and folders. New items are announced in the public chat after they have stopped changing. If a populated folder is added, only the folder itself is announced; its existing contents are silently added to the baseline. Items already present when the server starts or the setting is reloaded are used as the initial baseline and are not announced. +.Pp +Example: watch path = files/Uploads +.It Va watch enabled +If set to yes, enables the virtual user, the configured watch path and the local message pipe. If set to no, removes the virtual user from the public chat and stops both inputs. +.Pp +Example: watch enabled = no +.It Va watch pipe +Path to a named pipe used to send messages to the public chat through the virtual user. The server creates the pipe when needed. Each newline-terminated line written to it is sent as one chat message. Relative paths are resolved from the Wired server directory. HTML may be used for formatted messages. The aliases ... and ... are converted to a neutral HTML container and bold text. The pipe is inactive when watch enabled is set to no. +.Pp +Example: watch pipe = WiredBot +.Pp +Shell example: echo "Hello World." > /opt/wired/WiredBot +.Pp +Formatted example: echo '☹️ Hello' > /opt/wired/WiredBot +.It Va watch message +Text sent to the public chat when a new item is detected. The placeholder $FILE is replaced with the relative path. For files, $SIZE is replaced with the formatted file size; for folders it is replaced with the word "folder". +.Pp +Example: watch message = New stuff has arrived: $FILE +.It Va watch name +Name of the virtual user that announces new items in the public chat. +.Pp +Example: watch name = Wired Server +.It Va watch status +Status of the virtual user that announces new items in the public chat. +.Pp +Example: watch status = File notifications +.It Va watch icon +Path to the image used as the icon of the virtual user. Relative paths are resolved from the Wired server directory. Leave this setting empty to use no icon. +.Pp +Example: watch icon = file-notifier.png .It Va group Name or id of the group that .Xr wired 8 diff --git a/run/robo.png b/run/robo.png new file mode 100644 index 0000000..bd8024b Binary files /dev/null and b/run/robo.png differ diff --git a/test/transfertest/main.c b/test/transfertest/main.c index ec1b7a5..c1fe9c8 100755 --- a/test/transfertest/main.c +++ b/test/transfertest/main.c @@ -401,7 +401,7 @@ static wi_p7_socket_t * wc_connect(wi_url_t *url) { if(!wi_p7_socket_connect(p7_socket, 10.0, - WI_P7_ENCRYPTION_RSA_AES256_SHA1 | WI_P7_CHECKSUM_SHA1, + WI_P7_ENCRYPTION_RSA_AES256_SHA512 | WI_P7_CHECKSUM_SHA512, WI_P7_BINARY, wi_url_user(url), wi_string_sha1(wi_url_password(url)))) { @@ -431,7 +431,7 @@ static wi_boolean_t wc_login(wi_p7_socket_t *socket, wi_url_t *url) { message = wi_p7_message_with_name(WI_STR("wired.client_info"), wc_spec); wi_p7_message_set_string_for_name(message, WI_STR("transfertest"), WI_STR("wired.info.application.name")); wi_p7_message_set_string_for_name(message, WI_STR("1.0"), WI_STR("wired.info.application.version")); - wi_p7_message_set_uint32_for_name(message, 1, WI_STR("wired.info.application.build")); + wi_p7_message_set_string_for_name(message, WI_STR("1"), WI_STR("wired.info.application.build")); wi_p7_message_set_string_for_name(message, wi_process_os_name(wi_process()), WI_STR("wired.info.os.name")); wi_p7_message_set_string_for_name(message, wi_process_os_release(wi_process()), WI_STR("wired.info.os.version")); wi_p7_message_set_string_for_name(message, wi_process_os_arch(wi_process()), WI_STR("wired.info.arch")); diff --git a/version b/version index 21b159d..aedc15b 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.5.2 \ No newline at end of file +2.5.3 diff --git a/wired/accounts.c b/wired/accounts.c index 21a0391..feed651 100644 --- a/wired/accounts.c +++ b/wired/accounts.c @@ -916,7 +916,7 @@ void wd_accounts_add_download_statistics(wd_account_t *account, wi_boolean_t fin "download_transferred = download_transferred + ? " "WHERE name = ?"), WI_INT32(finished ? 1 : 0), - WI_INT32(transferred), + wi_number_with_int64((int64_t) transferred), wd_account_name(account), NULL)) { wi_log_error(WI_STR("Could not execute database statement: %m")); @@ -931,7 +931,7 @@ void wd_accounts_add_upload_statistics(wd_account_t *account, wi_boolean_t finis "upload_transferred = upload_transferred + ? " "WHERE name = ?"), WI_INT32(finished ? 1 : 0), - WI_INT32(transferred), + wi_number_with_int64((int64_t) transferred), wd_account_name(account), NULL)) { wi_log_error(WI_STR("Could not execute database statement: %m")); @@ -2033,7 +2033,7 @@ static wi_string_t * wd_account_sqlite3_insert_string(wd_account_t *account, wi_ case WD_ACCOUNT_FIELD_NUMBER: case WD_ACCOUNT_FIELD_BOOLEAN: case WD_ACCOUNT_FIELD_ENUM: - wi_mutable_string_append_format(sqlvalues, WI_STR("%u"), wi_number_integer(value)); + wi_mutable_string_append_format(sqlvalues, WI_STR("%lld"), (long long) wi_number_integer(value)); break; case WD_ACCOUNT_FIELD_LIST: @@ -2084,7 +2084,7 @@ static wi_string_t * wd_account_sqlite3_update_string(wd_account_t *account, wi_ case WD_ACCOUNT_FIELD_NUMBER: case WD_ACCOUNT_FIELD_BOOLEAN: - wi_mutable_string_append_format(string, WI_STR("%u"), wi_number_integer(value)); + wi_mutable_string_append_format(string, WI_STR("%lld"), (long long) wi_number_integer(value)); break; case WD_ACCOUNT_FIELD_LIST: diff --git a/wired/chats.c b/wired/chats.c index ccb16ce..500ee60 100644 --- a/wired/chats.c +++ b/wired/chats.c @@ -33,6 +33,7 @@ #include "chats.h" #include "server.h" +#include "watch.h" #define WD_PUBLIC_CHAT_ID 1 @@ -408,6 +409,8 @@ void wd_chat_reply_user_list(wd_chat_t *chat, wd_user_t *user, wi_p7_message_t * wi_array_unlock(chat->users); + wd_watch_reply_user_list(chat, user, message); + reply = wi_p7_message_with_name(WI_STR("wired.chat.user_list.done"), wd_p7_spec); wi_p7_message_set_uint32_for_name(reply, chat->id, WI_STR("wired.chat.id")); wd_user_reply_message(user, reply, message); diff --git a/wired/main.c b/wired/main.c index 885eb76..2e98f1b 100644 --- a/wired/main.c +++ b/wired/main.c @@ -52,6 +52,7 @@ #include "settings.h" #include "trackers.h" #include "transfers.h" +#include "watch.h" static void wd_cleanup(void); static void wd_usage(void); @@ -256,6 +257,7 @@ int main(int argc, const char **argv) { wd_settings_initialize(); wd_trackers_initialize(); wd_transfers_initialize(); + wd_watch_initialize(); if(!wd_settings_read_config()) exit(1); @@ -611,5 +613,5 @@ static void wd_schedule(void) { wd_trackers_schedule(); wd_transfers_schedule(); wd_users_schedule(); + wd_watch_schedule(); } - diff --git a/wired/settings.c b/wired/settings.c index 3e3994f..a7283b2 100644 --- a/wired/settings.c +++ b/wired/settings.c @@ -36,6 +36,7 @@ #include "settings.h" #include "trackers.h" #include "transfers.h" +#include "watch.h" wi_config_t *wd_config; @@ -69,6 +70,13 @@ void wd_settings_initialize(void) { WI_INT32(WI_CONFIG_INTEGER), WI_STR("total uploads"), WI_INT32(WI_CONFIG_STRINGLIST), WI_STR("tracker"), WI_INT32(WI_CONFIG_USER), WI_STR("user"), + WI_INT32(WI_CONFIG_BOOL), WI_STR("watch enabled"), + WI_INT32(WI_CONFIG_PATH), WI_STR("watch icon"), + WI_INT32(WI_CONFIG_STRING), WI_STR("watch message"), + WI_INT32(WI_CONFIG_STRING), WI_STR("watch name"), + WI_INT32(WI_CONFIG_PATH), WI_STR("watch path"), + WI_INT32(WI_CONFIG_PATH), WI_STR("watch pipe"), + WI_INT32(WI_CONFIG_STRING), WI_STR("watch status"), NULL); defaults = wi_dictionary_with_data_and_keys( @@ -95,6 +103,13 @@ void wd_settings_initialize(void) { WI_INT32(10), WI_STR("total uploads"), wi_array(), WI_STR("tracker"), WI_STR("wired"), WI_STR("user"), + wi_number_with_bool(false), WI_STR("watch enabled"), + WI_STR(""), WI_STR("watch icon"), + WI_STR("New file available: $FILE ($SIZE)"), WI_STR("watch message"), + WI_STR("Wired Server"), WI_STR("watch name"), + WI_STR(""), WI_STR("watch path"), + WI_STR(""), WI_STR("watch pipe"), + WI_STR("File notifications"), WI_STR("watch status"), NULL); wd_config = wi_config_init_with_path(wi_config_alloc(), wd_config_path, types, defaults); @@ -123,6 +138,7 @@ void wd_settings_apply_settings(wi_set_t *changes) { wd_server_apply_settings(changes); wd_trackers_apply_settings(changes); wd_transfers_apply_settings(changes); + wd_watch_apply_settings(changes); } diff --git a/wired/watch.c b/wired/watch.c new file mode 100644 index 0000000..5b80469 --- /dev/null +++ b/wired/watch.c @@ -0,0 +1,754 @@ +/* $Id$ */ + +/* + * Copyright (c) 2003-2009 Axel Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "chats.h" +#include "files.h" +#include "server.h" +#include "settings.h" +#include "watch.h" + +#define WD_WATCH_INTERVAL 2.0 +#define WD_WATCH_USER_ID 0 +#define WD_WATCH_USER_COLOR 4 +#define WD_WATCH_DEFAULT_MESSAGE "New file available: $FILE ($SIZE)" +#define WD_WATCH_DEFAULT_NAME "Wired Server" +#define WD_WATCH_DEFAULT_STATUS "File notifications" +#define WD_WATCH_PIPE_BUFFER_SIZE 65536 + + +static void wd_watch_scan(wi_timer_t *); +static void wd_watch_announce_path(wi_string_t *, wi_string_t *); +static wi_boolean_t wd_watch_path_is_descendant_of_path(wi_string_t *, wi_string_t *); +static int wd_watch_open_pipe(wi_string_t *); +static void wd_watch_drain_pipe(void); +static wi_string_t * wd_watch_normalize_pipe_markup(wi_string_t *); +static void wd_watch_broadcast_text(wi_string_t *); +static void wd_watch_broadcast_user_join(void); +static void wd_watch_broadcast_user_leave(void); +static void wd_watch_broadcast_user_status(void); +static void wd_watch_broadcast_user_icon(void); +static void wd_watch_set_user_fields(wi_p7_message_t *, wd_chat_t *); + + +static wi_lock_t *wd_watch_lock; +static wi_timer_t *wd_watch_timer; +static wi_string_t *wd_watch_path; +static wi_string_t *wd_watch_message; +static wi_string_t *wd_watch_name; +static wi_string_t *wd_watch_status; +static wi_data_t *wd_watch_icon; +static wi_mutable_dictionary_t *wd_watch_known_files; +static wi_mutable_dictionary_t *wd_watch_candidates; +static char wd_watch_pipe_buffer[WD_WATCH_PIPE_BUFFER_SIZE]; +static wi_uinteger_t wd_watch_pipe_buffer_length; +static int wd_watch_pipe_fd; +static wi_boolean_t wd_watch_pipe_overflow; +static wi_boolean_t wd_watch_enabled; +static wi_boolean_t wd_watch_baseline_pending; + + + +void wd_watch_initialize(void) { + wd_watch_lock = wi_lock_init(wi_lock_alloc()); + wd_watch_timer = wi_timer_init_with_function(wi_timer_alloc(), wd_watch_scan, 0.0, true); + wd_watch_known_files = wi_dictionary_init(wi_mutable_dictionary_alloc()); + wd_watch_candidates = wi_dictionary_init(wi_mutable_dictionary_alloc()); + wd_watch_pipe_fd = -1; +} + + + +void wd_watch_apply_settings(wi_set_t *changes) { + wi_string_t *configured_path, *configured_message, *configured_name; + wi_string_t *configured_status, *configured_icon, *configured_pipe, *realpath; + wi_string_t *name, *status; + wi_data_t *icon; + wi_boolean_t configured_enabled, directory, enabled, changed, was_enabled; + wi_boolean_t status_changed, icon_changed; + int pipe_fd, old_pipe_fd; + + configured_path = wi_config_path_for_name(wd_config, WI_STR("watch path")); + configured_message = wi_config_string_for_name(wd_config, WI_STR("watch message")); + configured_name = wi_config_string_for_name(wd_config, WI_STR("watch name")); + configured_status = wi_config_string_for_name(wd_config, WI_STR("watch status")); + configured_icon = wi_config_path_for_name(wd_config, WI_STR("watch icon")); + configured_pipe = wi_config_path_for_name(wd_config, WI_STR("watch pipe")); + configured_enabled = wi_config_bool_for_name(wd_config, WI_STR("watch enabled")); + realpath = NULL; + icon = wi_data(); + enabled = configured_enabled; + pipe_fd = -1; + + name = configured_name && wi_string_length(configured_name) > 0 + ? configured_name + : WI_STR(WD_WATCH_DEFAULT_NAME); + status = configured_status ? configured_status : WI_STR(WD_WATCH_DEFAULT_STATUS); + + if(configured_icon && wi_string_length(configured_icon) > 0) { + icon = wi_data_with_contents_of_file(configured_icon); + + if(!icon) { + wi_log_warn(WI_STR("Could not read watch icon \"%@\": %m"), configured_icon); + icon = wi_data(); + } + } + + if(configured_enabled && configured_path && wi_string_length(configured_path) > 0) { + realpath = wi_fs_real_path_for_path(configured_path); + + if(!realpath || !wi_fs_path_exists(realpath, &directory) || !directory) { + wi_log_warn(WI_STR("Could not watch \"%@\": path is not a directory"), configured_path); + realpath = NULL; + } + } + + if(configured_enabled && configured_pipe && wi_string_length(configured_pipe) > 0) + pipe_fd = wd_watch_open_pipe(configured_pipe); + + wi_lock_lock(wd_watch_lock); + + wi_release(wd_watch_message); + wd_watch_message = wi_retain(configured_message && wi_string_length(configured_message) > 0 + ? configured_message + : WI_STR(WD_WATCH_DEFAULT_MESSAGE)); + + status_changed = !wd_watch_name || !wi_is_equal(wd_watch_name, name) || + !wd_watch_status || !wi_is_equal(wd_watch_status, status); + icon_changed = !wd_watch_icon || !wi_is_equal(wd_watch_icon, icon); + + wi_release(wd_watch_name); + wd_watch_name = wi_retain(name); + + wi_release(wd_watch_status); + wd_watch_status = wi_retain(status); + + wi_release(wd_watch_icon); + wd_watch_icon = wi_retain(icon); + + old_pipe_fd = wd_watch_pipe_fd; + wd_watch_pipe_fd = pipe_fd; + + wd_watch_pipe_buffer_length = 0; + wd_watch_pipe_overflow = false; + + was_enabled = wd_watch_enabled; + changed = (enabled != wd_watch_enabled); + + if(!changed && enabled) { + if(wd_watch_path || realpath) + changed = !wd_watch_path || !realpath || !wi_is_equal(wd_watch_path, realpath); + } + + if(changed) { + wi_release(wd_watch_path); + wd_watch_path = enabled && realpath ? wi_retain(realpath) : NULL; + wd_watch_enabled = enabled; + wd_watch_baseline_pending = enabled && realpath; + + wi_mutable_dictionary_remove_all_data(wd_watch_known_files); + wi_mutable_dictionary_remove_all_data(wd_watch_candidates); + } + + wi_lock_unlock(wd_watch_lock); + + if(old_pipe_fd >= 0) + close(old_pipe_fd); + + if(!was_enabled && enabled) { + if(realpath) + wi_log_info(WI_STR("Watching \"%@\" for new items"), realpath); + + wd_watch_broadcast_user_join(); + } else if(was_enabled && !enabled) { + wi_log_info(WI_STR("Stopped watching for new items")); + wd_watch_broadcast_user_leave(); + } else if(changed && enabled && realpath) { + wi_log_info(WI_STR("Now watching \"%@\" for new items"), realpath); + } + + if(pipe_fd >= 0) + wi_log_info(WI_STR("Accepting chat messages from pipe \"%@\""), configured_pipe); + + if(was_enabled && enabled) { + if(status_changed) + wd_watch_broadcast_user_status(); + + if(icon_changed) + wd_watch_broadcast_user_icon(); + } +} + + + +void wd_watch_schedule(void) { + wi_boolean_t enabled; + + wi_lock_lock(wd_watch_lock); + enabled = wd_watch_enabled; + wi_lock_unlock(wd_watch_lock); + + if(enabled) + wi_timer_reschedule(wd_watch_timer, WD_WATCH_INTERVAL); + else + wi_timer_invalidate(wd_watch_timer); +} + + + +#pragma mark - + +static void wd_watch_scan(wi_timer_t *timer) { + wi_pool_t *pool; + wi_fsenumerator_t *fsenumerator; + wi_fsenumerator_status_t status; + wi_mutable_dictionary_t *current_inodes, *current_signatures, *current_directories; + wi_mutable_array_t *announcements, *unknown_directories, *new_directories; + wi_array_t *keys; + wi_enumerator_t *enumerator; + wi_string_t *path, *filepath, *key, *signature, *candidate, *directorypath; + wi_mutable_string_t *directory_signature; + wi_number_t *inode, *known_inode; + wi_fs_stat_t sb; + wi_uinteger_t i, j, count, directory_count; + wi_boolean_t enabled, baseline, has_new_parent, suppress_announcement; + + pool = wi_pool_init(wi_pool_alloc()); + + wi_lock_lock(wd_watch_lock); + enabled = wd_watch_enabled; + path = enabled ? wi_retain(wd_watch_path) : NULL; + wi_lock_unlock(wd_watch_lock); + + if(!enabled) { + wi_release(path); + wi_release(pool); + return; + } + + wd_watch_drain_pipe(); + + if(!path) { + wi_release(pool); + return; + } + + current_inodes = wi_mutable_dictionary(); + current_signatures = wi_mutable_dictionary(); + current_directories = wi_mutable_dictionary(); + announcements = wi_mutable_array(); + unknown_directories = wi_mutable_array(); + new_directories = wi_mutable_array(); + fsenumerator = wi_fs_enumerator_at_path(path); + + if(!fsenumerator) { + wi_log_error(WI_STR("Could not scan watched path \"%@\": %m"), path); + wi_release(path); + wi_release(pool); + return; + } + + while((status = wi_fsenumerator_get_next_path(fsenumerator, &filepath)) != WI_FSENUMERATOR_EOF) { + if(status == WI_FSENUMERATOR_ERROR) { + wi_log_error(WI_STR("Could not scan watched path \"%@\": %m"), filepath); + continue; + } + + if(wi_fs_path_is_invisible(filepath)) { + wi_fsenumerator_skip_descendents(fsenumerator); + continue; + } + + if(!wi_fs_lstat_path(filepath, &sb)) + continue; + + if(!S_ISREG(sb.mode) && !S_ISDIR(sb.mode)) + continue; + + inode = wi_number_with_int64((int64_t) sb.ino); + signature = wi_string_with_format(WI_STR("%c:%llu:%llu:%u"), + S_ISDIR(sb.mode) ? 'd' : 'f', sb.ino, sb.size, sb.mtime); + + wi_mutable_dictionary_set_data_for_key(current_inodes, inode, filepath); + + if(S_ISDIR(sb.mode)) { + directory_signature = wi_mutable_copy(signature); + wi_mutable_dictionary_set_data_for_key(current_signatures, directory_signature, filepath); + wi_mutable_dictionary_set_data_for_key(current_directories, wi_number_with_bool(true), filepath); + wi_release(directory_signature); + } else { + wi_mutable_dictionary_set_data_for_key(current_signatures, signature, filepath); + } + + /* + * A directory is stable only when its complete subtree is stable. This + * keeps a directory pending while files are still being copied into it. + */ + enumerator = wi_dictionary_key_enumerator(current_directories); + + while((directorypath = wi_enumerator_next_data(enumerator))) { + if(wd_watch_path_is_descendant_of_path(filepath, directorypath)) { + directory_signature = wi_dictionary_data_for_key(current_signatures, directorypath); + wi_mutable_string_append_format(directory_signature, WI_STR("|%@"), signature); + } + } + } + + wi_lock_lock(wd_watch_lock); + + if(!wd_watch_enabled || !wd_watch_path || !wi_is_equal(wd_watch_path, path)) { + wi_lock_unlock(wd_watch_lock); + wi_release(path); + wi_release(pool); + return; + } + + baseline = wd_watch_baseline_pending; + + if(baseline) { + wi_mutable_dictionary_set_dictionary(wd_watch_known_files, current_inodes); + wi_mutable_dictionary_remove_all_data(wd_watch_candidates); + wd_watch_baseline_pending = false; + + wi_log_info(WI_STR("Initialized watched path with %u existing items"), wi_dictionary_count(current_inodes)); + } else { + keys = wi_dictionary_all_keys(wd_watch_known_files); + count = wi_array_count(keys); + + for(i = 0; i < count; i++) { + key = WI_ARRAY(keys, i); + + if(!wi_dictionary_contains_key(current_inodes, key)) + wi_mutable_dictionary_remove_data_for_key(wd_watch_known_files, key); + } + + keys = wi_dictionary_all_keys(wd_watch_candidates); + count = wi_array_count(keys); + + for(i = 0; i < count; i++) { + key = WI_ARRAY(keys, i); + + if(!wi_dictionary_contains_key(current_signatures, key)) + wi_mutable_dictionary_remove_data_for_key(wd_watch_candidates, key); + } + + /* + * Find the outermost newly-created directories. Their complete current + * contents are adopted as known below so copying a populated directory + * results in one announcement for the directory, not one per child. + */ + enumerator = wi_dictionary_key_enumerator(current_directories); + + while((filepath = wi_enumerator_next_data(enumerator))) { + inode = wi_dictionary_data_for_key(current_inodes, filepath); + known_inode = wi_dictionary_data_for_key(wd_watch_known_files, filepath); + + if(!known_inode || !wi_is_equal(known_inode, inode)) + wi_mutable_array_add_data(unknown_directories, filepath); + } + + directory_count = wi_array_count(unknown_directories); + + for(i = 0; i < directory_count; i++) { + filepath = WI_ARRAY(unknown_directories, i); + has_new_parent = false; + + for(j = 0; j < directory_count; j++) { + directorypath = WI_ARRAY(unknown_directories, j); + + if(i != j && wd_watch_path_is_descendant_of_path(filepath, directorypath)) { + has_new_parent = true; + break; + } + } + + if(!has_new_parent) + wi_mutable_array_add_data(new_directories, filepath); + } + + enumerator = wi_dictionary_key_enumerator(current_inodes); + + while((filepath = wi_enumerator_next_data(enumerator))) { + inode = wi_dictionary_data_for_key(current_inodes, filepath); + known_inode = wi_dictionary_data_for_key(wd_watch_known_files, filepath); + + if(known_inode && wi_is_equal(known_inode, inode)) + continue; + + suppress_announcement = false; + directory_count = wi_array_count(new_directories); + + for(i = 0; i < directory_count; i++) { + directorypath = WI_ARRAY(new_directories, i); + + if(wd_watch_path_is_descendant_of_path(filepath, directorypath)) { + suppress_announcement = true; + break; + } + } + + if(suppress_announcement) { + wi_mutable_dictionary_set_data_for_key(wd_watch_known_files, inode, filepath); + wi_mutable_dictionary_remove_data_for_key(wd_watch_candidates, filepath); + continue; + } + + signature = wi_dictionary_data_for_key(current_signatures, filepath); + candidate = wi_dictionary_data_for_key(wd_watch_candidates, filepath); + + if(candidate && wi_is_equal(candidate, signature)) { + wi_mutable_dictionary_set_data_for_key(wd_watch_known_files, inode, filepath); + wi_mutable_dictionary_remove_data_for_key(wd_watch_candidates, filepath); + wi_mutable_array_add_data(announcements, filepath); + } else { + wi_mutable_dictionary_set_data_for_key(wd_watch_candidates, signature, filepath); + } + } + } + + wi_lock_unlock(wd_watch_lock); + + count = wi_array_count(announcements); + + for(i = 0; i < count; i++) + wd_watch_announce_path(WI_ARRAY(announcements, i), path); + + wi_release(path); + wi_pool_drain(pool); + wi_release(pool); +} + + + +static int wd_watch_open_pipe(wi_string_t *path) { + struct stat sb; + const char *cstring; + int fd; + + cstring = wi_string_cstring(path); + + if(lstat(cstring, &sb) < 0) { + if(errno != ENOENT) { + wi_log_warn(WI_STR("Could not inspect watch pipe \"%@\": %m"), path); + return -1; + } + + if(mkfifo(cstring, 0660) < 0) { + wi_log_warn(WI_STR("Could not create watch pipe \"%@\": %m"), path); + return -1; + } + + if(chmod(cstring, 0660) < 0) + wi_log_warn(WI_STR("Could not set permissions on watch pipe \"%@\": %m"), path); + } else if(!S_ISFIFO(sb.st_mode)) { + wi_log_warn(WI_STR("Could not use watch pipe \"%@\": path is not a named pipe"), path); + return -1; + } + + fd = open(cstring, O_RDONLY | O_NONBLOCK); + + if(fd < 0) { + wi_log_warn(WI_STR("Could not open watch pipe \"%@\": %m"), path); + return -1; + } + + return fd; +} + + + +static void wd_watch_drain_pipe(void) { + wi_mutable_array_t *messages; + wi_enumerator_t *enumerator; + wi_string_t *message, *formatted_message; + char buffer[4096]; + ssize_t bytes; + wi_uinteger_t i, length; + int error; + wi_boolean_t overflowed; + + messages = wi_mutable_array(); + error = 0; + overflowed = false; + + wi_lock_lock(wd_watch_lock); + + while(wd_watch_pipe_fd >= 0) { + bytes = read(wd_watch_pipe_fd, buffer, sizeof(buffer)); + + if(bytes < 0) { + if(errno == EINTR) + continue; + + if(errno != EAGAIN && errno != EWOULDBLOCK) + error = errno; + + break; + } + + if(bytes == 0) + break; + + for(i = 0; i < (wi_uinteger_t) bytes; i++) { + if(buffer[i] == '\n') { + if(wd_watch_pipe_overflow) { + wd_watch_pipe_overflow = false; + wd_watch_pipe_buffer_length = 0; + continue; + } + + length = wd_watch_pipe_buffer_length; + + if(length > 0 && wd_watch_pipe_buffer[length - 1] == '\r') + length--; + + if(length > 0) { + message = wi_string_with_bytes(wd_watch_pipe_buffer, length); + wi_mutable_array_add_data(messages, message); + } + + wd_watch_pipe_buffer_length = 0; + } else if(!wd_watch_pipe_overflow) { + if(wd_watch_pipe_buffer_length < WD_WATCH_PIPE_BUFFER_SIZE) { + wd_watch_pipe_buffer[wd_watch_pipe_buffer_length++] = buffer[i]; + } else { + wd_watch_pipe_buffer_length = 0; + wd_watch_pipe_overflow = true; + overflowed = true; + } + } + } + } + + wi_lock_unlock(wd_watch_lock); + + if(error != 0) { + errno = error; + wi_log_warn(WI_STR("Could not read watch pipe: %m")); + } + + if(overflowed) + wi_log_warn(WI_STR("Discarded watch pipe message larger than %u bytes"), WD_WATCH_PIPE_BUFFER_SIZE); + + enumerator = wi_array_data_enumerator(messages); + + while((message = wi_enumerator_next_data(enumerator))) { + formatted_message = wd_watch_normalize_pipe_markup(message); + wd_watch_broadcast_text(formatted_message); + wi_log_info(WI_STR("Announced watch pipe message \"%@\""), formatted_message); + } +} + + + +static wi_string_t * wd_watch_normalize_pipe_markup(wi_string_t *message) { + wi_mutable_string_t *formatted_message; + + formatted_message = wi_mutable_copy(message); + wi_mutable_string_replace_string_with_string(formatted_message, WI_STR(""), WI_STR(""), 0); + wi_mutable_string_replace_string_with_string(formatted_message, WI_STR(""), WI_STR(""), 0); + wi_mutable_string_replace_string_with_string(formatted_message, WI_STR(""), WI_STR(""), 0); + wi_mutable_string_replace_string_with_string(formatted_message, WI_STR(""), WI_STR(""), 0); + + return wi_autorelease(formatted_message); +} + + + +static wi_boolean_t wd_watch_path_is_descendant_of_path(wi_string_t *path, wi_string_t *directory) { + wi_string_t *prefix; + + prefix = wi_string_by_appending_string(directory, WI_STR("/")); + + return wi_string_has_prefix(path, prefix); +} + + + +static void wd_watch_announce_path(wi_string_t *filepath, wi_string_t *root) { + wi_mutable_string_t *text; + wi_string_t *relativepath, *size, *message_template; + wi_fs_stat_t sb; + + relativepath = wi_string_substring_from_index(filepath, wi_string_length(root) + 1); + + if(wi_fs_stat_path(filepath, &sb)) { + if(S_ISDIR(sb.mode)) + size = WI_STR("folder"); + else + size = wd_files_string_for_bytes(sb.size); + } else { + size = WI_STR("unknown size"); + } + + wi_lock_lock(wd_watch_lock); + message_template = wi_retain(wd_watch_message ? wd_watch_message : WI_STR(WD_WATCH_DEFAULT_MESSAGE)); + wi_lock_unlock(wd_watch_lock); + + text = wi_mutable_copy(message_template); + wi_mutable_string_replace_string_with_string(text, WI_STR("$SIZE"), size, 0); + wi_mutable_string_replace_string_with_string(text, WI_STR("$FILE"), relativepath, 0); + wi_release(message_template); + + wd_watch_broadcast_text(text); + + wi_log_info(WI_STR("Announced new item \"%@\" as \"%@\""), filepath, text); + + wi_release(text); +} + + + +static void wd_watch_broadcast_text(wi_string_t *text) { + wi_p7_message_t *message; + + message = wi_p7_message_with_name(WI_STR("wired.chat.say"), wd_p7_spec); + wi_p7_message_set_uint32_for_name(message, wd_chat_id(wd_public_chat), WI_STR("wired.chat.id")); + wi_p7_message_set_uint32_for_name(message, WD_WATCH_USER_ID, WI_STR("wired.user.id")); + wi_p7_message_set_string_for_name(message, text, WI_STR("wired.chat.say")); + wd_chat_broadcast_message(wd_public_chat, message); +} + + + +#pragma mark - + +static void wd_watch_set_user_fields(wi_p7_message_t *message, wd_chat_t *chat) { + wi_string_t *name, *status; + wi_data_t *icon; + + wi_lock_lock(wd_watch_lock); + name = wi_retain(wd_watch_name ? wd_watch_name : WI_STR(WD_WATCH_DEFAULT_NAME)); + status = wi_retain(wd_watch_status ? wd_watch_status : WI_STR(WD_WATCH_DEFAULT_STATUS)); + icon = wi_retain(wd_watch_icon ? wd_watch_icon : wi_data()); + wi_lock_unlock(wd_watch_lock); + + wi_p7_message_set_uint32_for_name(message, wd_chat_id(chat), WI_STR("wired.chat.id")); + wi_p7_message_set_uint32_for_name(message, WD_WATCH_USER_ID, WI_STR("wired.user.id")); + wi_p7_message_set_bool_for_name(message, false, WI_STR("wired.user.idle")); + wi_p7_message_set_string_for_name(message, name, WI_STR("wired.user.nick")); + wi_p7_message_set_string_for_name(message, status, WI_STR("wired.user.status")); + wi_p7_message_set_data_for_name(message, icon, WI_STR("wired.user.icon")); + wi_p7_message_set_enum_for_name(message, WD_WATCH_USER_COLOR, WI_STR("wired.account.color")); + + wi_release(name); + wi_release(status); + wi_release(icon); +} + + + +void wd_watch_reply_user_list(wd_chat_t *chat, wd_user_t *user, wi_p7_message_t *message) { + wi_p7_message_t *reply; + wi_boolean_t enabled; + + if(chat != wd_public_chat) + return; + + wi_lock_lock(wd_watch_lock); + enabled = wd_watch_enabled; + wi_lock_unlock(wd_watch_lock); + + if(!enabled) + return; + + reply = wi_p7_message_with_name(WI_STR("wired.chat.user_list"), wd_p7_spec); + wd_watch_set_user_fields(reply, chat); + wd_user_reply_message(user, reply, message); +} + + + +static void wd_watch_broadcast_user_join(void) { + wi_p7_message_t *message; + + message = wi_p7_message_with_name(WI_STR("wired.chat.user_join"), wd_p7_spec); + wd_watch_set_user_fields(message, wd_public_chat); + wd_chat_broadcast_message(wd_public_chat, message); +} + + + +static void wd_watch_broadcast_user_leave(void) { + wi_p7_message_t *message; + + message = wi_p7_message_with_name(WI_STR("wired.chat.user_leave"), wd_p7_spec); + wi_p7_message_set_uint32_for_name(message, wd_chat_id(wd_public_chat), WI_STR("wired.chat.id")); + wi_p7_message_set_uint32_for_name(message, WD_WATCH_USER_ID, WI_STR("wired.user.id")); + wd_chat_broadcast_message(wd_public_chat, message); +} + + + +static void wd_watch_broadcast_user_status(void) { + wi_p7_message_t *message; + wi_string_t *name, *status; + + wi_lock_lock(wd_watch_lock); + name = wi_retain(wd_watch_name ? wd_watch_name : WI_STR(WD_WATCH_DEFAULT_NAME)); + status = wi_retain(wd_watch_status ? wd_watch_status : WI_STR(WD_WATCH_DEFAULT_STATUS)); + wi_lock_unlock(wd_watch_lock); + + message = wi_p7_message_with_name(WI_STR("wired.chat.user_status"), wd_p7_spec); + wi_p7_message_set_uint32_for_name(message, wd_chat_id(wd_public_chat), WI_STR("wired.chat.id")); + wi_p7_message_set_uint32_for_name(message, WD_WATCH_USER_ID, WI_STR("wired.user.id")); + wi_p7_message_set_bool_for_name(message, false, WI_STR("wired.user.idle")); + wi_p7_message_set_string_for_name(message, name, WI_STR("wired.user.nick")); + wi_p7_message_set_string_for_name(message, status, WI_STR("wired.user.status")); + wi_p7_message_set_enum_for_name(message, WD_WATCH_USER_COLOR, WI_STR("wired.account.color")); + wd_chat_broadcast_message(wd_public_chat, message); + + wi_release(name); + wi_release(status); +} + + + +static void wd_watch_broadcast_user_icon(void) { + wi_p7_message_t *message; + wi_data_t *icon; + + wi_lock_lock(wd_watch_lock); + icon = wi_retain(wd_watch_icon ? wd_watch_icon : wi_data()); + wi_lock_unlock(wd_watch_lock); + + message = wi_p7_message_with_name(WI_STR("wired.chat.user_icon"), wd_p7_spec); + wi_p7_message_set_uint32_for_name(message, wd_chat_id(wd_public_chat), WI_STR("wired.chat.id")); + wi_p7_message_set_uint32_for_name(message, WD_WATCH_USER_ID, WI_STR("wired.user.id")); + wi_p7_message_set_data_for_name(message, icon, WI_STR("wired.user.icon")); + wd_chat_broadcast_message(wd_public_chat, message); + + wi_release(icon); +} diff --git a/wired/watch.h b/wired/watch.h new file mode 100644 index 0000000..aac0fe9 --- /dev/null +++ b/wired/watch.h @@ -0,0 +1,42 @@ +/* $Id$ */ + +/* + * Copyright (c) 2003-2009 Axel Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WD_WATCH_H +#define WD_WATCH_H 1 + +#include "main.h" + + +void wd_watch_initialize(void); +void wd_watch_apply_settings(wi_set_t *); +void wd_watch_schedule(void); + +void wd_watch_reply_user_list(wd_chat_t *, wd_user_t *, wi_p7_message_t *); + + +#endif /* WD_WATCH_H */ diff --git a/wired/wired.conf.in b/wired/wired.conf.in index 8223920..ff172de 100644 --- a/wired/wired.conf.in +++ b/wired/wired.conf.in @@ -26,7 +26,7 @@ map port = no # Name or id of the user that the server should operate as. # (default "wired") -user = nark +user = root # Name or id of the group that the server should operate as. # (default "daemon") @@ -95,6 +95,39 @@ files = files # (default 14400) # index time = 14400 +# Recursively watch a directory and announce new files or folders in the +# public chat. When a populated folder arrives, only the folder itself is +# announced; its existing contents are added to the baseline silently. +# Existing items are not announced. An item is announced only after it has +# stopped changing. +# (default "no") +watch enabled = no + +# Directory monitored when the watcher is enabled. +# (no default) +# watch path = files/Uploads + +# Named pipe used to send text to the virtual chat user from local processes. +# Each newline-terminated line is posted to the public chat unchanged. Relative +# paths are resolved from the Wired server directory. The aliases ... +# and ... are rendered as a normal HTML container and bold text. +# The pipe itself is installed by make install. +watch pipe = WiredBot + +# Text sent to the public chat for a new item. $FILE is replaced with the +# relative path. For files, $SIZE is the formatted size; for folders it is +# replaced with "folder". +# (default "New file available: $FILE ($SIZE)") +# watch message = New stuff has arrived: $FILE + +# Name, status and optional icon of the virtual chat user. Relative icon +# paths are resolved from the Wired server directory. +# (defaults "Wired Server", "File notifications" and no icon when omitted) +# watch name = Wired Server +# watch status = File notifications +# robo.png is installed by make install. +watch icon = robo.png + ### TRANSFERS #########################################################