darwin afshelper fix startup check
[openafs.git] / src / platform / DARWIN / AFSPreference / afshlp.m
1 //
2 //  afshlp.m
3 //  AFSCommander
4 //
5 //  Created by Claudio on 28/06/07.
6 //
7
8
9 #include <sys/types.h>
10 #include <unistd.h>
11 #include <Security/Authorization.h>
12 #include <Security/AuthorizationTags.h>
13 #include <sys/param.h>
14 #include <sys/stat.h>
15 #include <sys/wait.h>
16 #include <sys/types.h>
17 #include <sys/fcntl.h>
18 #include <sys/errno.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <asl.h>
23 #include <sys/event.h>
24 #include <mach-o/dyld.h>
25 #import "TaskUtil.h"
26 #import "AuthUtil.h"
27 #import "PListManager.h"
28
29 #define AFS_DAEMON_STARTUPSCRIPT        "/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.rc"
30 #define AFS_DAEMON_PATH                         "/Library/LaunchDaemons/org.openafs.filesystems.afs.plist"
31
32  void stopAfs(int argc, char *argv[]);
33  void getPath(char **selfPathPtr);
34  void selfRepair(char *selfPath);
35  void runWithSelfRepair(char *selfPath,int argc, char *argv[]);
36
37 void main(int argc, char *argv[])
38 {
39         if (argc < 2)
40                 return; // nothing to do
41         NSString *cmdString = [NSString stringWithCString:(const char *)argv[1] encoding:NSUTF8StringEncoding];
42
43         if(argc == 2 && [cmdString rangeOfString:@"stop_afs"].location!=NSNotFound ){
44                 if (setuid(0) == -1)
45                         return;
46                 const char *stopArgs[] = {"stop", 0L};
47                 [[AuthUtil shared] execUnixCommand:AFS_DAEMON_STARTUPSCRIPT
48                                                                           args:stopArgs
49                                                                         output:nil];
50         } else  if(argc == 2 && [cmdString rangeOfString:@"start_afs"].location!=NSNotFound){
51                 if (setuid(0) == -1)
52                         return;
53                 const char *startArgs[] = {"start", 0L};
54                 [[AuthUtil shared] execUnixCommand:AFS_DAEMON_STARTUPSCRIPT
55                                                                           args:startArgs
56                                                                         output:nil];
57         } else if(argc == 4 && [cmdString rangeOfString:@"enable_krb5_startup"].location!=NSNotFound) {
58                 int olduid = getuid();
59                 setuid(0);
60                 int arg2 = atoi(argv[2]);
61                 [PListManager krb5TiketAtLoginTime:[[NSNumber numberWithInt:arg2] boolValue]];
62         } else if(argc == 3 && [cmdString rangeOfString:@"start_afs_at_startup"].location!=NSNotFound){
63                 if (setuid(0) == -1)
64                         return;
65                 BOOL enable = strcmp("enable", argv[2])==0;
66                 NSLog(@"Manage start_afs_at_startup with option %s from helper", argv[2]);
67                 [PListManager launchctlStringCommand:enable?@"load":@"unload"
68                                                                           option:[NSArray arrayWithObjects:@"-w", nil]
69                                                                    plistName:@AFS_DAEMON_PATH];
70 #if 0
71         } else if(argc == 2 && [cmdString rangeOfString:@"check_afs_daemon"].location!=NSNotFound) {
72                 NSString *fsResult = [TaskUtil executeTaskSearchingPath:@"launchctl" args:[NSArray arrayWithObjects: @"list", nil]];
73                 BOOL checkAfsDaemon = (fsResult?([fsResult rangeOfString:@"org.openafs.filesystems.afs"].location != NSNotFound):NO);
74                 printf("afshlp:afs daemon registration result:%d",checkAfsDaemon);
75 #endif
76         }
77 }
78
79 #if 0
80 void stopAfs(int argc, char *argv[])
81 {
82         const char *umountArgs[] = {"-f", "/afs", 0L};
83         [[AuthUtil shared] execUnixCommand:"/sbin/umount" 
84                                                                   args:umountArgs
85                                                                 output:nil];
86         
87         const char *afsdArgs[] = {"-shutdown", 0L};
88         [[AuthUtil shared] execUnixCommand:argv[3]
89                                                                   args:afsdArgs
90                                                                 output:nil];
91         
92         const char *kernelExtArgs[] = {argv[2], 0L};
93         [[AuthUtil shared] execUnixCommand:"/sbin/kextunload"
94                                                                   args:kernelExtArgs
95                                                                 output:nil];
96         
97         [[AuthUtil shared] deautorize];
98 }
99
100 // Code to get the path to the executable using _NSGetExecutablePath.
101 void getPath(char **selfPathPtr)
102 {
103     uint32_t selfPathSize = MAXPATHLEN;
104     if(!(*selfPathPtr = malloc(selfPathSize)))
105     {
106         exit(-1);
107     }
108     if(_NSGetExecutablePath(*selfPathPtr, &selfPathSize) == -1)
109     {
110         // Try reallocating selfPath with the size returned by the function.
111         if(!(*selfPathPtr = realloc(*selfPathPtr, selfPathSize + 1)))
112         {
113             NSLog(@"Could not allocate memory to hold executable path.");
114             exit(-1);
115         }
116         if(_NSGetExecutablePath(*selfPathPtr, &selfPathSize) != 0)
117         {
118             NSLog(@"Could not get executable path.");
119             exit(-1);
120         }
121     }
122 }
123
124 int main(int argc, char *argv[])
125 {
126         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
127     char *selfPath;
128         
129         NSLog(@"num of arguments %d", argc);
130         int status = [[AuthUtil shared] autorize];
131         if(status != noErr) exit(-1);
132         
133     // Get the path to the tool's executable
134     getPath(&selfPath);
135
136     //selfRepair(selfPath);
137     // All done with the executable path
138     if(selfPath) free(selfPath);
139         
140         // Now do the real work of running the command.
141     runCommand(argc, argv);
142     [[AuthUtil shared] deautorize];
143     [pool release];
144         
145         return 0;
146 }
147
148 // Self-repair code. Found somehwere in internet
149 void selfRepair(char *selfPath)
150 {
151     struct stat st;
152     int fdTool;
153         printf("selfRepair"); 
154         
155 //    [[AuthUtil shared] autorize];
156     
157     // Open tool exclusively, noone can touch it when we work on it, this idea i kepped somewhere in internet
158     fdTool = open(selfPath, O_NONBLOCK | O_RDONLY | O_EXLOCK, 0);
159     
160     if(fdTool == -1)
161     {
162         NSLog(@"Open Filed: %d.", errno);
163         exit(-1);
164     }
165     
166     if(fstat(fdTool, &st))
167     {
168         NSLog(@"fstat failed.");
169         exit(-1);
170     }
171     
172     // Disable group and world writability and make setuid root.
173     if ((st.st_uid != 0) || (st.st_mode & S_IWGRP) || (st.st_mode & S_IWOTH) ||
174         !(st.st_mode & S_ISUID))
175     {
176         fchown(fdTool, 0, st.st_gid);
177         fchmod(fdTool, (st.st_mode & (~(S_IWGRP | S_IWOTH))) | S_ISUID);
178     } else  NSLog(@"st_uid = 0");
179     
180     close(fdTool);
181     
182     NSLog(@"Self-repair done.");
183 }
184
185
186 // Code to execute the tool in self-repair mode.
187 void runWithSelfRepair(char *selfPath, int argc, char *argv[])
188 {
189     int status;
190     int pid;
191         
192       
193         // Make the qargs array for passing to child the same args of father
194     const char *arguments[] = {argv[1], argv[2], argv[3], "--self-repair", 0L};
195         
196         // Get the privileged AuthorizationRef
197     [[AuthUtil shared] autorize];
198         [[AuthUtil shared] execUnixCommand:selfPath 
199                                                                   args:arguments 
200                                                                 output:nil];
201
202     pid = wait(&status);
203     if(pid == -1 || !WIFEXITED(status))
204     {
205         NSLog(@"Error returned from wait().");
206         exit(-1);
207     }
208     
209     // Exit with the same exit code as the self-repair child
210     exit(WEXITSTATUS(status));
211 }
212 #endif