]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/uxputty.c
Trivial segfault fix from Richard B.
[PuTTY.git] / unix / uxputty.c
1 /*
2  * Unix PuTTY main program.
3  */
4
5 #include <stdio.h>
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <unistd.h>
10
11 #include "putty.h"
12 #include "storage.h"
13
14 /*
15  * TODO:
16  * 
17  *  - libcharset enumeration.
18  * 
19  *  - fix the printer enum (I think the sensible thing is simply to
20  *    have uxcfg.c remove the drop-down list completely, since you
21  *    can't sensibly provide an enumerated list of lpr commands!).
22  * 
23  *  - Ctrl+right-click for a context menu (also in Windows for
24  *    consistency, I think). This should contain pretty much
25  *    everything in the Windows PuTTY menu, and a subset of that in
26  *    pterm:
27  * 
28  *     - Telnet special commands (not in pterm :-)
29  * 
30  *     - Event Log (this means we must implement the Event Log; not
31  *       in pterm)
32  * 
33  *     - New Session and Duplicate Session (perhaps in pterm, in fact?!)
34  *        + Duplicate Session will be fun, since we must work out
35  *          how to pass the config data through.
36  *        + In fact this should be easier on Unix, since fork() is
37  *          available so we need not even exec (this also saves us
38  *          the trouble of scrabbling around trying to find our own
39  *          binary). Possible scenario: respond to Duplicate
40  *          Session by forking. Parent continues as before; child
41  *          unceremoniously frees all extant resources (backend,
42  *          terminal, ldisc, frontend etc) and then _longjmps_ (I
43  *          kid you not) back to a point in pt_main() which causes
44  *          it to go back round to the point of opening a new
45  *          terminal window and a new backend.
46  *        + A tricky bit here is how to free everything without
47  *          also _destroying_ things - calling GTK to free up
48  *          existing widgets is liable to send destroy messages to
49  *          the X server, which won't go down too well with the
50  *          parent process. exec() is a much cleaner solution to
51  *          this bit, but requires us to invent some ghastly IPC as
52  *          we did in Windows PuTTY.
53  *        + Arrgh! Also, this won't work in pterm since we'll
54  *          already have dropped privileges by this point, so we
55  *          can't get another pty. Sigh. Looks like exec has to be
56  *          the way forward then :-/
57  * 
58  *     - Saved Sessions submenu (not in pterm of course)
59  * 
60  *     - Change Settings
61  *        + we must also implement mid-session reconfig in pterm.c.
62  *        + note this also requires config.c and uxcfg.c to be able
63  *          to get hold of the application name.
64  * 
65  *     - Copy All to Clipboard (for what that's worth)
66  * 
67  *     - Clear Scrollback and Reset Terminal
68  * 
69  *     - About (and uxcfg.c must also supply the about box)
70  */
71
72 /*
73  * Clean up and exit.
74  */
75 void cleanup_exit(int code)
76 {
77     /*
78      * Clean up.
79      */
80     sk_cleanup();
81     random_save_seed();
82     exit(code);
83 }
84
85 /*
86  * Another bunch of temporary stub functions. These ones will want
87  * removing by means of implementing them properly: libcharset
88  * should invent its own sensible format for codepage names and a
89  * means of enumerating them, and printer_enum needs to be dealt
90  * with somehow or other too.
91  */
92
93 char *cp_name(int codepage)
94 {
95     return "";
96 }
97 char *cp_enumerate(int index)
98 {
99     return NULL;
100 }
101 int decode_codepage(char *cp_name)
102 {
103     return -2;
104 }
105
106 printer_enum *printer_start_enum(int *nprinters_ptr) {
107     *nprinters_ptr = 0;
108     return NULL;
109 }
110 char *printer_get_name(printer_enum *pe, int i) { return NULL;
111 }
112 void printer_finish_enum(printer_enum *pe) { }
113
114 Backend *select_backend(Config *cfg)
115 {
116     int i;
117     Backend *back = NULL;
118     for (i = 0; backends[i].backend != NULL; i++)
119         if (backends[i].protocol == cfg->protocol) {
120             back = backends[i].backend;
121             break;
122         }
123     assert(back != NULL);
124     return back;
125 }
126
127 int cfgbox(Config *cfg)
128 {
129     extern int do_config_box(const char *title, Config *cfg);
130     return do_config_box("PuTTY Configuration", cfg);
131 }
132
133 static int got_host = 0;
134
135 int process_nonoption_arg(char *arg, Config *cfg)
136 {
137     char *p, *q = arg;
138
139     if (got_host) {
140         /*
141          * If we already have a host name, treat this argument as a
142          * port number. NB we have to treat this as a saved -P
143          * argument, so that it will be deferred until it's a good
144          * moment to run it.
145          */
146         int ret = cmdline_process_param("-P", arg, 1, cfg);
147         assert(ret == 2);
148     } else if (!strncmp(q, "telnet:", 7)) {
149         /*
150          * If the hostname starts with "telnet:",
151          * set the protocol to Telnet and process
152          * the string as a Telnet URL.
153          */
154         char c;
155
156         q += 7;
157         if (q[0] == '/' && q[1] == '/')
158             q += 2;
159         cfg->protocol = PROT_TELNET;
160         p = q;
161         while (*p && *p != ':' && *p != '/')
162             p++;
163         c = *p;
164         if (*p)
165             *p++ = '\0';
166         if (c == ':')
167             cfg->port = atoi(p);
168         else
169             cfg->port = -1;
170         strncpy(cfg->host, q, sizeof(cfg->host) - 1);
171         cfg->host[sizeof(cfg->host) - 1] = '\0';
172         got_host = 1;
173     } else {
174         /*
175          * Otherwise, treat this argument as a host name.
176          */
177         p = arg;
178         while (*p && !isspace((unsigned char)*p))
179             p++;
180         if (*p)
181             *p++ = '\0';
182         strncpy(cfg->host, q, sizeof(cfg->host) - 1);
183         cfg->host[sizeof(cfg->host) - 1] = '\0';
184         got_host = 1;
185     }
186     return 1;
187 }
188
189 char *make_default_wintitle(char *hostname)
190 {
191     return dupcat(hostname, " - PuTTY", NULL);
192 }
193
194 int main(int argc, char **argv)
195 {
196     extern int pt_main(int argc, char **argv);
197     sk_init();
198     flags = FLAG_VERBOSE | FLAG_INTERACTIVE;
199     default_protocol = be_default_protocol;
200     /* Find the appropriate default port. */
201     {
202         int i;
203         default_port = 0; /* illegal */
204         for (i = 0; backends[i].backend != NULL; i++)
205             if (backends[i].protocol == default_protocol) {
206                 default_port = backends[i].backend->default_port;
207                 break;
208             }
209     }
210     return pt_main(argc, argv);
211 }