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