]> git.saurik.com Git - apple/system_cmds.git/blob - vifs.tproj/vifs.c
system_cmds-735.20.1.tar.gz
[apple/system_cmds.git] / vifs.tproj / vifs.c
1 /*
2 * Copyright (c) 2005-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 #include <sys/errno.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/wait.h>
27
28 #include <err.h>
29 #include <fcntl.h>
30 #include <fstab.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <paths.h>
35 #include <unistd.h>
36 #include <signal.h>
37
38 char *warning = "\
39 #\n\
40 # Warning - this file should only be modified with vifs(8)\n\
41 #\n\
42 # Failure to do so is unsupported and may be destructive.\n\
43 #\n";
44
45 int
46 main(int argc, char *argv[])
47 {
48 struct stat sb;
49 int fd, x;
50 uid_t euid;
51 pid_t editpid;
52 char *p, *editor;
53
54 if (argc != 1) {
55 printf("usage: vifs\n");
56 exit(1);
57 }
58
59 euid = geteuid();
60 if (euid != 0)
61 errx(1, "need to run as root");
62
63 /* examine the existing fstab, try to create it if needed */
64 if (stat(_PATH_FSTAB, &sb) < 0) {
65 if (errno == ENOENT) {
66 fd = open(_PATH_FSTAB, O_CREAT | O_WRONLY,
67 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
68 if (fd < 0)
69 errx(1, "error creating %s", _PATH_FSTAB);
70 write(fd, warning, strlen(warning));
71 close(fd);
72 } else {
73 errx(1, "could not stat %s", _PATH_FSTAB);
74 }
75 }
76
77 /* prepare the file for the editor */
78 fd = open(_PATH_FSTAB, O_RDONLY, 0);
79 if (fd < 0)
80 errx(1, "error opening %s", _PATH_FSTAB);
81
82 x = fcntl(fd, F_SETFD, 1);
83 if (x < 0)
84 errx(1, "error setting close on exit");
85
86 x = flock(fd, LOCK_EX | LOCK_NB);
87 if (x != 0)
88 errx(1, "file is busy");
89
90 /* obtain and invoke the editor */
91 editor = getenv("EDITOR");
92 if (editor == NULL)
93 editor = _PATH_VI;
94 p = strrchr(editor, '/');
95 if (p != NULL)
96 ++p;
97 else
98 p = editor;
99
100 editpid = vfork();
101 if (editpid == 0) {
102 execlp(editor, p, _PATH_FSTAB, NULL);
103 _exit(1);
104 }
105
106 for ( ; ; ) {
107 editpid = waitpid(editpid, (int *)&x, WUNTRACED);
108 if (editpid == -1)
109 errx(1, "editing error");
110 else if (WIFSTOPPED(x))
111 raise(WSTOPSIG(x));
112 else if (WIFEXITED(x) && WEXITSTATUS(x) == 0)
113 break;
114 else
115 errx(1, "editing error");
116 }
117
118 /* let process death clean up locks and file descriptors */
119 return 0;
120 }