1 /* $NetBSD: ttyaction.c,v 1.19 2008/04/28 20:23:03 martin Exp $ */
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * For each matching "tty" and "action" run the "command."
34 * See fnmatch() for matching the tty name.
37 #include <sys/cdefs.h>
38 #if defined(LIBC_SCCS) && !defined(lint)
39 __RCSID("$NetBSD: ttyaction.c,v 1.19 2008/04/28 20:23:03 martin Exp $");
40 #endif /* LIBC_SCCS and not lint */
42 #include <sys/types.h>
58 #ifndef _PATH_TTYACTION
59 #define _PATH_TTYACTION "/etc/ttyaction"
62 static const char *actfile
= _PATH_TTYACTION
;
63 static const char *pathenv
= "PATH=" _PATH_STDPATH
;
66 ttyaction(const char *tty
, const char *act
, const char *user
)
77 int error
, linenum
, status
;
80 _DIAGASSERT(tty
!= NULL
);
81 _DIAGASSERT(act
!= NULL
);
82 _DIAGASSERT(user
!= NULL
);
84 fp
= fopen(actfile
, "r");
88 /* Skip the "/dev/" part of the first arg. */
89 if (!strncmp(tty
, "/dev/", (size_t)5))
92 /* Args will be: "sh -c ..." */
93 argv
[0] = _PATH_BSHELL
;
95 argv
[2] = NULL
; /* see below */
99 * Environment needs: TTY, ACT, USER
101 snprintf(env_tty
, sizeof(env_tty
), "TTY=%s", tty
);
102 snprintf(env_act
, sizeof(env_act
), "ACT=%s", act
);
103 snprintf(env_user
, sizeof(env_user
), "USER=%s", user
);
112 while (fgets(line
, (int)sizeof(line
), fp
)) {
115 /* Allow comment lines. */
119 p1
= strtok_r(line
, " \t", &lastp
);
120 p2
= strtok_r(NULL
, " \t", &lastp
);
121 /* This arg goes to end of line. */
122 argv
[2] = strtok_r(NULL
, "\n", &lastp
);
123 if (!p1
|| !p2
|| !argv
[2]) {
124 warnx("%s: line %d format error", actfile
, linenum
);
127 if (fnmatch(p1
, tty
, 0) || fnmatch(p2
, act
, 0))
129 /* OK, this is a match. Run the command. */
132 warnx("fork failed: %s", strerror(errno
));
136 /* This is the child. */
137 error
= execve(argv
[0],
138 (char *const *)__UNCONST(argv
),
139 (char *const *)__UNCONST(envp
));
140 /* If we get here, it is an error. */
141 warnx("%s: line %d: exec failed: %s",
142 actfile
, linenum
, strerror(errno
));
145 /* This is the parent. */
146 error
= waitpid(pid
, &status
, 0);
148 warnx("%s: line %d: wait failed: %s",
149 actfile
, linenum
, strerror(errno
));
152 if (WTERMSIG(status
)) {
153 warnx("%s: line %d: child died with signal %d",
154 actfile
, linenum
, WTERMSIG(status
));