Benjamin Peterson | 90f5ba5 | 2010-03-11 22:53:45 +0000 | [diff] [blame^] | 1 | #! /usr/bin/env python3 |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 2 | |
| 3 | # A simple gopher client. |
| 4 | # |
| 5 | # Usage: gopher [ [selector] host [port] ] |
| 6 | |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 7 | import sys |
| 8 | import os |
| 9 | import socket |
| 10 | |
| 11 | # Default selector, host and port |
| 12 | DEF_SELECTOR = '' |
| 13 | DEF_HOST = 'gopher.micro.umn.edu' |
| 14 | DEF_PORT = 70 |
| 15 | |
| 16 | # Recognized file types |
| 17 | T_TEXTFILE = '0' |
| 18 | T_MENU = '1' |
| 19 | T_CSO = '2' |
| 20 | T_ERROR = '3' |
| 21 | T_BINHEX = '4' |
| 22 | T_DOS = '5' |
| 23 | T_UUENCODE = '6' |
| 24 | T_SEARCH = '7' |
| 25 | T_TELNET = '8' |
| 26 | T_BINARY = '9' |
| 27 | T_REDUNDANT = '+' |
| 28 | T_SOUND = 's' |
| 29 | |
| 30 | # Dictionary mapping types to strings |
| 31 | typename = {'0': '<TEXT>', '1': '<DIR>', '2': '<CSO>', '3': '<ERROR>', \ |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 32 | '4': '<BINHEX>', '5': '<DOS>', '6': '<UUENCODE>', '7': '<SEARCH>', \ |
| 33 | '8': '<TELNET>', '9': '<BINARY>', '+': '<REDUNDANT>', 's': '<SOUND>'} |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 34 | |
| 35 | # Oft-used characters and strings |
| 36 | CRLF = '\r\n' |
| 37 | TAB = '\t' |
| 38 | |
| 39 | # Open a TCP connection to a given host and port |
| 40 | def open_socket(host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 41 | if not port: |
| 42 | port = DEF_PORT |
| 43 | elif type(port) == type(''): |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 44 | port = int(port) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 45 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 46 | s.connect((host, port)) |
| 47 | return s |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 48 | |
| 49 | # Send a selector to a given host and port, return a file with the reply |
| 50 | def send_request(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 51 | s = open_socket(host, port) |
| 52 | s.send(selector + CRLF) |
| 53 | s.shutdown(1) |
| 54 | return s.makefile('r') |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 55 | |
| 56 | # Get a menu in the form of a list of entries |
| 57 | def get_menu(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 58 | f = send_request(selector, host, port) |
| 59 | list = [] |
| 60 | while 1: |
| 61 | line = f.readline() |
| 62 | if not line: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 63 | print('(Unexpected EOF from server)') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 64 | break |
| 65 | if line[-2:] == CRLF: |
| 66 | line = line[:-2] |
| 67 | elif line[-1:] in CRLF: |
| 68 | line = line[:-1] |
| 69 | if line == '.': |
| 70 | break |
| 71 | if not line: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 72 | print('(Empty line from server)') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 73 | continue |
| 74 | typechar = line[0] |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 75 | parts = line[1:].split(TAB) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 76 | if len(parts) < 4: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 77 | print('(Bad line from server: %r)' % (line,)) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 78 | continue |
| 79 | if len(parts) > 4: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 80 | print('(Extra info from server: %r)' % (parts[4:],)) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 81 | parts.insert(0, typechar) |
| 82 | list.append(parts) |
| 83 | f.close() |
| 84 | return list |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 85 | |
| 86 | # Get a text file as a list of lines, with trailing CRLF stripped |
| 87 | def get_textfile(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 88 | list = [] |
| 89 | get_alt_textfile(selector, host, port, list.append) |
| 90 | return list |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 91 | |
| 92 | # Get a text file and pass each line to a function, with trailing CRLF stripped |
| 93 | def get_alt_textfile(selector, host, port, func): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 94 | f = send_request(selector, host, port) |
| 95 | while 1: |
| 96 | line = f.readline() |
| 97 | if not line: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 98 | print('(Unexpected EOF from server)') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 99 | break |
| 100 | if line[-2:] == CRLF: |
| 101 | line = line[:-2] |
| 102 | elif line[-1:] in CRLF: |
| 103 | line = line[:-1] |
| 104 | if line == '.': |
| 105 | break |
| 106 | if line[:2] == '..': |
| 107 | line = line[1:] |
| 108 | func(line) |
| 109 | f.close() |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 110 | |
| 111 | # Get a binary file as one solid data block |
| 112 | def get_binary(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 113 | f = send_request(selector, host, port) |
| 114 | data = f.read() |
| 115 | f.close() |
| 116 | return data |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 117 | |
| 118 | # Get a binary file and pass each block to a function |
| 119 | def get_alt_binary(selector, host, port, func, blocksize): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 120 | f = send_request(selector, host, port) |
| 121 | while 1: |
| 122 | data = f.read(blocksize) |
| 123 | if not data: |
| 124 | break |
| 125 | func(data) |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 126 | |
| 127 | # A *very* simple interactive browser |
| 128 | |
| 129 | # Browser main command, has default arguments |
| 130 | def browser(*args): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 131 | selector = DEF_SELECTOR |
| 132 | host = DEF_HOST |
| 133 | port = DEF_PORT |
| 134 | n = len(args) |
| 135 | if n > 0 and args[0]: |
| 136 | selector = args[0] |
| 137 | if n > 1 and args[1]: |
| 138 | host = args[1] |
| 139 | if n > 2 and args[2]: |
| 140 | port = args[2] |
| 141 | if n > 3: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 142 | raise RuntimeError('too many args') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 143 | try: |
| 144 | browse_menu(selector, host, port) |
Guido van Rossum | b940e11 | 2007-01-10 16:19:56 +0000 | [diff] [blame] | 145 | except socket.error as msg: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 146 | print('Socket error:', msg) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 147 | sys.exit(1) |
| 148 | except KeyboardInterrupt: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 149 | print('\n[Goodbye]') |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 150 | |
| 151 | # Browse a menu |
| 152 | def browse_menu(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 153 | list = get_menu(selector, host, port) |
| 154 | while 1: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 155 | print('----- MENU -----') |
| 156 | print('Selector:', repr(selector)) |
| 157 | print('Host:', host, ' Port:', port) |
| 158 | print() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 159 | for i in range(len(list)): |
| 160 | item = list[i] |
| 161 | typechar, description = item[0], item[1] |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 162 | print(repr(i+1).rjust(3) + ':', description, end=' ') |
| 163 | if typechar in typename: |
| 164 | print(typename[typechar]) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 165 | else: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 166 | print('<TYPE=' + repr(typechar) + '>') |
| 167 | print() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 168 | while 1: |
| 169 | try: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 170 | str = input('Choice [CR == up a level]: ') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 171 | except EOFError: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 172 | print() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 173 | return |
| 174 | if not str: |
| 175 | return |
| 176 | try: |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 177 | choice = int(str) |
| 178 | except ValueError: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 179 | print('Choice must be a number; try again:') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 180 | continue |
| 181 | if not 0 < choice <= len(list): |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 182 | print('Choice out of range; try again:') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 183 | continue |
| 184 | break |
| 185 | item = list[choice-1] |
| 186 | typechar = item[0] |
| 187 | [i_selector, i_host, i_port] = item[2:5] |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 188 | if typechar in typebrowser: |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 189 | browserfunc = typebrowser[typechar] |
| 190 | try: |
| 191 | browserfunc(i_selector, i_host, i_port) |
| 192 | except (IOError, socket.error): |
Neal Norwitz | ac3625f | 2006-03-17 05:49:33 +0000 | [diff] [blame] | 193 | t, v, tb = sys.exc_info() |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 194 | print('***', t, ':', v) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 195 | else: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 196 | print('Unsupported object type') |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 197 | |
| 198 | # Browse a text file |
| 199 | def browse_textfile(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 200 | x = None |
| 201 | try: |
| 202 | p = os.popen('${PAGER-more}', 'w') |
| 203 | x = SaveLines(p) |
| 204 | get_alt_textfile(selector, host, port, x.writeln) |
Guido van Rossum | b940e11 | 2007-01-10 16:19:56 +0000 | [diff] [blame] | 205 | except IOError as msg: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 206 | print('IOError:', msg) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 207 | if x: |
| 208 | x.close() |
| 209 | f = open_savefile() |
| 210 | if not f: |
| 211 | return |
| 212 | x = SaveLines(f) |
| 213 | try: |
| 214 | get_alt_textfile(selector, host, port, x.writeln) |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 215 | print('Done.') |
Guido van Rossum | b940e11 | 2007-01-10 16:19:56 +0000 | [diff] [blame] | 216 | except IOError as msg: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 217 | print('IOError:', msg) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 218 | x.close() |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 219 | |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 220 | def raw_input(prompt): |
| 221 | sys.stdout.write(prompt) |
| 222 | sys.stdout.flush() |
| 223 | return sys.stdin.readline() |
| 224 | |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 225 | # Browse a search index |
| 226 | def browse_search(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 227 | while 1: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 228 | print('----- SEARCH -----') |
| 229 | print('Selector:', repr(selector)) |
| 230 | print('Host:', host, ' Port:', port) |
| 231 | print() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 232 | try: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 233 | query = input('Query [CR == up a level]: ') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 234 | except EOFError: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 235 | print() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 236 | break |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 237 | query = query.strip() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 238 | if not query: |
| 239 | break |
| 240 | if '\t' in query: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 241 | print('Sorry, queries cannot contain tabs') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 242 | continue |
| 243 | browse_menu(selector + TAB + query, host, port) |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 244 | |
| 245 | # "Browse" telnet-based information, i.e. open a telnet session |
| 246 | def browse_telnet(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 247 | if selector: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 248 | print('Log in as', repr(selector)) |
Neal Norwitz | 3bd844e | 2006-08-29 04:39:12 +0000 | [diff] [blame] | 249 | if type(port) != type(''): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 250 | port = repr(port) |
| 251 | sts = os.system('set -x; exec telnet ' + host + ' ' + port) |
| 252 | if sts: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 253 | print('Exit status:', sts) |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 254 | |
| 255 | # "Browse" a binary file, i.e. save it to a file |
| 256 | def browse_binary(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 257 | f = open_savefile() |
| 258 | if not f: |
| 259 | return |
| 260 | x = SaveWithProgress(f) |
| 261 | get_alt_binary(selector, host, port, x.write, 8*1024) |
| 262 | x.close() |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 263 | |
| 264 | # "Browse" a sound file, i.e. play it or save it |
| 265 | def browse_sound(selector, host, port): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 266 | browse_binary(selector, host, port) |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 267 | |
| 268 | # Dictionary mapping types to browser functions |
| 269 | typebrowser = {'0': browse_textfile, '1': browse_menu, \ |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 270 | '4': browse_binary, '5': browse_binary, '6': browse_textfile, \ |
| 271 | '7': browse_search, \ |
| 272 | '8': browse_telnet, '9': browse_binary, 's': browse_sound} |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 273 | |
| 274 | # Class used to save lines, appending a newline to each line |
| 275 | class SaveLines: |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 276 | def __init__(self, f): |
| 277 | self.f = f |
| 278 | def writeln(self, line): |
| 279 | self.f.write(line + '\n') |
| 280 | def close(self): |
| 281 | sts = self.f.close() |
| 282 | if sts: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 283 | print('Exit status:', sts) |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 284 | |
| 285 | # Class used to save data while showing progress |
| 286 | class SaveWithProgress: |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 287 | def __init__(self, f): |
| 288 | self.f = f |
| 289 | def write(self, data): |
| 290 | sys.stdout.write('#') |
| 291 | sys.stdout.flush() |
| 292 | self.f.write(data) |
| 293 | def close(self): |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 294 | print() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 295 | sts = self.f.close() |
| 296 | if sts: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 297 | print('Exit status:', sts) |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 298 | |
| 299 | # Ask for and open a save file, or return None if not to save |
| 300 | def open_savefile(): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 301 | try: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 302 | savefile = input( \ |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 303 | 'Save as file [CR == don\'t save; |pipeline or ~user/... OK]: ') |
| 304 | except EOFError: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 305 | print() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 306 | return None |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 307 | savefile = savefile.strip() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 308 | if not savefile: |
| 309 | return None |
| 310 | if savefile[0] == '|': |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 311 | cmd = savefile[1:].strip() |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 312 | try: |
| 313 | p = os.popen(cmd, 'w') |
Guido van Rossum | b940e11 | 2007-01-10 16:19:56 +0000 | [diff] [blame] | 314 | except IOError as msg: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 315 | print(repr(cmd), ':', msg) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 316 | return None |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 317 | print('Piping through', repr(cmd), '...') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 318 | return p |
| 319 | if savefile[0] == '~': |
| 320 | savefile = os.path.expanduser(savefile) |
| 321 | try: |
| 322 | f = open(savefile, 'w') |
Guido van Rossum | b940e11 | 2007-01-10 16:19:56 +0000 | [diff] [blame] | 323 | except IOError as msg: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 324 | print(repr(savefile), ':', msg) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 325 | return None |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 326 | print('Saving to', repr(savefile), '...') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 327 | return f |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 328 | |
| 329 | # Test program |
| 330 | def test(): |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 331 | if sys.argv[4:]: |
Collin Winter | 6f2df4d | 2007-07-17 20:59:35 +0000 | [diff] [blame] | 332 | print('usage: gopher [ [selector] host [port] ]') |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 333 | sys.exit(2) |
| 334 | elif sys.argv[3:]: |
| 335 | browser(sys.argv[1], sys.argv[2], sys.argv[3]) |
| 336 | elif sys.argv[2:]: |
| 337 | try: |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 338 | port = int(sys.argv[2]) |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 339 | selector = '' |
| 340 | host = sys.argv[1] |
Neal Norwitz | ce96f69 | 2006-03-17 06:49:51 +0000 | [diff] [blame] | 341 | except ValueError: |
Tim Peters | e6ddc8b | 2004-07-18 05:56:09 +0000 | [diff] [blame] | 342 | selector = sys.argv[1] |
| 343 | host = sys.argv[2] |
| 344 | port = '' |
| 345 | browser(selector, host, port) |
| 346 | elif sys.argv[1:]: |
| 347 | browser('', sys.argv[1]) |
| 348 | else: |
| 349 | browser() |
Guido van Rossum | 6b8d699 | 1992-10-25 19:18:11 +0000 | [diff] [blame] | 350 | |
| 351 | # Call the test program as a main program |
| 352 | test() |