---
name: "pure-uploadscript"
section: "8"
platform: "linux"
package: "pure-ftpd-common"
version: "1.0.50-2.2"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/pure-uploadscript"
---

# pure-uploadscript(8)

Automatically run an external program after a successful upload

## NAME

pure-uploadscript - Automatically run an external program after a successful upload

## SYNTAX

pure-uploadscript \[*-p* \<*/path/to/pidfile*\>\] \[*-B*\] \[*-g* \<*gid*\>\] \[*-h*\] *-r* \<*program to run*\> \[*-u* \<*uid*\>\]

## DESCRIPTION

If Pure-FTPd is compiled with **--with-uploadscript** (default in binary distributions), and if the **-o** (or **--uploadscript**) is passed to the server, a named pipe called **/var/run/pure-ftpd.upload.pipe** is created. You will also notice an important file called **/var/run/pure-ftpd.upload.lock**, used for locking.\
 After a successful upload, the file name is written to the pipe.\
 **pure-uploadscript** reads this pipe to automatically run any program or script to process the newly uploaded file.

## OPTIONS

- **-B**

  Daemonize the process and fork it in background.

- **-g** \<*gid*\>

  Switch the group ID to \<*gid*\>.

- **-h** or **--help**

  Display available options.

- **-r** \<*program to run*\>

  Tell what program/script to run. It has to be *an absolute filename*, the **PATH** environment variable is ignored. The first argument of that program will be the *unquoted* name of the newly uploaded file. Environment variables aren't cleared. So don't put sensitive data in them before calling pure-uploadscript if you switch uid.

- **-u** \<*uid*\>

  Switch the user ID to \<*uid*\>.

## ENVIRONMENT

When the upload script is run, the name of the newly uploaded file is the first argument passed to the script (referenced as $1 by most shells) . Some environment variables are also filled by useful info about the file. **UPLOAD\_SIZE** The size of the file, in bytes. **UPLOAD\_PERMS** The permissions, as an octal integer. **UPLOAD\_UID** The numerical UID of the owner. **UPLOAD\_GID** The numerical GID of the owner. **UPLOAD\_USER** The login of the owner. **UPLOAD\_GROUP** The group name the files belongs to. **UPLOAD\_VUSER** The full user name, or the virtual user name (127 chars max) .

## FILES

*/var/run/pure-ftpd.upload.pipe*  */var/run/pure-ftpd.upload.lock*  */var/run/pure-uploadscript.pid*

## SECURITY

**pure-ftpd** and **pure-uploadscript** are trying to limit security implications of such a feature.

- \- The pipe can only be created and opened by root. It must have perms 600, with uid 0, or it will be ignored.

  - \- The argument passed to an external program/script is always an exact absolute path name. It doesn't get fooled by **chroot()**ed environments, and by absolute or relative paths added to the STOR command.

  - \- UID and GID are set just after parsing command-line options, and **pure-uploadscript** never gets back supervisor privileges.

  - \- Descriptors to the pipe are never passed to external programs/scripts. So when UID switched, the target user can't mess the pipe.

  - \- Only regular files are processed, control characters are rejected, and a header+footer avoid partial file names.

  - \- Two external programs/scripts can't run at the same time. Uploads are always processed sequentially, in chronological order. This is to avoid denial-of-services by issuing a lot of simultaneous STOR commands in order to launch a fork bomb on the server. For this reason, your programs shouldn't take a long time to complete (but they can run themselves in background) .

  ## EXAMPLES

A sample script could be:

\#! /bin/sh\
 echo "$1 uploaded" \| /usr/bin/mutt -s "New upload: $1" \\ ftpadmin@dom.ai.n

Never forget to quote (**"variable"**) all variables in all your shell scripts to avoid security flaws.

## AUTHORS

Frank DENIS \<j at pureftpd dot org\>

## SEE ALSO

**[ftp(1)](/ftp/1.md)**, **[pure-ftpd(8)](/pure-ftpd/8.md)** **[pure-ftpwho(8)](/pure-ftpwho/8.md)** **[pure-mrtginfo(8)](/pure-mrtginfo/8.md)** **[pure-uploadscript(8)](/pure-uploadscript/8.md)** **[pure-statsdecode(8)](/pure-statsdecode/8.md)** **[pure-pw(8)](/pure-pw/8.md)** **[pure-quotacheck(8)](/pure-quotacheck/8.md)** **[pure-authd(8)](/pure-authd/8.md)** **[pure-certd(8)](/pure-certd/8.md)**

**RFC 959**, **RFC 2228**, **RFC 2389** and **RFC 2428**.
