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