updown.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:14k
源码类别:

Modem编程

开发平台:

Unix_Linux

  1. /*
  2.  * updown.c Routines to do up and downloading by calling external
  3.  * programs (sz, rz, kermit).
  4.  *
  5.  * This file is part of the minicom communications package,
  6.  * Copyright 1991-1995 Miquel van Smoorenburg.
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License
  10.  * as published by the Free Software Foundation; either version
  11.  * 2 of the License, or (at your option) any later version.
  12.  *
  13.  * jl 13.09.97 pass actual terminal lines (LINES - statusline)
  14.  * to runscript in environment variable TERMLIN
  15.  * jl 16.09.97 logging of sz/rz file transfers
  16.  * jl 29.09.97 fix on the transfer logging
  17.  * hgk&jl 2.98 filename selection window
  18.  * acme 25.02.98 i18n
  19.  * js&jl 04.98 the better filename selection window
  20.  */
  21. #include "port.h"
  22. #include "minicom.h"
  23. #include "intl.h"
  24. /*#define LOG_XFER   debugging option to log all output of rz/sz
  25.  */
  26. static int udpid;
  27. /*
  28.  * Change to a directory.
  29.  */
  30. static int mcd(dir)
  31. char *dir;
  32. {
  33.   char buf[256];
  34.   char err[50];
  35.   static char odir[256];
  36.   static int init = 0;
  37.   if (!init) {
  38.    if (*dir == 0) return(0);
  39.    init = 1;
  40. #if defined (_COH3) || defined(NeXT)
  41. getwd(odir);
  42. #else
  43.    getcwd(odir, 255);
  44. #endif
  45.   }
  46.   if (*dir == 0) {
  47.    chdir(odir);
  48.    return(0);
  49.   }
  50.   
  51.   if(*dir != '/') {
  52.    snprintf(buf, sizeof(buf), "%s/%s", homedir, dir);
  53.    dir = buf;
  54.   }
  55.   if (chdir(dir) < 0) {
  56.    /* This may look safe but you might I8N change the string! so
  57.       snprintf it */
  58.    snprintf(err, sizeof(err),  _("Cannot chdir to %.30s"), dir);
  59.    werror(err);
  60.    return(-1);
  61.   }
  62.   return(0);
  63. }
  64. /*
  65.  * Catch the CTRL-C signal.
  66.  */
  67. /*ARGSUSED*/
  68. static void udcatch(dummy)
  69. int dummy;
  70. {
  71.   (void)dummy;
  72.   signal(SIGINT, udcatch);
  73.   if (udpid) kill((pid_t)udpid, SIGKILL);
  74. }
  75. /*
  76.  * Translate %b to the current bps rate, and
  77.  *           %l to the current tty port.
  78.  *           %f to the serial port file descriptor
  79.  */
  80. static char *translate(s)
  81. char *s;
  82. {
  83.   static char buf[128];
  84.   char str_portfd[8];     /* kino */
  85.   int i;
  86.   for(i = 0; *s && i < 127; i++, s++) {
  87.    if (*s != '%') {
  88.    buf[i] = *s;
  89.    continue;
  90.    }
  91.    switch(*++s) {
  92.    case 'l':
  93.    strncpy(buf + i, dial_tty, sizeof(buf)-i);
  94.    i += strlen(dial_tty) - 1;
  95.    break;
  96.    case 'b':
  97.    strncpy(buf + i, P_BAUDRATE, sizeof(buf)-i);
  98.    i += strlen(P_BAUDRATE) - 1;
  99.    break;
  100.   case 'f':
  101.    sprintf(str_portfd, "%d", portfd);
  102.                         strncpy(buf + i, str_portfd, sizeof(buf)-i);
  103.                         i += strlen(str_portfd) - 1;
  104.                         break;
  105.    default:
  106.    buf[i++] = '%';
  107.    buf[i] = *s;
  108.    break;
  109.    }
  110.   }
  111.   buf[i] = 0;
  112.   return(buf);
  113. }
  114. /*
  115.  * Trim the leading & trailing whitespaces from the string
  116.  * jl 15.09.97
  117.  */
  118. char *trim(char *outstring, char *instring, int n)
  119. {
  120.   char *p;
  121.   char *ip;
  122.   char *op;
  123.   char *np;
  124.   ip = instring;
  125.   np = ip + n;
  126.   while ((*ip <= ' ') && (ip < np)) ip++;
  127.   op = outstring;
  128.   np = op + n;
  129.   while ((*ip >= ' ') && (op <= np)) {
  130.     *op = *ip;
  131.     ip++;
  132.     op++;
  133.   }
  134.   if (op<np)
  135.     *op = 0;
  136.   while ((op > outstring) && (*op <= ' ')) {
  137.     *op = 0;
  138.     op--;
  139.   }
  140.   p = outstring;
  141.   return(p);
  142. }
  143.   
  144. /*
  145.  * Choose from numerous up and download protocols!
  146.  */
  147. void updown(what, nr)
  148. int what;
  149. int nr;
  150. {
  151. #ifdef LOG_XFER
  152.   #warning LOG_XFER defined!
  153.   FILE *xfl;
  154. #endif
  155.   char *name[13];
  156.   int idx[13];
  157.   int r, f, g = 0;
  158.   char *t = what == 'U' ? _("Upload") : _("Download");
  159.   char buf[160];
  160.   char buffirst[20];
  161.   char xfrstr[160] = "";
  162.   char trimbuf[160] = "";
  163.   char title[64];
  164.   char *s ="";
  165.   int pipefd[2];
  166.   int n, status;
  167.   char cmdline[128];
  168.   WIN *win = (WIN *)NULL;
  169. #if VC_MUSIC
  170.   _PROTO(void music, (void));
  171. #endif
  172.   if (mcd(what == 'U' ? P_UPDIR : P_DOWNDIR) < 0)
  173.    return;
  174.   /* Automatic? */
  175.   if (nr == 0) {
  176. for(f = 0; f < 12; f++) {
  177.    if (P_PNAME(f)[0] && P_PUD(f) == what) {
  178.    name[g] = P_PNAME(f);
  179.    idx[g++] = f;
  180.    }
  181. }
  182. name[g] = CNULL;
  183. if (g == 0) return;
  184. r = wselect(30, 7, name, NIL_FUNLIST, t, stdattr, mfcolor, mbcolor) - 1;
  185. if (r < 0) return;
  186. g = idx[r];
  187.   } else g = nr;
  188.   buf[0] = 0;
  189. /* jseymour file selector with choice of dir on zmodem, etc. download */
  190. #if 1
  191.   {
  192. int multiple; /* 0:only directory, 1:one file, -1:any number */
  193. if(P_MUL(g)=='Y') {
  194.     /* need file(s), or just a directory? */
  195.     multiple = what == 'U'? -1 : 0;
  196. }
  197. else {
  198.     multiple = 1; /* only one allowed */
  199. }
  200. if (P_FSELW[0] == 'Y' && (what == 'U' || P_ASKDNDIR[0] == 'Y')) {
  201.   s = filedir(multiple, what == 'U'? 0 : 1);
  202.   if (s == NULL)
  203.     return;
  204. }
  205. else if (P_PNN(g) == 'Y') {
  206.   s = input(_("Please enter file names"), buf);
  207.   if (s == NULL)
  208.     return;
  209. }
  210. /* discard directory if "multiple" == 0 */
  211. snprintf(cmdline, sizeof(cmdline), "%s %s", P_PPROG(g), multiple == 0? "" : s);
  212.   }
  213. #endif
  214.   if (P_LOGXFER[0] == 'Y')
  215.     do_log(cmdline);   /* jl 22.06.97 */
  216.   if (P_PFULL(g) == 'N') {
  217.     win = wopen(10, 7, 70, 13, BSINGLE, stdattr, mfcolor, mbcolor, 1, 0, 1);
  218.     snprintf(title, sizeof(title), _("%.30s %s - Press CTRL-C to quit"), P_PNAME(g),
  219.     what == 'U' ? _("upload") : _("download"));
  220.     wtitle(win, TMID, title);
  221.     pipe(pipefd);
  222.   } else
  223.     wleave();
  224.   switch(udpid = fork()) {
  225.    case -1:
  226.    werror(_("Out of memory: could not fork()"));
  227. if (win) {
  228.    close(pipefd[0]);
  229.    close(pipefd[1]);
  230.    wclose(win, 1);
  231. } else
  232. wreturn();
  233.    (void) mcd("");
  234.    return;
  235.    case 0: /* Child */
  236. if (P_PIORED(g) == 'Y') {
  237.    dup2(portfd, 0);
  238.    dup2(portfd, 1);
  239. }
  240. if (win) {
  241.    dup2(pipefd[1], 2);
  242.    close(pipefd[0]);
  243.    if (pipefd[1] != 2) close(pipefd[1]);
  244.    }
  245.    for(n = 1; n < _NSIG; n++) signal(n, SIG_DFL);
  246.   
  247. set_privs();
  248. setgid((gid_t)real_gid);
  249.    setuid((uid_t)real_uid);
  250.    (void) fastexec(translate(cmdline));
  251.    exit(1);
  252.    default: /* Parent */
  253.    break;
  254.   }
  255.   if (win) {
  256. (void) setcbreak(1); /* Cbreak, no echo. */
  257. enab_sig(1, 0);        /* But enable SIGINT */
  258.   }
  259.   signal(SIGINT, udcatch);
  260.   if (P_PIORED(g) == 'Y') {
  261. close(pipefd[1]);
  262. #ifdef LOG_XFER
  263. xfl=fopen("xfer.log","wb");
  264. #endif
  265. while((n = read(pipefd[0], buf, sizeof(buf))) > 0) {
  266.    buf[n] = '';
  267.    wputs(win, buf);
  268. timer_update();
  269. /* Log the filenames & sizes  jl 14.09.97 */
  270. if (P_LOGXFER[0] == 'Y') {
  271. #ifdef LOG_XFER
  272.   if (xfl)
  273.     fprintf(xfl,">%s<n",buf);
  274. #endif
  275.   if (sscanf(buf, "%19s", buffirst)) { /* if / jl 29.09.97 */
  276.     if (!strncmp (buffirst, "Receiving", 9) ||
  277. !strncmp (buffirst, "Sending", 7)) {
  278.       if (xfrstr[0]) {
  279. trim (trimbuf, xfrstr, sizeof(trimbuf));
  280. do_log (trimbuf);
  281. xfrstr[0] = 0;
  282.       }
  283.       trim (trimbuf, buf, sizeof(trimbuf));
  284.       do_log(trimbuf);
  285.     } else if (!strncmp (buffirst, "Bytes", 5)) {
  286.       strncpy (xfrstr, buf, sizeof(xfrstr));
  287.     }
  288.     buffirst[0]=0;
  289.     trimbuf[0]=0;
  290.   }
  291. }
  292. }
  293. #ifdef LOG_XFER
  294. if (xfl)
  295.   fclose(xfl);
  296. #endif
  297.   }
  298.   /* Log the last file size jl 14.09.97 */
  299.   if (P_LOGXFER[0] == 'Y' && xfrstr[0]) {
  300.     trim (trimbuf, xfrstr, sizeof(trimbuf));
  301.     do_log (trimbuf);
  302.     xfrstr[0] = 0;
  303.   }
  304.   while( udpid != m_wait(&status) );
  305.   if (win) {
  306. enab_sig(0, 0);
  307. signal(SIGINT, SIG_IGN);
  308.   }
  309.   if (win == (WIN *)0) wreturn();
  310.   /* MARK updated 02/17/94 - Flush modem port before displaying READY msg */
  311.   /* because a BBS often displays menu text right after a download, and we */
  312.   /* don't want the modem buffer to be lost while waiting for key to be hit */
  313.   m_flush(portfd);
  314.   port_init();
  315.   (void) setcbreak(2); /* Raw, no echo. */
  316.   if (win) close(pipefd[0]);
  317.   (void) mcd("");
  318.   timer_update();
  319.   /* If we got interrupted, status != 0 */
  320.   if (win && (status & 0xFF00) == 0) {
  321. #if VC_MUSIC
  322. if (P_SOUND[0] == 'Y') {
  323. wprintf(win, _("n READY: press any key to continue..."));
  324. music();
  325. } else
  326. sleep(1);
  327. #else
  328. /* MARK updated 02/17/94 - If there was no VC_MUSIC capability, */
  329. /* then at least make some beeps! */
  330. if (P_SOUND[0] == 'Y') wprintf(win, "070707");
  331. sleep(1);
  332. #endif
  333.   }
  334.   if (win) wclose(win, 1);
  335. }
  336. /*
  337.  * Run kermit. Used to do this in the main window, but newer
  338.  * versions of kermit are too intelligent and just want a tty
  339.  * for themselves or they won't function ok. Shame.
  340.  */
  341. void kermit()
  342. {
  343.   int status;
  344.   int pid, n;
  345.   char buf[81];
  346.   int fd;
  347.   /* Clear screen, set keyboard modes etc. */
  348.   wleave();
  349.   switch(pid = fork()) {
  350.    case -1:
  351. wreturn();
  352.    werror(_("Out of memory: could not fork()"));
  353.    return;
  354.    case 0: /* Child */
  355.    /* Remove lockfile */
  356. set_privs();
  357.    if (lockfile[0]) unlink(lockfile);
  358. setgid((gid_t)real_gid);
  359. setuid((uid_t)real_uid);
  360.    for(n = 0; n < _NSIG; n++) signal(n, SIG_DFL);
  361.    (void) fastexec(translate(P_KERMIT));
  362.    exit(1);
  363.    default: /* Parent */
  364.    break;
  365.   }
  366.   (void) m_wait(&status);
  367.   /* Restore screen and keyboard modes */
  368.   wreturn();
  369.   /* Re-create lockfile */
  370.   if (lockfile[0]) {
  371. set_privs();
  372. n = umask(022);
  373.    /* Create lockfile compatible with UUCP-1.2 */
  374.    if ((fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) {
  375.    werror(_("Cannot re-create lockfile!"));
  376.    } else {
  377. (void) chown(lockfile, (uid_t)real_uid, (gid_t)real_gid);
  378.    snprintf(buf, sizeof(buf),  "%05d minicom %.20sn", (int)getpid(), username);
  379.    write(fd, buf, strlen(buf));
  380.    close(fd);
  381.    }
  382. (void) umask(n);
  383. drop_privs();
  384.   }
  385.   m_flush(portfd);
  386.   port_init();
  387. }
  388. /* ============ Here begins the setenv function ============= */
  389. /*
  390.  * Compare two strings up to '='
  391.  */
  392. static int varcmp(s1, s2)
  393. char *s1, *s2;
  394. {
  395.   while(*s1 && *s2) {
  396.    if (*s1 == '=' && *s2 == '=') return(1);
  397.    if (*s1++ != *s2++) return(0);
  398.   }
  399.   return(1);
  400. }
  401. /*
  402.  * Generate a name=value string.
  403.  */
  404. static char *makenv(name, value)
  405. char *name, *value;
  406. {
  407.   char *p;
  408.   
  409.   if ((p = (char *)malloc(strlen(name) + strlen(value) + 3)) == CNULL)
  410. return(p);
  411.   sprintf(p, "%s=%s", name, value);
  412.   return(p);
  413. }
  414. /*
  415.  * Set a environment variable. 
  416.  */
  417. int mc_setenv(name, value)
  418. char *name, *value;
  419. {
  420.   static int init = 0;
  421.   extern char **environ;
  422.   char *p, **e, **newe;
  423.   int count = 0;
  424.   if ((p = makenv(name, value)) == CNULL) return(-1);
  425.   for(e = environ; *e; e++) {
  426.    count++;
  427.    if(varcmp(name, *e)) {
  428.    *e = p;
  429.    return(0);
  430.    }
  431.   }
  432.   count += 2;
  433.   if ((newe = (char **)malloc(sizeof(char *) * count)) == (char **)0) {
  434.    free(p);
  435.    return(-1);
  436.   }
  437.   memcpy((char *)newe, (char *)environ , (int) (count * sizeof(char *)));
  438.   if (init) free((char *)environ);
  439.   init = 1;
  440.   environ = newe;
  441.   for(e = environ; *e; e++)
  442.    ;
  443.   *e++ = p;
  444.   *e = CNULL;
  445.   return(0);
  446. }
  447. /* ============ This is the end of the setenv function ============= */
  448. /*
  449.  * Run an external script.
  450.  * ask = 1 if first ask for confirmation.
  451.  * s = scriptname, l=loginname, p=password.
  452.  */
  453. void runscript(ask, s, l, p)
  454. int ask;
  455. char *s, *l, *p;
  456. {
  457.   int status;
  458.   int n;
  459.   int pipefd[2];
  460.   char buf[81];
  461.   char scr_lines[5];
  462.   char cmdline[128];
  463.   char *ptr;
  464.   WIN *w;
  465.   int done = 0;
  466.   char *msg = "Same as last";
  467.   char* username = _(" A -   Username        :"),
  468.       * password = _(" B -   Password        :"),
  469.       * name_of_script = _(" C -   Name of script  :"),
  470.       * question = _("Change which setting?     (Return to run, ESC to stop)");
  471.   if (ask) {
  472. w = wopen(10, 5, 70, 10, BDOUBLE, stdattr, mfcolor, mbcolor, 0, 0, 1);
  473. wtitle(w, TMID, _("Run a script"));
  474. wputs(w, "n");
  475. wprintf(w, "%s %sn", username, scr_user[0] ? msg : "");
  476. wprintf(w, "%s %sn", password, scr_passwd[0] ? msg : "");
  477. wprintf(w, "%s %sn", name_of_script, scr_name);
  478. wlocate(w, 4, 5);
  479. wputs(w, question);
  480. wredraw(w, 1);
  481. while(!done) {
  482.     wlocate(w, strlen (question) + 5, 5);
  483.     n = wxgetch();
  484.     if (islower(n)) n = toupper(n);
  485.     switch(n) {
  486. case 'r':
  487. case 'n':
  488. if (scr_name[0] == '') {
  489. wbell();
  490. break;
  491. }
  492. wclose(w, 1);
  493. done = 1;
  494. break;
  495. case 27: /* ESC */
  496. wclose(w, 1);
  497. return;
  498. case 'A':
  499. wlocate(w, strlen (username) + 1, 1);
  500. wclreol(w);
  501. scr_user[0] = 0;
  502. wgets(w, scr_user, 32, 32);
  503. break;
  504. case 'B':
  505. wlocate(w, strlen (password) + 1, 2);
  506. wclreol(w);
  507. scr_passwd[0] = 0;
  508. wgets(w, scr_passwd, 32, 32);
  509. break;
  510. case 'C':
  511. wlocate(w, strlen (name_of_script) + 1, 3);
  512. wgets(w, scr_name, 32, 32);
  513. break;
  514. default:
  515. break;
  516.     }
  517. }
  518.   } else {
  519.    strncpy(scr_user, l, sizeof(scr_user));
  520.    strncpy(scr_name, s, sizeof(scr_name));
  521.    strncpy(scr_passwd, p, sizeof(scr_passwd));
  522.   }
  523.   sprintf(scr_lines, "%d", (int) lines);  /* jl 13.09.97 */
  524.   /* Throw away status line if temporary */
  525.   if (tempst) {
  526.    wclose(st, 1);
  527.    tempst = 0;
  528.    st = NIL_WIN;
  529.   }
  530.   scriptname(scr_name);
  531.   
  532.   pipe(pipefd);
  533.   if (mcd(P_SCRIPTDIR) < 0) return;
  534.   snprintf(cmdline, sizeof(cmdline), "%s %s %s %s",
  535.    P_SCRIPTPROG, scr_name, logfname, logfname[0]==0? "": homedir);
  536.   switch(udpid = fork()) {
  537.    case -1:
  538.    werror(_("Out of memory: could not fork()"));
  539.    close(pipefd[0]);
  540.    close(pipefd[1]);
  541.    (void) mcd("");
  542.    return;
  543.    case 0: /* Child */
  544.    dup2(portfd, 0);
  545.    dup2(portfd, 1);
  546.    dup2(pipefd[1], 2);
  547.    close(pipefd[0]);
  548.    close(pipefd[1]);
  549.   
  550.    for(n = 1; n < _NSIG; n++) signal(n, SIG_DFL);
  551.   
  552. set_privs();
  553. setgid((gid_t)real_gid);
  554.    setuid((uid_t)real_uid);
  555.    mc_setenv("LOGIN", scr_user);
  556.    mc_setenv("PASS", scr_passwd);
  557. mc_setenv("TERMLIN", scr_lines); /* jl 13.09.97 */
  558.    (void) fastexec(translate(cmdline));
  559.    exit(1);
  560.    default: /* Parent */
  561.    break;
  562.   }
  563.   (void) setcbreak(1); /* Cbreak, no echo */
  564.   enab_sig(1, 0);        /* But enable SIGINT */
  565.   signal(SIGINT, udcatch);
  566.   close(pipefd[1]);
  567.   
  568.   /* pipe output from "runscript" program to terminal emulator */
  569.   while((n = read(pipefd[0], buf, 80)) > 0) {
  570.    ptr = buf;
  571.    while(n--)
  572.    vt_out(*ptr++);
  573. timer_update();
  574.    wflush();
  575.   }
  576.   
  577.   /* Collect status, and clean up. */
  578.   (void) m_wait(&status);
  579.   enab_sig(0, 0);
  580.   signal(SIGINT, SIG_IGN);
  581.   (void) setcbreak(2); /* Raw, no echo */
  582.   close(pipefd[0]);
  583.   scriptname("");
  584.   (void) mcd("");
  585. }