1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #include <stdio.h>
4 #include <pobl/bl_dlfcn.h>
5 #include <pobl/bl_str.h>
6 #include <pobl/bl_debug.h>
7 #include <pobl/bl_mem.h>
8 #include <pobl/bl_file.h>
9
10 #include "zmodem.h"
11
12 #ifndef LIBDIR
13 #define TRANSFERLIB_DIR "/usr/local/lib/mlterm/"
14 #else
15 #define TRANSFERLIB_DIR LIBDIR "/mlterm/"
16 #endif
17
18 /* --- static variables --- */
19
20 static int zmodem_mode;
21 static struct file_info zmodem_info[2];
22
23 static void (*dl_zmodem)(unsigned char *, const unsigned int, unsigned char *, unsigned int *,
24 const unsigned int);
25 static Q_BOOL (*dl_zmodem_start)(struct file_info *, const char *, const Q_BOOL,
26 const ZMODEM_FLAVOR, int);
27 static Q_BOOL (*dl_zmodem_cancel)(void);
28 static Q_BOOL (*dl_zmodem_is_processing)(int *, int *);
29
30 static int is_tried;
31 #ifndef NO_DYNAMIC_LOAD_TRANSFER
32 static bl_dl_handle_t handle;
33 #endif
34 static int progress_prev = -1;
35
36 /* --- static functions --- */
37
load_library(void)38 static int load_library(void) {
39 is_tried = 1;
40
41 #ifndef NO_DYNAMIC_LOAD_TRANSFER
42 if (!(handle = bl_dl_open(TRANSFERLIB_DIR, "zmodem")) && !(handle = bl_dl_open("", "zmodem"))) {
43 bl_error_printf("ZMODEM: Could not load.\n");
44
45 return 0;
46 }
47
48 bl_dl_close_at_exit(handle);
49
50 dl_zmodem = bl_dl_func_symbol(handle, "zmodem");
51 dl_zmodem_start = bl_dl_func_symbol(handle, "zmodem_start");
52 dl_zmodem_cancel = bl_dl_func_symbol(handle, "zmodem_cancel");
53 dl_zmodem_is_processing = bl_dl_func_symbol(handle, "zmodem_is_processing");
54 #else
55 dl_zmodem = zmodem;
56 dl_zmodem_start = zmodem_start;
57 dl_zmodem_cancel = zmodem_cancel;
58 dl_zmodem_is_processing = zmodem_is_processing;
59 #endif
60
61 return 1;
62 }
63
reset(void)64 static void reset(void) {
65 zmodem_mode = 0;
66 free(zmodem_info[0].name);
67 zmodem_info[0].name = NULL;
68 progress_prev = -1;
69 }
70
71 /* --- global functions --- */
72
vt_transfer_start(char * send_file,const char * save_dir,int is_crc32,int progress_len)73 int vt_transfer_start(/* vt_transfer_type_t type, */
74 char *send_file /* allocated by the caller */,
75 const char *save_dir, int is_crc32, int progress_len) {
76 Q_BOOL ret;
77
78 if (zmodem_mode || (is_tried ? (dl_zmodem_start == NULL) : !load_library())) {
79 return 0;
80 }
81
82 if (send_file) {
83 zmodem_info[0].name = send_file;
84 stat(send_file, &zmodem_info[0].fstats);
85
86 ret = (*dl_zmodem_start)(zmodem_info, save_dir, Q_TRUE, is_crc32 ? Z_CRC32 : Z_CRC16,
87 progress_len);
88 } else {
89 char *p;
90 size_t len = strlen(save_dir);
91
92 if ((p = alloca(len + 2))) {
93 memcpy(p, save_dir, len);
94 strcpy(p + len, "/");
95 bl_mkdir_for_file(p, 0700);
96 }
97
98 ret = (*dl_zmodem_start)(NULL, save_dir, Q_FALSE, is_crc32 ? Z_CRC32 : Z_CRC16, progress_len);
99 }
100
101 if (ret) {
102 zmodem_mode = 1;
103
104 return 1;
105 } else {
106 free(zmodem_info[0].name);
107 zmodem_info[0].name = NULL;
108
109 return 0;
110 }
111 }
112
vt_transfer_cancel(void)113 void vt_transfer_cancel(void) {
114 (*dl_zmodem_cancel)();
115 reset();
116 }
117
vt_transfer_data(u_char * input,const u_int input_n,u_char * output,u_int * output_n,const u_int output_max)118 void vt_transfer_data(u_char *input, const u_int input_n, u_char *output, u_int *output_n,
119 const u_int output_max) {
120 #if 0
121 if (input_n > 0) {
122 FILE *fp = fopen("zmodem.log", "a");
123 u_int i;
124
125 fprintf(fp, "INPUT %d\n", input_n);
126 for (i = 0; i < input_n; i++) {
127 fprintf(fp, "%c", input[i]);
128 }
129 fprintf(fp, "\n");
130 fclose(fp);
131 }
132 #endif
133
134 (*dl_zmodem)(input, input_n, output, output_n, output_max);
135
136 #if 0
137 if (*output_n > 0) {
138 FILE *fp = fopen("zmodem.log", "a");
139 u_int i;
140
141 fprintf(fp, "OUTPUT %d\n", *output_n);
142 for (i = 0; i < *output_n; i++) {
143 fprintf(fp, "%c", output[i]);
144 }
145 fprintf(fp, "\n");
146 fclose(fp);
147 }
148 #endif
149 }
150
vt_transfer_get_state(int * progress_cur,int * progress_len)151 int vt_transfer_get_state(int *progress_cur, int *progress_len) {
152 if ((*dl_zmodem_is_processing)(progress_cur, progress_len)) {
153 if (progress_prev < *progress_cur) {
154 progress_prev = *progress_cur;
155
156 return 1;
157 } else {
158 return -1;
159 }
160 } else {
161 reset();
162
163 return 0;
164 }
165 }
166