home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 March / VPR9703A.ISO / OLS / Os2 / LHA2P205 / LHA2P205.LZH / lha2-2.05pre / source.lzh / src / mn.c < prev    next >
C/C++ Source or Header  |  1996-02-24  |  13KB  |  678 lines

  1. /*
  2.  * mn.c -- main module of LH
  3.  *   Copyright (C) 1988-1992, Haruyasu YOSHIZAKI
  4.  *   Copyright (C) 1991-1996, Satoshi HIRAMATSU (OS/2 HPFS version)
  5.  *
  6.  * $Log$
  7.  */
  8.  
  9.  
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <ctype.h>
  13. #include <stdio.h>
  14. #include <io.h>
  15. #include <errno.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <time.h>
  19. #include <fcntl.h>
  20. #include "typedef.h"
  21. #include "port2.h"
  22. #include "lh.h"
  23. #include "header.h"
  24. #include "errmes.h"
  25. #include "intrface.h"
  26. #include "disp.h"
  27.  
  28.  
  29. #define SECURITY 0
  30.  
  31.  
  32. char work[4096];
  33. char lhtmp1[MAXPATHLEN];
  34. char lhtmp2[MAXPATHLEN];
  35. FILE *inredir = NULL, *response = NULL;
  36. int  outredir;
  37. int  paramcount = -2;
  38. char cmd;
  39. int  cmdupdate;
  40. char *env;
  41. char workdir[MAXPATHLEN];
  42. #if 0
  43. char *pager = "less";
  44. char *keyword = "";
  45. #endif
  46. char arcname[MAXPATHLEN];
  47. char filename1[MAXPATHLEN];
  48. char filename2[MAXPATHLEN];
  49. char filename3[MAXPATHLEN];
  50. FILE *file1, *file2, *file3;
  51. int errorlevel = 0;
  52. #ifdef __SUPPORT_UID_GID__
  53. uid_t uid = 0;            /* root */
  54. gid_t gid = 0;            /* wheel */
  55. #endif
  56. #ifdef __SUPPORT_EA__
  57. FEA2LIST *arcea = (FEA2LIST *)NULL;
  58. #endif
  59.  
  60. #ifndef __SUPPORT_CTIME_ATIME__
  61. static time_t arcstamp;
  62. #else
  63. static struct
  64. {
  65.   time_t mtime;
  66.   time_t ctime;
  67.   time_t atime;
  68. } arcstamp;
  69. #endif
  70.  
  71.  
  72. /* display usages */
  73. void
  74. usage(void)
  75. {
  76.   flg_n = 2;
  77. #ifndef FIRST_COMPILATION
  78.   extract_internal(stdout, use);
  79. #endif
  80.   exit(2);
  81. }
  82.  
  83.  
  84. #ifndef __SUPPORT_CTIME_ATIME__
  85. void
  86. update_arcstamp(void)
  87. {
  88.   if(arcstamp < hpb.mtime)
  89.     arcstamp = hpb.mtime;
  90. }
  91.  
  92.  
  93. static void
  94. set_arcstamp(FILE *f)
  95. {
  96.   if(flg_t)
  97.     setfiletime(f, arcstamp);
  98. }
  99. #else
  100. void
  101. update_arcstamp(void)
  102. {
  103.   if(arcstamp.mtime < hpb.mtime)
  104.     {
  105.       arcstamp.mtime = hpb.mtime;
  106.       arcstamp.atime = hpb.atime;
  107.     }
  108. }
  109.  
  110.  
  111. static void
  112. set_arcstamp(FILE *f)
  113. {
  114.   if(flg_t)
  115.     setfiletime(f, &arcstamp.mtime, (time_t *)NULL, &arcstamp.atime);
  116. }
  117. #endif
  118.  
  119.  
  120. static char *
  121. readword(FILE *file)
  122. {
  123.   char *p;
  124.   int c;
  125.  
  126.   while(((unsigned)(c = getc(file)) & 0xff) <= ' ')
  127.     ;
  128.   if(c < 0)
  129.     {
  130.       fclose(file);
  131.       return NULL;
  132.     }
  133.   p = work;
  134.   do
  135.     *p++ = c;
  136.   while((c = getc(file)) > ' ');
  137.   *p++ = '\0';
  138.  
  139.   return work;
  140. }
  141.  
  142.  
  143. static void
  144. disparcname(char *title)
  145. {
  146.   FILE *f;
  147.  
  148.   f = (cmd == 'L') ? stdout : stderr;
  149.   if(flg_n == 0)
  150.     fprintf(f, "\n%s archive : %s\n\n", title, arcname);
  151. }
  152.  
  153.  
  154. static int
  155. executecmd(void)
  156. {
  157.   int modified, err;
  158.   char *bdir, *path;
  159.   ulong size0, size;
  160.   int _flg_n;
  161.   struct stat statbuf;
  162.   int existarc = 0;
  163.  
  164.   make_crctable();
  165.   err = 0;
  166. #ifndef __SUPPORT_CTIME_ATIME__
  167.   arcstamp = 0;
  168. #else
  169.   arcstamp.mtime = arcstamp.ctime = arcstamp.atime = 0;
  170. #endif
  171.   modified = 0;
  172.   strcpy(filename1, arcname);
  173.   if(cmdupdate)
  174.     {
  175.       strcpy(filename1, lhtmp1);
  176.       if(remove(filename1) && errno != ENOENT)
  177.     error(RDONLY, filename1); /* already EXIST tmpfile */
  178.  
  179.       existarc = stat(arcname, &statbuf);
  180.       if(rename(arcname, filename1) && !existarc)
  181.     {
  182.       /* copy */
  183.       file1 = myeopen(filename1, "wb", NULL);
  184.       file2 = myeopen(arcname, "rb", NULL);
  185.       _flg_n = flg_n;
  186.       flg_n = 2;        /* silent */
  187.       copyfile(file2, file1, statbuf.st_size, 0);
  188.       flg_n = _flg_n;
  189.       fclose(file1);
  190.       fclose(file2);
  191.     }
  192.     }
  193.   file1 = myeopen(filename1, "rb", NULL);
  194.   if(cmdupdate || cmd == 'S')
  195.     {
  196.       if(file1 == NULL)
  197.     {
  198.       fclose(mywopen(arcname, MKFILEERR));
  199.       remove(arcname);
  200.     }
  201.       strcpy(filename2, lhtmp2);
  202.       file2 = mywopen(filename2, NULL);
  203.       if(file2 == NULL)
  204.     {
  205.       file2 = mywopen(lhtmp2, NULL);
  206.       if(file2 == NULL)
  207.         error(MKTMPERR, filename2);
  208.       strcpy(filename2, lhtmp2);
  209.     }
  210.       setvbuf(file2, NULL, _IOFBF, 0x2000);
  211.     }
  212.   else
  213.     setvbuf(file1, NULL, _IOFBF, 0x2000);
  214.  
  215.   switch(cmd)
  216.     {
  217.     case 'V':
  218.       flg_x = 1;
  219.       cmd = 'L';
  220.     case 'L':
  221.       disparcname("Listing of");
  222.       initlist();
  223.       break;
  224.  
  225.     case 'A':
  226.       flg_c = 1;
  227.       cmd = 'U';
  228.     case 'U':
  229.     case 'M':
  230.       if(file1)
  231.     disparcname("Updating");
  232.       else
  233.     disparcname("Creating");
  234.       mklist();
  235.       break;
  236.  
  237.     case 'F':
  238.       disparcname("Freshening");
  239.       break;
  240.  
  241.     case 'D':
  242.       disparcname("Deleting from");
  243.       break;
  244.  
  245.     case 'P':
  246.     case 'E':
  247.       setmode(fileno(stdout), O_BINARY);
  248.       disparcname("Extracting from");
  249.       break;
  250.  
  251.     case 'T':
  252.       disparcname("Testing");
  253.       break;
  254.  
  255. #if 0
  256.     case 'S':
  257.       disparcname("Making SFX of");
  258.       initsfx();
  259.       break;
  260. #endif
  261.     }
  262.  
  263.   if(file1)
  264.     {
  265.       size0 = inithdr(file1);
  266.       if(cmd == 'T' &&
  267.      stricmp(arcname + strlen(arcname) - 4, ".lzh") == 0 && size0 != 0)
  268.     eprintf(EXTRADATA);
  269.  
  270.       while(file1 && (path = gethdr(file1, &hpb)) != NULL)
  271.     {
  272.       bdir = matchpat(path);
  273.       switch(cmd)
  274.         {
  275.         case 'L':
  276.           if(bdir)
  277.         list();
  278.           break;
  279.  
  280.         case 'U':
  281.         case 'M':
  282.           modified += append();
  283.           break;
  284.  
  285.         case 'F':
  286.           modified += freshen(bdir);
  287.           break;
  288.  
  289.         case 'D':
  290.           if(bdir)
  291.         {
  292.           dispalone("Deleted");
  293.           eprintf("\n");
  294.           modified++;
  295.         }
  296.           else
  297.         copylzh(&hpb);
  298.           break;
  299.  
  300.         case 'P':
  301.           flg_n = 2;
  302.         case 'E':
  303.         case 'T':
  304.           if(bdir)
  305.         extract(bdir);
  306.           break;
  307.  
  308. #if 0
  309.         case 'S':
  310.           if(bdir)
  311.         if(copysfx())
  312.           modified++;
  313.           break;
  314. #endif
  315.         
  316.         }
  317.       free(path);
  318.     }
  319.     }
  320.   else
  321.     {
  322.       size0 = 0;
  323.       if(!cmdupdate)
  324.     error(NOARCERR, arcname);
  325.     }
  326.  
  327.   if(!err)
  328.     {
  329.       switch(cmd)
  330.     {
  331.     case 'L':
  332.       endlist(getfiletime(file1));
  333.       break;
  334.  
  335.     case 'U':
  336.     case 'M':
  337.       modified += endappend();
  338.       break;
  339.  
  340. #if 0
  341.     case 'S':
  342.       makesfx(bdir);
  343.       break;
  344. #endif
  345.     }
  346.     }
  347. #if SECURITY
  348.   if(cmd == 'T')
  349.     {
  350.       extern int security(void);
  351.  
  352.       if(security())
  353.     return 1;
  354.     }
  355. #endif
  356.   if(err)
  357.     error(BROKENARC, arcname);
  358.   if(cmd == 'M')
  359.     deletefiles();
  360.   if(cmdupdate || (cmd == 'S' && file2))
  361.     {
  362.       putc('\0', file2);
  363.       size = ftell(file2);
  364.       fflush(file2);
  365.       if(ferror(file2))
  366.     error(WTERR, filename2);
  367.       set_arcstamp(file2);
  368.       fclose(file2);
  369.       if(file1)
  370.     {
  371.       set_arcstamp(file1);
  372.       fclose(file1);
  373.     }
  374.       if(modified == 0)
  375.     {
  376.       rename(filename1, arcname); /* restore the old archive */
  377.       remove(filename2);
  378.     }
  379.       else
  380.     {
  381.       if(rename(filename2, arcname))
  382.         {
  383.           flg_n = 2;
  384.           if(!flg_f && (diskspace(filename1) < size))
  385.         error(COPYERR, NULL);
  386.           eprintf("Copying TMP to ARCHIVE ... ");
  387.           rename(filename1, arcname);
  388.           file1 = mywopen(arcname, COPYERR);
  389.           file2 = myropen(filename2);
  390.           copyfile(file2, file1, size, 0);
  391.           set_arcstamp(file1);
  392.           fclose(file1);
  393. #ifdef __SUPPORT_EA__
  394.           if(arcea)
  395.         SetEA(arcname, arcea);
  396. #endif
  397.           fclose(file2);
  398.           remove(filename2);
  399.           eprintf("done.\n");
  400.         }
  401.       else
  402.         {
  403.           if(cmd != 'S')
  404.         remove(filename1);
  405.         }
  406.       if(size - size0 <= 1)
  407.         remove(arcname);
  408.     }
  409.     }
  410.   else
  411.     fclose(file1);
  412.  
  413.   return 0;
  414. }
  415.  
  416.  
  417. static int
  418. execute(void)
  419. {
  420.   struct find_t findbuf;
  421.   int nofile;
  422.   unsigned testflag;
  423.  
  424.   testflag = 0;
  425.   nofile = _dos_findfirst(arcname, 0x07, &findbuf);
  426.   if(nofile && strchr("AUM", cmd) == NULL)
  427.     error(NOARCERR, arcname);
  428.   if(cmdupdate)
  429.     {
  430.       if(strpbrk(arcname, "*?"))
  431.     error(NOARCERR, arcname);
  432.       /* when updating archive, wild cards can't used */
  433.       if(!nofile && findbuf.attrib & 0x01)
  434.     error(RDONLY, arcname);
  435. #ifdef __SUPPORT_EA__
  436.       if(findbuf.ea)
  437.     arcea = findbuf.ea;
  438. #endif
  439.       executecmd();
  440.     }
  441.   else
  442.     {
  443.       do
  444.     {
  445. #ifdef __SUPPORT_EA__
  446.       if(findbuf.ea)
  447.         free(findbuf.ea);
  448. #endif
  449.       backpath(arcname);
  450.       strcat(arcname, findbuf.name);
  451.       testflag |= (unsigned)executecmd();
  452.     }
  453.       while(!_dos_findnext(&findbuf));
  454.     }
  455.   if(cmd != 'L' && testflag == 0)
  456.     tstpat();
  457.  
  458.   return 0;
  459. }
  460.  
  461.  
  462. int
  463. main(int argc, char *argv[])
  464. {
  465.   uchar c, *p, *q;
  466.   int i;
  467.   static fileinputflag = 0;
  468.   static char *basedir = "";
  469.   int __ifs__;
  470.  
  471.   initbreak();
  472.   getswchar();
  473.   initpat();
  474.  
  475.   SetMessage();
  476.   if((p = getenv("TMPDIR")) != NULL && (p = strtok(p, " \t")) != NULL)
  477.     {
  478.       strcpy(workdir, p);
  479.       flg_w = 1;
  480.     }
  481.   else if((p = getenv("TMP")) != NULL && (p = strtok(p, " \t")) != NULL)
  482.     {
  483.       strcpy(workdir, p);
  484.       flg_w = 1;
  485.     }
  486.   else if((p = getenv("TEMP")) != NULL && (p = strtok(p, " \t")) != NULL)
  487.     {
  488.       strcpy(workdir, p);
  489.       flg_w = 1;
  490.     }
  491.   if((env = getenv("LHA")) == NULL)
  492.     env = getenv("LHARC");
  493. #ifdef __SUPPORT_UID_GID__
  494. #ifdef __OS2__
  495.   if(p = getenv("UNIX.UID"))
  496.     uid = 0xffff & atoi(p);
  497.   if(p = getenv("UNIX.GID"))
  498.     gid = 0xffff & atoi(p);
  499. #endif
  500. #endif
  501.   if(!isatty(0))
  502.     {
  503.       fileinputflag = 1;
  504.       inredir = fdopen(dup(0), "rt");
  505.       fclose(stdin);
  506.       fopen("con", "rt");    /* open stdin */
  507.     }
  508.   outredir = !isatty(1);
  509.   argc--;
  510.   argv++;
  511.  
  512.   while(1)
  513.     {
  514.       if(env)
  515.     {
  516.       while(*env && (uchar)*env <= ' ')
  517.         env++;
  518.       if(*env == '\0')
  519.         {
  520.           env = NULL;
  521.           continue;
  522.         }
  523.       p = env;
  524.       while(*env > ' ')
  525.         env++;
  526.       if(*env)
  527.         *env++ = '\0';
  528.     }
  529.       else if(response)
  530.     {
  531.       fileinputflag = 1;
  532.       if((p = readword(response)) == NULL)
  533.         {
  534.           response = NULL;
  535.           continue;
  536.         }
  537.     }
  538.       else if(argc)
  539.     {
  540.       argc--;
  541.       p = *argv++;
  542.     }
  543.       else if(inredir == NULL || (p = readword(inredir)) == NULL)
  544.     break;
  545.  
  546.       if(*p == swchar && swchar != '-' || *p == '-' && !flg_at)
  547.     {
  548.       p++;
  549.       getopt(p);
  550.       continue;
  551.     }
  552.       else if(*p == '@' && !flg_at)
  553.     {
  554.       if(!response)
  555.         {
  556.           p++;
  557.           if((response = fopen(p, "rt")) == NULL)
  558.         error(RDERR, p);
  559.           continue;
  560.         }
  561.     }
  562.  
  563.       if(paramcount == -2)
  564.     {
  565.       /* get command */
  566.       cmd = toupper(*p);
  567.       if(p[1] != '\0' || !strchr("EXTDLVAUMFPS", cmd))
  568.         {
  569.           cmd = 'L';
  570.           paramcount++;
  571.         }
  572.       /* command updating archive? */
  573.       cmdupdate = (int)strchr("AUMFD", cmd);
  574.       /* command 'X' = 'E -x1m1' */
  575.       if(cmd == 'X')
  576.         {
  577.           cmd = 'E';
  578.           flg_x = flg_m = 1;
  579.         }
  580.     }
  581.       if(paramcount == -1)
  582.     {
  583.       /* get archive name */
  584.       i = strlen(p);
  585.       strcpy(arcname, p);
  586.     }
  587.       else if(paramcount >= 0)
  588.     {
  589.       convdelim(p, DELIM);
  590.       c = p[strlen(p) - 1];
  591.       if(c == DELIM || c == ':')
  592.         {
  593.           basedir = strcmp(p, "." DELIMSTR) ? regbdir(p) : "";
  594.           continue;
  595.         }
  596.       else
  597.         regpat(p, basedir);
  598.     }
  599.       paramcount++;
  600.     }
  601.   if(paramcount == -2)
  602.     usage();
  603.   if(paramcount == -1)
  604.     error(NOARCNMERR, NULL);
  605.   if(paramcount == 0)
  606.     {
  607.       if(cmd == 'D' || fileinputflag)
  608.     error(NOFNERR, NULL);
  609. #ifndef __SUPPORT_HPFS__
  610.       regpat("+", basedir);    /* We can use '+' for filename on OS/2 HPFS. */
  611. #else
  612.       regpat("\xff", basedir);    /* special case */
  613. #endif
  614.     }
  615.   if(flg_o)
  616.     flg_h = 0;
  617.   if(flg_d)
  618.     {
  619.       flg_r = 2;
  620.       flg_x = 1;
  621.       flg_a = 2;
  622.     }
  623.   else if(flg_x && (flg_r == 2) && (flg_a == 2))
  624.     flg_d = 1;
  625.  
  626.   SetFileSystem(cmdupdate, basedir);
  627.   /* make temporary filenames.  */
  628.   convdelim(workdir, DELIM);
  629.   __ifs__ = GetFileSystem(workdir);
  630.   strcpy(lhtmp2, workdir);
  631.   if(*(lhtmp2 + strlen(lhtmp2) - 1) != DELIM)
  632.     strcat(lhtmp2, DELIMSTR);
  633.   if(__ifs__ == FAT)
  634.     strcat(lhtmp2, "l2XXXXXX");
  635.   else
  636.     strcat(lhtmp2, "lha2.XXXXXX");
  637.  
  638.   convdelim(arcname, DELIM);
  639.   __ifs__ = GetFileSystem(arcname);
  640.   strcpy(lhtmp1, arcname);
  641.   if(lhtmp1[1] != ':')
  642.     strcpy(lhtmp1, workdir);    /* current drive */
  643.   else
  644.     strcat(backpath(lhtmp1), "\0");
  645.   if(*(lhtmp1 + strlen(lhtmp1) - 1) != DELIM)
  646.     strcat(lhtmp1, DELIMSTR);
  647.   if(__ifs__ == FAT)
  648.     strcat(lhtmp1, "l1XXXXXX");
  649.   else
  650.     strcat(lhtmp1, "lha1.XXXXXX");
  651.  
  652.   mktemp(lhtmp1);
  653.   mktemp(lhtmp2);
  654.  
  655.   __ifs__ = GetFileSystem(arcname);
  656.   p = convdelim(arcname, DELIM);
  657.   if ((q = strchr(p, '.')) == NULL)
  658.     strcat(arcname, ".lzh");    /* if no extension */
  659.  
  660.   q = arcname + strlen(arcname) - 4;
  661.   if(stricmp(".lzh", q) && stricmp(".lzs", q) && __ifs__ == HPFS)
  662.     strcat(arcname, ".lzh");    /* if no extension */
  663.   else if(stricmp(".lzh", q) && cmdupdate && __ifs__ == FAT)
  664.     {
  665.       if(flg_m == 0)
  666.     {
  667.       eprintf(NOTLZH, arcname);
  668.       c = getyn();        /* if the extension is not '.lzh' */
  669.       if(c == 'N')
  670.         return(2);
  671.     }
  672.       flg_h = 0;
  673.     }
  674.   execute();
  675.  
  676.   return errorlevel;
  677. }
  678.