xref: /netbsd-src/external/bsd/am-utils/dist/amd/amfs_program.c (revision b9c2640a340c3bc4788a10c7cc4986f2c3daaf56)
1*b9c2640aSmrg /*	$NetBSD: amfs_program.c,v 1.2 2018/02/04 09:15:44 mrg Exp $	*/
2a53f50b9Schristos 
3a53f50b9Schristos /*
48bae5d40Schristos  * Copyright (c) 1997-2014 Erez Zadok
5a53f50b9Schristos  * Copyright (c) 1989 Jan-Simon Pendry
6a53f50b9Schristos  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
7a53f50b9Schristos  * Copyright (c) 1989 The Regents of the University of California.
8a53f50b9Schristos  * All rights reserved.
9a53f50b9Schristos  *
10a53f50b9Schristos  * This code is derived from software contributed to Berkeley by
11a53f50b9Schristos  * Jan-Simon Pendry at Imperial College, London.
12a53f50b9Schristos  *
13a53f50b9Schristos  * Redistribution and use in source and binary forms, with or without
14a53f50b9Schristos  * modification, are permitted provided that the following conditions
15a53f50b9Schristos  * are met:
16a53f50b9Schristos  * 1. Redistributions of source code must retain the above copyright
17a53f50b9Schristos  *    notice, this list of conditions and the following disclaimer.
18a53f50b9Schristos  * 2. Redistributions in binary form must reproduce the above copyright
19a53f50b9Schristos  *    notice, this list of conditions and the following disclaimer in the
20a53f50b9Schristos  *    documentation and/or other materials provided with the distribution.
218bae5d40Schristos  * 3. Neither the name of the University nor the names of its contributors
22a53f50b9Schristos  *    may be used to endorse or promote products derived from this software
23a53f50b9Schristos  *    without specific prior written permission.
24a53f50b9Schristos  *
25a53f50b9Schristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26a53f50b9Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27a53f50b9Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28a53f50b9Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29a53f50b9Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30a53f50b9Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31a53f50b9Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32a53f50b9Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33a53f50b9Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34a53f50b9Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35a53f50b9Schristos  * SUCH DAMAGE.
36a53f50b9Schristos  *
37a53f50b9Schristos  *
38a53f50b9Schristos  * File: am-utils/amd/amfs_program.c
39a53f50b9Schristos  *
40a53f50b9Schristos  */
41a53f50b9Schristos 
42a53f50b9Schristos /*
43a53f50b9Schristos  * Program file system
44a53f50b9Schristos  */
45a53f50b9Schristos 
46a53f50b9Schristos #ifdef HAVE_CONFIG_H
47a53f50b9Schristos # include <config.h>
48a53f50b9Schristos #endif /* HAVE_CONFIG_H */
49a53f50b9Schristos #include <am_defs.h>
50a53f50b9Schristos #include <amd.h>
51a53f50b9Schristos 
52a53f50b9Schristos /* forward definitions */
53a53f50b9Schristos static char *amfs_program_match(am_opts *fo);
54a53f50b9Schristos static int amfs_program_mount(am_node *am, mntfs *mf);
55a53f50b9Schristos static int amfs_program_umount(am_node *am, mntfs *mf);
56a53f50b9Schristos static int amfs_program_init(mntfs *mf);
57a53f50b9Schristos 
58a53f50b9Schristos /*
59a53f50b9Schristos  * Ops structure
60a53f50b9Schristos  */
61a53f50b9Schristos am_ops amfs_program_ops =
62a53f50b9Schristos {
63a53f50b9Schristos   "program",
64a53f50b9Schristos   amfs_program_match,
65a53f50b9Schristos   amfs_program_init,
66a53f50b9Schristos   amfs_program_mount,
67a53f50b9Schristos   amfs_program_umount,
68a53f50b9Schristos   amfs_error_lookup_child,
69a53f50b9Schristos   amfs_error_mount_child,
70a53f50b9Schristos   amfs_error_readdir,
71a53f50b9Schristos   0,				/* amfs_program_readlink */
72a53f50b9Schristos   0,				/* amfs_program_mounted */
73a53f50b9Schristos   0,				/* amfs_program_umounted */
74a53f50b9Schristos   amfs_generic_find_srvr,
75a53f50b9Schristos   0,				/* amfs_program_get_wchan */
76a53f50b9Schristos   FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
77a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
78a53f50b9Schristos   AUTOFS_PROGRAM_FS_FLAGS,
79a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
80a53f50b9Schristos };
81a53f50b9Schristos 
82a53f50b9Schristos 
83a53f50b9Schristos /*
84a53f50b9Schristos  * Execute needs a mount and unmount command.
85a53f50b9Schristos  */
86a53f50b9Schristos static char *
amfs_program_match(am_opts * fo)87a53f50b9Schristos amfs_program_match(am_opts *fo)
88a53f50b9Schristos {
89a53f50b9Schristos   char *prog;
90a53f50b9Schristos 
91a53f50b9Schristos   if (fo->opt_unmount && fo->opt_umount) {
92a53f50b9Schristos     plog(XLOG_ERROR, "program: cannot specify both unmount and umount options");
93a53f50b9Schristos     return 0;
94a53f50b9Schristos   }
95a53f50b9Schristos   if (!fo->opt_mount) {
96a53f50b9Schristos     plog(XLOG_ERROR, "program: must specify mount command");
97a53f50b9Schristos     return 0;
98a53f50b9Schristos   }
99a53f50b9Schristos   if (!fo->opt_unmount && !fo->opt_umount) {
100a53f50b9Schristos     fo->opt_unmount = str3cat(NULL, UNMOUNT_PROGRAM, " umount ", fo->opt_fs);
101a53f50b9Schristos     plog(XLOG_INFO, "program: un/umount not specified; using default \"%s\"",
102a53f50b9Schristos 	 fo->opt_unmount);
103a53f50b9Schristos   }
104a53f50b9Schristos   prog = strchr(fo->opt_mount, ' ');
105a53f50b9Schristos 
1068bae5d40Schristos   return xstrdup(prog ? prog + 1 : fo->opt_mount);
107a53f50b9Schristos }
108a53f50b9Schristos 
109a53f50b9Schristos 
110a53f50b9Schristos static int
amfs_program_init(mntfs * mf)111a53f50b9Schristos amfs_program_init(mntfs *mf)
112a53f50b9Schristos {
113a53f50b9Schristos   /* check if already saved value */
114a53f50b9Schristos   if (mf->mf_private != NULL)
115a53f50b9Schristos     return 0;
116a53f50b9Schristos 
1178bae5d40Schristos   if (mf->mf_fo == NULL)
1188bae5d40Schristos     return 0;
1198bae5d40Schristos 
120a53f50b9Schristos   /* save unmount (or umount) command */
121a53f50b9Schristos   if (mf->mf_fo->opt_unmount != NULL)
1228bae5d40Schristos     mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_unmount);
123a53f50b9Schristos   else
1248bae5d40Schristos     mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_umount);
125a53f50b9Schristos   mf->mf_prfree = (void (*)(opaque_t)) free;
126a53f50b9Schristos 
127a53f50b9Schristos   return 0;
128a53f50b9Schristos }
129a53f50b9Schristos 
130a53f50b9Schristos 
131a53f50b9Schristos static int
amfs_program_exec(char * info)132a53f50b9Schristos amfs_program_exec(char *info)
133a53f50b9Schristos {
134a53f50b9Schristos   char **xivec;
135a53f50b9Schristos   int error;
136a53f50b9Schristos 
137a53f50b9Schristos   /*
138a53f50b9Schristos    * Split copy of command info string
139a53f50b9Schristos    */
1408bae5d40Schristos   info = xstrdup(info);
141a53f50b9Schristos   xivec = strsplit(info, ' ', '\'');
142a53f50b9Schristos 
143a53f50b9Schristos   /*
144a53f50b9Schristos    * Put stdout to stderr
145a53f50b9Schristos    */
146a53f50b9Schristos   (void) fclose(stdout);
147*b9c2640aSmrg   if (!logfp) {
148a53f50b9Schristos     logfp = stderr;		/* initialize before possible first use */
1498bae5d40Schristos     if (dup(fileno(logfp)) == -1)
1508bae5d40Schristos       goto out;
151*b9c2640aSmrg   }
152a53f50b9Schristos   if (fileno(logfp) != fileno(stderr)) {
153a53f50b9Schristos     (void) fclose(stderr);
1548bae5d40Schristos     if (dup(fileno(logfp)) == -1)
1558bae5d40Schristos       goto out;
156a53f50b9Schristos   }
157a53f50b9Schristos 
158a53f50b9Schristos   /*
159a53f50b9Schristos    * Try the exec
160a53f50b9Schristos    */
161a53f50b9Schristos   if (amuDebug(D_FULL)) {
162a53f50b9Schristos     char **cp = xivec;
163a53f50b9Schristos     plog(XLOG_DEBUG, "executing (un)mount command...");
164a53f50b9Schristos     while (*cp) {
165a53f50b9Schristos       plog(XLOG_DEBUG, "arg[%ld] = '%s'", (long) (cp - xivec), *cp);
166a53f50b9Schristos       cp++;
167a53f50b9Schristos     }
168a53f50b9Schristos   }
169a53f50b9Schristos 
170a53f50b9Schristos   if (xivec[0] == 0 || xivec[1] == 0) {
171a53f50b9Schristos     errno = EINVAL;
172a53f50b9Schristos     plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
173a53f50b9Schristos   } else {
174a53f50b9Schristos     (void) execv(xivec[0], xivec + 1);
1758bae5d40Schristos     error = errno;
1768bae5d40Schristos     plog(XLOG_ERROR, "exec failed: %m");
1778bae5d40Schristos     errno = error;
178a53f50b9Schristos   }
179a53f50b9Schristos 
1808bae5d40Schristos out:
181a53f50b9Schristos   /*
182a53f50b9Schristos    * Save error number
183a53f50b9Schristos    */
184a53f50b9Schristos   error = errno;
185a53f50b9Schristos 
186a53f50b9Schristos   /*
187a53f50b9Schristos    * Free allocate memory
188a53f50b9Schristos    */
189a53f50b9Schristos   XFREE(info);
190a53f50b9Schristos   XFREE(xivec);
191a53f50b9Schristos 
192a53f50b9Schristos   /*
193a53f50b9Schristos    * Return error
194a53f50b9Schristos    */
195a53f50b9Schristos   return error;
196a53f50b9Schristos }
197a53f50b9Schristos 
198a53f50b9Schristos 
199a53f50b9Schristos static int
amfs_program_mount(am_node * am,mntfs * mf)200a53f50b9Schristos amfs_program_mount(am_node *am, mntfs *mf)
201a53f50b9Schristos {
202a53f50b9Schristos   return amfs_program_exec(mf->mf_fo->opt_mount);
203a53f50b9Schristos }
204a53f50b9Schristos 
205a53f50b9Schristos 
206a53f50b9Schristos static int
amfs_program_umount(am_node * am,mntfs * mf)207a53f50b9Schristos amfs_program_umount(am_node *am, mntfs *mf)
208a53f50b9Schristos {
209a53f50b9Schristos   return amfs_program_exec((char *) mf->mf_private);
210a53f50b9Schristos }
211