findlanabyname-20040228
[openafs.git] / src / WINNT / afsusrmgr / 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 "TaAfsUsrMgr.h"
16 #include "cmdline.h"
17
18 extern "C" {
19 #include <afs/afs_AdminErrors.h>
20 } // extern "C"
21
22
23 /*
24  * VARIABLES __________________________________________________________________
25  *
26  */
27
28 typedef enum {
29    swCELL,
30    swREMOTE,
31    swUSER,
32    swPASSWORD
33 } SWITCH;
34
35 static struct {
36    TCHAR szSwitch[ cchRESOURCE ];
37    BOOL fGetsValue;
38    BOOL fPresent;
39    TCHAR szValue[ cchRESOURCE ];
40 } aSWITCHES[] = {
41    { TEXT("cell"),      TRUE,   FALSE,  TEXT("") },
42    { TEXT("remote"),    TRUE,   FALSE,  TEXT("") },
43    { TEXT("user"),      TRUE,   FALSE,  TEXT("") },
44    { TEXT("password"),  TRUE,   FALSE,  TEXT("") }
45 };
46
47 #define nSWITCHES (sizeof(aSWITCHES) / sizeof(aSWITCHES[0]))
48
49
50 /*
51  * PROTOTYPES _________________________________________________________________
52  *
53  */
54
55 #define iswhite(_ch) ( ((_ch)==TEXT(' ')) || ((_ch)==TEXT('\t')) )
56
57 void cdecl CommandLineHelp (int ids, LPTSTR pszFormat = NULL, ...);
58
59
60 /*
61  * ROUTINES ___________________________________________________________________
62  *
63  */
64
65 CMDLINEOP ParseCommandLine (LPTSTR pszCmdLine)
66 {
67    for (size_t ii = 0; ii < nSWITCHES; ++ii)
68       aSWITCHES[ ii ].fPresent = FALSE;
69
70    // Search through pszCmdLine for switches; each switch must be
71    // preceeded by "/" or "-".
72    //
73    while (pszCmdLine && *pszCmdLine)
74       {
75       while (iswhite(*pszCmdLine))
76          ++pszCmdLine;
77       if (!*pszCmdLine)
78          break;
79
80       if ( (*pszCmdLine != '-') && (*pszCmdLine != '/') )
81          {
82          CommandLineHelp (IDS_CMDLINE_SYNTAX);
83          return opCLOSEAPP;
84          }
85
86       ++pszCmdLine;
87
88       // Okay, we've found what is probably the start of a switch.
89       // See if it matches anything.
90       //
91       for (ii = 0; ii < nSWITCHES; ++ii)
92          {
93          size_t cch = lstrlen(aSWITCHES[ ii ].szSwitch);
94          if (lstrncmpi (pszCmdLine, aSWITCHES[ ii ].szSwitch, cch))
95             continue;
96
97          // If the switch wants a value, it must be followed by ":"
98          // or whitespace; if it doesn't, it must be followed by "/"
99          // or whitespace.
100          //
101          LPTSTR pszAfter = &pszCmdLine[ cch ];
102          if (iswhite (*pszAfter) || (!*pszAfter) ||
103              ((*pszAfter == TEXT(':')) && (aSWITCHES[ ii ].fGetsValue)) ||
104              ((*pszAfter == TEXT('/')) && (!aSWITCHES[ ii ].fGetsValue)) )
105             {
106             break; // found a switch!
107             }
108          }
109
110       if (ii >= nSWITCHES)
111          {
112          TCHAR szCopy[ cchRESOURCE ];
113          lstrcpy (szCopy, pszCmdLine);
114          for (LPTSTR pch = szCopy;
115               *pch && !iswhite(*pch) && !(*pch == TEXT('/')) && !(*pch == TEXT(':'));
116               ++pch)
117             ;
118          *pch = TEXT('\0');
119          CommandLineHelp (IDS_CMDLINE_UNRECOGNIZED, TEXT("%s"), szCopy);
120          return opCLOSEAPP;
121          }
122       if (aSWITCHES[ ii ].fPresent)
123          {
124          CommandLineHelp (IDS_CMDLINE_DUPLICATE, TEXT("%s"), aSWITCHES[ ii ].szSwitch);
125          return opCLOSEAPP;
126          }
127
128       // Woo hoo!  Found what appears to be a valid switch.  Parse it now.
129       //
130       aSWITCHES[ ii ].fPresent = TRUE;
131       pszCmdLine += lstrlen( aSWITCHES[ ii ].szSwitch );
132       while (iswhite (*pszCmdLine))
133          ++pszCmdLine;
134
135       if (*pszCmdLine == TEXT(':'))
136          {
137          if (!aSWITCHES[ ii ].fGetsValue)
138             {
139             CommandLineHelp (IDS_CMDLINE_UNEXPECTVALUE, TEXT("%s"), aSWITCHES[ ii ].szSwitch);
140             return opCLOSEAPP;
141             }
142          for (++pszCmdLine; iswhite (*pszCmdLine); ++pszCmdLine)
143             ;
144          }
145
146       if (aSWITCHES[ ii ].fGetsValue)
147          {
148          if ( (*pszCmdLine == TEXT('/')) || (*pszCmdLine == TEXT('\0')) )
149             {
150             CommandLineHelp (IDS_CMDLINE_MISSINGVAL, TEXT("%s"), aSWITCHES[ ii ].szSwitch);
151             return opCLOSEAPP;
152             }
153          BOOL fQuoted = FALSE;
154          for (LPTSTR pszTarget = aSWITCHES[ ii ].szValue;
155               *pszCmdLine && !(*pszCmdLine == TEXT('/') && !fQuoted)
156                           && !(iswhite(*pszCmdLine) && !fQuoted); )
157             {
158             if (*pszCmdLine == TEXT('"'))
159                {
160                ++pszCmdLine;
161                if (fQuoted)
162                   break;
163                fQuoted = TRUE;
164                continue;
165                }
166             *pszTarget++ = *pszCmdLine++;
167             }
168          *pszTarget++ = TEXT('\0');
169          }
170       }
171
172    // Now test the command-line for syntactical correctness.
173    // First case: if the USER or PASSWORD switch is given, the other
174    // is required.
175    //
176    if ( (aSWITCHES[ swUSER ].fPresent && !aSWITCHES[ swPASSWORD ].fPresent) ||
177         (aSWITCHES[ swPASSWORD ].fPresent && !aSWITCHES[ swUSER ].fPresent) )
178       {
179       CommandLineHelp (IDS_CMDLINE_USERPASSWORD);
180       return opCLOSEAPP;
181       }
182
183    // Connect to an administration server
184    //
185    if (aSWITCHES[ swREMOTE ].fPresent)
186       {
187       ULONG status;
188       if (!AfsAppLib_OpenAdminServer (aSWITCHES[ swREMOTE ].szValue, &status))
189          {
190          if (status == ADMCLIENTCANTINITAFSLOCATION)
191             ImmediateErrorDialog (status, IDS_ERROR_BAD_REMOTE_SERVER_INSTALL, aSWITCHES[ swREMOTE ].szValue);
192          else
193             ImmediateErrorDialog (status, IDS_ERROR_BAD_REMOTE_SERVER, TEXT("%s"), aSWITCHES[ swREMOTE ].szValue);
194          return opCLOSEAPP;
195          }
196       }
197    else // (!aSWITCHES[ swREMOTE ].fPresent)
198       {
199       ULONG status;
200       if (!AfsAppLib_OpenAdminServer (NULL, &status))
201          {
202          if (status == ADMCLIENTCANTINITAFSLOCATION)
203             ImmediateErrorDialog (status, IDS_ERROR_BAD_REMOTE_SERVER_INSTALL, aSWITCHES[ swREMOTE ].szValue);
204          else
205             ImmediateErrorDialog (status, IDS_ERROR_BAD_LOCAL_SERVER, TEXT("%s"), aSWITCHES[ swREMOTE ].szValue);
206          return opCLOSEAPP;
207          }
208       }
209    g.idClient = AfsAppLib_GetAdminServerClientID();
210
211    // Obtain credentials
212    //
213    if (aSWITCHES[ swUSER ].fPresent)
214       {
215       LPTSTR pszCell = (aSWITCHES[ swCELL ].fPresent) ? (aSWITCHES[ swCELL ].szValue) : NULL;
216
217       ULONG status;
218       if (!AfsAppLib_SetCredentials (pszCell, aSWITCHES[ swUSER ].szValue, aSWITCHES[ swPASSWORD ].szValue, &status))
219          {
220          ImmediateErrorDialog (status, IDS_ERROR_BAD_CREDENTIALS);
221          return opCLOSEAPP;
222          }
223       }
224
225    // If the user asked us to, try to open the specified cell
226    //
227    if (aSWITCHES[ swCELL ].fPresent)
228       {
229       LPOPENCELL_PARAMS lpp = New (OPENCELL_PARAMS);
230       memset (lpp, 0x00, sizeof(OPENCELL_PARAMS));
231       lstrcpy (lpp->szCell, aSWITCHES[ swCELL ].szValue);
232       lpp->fCloseAppOnFail = TRUE;
233       StartTask (taskOPENCELL, NULL, lpp);
234       return opNOCELLDIALOG;
235       }
236
237    // Okay--nothing sufficiently special took place to prevent us
238    // from running the tool normally.
239    //
240    return opNORMAL;
241 }
242
243
244 void cdecl CommandLineHelp (int ids, LPTSTR pszFormat, ...)
245 {
246    va_list   arg;
247    va_start (arg, pszFormat);
248    vMessage (MB_OK | MB_ICONHAND, IDS_CMDLINE_TITLE, ids, pszFormat, arg);
249 }
250