287250ba301dc03fc3625d861de4d513235e92b3
[openafs.git] / src / WINNT / afssvrmgr / cmdline.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include "../afsapplib/afsapplib.h"
16
17 #include "svrmgr.h"
18 #include "cmdline.h"
19 #include "action.h"
20 #include "creds.h"
21
22
23 /*
24  * VARIABLES __________________________________________________________________
25  *
26  */
27
28 typedef enum {
29    swCELL,
30    swSUBSET,
31    swSERVER,
32    swRESET,
33    swCONFIRM,
34    swUSER,
35    swPASSWORD,
36    swLOOKUP,
37    swUSEEXISTING
38 } SWITCH;
39
40 static struct {
41    TCHAR szSwitch[ cchRESOURCE ];
42    BOOL fGetsValue;
43    BOOL fPresent;
44    TCHAR szValue[ cchRESOURCE ];
45 } aSWITCHES[] = {
46    { TEXT("cell"),        TRUE,         FALSE,  TEXT("") },
47    { TEXT("subset"),      TRUE,         FALSE,  TEXT("") },
48    { TEXT("server"),      TRUE,         FALSE,  TEXT("") },
49    { TEXT("reset"),       FALSE,        FALSE,  TEXT("") },
50    { TEXT("confirm"),     FALSE,        FALSE,  TEXT("") },
51    { TEXT("user"),        TRUE,         FALSE,  TEXT("") },
52    { TEXT("password"),    TRUE,         FALSE,  TEXT("") },
53    { TEXT("lookup"),      FALSE,        FALSE,  TEXT("") },
54    { TEXT("useexisting"), FALSE,        FALSE,  TEXT("") }
55 };
56
57 #define nSWITCHES (sizeof(aSWITCHES) / sizeof(aSWITCHES[0]))
58
59
60 /*
61  * PROTOTYPES _________________________________________________________________
62  *
63  */
64
65 #define iswhite(_ch) ( ((_ch)==TEXT(' ')) || ((_ch)==TEXT('\t')) )
66
67 void cdecl CommandLineHelp (int ids, LPTSTR pszFormat = NULL, ...);
68
69
70 /*
71  * ROUTINES ___________________________________________________________________
72  *
73  */
74
75 CMDLINEOP ParseCommandLine (LPTSTR pszCmdLine)
76 {
77    for (size_t ii = 0; ii < nSWITCHES; ++ii)
78       aSWITCHES[ ii ].fPresent = FALSE;
79
80    // Search through pszCmdLine for switches; each switch must be
81    // preceeded by "/" or "-".
82    //
83    while (pszCmdLine && *pszCmdLine)
84       {
85       while (iswhite(*pszCmdLine))
86          ++pszCmdLine;
87       if (!*pszCmdLine)
88          break;
89
90       if ( (*pszCmdLine != '-') && (*pszCmdLine != '/') )
91          {
92          CommandLineHelp (IDS_CMDLINE_SYNTAX);
93          return opCLOSEAPP;
94          }
95
96       ++pszCmdLine;
97
98       // Okay, we've found what is probably the start of a switch.
99       // See if it matches anything.
100       //
101       for (ii = 0; ii < nSWITCHES; ++ii)
102          {
103          size_t cch = lstrlen(aSWITCHES[ ii ].szSwitch);
104          if (lstrncmpi (pszCmdLine, aSWITCHES[ ii ].szSwitch, cch))
105             continue;
106
107          // If the switch wants a value, it must be followed by ":"
108          // or whitespace; if it doesn't, it must be followed by "/"
109          // or whitespace.
110          //
111          LPTSTR pszAfter = &pszCmdLine[ cch ];
112          if (iswhite (*pszAfter) || (!*pszAfter) ||
113              ((*pszAfter == TEXT(':')) && (aSWITCHES[ ii ].fGetsValue)) ||
114              ((*pszAfter == TEXT('/')) && (!aSWITCHES[ ii ].fGetsValue)) )
115             {
116             break; // found a switch!
117             }
118          }
119
120       if (ii >= nSWITCHES)
121          {
122          TCHAR szCopy[ cchRESOURCE ];
123          lstrcpy (szCopy, pszCmdLine);
124          for (LPTSTR pch = szCopy;
125               *pch && !iswhite(*pch) && !(*pch == TEXT('/')) && !(*pch == TEXT(':'));
126               ++pch)
127             ;
128          *pch = TEXT('\0');
129          CommandLineHelp (IDS_CMDLINE_UNRECOGNIZED, TEXT("%s"), szCopy);
130          return opCLOSEAPP;
131          }
132       if (aSWITCHES[ ii ].fPresent)
133          {
134          CommandLineHelp (IDS_CMDLINE_DUPLICATE, TEXT("%s"), aSWITCHES[ ii ].szSwitch);
135          return opCLOSEAPP;
136          }
137
138       // Woo hoo!  Found what appears to be a valid switch.  Parse it now.
139       //
140       aSWITCHES[ ii ].fPresent = TRUE;
141       pszCmdLine += lstrlen( aSWITCHES[ ii ].szSwitch );
142       while (iswhite (*pszCmdLine))
143          ++pszCmdLine;
144
145       if (*pszCmdLine == TEXT(':'))
146          {
147          if (!aSWITCHES[ ii ].fGetsValue)
148             {
149             CommandLineHelp (IDS_CMDLINE_UNEXPECTVALUE, TEXT("%s"), aSWITCHES[ ii ].szSwitch);
150             return opCLOSEAPP;
151             }
152          for (++pszCmdLine; iswhite (*pszCmdLine); ++pszCmdLine)
153             ;
154          }
155
156       if (aSWITCHES[ ii ].fGetsValue)
157          {
158          if ( (*pszCmdLine == TEXT('/')) || (*pszCmdLine == TEXT('\0')) )
159             {
160             CommandLineHelp (IDS_CMDLINE_MISSINGVAL, TEXT("%s"), aSWITCHES[ ii ].szSwitch);
161             return opCLOSEAPP;
162             }
163          BOOL fQuoted = FALSE;
164          for (LPTSTR pszTarget = aSWITCHES[ ii ].szValue;
165               *pszCmdLine && !(*pszCmdLine == TEXT('/') && !fQuoted)
166                           && !(iswhite(*pszCmdLine) && !fQuoted); )
167             {
168             if (*pszCmdLine == TEXT('"'))
169                {
170                ++pszCmdLine;
171                if (fQuoted)
172                   break;
173                fQuoted = TRUE;
174                continue;
175                }
176             *pszTarget++ = *pszCmdLine++;
177             }
178          *pszTarget++ = TEXT('\0');
179          }
180       }
181
182    // Was the -CONFIRM switch given?  It works with any other switch
183    // combination.
184    //
185    if (aSWITCHES[ swCONFIRM ].fPresent)
186       {
187       Action_ShowConfirmations (TRUE);
188       }
189
190    // Now test the command-line for syntactical correctness.
191    // First test: if the SUBSET switch is given, the CELL switch must
192    // be given as well.
193    //
194    if ( (aSWITCHES[ swSUBSET ].fPresent) &&
195         (!aSWITCHES[ swCELL ].fPresent) )
196       {
197       CommandLineHelp (IDS_CMDLINE_SUBSETNOTCELL);
198       return opCLOSEAPP;
199       }
200
201    // Similarly, if the SERVER switch is given, the CELL switch must
202    // be given as well.
203    //
204    if ( (aSWITCHES[ swSERVER ].fPresent) &&
205         (!aSWITCHES[ swCELL ].fPresent) )
206       {
207       CommandLineHelp (IDS_CMDLINE_SERVERNOTCELL);
208       return opCLOSEAPP;
209       }
210
211    // And if the USER or PASSWORD switch is given, the other is required.
212    //
213    if ( (aSWITCHES[ swUSER ].fPresent && !aSWITCHES[ swPASSWORD ].fPresent) ||
214         (aSWITCHES[ swPASSWORD ].fPresent && !aSWITCHES[ swUSER ].fPresent) )
215       {
216       CommandLineHelp (IDS_CMDLINE_USERPASSWORD);
217       return opCLOSEAPP;
218       }
219
220    // Implement the command-line switches.
221    //
222    if (aSWITCHES[ swRESET ].fPresent)
223       {
224       if (aSWITCHES[ swSERVER ].fPresent)
225          {
226          ErasePreferences (aSWITCHES[ swCELL ].szValue, aSWITCHES[ swSERVER ].szValue);
227          }
228       else if (aSWITCHES[ swCELL ].fPresent)
229          {
230          ErasePreferences (aSWITCHES[ swCELL ].szValue);
231          }
232       else // neither cell nor server specified--kill just the general stuff
233          {
234          EraseSettings (REGSTR_SETTINGS_BASE, REGSTR_SETTINGS_PATH, REGVAL_SETTINGS);
235          }
236
237       Message (MB_OK | MB_ICONINFORMATION, IDS_CMDLINE_RESET_TITLE, IDS_CMDLINE_RESET_DESC);
238       return opCLOSEAPP;
239       }
240
241    if (aSWITCHES[ swUSER ].fPresent)
242       {
243       LPTSTR pszCell = (aSWITCHES[ swCELL ].fPresent) ? (aSWITCHES[ swCELL ].szValue) : NULL;
244
245       ULONG status;
246       if (!AfsAppLib_SetCredentials (pszCell, aSWITCHES[ swUSER ].szValue, aSWITCHES[ swPASSWORD ].szValue, &status))
247          {
248          ImmediateErrorDialog (status, IDS_SVR_ERROR_BAD_CREDENTIALS);
249          return opCLOSEAPP;
250          }
251       }
252
253    if (aSWITCHES[ swLOOKUP ].fPresent)
254       {
255       return opLOOKUPERRORCODE;
256       }
257
258    if (aSWITCHES[ swUSEEXISTING ].fPresent)
259      {
260        ULONG ulStatus;
261        TCHAR szDefCell[ cchNAME ];
262        
263        if (aSWITCHES[ swCELL ].fPresent)
264          {
265            lstrcpy(szDefCell,aSWITCHES[ swCELL ].szValue);
266          }
267        else
268          {
269            AfsAppLib_GetLocalCell(szDefCell);
270          }
271        g.hCreds = AfsAppLib_GetCredentials(szDefCell,&ulStatus);
272        if (g.hCreds != NULL)
273          {
274            LPOPENCELL_PACKET lpocp = New (OPENCELL_PACKET);
275
276            memset(lpocp,0x00,sizeof(OPENCELL_PACKET));
277            lstrcpy(lpocp->szCell,szDefCell);
278            lpocp->fCloseAppOnFail = TRUE;
279            lpocp->hCreds = g.hCreds;
280            lpocp->sub = NULL;
281            StartTask(taskOPENCELL,NULL,lpocp);
282            return opNOCELLDIALOG;
283          }
284        else
285          return opCLOSEAPP;
286      }
287
288    if (aSWITCHES[ swCELL ].fPresent)
289       {
290       LPOPENCELL_PACKET lpp = New (OPENCELL_PACKET);
291       memset (lpp, 0x00, sizeof(OPENCELL_PACKET));
292
293       lstrcpy (lpp->szCell, aSWITCHES[ swCELL ].szValue);
294       lpp->fCloseAppOnFail = TRUE;
295
296       if (aSWITCHES[ swSUBSET ].fPresent)
297          {
298          lpp->sub = Subsets_LoadSubset (lpp->szCell, aSWITCHES[ swSUBSET ].szValue);
299          if (lpp->sub == NULL)
300             {
301             Delete (lpp);
302             lpp = NULL;
303
304             CommandLineHelp (IDS_CMDLINE_INVALIDSUBSET, TEXT("%s%s"), aSWITCHES[ swCELL ].szValue, aSWITCHES[ swSUBSET ].szValue);
305             return opCLOSEAPP;
306             }
307          }
308       else if (aSWITCHES[ swSERVER ].fPresent)
309          {
310          lpp->sub = New (SUBSET);
311          memset (lpp->sub, 0x0, sizeof(SUBSET));
312          FormatMultiString (&lpp->sub->pszMonitored, TRUE, TEXT("%1"), TEXT("%s"), aSWITCHES[ swSERVER ].szValue);
313          }
314
315       StartTask (taskOPENCELL, NULL, lpp);
316       return opNOCELLDIALOG;
317       }
318
319    // Okay--nothing sufficiently special took place to prevent us
320    // from running the tool normally.
321    //
322    return opNORMAL;
323 }
324
325
326 void cdecl CommandLineHelp (int ids, LPTSTR pszFormat, ...)
327 {
328    va_list   arg;
329    va_start (arg, pszFormat);
330    vMessage (MB_OK | MB_ICONHAND, IDS_CMDLINE_TITLE, ids, pszFormat, arg);
331 }
332