1/*
2 *  This parses the command line arguments. It was seperated from main.c by
3 *  Justin Dearing <jdeari01@longisland.poly.edu>.
4 */
5
6/*
7 *  LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
8 *  Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
9 *  Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
10 *  All Rights Reserved.
11 *
12 *  see GPL (latest version) for full details
13 */
14
15#include <rfb/rfb.h>
16
17extern int rfbStringToAddr(char *str, in_addr_t *iface);
18
19void
20rfbUsage(void)
21{
22    rfbProtocolExtension* extension;
23
24    fprintf(stderr, "-rfbport port          TCP port for RFB protocol\n");
25#ifdef LIBVNCSERVER_IPv6
26    fprintf(stderr, "-rfbportv6 port        TCP6 port for RFB protocol\n");
27#endif
28    fprintf(stderr, "-rfbwait time          max time in ms to wait for RFB client\n");
29    fprintf(stderr, "-rfbauth passwd-file   use authentication on RFB protocol\n"
30                    "                       (use 'storepasswd' to create a password file)\n");
31    fprintf(stderr, "-rfbversion 3.x        Set the version of the RFB we choose to advertise\n");
32    fprintf(stderr, "-permitfiletransfer    permit file transfer support\n");
33    fprintf(stderr, "-passwd plain-password use authentication \n"
34                    "                       (use plain-password as password, USE AT YOUR RISK)\n");
35    fprintf(stderr, "-deferupdate time      time in ms to defer updates "
36                                                             "(default 40)\n");
37    fprintf(stderr, "-deferptrupdate time   time in ms to defer pointer updates"
38                                                           " (default none)\n");
39    fprintf(stderr, "-desktop name          VNC desktop name (default \"LibVNCServer\")\n");
40    fprintf(stderr, "-alwaysshared          always treat new clients as shared\n");
41    fprintf(stderr, "-nevershared           never treat new clients as shared\n");
42    fprintf(stderr, "-dontdisconnect        don't disconnect existing clients when a "
43                                                             "new non-shared\n"
44                    "                       connection comes in (refuse new connection "
45                                                                "instead)\n");
46    fprintf(stderr, "-httpdir dir-path      enable http server using dir-path home\n");
47    fprintf(stderr, "-httpport portnum      use portnum for http connection\n");
48#ifdef LIBVNCSERVER_IPv6
49    fprintf(stderr, "-httpportv6 portnum    use portnum for IPv6 http connection\n");
50#endif
51    fprintf(stderr, "-enablehttpproxy       enable http proxy support\n");
52    fprintf(stderr, "-progressive height    enable progressive updating for slow links\n");
53    fprintf(stderr, "-listen ipaddr         listen for connections only on network interface with\n");
54    fprintf(stderr, "                       addr ipaddr. '-listen localhost' and hostname work too.\n");
55#ifdef LIBVNCSERVER_IPv6
56    fprintf(stderr, "-listenv6 ipv6addr     listen for IPv6 connections only on network interface with\n");
57    fprintf(stderr, "                       addr ipv6addr. '-listen localhost' and hostname work too.\n");
58#endif
59
60    for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
61	if(extension->usage)
62		extension->usage();
63    rfbReleaseExtensionIterator();
64}
65
66/* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
67   POSITION points to the first non purged argument afterwards. */
68void rfbPurgeArguments(int* argc,int* position,int count,char *argv[])
69{
70  int amount=(*argc)-(*position)-count;
71  if(amount)
72    memmove(argv+(*position),argv+(*position)+count,sizeof(char*)*amount);
73  (*argc)-=count;
74}
75
76rfbBool
77rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
78{
79    int i,i1;
80
81    if(!argc) return TRUE;
82
83    for (i = i1 = 1; i < *argc;) {
84        if (strcmp(argv[i], "-help") == 0) {
85	    rfbUsage();
86	    return FALSE;
87	} else if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
88            if (i + 1 >= *argc) {
89		rfbUsage();
90		return FALSE;
91	    }
92	    rfbScreen->port = atoi(argv[++i]);
93#ifdef LIBVNCSERVER_IPv6
94	} else if (strcmp(argv[i], "-rfbportv6") == 0) { /* -rfbportv6 port */
95            if (i + 1 >= *argc) {
96		rfbUsage();
97		return FALSE;
98	    }
99	    rfbScreen->ipv6port = atoi(argv[++i]);
100#endif
101        } else if (strcmp(argv[i], "-rfbwait") == 0) {  /* -rfbwait ms */
102            if (i + 1 >= *argc) {
103		rfbUsage();
104		return FALSE;
105	    }
106	    rfbScreen->maxClientWait = atoi(argv[++i]);
107        } else if (strcmp(argv[i], "-rfbauth") == 0) {  /* -rfbauth passwd-file */
108            if (i + 1 >= *argc) {
109		rfbUsage();
110		return FALSE;
111	    }
112            rfbScreen->authPasswdData = argv[++i];
113
114        } else if (strcmp(argv[i], "-permitfiletransfer") == 0) {  /* -permitfiletransfer  */
115            rfbScreen->permitFileTransfer = TRUE;
116        } else if (strcmp(argv[i], "-rfbversion") == 0) {  /* -rfbversion 3.6  */
117            if (i + 1 >= *argc) {
118		rfbUsage();
119		return FALSE;
120	    }
121	    sscanf(argv[++i],"%d.%d", &rfbScreen->protocolMajorVersion, &rfbScreen->protocolMinorVersion);
122	} else if (strcmp(argv[i], "-passwd") == 0) {  /* -passwd password */
123	    char **passwds = malloc(sizeof(char**)*2);
124	    if (i + 1 >= *argc) {
125		rfbUsage();
126		return FALSE;
127	    }
128	    passwds[0] = argv[++i];
129	    passwds[1] = NULL;
130	    rfbScreen->authPasswdData = (void*)passwds;
131	    rfbScreen->passwordCheck = rfbCheckPasswordByList;
132        } else if (strcmp(argv[i], "-deferupdate") == 0) {  /* -deferupdate milliseconds */
133            if (i + 1 >= *argc) {
134		rfbUsage();
135		return FALSE;
136	    }
137            rfbScreen->deferUpdateTime = atoi(argv[++i]);
138        } else if (strcmp(argv[i], "-deferptrupdate") == 0) {  /* -deferptrupdate milliseconds */
139            if (i + 1 >= *argc) {
140		rfbUsage();
141		return FALSE;
142	    }
143            rfbScreen->deferPtrUpdateTime = atoi(argv[++i]);
144        } else if (strcmp(argv[i], "-desktop") == 0) {  /* -desktop desktop-name */
145            if (i + 1 >= *argc) {
146		rfbUsage();
147		return FALSE;
148	    }
149            rfbScreen->desktopName = argv[++i];
150        } else if (strcmp(argv[i], "-alwaysshared") == 0) {
151	    rfbScreen->alwaysShared = TRUE;
152        } else if (strcmp(argv[i], "-nevershared") == 0) {
153            rfbScreen->neverShared = TRUE;
154        } else if (strcmp(argv[i], "-dontdisconnect") == 0) {
155            rfbScreen->dontDisconnect = TRUE;
156        } else if (strcmp(argv[i], "-httpdir") == 0) {  /* -httpdir directory-path */
157            if (i + 1 >= *argc) {
158		rfbUsage();
159		return FALSE;
160	    }
161            rfbScreen->httpDir = argv[++i];
162        } else if (strcmp(argv[i], "-httpport") == 0) {  /* -httpport portnum */
163            if (i + 1 >= *argc) {
164		rfbUsage();
165		return FALSE;
166	    }
167            rfbScreen->httpPort = atoi(argv[++i]);
168#ifdef LIBVNCSERVER_IPv6
169	} else if (strcmp(argv[i], "-httpportv6") == 0) {  /* -httpportv6 portnum */
170            if (i + 1 >= *argc) {
171		rfbUsage();
172		return FALSE;
173	    }
174            rfbScreen->http6Port = atoi(argv[++i]);
175#endif
176        } else if (strcmp(argv[i], "-enablehttpproxy") == 0) {
177            rfbScreen->httpEnableProxyConnect = TRUE;
178        } else if (strcmp(argv[i], "-progressive") == 0) {  /* -httpport portnum */
179            if (i + 1 >= *argc) {
180		rfbUsage();
181		return FALSE;
182	    }
183            rfbScreen->progressiveSliceHeight = atoi(argv[++i]);
184        } else if (strcmp(argv[i], "-listen") == 0) {  /* -listen ipaddr */
185            if (i + 1 >= *argc) {
186		rfbUsage();
187		return FALSE;
188	    }
189            if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) {
190                return FALSE;
191            }
192#ifdef LIBVNCSERVER_IPv6
193	} else if (strcmp(argv[i], "-listenv6") == 0) {  /* -listenv6 ipv6addr */
194            if (i + 1 >= *argc) {
195		rfbUsage();
196		return FALSE;
197	    }
198	    rfbScreen->listen6Interface = argv[++i];
199#endif
200#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
201        } else if (strcmp(argv[i], "-sslkeyfile") == 0) {  /* -sslkeyfile sslkeyfile */
202            if (i + 1 >= *argc) {
203		rfbUsage();
204		return FALSE;
205	    }
206            rfbScreen->sslkeyfile = argv[++i];
207        } else if (strcmp(argv[i], "-sslcertfile") == 0) {  /* -sslcertfile sslcertfile */
208            if (i + 1 >= *argc) {
209		rfbUsage();
210		return FALSE;
211	    }
212            rfbScreen->sslcertfile = argv[++i];
213#endif
214        } else {
215	    rfbProtocolExtension* extension;
216	    int handled=0;
217
218	    for(extension=rfbGetExtensionIterator();handled==0 && extension;
219			extension=extension->next)
220		if(extension->processArgument)
221			handled = extension->processArgument(*argc - i, argv + i);
222	    rfbReleaseExtensionIterator();
223
224	    if(handled==0) {
225		i++;
226		i1=i;
227		continue;
228	    }
229	    i+=handled-1;
230	}
231	/* we just remove the processed arguments from the list */
232	rfbPurgeArguments(argc,&i1,i-i1+1,argv);
233	i=i1;
234    }
235    return TRUE;
236}
237
238rfbBool
239rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[])
240{
241    int i,i1;
242
243    if(!argc) return TRUE;
244    for (i = i1 = 1; i < *argc-1;) {
245        if (strcmp(argv[i], "-bpp") == 0) {
246               *bpp = atoi(argv[++i]);
247        } else if (strcmp(argv[i], "-width") == 0) {
248               *width = atoi(argv[++i]);
249        } else if (strcmp(argv[i], "-height") == 0) {
250               *height = atoi(argv[++i]);
251        } else {
252	    i++;
253	    i1=i;
254	    continue;
255	}
256	rfbPurgeArguments(argc,&i1,i-i1,argv);
257	i=i1;
258    }
259    return TRUE;
260}
261
262