Implement variable expansions in prompt.
Showing
1 changed file
with
226 additions
and
56 deletions
... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
2 | GNU Mailutils pop3 functions. This application interactively allows users | 2 | GNU Mailutils pop3 functions. This application interactively allows users |
3 | to contact a pop3 server. | 3 | to contact a pop3 server. |
4 | 4 | ||
5 | Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | 5 | Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation |
6 | 6 | ||
7 | GNU Mailutils is free software; you can redistribute it and/or modify | 7 | GNU Mailutils is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
... | @@ -23,6 +23,8 @@ | ... | @@ -23,6 +23,8 @@ |
23 | # include <config.h> | 23 | # include <config.h> |
24 | #endif | 24 | #endif |
25 | #include <sys/types.h> | 25 | #include <sys/types.h> |
26 | #include <netinet/in.h> | ||
27 | #include <netdb.h> | ||
26 | #include <unistd.h> | 28 | #include <unistd.h> |
27 | #include <stdio.h> | 29 | #include <stdio.h> |
28 | #include <errno.h> | 30 | #include <errno.h> |
... | @@ -42,6 +44,8 @@ | ... | @@ -42,6 +44,8 @@ |
42 | #include <mailutils/iterator.h> | 44 | #include <mailutils/iterator.h> |
43 | #include <mailutils/error.h> | 45 | #include <mailutils/error.h> |
44 | #include <mailutils/errno.h> | 46 | #include <mailutils/errno.h> |
47 | #include <mailutils/vartab.h> | ||
48 | #include <mailutils/argcv.h> | ||
45 | 49 | ||
46 | /* A structure which contains information on the commands this program | 50 | /* A structure which contains information on the commands this program |
47 | can understand. */ | 51 | can understand. */ |
... | @@ -73,6 +77,7 @@ int com_top (char *); | ... | @@ -73,6 +77,7 @@ int com_top (char *); |
73 | int com_uidl (char *); | 77 | int com_uidl (char *); |
74 | int com_user (char *); | 78 | int com_user (char *); |
75 | int com_verbose (char *); | 79 | int com_verbose (char *); |
80 | int com_prompt (char *); | ||
76 | 81 | ||
77 | void initialize_readline (void); | 82 | void initialize_readline (void); |
78 | char *stripwhite (char *); | 83 | char *stripwhite (char *); |
... | @@ -84,31 +89,29 @@ int valid_argument (const char *, char *); | ... | @@ -84,31 +89,29 @@ int valid_argument (const char *, char *); |
84 | void sig_int (int); | 89 | void sig_int (int); |
85 | 90 | ||
86 | COMMAND commands[] = { | 91 | COMMAND commands[] = { |
87 | {"apop", com_apop, "Authenticate with APOP: APOP user secret"}, | 92 | { "apop", com_apop, "Authenticate with APOP: APOP user secret" }, |
88 | {"capa", com_capa, "List capabilities: capa"}, | 93 | { "capa", com_capa, "List capabilities: capa" }, |
89 | {"disconnect", com_disconnect, "Close connection: disconnect"}, | 94 | { "disconnect", com_disconnect, "Close connection: disconnect" }, |
90 | {"dele", com_dele, "Mark message: DELE msgno"}, | 95 | { "dele", com_dele, "Mark message: DELE msgno" }, |
91 | {"exit", com_exit, "exit program"}, | 96 | { "exit", com_exit, "exit program" }, |
92 | {"help", com_help, "Display this text"}, | 97 | { "help", com_help, "Display this text" }, |
93 | {"?", com_help, "Synonym for `help'"}, | 98 | { "?", com_help, "Synonym for `help'" }, |
94 | {"list", com_list, "List messages: LIST [msgno]"}, | 99 | { "list", com_list, "List messages: LIST [msgno]" }, |
95 | {"noop", com_noop, "Send no operation: NOOP"}, | 100 | { "noop", com_noop, "Send no operation: NOOP" }, |
96 | {"pass", com_pass, "Send passwd: PASS [passwd]"}, | 101 | { "pass", com_pass, "Send passwd: PASS [passwd]" }, |
97 | {"connect", com_connect, "Open connection: connect hostname [port]"}, | 102 | { "prompt", com_prompt, "Set command prompt" }, |
98 | {"quit", com_quit, "Go to Update state : QUIT"}, | 103 | { "connect", com_connect, "Open connection: connect hostname [port]" }, |
99 | {"retr", com_retr, "Dowload message: RETR msgno"}, | 104 | { "quit", com_quit, "Go to Update state : QUIT" }, |
100 | {"rset", com_rset, "Unmark all messages: RSET"}, | 105 | { "retr", com_retr, "Dowload message: RETR msgno" }, |
101 | {"stat", com_stat, "Get the size and count of mailbox : STAT [msgno]"}, | 106 | { "rset", com_rset, "Unmark all messages: RSET" }, |
102 | {"top", com_top, "Get the header of message: TOP msgno [lines]"}, | 107 | { "stat", com_stat, "Get the size and count of mailbox : STAT [msgno]" }, |
103 | {"uidl", com_uidl, "Get the unique id of message: UIDL [msgno]"}, | 108 | { "top", com_top, "Get the header of message: TOP msgno [lines]" }, |
104 | {"user", com_user, "send login: USER user"}, | 109 | { "uidl", com_uidl, "Get the unique id of message: UIDL [msgno]" }, |
105 | {"verbose", com_verbose, "Enable Protocol tracing: verbose [on|off]"}, | 110 | { "user", com_user, "send login: USER user" }, |
106 | {NULL, NULL, NULL} | 111 | { "verbose", com_verbose, "Enable Protocol tracing: verbose [on|off]" }, |
112 | { NULL, NULL, NULL } | ||
107 | }; | 113 | }; |
108 | 114 | ||
109 | /* The name of this program, as taken from argv[0]. */ | ||
110 | char *progname; | ||
111 | |||
112 | /* Global handle for pop3. */ | 115 | /* Global handle for pop3. */ |
113 | mu_pop3_t pop3; | 116 | mu_pop3_t pop3; |
114 | 117 | ||
... | @@ -118,6 +121,69 @@ int verbose; | ... | @@ -118,6 +121,69 @@ int verbose; |
118 | /* When non-zero, this global means the user is done using this program. */ | 121 | /* When non-zero, this global means the user is done using this program. */ |
119 | int done; | 122 | int done; |
120 | 123 | ||
124 | enum pop_session_status | ||
125 | { | ||
126 | pop_session_disconnected, | ||
127 | pop_session_connected, | ||
128 | pop_session_logged_in | ||
129 | }; | ||
130 | |||
131 | enum pop_session_status pop_session_status; | ||
132 | |||
133 | int connect_argc; | ||
134 | char **connect_argv; | ||
135 | |||
136 | /* Host we are connected to. */ | ||
137 | #define host connect_argv[0] | ||
138 | int port = 110; | ||
139 | char *username; | ||
140 | |||
141 | /* Command line prompt */ | ||
142 | #define DEFAULT_PROMPT "pop3> " | ||
143 | char *prompt; | ||
144 | |||
145 | const char * | ||
146 | pop_session_str (enum pop_session_status stat) | ||
147 | { | ||
148 | switch (stat) | ||
149 | { | ||
150 | case pop_session_disconnected: | ||
151 | return "disconnected"; | ||
152 | |||
153 | case pop_session_connected: | ||
154 | return "connected"; | ||
155 | |||
156 | case pop_session_logged_in: | ||
157 | return "logged in"; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | char * | ||
162 | expand_prompt () | ||
163 | { | ||
164 | mu_vartab_t vtab; | ||
165 | char *str; | ||
166 | |||
167 | if (mu_vartab_create (&vtab)) | ||
168 | return strdup (prompt); | ||
169 | mu_vartab_define (vtab, "user", | ||
170 | (pop_session_status == pop_session_logged_in) ? | ||
171 | username : "not logged in", 1); | ||
172 | mu_vartab_define (vtab, "host", | ||
173 | (pop_session_status != pop_session_disconnected) ? | ||
174 | host : "not connected", 1); | ||
175 | mu_vartab_define (vtab, "program-name", mu_program_name, 1); | ||
176 | mu_vartab_define (vtab, "canonical-program-name", "pop3client", 1); | ||
177 | mu_vartab_define (vtab, "package", PACKAGE, 1); | ||
178 | mu_vartab_define (vtab, "version", PACKAGE_VERSION, 1); | ||
179 | mu_vartab_define (vtab, "status", pop_session_str (pop_session_status), 1); | ||
180 | |||
181 | if (mu_vartab_expand (vtab, prompt, &str)) | ||
182 | str = strdup (prompt); | ||
183 | mu_vartab_destroy (&vtab); | ||
184 | return str; | ||
185 | } | ||
186 | |||
121 | char * | 187 | char * |
122 | dupstr (const char *s) | 188 | dupstr (const char *s) |
123 | { | 189 | { |
... | @@ -126,7 +192,7 @@ dupstr (const char *s) | ... | @@ -126,7 +192,7 @@ dupstr (const char *s) |
126 | r = malloc (strlen (s) + 1); | 192 | r = malloc (strlen (s) + 1); |
127 | if (!r) | 193 | if (!r) |
128 | { | 194 | { |
129 | fprintf (stderr, "Memory exhausted\n"); | 195 | mu_error ("Memory exhausted"); |
130 | exit (1); | 196 | exit (1); |
131 | } | 197 | } |
132 | strcpy (r, s); | 198 | strcpy (r, s); |
... | @@ -159,11 +225,10 @@ initialize_readline () | ... | @@ -159,11 +225,10 @@ initialize_readline () |
159 | in case we want to do some simple parsing. Return the array of matches, | 225 | in case we want to do some simple parsing. Return the array of matches, |
160 | or NULL if there aren't any. */ | 226 | or NULL if there aren't any. */ |
161 | char ** | 227 | char ** |
162 | pop_completion (char *text, int start, int end) | 228 | pop_completion (char *text, int start, int end MU_ARG_UNUSED) |
163 | { | 229 | { |
164 | char **matches; | 230 | char **matches; |
165 | 231 | ||
166 | (void) end; | ||
167 | matches = (char **) NULL; | 232 | matches = (char **) NULL; |
168 | 233 | ||
169 | /* If this word is at the start of the line, then it is a command | 234 | /* If this word is at the start of the line, then it is a command |
... | @@ -203,7 +268,7 @@ command_generator (const char *text, int state) | ... | @@ -203,7 +268,7 @@ command_generator (const char *text, int state) |
203 | } | 268 | } |
204 | 269 | ||
205 | /* If no names matched, then return NULL. */ | 270 | /* If no names matched, then return NULL. */ |
206 | return ((char *) NULL); | 271 | return NULL; |
207 | } | 272 | } |
208 | 273 | ||
209 | #else | 274 | #else |
... | @@ -240,19 +305,16 @@ main (int argc MU_ARG_UNUSED, char **argv) | ... | @@ -240,19 +305,16 @@ main (int argc MU_ARG_UNUSED, char **argv) |
240 | { | 305 | { |
241 | char *line, *s; | 306 | char *line, *s; |
242 | 307 | ||
243 | progname = strrchr (argv[0], '/'); | 308 | mu_set_program_name (argv[0]); |
244 | if (progname) | 309 | prompt = strdup (DEFAULT_PROMPT); |
245 | progname++; | ||
246 | else | ||
247 | progname = argv[0]; | ||
248 | |||
249 | initialize_readline (); /* Bind our completer. */ | 310 | initialize_readline (); /* Bind our completer. */ |
250 | 311 | ||
251 | /* Loop reading and executing lines until the user quits. */ | 312 | /* Loop reading and executing lines until the user quits. */ |
252 | while (!done) | 313 | while (!done) |
253 | { | 314 | { |
254 | 315 | char *p = expand_prompt (); | |
255 | line = readline ((char *) "pop3> "); | 316 | line = readline (p); |
317 | free (p); | ||
256 | 318 | ||
257 | if (!line) | 319 | if (!line) |
258 | break; | 320 | break; |
... | @@ -268,7 +330,7 @@ main (int argc MU_ARG_UNUSED, char **argv) | ... | @@ -268,7 +330,7 @@ main (int argc MU_ARG_UNUSED, char **argv) |
268 | add_history (s); | 330 | add_history (s); |
269 | status = execute_line (s); | 331 | status = execute_line (s); |
270 | if (status != 0) | 332 | if (status != 0) |
271 | fprintf (stderr, "Error: %s\n", mu_strerror (status)); | 333 | mu_error ("Error: %s", mu_strerror (status)); |
272 | } | 334 | } |
273 | 335 | ||
274 | free (line); | 336 | free (line); |
... | @@ -300,8 +362,8 @@ execute_line (char *line) | ... | @@ -300,8 +362,8 @@ execute_line (char *line) |
300 | 362 | ||
301 | if (!command) | 363 | if (!command) |
302 | { | 364 | { |
303 | fprintf (stderr, "%s: No such command for %s.\n", word, progname); | 365 | mu_error ("%s: No such command.", word); |
304 | return (-1); | 366 | return 0; |
305 | } | 367 | } |
306 | 368 | ||
307 | /* Get argument to command, if any. */ | 369 | /* Get argument to command, if any. */ |
... | @@ -378,14 +440,20 @@ com_verbose (char *arg) | ... | @@ -378,14 +440,20 @@ com_verbose (char *arg) |
378 | int | 440 | int |
379 | com_user (char *arg) | 441 | com_user (char *arg) |
380 | { | 442 | { |
443 | int status; | ||
444 | |||
381 | if (!valid_argument ("user", arg)) | 445 | if (!valid_argument ("user", arg)) |
382 | return EINVAL; | 446 | return EINVAL; |
383 | return mu_pop3_user (pop3, arg); | 447 | status = mu_pop3_user (pop3, arg); |
448 | if (status == 0) | ||
449 | username = strdup (arg); | ||
450 | return status; | ||
384 | } | 451 | } |
385 | 452 | ||
386 | int | 453 | int |
387 | com_apop (char *arg) | 454 | com_apop (char *arg) |
388 | { | 455 | { |
456 | int status; | ||
389 | char *user, *digest; | 457 | char *user, *digest; |
390 | 458 | ||
391 | if (!valid_argument ("apop", arg)) | 459 | if (!valid_argument ("apop", arg)) |
... | @@ -394,7 +462,13 @@ com_apop (char *arg) | ... | @@ -394,7 +462,13 @@ com_apop (char *arg) |
394 | digest = strtok (NULL, " "); | 462 | digest = strtok (NULL, " "); |
395 | if (!valid_argument ("apop", user) || !valid_argument ("apop", digest)) | 463 | if (!valid_argument ("apop", user) || !valid_argument ("apop", digest)) |
396 | return EINVAL; | 464 | return EINVAL; |
397 | return mu_pop3_apop (pop3, user, digest); | 465 | status = mu_pop3_apop (pop3, user, digest); |
466 | if (status == 0) | ||
467 | { | ||
468 | username = strdup (user); | ||
469 | pop_session_status = pop_session_logged_in; | ||
470 | } | ||
471 | return status; | ||
398 | } | 472 | } |
399 | 473 | ||
400 | int | 474 | int |
... | @@ -505,9 +579,32 @@ echo_on (struct termios *stored_settings) | ... | @@ -505,9 +579,32 @@ echo_on (struct termios *stored_settings) |
505 | } | 579 | } |
506 | 580 | ||
507 | int | 581 | int |
582 | com_prompt (char *arg) | ||
583 | { | ||
584 | int quote; | ||
585 | size_t size; | ||
586 | |||
587 | if (!valid_argument ("prompt", arg)) | ||
588 | return EINVAL; | ||
589 | |||
590 | free (prompt); | ||
591 | size = mu_argcv_quoted_length (arg, "e); | ||
592 | prompt = malloc (size + 1); | ||
593 | if (!prompt) | ||
594 | { | ||
595 | mu_error ("Memory exhausted"); | ||
596 | exit (1); | ||
597 | } | ||
598 | mu_argcv_unquote_copy (prompt, arg, size); | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | int | ||
508 | com_pass (char *arg) | 603 | com_pass (char *arg) |
509 | { | 604 | { |
605 | int status; | ||
510 | char pass[256]; | 606 | char pass[256]; |
607 | |||
511 | if (!arg || *arg == '\0') | 608 | if (!arg || *arg == '\0') |
512 | { | 609 | { |
513 | struct termios stored_settings; | 610 | struct termios stored_settings; |
... | @@ -522,7 +619,10 @@ com_pass (char *arg) | ... | @@ -522,7 +619,10 @@ com_pass (char *arg) |
522 | pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */ | 619 | pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */ |
523 | arg = pass; | 620 | arg = pass; |
524 | } | 621 | } |
525 | return mu_pop3_pass (pop3, arg); | 622 | status = mu_pop3_pass (pop3, arg); |
623 | if (status == 0) | ||
624 | pop_session_status = pop_session_logged_in; | ||
625 | return status; | ||
526 | } | 626 | } |
527 | 627 | ||
528 | int | 628 | int |
... | @@ -533,7 +633,7 @@ com_stat (char *arg MU_ARG_UNUSED) | ... | @@ -533,7 +633,7 @@ com_stat (char *arg MU_ARG_UNUSED) |
533 | 633 | ||
534 | count = size = 0; | 634 | count = size = 0; |
535 | status = mu_pop3_stat (pop3, &count, &size); | 635 | status = mu_pop3_stat (pop3, &count, &size); |
536 | fprintf (stdout, "Mesgs: %d Size %d\n", count, size); | 636 | printf ("Mesgs: %d Size %d\n", count, size); |
537 | return status; | 637 | return status; |
538 | } | 638 | } |
539 | 639 | ||
... | @@ -653,19 +753,74 @@ com_retr (char *arg) | ... | @@ -653,19 +753,74 @@ com_retr (char *arg) |
653 | } | 753 | } |
654 | 754 | ||
655 | int | 755 | int |
756 | get_port (const char *port_str, int *pn) | ||
757 | { | ||
758 | short port_num; | ||
759 | long num; | ||
760 | char *p; | ||
761 | |||
762 | num = port_num = strtol (port_str, &p, 0); | ||
763 | if (*p == 0) | ||
764 | { | ||
765 | if (num != port_num) | ||
766 | { | ||
767 | mu_error ("bad port number: %s", port_str); | ||
768 | return 1; | ||
769 | } | ||
770 | } | ||
771 | else | ||
772 | { | ||
773 | struct servent *sp = getservbyname (port_str, "tcp"); | ||
774 | if (!sp) | ||
775 | { | ||
776 | mu_error ("unknown port name"); | ||
777 | return 1; | ||
778 | } | ||
779 | port_num = ntohs (sp->s_port); | ||
780 | } | ||
781 | *pn = port_num; | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | int | ||
656 | com_connect (char *arg) | 786 | com_connect (char *arg) |
657 | { | 787 | { |
658 | char host[256]; | ||
659 | int port = 110; | ||
660 | int status; | 788 | int status; |
789 | int n = 110; | ||
790 | int argc; | ||
791 | char **argv; | ||
792 | |||
661 | if (!valid_argument ("connect", arg)) | 793 | if (!valid_argument ("connect", arg)) |
662 | return 1; | 794 | return 1; |
663 | *host = '\0'; | 795 | |
664 | sscanf (arg, "%256s %d", host, &port); | 796 | if (mu_argcv_get (arg, NULL, NULL, &argc, &argv)) |
665 | if (!valid_argument ("connect", host)) | 797 | { |
798 | mu_error ("Cannot parse arguments"); | ||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | if (!valid_argument ("connect", argv[0])) | ||
803 | { | ||
804 | mu_argcv_free (argc, argv); | ||
666 | return EINVAL; | 805 | return EINVAL; |
667 | if (pop3) | 806 | } |
807 | |||
808 | if (argc > 2) | ||
809 | { | ||
810 | mu_error ("Too many arguments"); | ||
811 | mu_argcv_free (argc, argv); | ||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | if (argc == 2 && get_port (argv[1], &n)) | ||
816 | { | ||
817 | mu_argcv_free (argc, argv); | ||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | if (pop_session_status != pop_session_disconnected) | ||
668 | com_disconnect (NULL); | 822 | com_disconnect (NULL); |
823 | |||
669 | status = mu_pop3_create (&pop3); | 824 | status = mu_pop3_create (&pop3); |
670 | if (status == 0) | 825 | if (status == 0) |
671 | { | 826 | { |
... | @@ -674,7 +829,7 @@ com_connect (char *arg) | ... | @@ -674,7 +829,7 @@ com_connect (char *arg) |
674 | if (verbose) | 829 | if (verbose) |
675 | com_verbose ("on"); | 830 | com_verbose ("on"); |
676 | status = | 831 | status = |
677 | mu_tcp_stream_create (&tcp, host, port, | 832 | mu_tcp_stream_create (&tcp, argv[0], n, |
678 | MU_STREAM_READ | MU_STREAM_NO_CHECK); | 833 | MU_STREAM_READ | MU_STREAM_NO_CHECK); |
679 | if (status == 0) | 834 | if (status == 0) |
680 | { | 835 | { |
... | @@ -688,20 +843,35 @@ com_connect (char *arg) | ... | @@ -688,20 +843,35 @@ com_connect (char *arg) |
688 | } | 843 | } |
689 | } | 844 | } |
690 | 845 | ||
691 | if (status != 0) | 846 | if (status) |
692 | fprintf (stderr, "Failed to create pop3: %s\n", mu_strerror (status)); | 847 | { |
848 | mu_error ("Failed to create pop3: %s", mu_strerror (status)); | ||
849 | mu_argcv_free (argc, argv); | ||
850 | } | ||
851 | else | ||
852 | { | ||
853 | connect_argc = argc; | ||
854 | connect_argv = argv; | ||
855 | port = n; | ||
856 | pop_session_status = pop_session_connected; | ||
857 | } | ||
858 | |||
693 | return status; | 859 | return status; |
694 | } | 860 | } |
695 | 861 | ||
696 | int | 862 | int |
697 | com_disconnect (char *arg MU_ARG_UNUSED) | 863 | com_disconnect (char *arg MU_ARG_UNUSED) |
698 | { | 864 | { |
699 | (void) arg; | ||
700 | if (pop3) | 865 | if (pop3) |
701 | { | 866 | { |
702 | mu_pop3_disconnect (pop3); | 867 | mu_pop3_disconnect (pop3); |
703 | mu_pop3_destroy (&pop3); | 868 | mu_pop3_destroy (&pop3); |
704 | pop3 = NULL; | 869 | pop3 = NULL; |
870 | |||
871 | mu_argcv_free (connect_argc, connect_argv); | ||
872 | connect_argc = 0; | ||
873 | connect_argv = NULL; | ||
874 | pop_session_status = pop_session_disconnected; | ||
705 | } | 875 | } |
706 | return 0; | 876 | return 0; |
707 | } | 877 | } |
... | @@ -718,11 +888,11 @@ com_quit (char *arg MU_ARG_UNUSED) | ... | @@ -718,11 +888,11 @@ com_quit (char *arg MU_ARG_UNUSED) |
718 | } | 888 | } |
719 | else | 889 | else |
720 | { | 890 | { |
721 | fprintf (stdout, "Try 'exit' to leave %s\n", progname); | 891 | printf ("Try 'exit' to leave %s\n", mu_program_name); |
722 | } | 892 | } |
723 | } | 893 | } |
724 | else | 894 | else |
725 | fprintf (stdout, "Try 'exit' to leave %s\n", progname); | 895 | printf ("Try 'exit' to leave %s\n", mu_program_name); |
726 | return status; | 896 | return status; |
727 | } | 897 | } |
728 | 898 | ||
... | @@ -745,7 +915,7 @@ valid_argument (const char *caller, char *arg) | ... | @@ -745,7 +915,7 @@ valid_argument (const char *caller, char *arg) |
745 | { | 915 | { |
746 | if (!arg || !*arg) | 916 | if (!arg || !*arg) |
747 | { | 917 | { |
748 | fprintf (stderr, "%s: Argument required.\n", caller); | 918 | mu_error ("%s: Argument required", caller); |
749 | return 0; | 919 | return 0; |
750 | } | 920 | } |
751 | 921 | ... | ... |
-
Please register or sign in to post a comment