diff -u upstart-1.3/ChangeLog upstart-1.3/ChangeLog --- upstart-1.3/ChangeLog +++ upstart-1.3/ChangeLog @@ -1,3 +1,13 @@ +2011-11-09 James Hunt + + * ChangeLog: Updated. + * extra/upstart-udev-bridge.c: Change default behaviour to strip control + characters from udev data to avoid nasty side-effects. A new option + "--no-strip" is provided to allow the old behaviour of passing the + udev data through unmolested (LP: #829980). + * extra/man/upstart-udev-bridge.8: Update for new "--no-strip" option + and added missing options: "--debug", "--verbose" and "--help". + 2011-07-25 James Hunt * init/job_process.c: job_process_spawn(): diff -u upstart-1.3/conf/rc-sysinit.conf upstart-1.3/conf/rc-sysinit.conf --- upstart-1.3/conf/rc-sysinit.conf +++ upstart-1.3/conf/rc-sysinit.conf @@ -6,7 +6,7 @@ description "System V initialisation compatibility" author "Scott James Remnant " -start on (filesystem and static-network-up) or started failsafe +start on (filesystem and static-network-up) or failsafe-boot stop on runlevel # Default runlevel, this may be overriden on the kernel command-line diff -u upstart-1.3/debian/control upstart-1.3/debian/control --- upstart-1.3/debian/control +++ upstart-1.3/debian/control @@ -14,7 +14,7 @@ Replaces: upstart-job, sysvinit, upstart-compat-sysv, startup-tasks, system-services Conflicts: upstart-job, sysvinit, upstart-compat-sysv, startup-tasks, system-services Provides: upstart-job, upstart-compat-sysv, startup-tasks, system-services -Breaks: libc6 ( << 2.12.1-0ubuntu12 ) +Breaks: libc6 (<< 2.12.1-0ubuntu12), friendly-recovery (<< 0.2.13) Description: event-based init daemon upstart is a replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during diff -u upstart-1.3/debian/changelog upstart-1.3/debian/changelog --- upstart-1.3/debian/changelog +++ upstart-1.3/debian/changelog @@ -1,21 +1,56 @@ -upstart (1.3-0ubuntu8~jhubuntu2) oneiric; urgency=low +upstart (1.3-0ubuntu12~bug829980) oneiric; urgency=low - * respun Makefile.in. I love VC on auto-gen files :( + * ChangeLog: Updated. + * extra/upstart-udev-bridge.c: Change default behaviour to strip control + characters from udev data to avoid nasty side-effects. A new option + "--no-strip" is provided to allow the old behaviour of passing the + udev data through unmolested (LP: #829980). + * extra/man/upstart-udev-bridge.8: Update for new "--no-strip" option + and added missing options: "--debug", "--verbose" and "--help". - -- James Hunt Mon, 12 Sep 2011 16:44:19 +0100 + -- James Hunt Wed, 09 Nov 2011 12:04:59 +0000 -upstart (1.3-0ubuntu8~jhubuntu1) oneiric; urgency=low +upstart (1.3-0ubuntu11) oneiric-proposed; urgency=low - * init/log.c: added log_io_error_handler() which must consume the NihIo - error when children die. + * debian/conf/failsafe.conf: stop on static-network-up, so that a slow + runlevel switch doesn't leave a confusing message on screen about + starting up without networking. LP: #881079. - -- James Hunt Mon, 12 Sep 2011 15:44:07 +0100 + -- Steve Langasek Wed, 26 Oct 2011 12:05:47 -0700 -upstart (1.3-0ubuntu8~jh) oneiric; urgency=low +upstart (1.3-0ubuntu10) oneiric; urgency=low - * Test commit for job logging feature. + [ Clint Byrum ] + * debian/conf/failsafe.conf: do delay as script, not pre-start, so + that the messages/delays are stopped on runlevel immediately. emit + as an event, failsafe-boot, to provide finer grained control. + (LP: #863864) + * conf/rc-sysinit.conf: change from 'started failsafe' to 'failsafe-boot' + to accomodate changes to failsafe.conf. + + [ Steve Langasek ] + * Document device-not-ready in upstart-events(7). LP: #805510. + * Document desktop-shutdown in upstart-events(7). LP: #854329. + * Mention lightdm in the list of example DMs in upstart-events(7), since + it's now the default... + + -- Steve Langasek Mon, 03 Oct 2011 18:37:04 -0700 + +upstart (1.3-0ubuntu9) oneiric; urgency=low + + * Update rcS.conf to only start single user mode but not friendly-recovery. + (LP: #575469) + * Mark upstart as breaking friendly-recovery << 0.2.13 + + -- Stéphane Graber Thu, 15 Sep 2011 16:04:17 -0400 + +upstart (1.3-0ubuntu8) oneiric; urgency=low + + * debian/conf/failsafe.conf: Add plymouth messages to help users + understand why the system boot takes longer when they have + static network interfaces defined. (LP: #847782) - -- James Hunt Mon, 12 Sep 2011 14:12:46 +0100 + -- Clint Byrum Wed, 14 Sep 2011 18:53:10 -0700 upstart (1.3-0ubuntu7) oneiric; urgency=low diff -u upstart-1.3/debian/conf/rcS.conf upstart-1.3/debian/conf/rcS.conf --- upstart-1.3/debian/conf/rcS.conf +++ upstart-1.3/debian/conf/rcS.conf @@ -12,11 +12,7 @@ console owner script - if [ -x /usr/share/recovery-mode/recovery-menu ]; then - exec /usr/share/recovery-mode/recovery-menu - else - exec /sbin/sulogin - fi + exec /sbin/sulogin end script post-stop script diff -u upstart-1.3/debian/conf/failsafe.conf upstart-1.3/debian/conf/failsafe.conf --- upstart-1.3/debian/conf/failsafe.conf +++ upstart-1.3/debian/conf/failsafe.conf @@ -7,3 +7,36 @@ -stop on runlevel +stop on static-network-up or runlevel -pre-start exec sleep 120 +console output + +script + # Determine if plymouth is available + if [ -x /bin/plymouth ] && /bin/plymouth --ping ; then + PLYMOUTH=/bin/plymouth + else + PLYMOUTH=":" + fi + + # The point here is to wait for 2 minutes before forcibly booting + # the system. Anything that is in an "or" condition with 'started + # failsafe' in rc-sysinit deserves consideration for mentioning in + # these messages. currently only static-network-up counts for that. + + sleep 20 + + # Plymouth errors should not stop the script because we *must* reach + # the end of this script to avoid letting the system spin forever + # waiting on it to start. + $PLYMOUTH message --text="Waiting for network configuration..." || : + sleep 40 + + $PLYMOUTH message --text="Waiting up to 60 more seconds for network configuration..." || : + sleep 59 + $PLYMOUTH message --text="Booting system without full network configuration..." || : + + # give user 1 second to see this message since plymouth will go + # away as soon as failsafe starts. + sleep 1 + exec initctl emit --no-wait failsafe-boot +end script + +post-start exec logger -t 'failsafe' -p daemon.warning "Failsafe of 120 seconds reached." diff -u upstart-1.3/debian/manpages/upstart-events.7 upstart-1.3/debian/manpages/upstart-events.7 --- upstart-1.3/debian/manpages/upstart-events.7 +++ upstart-1.3/debian/manpages/upstart-events.7 @@ -50,7 +50,9 @@ @\fBall\-swaps\fP@S@M@> (5)@ @\fBcontrol\-alt\-delete\fP(7)@S@A@> (5)@A @dbus\-activation@S@B@> D\-Bus client request@ + @device\-not\-ready@H@M@> (2)@N @desktop\-session\-start@H@D@> \fBX\fP(7) session created@B + @desktop\-shutdown@H@D@> \fBX\fP(7) session ended@O @drm\-device\-added@S@U@> (5)@C @\fBfilesystem\fP@S@M@After last (1)@D @graphics\-device\-added@S@U@> (5)@C @@ -127,7 +129,7 @@ = A@System Administrator (initiator)@Technically emitted by init(8). B@\fBdbus\-daemon\fP(1)@Run with "\fI\-\-activation=upstart"\fP -D@Display Manager@e.g. gdm/kdm/xdm. +D@Display Manager@e.g. lightdm/gdm/kdm/xdm. F@\fBifup\fP(8) or \fBifdown\fP(8)@See \fI/etc/network/\fP. I@\fBinit\fP(8)@ M@\fBmountall\fP(8)@ @@ -188,6 +190,14 @@ T} L@\fI/etc/init/umountnfs.sh\fP. M@Emitted when all virtual filesystems (such as \fI/proc\fR) mounted. +N@T{ +Emitted when the \fI\-\-dev\-wait\-time\fP timeout is exceeded for +\fBmountall\fP(8). This defaults to 30 seconds. +T} +O@T{ +Emitted when the \fIX\fP(7) display manager exits at shutdown or reboot, to +hand off to the shutdown splash manager. +T} .TE .po \n[old_po] .in \n[old_in] diff -u upstart-1.3/po/en@boldquot.po upstart-1.3/po/en@boldquot.po --- upstart-1.3/po/en@boldquot.po +++ upstart-1.3/po/en@boldquot.po @@ -32,8 +32,8 @@ msgstr "" "Project-Id-Version: upstart 1.3\n" "Report-Msgid-Bugs-To: new@bugs.launchpad.net\n" -"POT-Creation-Date: 2011-07-25 17:06+0100\n" -"PO-Revision-Date: 2011-06-16 15:04+0100\n" +"POT-Creation-Date: 2011-11-09 10:05+0000\n" +"PO-Revision-Date: 2011-11-09 10:05+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: en\n" @@ -354,19 +354,19 @@ msgstr "unable to execute: %s" #: init/job_process.c:885 -#, fuzzy, c-format +#, c-format msgid "unable to setuid: %s" -msgstr "unable to set trace: %s" +msgstr "unable to setuid: %s" #: init/job_process.c:890 -#, fuzzy, c-format +#, c-format msgid "unable to setgid: %s" -msgstr "unable to set trace: %s" +msgstr "unable to setgid: %s" #: init/job_process.c:895 -#, fuzzy, c-format +#, c-format msgid "unable to chown: %s" -msgstr "unable to open console: %s" +msgstr "unable to chown: %s" #: init/job_process.c:926 init/job_process.c:976 #, c-format @@ -1102,15 +1102,19 @@ msgid "%s: illegal runlevel: %s\n" msgstr "%s: illegal runlevel: %s\n" -#: extra/upstart-udev-bridge.c:76 +#: extra/upstart-udev-bridge.c:85 msgid "Detach and run in the background" msgstr "Detach and run in the background" -#: extra/upstart-udev-bridge.c:95 +#: extra/upstart-udev-bridge.c:87 +msgid "Do not strip non-printable bytes from udev message data" +msgstr "Do not strip non-printable bytes from udev message data" + +#: extra/upstart-udev-bridge.c:106 msgid "Bridge udev events into upstart" msgstr "Bridge udev events into upstart" -#: extra/upstart-udev-bridge.c:97 +#: extra/upstart-udev-bridge.c:108 msgid "" "By default, upstart-udev-bridge does not detach from the console and remains " "in the foreground. Use the --daemon option to have it detach." @@ -1119,17 +1123,17 @@ "in the foreground. Use the --daemon option to have it detach." -#: extra/upstart-udev-bridge.c:111 +#: extra/upstart-udev-bridge.c:122 msgid "Could not connect to Upstart" msgstr "Could not connect to Upstart" -#: extra/upstart-udev-bridge.c:125 +#: extra/upstart-udev-bridge.c:136 msgid "Could not create Upstart proxy" msgstr "Could not create Upstart proxy" -#: extra/upstart-udev-bridge.c:149 +#: extra/upstart-udev-bridge.c:160 msgid "Unable to become daemon" msgstr "Unable to become daemon" -#: extra/upstart-udev-bridge.c:297 +#: extra/upstart-udev-bridge.c:334 msgid "Disconnected from Upstart" msgstr "Disconnected from Upstart" diff -u upstart-1.3/po/en@quot.po upstart-1.3/po/en@quot.po --- upstart-1.3/po/en@quot.po +++ upstart-1.3/po/en@quot.po @@ -29,8 +29,8 @@ msgstr "" "Project-Id-Version: upstart 1.3\n" "Report-Msgid-Bugs-To: new@bugs.launchpad.net\n" -"POT-Creation-Date: 2011-07-25 17:06+0100\n" -"PO-Revision-Date: 2011-06-16 15:04+0100\n" +"POT-Creation-Date: 2011-11-09 10:05+0000\n" +"PO-Revision-Date: 2011-11-09 10:05+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: en\n" @@ -351,19 +351,19 @@ msgstr "unable to execute: %s" #: init/job_process.c:885 -#, fuzzy, c-format +#, c-format msgid "unable to setuid: %s" -msgstr "unable to set trace: %s" +msgstr "unable to setuid: %s" #: init/job_process.c:890 -#, fuzzy, c-format +#, c-format msgid "unable to setgid: %s" -msgstr "unable to set trace: %s" +msgstr "unable to setgid: %s" #: init/job_process.c:895 -#, fuzzy, c-format +#, c-format msgid "unable to chown: %s" -msgstr "unable to open console: %s" +msgstr "unable to chown: %s" #: init/job_process.c:926 init/job_process.c:976 #, c-format @@ -1099,15 +1099,19 @@ msgid "%s: illegal runlevel: %s\n" msgstr "%s: illegal runlevel: %s\n" -#: extra/upstart-udev-bridge.c:76 +#: extra/upstart-udev-bridge.c:85 msgid "Detach and run in the background" msgstr "Detach and run in the background" -#: extra/upstart-udev-bridge.c:95 +#: extra/upstart-udev-bridge.c:87 +msgid "Do not strip non-printable bytes from udev message data" +msgstr "Do not strip non-printable bytes from udev message data" + +#: extra/upstart-udev-bridge.c:106 msgid "Bridge udev events into upstart" msgstr "Bridge udev events into upstart" -#: extra/upstart-udev-bridge.c:97 +#: extra/upstart-udev-bridge.c:108 msgid "" "By default, upstart-udev-bridge does not detach from the console and remains " "in the foreground. Use the --daemon option to have it detach." @@ -1116,17 +1120,17 @@ "in the foreground. Use the --daemon option to have it detach." -#: extra/upstart-udev-bridge.c:111 +#: extra/upstart-udev-bridge.c:122 msgid "Could not connect to Upstart" msgstr "Could not connect to Upstart" -#: extra/upstart-udev-bridge.c:125 +#: extra/upstart-udev-bridge.c:136 msgid "Could not create Upstart proxy" msgstr "Could not create Upstart proxy" -#: extra/upstart-udev-bridge.c:149 +#: extra/upstart-udev-bridge.c:160 msgid "Unable to become daemon" msgstr "Unable to become daemon" -#: extra/upstart-udev-bridge.c:297 +#: extra/upstart-udev-bridge.c:334 msgid "Disconnected from Upstart" msgstr "Disconnected from Upstart" diff -u upstart-1.3/po/upstart.pot upstart-1.3/po/upstart.pot --- upstart-1.3/po/upstart.pot +++ upstart-1.3/po/upstart.pot @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: upstart 1.3\n" "Report-Msgid-Bugs-To: new@bugs.launchpad.net\n" -"POT-Creation-Date: 2011-07-25 17:06+0100\n" +"POT-Creation-Date: 2011-11-09 10:05+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -998,31 +998,35 @@ msgstr "" -#: extra/upstart-udev-bridge.c:76 +#: extra/upstart-udev-bridge.c:85 msgid "Detach and run in the background" msgstr "" -#: extra/upstart-udev-bridge.c:95 +#: extra/upstart-udev-bridge.c:87 +msgid "Do not strip non-printable bytes from udev message data" +msgstr "" + +#: extra/upstart-udev-bridge.c:106 msgid "Bridge udev events into upstart" msgstr "" -#: extra/upstart-udev-bridge.c:97 +#: extra/upstart-udev-bridge.c:108 msgid "" "By default, upstart-udev-bridge does not detach from the console and remains " "in the foreground. Use the --daemon option to have it detach." msgstr "" -#: extra/upstart-udev-bridge.c:111 +#: extra/upstart-udev-bridge.c:122 msgid "Could not connect to Upstart" msgstr "" -#: extra/upstart-udev-bridge.c:125 +#: extra/upstart-udev-bridge.c:136 msgid "Could not create Upstart proxy" msgstr "" -#: extra/upstart-udev-bridge.c:149 +#: extra/upstart-udev-bridge.c:160 msgid "Unable to become daemon" msgstr "" -#: extra/upstart-udev-bridge.c:297 +#: extra/upstart-udev-bridge.c:334 msgid "Disconnected from Upstart" msgstr "" reverted: --- upstart-1.3/init/parse_job.c +++ upstart-1.3.orig/init/parse_job.c @@ -2122,8 +2122,6 @@ class->console = CONSOLE_OUTPUT; } else if (! strcmp (arg, "owner")) { class->console = CONSOLE_OWNER; - } else if (! strcmp (arg, "log")) { - class->console = CONSOLE_LOG; } else { nih_return_error (-1, NIH_CONFIG_UNKNOWN_STANZA, _(NIH_CONFIG_UNKNOWN_STANZA_STR)); reverted: --- upstart-1.3/init/job_class.c +++ upstart-1.3.orig/init/job_class.c @@ -83,7 +83,7 @@ /** * JOB_DEFAULT_UMASK: * + * The default file creation mark for processes. - * The default file creation mask for processes. **/ #define JOB_DEFAULT_UMASK 022 @@ -246,7 +246,7 @@ class->normalexit = NULL; class->normalexit_len = 0; + class->console = CONSOLE_NONE; - class->console = CONSOLE_LOG; class->umask = JOB_DEFAULT_UMASK; class->nice = 0; diff -u upstart-1.3/init/job_process.c upstart-1.3/init/job_process.c --- upstart-1.3/init/job_process.c +++ upstart-1.3/init/job_process.c @@ -23,8 +23,6 @@ # include #endif /* HAVE_CONFIG_H */ -/* Required for pty handling */ -#define _XOPEN_SOURCE 600 #include #include @@ -51,7 +49,6 @@ #include #include #include -#include #include "paths.h" #include "system.h" @@ -259,7 +256,7 @@ trace = TRUE; /* Spawn the process, repeat until fork() works */ - while ((job->pid[process] = job_process_spawn (job, argv, + while ((job->pid[process] = job_process_spawn (job->class, argv, env, trace, fds[0])) < 0) { NihError *err; @@ -335,20 +332,20 @@ /** * job_process_spawn: - * @job: job of process to be spawned, + * @class: job class of process to be spawned, * @argv: NULL-terminated list of arguments for the process, * @env: NULL-terminated list of environment variables for the process, * @trace: whether to trace this process, * @script_fd: script file descriptor. * - * This function spawns a new process using the class details in @job to set up - * the environment for it; the process is always a session and process group + * This function spawns a new process using the @class details to set up the + * environment for it; the process is always a session and process group * leader as we never want anything in our own group. * * The process to be executed is given in the @argv array which is passed * directly to execvp(), so should be in the same NULL-terminated form with * the first argument containing the path or filename of the binary. The - * PATH environment in the @job's associated class will be searched. + * PATH environment in @class will be searched. * * If @trace is TRUE, the process will be traced with ptrace and this will * cause the process to be stopped when the exec() call is made. You must @@ -370,7 +367,7 @@ * Returns: process id of new process on success, -1 on raised error **/ pid_t -job_process_spawn (Job *job, +job_process_spawn (JobClass *class, char * const argv[], char * const *env, int trace, @@ -379,20 +376,13 @@ sigset_t child_set, orig_set; pid_t pid; int i, fds[2]; - int pty_master = -1; - int pty_slave = -1; char filename[PATH_MAX]; FILE *fd; int user_job = FALSE; nih_local char *user_dir = NULL; - JobClass *class; - char pts_name[PATH_MAX]; - nih_assert (job != NULL); - nih_assert (job->class != NULL); - - class = job->class; + nih_assert (class != NULL); if (class && class->session && class->session->user) user_job = TRUE; @@ -403,38 +393,6 @@ if (pipe (fds) < 0) nih_return_system_error (-1); - if (class->console == CONSOLE_LOG) { - nih_local char *log_path = NULL; - - log_path = job_process_log_path (job, user_job); - - if (! log_path) - nih_return_system_error (-1); - - pty_master = posix_openpt (O_RDWR | O_NOCTTY); - - if (pty_master < 0) { - /* Give the user an indication that they need to - * increase the available ptys. Any other scenario - * suggest more serious trouble. - */ - if (errno == ENOENT) - nih_warn (_("No available ptys")); - nih_return_system_error (-1); - } - - /* Child is the slave, so won't need this */ - if (nih_io_set_cloexec (pty_master) < 0) { - nih_return_system_error (-1); - } - - /* pty_master will be closed by log_destroy() */ - job->log = log_new (job, log_path, pty_master, - user_job ? class->session->user : 0); - if (! job->log) - nih_return_system_error (-1); - } - /* Block all signals while we fork to avoid the child process running * our own signal handlers before we've reset them all back to the * default. @@ -462,20 +420,13 @@ } close (fds[0]); - - /* Note that pts_master is closed automatically in the parent when the - * log object is destroyed. - */ return pid; - } else if (pid < 0) { nih_error_raise_system (); sigprocmask (SIG_SETMASK, &orig_set, NULL); close (fds[0]); close (fds[1]); - if (class->console == CONSOLE_LOG) - close (pty_master); return -1; } @@ -487,39 +438,6 @@ * and writing an error back to the parent. */ - /* Temporarily disable signal handlers prior to grantpt */ - if (class->console == CONSOLE_LOG) { - sigfillset (&child_set); - sigprocmask (SIG_BLOCK, &child_set, &orig_set); - - if (grantpt (pty_master) < 0) { - close (pty_master); - job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OPENPT_MASTER, 0); - } - - /* Restore signal handlers */ - sigprocmask (SIG_SETMASK, &orig_set, NULL); - - if (unlockpt (pty_master) < 0) { - close (pty_master); - job_process_error_abort (fds[1], JOB_PROCESS_ERROR_UNLOCKPT, 0); - } - - if (ptsname_r (pty_master, pts_name, sizeof(pts_name)) < 0) { - close (pty_master); - job_process_error_abort (fds[1], JOB_PROCESS_ERROR_PTSNAME, 0); - } - - /* Child no longer needs this */ - close (pty_master); - - pty_slave = open (pts_name, O_RDWR | O_NOCTTY); - - if (pty_slave < 0) { - job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OPENPT_SLAVE, 0); - } - } - /* Close the reading end of the pipe with our parent and mark the * writing end to be closed-on-exec so the parent knows we got that * far because read() returned zero. @@ -534,14 +452,6 @@ } nih_io_set_cloexec (fds[1]); - if (class->console == CONSOLE_LOG && pty_slave == JOB_PROCESS_SCRIPT_FD) { - int tmp = dup2 (pty_slave, fds[0]); - if (tmp < 0) - job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0); - close (pty_slave); - pty_slave = tmp; - } - /* Move the script fd to special fd 9; the only gotcha is if that * would be our error descriptor, but that's handled above. */ @@ -553,8 +463,6 @@ script_fd = tmp; } - nih_assert (pty_slave != JOB_PROCESS_SCRIPT_FD); - /* Become the leader of a new session and process group, shedding * any controlling tty (which we shouldn't have had anyway). */ @@ -658,21 +566,6 @@ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CONSOLE, 0); } - if (class->console == CONSOLE_LOG) { - /* Redirect stdout to the logger fd */ - if (dup2 (pty_slave, STDOUT_FILENO) < 0) { - nih_error_raise_system (); - job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0); - } - - /* Redirect stderr to the logger fd */ - if (dup2 (pty_slave, STDERR_FILENO) < 0) { - nih_error_raise_system (); - job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0); - } - - close (pty_slave); - } /* Set resource limits for the process, skipping over any that * aren't set in the job class such that they inherit from @@ -1002,26 +895,6 @@ err, _("unable to chown: %s"), strerror (err->errnum))); break; - case JOB_PROCESS_ERROR_OPENPT_MASTER: - err->error.message = NIH_MUST (nih_sprintf ( - err, _("unable to open pt master: %s"), - strerror (err->errnum))); - break; - case JOB_PROCESS_ERROR_UNLOCKPT: - err->error.message = NIH_MUST (nih_sprintf ( - err, _("unable to unlockpt: %s"), - strerror (err->errnum))); - break; - case JOB_PROCESS_ERROR_PTSNAME: - err->error.message = NIH_MUST (nih_sprintf ( - err, _("unable to get ptsname: %s"), - strerror (err->errnum))); - break; - case JOB_PROCESS_ERROR_OPENPT_SLAVE: - err->error.message = NIH_MUST (nih_sprintf ( - err, _("unable to open pt slave: %s"), - strerror (err->errnum))); - break; default: nih_assert_not_reached (); } @@ -1868,72 +1740,0 @@ - -/** - * job_process_log_path: - * - * @job: Job, - * @user_job: TRUE if @job refers to a non-root job, else FALSE. - * - * Determine full path to on-disk log file for specified @job. - * - * This differs depending on whether the job is a system job or a user job. - * Instance names need to be encoded as part of the path. D-Bus name - * encoding is employed to avoid attempting to create illegal path names - * and for consistency with job names on D-Bus. - * - * Returns: newly allocated log path string, or NULL on raised error. - **/ -char * -job_process_log_path (Job *job, int user_job) -{ - JobClass *class = NULL; - char *log_path = NULL; - nih_local char *dir = NULL; - nih_local char *class_name = NULL; - - nih_assert (job); - nih_assert (job->class); - - class = job->class; - - nih_assert (class->name); - - /* Override, primarily for tests */ - if (getenv (LOGDIR_ENV)) { - dir = NIH_MUST (nih_strdup (NULL, getenv (LOGDIR_ENV))); - nih_debug ("Using alternative directory '%s' for logs", dir); - } else { - if (user_job) { - nih_local char *home = - session_user_home (NULL, class->session->user); - - if (!home) - return NULL; - - dir = NIH_MUST (nih_sprintf (NULL, "%s/%s", home, USER_JOB_LOGDIR)); - } - else - dir = NIH_MUST (nih_strdup (NULL, JOB_LOGDIR)); - } - - class_name = NIH_MUST (nih_dbus_path (NULL, "", class->name, NULL)); - - /* Handle jobs with multiple instances */ - if (job->name && *job->name) { - nih_local char *job_name = NULL; - - job_name = NIH_MUST (nih_dbus_path (NULL, "", job->name, NULL)); - - /* Note we skip over the leading slash generated by - * nih_dbus_path(). - */ - log_path = NIH_MUST (nih_sprintf (NULL, "%s/%s-%s.log", - dir, - class_name+1, - job_name+1)); - } else { - log_path = NIH_MUST (nih_sprintf (NULL, "%s/%s.log", - dir, - class_name+1)); - } - - return log_path; -} reverted: --- upstart-1.3/init/job.c +++ upstart-1.3.orig/init/job.c @@ -151,8 +151,6 @@ job->trace_forks = 0; job->trace_state = TRACE_NONE; - job->log = NULL; - nih_hash_add (class->instances, &job->entry); NIH_LIST_FOREACH (control_conns, iter) { reverted: --- upstart-1.3/init/log.h +++ upstart-1.3.orig/init/log.h @@ -1,74 +0,0 @@ -/* upstart - * - * Copyright © 2011 Canonical Ltd. - * Authors: Scott James Remnant , - * James Hunt . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef INIT_LOG_H -#define INIT_LOG_H - -#include -#include -#include -#include -#include -#include -#include - -/** LOG_DEFAULT_UMASK: - * - * The default file creation mask for log files. - **/ -#define LOG_DEFAULT_UMASK (S_IXUSR | S_IXGRP | S_IRWXO) - -/** LOG_DEFAULT_MODE: - * - * File creation mode for log files. - **/ -#define LOG_DEFAULT_MODE (S_IRWXU | S_IRGRP) - -/** - * Log: - * - * @fd: Write file descriptor associated with @path, - * @path: Full path to log file, - * @io: NihIo associated with jobs stdout and stderr. - * @uid: User id of caller, - * @unflushed: Unflushed data. - **/ -typedef struct log { - int fd; - char *path; - NihIo *io; - uid_t uid; - NihIoBuffer *unflushed; -} Log; - -NIH_BEGIN_EXTERN - -Log *log_new (const void *parent, const char *path, int fd, uid_t uid) - __attribute__ ((warn_unused_result, malloc)); - -void log_io_reader (Log *log, NihIo *io, const char *buf, size_t len); - -void log_io_error_handler (Log *log, NihIo *io); - -int log_destroy (Log *log); - -NIH_END_EXTERN - -#endif /* INIT_LOG_H */ reverted: --- upstart-1.3/init/system.c +++ upstart-1.3.orig/init/system.c @@ -110,7 +110,6 @@ if (type == CONSOLE_OWNER) ioctl (fd, TIOCSCTTY, 1); break; - case CONSOLE_LOG: /* fall through */ case CONSOLE_NONE: /* No console really means /dev/null */ fd = open (DEV_NULL, O_RDWR | O_NOCTTY); reverted: --- upstart-1.3/init/conf.c +++ upstart-1.3.orig/init/conf.c @@ -702,7 +702,8 @@ nih_assert (path != NULL); nih_assert (statbuf != NULL); + /* note that symbolic links are ignored */ + if (! S_ISREG (statbuf->st_mode)) - if (! CONF_FILE_TYPE_VALID (source, statbuf->st_mode)) return; new_path = toggle_conf_name (NULL, path); @@ -888,7 +889,7 @@ */ nih_assert (CONF_EXT_STD[1] < CONF_EXT_OVERRIDE[1]); + if (! S_ISREG (statbuf->st_mode)) - if (! CONF_FILE_TYPE_VALID (source, statbuf->st_mode)) return 0; if (is_conf_file_std (path)) { reverted: --- upstart-1.3/init/job_class.h +++ upstart-1.3.orig/init/job_class.h @@ -56,18 +56,14 @@ * ConsoleType: * * This is used to identify how a job would like its standard input, output + * and error file descriptors arranged. The options are to have these + * mapped to /dev/null, the console device (without being or being the owning + * process) or to the logging daemon. - * and error file descriptors arranged. The options are: - * - CONSOLE_NONE: to have these all mapped to /dev/null, - * - CONSOLE_OUTPUT: the console device (non-owning process), - * - CONSOLE_OWNER: the console device (non-owning process), - * - CONSOLE_LOG: stdin is mapped to /dev/null and standard output and error - * are redirected to the built-in logger (this is the default). **/ typedef enum console_type { CONSOLE_NONE, CONSOLE_OUTPUT, + CONSOLE_OWNER - CONSOLE_OWNER, - CONSOLE_LOG } ConsoleType; diff -u upstart-1.3/init/job_process.h upstart-1.3/init/job_process.h --- upstart-1.3/init/job_process.h +++ upstart-1.3/init/job_process.h @@ -59,11 +59,7 @@ JOB_PROCESS_ERROR_EXEC, JOB_PROCESS_ERROR_SETUID, JOB_PROCESS_ERROR_SETGID, - JOB_PROCESS_ERROR_CHOWN, - JOB_PROCESS_ERROR_OPENPT_MASTER, - JOB_PROCESS_ERROR_UNLOCKPT, - JOB_PROCESS_ERROR_PTSNAME, - JOB_PROCESS_ERROR_OPENPT_SLAVE + JOB_PROCESS_ERROR_CHOWN } JobProcessErrorType; /** @@ -97,7 +93,7 @@ int job_process_run (Job *job, ProcessType process); -pid_t job_process_spawn (Job *job, char * const argv[], +pid_t job_process_spawn (JobClass *class, char * const argv[], char * const *env, int trace, int script_fd) __attribute__ ((warn_unused_result)); @@ -106,10 +102,7 @@ void job_process_handler (void *ptr, pid_t pid, NihChildEvents event, int status); -Job *job_process_find (pid_t pid, ProcessType *process); - -char *job_process_log_path (Job *job, int user_job) - __attribute__ ((malloc, warn_unused_result)); +Job *job_process_find (pid_t pid, ProcessType *process); NIH_END_EXTERN reverted: --- upstart-1.3/init/job.h +++ upstart-1.3.orig/init/job.h @@ -34,7 +34,6 @@ #include "job_class.h" #include "event_operator.h" -#include "log.h" #include "com.ubuntu.Upstart.Instance.h" @@ -114,8 +113,7 @@ * @respawn_time: time job was first respawned, * @respawn_count: number of respawns since @respawn_time, * @trace_forks: number of forks traced, + * @trace_state: state of trace. - * @trace_state: state of trace, - * @log: pointer to log to hold job output. * * This structure holds the state of an active job instance being tracked * by the init daemon, the configuration details of the job are available @@ -155,7 +153,6 @@ int trace_forks; TraceState trace_state; - Log *log; } Job; reverted: --- upstart-1.3/init/Makefile.in +++ upstart-1.3.orig/init/Makefile.in @@ -37,7 +37,7 @@ sbin_PROGRAMS = init$(EXEEXT) TESTS = test_system$(EXEEXT) test_environ$(EXEEXT) \ test_process$(EXEEXT) test_job_class$(EXEEXT) \ + test_job_process$(EXEEXT) test_job$(EXEEXT) \ - test_job_process$(EXEEXT) test_job$(EXEEXT) test_log$(EXEEXT) \ test_event$(EXEEXT) test_event_operator$(EXEEXT) \ test_blocked$(EXEEXT) test_parse_job$(EXEEXT) \ test_parse_conf$(EXEEXT) test_conf$(EXEEXT) \ @@ -74,7 +74,7 @@ CONFIG_CLEAN_VPATH_FILES = am__EXEEXT_1 = test_system$(EXEEXT) test_environ$(EXEEXT) \ test_process$(EXEEXT) test_job_class$(EXEEXT) \ + test_job_process$(EXEEXT) test_job$(EXEEXT) \ - test_job_process$(EXEEXT) test_job$(EXEEXT) test_log$(EXEEXT) \ test_event$(EXEEXT) test_event_operator$(EXEEXT) \ test_blocked$(EXEEXT) test_parse_job$(EXEEXT) \ test_parse_conf$(EXEEXT) test_conf$(EXEEXT) \ @@ -84,10 +84,9 @@ PROGRAMS = $(sbin_PROGRAMS) am_init_OBJECTS = main.$(OBJEXT) system.$(OBJEXT) environ.$(OBJEXT) \ process.$(OBJEXT) session.$(OBJEXT) job_class.$(OBJEXT) \ + job_process.$(OBJEXT) job.$(OBJEXT) event.$(OBJEXT) \ + event_operator.$(OBJEXT) blocked.$(OBJEXT) parse_job.$(OBJEXT) \ + parse_conf.$(OBJEXT) conf.$(OBJEXT) control.$(OBJEXT) - job_process.$(OBJEXT) job.$(OBJEXT) log.$(OBJEXT) \ - event.$(OBJEXT) event_operator.$(OBJEXT) blocked.$(OBJEXT) \ - parse_job.$(OBJEXT) parse_conf.$(OBJEXT) conf.$(OBJEXT) \ - control.$(OBJEXT) am__objects_1 = com.ubuntu.Upstart.$(OBJEXT) am__objects_2 = com.ubuntu.Upstart.Job.$(OBJEXT) am__objects_3 = com.ubuntu.Upstart.Instance.$(OBJEXT) @@ -104,7 +103,7 @@ test_blocked_OBJECTS = $(am_test_blocked_OBJECTS) test_blocked_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -112,7 +111,7 @@ test_conf_OBJECTS = $(am_test_conf_OBJECTS) test_conf_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -120,7 +119,7 @@ test_control_OBJECTS = $(am_test_control_OBJECTS) test_control_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -131,7 +130,7 @@ test_event_OBJECTS = $(am_test_event_OBJECTS) test_event_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -140,14 +139,14 @@ test_event_operator_DEPENDENCIES = system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o \ blocked.o parse_job.o parse_conf.o conf.o control.o session.o \ + com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ - log.o com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_test_job_OBJECTS = test_job.$(OBJEXT) test_job_OBJECTS = $(am_test_job_OBJECTS) test_job_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -155,7 +154,7 @@ test_job_class_OBJECTS = $(am_test_job_class_OBJECTS) test_job_class_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -164,14 +163,6 @@ test_job_process_DEPENDENCIES = system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o \ blocked.o parse_job.o parse_conf.o conf.o control.o session.o \ - log.o com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ - com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_test_log_OBJECTS = test_log.$(OBJEXT) -test_log_OBJECTS = $(am_test_log_OBJECTS) -test_log_DEPENDENCIES = system.o environ.o process.o job_class.o \ - job_process.o job.o event.o event_operator.o blocked.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -180,14 +171,14 @@ test_parse_conf_DEPENDENCIES = system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o \ blocked.o parse_job.o parse_conf.o conf.o control.o session.o \ + com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ - log.o com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_test_parse_job_OBJECTS = test_parse_job.$(OBJEXT) test_parse_job_OBJECTS = $(am_test_parse_job_OBJECTS) test_parse_job_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -195,7 +186,7 @@ test_process_OBJECTS = $(am_test_process_OBJECTS) test_process_DEPENDENCIES = system.o environ.o process.o job_class.o \ job_process.o job.o event.o event_operator.o blocked.o \ + parse_job.o parse_conf.o conf.o control.o session.o \ - parse_job.o parse_conf.o conf.o control.o session.o log.o \ com.ubuntu.Upstart.o com.ubuntu.Upstart.Job.o \ com.ubuntu.Upstart.Instance.o $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -233,17 +224,16 @@ $(test_control_SOURCES) $(test_environ_SOURCES) \ $(test_event_SOURCES) $(test_event_operator_SOURCES) \ $(test_job_SOURCES) $(test_job_class_SOURCES) \ + $(test_job_process_SOURCES) $(test_parse_conf_SOURCES) \ + $(test_parse_job_SOURCES) $(test_process_SOURCES) \ + $(test_system_SOURCES) - $(test_job_process_SOURCES) $(test_log_SOURCES) \ - $(test_parse_conf_SOURCES) $(test_parse_job_SOURCES) \ - $(test_process_SOURCES) $(test_system_SOURCES) DIST_SOURCES = $(init_SOURCES) $(test_blocked_SOURCES) \ $(test_conf_SOURCES) $(test_control_SOURCES) \ $(test_environ_SOURCES) $(test_event_SOURCES) \ $(test_event_operator_SOURCES) $(test_job_SOURCES) \ $(test_job_class_SOURCES) $(test_job_process_SOURCES) \ + $(test_parse_conf_SOURCES) $(test_parse_job_SOURCES) \ + $(test_process_SOURCES) $(test_system_SOURCES) - $(test_log_SOURCES) $(test_parse_conf_SOURCES) \ - $(test_parse_job_SOURCES) $(test_process_SOURCES) \ - $(test_system_SOURCES) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -500,7 +490,6 @@ job_class.c job_class.h \ job_process.c job_process.h \ job.c job.h \ - log.c log.h \ event.c event.h \ event_operator.c event_operator.h \ blocked.c blocked.h \ @@ -572,7 +561,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -584,7 +573,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -596,7 +585,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -608,19 +597,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ - com.ubuntu.Upstart.o \ - com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ - $(NIH_LIBS) \ - $(NIH_DBUS_LIBS) \ - $(DBUS_LIBS) - -test_log_SOURCES = tests/test_log.c -test_log_LDADD = \ - system.o environ.o process.o \ - job_class.o job_process.o job.o event.o event_operator.o blocked.o \ - parse_job.o parse_conf.o conf.o control.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -632,7 +609,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -644,7 +621,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -656,7 +633,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -668,7 +645,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -680,7 +657,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -692,7 +669,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -704,7 +681,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -828,9 +805,6 @@ test_job_process$(EXEEXT): $(test_job_process_OBJECTS) $(test_job_process_DEPENDENCIES) @rm -f test_job_process$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_job_process_OBJECTS) $(test_job_process_LDADD) $(LIBS) -test_log$(EXEEXT): $(test_log_OBJECTS) $(test_log_DEPENDENCIES) - @rm -f test_log$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_log_OBJECTS) $(test_log_LDADD) $(LIBS) test_parse_conf$(EXEEXT): $(test_parse_conf_OBJECTS) $(test_parse_conf_DEPENDENCIES) @rm -f test_parse_conf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_parse_conf_OBJECTS) $(test_parse_conf_LDADD) $(LIBS) @@ -862,7 +836,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job_class.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job_process.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_conf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_job.Po@am__quote@ @@ -878,7 +851,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_job_class.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_job_process.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_parse_conf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_parse_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_process.Po@am__quote@ @@ -1052,22 +1024,6 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_job_process.obj `if test -f 'tests/test_job_process.c'; then $(CYGPATH_W) 'tests/test_job_process.c'; else $(CYGPATH_W) '$(srcdir)/tests/test_job_process.c'; fi` -test_log.o: tests/test_log.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_log.o -MD -MP -MF $(DEPDIR)/test_log.Tpo -c -o test_log.o `test -f 'tests/test_log.c' || echo '$(srcdir)/'`tests/test_log.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_log.Tpo $(DEPDIR)/test_log.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_log.c' object='test_log.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_log.o `test -f 'tests/test_log.c' || echo '$(srcdir)/'`tests/test_log.c - -test_log.obj: tests/test_log.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_log.obj -MD -MP -MF $(DEPDIR)/test_log.Tpo -c -o test_log.obj `if test -f 'tests/test_log.c'; then $(CYGPATH_W) 'tests/test_log.c'; else $(CYGPATH_W) '$(srcdir)/tests/test_log.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_log.Tpo $(DEPDIR)/test_log.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_log.c' object='test_log.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_log.obj `if test -f 'tests/test_log.c'; then $(CYGPATH_W) 'tests/test_log.c'; else $(CYGPATH_W) '$(srcdir)/tests/test_log.c'; fi` - test_parse_conf.o: tests/test_parse_conf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_parse_conf.o -MD -MP -MF $(DEPDIR)/test_parse_conf.Tpo -c -o test_parse_conf.o `test -f 'tests/test_parse_conf.c' || echo '$(srcdir)/'`tests/test_parse_conf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_parse_conf.Tpo $(DEPDIR)/test_parse_conf.Po diff -u upstart-1.3/init/main.c upstart-1.3/init/main.c --- upstart-1.3/init/main.c +++ upstart-1.3/init/main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include reverted: --- upstart-1.3/init/log.c +++ upstart-1.3.orig/init/log.c @@ -1,528 +0,0 @@ -/* TODO - - - log_io_reader as root: - open log file - write to log file - nih_io_buffer_shrink - - log_io_reader as non-root: - fork - parent - child opens log file - child writes to log file - child tells parents how much data written - parent calls nih_io_buffer_shrink - -*/ - -/* upstart - * - * log.c - persist job output to a log file. - * - * Copyright © 2011 Canonical Ltd. - * Authors: Scott James Remnant , - * James Hunt . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include "log.h" -#include "session.h" - -static ssize_t log_write_user (Log *log, const char *buf, size_t len); - -/** - * log_io_error_handler: - * - * @log: Log associated with this @io, - * @io: NihIo. - * - * Called automatically when reading the jobs stdout/stderr - * causes an error. This will occur when the parent attempts a read after - * the child has exited abnormally. - */ -void -log_io_error_handler (Log *log, NihIo *io) -{ - NihError *err; - - nih_assert (log); - nih_assert (io); - - /* Consume */ - err = nih_error_get (); - nih_assert (err->number == EIO); - nih_free (err); - - /* Close the connection with the child */ - nih_free (log->io); -} - -/** - * log_new: - * - * @parent: parent for new job class, - * @path: full path to on-disk log file, - * @fd: file descriptor associated with jobs stdout and stderr which - * will be read from, - * @uid: user id associated with this logger. - * - * Allocates and returns a new Log structure with the given @path - * and @session. - * - * If @parent is not NULL, it should be a pointer to another object which - * will be used as a parent for the returned job class. When all parents - * of the returned job class are freed, the returned log will also be - * freed. - * - * Returns: newly allocated Log structure or NULL if insufficient memory. - **/ -Log * -log_new (const void *parent, - const char *path, - int fd, - uid_t uid) -{ - Log *log; - - nih_assert (path); - nih_assert (fd > 0); - - log = nih_new (parent, Log); - if (! log) { - return NULL; - } - - log->fd = -1; - log->uid = uid; - - log->path = nih_strdup (log, path); - if (! log->path) { - nih_free (log); - return NULL; - } - - log->unflushed = nih_io_buffer_new (log); - if (! log->unflushed) { - nih_free (log); - return NULL; - } - - log->io = nih_io_reopen (log, fd, NIH_IO_STREAM, - (NihIoReader)log_io_reader, - NULL, (NihIoErrorHandler)log_io_error_handler, - log); - - if (! log->io) { - NihError *err = nih_error_get (); - if (err->number == ENOMEM) { - nih_free (err); - } - nih_free (log); - return NULL; - } - - nih_alloc_set_destructor (log, log_destroy); - - return log; -} - -/** - * log_destroy: - * - * @log: Log. - * - * Called automatically when Log is being destroyed. - **/ -int -log_destroy (Log *log) -{ - ssize_t wlen; - struct stat statbuf; - - nih_assert (log); - - memset (&statbuf, '\0', sizeof(struct stat)); - - /* Job probably attempted to only write data before the logger - * could access the disk. Last ditch attempt to persist the - * data. - */ - if (log->unflushed->len) { - int rc = -1; - if (log->fd < 0 || (! (rc=fstat (log->fd, &statbuf)) && ! statbuf.st_nlink)) { - - /* File was deleted. This isn't a problem for - * the logger as it is happy to keep writing the - * unlinked file, but it *is* a problem for - * users who expect to see some data. Therefore, - * close the file and attempt to rewrite it. - */ - if (! rc && ! statbuf.st_nlink) - close (log->fd); - - /* Impose some sane defaults. */ - umask (LOG_DEFAULT_UMASK); - - /* Non-blocking to avoid holding up the main loop. Without - * this, we'd probably need to spawn a thread to handle - * job logging. - */ - log->fd = open (log->path, - O_CREAT | O_APPEND | O_WRONLY | - O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK, - S_IRWXU | S_IRGRP); - if (log->fd < 0) - return 0; - } - - wlen = write (log->fd, log->unflushed->buf, log->unflushed->len); - if (wlen < 0) { - nih_warn (_("failed to flush log")); - } - } - - /* Force file to flush */ - if (log->fd > 0) - close (log->fd); - log->fd = -1; - - return 0; -} - -/** - * log_io_reader: - * - * @log: Log associated with this @io, - * @io: NihIo with data to be read, - * @buf: buffer data is available in, - * @len: bytes in @buf available for reading. - * - * Called automatically when data is available to read on the fd - * encapsulated in @io. - * - * Notes for user jobs: - * - * User jobs by necessity are handled differently to system jobs. Since - * a user job must log their data to files owned by a non-root user, the - * safest technique is for a process running as that user to create the - * log file. However, that requires an additional log process to be - * running. Since most jobs do not produce any output it would be highly - * inefficient to spawn such a logger process for every user job. - * Therefore the approach taken is the lazy one: create a user logger - * process _when the job first produces output_. To avoid terrible - * performance this process will then hang around until the job has - * finished. - * - * FIXME: update these comments!! - * - * This function create a child process to handle writing of user job - * log files using log_become_user() to ensure they have the correct - * ownership. - * - * Note that this design is non-optimal from a performance - * perspective due to the need to create child processes. - * - * Note too that since the job output data is buffered - * within init, there is also the danger of OOM should a user job - * generate too much data. - **/ - -void -log_io_reader (Log *log, NihIo *io, const char *buf, size_t len) -{ - ssize_t wlen = 0; - struct stat statbuf; - - nih_assert (log); - nih_assert (log->path); - nih_assert (io); - nih_assert (buf); - - /* Just in case we try to write more than read can inform us - * about. - */ - nih_assert (sizeof (size_t) == sizeof (ssize_t)); - - memset (&statbuf, '\0', sizeof(struct stat)); - - if (log->uid > 0) { - if (log->unflushed->len) { - wlen = log_write_user (log, log->unflushed->buf, log->unflushed->len); - if (wlen < 0) { - if (nih_io_buffer_push (log->unflushed, buf, len) < 0) - goto error; - nih_io_buffer_shrink (io->recv_buf, len); - - goto error; - } - nih_io_buffer_shrink (log->unflushed, wlen); - } - wlen = log_write_user (log, buf, len); - } else { - int rc = -1; - - /* File hasn't been opened yet, or failed to open last time */ - if (log->fd < 0 || (! (rc=fstat (log->fd, &statbuf)) && ! statbuf.st_nlink)) { - - /* File was deleted. This isn't a problem for - * the logger as it is happy to keep writing the - * unlinked file, but it *is* a problem for - * users who expect to see some data. Therefore, - * close the file and attempt to rewrite it. - */ - if (! rc && ! statbuf.st_nlink) - close (log->fd); - - /* Impose some sane defaults. */ - umask (LOG_DEFAULT_UMASK); - - /* Non-blocking to avoid holding up the main loop. Without - * this, we'd probably need to spawn a thread to handle - * job logging. - */ - log->fd = open (log->path, - O_CREAT | O_APPEND | O_WRONLY | - O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK, - S_IRWXU | S_IRGRP); - - /* Open may have failed due to path being unaccessible - * (disk might not be mounted yet). - * - * We save the data to ensure we have atleast one last - * attempt at flushing it to disk - when the logger object - * is destroyed. If we didn't do this, a job which only - * wrote to its stdout/stderr before the logger could - * persist it to disk would never have its output written. - */ - if (log->fd < 0) { - /* Add new data to unflushed buffer */ - if (nih_io_buffer_push (log->unflushed, buf, len) < 0) { - return; - } - nih_io_buffer_shrink (io->recv_buf, len); - return; - } - } - - /* Flush any lingering unflushed data */ - if (log->unflushed->len) { - wlen = write (log->fd, log->unflushed->buf, log->unflushed->len); - if (wlen < 0) { - /* Failed to flush the unflushed data, - * so unlikely to be able to flush the - * new data. Hence, add the new data - * to the unflushed buffer. - */ - - /* If this fails, we still want to - * indicate an error condition, so no - * explicit return check. - */ - if (nih_io_buffer_push (log->unflushed, buf, len) < 0) - goto error; - - nih_io_buffer_shrink (io->recv_buf, len); - - goto error; - } - - nih_io_buffer_shrink (log->unflushed, wlen); - } - - wlen = write (log->fd, buf, len); - } - - if (wlen < 0) { - if (nih_io_buffer_push (log->unflushed, buf, len) < 0) { - /* Appease the compiler */ - goto error; - } - } - - /* Shrink buffer by amount of data written */ - nih_io_buffer_shrink (io->recv_buf, wlen < 0 ? len : (size_t)wlen); - - return; - -error: - close (log->fd); - log->fd = -1; -} - -/** - * log_write_user: - * - * @log: Log, - * @buf: buffer data is available in, - * @len: bytes in @buf to be written to log. - * - * Write data to log file as user log->uid. - * - * Returns number of bytes written, or -1 if write failed. - **/ -ssize_t -log_write_user (Log *log, const char *buf, size_t len) -{ - pid_t pid; - gid_t gid; - ssize_t ret = 0; - ssize_t rlen = 0; - ssize_t wlen = 0; - sigset_t child_set, orig_set; - int fds[2] = { -1, -1 }; - - nih_assert (log); - nih_assert (len); - - /* This routine is only for user jobs */ - nih_assert (log->uid > 0); - - /* Logger is associated with user job, so avoid - * any possibility of creating file with gid of root. - */ - gid = session_user_group (log->uid); - - /* Logger is associated with user job, so avoid - * any possibility of creating file with gid of root. - */ - if (gid < 1) - return -1; - - if (pipe (fds) < 0) { - NihError *err; - - nih_error_raise_system (); - err = nih_error_get (); - nih_warn (_("Failed to create pipe: %s"), - err->message); - nih_free (err); - return -1; - } - - /* Block all signals while we fork to avoid the child process running - * our own signal handlers before we've reset them all back to the - * default. - */ - sigfillset (&child_set); - sigprocmask (SIG_BLOCK, &child_set, &orig_set); - - /* - * User jobs are the "fly in the ointment" here because - * for us to write their log file, we need to - * impersonate the user in question (to ensure the log is - * owned by that user). Disregarding pid 1 setuid games and - * chown hacks (racy), we only have one option left: - * creating a new process to handle writing the log as - * the user. This isn't ideal since we create a new - * process _each time we have data to read from a user - * job_. However, we prefer safety to speed and it seems - * reasonable to treat user jobs as lower priority than - * system jobs anyway. - */ - if ((pid = fork ()) < 0) { - NihError *err; - - /* Restore signal handlers */ - sigprocmask (SIG_SETMASK, &orig_set, NULL); - - nih_error_raise_system (); - - err = nih_error_get (); - nih_warn (_("Failed to fork: %s"), err->message); - nih_free (err); - - close (fds[0]); - close (fds[1]); - - return -1; - - } else if (pid > 0) { - - /* Restore signal handlers */ - sigprocmask (SIG_SETMASK, &orig_set, NULL); - - close (fds[1]); - - /* Nominally a blocking read, but effectively a - * non-blocking one since the parent uses it to obtain - * the return code of a non-blocking write in the child. - */ - ret = read (fds[0], &rlen, sizeof (rlen)); - close (fds[0]); - - if (ret < 0) { - close (log->fd); - log->fd = -1; - return -1; - } - - if ( (size_t)ret < sizeof (rlen)) - return -1; - - return rlen; - } - - /* Child */ - - /* Ensure that the corresponding child job process - * cannot kill the logger if it gets a SIGHUP - */ - setsid (); - - close (fds[0]); - - if (setgid (gid) < 0) { - return -1; - } - if (setuid (log->uid) < 0) { - return -1; - } - - /* Impose some sane defaults. */ - umask (LOG_DEFAULT_UMASK); - - /* Non-blocking to avoid holding up main (parent) loop. Without - * this, we'd probably need to spawn a thread to handle - * job logging. - */ - log->fd = open (log->path, - O_CREAT | O_APPEND | O_WRONLY | - O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK, - S_IRWXU | S_IRGRP); - - /* path may be unaccessible (disk might not be mounted yet) */ - if (log->fd < 0) { - wlen = -1; - goto out; - } - - /* Write to log file */ - wlen = write (log->fd, buf, len); - -out: - /* Inform parent how much we wrote. - * - * Note that we can't check the result of this call - */ - (void)write (fds[1], &wlen, sizeof (wlen)); - - close (fds[1]); - - _exit (0); -} diff -u upstart-1.3/init/session.c upstart-1.3/init/session.c --- upstart-1.3/init/session.c +++ upstart-1.3/init/session.c @@ -82,7 +82,6 @@ } -/* FIXME */ Session * session_new (const void *parent, const char *chroot, @@ -121,7 +120,6 @@ return session; } -/* FIXME */ Session * session_from_dbus (const void *parent, NihDBusMessage *message) @@ -270,7 +268,6 @@ return session; } -/* FIXME */ static void session_create_conf_source (Session *session) { @@ -324,53 +320,0 @@ - -/** - * session_user_home: - * - * @parent: Parent, - * @user: uid of user. - * - * Determine path to users home directory. - * - * Returns newly allocated home directory string, or NULL on raised - * error. - **/ -char * -session_user_home (const void *parent, - uid_t user) -{ - struct passwd *pwd; - - /* Note we cannot assert user as this could be called for root. - */ - - pwd = getpwuid (user); - - if (! pwd || ! pwd->pw_dir) { - nih_error ("%lu: %s: %s", (unsigned long int)user, - _("Unable to lookup home directory"), - strerror (errno)); - nih_return_system_error (NULL); - } - - return nih_strdup (parent, pwd->pw_dir); -} - -/* FIXME */ -gid_t -session_user_group (uid_t user) -{ - struct passwd *pwd; - - /* Note we cannot assert user as this could be called for root. - */ - - pwd = getpwuid (user); - - if (! pwd || ! pwd->pw_dir) { - nih_error ("%lu: %s: %s", (unsigned long int)user, - _("Unable to lookup home directory"), - strerror (errno)); - return 0; - } - - return pwd->pw_gid; -} reverted: --- upstart-1.3/init/conf.h +++ upstart-1.3.orig/init/conf.h @@ -30,19 +30,6 @@ #include "job_class.h" -/* Symbolic links are only allowed for user sessions. */ -/* FIXME: needed? since this works already: - * - * mkdir -p ~/.config/upstart - * ln -s ~/.init ~/.config/upstart - * echo "manual" > ~/.init/foo.conf - * - * */ -#define CONF_FILE_TYPE_VALID(source, mode) \ - (((source->session && source->session->user) \ - && (S_ISREG (mode) || S_ISLNK (mode))) \ - || S_ISREG (mode)) - /** * ConfSourceType: * reverted: --- upstart-1.3/init/Makefile.am +++ upstart-1.3.orig/init/Makefile.am @@ -44,7 +44,6 @@ job_class.c job_class.h \ job_process.c job_process.h \ job.c job.h \ - log.c log.h \ event.c event.h \ event_operator.c event_operator.h \ blocked.c blocked.h \ @@ -126,7 +125,6 @@ EXTRA_DIST = init.supp -# FIXME: need test_session TESTS = \ test_system \ test_environ \ @@ -134,7 +132,6 @@ test_job_class \ test_job_process \ test_job \ - test_log \ test_event \ test_event_operator \ test_blocked \ @@ -162,7 +159,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -174,7 +171,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -186,7 +183,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -198,19 +195,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ - com.ubuntu.Upstart.o \ - com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ - $(NIH_LIBS) \ - $(NIH_DBUS_LIBS) \ - $(DBUS_LIBS) - -test_log_SOURCES = tests/test_log.c -test_log_LDADD = \ - system.o environ.o process.o \ - job_class.o job_process.o job.o event.o event_operator.o blocked.o \ - parse_job.o parse_conf.o conf.o control.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -222,7 +207,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -234,7 +219,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -246,7 +231,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -258,7 +243,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -270,7 +255,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -282,7 +267,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ @@ -294,7 +279,7 @@ system.o environ.o process.o \ job_class.o job_process.o job.o event.o event_operator.o blocked.o \ parse_job.o parse_conf.o conf.o control.o \ + session.o \ - session.o log.o \ com.ubuntu.Upstart.o \ com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ $(NIH_LIBS) \ reverted: --- upstart-1.3/init/paths.h +++ upstart-1.3.orig/init/paths.h @@ -82,16 +82,6 @@ #define USERCONFDIR ".init" #endif -/** - * USER_JOB_LOGDIR: - * - * XDG directory equivalent of JOB_LOGDIR for user jobs. Note that like - * its counterpart, the directory must exist since Upstart will not - * attempt to create it. - **/ -#ifndef USER_JOB_LOGDIR -#define USER_JOB_LOGDIR ".cache/upstart/log" -#endif /** * CONFDIR_ENV: @@ -106,6 +96,7 @@ #define CONFDIR_ENV "UPSTART_CONFDIR" #endif + /** * SHELL: * @@ -136,31 +127,6 @@ #endif /** - * JOB_LOGDIR: - * - * Directory that jobs which specify CONSOLE_LOG will have their output - * logged to. - * - * FIXME: mkdir /var/log/upstart/ in Ubuntu postinst script. - * - **/ -#ifndef JOB_LOGDIR -#define JOB_LOGDIR "/var/log/upstart" -#endif - -/** - * LOGDIR_ENV: - * - * Environment variable that if set specifies an alternative directory - * to JOB_LOGDIR to write log files to. - * - **/ -#ifndef LOGDIR_ENV -#define LOGDIR_ENV "UPSTART_LOGDIR" -#endif - - -/** * File extension for standard configuration files. **/ #define CONF_EXT_STD ".conf" diff -u upstart-1.3/init/session.h upstart-1.3/init/session.h --- upstart-1.3/init/session.h +++ upstart-1.3/init/session.h @@ -84,10 +84,6 @@ Session *session_from_dbus (const void *parent, NihDBusMessage *message); -char *session_user_home (const void *parent, uid_t user) - __attribute__ ((malloc, warn_unused_result)); -gid_t session_user_group (uid_t user) - __attribute__ ((warn_unused_result)); NIH_END_EXTERN #endif /* INIT_SESSION_H */ reverted: --- upstart-1.3/init/tests/test_job_class.c +++ upstart-1.3.orig/init/tests/test_job_class.c @@ -128,7 +128,7 @@ TEST_EQ_P (class->normalexit, NULL); TEST_EQ (class->normalexit_len, 0); + TEST_EQ (class->console, CONSOLE_NONE); - TEST_EQ (class->console, CONSOLE_LOG); TEST_EQ (class->umask, 022); TEST_EQ (class->nice, 0); @@ -179,17 +179,14 @@ file1 = conf_file_new (source2, "/tmp/bar/frodo"); class1 = file1->job = job_class_new (NULL, "frodo", NULL); - class1->console = CONSOLE_NONE; file2 = conf_file_new (source2, "/tmp/bar/bilbo"); class2 = file2->job = job_class_new (NULL, "bilbo", NULL); - class2->console = CONSOLE_NONE; source3 = conf_source_new (NULL, "/tmp/baz", CONF_JOB_DIR); file3 = conf_file_new (source3, "/tmp/baz/frodo"); class3 = file3->job = job_class_new (NULL, "frodo", NULL); - class3->console = CONSOLE_NONE; control_init (); @@ -383,7 +380,6 @@ */ TEST_FEATURE ("with replacable registered class and not best class"); class4 = job_class_new (NULL, "frodo", NULL); - class4->console = CONSOLE_NONE; nih_hash_add (job_classes, &class4->entry); job_class_register (class4, conn, FALSE); @@ -482,17 +478,14 @@ file1 = conf_file_new (source2, "/tmp/bar/frodo"); class1 = file1->job = job_class_new (NULL, "frodo", NULL); - class1->console = CONSOLE_NONE; file2 = conf_file_new (source2, "/tmp/bar/bilbo"); class2 = file2->job = job_class_new (NULL, "bilbo", NULL); - class2->console = CONSOLE_NONE; source3 = conf_source_new (NULL, "/tmp/baz", CONF_JOB_DIR); file3 = conf_file_new (source3, "/tmp/baz/frodo"); class3 = file3->job = job_class_new (NULL, "frodo", NULL); - class3->console = CONSOLE_NONE; control_init (); @@ -726,7 +719,6 @@ nih_free (source1); class4 = job_class_new (NULL, "frodo", NULL); - class4->console = CONSOLE_NONE; nih_hash_add (job_classes, &class4->entry); job_class_register (class4, conn, FALSE); @@ -796,7 +788,6 @@ */ TEST_FEATURE ("with signal emission"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; assert (dbus_connection_get_object_path_data (conn, class->path, (void **)&object)); @@ -834,7 +825,6 @@ */ TEST_FEATURE ("without signal emission"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; assert (dbus_connection_get_object_path_data (conn, class->path, (void **)&object)); @@ -903,7 +893,6 @@ class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; assert (dbus_connection_get_object_path_data (conn, class->path, (void **)&object)); @@ -961,7 +950,6 @@ */ TEST_FEATURE ("with no configured environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; TEST_ALLOC_FAIL { env = job_class_environment (NULL, class, &len); @@ -992,7 +980,6 @@ */ TEST_FEATURE ("with configured environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->env = nih_str_array_new (class); assert (nih_str_array_add (&(class->env), class, NULL, "FOO=BAR")); @@ -1030,7 +1017,6 @@ */ TEST_FEATURE ("with configuration overriding built-ins"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->env = nih_str_array_new (class); assert (nih_str_array_add (&(class->env), class, NULL, "FOO=BAR")); @@ -1089,7 +1075,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); message = nih_new (NULL, NihDBusMessage); @@ -1127,7 +1112,6 @@ */ TEST_FEATURE ("with unknown job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; @@ -1159,7 +1143,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$FOO"; job = job_new (class, "wibble"); @@ -1204,7 +1187,6 @@ */ TEST_FEATURE ("with invalid environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$FOO"; job = job_new (class, "wibble"); @@ -1248,7 +1230,6 @@ nih_error_init (); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; /* Check that when given a known instance name, the path to that @@ -1379,7 +1360,6 @@ job_class_init (); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; /* Check that paths for each of the active instances are returned @@ -1513,7 +1493,6 @@ */ TEST_FEATURE ("with new job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; method = dbus_message_new_method_call ( dbus_bus_get_unique_name (conn), @@ -1605,7 +1584,6 @@ */ TEST_FEATURE ("with no wait"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; method = dbus_message_new_method_call ( dbus_bus_get_unique_name (conn), @@ -1686,7 +1664,6 @@ */ TEST_FEATURE ("with stopping job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_STOP; @@ -1788,7 +1765,6 @@ */ TEST_FEATURE ("with starting job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -1845,7 +1821,6 @@ */ TEST_FEATURE ("with environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$FOO"; method = dbus_message_new_method_call ( @@ -1947,7 +1922,6 @@ */ TEST_FEATURE ("with invalid environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; method = dbus_message_new_method_call ( dbus_bus_get_unique_name (conn), @@ -2034,7 +2008,6 @@ */ TEST_FEATURE ("with running job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -2118,7 +2091,6 @@ */ TEST_FEATURE ("with no wait"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -2189,7 +2161,6 @@ */ TEST_FEATURE ("with stopping job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_STOP; @@ -2245,7 +2216,6 @@ */ TEST_FEATURE ("with unknown job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; method = dbus_message_new_method_call ( dbus_bus_get_unique_name (conn), @@ -2295,7 +2265,6 @@ */ TEST_FEATURE ("with environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$FOO"; job = job_new (class, "wibble"); @@ -2385,7 +2354,6 @@ */ TEST_FEATURE ("with invalid environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -2475,7 +2443,6 @@ */ TEST_FEATURE ("with running job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -2573,7 +2540,6 @@ */ TEST_FEATURE ("with no wait"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -2655,7 +2621,6 @@ */ TEST_FEATURE ("with stopping job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_STOP; @@ -2711,7 +2676,6 @@ */ TEST_FEATURE ("with unknown job"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; method = dbus_message_new_method_call ( dbus_bus_get_unique_name (conn), @@ -2761,7 +2725,6 @@ */ TEST_FEATURE ("with environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$FOO"; job = job_new (class, "wibble"); @@ -2875,7 +2838,6 @@ */ TEST_FEATURE ("with invalid environment"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -2952,7 +2914,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; @@ -3005,7 +2966,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->description = nih_strdup (class, "a test job"); message = nih_new (NULL, NihDBusMessage); @@ -3046,7 +3006,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; @@ -3099,7 +3058,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->author = nih_strdup (class, "a test job"); message = nih_new (NULL, NihDBusMessage); @@ -3140,7 +3098,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; @@ -3193,7 +3150,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->version = nih_strdup (class, "a test job"); message = nih_new (NULL, NihDBusMessage); @@ -3234,7 +3190,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; @@ -3290,7 +3245,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->start_on = event_operator_new ( class, EVENT_OR, NULL, NULL); @@ -3386,7 +3340,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; @@ -3443,7 +3396,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->stop_on = event_operator_new ( class, EVENT_OR, NULL, NULL); @@ -3539,7 +3491,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; @@ -3595,7 +3546,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->emits = nih_str_array_new (class); NIH_MUST (nih_str_array_add (&class->emits, class, NULL, "foo")); @@ -3648,7 +3598,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; message = nih_new (NULL, NihDBusMessage); message->connection = NULL; reverted: --- upstart-1.3/init/tests/test_job.c +++ upstart-1.3.orig/init/tests/test_job.c @@ -147,8 +147,6 @@ TEST_EQ (job->trace_forks, 0); TEST_EQ (job->trace_state, TRACE_NONE); - TEST_EQ_P (job->log, NULL); - event_operator_reset (job->stop_on); nih_free (job); @@ -693,7 +691,6 @@ mkdir (dirname, 0700); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = nih_sprintf ( class->process[PROCESS_MAIN], "touch %s/run", dirname); @@ -1043,9 +1040,6 @@ job->failed_process = -1; job->exit_status = 0; - nih_message ("DEBUG: test_alloc_failed=%d, _test_alloc_count=%d, _test_alloc_call=%d, __nih_malloc=%p, __nih_realloc=%p, malloc=%p, realloc=%p", - test_alloc_failed, _test_alloc_count, _test_alloc_call, (void *)__nih_malloc, (void *)__nih_realloc, (void *)malloc, (void *)realloc); - job_change_state (job, JOB_PRE_START); TEST_EQ (job->goal, JOB_START); reverted: --- upstart-1.3/init/tests/test_job_process.c +++ upstart-1.3.orig/init/tests/test_job_process.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -55,83 +54,6 @@ #include "errors.h" -#define EXPECTED_JOB_LOGDIR "/var/log/upstart" -#define EXPECTED_USER_JOB_LOGDIR ".cache/upstart/log" -#define TEST_SHELL "/bin/sh" -#define TEST_SHELL_ARG "-e" - -/* Used to generate single- and multi-line output. */ -#define TEST_CMD_ECHO "/bin/echo" - -/* Used to generate multi-line output out stdout without using shell - * meta-characters. - */ -#define TEST_CMD_YES "/usr/bin/yes" - -/* Used to generate multi-line output on stderr without using shell - * meta-characters. - */ -#define TEST_CMD_DD "/bin/dd" - -/* Used to generate newlines without having to use shell - * meta-characters. - */ -#define TEST_CMD_DATE "/bin/date" - -/* Force an inotify watch update */ -#define TEST_FORCE_WATCH_UPDATE() \ -{ \ - int nfds = 0; \ - int ret = 0; \ - fd_set readfds, writefds, exceptfds; \ - \ - FD_ZERO (&readfds); \ - FD_ZERO (&writefds); \ - FD_ZERO (&exceptfds); \ - \ - nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds); \ - ret = select (nfds, &readfds, &writefds, &exceptfds, NULL); \ - if (ret > 0) \ - nih_io_handle_fds (&readfds, &writefds, &exceptfds); \ -} - -#define TEST_FORCE_WATCH_UPDATE_TIMEOUT(t) \ -{ \ - int nfds = 0; \ - int ret = 0; \ - fd_set readfds, writefds, exceptfds; \ - \ - FD_ZERO (&readfds); \ - FD_ZERO (&writefds); \ - FD_ZERO (&exceptfds); \ - \ - nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds); \ - ret = select (nfds, &readfds, &writefds, &exceptfds, &t); \ - if (ret > 0) \ - nih_io_handle_fds (&readfds, &writefds, &exceptfds); \ -} - -#define ENSURE_DIRECTORY_EMPTY(path) \ -{ \ - DIR *dp = NULL; \ - struct dirent *file = NULL; \ - int count = 0; \ - \ - dp = opendir (path); \ - TEST_NE_P (dp, NULL); \ - \ - while((file = readdir (dp))) { \ - if (!strcmp (".", file->d_name) || \ - !strcmp ("..", file->d_name)) \ - continue; \ - count++; \ - } \ - \ - closedir (dp); \ - \ - TEST_EQ (count, 0); \ -} - /* Sadly we can't test everything that job_process_spawn() does simply because * a lot of it can only be done by root, or in the case of the console stuff, * kills whatever had /dev/console (usually X). @@ -143,8 +65,7 @@ TEST_PIDS, TEST_CONSOLE, TEST_PWD, + TEST_ENVIRONMENT - TEST_ENVIRONMENT, - TEST_OUTPUT }; static char *argv0; @@ -189,13 +110,6 @@ for (char **env = environ; *env; env++) fprintf (out, "%s\n", *env); break; - case TEST_OUTPUT: - /* Of course, daemon's usually make a point of not writing to - * stdout/stderr... - */ - fprintf(stdout, "stdout\n"); - fprintf(stderr, "stderr\n"); - break; } fsync (fileno (out)); @@ -206,66 +120,17 @@ exit (0); } -#if 0 -static int -get_available_pty_count (void) -{ - FILE *f; - int nr, max; - int ret; - - f = fopen ("/proc/sys/kernel/pty/max", "r"); - TEST_NE_P (f, NULL); - - ret = fscanf (f, "%d", &max); - TEST_EQ (ret, 1); - TEST_GT (max, 0); - - fclose (f); - - f = fopen ("/proc/sys/kernel/pty/nr", "r"); - TEST_NE_P (f, NULL); - - ret = fscanf (f, "%d", &nr); - TEST_EQ (ret, 1); - TEST_GE (nr, 0); - - fclose (f); - - return max - nr; -} -#endif -/* XXX: Note that none of these tests attempts to test with a Session - * passed to job_class_new() since to do so would modify the home - * directory of the user running these tests (BAD!!). - * - * (Such tests are handled in the bundled test_user_sessions.sh script). - */ void test_run (void) { + JobClass *class = NULL; + Job *job = NULL; + FILE *output; + struct stat statbuf; + char filename[PATH_MAX], buf[80]; + int ret = -1, status, first; + siginfo_t info; - char dirname[PATH_MAX]; - JobClass *class = NULL; - Job *job = NULL; - FILE *output; - struct stat statbuf; - char filename[PATH_MAX], buf[80]; - int ret = -1, status, first; - siginfo_t info; - char filebuf[1024]; - char *p; - int ok; - - /* FIXME: testing */ -#if 1 - { - info.si_status = 0; - output = NULL; - first = 0; - buf[0] = '\0'; - } -#endif TEST_FUNCTION ("job_process_run"); job_class_init (); @@ -275,7 +140,6 @@ TEST_FILENAME (filename); program_name = "test"; -#if 0 /* Check that we can run a simple command, and have the process id * and state filled in. We should be able to wait for the pid to * finish and see that it has been run as expected. @@ -284,7 +148,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = nih_sprintf ( class->process[PROCESS_MAIN], @@ -317,7 +180,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = nih_sprintf ( class->process[PROCESS_MAIN], @@ -355,7 +217,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->script = TRUE; class->process[PROCESS_MAIN]->command = nih_sprintf ( @@ -393,7 +254,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->script = TRUE; class->process[PROCESS_MAIN]->command = nih_sprintf ( @@ -431,7 +291,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->script = TRUE; class->process[PROCESS_MAIN]->command = nih_sprintf ( @@ -469,7 +328,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = nih_sprintf ( class->process[PROCESS_MAIN], @@ -504,7 +362,6 @@ TEST_FILE_EQ (output, "BAR=BAZ\n"); TEST_FILE_EQ (output, "UPSTART_JOB=test\n"); TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n"); - TEST_FILE_EQ (output, "UPSTART_NO_SESSIONS=1\n"); TEST_FILE_END (output); fclose (output); unlink (filename); @@ -520,7 +377,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = nih_sprintf ( class->process[PROCESS_MAIN], @@ -555,7 +411,6 @@ TEST_FILE_EQ (output, "BAR=BAZ\n"); TEST_FILE_EQ (output, "UPSTART_JOB=test\n"); TEST_FILE_EQ (output, "UPSTART_INSTANCE=foo\n"); - TEST_FILE_EQ (output, "UPSTART_NO_SESSIONS=1\n"); TEST_FILE_END (output); fclose (output); unlink (filename); @@ -572,7 +427,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_PRE_STOP] = process_new (class); class->process[PROCESS_PRE_STOP]->command = nih_sprintf ( class->process[PROCESS_PRE_STOP], @@ -608,7 +462,6 @@ TEST_FILE_EQ (output, "CRACKLE=FIZZ\n"); TEST_FILE_EQ (output, "UPSTART_JOB=test\n"); TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n"); - TEST_FILE_EQ (output, "UPSTART_NO_SESSIONS=1\n"); TEST_FILE_END (output); fclose (output); unlink (filename); @@ -625,7 +478,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_POST_STOP] = process_new (class); class->process[PROCESS_POST_STOP]->command = nih_sprintf ( class->process[PROCESS_POST_STOP], @@ -661,7 +513,6 @@ TEST_FILE_EQ (output, "CRACKLE=FIZZ\n"); TEST_FILE_EQ (output, "UPSTART_JOB=test\n"); TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n"); - TEST_FILE_EQ (output, "UPSTART_NO_SESSIONS=1\n"); TEST_FILE_END (output); fclose (output); unlink (filename); @@ -678,7 +529,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->script = TRUE; class->process[PROCESS_MAIN]->command = nih_alloc ( @@ -744,7 +594,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = "true"; @@ -781,7 +630,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_PRE_START] = process_new (class); class->process[PROCESS_PRE_START]->command = "true"; @@ -819,7 +667,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->expect = EXPECT_DAEMON; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = "true"; @@ -867,7 +714,6 @@ TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->expect = EXPECT_FORK; class->process[PROCESS_MAIN] = process_new (class); class->process[PROCESS_MAIN]->command = "true"; @@ -903,1849 +749,60 @@ TEST_EQ (info.si_code, CLD_EXITED); TEST_EQ (info.si_status, 0); + nih_free (class); + } - nih_free (class); - } - - - /* Check that if we try and run a command that doesn't exist, - * job_process_run() raises a ProcessError and the command doesn't - * have any stored process id for it. - */ - TEST_FEATURE ("with no such file"); - output = tmpfile (); - - TEST_ALLOC_FAIL { - TEST_ALLOC_SAFE { - class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = filename; - - job = job_new (class, "foo"); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - } - - TEST_DIVERT_STDERR (output) { - ret = job_process_run (job, PROCESS_MAIN); - } - rewind (output); - TEST_LT (ret, 0); - - TEST_EQ (job->pid[PROCESS_MAIN], 0); - - TEST_FILE_EQ (output, ("test: Failed to spawn test (foo) main " - "process: unable to execute: " - "No such file or directory\n")); - TEST_FILE_END (output); - TEST_FILE_RESET (output); - - nih_free (class); - } -#endif - - - TEST_FILENAME (dirname); - TEST_EQ (mkdir (dirname, 0755), 0); - - /* Override default location to ensure job output goes to a - * writeable location - */ - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - -#if 0 - /************************************************************/ - TEST_FEATURE ("ensure that no log file written for single-line no-output script"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_strdup ( - class->process[PROCESS_MAIN], - "/bin/true"); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - ENSURE_DIRECTORY_EMPTY (dirname); - - /* Paranoia */ - TEST_TRUE (stat (filename, &statbuf) < 0 && errno == ENOENT); - - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("ensure that no log file written for single-line no-output command"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_strdup ( - class->process[PROCESS_MAIN], - "/bin/true"); - class->process[PROCESS_MAIN]->script = FALSE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - ENSURE_DIRECTORY_EMPTY (dirname); - - /* Paranoia */ - TEST_TRUE (stat (filename, &statbuf) < 0 && errno == ENOENT); - - nih_free (class); -#endif - - /************************************************************/ - TEST_FEATURE ("ensure that no log file written for CONSOLE_NONE"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_NONE; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s hello world", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - - TEST_EQ (WEXITSTATUS (status), 0); - - /* If a log is written, select(2) will inform us, but we don't - * expect this, hence specify a timeout. - */ - { - struct timeval t; - /* be generous */ - t.tv_usec = 500000; - TEST_FORCE_WATCH_UPDATE_TIMEOUT (t); - } - - ENSURE_DIRECTORY_EMPTY (dirname); - - /* Paranoia */ - TEST_TRUE (stat (filename, &statbuf) < 0 && errno == ENOENT); - - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("ensure that no log file written for multi-line no-output script"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_strdup ( - class->process[PROCESS_MAIN], - "/bin/true\n/bin/false"); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - /* XXX: call 1: wait for script write to child shell */ - TEST_FORCE_WATCH_UPDATE (); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - - /* we've just run /bin/false remember? :) */ - TEST_EQ (WEXITSTATUS (status), 1); - - /* XXX: call 2: wait for read from pty allowing logger to write to log file */ - TEST_FORCE_WATCH_UPDATE (); - - ENSURE_DIRECTORY_EMPTY (dirname); - - /* Paranoia */ - TEST_TRUE (stat (filename, &statbuf) < 0 && errno == ENOENT); - - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that writes 1 line to stdout"); - - /* Note we can't use TEST_ALLOC_FAIL() for this test since on - * the ENOMEM loop all we could do is discard the error and - * continue since job_process_run() calls job_process_spawn() - * repeatedly until it works, but the alloc fails in log_new() - * invoked by job_process_spawn() such that when we've left - * job_process_run(), it's too late. - * - * However, we test this scenario in test_spawn() so all is not - * lost. - */ - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s hello world", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that is killed"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s hello world;sleep 999", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - /* wait for read from pty allowing logger to write to log file */ - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (kill (job->pid[PROCESS_MAIN], SIGKILL), 0); - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFSIGNALED (status)); - TEST_EQ (WTERMSIG (status), SIGKILL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line command that is killed"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s", TEST_CMD_YES); - class->process[PROCESS_MAIN]->script = FALSE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - /* wait for read from pty allowing logger to write to log file */ - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (kill (job->pid[PROCESS_MAIN], SIGKILL), 0); - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFSIGNALED (status)); - TEST_EQ (WTERMSIG (status), SIGKILL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - /* XXX: this _might_ be a kernel? bug - sometimes we don't read - * the final line end character (presumably since the process - * was forcibly killed). - */ - while (fgets (filebuf, sizeof(filebuf), output) != NULL) { - if (! strcmp (filebuf, "y\r\n")) - ok = 1; - else if (! strcmp (filebuf, "y") && feof (output)) - ok = 1; - else - ok = 0; - - if (! ok) - break; - } - TEST_EQ (ok, 1); - - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with multi-line script that is killed"); - - /* Note we can't use TEST_ALLOC_FAIL() for this test since on - * the ENOMEM loop all we could do is discard the error and - * continue since job_process_run() calls job_process_spawn() - * repeatedly until it works, but the alloc fails in log_new() - * invoked by job_process_spawn() such that when we've left - * job_process_run(), it's too late. - * - * However, we test this scenario in test_spawn() so all is not - * lost. - */ - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s hello world\nsleep 999", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - /* XXX: call 1: wait for script write to child shell */ - TEST_FORCE_WATCH_UPDATE (); - - /* XXX: call 2: wait for read from pty allowing logger to write to log file */ - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (kill (job->pid[PROCESS_MAIN], SIGKILL), 0); - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFSIGNALED (status)); - TEST_EQ (WTERMSIG (status), SIGKILL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that writes 1 byte and is killed"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s -ne X;sleep 999", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - /* wait for read from pty allowing logger to write to log file */ - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (kill (job->pid[PROCESS_MAIN], SIGKILL), 0); - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFSIGNALED (status)); - TEST_EQ (WTERMSIG (status), SIGKILL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "X"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - /* Can't think of a command that would echo 1 byte and then - * either sleep or read a file forever to allow us time to kill - * it *after* it had written the single byte. Answers on a - * postcard please. - * - * TEST_FEATURE ("with single-line command that writes 1 byte and is killed"); - */ - - /************************************************************/ - TEST_FEATURE ("with multi-line script that writes 1 byte and is killed"); - - class = job_class_new (NULL, "multiline", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/multiline.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "/bin/true\n%s -ne F", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - /* XXX: call 1: wait for script write to child shell */ - TEST_FORCE_WATCH_UPDATE (); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - /* XXX: call 2: wait for read from pty allowing logger to write to log file */ - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "F"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line command that writes 1 line to stdout"); - - /* Note we can't use TEST_ALLOC_FAIL() for this test since on - * the ENOMEM loop all we could do is discard the error and - * continue since job_process_run() calls job_process_spawn() - * repeatedly until it works, but the alloc fails in log_new() - * invoked by job_process_spawn() such that when we've left - * job_process_run(), it's too late. - * - * However, we test this scenario in test_spawn() so all is not - * lost. - */ - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s hello world", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = FALSE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with multi-line script that writes 1 line to stdout"); - - /* XXX: Note that all tests which use multi-line scripts (but - * XXX: *NOT* commands!) and produce output must call - * XXX: TEST_FORCE_WATCH_UPDATE() *TWICE* to ensure select(2) is - * XXX: called twice. - * - * This is required since job_process_run() uses an NihIo object - * to squirt the script to the shell sub-process and this - * triggers select to return when the data is written to the shell. - * However, we don't care about that directly - we care more about - * a subsequent fd becoming ready to read data from - the fd - * associated with the pty which will trigger the log file to be - * written. - * - * Note that the 2nd call to TEST_FORCE_WATCH_UPDATE would not be - * required should job_process_run() simple invoke write(2) to - * send the data. - */ - - class = job_class_new (NULL, "multiline", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/multiline.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "/bin/true\n%s hello world\n\n\n\n\n\n\n\n\n\n", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - /* XXX: call 1: wait for script write to child shell */ - TEST_FORCE_WATCH_UPDATE (); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - /* XXX: call 2: wait for read from pty allowing logger to write to log file */ - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with instance job and single-line script that writes 1 line to stdout"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test-instance.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s hello world", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, "instance"); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that writes >1 lines to stdout"); - - class = job_class_new (NULL, "foo", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/foo.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "%s -ne \"hello world\\n\\n\\n\"", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - /* Yup, pseudo-terminals record *everything*, - * even the carriage returns. - */ - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line command that writes >1 lines to stdout"); - - class = job_class_new (NULL, "foo", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/foo.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "%s -ne \"hello world\\n\\n\\n\"", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = FALSE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with multi-line script that writes >1 lines to stdout"); - - class = job_class_new (NULL, "elf", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/elf.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "\n/bin/true\n%s -ne \"hello world\\n\\n\\n\"\n\n", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - TEST_FORCE_WATCH_UPDATE (); - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that writes 1 line to stderr"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s hello world >&2", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line command that writes 1 line to stderr"); - - /* Run a command that generates output to stderr without having - * to use script redirection. - * - * dd(1) is a good choice as it always writes to stderr. - */ - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s if=/dev/zero of=/dev/null bs=1 count=0", TEST_CMD_DD); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "0+0 records in\r\n"); - TEST_FILE_EQ (output, "0+0 records out\r\n"); - TEST_FILE_MATCH (output, "0 bytes (0 B) copied,*\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with multi-line script that writes 1 line to stderr"); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "/bin/true\n%s hello world >&2\n\n\n", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - TEST_FORCE_WATCH_UPDATE (); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that writes >1 lines to stderr"); - - class = job_class_new (NULL, "foo", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/foo.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "%s -ne \"hello\\nworld\\n\\n\\n\" >&2", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - /* Yup, pseudo-terminals record *everything*, - * even the carriage returns. - */ - TEST_FILE_EQ (output, "hello\r\n"); - TEST_FILE_EQ (output, "world\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line command that writes >1 lines to stderr"); - - class = job_class_new (NULL, "foo", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/foo.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "%s -ne \"hello world\\n\\n\\n\"", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = FALSE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with multi-line script that writes >1 lines to stderr"); - - class = job_class_new (NULL, "elf", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/elf.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "/bin/true\n%s -ne \"hello world\\n\\n\" 1>&2\n\n\n", TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - TEST_FORCE_WATCH_UPDATE (); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_EQ (output, "\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that writes 1 line to stdout then 1 line to stderr"); - - class = job_class_new (NULL, "blah", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/blah.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "%s stdout;%s stderr >&2", - TEST_CMD_ECHO, TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "stdout\r\n"); - TEST_FILE_EQ (output, "stderr\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script that writes 1 line to stderr then 1 line to stdout"); - - class = job_class_new (NULL, "blah", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/blah.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - /* XXX: note the required quoting */ - "%s stderr >&2;%s stdout", - TEST_CMD_ECHO, TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "stderr\r\n"); - TEST_FILE_EQ (output, "stdout\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line command that writes to stdout and stderr"); - - class = job_class_new (NULL, "blah", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/blah.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s if=/dev/zero bs=1 count=7", TEST_CMD_DD); - class->process[PROCESS_MAIN]->script = FALSE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_NE_P (fgets (filebuf, sizeof(filebuf), output), NULL); - TEST_EQ (memcmp (filebuf, "\000\000\000\000\000\000", 7), 0); - p = filebuf + 7; - TEST_EQ_STR (p, "7+0 records in\r\n"); - - TEST_FILE_EQ (output, "7+0 records out\r\n"); - TEST_FILE_MATCH (output, "7 bytes (7 B) copied,*\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with single-line script running an invalid command"); - - class = job_class_new (NULL, "blah", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/blah.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_strdup ( - class->process[PROCESS_MAIN], - "/this/command/does/not/exist"); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_NE (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "/bin/sh: 1: /this/command/does/not/exist: not found\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************ - * No point in running a test for: - * - * TEST_FEATURE ("with single-line command running an invalid command"); - * - * Since as such commands are exec'ed directly, there is no shell to report - * an error back - exec just fails. - * - ************************************************************/ - - /************************************************************/ - TEST_FEATURE ("with multi-line script running an invalid command"); - - class = job_class_new (NULL, "blah", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/blah.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_strdup ( - class->process[PROCESS_MAIN], - "true\n/this/command/does/not/exist"); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - TEST_FORCE_WATCH_UPDATE (); - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_NE (WEXITSTATUS (status), 0); - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "/proc/self/fd/9: 3: /this/command/does/not/exist: not found\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with multi-line script that writes 1 line to stdout then 1 line to stderr"); - - class = job_class_new (NULL, "blah", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/blah.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s stdout\n%s stderr >&2\n", - TEST_CMD_ECHO, TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - TEST_FORCE_WATCH_UPDATE (); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "stdout\r\n"); - TEST_FILE_EQ (output, "stderr\r\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (class); - - /************************************************************/ - TEST_FEATURE ("with multi-line script that writes 1 line to stderr then 1 line to stdout"); - - class = job_class_new (NULL, "blah", NULL); - TEST_NE_P (class, NULL); - - TEST_FILENAME (filename); - TEST_GT (sprintf (filename, "%s/blah.log", dirname), 0); - - class->console = CONSOLE_LOG; - class->process[PROCESS_MAIN] = process_new (class); - class->process[PROCESS_MAIN]->command = nih_sprintf ( - class->process[PROCESS_MAIN], - "%s stderr >&2\n%s stdout\n", - TEST_CMD_ECHO, TEST_CMD_ECHO); - class->process[PROCESS_MAIN]->script = TRUE; - - job = job_new (class, ""); - job->goal = JOB_START; - job->state = JOB_SPAWNED; - - ret = job_process_run (job, PROCESS_MAIN); - TEST_EQ (ret, 0); - - TEST_NE (job->pid[PROCESS_MAIN], 0); - - TEST_FORCE_WATCH_UPDATE (); - - waitpid (job->pid[PROCESS_MAIN], &status, 0); - TEST_TRUE (WIFEXITED (status)); - TEST_EQ (WEXITSTATUS (status), 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); + /* Check that if we try and run a command that doesn't exist, + * job_process_run() raises a ProcessError and the command doesn't + * have any stored process id for it. + */ + TEST_FEATURE ("with no such file"); + output = tmpfile (); - TEST_FILE_EQ (output, "stderr\r\n"); - TEST_FILE_EQ (output, "stdout\r\n"); - TEST_FILE_END (output); - fclose (output); + TEST_ALLOC_FAIL { + TEST_ALLOC_SAFE { + class = job_class_new (NULL, "test", NULL); + class->process[PROCESS_MAIN] = process_new (class); + class->process[PROCESS_MAIN]->command = filename; - TEST_EQ (unlink (filename), 0); - nih_free (class); + job = job_new (class, "foo"); + job->goal = JOB_START; + job->state = JOB_SPAWNED; + } - /************************************************************/ - /* Final clean-up */ + TEST_DIVERT_STDERR (output) { + ret = job_process_run (job, PROCESS_MAIN); + } + rewind (output); + TEST_LT (ret, 0); - TEST_EQ (rmdir (dirname), 0); - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); + TEST_EQ (job->pid[PROCESS_MAIN], 0); - /* FIXME */ - return; + TEST_FILE_EQ (output, ("test: Failed to spawn test (foo) main " + "process: unable to execute: " + "No such file or directory\n")); + TEST_FILE_END (output); + TEST_FILE_RESET (output); - TEST_FEATURE ("with single-line script that writes 1 line to stderr, >1 line to stdout"); - TEST_FEATURE ("with multi-line script that writes 1 line to stderr, >1 line to stdout"); - TEST_FEATURE ("with single-line command that writes 1 line to stdout, >1 line to stderr"); + nih_free (class); + } - TEST_FEATURE ("with single-line script that writes >1 line to stderr, 1 line to stdout"); - TEST_FEATURE ("with multi-line script that writes >1 line to stderr, 1 line to stdout"); - TEST_FEATURE ("with single-line command that writes >1 line to stdout, 1 line to stderr"); - - TEST_FEATURE ("with single-line script that writes >1 line to stderr, >1 line to stdout"); - TEST_FEATURE ("with multi-line script that writes >1 line to stderr, >1 line to stdout"); - TEST_FEATURE ("with single-line command that writes >1 line to stdout, >1 line to stderr"); - - TEST_FEATURE ("with single-line script that writes slowly: >1 line to stderr, >1 line to stdout"); - TEST_FEATURE ("with multi-line script that writes slowly: >1 line to stderr, >1 line to stdout"); - TEST_FEATURE ("with single-line command that writes slowly: >1 line to stdout, >1 line to stderr"); - - /* XXX: ensure that file appended to */ - TEST_FEATURE ("with job that has a pre-start, main and post-stop scripts"); } -/* XXX: Note that none of these tests attempts to test with a Session - * passed to job_class_new() since to do so would modify the home - * directory of the user running these tests (BAD!!). - * - * (Such tests are handled in the bundled test_user_sessions.sh script). - */ void test_spawn (void) { + FILE *output; - FILE *output, *input; char function[PATH_MAX], filename[PATH_MAX]; + char buf[80]; + char *env[3], *args[4]; - char dirname[PATH_MAX]; - char script[PATH_MAX]; - //char buf[80]; - char filebuf[1024]; - char *args[6]; - //char *env[3]; - nih_local char **args_array = NULL; - size_t argc; JobClass *class; - Job *job; pid_t pid; + siginfo_t info; + NihError *err; + JobProcessError *perr; - //siginfo_t info; - //NihError *err; - //JobProcessError *perr; int status; - //int fds[2] = { -1, -1 }; - //int pty, ptys; - //int ret; - TEST_FUNCTION ("job_process_spawn"); TEST_FILENAME (filename); @@ -2755,7 +812,6 @@ args[2] = filename; args[3] = NULL; -#if 0 /* Check that we can spawn a simple job, waiting for the child * process to complete and reading from the file written to check * that the process tree is what we expect it to look like. @@ -2764,10 +820,8 @@ sprintf (function, "%d", TEST_PIDS); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; - job = job_new (class, ""); + pid = job_process_spawn (class, args, NULL, FALSE, -1); - pid = job_process_spawn (job, args, NULL, FALSE, -1); TEST_GT (pid, 0); waitpid (pid, NULL, 0); @@ -2804,9 +858,8 @@ class = job_class_new (NULL, "test", NULL); class->console = CONSOLE_NONE; - job = job_new (class, ""); + pid = job_process_spawn (class, args, NULL, FALSE, -1); - pid = job_process_spawn (job, args, NULL, FALSE, -1); TEST_GT (pid, 0); waitpid (pid, NULL, 0); @@ -2822,52 +875,6 @@ nih_free (class); - /* Check that a job spawned with a log console has file descriptors: - * - * 0 bound to the /dev/null device. - * 1 bound to the pseudo-tty device. - * 2 bound to the pseudo-tty device. - * - */ - TEST_FEATURE ("with console logging"); - sprintf (function, "%d", TEST_CONSOLE); - - class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_LOG; - job = job_new (class, ""); - - pid = job_process_spawn (job, args, NULL, FALSE, -1); - TEST_GT (pid, 0); - - waitpid (pid, NULL, 0); - output = fopen (filename, "r"); - - /* /dev/null */ - TEST_FILE_EQ (output, "0: 1 3\n"); - - /* stdout and stderr should be bound to the same Unix98 PTY slave - * device (one of the char devices in range 136-143). - * We ignore the minor as it could be any value. - */ - { - unsigned int major, saved_major; - - TEST_EQ (fscanf (output, "1: %u %*\n", &major, &minor), 2); - TEST_TRUE (major >= 136 && major <= 143); - saved_major = major; - - TEST_EQ (fscanf (output, "2: %u %*\n", &major, &minor), 2); - TEST_TRUE (major == saved_major); - } - - - TEST_FILE_END (output); - - fclose (output); - unlink (filename); - - nih_free (class); - /* Check that a job with an alternate working directory is run from * that directory. @@ -2876,11 +883,9 @@ sprintf (function, "%d", TEST_PWD); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->chdir = "/tmp"; - job = job_new (class, ""); + pid = job_process_spawn (class, args, NULL, FALSE, -1); - pid = job_process_spawn (job, args, NULL, FALSE, -1); TEST_GT (pid, 0); waitpid (pid, NULL, 0); @@ -2907,10 +912,8 @@ env[2] = NULL; class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; - job = job_new (class, ""); + pid = job_process_spawn (class, args, env, FALSE, -1); - pid = job_process_spawn (job, args, env, FALSE, -1); TEST_GT (pid, 0); waitpid (pid, NULL, 0); @@ -2934,10 +937,8 @@ sprintf (function, "%d", TEST_SIMPLE); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; - job = job_new (class, ""); + pid = job_process_spawn (class, args, NULL, FALSE, -1); - pid = job_process_spawn (job, args, NULL, FALSE, -1); TEST_GT (pid, 0); assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED)); @@ -2956,8 +957,8 @@ sprintf (function, "%d", TEST_SIMPLE); class = job_class_new (NULL, "test", NULL); + + pid = job_process_spawn (class, args, NULL, TRUE, -1); - class->console = CONSOLE_NONE; - job = job_new (class, ""); TEST_GT (pid, 0); assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED)); @@ -2985,10 +986,8 @@ args[2] = NULL; class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; - job = job_new (class, ""); + pid = job_process_spawn (class, args, NULL, FALSE, -1); - pid = job_process_spawn (job, args, NULL, FALSE, -1); TEST_LT (pid, 0); err = nih_error_get (); @@ -3006,16 +1005,14 @@ TEST_FEATURE ("with debug enabled"); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->debug = TRUE; - job = job_new (class, ""); sprintf (function, "%s", "/bin/true"); args[0] = function; args[1] = function; args[2] = NULL; + pid = job_process_spawn (class, args, NULL, FALSE, -1); - pid = job_process_spawn (job, args, NULL, FALSE, -1); TEST_GT (pid, 0); /* Ensure process is still running after some period of time. @@ -3036,614 +1033,6 @@ TEST_EQ (WEXITSTATUS (status), 0); nih_free (class); -#endif - - /* FIXME */ -#if 0 - /************************************************************/ - TEST_FEATURE ("simple test"); - - TEST_FILENAME (dirname); - umask(0); - TEST_EQ (mkdir (dirname, 0755), 0); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - TEST_ALLOC_FAIL { - NihError *err; - - TEST_ALLOC_SAFE { - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - argc = 0; - args_array = NIH_MUST (nih_str_array_new (NULL)); - - TEST_FILENAME (script); - input = fopen (script, "w"); - TEST_NE_P (input, NULL); - TEST_GT (fprintf (input, "%s hello world\n", TEST_CMD_ECHO), 0); - fclose (input); - - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); - } - pid = job_process_spawn (job, args_array, NULL, FALSE, -1); - if (test_alloc_failed) { - err = nih_error_get (); - TEST_NE_P (err, NULL); - TEST_EQ (err->number, ENOMEM); - nih_free (err); - TEST_LT (pid, 0); - } else { - TEST_GT (pid, 0); - } - } -#endif - - /************************************************************/ - TEST_FEATURE ("with single-line script and 'console log'"); - - /* Check that we can spawn a job and retrieve its output. - */ - - TEST_FILENAME (dirname); - umask(0); - TEST_EQ (mkdir (dirname, 0755), 0); - - /* Override default location to ensure job output goes to a - * writeable location - */ - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - argc = 0; - args_array = NIH_MUST (nih_str_array_new (NULL)); - - TEST_FILENAME (script); - input = fopen (script, "w"); - TEST_NE_P (input, NULL); - TEST_GT (fprintf (input, "%s hello world\n", TEST_CMD_ECHO), 0); - fclose (input); - - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); - - pid = job_process_spawn (job, args_array, NULL, FALSE, -1); - TEST_GT (pid, 0); - - TEST_EQ (waitpid (pid, &status, 0), pid); - TEST_TRUE (WIFEXITED (status)); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - - TEST_EQ (fclose (output), 0); - - unlink (filename); - - TEST_EQ (rmdir (dirname), 0); - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with multi-line script and 'console log'"); - - /* Check that we can spawn a job and retrieve its output. - */ - TEST_FILENAME (dirname); - umask(0); - TEST_EQ (mkdir (dirname, 0755), 0); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - argc = 0; - args_array = NIH_MUST (nih_str_array_new (NULL)); - - TEST_FILENAME (script); - input = fopen (script, "w"); - TEST_NE_P (input, NULL); - TEST_GT (fprintf (input, "/bin/true\n%s hello world\n", TEST_CMD_ECHO), 0); - fclose (input); - - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); - - pid = job_process_spawn (job, args_array, NULL, FALSE, -1); - TEST_GT (pid, 0); - - TEST_EQ (waitpid (pid, &status, 0), pid); - TEST_TRUE (WIFEXITED (status)); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello world\r\n"); - TEST_FILE_END (output); - - TEST_EQ (fclose (output), 0); - - unlink (filename); - - TEST_EQ (rmdir (dirname), 0); - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("read single null byte with 'console log'"); - - /* Check that we can spawn a job and read a single byte written - * to stdout. - */ - - TEST_FILENAME (dirname); - umask(0); - TEST_EQ (mkdir (dirname, 0755), 0); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - argc = 0; - args_array = NIH_MUST (nih_str_array_new (NULL)); - - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_CMD_ECHO)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "-en")); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "\\000")); - - pid = job_process_spawn (job, args_array, NULL, FALSE, -1); - TEST_GT (pid, 0); - - TEST_EQ (waitpid (pid, &status, 0), pid); - TEST_TRUE (WIFEXITED (status)); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_NE_P (fgets (filebuf, sizeof(filebuf), output), NULL); - TEST_EQ (memcmp (filebuf, "\000", 1), 0); - TEST_FILE_END (output); - - TEST_EQ (fclose (output), 0); - - unlink (filename); - - TEST_EQ (rmdir (dirname), 0); - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("read data from forked process"); - - TEST_FILENAME (dirname); - umask(0); - TEST_EQ (mkdir (dirname, 0755), 0); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - sprintf (function, "%d", TEST_OUTPUT); - - /* fork */ - sprintf (filebuf, "%d", 1); - TEST_FILENAME (script); - - args[0] = argv0; - args[1] = function; - args[2] = script; - args[3] = filebuf; - args[4] = NULL; - - pid = job_process_spawn (job, args, NULL, FALSE, -1); - TEST_GT (pid, 0); - - TEST_EQ (waitpid (pid, &status, 0), pid); - TEST_TRUE (WIFEXITED (status)); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "stdout\r\n"); - TEST_FILE_EQ (output, "stderr\r\n"); - TEST_FILE_END (output); - - TEST_EQ (fclose (output), 0); - - unlink (filename); - - TEST_EQ (rmdir (dirname), 0); - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("read data from daemon process"); - - TEST_FILENAME (dirname); - umask(0); - TEST_EQ (mkdir (dirname, 0755), 0); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - sprintf (function, "%d", TEST_OUTPUT); - - /* daemonize */ - sprintf (filebuf, "%d", 2); - TEST_FILENAME (script); - - args[0] = argv0; - args[1] = function; - args[2] = script; - args[3] = filebuf; - args[4] = NULL; - - pid = job_process_spawn (job, args, NULL, FALSE, -1); - TEST_GT (pid, 0); - - TEST_EQ (waitpid (pid, &status, 0), pid); - TEST_TRUE (WIFEXITED (status)); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "stdout\r\n"); - TEST_FILE_EQ (output, "stderr\r\n"); - TEST_FILE_END (output); - - TEST_EQ (fclose (output), 0); - - unlink (filename); - - TEST_EQ (rmdir (dirname), 0); - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - - nih_free (job); - - -#if 0 - /************************************************************/ - TEST_FEATURE ("when no free ptys"); - - TEST_FILENAME (dirname); - umask(0); - TEST_EQ (mkdir (dirname, 0755), 0); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - class = job_class_new (NULL, "test", NULL); - TEST_NE_P (class, NULL); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - ptys = get_available_pty_count (); -// TEST_GT (ptys, 1); - fprintf(stderr, "ptys=%d\n", (int)ptys); - - { - int last = -1; - - /* FIXME */ - ptys=4096; - for (pty = 0; pty < ptys; ++pty) { - ret = posix_openpt (O_RDWR | O_NOCTTY); - fprintf(stderr, "%d posix_openpt returned %d (errno=%d)\n", (int)pty, (int)ret, errno); - //if (ret < 0) { - // break; - //} - if ( ret > 0) last = ret; - } - fprintf(stderr, "BREAK: %d posix_openpt returned %d (errno=%d). last=%d\n", (int)pty, (int)ret, errno, last); - } - - nih_free (job); -#else - TEST_FEATURE ("FIXME: NOT IMPLEMENTED: when no free ptys"); -#endif - - /************************************************************/ - - /* FIXME: test job that produces: - * - * - XXX: test instances - different log names!! - * - XXX: user sessions!! - update script util/tests/test_user_sessions.sh - * - no output - * - output to stdout only - * - output to stderr only - * - output to stdout+stderr - * - outputs 1 null - * - outputs 2 null - * - outputs 87 nulls - * - outputs 1 non-null byte - * - outputs 2 non-null bytes - * - outputs 17 non-nulls - * - outputs mixture of null and non-null bytes to - * stdout+stderr. - * - outputs 1 byte, then sleeps for 2 seconds, then outputs 1 - * more. - * - outputs some data and is then killed? - * - * - XXX: once all tests working, move ptsname_r() to before - * fork() to check that: - * - * /proc/self/fd/0 -> /dev/null - * /proc/self/fd/1 -> /dev/pts/XXX - * /proc/self/fd/2 -> /dev/pts/XXX - */ - - nih_free (class); - - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - -#if 0 - fprintf(stderr, "dirname='%s'\n", dirname); - fprintf(stderr, "XXXX: child pid=%d\n", (int)pid); - fprintf(stderr, "XXXX: script='%s'\n", script); - fprintf(stderr, "XXXX: filename='%s'\n", filename); -#endif -} - -void -test_log_path (void) -{ - JobClass *class = NULL; - Job *job = NULL; - Session *session = NULL; - nih_local char *log_path = NULL; - nih_local char *expected = NULL; - nih_local char *home = NULL; - char dirname[PATH_MAX]; - - TEST_FILENAME (dirname); - - TEST_FUNCTION ("job_process_log_path"); - - /************************************************************/ - TEST_FEATURE ("with system job with simple name"); - - class = job_class_new (NULL, "system", NULL); - TEST_NE_P (class, NULL); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, FALSE); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s.log", - EXPECTED_JOB_LOGDIR, "system")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with system job containing illegal path characters"); - - class = job_class_new (NULL, "//hello_foo bar.z/", NULL); - TEST_NE_P (class, NULL); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, FALSE); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s.log", - EXPECTED_JOB_LOGDIR, "_2f_2fhello_5ffoo_20bar_2ez_2f")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with system job with named instance"); - - class = job_class_new (NULL, "foo bar", NULL); - TEST_NE_P (class, NULL); - job = job_new (class, "bar foo"); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, FALSE); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s.log", - EXPECTED_JOB_LOGDIR, "foo_20bar-bar_20foo")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with system job with named instance and illegal path characters"); - - class = job_class_new (NULL, "a/b", NULL); - TEST_NE_P (class, NULL); - job = job_new (class, "c/d_?/"); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, FALSE); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s.log", - EXPECTED_JOB_LOGDIR, "a_2fb-c_2fd_5f_3f_2f")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with subverted logdir and system job with named instance and illegal path characters"); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - class = job_class_new (NULL, "a/b", NULL); - TEST_NE_P (class, NULL); - job = job_new (class, "c/d_?/"); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, FALSE); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s.log", - dirname, "a_2fb-c_2fd_5f_3f_2f")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - - /************************************************************/ - TEST_FEATURE ("with user job with simple name"); - - session = session_new (NULL, NULL, getuid ()); - TEST_NE_P (session, NULL); - class = job_class_new (NULL, "user", session); - TEST_NE_P (class, NULL); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, TRUE); - - home = session_user_home (NULL, getuid ()); - TEST_NE_P (home, NULL); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s/%s.log", - home, EXPECTED_USER_JOB_LOGDIR, "user")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with user job containing illegal path characters"); - - session = session_new (NULL, NULL, getuid ()); - TEST_NE_P (session, NULL); - class = job_class_new (NULL, "/u/s/e/r//j/o/b/", session); - TEST_NE_P (class, NULL); - job = job_new (class, ""); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, TRUE); - - home = session_user_home (NULL, getuid ()); - TEST_NE_P (home, NULL); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s/%s.log", - home, EXPECTED_USER_JOB_LOGDIR, - "_2fu_2fs_2fe_2fr_2f_2fj_2fo_2fb_2f")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with user job with named instance"); - - session = session_new (NULL, NULL, getuid ()); - TEST_NE_P (session, NULL); - class = job_class_new (NULL, "'job class for a user job'.", session); - TEST_NE_P (class, NULL); - job = job_new (class, "quercus"); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, TRUE); - - home = session_user_home (NULL, getuid ()); - TEST_NE_P (home, NULL); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s/%s-%s.log", - home, EXPECTED_USER_JOB_LOGDIR, - "_27job_20class_20for_20a_20user_20job_27_2e", - "quercus")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with user job with named instance and illegal path characters"); - - session = session_new (NULL, NULL, getuid ()); - TEST_NE_P (session, NULL); - class = job_class_new (NULL, "//'/job class |/&for a user job'.", session); - TEST_NE_P (class, NULL); - job = job_new (class, "/eek / '!' ?"); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, TRUE); - - home = session_user_home (NULL, getuid ()); - TEST_NE_P (home, NULL); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s/%s-%s.log", - home, EXPECTED_USER_JOB_LOGDIR, - "_2f_2f_27_2fjob_20class_20_7c_2f_26" - "for_20a_20user_20job_27_2e", - "_2feek_20_2f_20_27_21_27_20_3f")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - /************************************************************/ - TEST_FEATURE ("with subverted logdir and user job with named instance " - "and illegal path characters"); - - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - - session = session_new (NULL, NULL, getuid ()); - TEST_NE_P (session, NULL); - class = job_class_new (NULL, "//'/job class |/&for a user job'.", session); - TEST_NE_P (class, NULL); - job = job_new (class, "/eek / '!' ?"); - TEST_NE_P (job, NULL); - - log_path = job_process_log_path (job, TRUE); - - home = session_user_home (NULL, getuid ()); - TEST_NE_P (home, NULL); - - expected = NIH_MUST (nih_sprintf (NULL, "%s/%s-%s.log", - dirname, - "_2f_2f_27_2fjob_20class_20_7c_2f_26" - "for_20a_20user_20job_27_2e", - "_2feek_20_2f_20_27_21_27_20_3f")); - TEST_EQ_STR (log_path, expected); - nih_free (job); - - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); } @@ -7343,11 +4732,6 @@ * environment). */ - /* FIXME!!! */ - /* run tests in legacy (pre-session support) mode */ - setenv ("UPSTART_NO_SESSIONS", "1", 1); - - /* We re-exec this binary to test various children features. To * do that, we need to know the full path to the program. */ @@ -7362,24 +4746,6 @@ argv0 = path; } - /* If three arguments are given, the first is the child enum, - * second is a filename to write the result to and the third is - * the number of times to fork. - */ - if (argc == 4) { - int forks = atol (argv[3]); - nih_assert (forks > 0); - - do { - if (fork () != 0) - exit (0); - - } while (forks--); - - child (atoi (argv[1]), argv[2]); - exit (1); - } - /* If two arguments are given, the first is the child enum and the * second is a filename to write the result to. */ @@ -7388,18 +4754,6 @@ exit (1); } - /* FIXME */ -#if 1 - test_run (); - test_spawn (); - test_log_path(); - exit (0); - - /* FIXME */ - test_spawn (); - exit (0); -#endif - /* Otherwise run the tests as normal */ test_run (); test_spawn (); @@ -7411,30 +4765,3 @@ return 0; } - -#if 0 - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL)); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "-c")); - - /* Works!*/ - //NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "/bin/echo hello `date` world > /tmp/foo.log;echo foo")); - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "/bin/echo hello `date` world")); -#endif - -#if 0 - NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "/bin/date")); -#endif - -#if 0 - { - size_t i; - - for(i=0; i < argc; ++i) { - fprintf (stderr, "args_array[%d]='%s'\n", i, args_array[i]); - } - } -#endif - - //env[0] = "PATH=/bin"; - //env[1] = NULL; - diff -u upstart-1.3/init/tests/test_conf.c upstart-1.3/init/tests/test_conf.c --- upstart-1.3/init/tests/test_conf.c +++ upstart-1.3/init/tests/test_conf.c @@ -85,7 +85,9 @@ FD_ZERO (&writefds); \ FD_ZERO (&exceptfds); \ \ + nih_debug("calling nih_io_select_fds"); \ nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds); \ + nih_debug("calling nih_io_handle_fds"); \ nih_io_handle_fds (&readfds, &writefds, &exceptfds); \ } reverted: --- upstart-1.3/init/tests/test_event.c +++ upstart-1.3.orig/init/tests/test_event.c @@ -234,7 +234,6 @@ event = event_new (NULL, "test", NULL); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->process[PROCESS_MAIN] = process_new (class->process); class->process[PROCESS_MAIN]->command = "echo"; @@ -294,7 +293,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->start_on = event_operator_new ( @@ -330,7 +328,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->start_on = event_operator_new ( @@ -390,7 +387,6 @@ TEST_FREE_TAG (event2); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; assert (nih_str_array_add (&(class->env), class, @@ -507,7 +503,6 @@ TEST_FREE_TAG (event2); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; assert (nih_str_array_add (&(class->env), class, @@ -634,7 +629,6 @@ TEST_FREE_TAG (event2); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; assert (nih_str_array_add (&(class->env), class, @@ -803,7 +797,6 @@ TEST_FREE_TAG (event2); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; assert (nih_str_array_add (&(class->env), class, @@ -929,7 +922,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$FRODO"; class->task = TRUE; @@ -1009,7 +1001,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$FRODO"; class->task = TRUE; @@ -1094,7 +1085,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->instance = "$TIPPLE"; class->task = TRUE; @@ -1138,7 +1128,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->process[PROCESS_POST_STOP] = process_new (class); @@ -1187,7 +1176,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->process[PROCESS_POST_STOP] = process_new (class); @@ -1263,7 +1251,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->process[PROCESS_POST_STOP] = process_new (class); @@ -1343,7 +1330,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->process[PROCESS_POST_STOP] = process_new (class); @@ -1454,7 +1440,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->process[PROCESS_POST_STOP] = process_new (class); @@ -1543,7 +1528,6 @@ TEST_FREE_TAG (event1); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->task = TRUE; class->process[PROCESS_POST_STOP] = process_new (class); @@ -1640,7 +1624,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class->process); class->process[PROCESS_MAIN]->command = "echo"; @@ -1675,7 +1658,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class->process); class->process[PROCESS_MAIN]->command = "echo"; @@ -1718,7 +1700,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "test", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_MAIN] = process_new (class->process); class->process[PROCESS_MAIN]->command = "echo"; @@ -1760,7 +1741,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "foo", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_STOP; @@ -1794,7 +1774,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "foo", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -1826,7 +1805,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "foo", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_STOP; @@ -1869,7 +1847,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "foo", NULL); - class->console = CONSOLE_NONE; job = job_new (class, ""); job->goal = JOB_START; @@ -1913,7 +1890,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "foo", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_POST_STOP] = process_new (class); class->process[PROCESS_POST_STOP]->command = "echo"; @@ -1959,7 +1935,6 @@ TEST_FREE_TAG (event); class = job_class_new (NULL, "foo", NULL); - class->console = CONSOLE_NONE; class->process[PROCESS_PRE_START] = process_new (class); class->process[PROCESS_PRE_START]->command = "echo"; reverted: --- upstart-1.3/init/tests/test_log.c +++ upstart-1.3.orig/init/tests/test_log.c @@ -1,1735 +0,0 @@ -/* upstart - * - * test_log.c - test suite for init/log.c - * - * Copyright © 2011 Canonical Ltd. - * Author: James Hunt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include "job.h" - -#define TEST_FORCE_WATCH_UPDATE() \ -{ \ - int nfds = 0; \ - int ret = 0; \ - fd_set readfds, writefds, exceptfds; \ - \ - FD_ZERO (&readfds); \ - FD_ZERO (&writefds); \ - FD_ZERO (&exceptfds); \ - \ - nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds); \ - ret = select (nfds, &readfds, &writefds, &exceptfds, NULL); \ - if (ret > 0) \ - nih_io_handle_fds (&readfds, &writefds, &exceptfds); \ -} - -void -test_log_new (void) -{ - NihError *err; - Log *log; - int fds[2] = { -1, -1 }; - char path[] = "/foo"; - char str[] = "hello, world!"; - char str2[] = "The end?"; - char filename[1024]; - char dirname[1024]; - char buffer[1024]; - ssize_t ret; - ssize_t bytes; - struct stat statbuf; - FILE *output; - mode_t old_perms; - off_t old_size; - - - TEST_FUNCTION ("log_new"); - - TEST_FILENAME (filename); - TEST_FILENAME (dirname); - TEST_EQ (mkdir (dirname, 0755), 0); - TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); - -/* FIXME */ - path[0] = '\0'; - err = NULL; -#if 0 - path[0] = '\0'; - err = NULL; - old_size = 0; - old_perms = 0; - bytes = 0; -#else - -#if 0 - /************************************************************/ - TEST_FEATURE ("object checks with uid 0"); - - TEST_ALLOC_FAIL { - fprintf(stderr, "called\n"); - TEST_EQ (pipe (fds), 0); - log = log_new (NULL, path, fds[0], 0); - // FIXME: can't get this working!! - if (test_alloc_failed) { - TEST_EQ_P (log, NULL); - -#if 0 - err = nih_error_get (); - TEST_EQ (err->number, ENOMEM); - nih_free (err); -#endif - continue; - } - TEST_ALLOC_SIZE (log, sizeof(Log)); - - TEST_ALLOC_PARENT (log->io, log); - TEST_ALLOC_SIZE (log->io, sizeof(NihIo)); - - TEST_ALLOC_PARENT (log->path, log); - - TEST_EQ_STR (log->path, path); - TEST_EQ (log->io->watch->fd, fds[0]); - TEST_EQ (log->uid, 0); - TEST_LT (log->fd, 0); - - close (fds[1]); - - /* frees fds[0] */ - nih_free (log); - } - - /************************************************************/ - TEST_FEATURE ("object checks with uid >0"); - - TEST_ALLOC_FAIL { - TEST_EQ (pipe (fds), 0); - log = log_new (NULL, path, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - if (test_alloc_failed) { - TEST_EQ_P (log, NULL); - continue; - } - TEST_ALLOC_SIZE (log, sizeof(Log)); - - TEST_ALLOC_PARENT (log->io, log); - TEST_ALLOC_SIZE (log->io, sizeof(NihIo)); - - TEST_ALLOC_PARENT (log->path, log); - TEST_ALLOC_SIZE (log->path, sizeof(char *)); - - TEST_EQ (strcmp (path, log->path), 0); - - TEST_EQ (log->io->watch->fd, fds[0]); - TEST_EQ (log->uid, getuid ()); - TEST_LT (log->fd, 0); - - close (fds[1]); - - /* frees fds[0] */ - nih_free (log); - } -#endif - - /************************************************************/ - TEST_FEATURE ("parent check"); - - { - char *string = NIH_MUST (nih_strdup (NULL, str)); - - TEST_EQ (pipe (fds), 0); - - log = log_new (string, path, fds[0], 0); - TEST_NE_P (log, NULL); - TEST_ALLOC_PARENT (log, string); - - nih_free (string); - close (fds[1]); - } - - /************************************************************/ - TEST_FEATURE ("writing a new log file with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing a new log file with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /* FIXME: won't work. */ -#if 0 - /************************************************************/ - TEST_FEATURE ("ensure log flushed when log object destroyed"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - close (fds[1]); - nih_free (log); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - nih_free (log); -#endif - - /************************************************************/ - TEST_FEATURE ("same logger appending to file with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - old_size = statbuf.st_size; - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (pipe (fds), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_NE (statbuf.st_size, 0); - TEST_EQ (statbuf.st_size, old_size + ret); - - TEST_EQ (unlink (filename), 0); - close (fds[1]); - nih_free (log); - - /************************************************************/ - TEST_FEATURE ("same logger appending to file with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - old_size = statbuf.st_size; - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (pipe (fds), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_NE (statbuf.st_size, 0); - TEST_EQ (statbuf.st_size, old_size + ret); - - TEST_EQ (unlink (filename), 0); - close (fds[1]); - nih_free (log); - - /************************************************************/ - TEST_FEATURE ("different logger appending to file with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - bytes = 0; - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - bytes += ret; - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - bytes += ret; - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - old_size = statbuf.st_size; - TEST_EQ (old_size, bytes); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - close (fds[1]); - nih_free (log); - - TEST_EQ (pipe (fds), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, old_size); - - bytes = 0; - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - bytes += ret; - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - bytes += ret; - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, old_size + bytes); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("different logger appending to file with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - bytes = 0; - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - bytes += ret; - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - bytes += ret; - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - old_size = statbuf.st_size; - TEST_EQ (old_size, bytes); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - close (fds[1]); - nih_free (log); - - TEST_EQ (pipe (fds), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, old_size); - - bytes = 0; - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - bytes += ret; - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - bytes += ret; - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, old_size + bytes); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("ensure logging resumes when file made accessible with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - /* Save */ - old_perms = statbuf.st_mode; - - old_size = statbuf.st_size; - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - /* Make file inaccessible */ - TEST_EQ (chmod (filename, 0x0), 0); - - /* Send more data to logger */ - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - /* File shouldn't have changed */ - TEST_EQ (stat (filename, &statbuf), 0); - TEST_EQ (statbuf.st_size, old_size); - - /* Restore access */ - TEST_EQ (chmod (filename, old_perms), 0); - - /* Further data should cause previous data that could not be - * written to be flushed to the file. - */ - ret = write (fds[1], "foo\n", 4); - TEST_EQ (ret, 4); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - TEST_GT (statbuf.st_size, old_size); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - /* Re-check entire file contents */ - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_EQ (output, "foo\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("ensure logging resumes when file made accessible with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - /* Save */ - old_perms = statbuf.st_mode; - - old_size = statbuf.st_size; - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - /* Make file inaccessible */ - TEST_EQ (chmod (filename, 0x0), 0); - - /* Send more data to logger */ - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - /* File shouldn't have changed */ - TEST_EQ (stat (filename, &statbuf), 0); - TEST_EQ (statbuf.st_size, old_size); - - /* Restore access */ - TEST_EQ (chmod (filename, old_perms), 0); - - /* Further data should cause previous data that could not be - * written to be flushed to the file. - */ - ret = write (fds[1], "foo\n", 4); - TEST_EQ (ret, 4); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - TEST_GT (statbuf.st_size, old_size); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - /* Re-check entire file contents */ - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_EQ (output, "foo\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("ensure logger flushes when destroyed with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - TEST_EQ (rmdir (dirname), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - old_perms = umask (0); - TEST_EQ (mkdir (dirname, 0755), 0); - umask (old_perms); - - /* No more data sent to ensure logger writes it on log destroy */ - close (fds[1]); - nih_free (log); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("ensure logger flushes when destroyed with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - TEST_EQ (rmdir (dirname), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - old_perms = umask (0); - TEST_EQ (mkdir (dirname, 0755), 0); - umask (old_perms); - - /* No more data sent to ensure logger writes it on log destroy */ - close (fds[1]); - nih_free (log); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("ensure log written when directory created accessible with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - TEST_EQ (rmdir (dirname), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - old_perms = umask (0); - TEST_EQ (mkdir (dirname, 0755), 0); - umask (old_perms); - - /* Send more data */ - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("ensure log written when directory created accessible with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - TEST_EQ (rmdir (dirname), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - old_perms = umask (0); - TEST_EQ (mkdir (dirname, 0755), 0); - umask (old_perms); - - /* Send more data */ - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); -#endif - - /************************************************************/ - TEST_FEATURE ("ensure remainder of log written when file deleted with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_EQ (fstat (log->fd, &statbuf), 0); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - TEST_EQ (fstat (log->fd, &statbuf), 0); - - /* Send more data */ - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_END (output); - fclose (output); - - close (fds[1]); - nih_free (log); - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("ensure remainder of log written when file deleted with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], str, strlen (str)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_FILE_EQ (output, "hello, world!\n"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /* Send more data */ - ret = write (fds[1], str2, strlen (str2)); - TEST_GT (ret, 0); - ret = write (fds[1], "\n", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_FILE_EQ (output, "The end?\n"); - TEST_FILE_END (output); - fclose (output); - - close (fds[1]); - nih_free (log); - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing 1 null with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], "\000", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_EQ (statbuf.st_size, 1); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, ""); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing 1 null with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], "\000", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, 1); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, ""); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing >1 null with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], "\000\000\000", 3); - TEST_EQ (ret, 3); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_EQ (statbuf.st_size, 3); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "\000\000\000"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing >1 null with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], "\000\000\000", 3); - TEST_EQ (ret, 3); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, 3); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, "\000\000\000"); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing 1 non-printable only with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], " ", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_EQ (statbuf.st_size, 1); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, " "); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing 1 non-printable only with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], " ", 1); - TEST_EQ (ret, 1); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, 1); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_FILE_EQ (output, " "); - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing >1 non-printable only with uid 0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], 0); - TEST_NE_P (log, NULL); - - ret = write (fds[1], "\n \t", 3); - TEST_EQ (ret, 3); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - TEST_EQ (statbuf.st_size, 3); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (fread (buffer, 1, 3, output), 3); - TEST_EQ (buffer[0], '\n'); - TEST_EQ (buffer[1], ' '); - TEST_EQ (buffer[2], '\t'); - - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - TEST_FEATURE ("writing >1 non-printable only with uid >0"); - - TEST_EQ (pipe (fds), 0); - - TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); - TEST_LT (stat (filename, &statbuf), 0); - - log = log_new (NULL, filename, fds[0], getuid ()); - TEST_NE_P (log, NULL); - - ret = write (fds[1], "\n \t", 3); - TEST_EQ (ret, 3); - - TEST_FORCE_WATCH_UPDATE (); - - close (fds[1]); - nih_free (log); - - TEST_EQ (stat (filename, &statbuf), 0); - - TEST_EQ (statbuf.st_uid, getuid ()); - TEST_TRUE (S_ISREG (statbuf.st_mode)); - TEST_TRUE (statbuf.st_mode & S_IRUSR); - TEST_TRUE (statbuf.st_mode & S_IWUSR); - TEST_FALSE (statbuf.st_mode & S_IXUSR); - - TEST_TRUE (statbuf.st_mode & S_IRGRP); - TEST_FALSE (statbuf.st_mode & S_IWGRP); - TEST_FALSE (statbuf.st_mode & S_IXGRP); - - TEST_FALSE (statbuf.st_mode & S_IROTH); - TEST_FALSE (statbuf.st_mode & S_IWOTH); - TEST_FALSE (statbuf.st_mode & S_IXOTH); - - TEST_EQ (statbuf.st_size, 3); - - output = fopen (filename, "r"); - TEST_NE_P (output, NULL); - - TEST_EQ (fread (buffer, 1, 3, output), 3); - TEST_EQ (buffer[0], '\n'); - TEST_EQ (buffer[1], ' '); - TEST_EQ (buffer[2], '\t'); - - TEST_FILE_END (output); - fclose (output); - - TEST_EQ (unlink (filename), 0); - - /************************************************************/ - /* Tidy up */ - - TEST_EQ (rmdir (dirname), 0); - TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); - - /* FIXME - * - * implement!! - */ - TEST_FEATURE ("ensure log written when underlying file deleted with uid 0"); - TEST_FEATURE ("ensure log written when underlying file deleted with uid >0"); - - /* */ - TEST_FEATURE ("ensure log flushed when log object destroyed"); -} - -void -test_log_destroy (void) -{ - Log *log; - int fd; - int flags; - - TEST_FUNCTION ("log_destroy"); - - /************************************************************/ - TEST_FEATURE ("ensure log fd closed with uid 0"); - - fd = dup (2); - TEST_GT (fd, 0); - - flags = fcntl (fd, F_GETFL); - TEST_NE (flags, -1); - - log = log_new (NULL, "/foo", fd, 0); - TEST_NE_P (log, NULL); - - nih_free (log); - - flags = fcntl (fd, F_GETFL); - TEST_EQ (flags, -1); - TEST_EQ (errno, EBADF); - - /************************************************************/ - TEST_FEATURE ("ensure log fd closed with uid >0"); - - fd = dup (2); - TEST_GT (fd, 0); - - flags = fcntl (fd, F_GETFL); - TEST_NE (flags, -1); - - log = log_new (NULL, "/foo", fd, getuid ()); - TEST_NE_P (log, NULL); - - nih_free (log); - - flags = fcntl (fd, F_GETFL); - TEST_EQ (flags, -1); - TEST_EQ (errno, EBADF); - - /************************************************************/ - TEST_FEATURE ("ensure path and io elements freed with uid 0"); - - fd = dup (2); - TEST_GT (fd, 0); - - log = log_new (NULL, "/bar", fd, 0); - TEST_NE_P (log, NULL); - - TEST_FREE_TAG (log->path); - TEST_FREE_TAG (log->io); - - nih_free (log); - - TEST_FREE (log->path); - TEST_FREE (log->io); - - /************************************************************/ - TEST_FEATURE ("ensure path and io elements freed with uid >0"); - - fd = dup (2); - TEST_GT (fd, 0); - - log = log_new (NULL, "/bar", fd, getuid ()); - TEST_NE_P (log, NULL); - - TEST_FREE_TAG (log->path); - TEST_FREE_TAG (log->io); - - nih_free (log); - - TEST_FREE (log->path); - TEST_FREE (log->io); - - /*FIXME: parent test! - * - * log_new (FOO, ...); - * - */ -#if 0 - fprintf(stderr, "XXX: POST: fstat(fd=%d): st_nlink=%d\n", log->fd, statbuf.st_nlink); - - fprintf(stderr, "XXX: dirname='%s'\n", dirname); - fprintf(stderr, "XXX: filename='%s'\n", filename); -#endif - -} - - -int -main (int argc, - char *argv[]) -{ - /* run tests in legacy (pre-session support) mode */ - setenv ("UPSTART_NO_SESSIONS", "1", 1); - - test_log_new (); - test_log_destroy (); - /* FIXME */ - - return 0; -} diff -u upstart-1.3/init/man/init.5 upstart-1.3/init/man/init.5 --- upstart-1.3/init/man/init.5 +++ upstart-1.3/init/man/init.5 @@ -566,33 +566,17 @@ them yourself. .TP -.B console \fBlog\fR|\fBnone\fR|\fBoutput\fR|\fBowner\fR -The default value (if the \fBconsole\fR stanza is not specified) is -\fBlog\fR where standard input is connected to +.B console output\fR|\fBowner +By default the standard input, output and error file descriptors of jobs +are connected to .I /dev/null -and all job output is written to file -.IR /var/log/upstart/.log "," -\(aq\(aq being replaced with the job name. If a job has -specified \fBinstance\fR, output for that job will instead go to file -.I /var/log/upstart/-.log -where \(aq\(aq is replaced by the specific instance value. -Note that since this facility utilizes pseudo-ttys, it may be necessary -to increase the number of available pty devices; see -.BR pty (7) -for details. -If \fBnone\fR is specified, standard input, output and error file -descriptors of jobs are connected to -.IR /dev/null "." -This used to be the default prior to the introduction of \fBlog\fR in -Upstart 1.4. - -If \fBoutput\fR is specified, the standard input, output and error file -descriptors are connected to -.IR /dev/console "." +If this stanza is specified, they are connected to +.I /dev/console +instead. .B console owner -is special: it not only connects the job to the system console but sets +is special, it not only connects the job to the system console but sets the job to be the owner of the system console, which means it will receive certain signals from the kernel when special key combinations such as Control\-C are pressed. @@ -826,5 +810,4 @@ .BR init (8) .BR initctl (8) -.BR pty (7) .BR sh (1) .BR upstart-events (7) only in patch2: unchanged: --- upstart-1.3.orig/extra/upstart-udev-bridge.c +++ upstart-1.3/extra/upstart-udev-bridge.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ static void upstart_disconnected (DBusConnection *connection); static void emit_event_error (void *data, NihDBusMessage *message); +static char *make_safe_string (const void *parent, const char *original); /** * daemonise: @@ -66,6 +68,13 @@ **/ static NihDBusProxy *upstart = NULL; +/** + * no_strip_udev_data: + * + * If TRUE, do not modify any udev message data (old behaviour). + * If FALSE, use make_safe_string () to cleanse udev strings. + **/ +static int no_strip_udev_data = FALSE; /** * options: @@ -75,6 +84,8 @@ static NihOption options[] = { { 0, "daemon", N_("Detach and run in the background"), NULL, NULL, &daemonise, NULL }, + { 0, "no-strip", N_("Do not strip non-printable bytes from udev message data"), + NULL, NULL, &no_strip_udev_data, NULL }, NIH_OPTION_LAST }; @@ -179,25 +190,44 @@ NihIoEvents events) { struct udev_device * udev_device; - const char * subsystem; - const char * action; - const char * kernel; - const char * devpath; - const char * devname; + nih_local char * subsystem = NULL; + nih_local char * action = NULL; + nih_local char * kernel = NULL; + nih_local char * devpath = NULL; + nih_local char * devname = NULL; nih_local char * name = NULL; nih_local char ** env = NULL; size_t env_len = 0; DBusPendingCall * pending_call; + char *(*copy_string)(const void *, const char *) = NULL; + udev_device = udev_monitor_receive_device (udev_monitor); if (! udev_device) return; - subsystem = udev_device_get_subsystem (udev_device); - action = udev_device_get_action (udev_device); - kernel = udev_device_get_sysname (udev_device); - devpath = udev_device_get_devpath (udev_device); - devname = udev_device_get_devnode (udev_device); + copy_string = no_strip_udev_data ? nih_strdup : make_safe_string; + + subsystem = copy_string (NULL, udev_device_get_subsystem (udev_device)); + if (! action) + goto out; + + action = copy_string (NULL, udev_device_get_action (udev_device)); + if (! action) + goto out; + + kernel = copy_string (NULL, udev_device_get_sysname (udev_device)); + if (! kernel) + goto out; + + devpath = copy_string (NULL, udev_device_get_devpath (udev_device)); + if (! devpath) + goto out; + + devname = copy_string (NULL, udev_device_get_devnode (udev_device)); + if (! devname) + goto out; + if (! strcmp (action, "add")) { name = NIH_MUST (nih_sprintf (NULL, "%s-device-added", @@ -253,10 +283,10 @@ for (struct udev_list_entry *list_entry = udev_device_get_properties_list_entry (udev_device); list_entry != NULL; list_entry = udev_list_entry_get_next (list_entry)) { - const char * key; + nih_local char *key = NULL; nih_local char *var = NULL; - key = udev_list_entry_get_name (list_entry); + key = copy_string (NULL, udev_list_entry_get_name (list_entry)); if (! strcmp (key, "DEVPATH")) continue; if (! strcmp (key, "DEVNAME")) @@ -267,26 +297,33 @@ continue; var = NIH_MUST (nih_sprintf (NULL, "%s=%s", key, - udev_list_entry_get_value (list_entry))); + copy_string (NULL, udev_list_entry_get_value (list_entry)))); NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var)); } nih_debug ("%s %s", name, devname); - pending_call = NIH_SHOULD (upstart_emit_event (upstart, - name, env, FALSE, - NULL, emit_event_error, NULL, - NIH_DBUS_TIMEOUT_NEVER)); + pending_call = upstart_emit_event (upstart, + name, env, FALSE, + NULL, emit_event_error, NULL, + NIH_DBUS_TIMEOUT_NEVER); + if (! pending_call) { NihError *err; + int saved = errno; err = nih_error_get (); nih_warn ("%s", err->message); + + if (saved != ENOMEM && subsystem) + nih_warn ("Likely that udev '%s' event contains binary garbage", subsystem); + nih_free (err); } dbus_pending_call_unref (pending_call); +out: udev_device_unref (udev_device); } @@ -308,3 +345,75 @@ nih_warn ("%s", err->message); nih_free (err); } + +/** + * make_safe_string: + * @parent: parent, + * @original: original string. + * + * Strip non-printable and non-blank bytes from specified string. + * + * Notes: + * + * Sadly, this is necessary as some hardware (such as battery devices) + * exposes non-printable bytes in their descriptive registers to the + * kernel. Since neither the kernel nor udev specify any encoding for + * udev messages, these (probably bogus) bytes get passed up to userland + * to deal with. This is sub-optimal since it implies that _every_ + * application that processes udev messages must perform its own + * sanitizing on the messages. Let's just hope they all deal with the + * problem in the same way... + * + * Note that *iff* the kernel/udev did specify an encoding model, this + * problem could go away since one of the lower layers could then + * detect the out-of-bound data and deal with it at source. All instances + * of this issue seen so far seem to indicate the binary control data + * being presented by the hardware is in fact bogus ("corruption") and + * looks like some block of memory has not been initialized correctly. + * + * The approach taken here is to simulate the approach already adopted + * by 'upower' (up_device_supply_make_safe_string()), with the exception + * that we also allow blank characters (such as tabs). + * + * Returns a copy of @original stripped of all non-printable and + * non-blank characters, or NULL if insufficient memory. + **/ +char * +make_safe_string(const void *parent, const char *original) +{ + size_t len; + size_t i, j; + char *cleaned; + + nih_assert (original); + + + len = strlen (original); + + cleaned = nih_alloc (parent, len); + + if (! cleaned) + return NULL; + + for (i=0, j=0; i <= len; ) { + /* Skip over bogus bytes */ + if (! isprint (original[i]) && ! isblank (original[i])) { + i++; + continue; + } + + /* Copy what remains */ + cleaned[j] = original[i]; + i++; j++; + } + + /* Terminate */ + cleaned[j] = '\0'; + + if (i != j) + nih_debug ("removed bogus bytes in udev message data"); + + /* If substitutions were necessary, shrink the string */ + return i == j ? cleaned : nih_realloc (cleaned, parent, j); +} + only in patch2: unchanged: --- upstart-1.3.orig/extra/man/upstart-udev-bridge.8 +++ upstart-1.3/extra/man/upstart-udev-bridge.8 @@ -21,10 +21,46 @@ Assuming \fI/sys\fP is mounted, possible values for \fIsubsystem\fP for your system are viewable via \fI/sys/class/\fP. - +.\" +.SH OPTIONS +.\" +.TP +.B \-\-daemon +Detach and run in the background. +.\" +.TP +.B \-\-debug +Enable debugging output. +.\" +.TP +.B \-\-help +Show brief usage summary. +.\" +.TP +.B \-\-no\-strip +Do not modify udev message contents. By default, all udev data will have +non-printable bytes removed. This option reverts the behaviour to not +modifying the data in any way. This option is not recommended since +specifying it +.I could +result in +.BR udev (7) +events not being emitted as Upstart events should any of your +hardware expose non-printable characters to the kernel. You can establish +whether this is happening by running +.I without +specifying this option +but with the +.B --debug +option. +.\" +.TP +.B \-\-verbose +Enable verbose output. .\" .SH EXAMPLES +Some examples of Upstart events generated by this bridge: .IP net\-device\-added Event emitted when a network device is added. .IP net\-device\-removed