1 2#include <sys/param.h> 3#include <sys/mount.h> 4#include <sys/errno.h> 5#include <sys/wait.h> 6#include <stdio.h> 7#include <stdlib.h> 8#include <string.h> 9#include <err.h> 10#include <stdbool.h> 11#include <unistd.h> 12 13#include "autofs.h" 14 15static char usage[] = "usage: %s [-d] mount_point opts map subdir key"; 16 17static char gKextLoadCommand[] = "/sbin/kextload"; 18static char gKextLoadPath[] = "/System/Library/Extensions/autofs.kext"; 19 20static int LoadAutoFS(void); 21 22int 23main(int argc, char **argv) 24{ 25 int ch; 26 int error; 27 bool retried; 28 struct autofs_args mnt_args; 29 char mount_path[PATH_MAX]; 30 char *path; 31 int32_t direct = 0; 32 33 while ((ch = getopt(argc, argv, "dt:")) != EOF) { 34 switch (ch) { 35 36 case 'd': 37 direct = 1; 38 break; 39 40 default: 41 fprintf(stderr, "%s: unknown option '-%c'.\n", getprogname(), ch); 42 fprintf(stderr, usage, getprogname()); 43 return (EXIT_FAILURE); 44 } 45 } 46 argc -= optind; 47 argv += optind; 48 49 if (argc < 5) 50 errx(1, usage, getprogname()); 51 52 path = realpath(argv[0], mount_path); 53 if (path == NULL) { 54 err(1, "couldn't resolve mount path: %s", strerror(errno)); 55 /* NOT REACHED */ 56 return 1; 57 }; 58 59 mnt_args.version = AUTOFS_ARGSVERSION; 60 mnt_args.path = path; 61 mnt_args.opts = argv[1]; 62 mnt_args.map = argv[2]; 63 mnt_args.subdir = argv[3]; 64 mnt_args.key = argv[4]; 65 mnt_args.direct = direct; 66 mnt_args.mount_type = MOUNT_TYPE_MAP; /* top-level autofs mount */ 67 68 retried = false; 69 while (true) { 70 error = mount("autofs", mount_path, 71 MNT_DONTBROWSE|MNT_AUTOMOUNTED, &mnt_args); 72 if (error == 0) { 73 break; 74 } else if (retried) { 75 perror("mount"); 76 break; 77 } else { 78 retried = true; 79 (void)LoadAutoFS(); 80 } 81 } 82 83 return (error == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 84} 85 86static int 87LoadAutoFS(void) 88{ 89 pid_t pid, terminated_pid; 90 int result; 91 union wait status; 92 93 pid = fork(); 94 if (pid == 0) { 95 result = execl(gKextLoadCommand, gKextLoadCommand, "-q", gKextLoadPath, NULL); 96 /* IF WE ARE HERE, WE WERE UNSUCCESSFUL */ 97 return result ? result : ECHILD; 98 } 99 100 if (pid == -1) { 101 result = -1; 102 goto Err_Exit; 103 } 104 105 /* Success! Wait for completion in-line here */ 106 while ( (terminated_pid = wait4(pid, (int *)&status, 0, NULL)) < 0 ) { 107 /* retry if EINTR, else break out with error */ 108 if ( errno != EINTR ) { 109 break; 110 } 111 } 112 113 if ((terminated_pid == pid) && (WIFEXITED(status))) { 114 result = WEXITSTATUS(status); 115 } else { 116 result = -1; 117 } 118#if DEBUG_TRACE 119 syslog(LOG_INFO, "LoadAutoFS: result of fork / exec = %d.\n", result); 120#endif 121 122Err_Exit: 123 return result; 124} 125