home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / setd / mark.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-11  |  14.5 KB  |  688 lines

  1. /*
  2.  *  MARK
  3.  *  Mark Directory
  4.  *  Version 1.7
  5.  *
  6.  *  Sunil William Savkar
  7.  *  sunil@hal.com
  8.  *  Copyright (c) 1991
  9.  *  All Rights Reserved
  10.  *
  11.  *  DISCLOSURE
  12.  *
  13.  *  This source may be modified or copied freely.  The intent
  14.  *  is the free distribution of a useful utility used for moving
  15.  *  between directories.  Any modifications and additions, along
  16.  *  with bug reports should be sent to the author, so all might
  17.  *  benefit!
  18.  *
  19.  *  DESCRIPTION
  20.  * 
  21.  *  Mark directory utility used in conjunction with the
  22.  *  setd command to allow ease of directory changes.
  23.  *
  24.  *  MODIFICATION HISTORY
  25.  *
  26.  *  8/2/91  Sunil William Savkar
  27.  *          Changed code to allow running on HPs.
  28.  *
  29.  *  12/6/92 Sunil William Savkar
  30.  *          Changed code to allow for alphabetical sorting
  31.  *          of the mark file (easier to peruse).
  32.  *
  33.  *  Please send all updates along with suggestions
  34.  *  to sunil@hal.com
  35.  */
  36.  
  37. #if (MACH == hp || MACH == m88k || MACH == rs)
  38. #include <stdlib.h>
  39. #else
  40. #include <alloca.h>
  41. #endif
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45. #include "macros.h"
  46. #include "enum.h"
  47. #include "types.h"
  48.  
  49.  
  50. /*
  51.  *  command[]
  52.  *
  53.  *  This array holds all the strings which are command line arguments
  54.  *  recognized, along with the enumerated type they match with.
  55.  */
  56.  
  57. COMMAND_NODE command[] = {  K_MARK_DIR, "", K_REMOVE_MARK, "-rm", 
  58.                             K_HELP, "-h", K_HELP, "-help", K_VERSION,
  59.                             "-v", K_VERSION, "-ver", K_VERSION, "version",
  60.                             K_RESET_MARKS, "-reset", K_REMOVE_MARK, "-remove",
  61.                             K_LIST_MARKS, "-list", K_REFRESH_MARKS, "-r",
  62.                             K_LIST_MARKS, "-l", 
  63.                             K_REFRESH_MARKS, "-refresh", K_REFRESH_MARKS, "-ref",
  64.                             K_NULL, NULL};
  65.  
  66. /*
  67.  *  version_header[]
  68.  */
  69.  
  70. static char version_header[] =
  71. "Mark Directory\tv1.7\tSunil William Savkar\n";
  72.  
  73. /*
  74.  *  help_header[]
  75.  */
  76.  
  77. static  char    help_header[] =
  78. "Mark Directory\tv1.7\nusage:\tmark <options>\n\n\
  79. option\t\t\tdescription\n\n\
  80. <cr>\n\
  81. -l<ist>\t\t\tLists current marks and their directories\n\
  82. [mark]\t\t\tAliases current directory to alphanumeric mark name\n\
  83. -rm [mark]\n\
  84. -remove [mark]\t\tRemoves specified mark\n\
  85. -v<ersion>\t\tPrints current version of the program\n\
  86. -h<elp>\t\t\tThis help message\n\
  87. -reset\t\t\tClears all marks in the current environment\n\
  88. -r<efresh>\t\tRefreshes all marks in the current environment\n\
  89. \nexamples:\tmark xxx, mark -list, mark -reset, mark -rm xxx\n";
  90.  
  91. /*
  92.  *  boolean read_into_list( char *mark_fil, 
  93.  *                          LIST_NODE **list_head)
  94.  *
  95.  *  This routine opens the passed mark file, holding all the currently
  96.  *  enabled marks, and parses them into the linked list of marks
  97.  *  with their expansions.
  98.  */
  99.  
  100. boolean read_into_list(mark_fil,  /*  The mark file                         */
  101.                        list_head, /*  Pointer to the head of the mark list  */ 
  102.                        list_tail)
  103. char *mark_fil;
  104. LIST_NODE **list_head;
  105. LIST_NODE **list_tail;
  106. {
  107.  
  108.   FILE *mark_fp;                  /*  Pointer to the mark file stream       */
  109.   LIST_NODE *new_ptr;             /*  New list element to add to marks      */
  110.   char setenv[MAX_LINE];          /*  Contains the setenv line in mark file */
  111.   char mark[MAX_LINE];            /*  The mark string which will expand     */
  112.   char path[MAX_LINE];            /*  The expansion of the mark             */
  113.   char buffer[MAX_LINE];          /*  Temporary buffer to hold information  */
  114.  
  115.   /*
  116.    *  Open the mark file.
  117.    */
  118.  
  119.   *list_tail = *list_head;
  120.   if (!(mark_fp = fopen(mark_fil, "r"))) {
  121.  
  122.     fprintf(stderr, "read_into_list:  Unable to open %s\n", mark_fil);
  123.     return FALSE;
  124.   }
  125.  
  126.   /*
  127.    *  Now continue reading the file and setting up the linked list.
  128.    */
  129.  
  130.   while (fgets(buffer, MAX_LINE, mark_fp)) {
  131.  
  132.     /*
  133.      *  Format for the file is : "setenv mark_<mark_name> <mark_expansion>"
  134.      */
  135.  
  136.     sscanf(buffer, "%s mark_%s %s", setenv, mark, path);
  137.  
  138.     if (STREQU(setenv, "unsetenv")) continue;
  139.     if (!STREQU(setenv, "setenv")) {
  140.  
  141.       fprintf(stderr, "read_into_list:  Error in mark database\n");
  142.       return FALSE;
  143.     }
  144.  
  145.     /*
  146.      *  Set up a new node.
  147.      */
  148.  
  149.     if (!(new_ptr = (LIST_NODE *)malloc(sizeof(LIST_NODE)))) {
  150.  
  151.       fprintf( stderr, "read_into_list: error mallocing new structure\n");
  152.       return FALSE;
  153.     }
  154.  
  155.     new_ptr->unset_flag = FALSE;
  156.     if (!(new_ptr->mark = (char *)malloc(strlen(mark) + 1))) {
  157.  
  158.       fprintf( stderr, "read_into_list: error mallocing new mark string\n");
  159.       return FALSE;
  160.     } else if (!(new_ptr->path = (char *)malloc(strlen(path) + 1))) {
  161.  
  162.       fprintf( stderr, "read_into_list: error mallocing new expand string\n");
  163.       return FALSE;
  164.     }
  165.     new_ptr->next = NULL;
  166.     strcpy(new_ptr->mark, mark); strcpy(new_ptr->path, path);
  167.  
  168.     /*
  169.      *  Insert the new mark into the list.
  170.      */
  171.  
  172.     if (*list_head == NULL) {
  173.  
  174.       *list_head = *list_tail = new_ptr;
  175.     } else {
  176.  
  177.       (*list_tail)->next = new_ptr;
  178.       *list_tail = new_ptr;
  179.     }
  180.   }
  181.  
  182.   /*
  183.    *  Done with generating the linked list of current marks.
  184.    */
  185.  
  186.   fclose(mark_fp);
  187.   return TRUE;
  188. }
  189.  
  190. /*
  191.  *  boolean initialize( char **pwd,
  192.  *                      char *mark_fil,
  193.  *                      LIST_NODE **list_head,
  194.  *                      LIST_NODE **list_tail)
  195.  *
  196.  *  This routine is called to initialize the variables and list
  197.  *  of marks currently set.
  198.  */
  199.  
  200. boolean initialize( pwd, 
  201.                     mark_fil, 
  202.                     list_head,
  203.                     list_tail)
  204. LIST_NODE **list_tail;
  205. LIST_NODE **list_head;
  206. char *mark_fil;
  207. char **pwd;
  208. {
  209.  
  210.   FILE *mark_fp;
  211.   char *getenv();
  212.   char *ptr;
  213.  
  214.   /*
  215.    *  Get current directory and pointer to the mark directory.
  216.    */
  217.  
  218. #ifdef HP
  219.  
  220.   if (!(getcwd((*pwd = (char *)malloc(MAX_LINE)), MAX_LINE))) {
  221. #else
  222.  
  223.   if (!(*pwd = getenv("PWD"))) {
  224. #endif
  225.  
  226.     fprintf(stderr, "initialize:  Unable to get environment var $PWD\n");
  227.     return FALSE;
  228.   }
  229.  
  230.   /*
  231.    *  Notice we would like to strip off the /tmp_mount from the *pwd,
  232.    *  if it exists!
  233.    */
  234.  
  235.   if (strncmp(*pwd, "/tmp_mnt", 8) == 0) {
  236.     *pwd += 8;
  237.   }
  238.  
  239.   if (!(ptr = getenv("MARK_DIR"))) {
  240.  
  241.     fprintf(stderr, "initialize:  Must set environment var $MARK_DIR\n");
  242.     return FALSE;
  243.   } else {
  244.  
  245.     /*
  246.      *  Construct mark data base file pointer.
  247.      */
  248.  
  249.     sprintf( mark_fil, "%s/mark_db", ptr);
  250.   }
  251.  
  252.   if (!(mark_fp = fopen(mark_fil, "a"))) {
  253.  
  254.     fprintf(stderr, "initialize:  Unable to open %s\n", mark_fil);
  255.     return FALSE;
  256.   }
  257.  
  258.   fclose(mark_fp);
  259.  
  260.   /*
  261.    *  Read marks into a linked list, with the mark string,
  262.    *  and the path string.
  263.    */
  264.  
  265.   if (!read_into_list(mark_fil, list_head, list_tail)) {
  266.  
  267.     fprintf(stderr, "initialize:  Unable to read mark file %s\n", mark_fil);
  268.     return FALSE;
  269.   }
  270.  
  271.   return TRUE;
  272. }  
  273.  
  274. /*
  275.  *  T_COMM parse( char *option)
  276.  *
  277.  *  This routine returns the enumeration for the given string which
  278.  *  represents an option on the command line.  Options can be anything
  279.  *  from -help for help, to the mark to be set.
  280.  */
  281.  
  282. T_COMM parse( option)  /*  The string representing the option requested     */
  283. char *option;
  284. {
  285.  
  286.   int j;
  287.   char *ptr;
  288.  
  289.   /*
  290.    *  No dash indicates no real option, but just a directory to mark.
  291.    */
  292.  
  293.   if (*option != '-') {
  294.  
  295.     return K_MARK_DIR;
  296.   }
  297.  
  298.   /*
  299.    *  Must be one of the commands, else there is
  300.    *  an error.
  301.    */
  302.  
  303.   for (j = 0; ptr = command[j].text; j++) {
  304.  
  305.     if (STREQU(ptr, option)) break;
  306.   }
  307.  
  308.   if (!ptr) {
  309.  
  310.     fprintf(stderr, "parse: unrecognized option from main (%s)\n", option);
  311.     return K_NULL;
  312.   }
  313.  
  314.   return command[j].type;
  315. }
  316.  
  317. boolean list_marks( list_ptr)
  318. LIST_NODE *list_ptr;
  319. {
  320.  
  321.   
  322.   /*
  323.    *  Each line consists of the mark, and then the pathname.
  324.    */
  325.  
  326.   fprintf(stdout, "MARK\t\tPATH\n----\t\t----\n");
  327.   for (; list_ptr; list_ptr = list_ptr->next) {
  328.  
  329.     fprintf(stdout, "%s\t\t%s\n", list_ptr->mark, list_ptr->path);
  330.   }
  331.  
  332.   return TRUE;
  333. }
  334.  
  335. /*
  336.  *  boolean mark_dir( char *pwd,
  337.  *                    char *mark,
  338.  *                    LIST_NODE **list_head,
  339.  *                    LIST_NODE **list_tail)
  340.  *
  341.  *  This routine adds a new mark with expansion to the given list.
  342.  */
  343.  
  344. boolean mark_dir(pwd, 
  345.                  mark, 
  346.                  list_head,
  347.                  list_tail)
  348. LIST_NODE **list_head,
  349.           **list_tail;
  350. char *pwd;
  351. char *mark;
  352. {
  353.  
  354.   char *ptr;
  355.   LIST_NODE *new_ptr, *list_ptr;
  356.  
  357.   /*
  358.    *  A mark must be alphanumeric.
  359.    */
  360.  
  361.   for (ptr = mark; *ptr != '\0'; ptr++) {
  362.  
  363.     if (!(isalnum(*ptr) || (*ptr == '_'))) {
  364.  
  365.       fprintf(stderr, "mark_dir: mark must be alphanumeric\n");
  366.       return FALSE;
  367.     }
  368.   }
  369.  
  370.   /*
  371.    *  If there is an old mark by the same name, just change the
  372.    *  path for that mark.
  373.    */
  374.  
  375.   for (list_ptr = *list_head; list_ptr; list_ptr = list_ptr->next) {
  376.  
  377.     if (STREQU(mark, list_ptr->mark)) break;
  378.   }
  379.  
  380.   if (list_ptr) {
  381.  
  382.     free(list_ptr->path);
  383.     list_ptr->path = pwd;
  384.   } else if (!(new_ptr = (LIST_NODE *)malloc(sizeof(LIST_NODE)))) {
  385.  
  386.     fprintf(stderr, "mark_dir: error allocating space in list\n");
  387.     return FALSE;
  388.   } else {
  389.  
  390.     new_ptr->unset_flag = FALSE;
  391.     new_ptr->next = NULL;
  392.     new_ptr->mark = mark;
  393.     new_ptr->path = pwd;
  394.  
  395.     if (*list_head == NULL) {
  396.  
  397.       *list_head = *list_tail = new_ptr;
  398.     } else {
  399.  
  400.       (*list_tail)->next = new_ptr;
  401.       *list_tail = new_ptr;
  402.     }
  403.   }
  404.  
  405.   fprintf(stderr, "mark_dir: mark \"%s\" (%s) set\n", mark, pwd);
  406.   return TRUE;
  407. }
  408.  
  409. /*
  410.  *  boolean remove_mark( char *mark,
  411.  *                       LIST_NODE *list_ptr)
  412.  *
  413.  *  This routine is used to remove a mark from the given list (through
  414.  *  including an unsetenv declarator in the mark file.
  415.  */
  416.  
  417. boolean remove_mark(mark, 
  418.                     list_ptr)
  419. char *mark;
  420. LIST_NODE *list_ptr;
  421. {
  422.  
  423.   for (; list_ptr; list_ptr = list_ptr->next) {
  424.  
  425.     if (STREQU(list_ptr->mark, mark)) {
  426.  
  427.       list_ptr->unset_flag = TRUE;
  428.       fprintf( stderr, "mark_dir: mark \"%s\" (%s) removed\n", mark, 
  429.                list_ptr->path);
  430.       return TRUE;
  431.     }
  432.   }
  433.  
  434.   fprintf(stderr, "mark_dir: mark \"%s\" not found\n", mark);
  435.   return FALSE;
  436. }
  437.  
  438. /*
  439.  *  boolean reset_marks( LIST_NODE *list_ptr)
  440.  *
  441.  *  This routine resets the marks by unsetenv all of them.
  442.  */
  443.  
  444. boolean reset_marks( list_ptr)
  445. LIST_NODE *list_ptr;
  446. {
  447.  
  448.   /*
  449.    *  Go through all the marks and set their unset_flag.
  450.    */
  451.  
  452.   for (; list_ptr; list_ptr = list_ptr->next) list_ptr->unset_flag = TRUE;
  453.  
  454.   return TRUE;
  455. }
  456.  
  457. /*
  458.  *  boolean sort_list( list_head)
  459.  *
  460.  *  This routine simply pops off the old list and rearranges into a sorted
  461.  *  order.  This simple routine is written instead of using the system
  462.  *  sort command.
  463.  */
  464.  
  465. void sort_list( list_head)
  466. LIST_NODE **list_head;
  467. {
  468.  
  469.   LIST_NODE *sort_head, 
  470.             *sort_tail,
  471.             *list_ptr, 
  472.             *old_ptr, 
  473.             *sort_ptr;
  474.  
  475.   sort_head = old_ptr = NULL;
  476.  
  477.   /*
  478.    *  Pop off the old list and rearrange in the new sort list.
  479.    */
  480.  
  481.   while (*list_head) {
  482.  
  483.     list_ptr = *list_head;
  484.     *list_head = (*list_head)->next;
  485.     list_ptr->next = NULL;
  486.  
  487.     /*
  488.      *  No sorted list exists.
  489.      */
  490.  
  491.     if (!sort_head) {
  492.  
  493.       sort_head = sort_tail = list_ptr;
  494.       continue;
  495.     } else {
  496.  
  497.       /*
  498.        *  Check for mark precedence over current list head.
  499.        */
  500.  
  501.       if (strcmp( list_ptr->mark, sort_head->mark) < 0) {
  502.  
  503.         list_ptr->next = sort_head;
  504.         sort_head = list_ptr;
  505.  
  506.       /* 
  507.        *  Check for mark being of lesser precedence than the tail.
  508.        */
  509.  
  510.       } else if (strcmp( list_ptr->mark, sort_tail->mark) > 0) {
  511.  
  512.         sort_tail->next = list_ptr;
  513.         sort_tail = list_ptr;
  514.       } else {
  515.  
  516.         /*
  517.          *  Insert the mark somewhere within the list alphabetically.
  518.          */
  519.  
  520.         for (sort_ptr = sort_head; sort_ptr; old_ptr = sort_ptr, sort_ptr = sort_ptr->next) {
  521.  
  522.           if (strcmp( list_ptr->mark, sort_ptr->mark) < 0) {
  523.  
  524.             old_ptr->next = list_ptr;
  525.             list_ptr->next = sort_ptr;
  526.             break;
  527.       }
  528.     }
  529.       }
  530.     }
  531.   }
  532.  
  533.   /*
  534.    *  Set the new list head.
  535.    */
  536.  
  537.   *list_head = sort_head;
  538. }
  539.  
  540. boolean update_file( mark_fil, list_ptr)
  541. char *mark_fil;
  542. LIST_NODE *list_ptr;
  543. {
  544.  
  545.   FILE *mark_fp;
  546.  
  547.   /*
  548.    *  Write the new list of marks to the update file.
  549.    */
  550.  
  551.   if (!(mark_fp = fopen(mark_fil, "w"))) {
  552.  
  553.     fprintf(stderr, "update_file: Unable to update %s\n", mark_fil);
  554.     return FALSE;
  555.   }
  556.  
  557.   for (; list_ptr; list_ptr = list_ptr->next) {
  558.  
  559.     if (!list_ptr->unset_flag) {
  560.  
  561.       fprintf(mark_fp, "setenv mark_%s %s\n", list_ptr->mark, list_ptr->path);
  562.     } else {
  563.  
  564.       fprintf(mark_fp, "unsetenv mark_%s\n", list_ptr->mark);
  565.     }
  566.   }
  567.  
  568.   fclose(mark_fp);
  569.   return TRUE;
  570. }
  571.  
  572. /*
  573.  *  main( int argc,
  574.  *        char *argv[])
  575.  *
  576.  *  The main event.
  577.  */
  578.  
  579. main(argc, 
  580.      argv)
  581. char *argv[];
  582. int argc;
  583. {
  584.  
  585.   LIST_NODE *list_head,
  586.             *list_tail;
  587.   int i;
  588.   char mark_fil[MAX_LINE];
  589.   char *pwd;
  590.   T_COMM option;
  591.   
  592.   list_head = list_tail = NULL;
  593.  
  594.   /*
  595.    *  First we must initialize, getting pointer to the
  596.    *  mark file, and read in the current directory.
  597.    */
  598.  
  599.   if (!initialize(&pwd, mark_fil, &list_head, &list_tail)) {
  600.  
  601.     fprintf(stderr, "mark: error code from initialize\n");
  602.     exit(-1);
  603.   }
  604.  
  605.   /*
  606.    *  Now we have the file pointer for mark, and the current
  607.    *  directory.  It is time to start parsing the arguments
  608.    *  on the command line.
  609.    */
  610.  
  611.   for (i = 1; i <= argc; i++) {
  612.  
  613.     if (argc == 1) {
  614.  
  615.       option = K_LIST_MARKS;
  616.     } else if (i == argc) {
  617.  
  618.        break;
  619.     } else if ((option = parse( argv[i])) == K_NULL) {
  620.  
  621.  
  622.       fprintf(stderr, "mark: error code from parse\n");
  623.       exit(-1);
  624.     }
  625.  
  626.     /*
  627.      *  Switch, based upon the given option, to the
  628.      *  proper function.
  629.      */
  630.  
  631.     switch (option) {
  632.  
  633.     case K_MARK_DIR:
  634.  
  635.       if (!mark_dir(pwd, argv[i], &list_head, &list_tail)) {
  636.  
  637.         fprintf(stderr, "mark: error code from mark_dir\n");
  638.         exit(-1);
  639.       }
  640.       break;
  641.  
  642.     case K_REMOVE_MARK: 
  643.       if (!remove_mark(argv[++i], list_head)) {
  644.  
  645.         fprintf(stderr, "mark: error code from remove_mark\n");
  646.         exit(-1); 
  647.       }
  648.       break;
  649.  
  650.     case K_LIST_MARKS: 
  651.       if (!list_marks(list_head)) {
  652.  
  653.         fprintf(stderr, "mark:  error code from list_marks\n");
  654.         exit(-1);
  655.       }
  656.       break;
  657.  
  658.     case K_VERSION:
  659.       fprintf(stdout, version_header);
  660.       break;
  661.  
  662.     case K_HELP:
  663.       fprintf(stdout, help_header);
  664.       break;
  665.  
  666.     case K_RESET_MARKS: 
  667.       if (!reset_marks(list_head)) {
  668.  
  669.         fprintf(stderr, "mark: error code from reset_marks\n");
  670.         exit(-1);
  671.       }
  672.       break;
  673.  
  674.     case K_REFRESH_MARKS: break;
  675.     default: break;
  676.     }
  677.   }
  678.  
  679.   if (option == K_MARK_DIR) sort_list( &list_head);
  680.   if (!update_file(mark_fil, list_head)) {
  681.  
  682.     fprintf(stderr, "mark: error code from update_file\n");
  683.     exit(-1);
  684.   }
  685.  
  686.   exit(0);
  687. }
  688.