Advertisement
Guest User

Untitled

a guest
May 19th, 2017
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.60 KB | None | 0 0
  1. // database.c
  2.  
  3. #include "database.h"
  4.  
  5.  
  6.  
  7. // ============================================================================
  8.  
  9. struct Database* createDatabase()
  10.  
  11. {
  12.  
  13. Database* database = (Database*)malloc(sizeof(Database));
  14.  
  15.  
  16.  
  17. if(database == NULL) {
  18.  
  19. fprintf(stderr, "allocation failed");
  20.  
  21. return NULL;
  22.  
  23. } else {
  24.  
  25.  
  26.  
  27. database->firstEntry = NULL;
  28.  
  29. database->lastEntry = NULL;
  30.  
  31.  
  32.  
  33. return database;
  34.  
  35. }
  36.  
  37. }
  38.  
  39. // ============================================================================
  40.  
  41. void freeDatabase(struct Database* database)
  42.  
  43. {
  44.  
  45.  
  46.  
  47. Entry *entry = database->firstEntry;
  48.  
  49.  
  50.  
  51. while(entry != NULL) {
  52.  
  53.  
  54.  
  55. Entry *tmpEntry = entry;
  56.  
  57. entry = entry->next;
  58.  
  59.  
  60.  
  61. freeEntry(tmpEntry);
  62.  
  63.  
  64.  
  65. }
  66.  
  67.  
  68.  
  69. free(database);
  70.  
  71.  
  72.  
  73. }
  74.  
  75. // ============================================================================
  76.  
  77. void freeEntry(struct Entry* entry) {
  78.  
  79. free(entry->username);
  80.  
  81. free(entry->passwd);
  82.  
  83. free(entry->comment);
  84.  
  85. free(entry->home);
  86.  
  87. free(entry->shell);
  88.  
  89. free(entry);
  90.  
  91. }
  92.  
  93. // ============================================================================
  94.  
  95. int insertEntry(struct Database *database, struct Entry* newEntry, char* username)
  96.  
  97. {
  98.  
  99. if(database == NULL || newEntry == NULL || username == NULL) {
  100.  
  101. return ERROR_WRONG_ARGUMENTS;
  102.  
  103. }
  104.  
  105.  
  106.  
  107. newEntry->next = NULL;
  108.  
  109.  
  110.  
  111. if(database->firstEntry == NULL) {
  112.  
  113. database->firstEntry = newEntry;
  114.  
  115. } else {
  116.  
  117.  
  118.  
  119. Entry* link = database->firstEntry;
  120.  
  121.  
  122.  
  123. while(link->next != NULL) {
  124.  
  125.  
  126.  
  127. if(link->uid == newEntry->uid) {
  128.  
  129. return ERROR_DUPLICATE_ENTRY;
  130.  
  131. }
  132.  
  133.  
  134.  
  135. link = link->next;
  136.  
  137. }
  138.  
  139.  
  140.  
  141. // if uid of first argument == uid of second argument
  142.  
  143. if(link->uid == newEntry->uid) {
  144.  
  145. return ERROR_DUPLICATE_ENTRY;
  146.  
  147. }
  148.  
  149.  
  150.  
  151. link->next = newEntry;
  152.  
  153.  
  154.  
  155.  
  156.  
  157. }
  158.  
  159.  
  160.  
  161. strcpy(username, newEntry->username);
  162.  
  163. return NO_ERROR;
  164.  
  165. }
  166.  
  167. // ============================================================================
  168.  
  169. int removeEntry(struct Database* database, int id, char* username) {
  170.  
  171.  
  172.  
  173.  
  174.  
  175. if(id < 1 || id > countEntries(database)) {
  176.  
  177. return ERROR_ID_NOT_IN_INTERVAL;
  178.  
  179. }
  180.  
  181.  
  182.  
  183. if(database == NULL || username == NULL) {
  184.  
  185. return ERROR_WRONG_ARGUMENTS;
  186.  
  187. }
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195. Entry *entry = database->firstEntry;
  196.  
  197.  
  198.  
  199. int i = 1;
  200.  
  201.  
  202.  
  203. if(id == 1) {
  204.  
  205. Entry* tmpEntry = entry->next;
  206.  
  207. strcpy(username, entry->username);
  208.  
  209. freeEntry(entry);
  210.  
  211. database->firstEntry = tmpEntry;
  212.  
  213. return NO_ERROR;
  214.  
  215. } else {
  216.  
  217.  
  218.  
  219. while(entry != NULL) {
  220.  
  221.  
  222.  
  223. if(i+1 == id) {
  224.  
  225. Entry* tmpEntry = entry->next->next;
  226.  
  227. strcpy(username, entry->next->username);
  228.  
  229. freeEntry(entry->next);
  230.  
  231. entry->next = tmpEntry;
  232.  
  233. return NO_ERROR;
  234.  
  235. }
  236.  
  237.  
  238.  
  239. i++;
  240.  
  241. entry = entry->next;
  242.  
  243. }
  244.  
  245.  
  246.  
  247.  
  248.  
  249. }
  250.  
  251.  
  252.  
  253. return ERROR_ID_NOT_IN_INTERVAL;
  254.  
  255.  
  256.  
  257.  
  258.  
  259. }
  260.  
  261. // ============================================================================
  262.  
  263. struct Entry* loadEntry(char* line) {
  264.  
  265.  
  266.  
  267. if(line == NULL) {
  268.  
  269. return NULL;
  270.  
  271. }
  272.  
  273.  
  274.  
  275. Entry* entry = (Entry*)malloc(sizeof(Entry));
  276.  
  277. if(entry == NULL) {
  278.  
  279. fprintf(stderr, "allocation failed");
  280.  
  281. return NULL;
  282.  
  283. }
  284.  
  285.  
  286.  
  287. char* tmp = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  288.  
  289. if(tmp == NULL) {
  290.  
  291. fprintf(stderr, "allocation failed");
  292.  
  293. free(entry);
  294.  
  295. return NULL;
  296.  
  297. }
  298.  
  299.  
  300.  
  301.  
  302.  
  303. entry->username = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  304.  
  305. memset(entry->username,0,sizeof(char)*(MAX_FIELD_LENGTH+1));
  306.  
  307. entry->passwd= (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  308.  
  309. memset(entry->passwd,0,sizeof(char)*(MAX_FIELD_LENGTH+1));
  310.  
  311. entry->uid = 0;
  312.  
  313. entry->gid = 0;
  314.  
  315. entry->comment= (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  316.  
  317. memset(entry->comment,0,sizeof(char)*(MAX_FIELD_LENGTH+1));
  318.  
  319. entry->home = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  320.  
  321. memset(entry->home,0,sizeof(char)*(MAX_FIELD_LENGTH+1));
  322.  
  323. entry->shell = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  324.  
  325. memset(entry->shell,0,sizeof(char)*(MAX_FIELD_LENGTH+1));
  326.  
  327.  
  328.  
  329. strncpy(entry->username, line, strlen(line) - strlen(strchr(line, ':')));
  330.  
  331. entry->username[strlen(line) - strlen(strchr(line, ':'))] = '\0';
  332.  
  333. if(strlen(entry->username) == 0){
  334.  
  335. freeEntry(entry);
  336.  
  337. free(tmp);
  338.  
  339. return NULL;
  340.  
  341. }
  342.  
  343. line = strchr(line, ':')+1;
  344.  
  345.  
  346.  
  347. strncpy(entry->passwd, line, strlen(line) - strlen(strchr(line, ':')));
  348.  
  349. entry->passwd[strlen(line) - strlen(strchr(line, ':'))] = '\0';
  350.  
  351. line = strchr(line, ':')+1;
  352.  
  353.  
  354.  
  355. strncpy(tmp, line, strlen(line) - strlen(strchr(line, ':')));
  356.  
  357. tmp[strlen(line) - strlen(strchr(line, ':'))] = '\0';
  358.  
  359. line = strchr(line, ':')+1;
  360.  
  361. if(atoi(tmp) == 0) {
  362.  
  363. freeEntry(entry);
  364.  
  365. free(tmp);
  366.  
  367. return NULL;
  368.  
  369. }
  370.  
  371. entry->uid = atoi(tmp);
  372.  
  373.  
  374.  
  375. strncpy(tmp, line, strlen(line) - strlen(strchr(line, ':')));
  376.  
  377. tmp[strlen(line) - strlen(strchr(line, ':'))] = '\0';
  378.  
  379. line = strchr(line, ':')+1;
  380.  
  381. entry->gid = atoi(tmp);
  382.  
  383.  
  384.  
  385. strncpy(entry->comment, line, strlen(line) - strlen(strchr(line, ':')));
  386.  
  387. entry->comment[strlen(line) - strlen(strchr(line, ':'))] = '\0';
  388.  
  389. line = strchr(line, ':')+1;
  390.  
  391.  
  392.  
  393. strncpy(entry->home, line, strlen(line) - strlen(strchr(line, ':')));
  394.  
  395. entry->home[strlen(line) - strlen(strchr(line, ':'))] = '\0';
  396.  
  397. line = strchr(line, ':')+1;
  398.  
  399.  
  400.  
  401. strcpy(entry->shell, line);
  402.  
  403. // trim whitespaces from end of the entry->shell
  404.  
  405. char *end;
  406.  
  407. end = entry->shell + strlen(entry->shell) - 1;
  408.  
  409. while(end > entry->shell && isspace(*end)) end--;
  410.  
  411.  
  412.  
  413. *(end+1) = '\0';
  414.  
  415.  
  416.  
  417. free(tmp);
  418.  
  419.  
  420.  
  421. return entry;
  422.  
  423. }
  424.  
  425.  
  426.  
  427. // ============================================================================
  428.  
  429. struct Entry* fillEntry() {
  430.  
  431.  
  432.  
  433. char *tmpString = (char*)malloc(sizeof(char)*MAX_FIELD_LENGTH);
  434.  
  435.  
  436.  
  437. if(tmpString == NULL) {
  438.  
  439. fprintf(stderr, "allocation failed");
  440.  
  441. return NULL;
  442.  
  443. }
  444.  
  445.  
  446.  
  447. while (getchar() != '\n') {;}
  448.  
  449.  
  450.  
  451. Entry *entry = (Entry*)malloc(sizeof(Entry));
  452.  
  453.  
  454.  
  455. entry->username = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  456.  
  457. memset(entry->username,0,sizeof(char)*MAX_FIELD_LENGTH);
  458.  
  459.  
  460.  
  461. entry->passwd = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  462.  
  463. memset(entry->passwd,0,sizeof(char)*MAX_FIELD_LENGTH);
  464.  
  465.  
  466.  
  467. entry->comment = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  468.  
  469. memset(entry->comment,0,sizeof(char)*MAX_FIELD_LENGTH);
  470.  
  471.  
  472.  
  473. entry->home = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  474.  
  475. memset(entry->home,0,sizeof(char)*MAX_FIELD_LENGTH);
  476.  
  477.  
  478.  
  479. entry->shell = (char*)malloc(sizeof(char)*(MAX_FIELD_LENGTH+1));
  480.  
  481. memset(entry->shell,0,sizeof(char)*MAX_FIELD_LENGTH);
  482.  
  483.  
  484.  
  485. memset(tmpString,0,sizeof(char)*MAX_FIELD_LENGTH);
  486.  
  487.  
  488.  
  489.  
  490.  
  491. printf("username: ");
  492.  
  493. fgets(tmpString,MAX_FIELD_LENGTH+1,stdin);
  494.  
  495. if(strlen(tmpString) == 0){
  496.  
  497. free(tmpString);
  498.  
  499. freeEntry(entry);
  500.  
  501. return NULL;
  502.  
  503. }
  504.  
  505. strncpy(entry->username, tmpString, strlen(tmpString)-1);
  506.  
  507.  
  508.  
  509. memset(tmpString,0,sizeof(char)*MAX_FIELD_LENGTH);
  510.  
  511.  
  512.  
  513. printf("password: ");
  514.  
  515. fgets(tmpString,MAX_FIELD_LENGTH+1,stdin);
  516.  
  517. strncpy(entry->passwd, tmpString, strlen(tmpString)-1);
  518.  
  519.  
  520.  
  521. memset(tmpString,0,sizeof(char)*MAX_FIELD_LENGTH);
  522.  
  523.  
  524.  
  525. printf("UID: ");
  526.  
  527. fgets(tmpString,MAX_FIELD_LENGTH+1,stdin);
  528.  
  529. if(atoi(tmpString) == 0) {
  530.  
  531. free(tmpString);
  532.  
  533. freeEntry(entry);
  534.  
  535. return NULL;
  536.  
  537. }
  538.  
  539. entry->uid = atoi(tmpString);
  540.  
  541.  
  542.  
  543. memset(tmpString,0,sizeof(char)*MAX_FIELD_LENGTH);
  544.  
  545.  
  546.  
  547. printf("GID: ");
  548.  
  549. fgets(tmpString,MAX_FIELD_LENGTH+1,stdin);
  550.  
  551. entry->gid = atoi(tmpString);
  552.  
  553.  
  554.  
  555. memset(tmpString,0,sizeof(char)*MAX_FIELD_LENGTH);
  556.  
  557.  
  558.  
  559. printf("comment: ");
  560.  
  561. fgets(tmpString,MAX_FIELD_LENGTH+1,stdin);
  562.  
  563. strncpy(entry->comment, tmpString, strlen(tmpString)-1);
  564.  
  565.  
  566.  
  567. memset(tmpString,0,sizeof(char)*MAX_FIELD_LENGTH);
  568.  
  569.  
  570.  
  571. printf("home: ");
  572.  
  573. fgets(tmpString,MAX_FIELD_LENGTH+1,stdin);
  574.  
  575. strncpy(entry->home, tmpString, strlen(tmpString)-1);
  576.  
  577.  
  578.  
  579. memset(tmpString,0,sizeof(char)*MAX_FIELD_LENGTH);
  580.  
  581.  
  582.  
  583. printf("shell: ");
  584.  
  585. fgets(tmpString,MAX_FIELD_LENGTH+1,stdin);
  586.  
  587. strncpy(entry->shell, tmpString, strlen(tmpString)-1);
  588.  
  589.  
  590.  
  591. // trim whitespaces from end of the entry->shell
  592.  
  593. char *end;
  594.  
  595. end = entry->shell + strlen(entry->shell) - 1;
  596.  
  597. while(end > entry->shell && isspace(*end)) end--;
  598.  
  599.  
  600.  
  601. *(end+1) = '\0';
  602.  
  603.  
  604.  
  605.  
  606.  
  607. free(tmpString);
  608.  
  609.  
  610.  
  611. return entry;
  612.  
  613. }
  614.  
  615. // ============================================================================
  616.  
  617. int changePassword(struct Database* database, int entryID, char* newPassword) {
  618.  
  619.  
  620.  
  621. if(entryID < 1 || entryID > countEntries(database)) {
  622.  
  623. return ERROR_ID_NOT_IN_INTERVAL;
  624.  
  625. }
  626.  
  627.  
  628.  
  629. if(database == NULL || newPassword == NULL) {
  630.  
  631. return ERROR_WRONG_ARGUMENTS;
  632.  
  633. }
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641. Entry *entry = database->firstEntry;
  642.  
  643.  
  644.  
  645. int i = 1;
  646.  
  647.  
  648.  
  649. while(entry != NULL) {
  650.  
  651.  
  652.  
  653. if(i == entryID) {
  654.  
  655. memset(entry->passwd,0,sizeof(char)*(MAX_FIELD_LENGTH+1));
  656.  
  657. strcpy(entry->passwd, newPassword);
  658.  
  659. }
  660.  
  661.  
  662.  
  663. i++;
  664.  
  665. entry = entry->next;
  666.  
  667. }
  668.  
  669.  
  670.  
  671. return NO_ERROR;
  672.  
  673. }
  674.  
  675. // ============================================================================
  676.  
  677. void printDatabase(struct Database* database) {
  678.  
  679.  
  680.  
  681. if(database == NULL) {
  682.  
  683. fprintf(stderr, "no database connection");
  684.  
  685. }else{
  686.  
  687.  
  688.  
  689. if(database->firstEntry == NULL) {
  690.  
  691. puts("No entries found");
  692.  
  693. } else {
  694.  
  695.  
  696.  
  697. Entry* entry = database->firstEntry;
  698.  
  699. unsigned int i = 1;
  700.  
  701. while(entry != NULL) {
  702.  
  703.  
  704.  
  705. printf("%d\t%s\t%s\t%u\t%u\t%s\t%s\t%s\r\n", i++, entry->username, entry->passwd,
  706.  
  707. entry->uid, entry->gid, entry->comment, entry->home, entry->shell);
  708.  
  709.  
  710.  
  711. entry = entry->next;
  712.  
  713. }
  714.  
  715.  
  716.  
  717. }
  718.  
  719.  
  720.  
  721. }
  722.  
  723.  
  724.  
  725. }
  726.  
  727. // ============================================================================
  728.  
  729. int sortDatabase(struct Database* database, int desc)
  730.  
  731. {
  732.  
  733. // TODO: implement
  734.  
  735.  
  736.  
  737. return NO_ERROR;
  738.  
  739. }
  740.  
  741. // ============================================================================
  742.  
  743. void swapEntries(struct Entry *a, struct Entry *b)
  744.  
  745. {
  746.  
  747. // TODO: implement
  748.  
  749. }
  750.  
  751. // ===========================================================================
  752.  
  753. int saveDatabase(const char* filename, const struct Database* database) {
  754.  
  755. // check input arguments
  756.  
  757. if(database == NULL || filename == NULL)
  758.  
  759. return ERROR_WRONG_ARGUMENTS;
  760.  
  761.  
  762.  
  763. FILE* file;
  764.  
  765. struct Entry* entry;
  766.  
  767.  
  768.  
  769. // try to open file
  770.  
  771. if(!(file = fopen(filename, "w")))
  772.  
  773. return ERROR_OPENING_FILE;
  774.  
  775.  
  776.  
  777. entry = database->firstEntry;
  778.  
  779.  
  780.  
  781. // go through all the entries and write to the standard output
  782.  
  783. while(entry != NULL) {
  784.  
  785. fprintf(file, "%s:%s:%u:%u:%s:%s:%s\n", entry->username, entry->passwd,
  786.  
  787. entry->uid, entry->gid, entry->comment, entry->home, entry->shell);
  788.  
  789.  
  790.  
  791. entry = entry->next;
  792.  
  793. }
  794.  
  795.  
  796.  
  797. // close access to file stream
  798.  
  799. fflush(file);
  800.  
  801. fclose(file);
  802.  
  803.  
  804.  
  805. return NO_ERROR;
  806.  
  807. }
  808.  
  809. // ============================================================================
  810.  
  811. int countEntries(struct Database* database) {
  812.  
  813. Entry* entry = database->firstEntry;
  814.  
  815. int counter = 0;
  816.  
  817.  
  818.  
  819. while(entry != NULL) {
  820.  
  821. counter++;
  822.  
  823. entry = entry->next;
  824.  
  825. }
  826.  
  827.  
  828.  
  829. return counter;
  830.  
  831. }
  832.  
  833. // ============================================================================
  834.  
  835. int loadDatabase(struct Database** db, char* filename, int silence) {
  836.  
  837. // check name
  838.  
  839. if(!filename) {
  840.  
  841. fprintf(stderr, "wrong filename!\n");
  842.  
  843.  
  844.  
  845. return ERROR_WRONG_ARGUMENTS;
  846.  
  847. }
  848.  
  849.  
  850.  
  851. // try to open file
  852.  
  853. FILE* inputF = fopen(filename, "rb");
  854.  
  855.  
  856.  
  857. // check opening correctness
  858.  
  859. if(inputF == NULL) {
  860.  
  861. fprintf(stderr, "error during opening filename '%s'!\n", filename);
  862.  
  863.  
  864.  
  865. return ERROR_OPENING_FILE;
  866.  
  867. }
  868.  
  869.  
  870.  
  871. char line[MAX_LINE_LENGTH]; // line buffer
  872.  
  873. memset(line, 0, MAX_LINE_LENGTH); // clear buffer
  874.  
  875.  
  876.  
  877. // create empty database
  878.  
  879. if(*db == NULL)
  880.  
  881. *db = createDatabase();
  882.  
  883.  
  884.  
  885. if(*db == NULL)
  886.  
  887. return ERROR_ALLOCATION;
  888.  
  889.  
  890.  
  891. // temporary space for username
  892.  
  893. char* username = (char*)malloc(sizeof(char)*MAX_FIELD_LENGTH);
  894.  
  895.  
  896.  
  897. if(username == NULL)
  898.  
  899. return ERROR_ALLOCATION;
  900.  
  901.  
  902.  
  903. // read all lines till the end of the file
  904.  
  905. while(fgets(line, MAX_LINE_LENGTH, inputF) != NULL) {
  906.  
  907.  
  908.  
  909. memset(username, 0, MAX_FIELD_LENGTH);
  910.  
  911.  
  912.  
  913. // load entry
  914.  
  915. struct Entry* entry = loadEntry(line);
  916.  
  917.  
  918.  
  919. // insert it into database
  920.  
  921. int insertResult = ERROR;
  922.  
  923. if(entry != NULL)
  924.  
  925. insertResult = insertEntry(*db, entry, username);
  926.  
  927.  
  928.  
  929. // print information about loading
  930.  
  931. if(!silence) {
  932.  
  933. switch(insertResult) {
  934.  
  935. case NO_ERROR:
  936.  
  937. printf("user '%s' inserted\n", username);
  938.  
  939. break;
  940.  
  941. case ERROR_DUPLICATE_ENTRY:
  942.  
  943. printf("user with the same UID already exists!\n");
  944.  
  945. freeEntry(entry);
  946.  
  947. break;
  948.  
  949. case ERROR_WRONG_ARGUMENTS:
  950.  
  951. printf("entry wasn't inserted!\n");
  952.  
  953. freeEntry(entry);
  954.  
  955. break;
  956.  
  957. case ERROR:
  958.  
  959. printf("loading entry failed\n");
  960.  
  961. break;
  962.  
  963. }
  964.  
  965. }
  966.  
  967.  
  968.  
  969. memset(line, 0, MAX_LINE_LENGTH); // clear line buffer
  970.  
  971. }
  972.  
  973.  
  974.  
  975. // release temporary memory
  976.  
  977. free(username);
  978.  
  979. username = NULL;
  980.  
  981.  
  982.  
  983. // close access to file stream
  984.  
  985. fclose(inputF);
  986.  
  987.  
  988.  
  989. return NO_ERROR;
  990.  
  991. }
  992.  
  993. // ============================================================================
  994.  
  995.  
  996.  
  997. // main.c
  998.  
  999. #define MAINIMPL
  1000.  
  1001. #ifdef MAINIMPL
  1002.  
  1003.  
  1004.  
  1005. #define CLEAR_SCREEN "clear" // windows = "cls", unix = "clear"
  1006.  
  1007.  
  1008.  
  1009. #include "database.h"
  1010.  
  1011. #include "entry.h"
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017. int guiPrintMenu();
  1018.  
  1019. void guiCreateDatabase();
  1020.  
  1021. void guiLoadDatabase();
  1022.  
  1023. void guiSaveDatabase();
  1024.  
  1025. void guiPrintDatabase();
  1026.  
  1027. void guiInsertEntry();
  1028.  
  1029. void guiMainLoop();
  1030.  
  1031. void guiRemoveEntry();
  1032.  
  1033. void guiSortDatabase();
  1034.  
  1035. void guiChangePassword();
  1036.  
  1037.  
  1038.  
  1039. #define NO_ACTIVE_DATABASE "No active database!\n"
  1040.  
  1041.  
  1042.  
  1043. int returnCode = 0;
  1044.  
  1045. struct Database* database = NULL;
  1046.  
  1047.  
  1048.  
  1049. // ============================================================================
  1050.  
  1051. /**
  1052.  
  1053. * Entry point of the application
  1054.  
  1055. *
  1056.  
  1057. * @return 0 = no error, !0 otherwise
  1058.  
  1059. */
  1060.  
  1061. int main(int argc, char* argv[]) {
  1062.  
  1063. printf("***************************************************************\n");
  1064.  
  1065. printf(" HW06 - database \n");
  1066.  
  1067. printf("***************************************************************\n");
  1068.  
  1069.  
  1070.  
  1071. // test number of input parameters
  1072.  
  1073. if(argc > 2)
  1074.  
  1075. printf("Wrong input parameters! \"database [file]\"");
  1076.  
  1077.  
  1078.  
  1079. // load input database file if the file was provided
  1080.  
  1081. if(argc == 2) {
  1082.  
  1083. loadDatabase(&database, argv[1], 0);
  1084.  
  1085. printf("***************************************************************\n\n");
  1086.  
  1087. }
  1088.  
  1089.  
  1090.  
  1091. // main menu loop
  1092.  
  1093. guiMainLoop();
  1094.  
  1095.  
  1096.  
  1097. // have to free allocated memory
  1098.  
  1099. if(database != NULL)
  1100.  
  1101. freeDatabase(database);
  1102.  
  1103.  
  1104.  
  1105. printf(" Good luck! \n");
  1106.  
  1107. printf("***************************************************************\n");
  1108.  
  1109.  
  1110.  
  1111. return returnCode;
  1112.  
  1113. }
  1114.  
  1115. // ============================================================================
  1116.  
  1117. /**
  1118.  
  1119. * Print main user's menu.
  1120.  
  1121. */
  1122.  
  1123. int guiPrintMenu() {
  1124.  
  1125. char ch = '0';
  1126.  
  1127.  
  1128.  
  1129. // print all actions
  1130.  
  1131. printf("1) create new database\n");
  1132.  
  1133. printf("2) list entries\n");
  1134.  
  1135. printf("3) insert entry\n");
  1136.  
  1137. printf("4) remove entry\n");
  1138.  
  1139. printf("5) change password\n");
  1140.  
  1141. printf("6) save\n");
  1142.  
  1143. printf("7) load\n");
  1144.  
  1145. printf("8) BONUS: sort\n");
  1146.  
  1147. printf("9) exit\n");
  1148.  
  1149.  
  1150.  
  1151. // get next choice
  1152.  
  1153. while(ch < '1' || ch > '9') {
  1154.  
  1155. if((int)ch != 10) // skip EOL flag
  1156.  
  1157. printf("choice: ");
  1158.  
  1159.  
  1160.  
  1161. scanf("%c", &ch);
  1162.  
  1163. }
  1164.  
  1165.  
  1166.  
  1167. return ch - '0';
  1168.  
  1169. }
  1170.  
  1171. // ============================================================================
  1172.  
  1173. /**
  1174.  
  1175. * Main GUI loop handler. Calls while user wants to work with the application.
  1176.  
  1177. */
  1178.  
  1179. void guiMainLoop() {
  1180.  
  1181. int result = guiPrintMenu();
  1182.  
  1183.  
  1184.  
  1185. // clear screen
  1186.  
  1187. system(CLEAR_SCREEN);
  1188.  
  1189.  
  1190.  
  1191. printf("***************************************************************\n");
  1192.  
  1193.  
  1194.  
  1195. switch(result) {
  1196.  
  1197. case 1:
  1198.  
  1199. guiCreateDatabase();
  1200.  
  1201. break;
  1202.  
  1203. case 2:
  1204.  
  1205. guiPrintDatabase();
  1206.  
  1207. break;
  1208.  
  1209. case 3:
  1210.  
  1211. guiInsertEntry();
  1212.  
  1213. break;
  1214.  
  1215. case 4:
  1216.  
  1217. guiRemoveEntry();
  1218.  
  1219. break;
  1220.  
  1221. case 5:
  1222.  
  1223. guiChangePassword();
  1224.  
  1225. break;
  1226.  
  1227. case 6:
  1228.  
  1229. guiSaveDatabase();
  1230.  
  1231. break;
  1232.  
  1233. case 7:
  1234.  
  1235. guiLoadDatabase();
  1236.  
  1237. break;
  1238.  
  1239. case 8:
  1240.  
  1241. guiSortDatabase();
  1242.  
  1243. break;
  1244.  
  1245. case 9:
  1246.  
  1247. return;
  1248.  
  1249. default:
  1250.  
  1251. printf("wrong choice!\n choice: ");
  1252.  
  1253. break;
  1254.  
  1255. }
  1256.  
  1257.  
  1258.  
  1259. printf("***************************************************************\n\n");
  1260.  
  1261.  
  1262.  
  1263. // redisplay the menu
  1264.  
  1265. guiMainLoop();
  1266.  
  1267. }
  1268.  
  1269. // ============================================================================
  1270.  
  1271. /**
  1272.  
  1273. * This method creates a new database connection and set it as active.
  1274.  
  1275. * If some old connection already exists, kill it.
  1276.  
  1277. */
  1278.  
  1279. void guiCreateDatabase() {
  1280.  
  1281. // if any database connection is available, kill them
  1282.  
  1283. if(database != NULL) {
  1284.  
  1285. freeDatabase(database);
  1286.  
  1287. database = NULL;
  1288.  
  1289. }
  1290.  
  1291.  
  1292.  
  1293. // create a new database
  1294.  
  1295. if((database = createDatabase()) == NULL)
  1296.  
  1297. fprintf(stderr, "error while creating database\n");
  1298.  
  1299. else
  1300.  
  1301. printf("database created\n");
  1302.  
  1303. }
  1304.  
  1305. // ============================================================================
  1306.  
  1307. /**
  1308.  
  1309. * User interface for inserting a new entry into database.
  1310.  
  1311. * User is asked for filling up the fields, then new entry is created and stored
  1312.  
  1313. * into the database.
  1314.  
  1315. */
  1316.  
  1317. void guiInsertEntry() {
  1318.  
  1319. // check if some connection is available
  1320.  
  1321. if(database == NULL)
  1322.  
  1323. guiCreateDatabase();
  1324.  
  1325.  
  1326.  
  1327. struct Entry* entry = NULL;
  1328.  
  1329.  
  1330.  
  1331. // get the data fields from the user
  1332.  
  1333. if((entry = fillEntry()) == NULL)
  1334.  
  1335. printf("error while filling the entry!\n");
  1336.  
  1337. else {
  1338.  
  1339.  
  1340.  
  1341. printf("***************************************************************\n");
  1342.  
  1343.  
  1344.  
  1345. char* username = (char*)malloc(sizeof(char)*MAX_FIELD_LENGTH);
  1346.  
  1347. if(username == NULL) {
  1348.  
  1349. fprintf(stderr, "allocation failed\n");
  1350.  
  1351. return;
  1352.  
  1353. }
  1354.  
  1355.  
  1356.  
  1357. int result = insertEntry(database, entry, username);
  1358.  
  1359.  
  1360.  
  1361. // add entry into database
  1362.  
  1363. switch(result) {
  1364.  
  1365. case ERROR_DUPLICATE_ENTRY:
  1366.  
  1367. printf("user with this UID already exists!\n");
  1368.  
  1369. freeEntry(entry);
  1370.  
  1371. break;
  1372.  
  1373. case ERROR_WRONG_ARGUMENTS:
  1374.  
  1375. printf("entry wasn't inserted!\n");
  1376.  
  1377. freeEntry(entry);
  1378.  
  1379. break;
  1380.  
  1381. default:
  1382.  
  1383. printf("user '%s' inserted\n", username);
  1384.  
  1385. break;
  1386.  
  1387. }
  1388.  
  1389.  
  1390.  
  1391. free(username);
  1392.  
  1393. username = NULL;
  1394.  
  1395. }
  1396.  
  1397. }
  1398.  
  1399. // ============================================================================
  1400.  
  1401. /**
  1402.  
  1403. * User interface for removing an entry.
  1404.  
  1405. */
  1406.  
  1407. void guiRemoveEntry() {
  1408.  
  1409. int id = -1, result = 1;
  1410.  
  1411.  
  1412.  
  1413. if(database != NULL) {
  1414.  
  1415.  
  1416.  
  1417. // get removing entry ID - NOT a UID or GID
  1418.  
  1419. printf("write ID of entry to remove: ");
  1420.  
  1421. scanf("%d", &id);
  1422.  
  1423. printf("\n");
  1424.  
  1425.  
  1426.  
  1427. // allocate temporary memory for user name from removed entry
  1428.  
  1429. char* username = (char*)malloc(sizeof(char)*MAX_FIELD_LENGTH);
  1430.  
  1431. if(username == NULL) {
  1432.  
  1433. fprintf(stderr, "allocation failed\n");
  1434.  
  1435. return;
  1436.  
  1437. }
  1438.  
  1439.  
  1440.  
  1441. memset(username, 0, MAX_FIELD_LENGTH);
  1442.  
  1443.  
  1444.  
  1445. // try to remove entry
  1446.  
  1447. result = removeEntry(database, id, username);
  1448.  
  1449.  
  1450.  
  1451. if(result)
  1452.  
  1453. fprintf(stderr, "error while removing entry with ID=%u\n", id);
  1454.  
  1455. else
  1456.  
  1457. printf("user '%s' removed\n", username);
  1458.  
  1459.  
  1460.  
  1461. free(username);
  1462.  
  1463. username = NULL;
  1464.  
  1465.  
  1466.  
  1467. } else
  1468.  
  1469. fprintf(stderr, NO_ACTIVE_DATABASE);
  1470.  
  1471. }
  1472.  
  1473. // ============================================================================
  1474.  
  1475. /**
  1476.  
  1477. * User interface for changing password.
  1478.  
  1479. */
  1480.  
  1481. void guiChangePassword() {
  1482.  
  1483. unsigned id = 0;
  1484.  
  1485. char passwd[MAX_FIELD_LENGTH];
  1486.  
  1487.  
  1488.  
  1489. if(database != NULL) {
  1490.  
  1491.  
  1492.  
  1493. // get removing entry ID - NOT a UID or GID
  1494.  
  1495. printf("write ID of changing entry: ");
  1496.  
  1497. scanf("%u", &id);
  1498.  
  1499. printf("\n");
  1500.  
  1501.  
  1502.  
  1503. // get new password
  1504.  
  1505. printf("new password: ");
  1506.  
  1507. scanf("%s", passwd);
  1508.  
  1509. printf("\n");
  1510.  
  1511.  
  1512.  
  1513. if(changePassword(database, id, passwd))
  1514.  
  1515. fprintf(stderr, "error during changing password in entry of ID=%u\n", id);
  1516.  
  1517. else
  1518.  
  1519. printf("password changed\n");
  1520.  
  1521.  
  1522.  
  1523. } else
  1524.  
  1525. fprintf(stderr, NO_ACTIVE_DATABASE);
  1526.  
  1527.  
  1528.  
  1529. }
  1530.  
  1531. // ============================================================================
  1532.  
  1533. /**
  1534.  
  1535. * This method prints the database to the standard output in a given format.
  1536.  
  1537. */
  1538.  
  1539. void guiPrintDatabase() {
  1540.  
  1541.  
  1542.  
  1543. if(database == NULL) // check is connection exists
  1544.  
  1545. printf(NO_ACTIVE_DATABASE);
  1546.  
  1547. else {
  1548.  
  1549. // print the header
  1550.  
  1551. printf("list of %u entries :\n\n", countEntries(database));
  1552.  
  1553.  
  1554.  
  1555. printf("%2s. %-10s %-15s %-5s %-5s %-20s\n", "ID", "USERNAME",
  1556.  
  1557. "PASSWORD", "UID", "GID", "COMMENT");
  1558.  
  1559.  
  1560.  
  1561. printf(" %-20s %-20s\n", "HOME", "SHELL");
  1562.  
  1563. printf("_______________________________________________________________\n");
  1564.  
  1565.  
  1566.  
  1567. // prints all entries
  1568.  
  1569. printDatabase(database);
  1570.  
  1571. }
  1572.  
  1573. }
  1574.  
  1575. // ============================================================================
  1576.  
  1577. /**
  1578.  
  1579. * User interface for loading database.
  1580.  
  1581. */
  1582.  
  1583. void guiLoadDatabase() {
  1584.  
  1585. char filename[MAX_FILENAME_SIZE];
  1586.  
  1587.  
  1588.  
  1589. printf("database to load: ");
  1590.  
  1591. scanf("%s", filename);
  1592.  
  1593. printf("\n");
  1594.  
  1595.  
  1596.  
  1597. // read database
  1598.  
  1599. loadDatabase(&database, filename, 0);
  1600.  
  1601. }
  1602.  
  1603. // ============================================================================
  1604.  
  1605. /**
  1606.  
  1607. * User interface for saving database.
  1608.  
  1609. */
  1610.  
  1611. void guiSaveDatabase() {
  1612.  
  1613. char filename[MAX_FILENAME_SIZE];
  1614.  
  1615.  
  1616.  
  1617. // gets target filename from user
  1618.  
  1619. printf("target filename: ");
  1620.  
  1621. scanf("%s", filename);
  1622.  
  1623. printf("\n");
  1624.  
  1625.  
  1626.  
  1627. if(saveDatabase(filename, database) != 0)
  1628.  
  1629. fprintf(stderr, "error while storing to file '%s'!\n", filename);
  1630.  
  1631. else
  1632.  
  1633. printf("storing to file '%s' was successful\n", filename);
  1634.  
  1635.  
  1636.  
  1637. }
  1638.  
  1639. // ============================================================================
  1640.  
  1641. /*
  1642.  
  1643. * User interface for sorting database.
  1644.  
  1645. */
  1646.  
  1647. void guiSortDatabase() {
  1648.  
  1649. int desc = 0;
  1650.  
  1651.  
  1652.  
  1653. if(database == NULL)
  1654.  
  1655. printf(NO_ACTIVE_DATABASE);
  1656.  
  1657. else {
  1658.  
  1659.  
  1660.  
  1661. // get sorting type
  1662.  
  1663. printf("descendant(0) or ascendant(1)?: ");
  1664.  
  1665. scanf("%d", &desc);
  1666.  
  1667. printf("\n");
  1668.  
  1669.  
  1670.  
  1671. if(sortDatabase(database, desc))
  1672.  
  1673. printf("database sorting failed\n");
  1674.  
  1675. else
  1676.  
  1677. printf("database sorted (%s)\n", (desc == 0) ? "descendant" : "ascendant");
  1678.  
  1679. }
  1680.  
  1681. }
  1682.  
  1683. // ============================================================================
  1684.  
  1685. #endif
  1686.  
  1687.  
  1688.  
  1689. // entry.h
  1690.  
  1691. #ifndef ENTRY_H
  1692.  
  1693. #define ENTRY_H
  1694.  
  1695.  
  1696.  
  1697. /**
  1698.  
  1699. *
  1700.  
  1701. */
  1702.  
  1703. typedef struct Entry
  1704.  
  1705. {
  1706.  
  1707. char *username; // user's name
  1708.  
  1709. char *passwd; // user's password
  1710.  
  1711. unsigned short uid; // user's ID
  1712.  
  1713. unsigned short gid; // user's group ID
  1714.  
  1715. char *comment; // user's comment
  1716.  
  1717. char *home; // user's home directory
  1718.  
  1719. char *shell; // user's shell
  1720.  
  1721. struct Entry *next; // pointer to the next user
  1722.  
  1723.  
  1724.  
  1725. struct Entry *previous; // pointer to the previous user - use it only when implementing BONUS
  1726.  
  1727.  
  1728.  
  1729. } Entry;
  1730.  
  1731.  
  1732.  
  1733. #endif
  1734.  
  1735.  
  1736.  
  1737. // database.h
  1738.  
  1739. #ifndef DATABASE_H
  1740.  
  1741. #define DATABASE_H
  1742.  
  1743.  
  1744.  
  1745. #include "entry.h"
  1746.  
  1747. #include <ctype.h>
  1748.  
  1749. #include <stdio.h>
  1750.  
  1751. #include <stdlib.h>
  1752.  
  1753. #include <string.h>
  1754.  
  1755.  
  1756.  
  1757. #define MAX_FILENAME_SIZE 100 // maximal length of input/output filename
  1758.  
  1759. #define MAX_LINE_LENGTH 500 // maximal length of input line
  1760.  
  1761. #define MAX_FIELD_LENGTH 30 // maximal length of data attribute when inserting by the user
  1762.  
  1763.  
  1764.  
  1765. #define NO_ERROR 0
  1766.  
  1767. #define ERROR_OPENING_FILE 1
  1768.  
  1769. #define ERROR_CREATING_DATABASE 2
  1770.  
  1771. #define ERROR_INSERTING_ENTRY 3
  1772.  
  1773. #define ERROR_WRONG_ARGUMENTS 4
  1774.  
  1775. #define ERROR_DUPLICATE_ENTRY 5
  1776.  
  1777. #define ERROR_ID_NOT_IN_INTERVAL 6
  1778.  
  1779. #define ERROR 7
  1780.  
  1781. #define ERROR_ALLOCATION 8
  1782.  
  1783.  
  1784.  
  1785. #define ZERO_CHAR '\0'
  1786.  
  1787.  
  1788.  
  1789. /**
  1790.  
  1791. *
  1792.  
  1793. */
  1794.  
  1795. typedef struct Database
  1796.  
  1797. {
  1798.  
  1799. // first database entry pointer
  1800.  
  1801. struct Entry* firstEntry;
  1802.  
  1803.  
  1804.  
  1805. // only for BONUS: pointer to the last entry of the database
  1806.  
  1807. struct Entry* lastEntry;
  1808.  
  1809. } Database;
  1810.  
  1811.  
  1812.  
  1813.  
  1814.  
  1815. /**
  1816.  
  1817. * Save the database to given external file.
  1818.  
  1819. *
  1820.  
  1821. * @param file Target file.
  1822.  
  1823. * @param database Which database.
  1824.  
  1825. * @return NO_ERROR = no error, ERROR_WRONG_ARGUMENTS = wrong input arguments, ERROR_OPENING_FILE = failed when opening file
  1826.  
  1827. */
  1828.  
  1829. int saveDatabase(const char* file, const struct Database* database);
  1830.  
  1831.  
  1832.  
  1833. /**
  1834.  
  1835. * Creates new empty database without any entry and set all pointers to NULL.
  1836.  
  1837. *
  1838.  
  1839. * @return Pointer to the memory, where the structure was created.
  1840.  
  1841. */
  1842.  
  1843. struct Database* createDatabase();
  1844.  
  1845.  
  1846.  
  1847. /**
  1848.  
  1849. * Prints all entries to standard output in "user readable" format.
  1850.  
  1851. * If database is NULL, print "no database connection" to stderr.
  1852.  
  1853. *
  1854.  
  1855. * @param database Database to print.
  1856.  
  1857. */
  1858.  
  1859. void printDatabase(struct Database* database);
  1860.  
  1861.  
  1862.  
  1863. /**
  1864.  
  1865. * Release all memory of given database which was allocated during working.
  1866.  
  1867. */
  1868.  
  1869. void freeDatabase(struct Database* database);
  1870.  
  1871.  
  1872.  
  1873. /**
  1874.  
  1875. * Release all memory of entry fields.
  1876.  
  1877. */
  1878.  
  1879. void freeEntry(struct Entry* entry);
  1880.  
  1881.  
  1882.  
  1883. /**
  1884.  
  1885. * Provide interface for creating new entry to the user. User fills each data field.
  1886.  
  1887. * You can rely on that the maximum data attribute length won't be more than MAX_FIELD_LENGTH
  1888.  
  1889. * and that the data on the input will be correct (ie. int where expected, ...).
  1890.  
  1891. * Correct UID is from interval <1, unsigned short>.
  1892.  
  1893. *
  1894.  
  1895. * @return NULL if strlen(username) == 0 or UID == 0 , Entry otherwise
  1896.  
  1897. */
  1898.  
  1899. struct Entry* fillEntry();
  1900.  
  1901.  
  1902.  
  1903. /**
  1904.  
  1905. * Insert entry into database. New entry is placed to the end of database.
  1906.  
  1907. *
  1908.  
  1909. * @param database Target database.
  1910.  
  1911. * @param newEntry Inserted entry.
  1912.  
  1913. * @param username If entry is inserted, copy of username from inserted entry to inform the user.
  1914.  
  1915. * @return NO_ERROR = no error, ERROR_WRONG_ARGUMENTS = wrong input arguments, ERROR_DUPLICATE_ENTRY = entry with the same UID already exists
  1916.  
  1917. */
  1918.  
  1919. int insertEntry(struct Database *database, struct Entry* newEntry, char* username);
  1920.  
  1921.  
  1922.  
  1923. /**
  1924.  
  1925. * Remove entry from the database.
  1926.  
  1927. *
  1928.  
  1929. * @param database Database from which the entry should be removed.
  1930.  
  1931. * @param id ID of removing entry. ID is not the same as UID or GID and is inside interval <1, num_of_entries>
  1932.  
  1933. * @param username If entry is removed, copy of username from removed entry to inform the user.
  1934.  
  1935. * @return NO_ERROR = entry removed, ERROR_ID_NOT_IN_INTERVAL = id is not in interval , ERROR_WRONG_ARGUMENTS = wrong input arguments
  1936.  
  1937. */
  1938.  
  1939. int removeEntry(struct Database* database, int id, char* username);
  1940.  
  1941.  
  1942.  
  1943. /**
  1944.  
  1945. * Count all entries in database.
  1946.  
  1947. *
  1948.  
  1949. * @param database Database to be printed.
  1950.  
  1951. * @return Number of entries in the database.
  1952.  
  1953. */
  1954.  
  1955. int countEntries(struct Database* database);
  1956.  
  1957.  
  1958.  
  1959. /**
  1960.  
  1961. * Parse the input line, create a new empty Entry and fills it with data.
  1962.  
  1963. *
  1964.  
  1965. * @param line One line from input file.
  1966.  
  1967. * @return NULL = error during loading (wrong argument), Entry otherwise
  1968.  
  1969. */
  1970.  
  1971. struct Entry* loadEntry(char* line);
  1972.  
  1973.  
  1974.  
  1975. /**
  1976.  
  1977. * Load the database from file.
  1978.  
  1979. *
  1980.  
  1981. * @param db pointer to database, if NULL create a new database first
  1982.  
  1983. * @param filename input filename
  1984.  
  1985. * @param silence 0 no output, OTHERWISE print information about entry insertion to the stdout
  1986.  
  1987. * @return NO_ERROR = load successful, ERROR_WRONG_ARGUMENTS = wrong input arguments,
  1988.  
  1989. * ERROR_OPENING_FILE = error during opening input file, ERROR_ALLOCATION - error during memory allocation
  1990.  
  1991. */
  1992.  
  1993. int loadDatabase(struct Database** db, char* filename, int silence);
  1994.  
  1995.  
  1996.  
  1997. // BONUS
  1998.  
  1999. /**
  2000.  
  2001. * Swap two entries with all of their bindings.
  2002.  
  2003. *
  2004.  
  2005. * @param a Entry
  2006.  
  2007. * @param b Entry
  2008.  
  2009. */
  2010.  
  2011. void swapEntries(struct Entry* a, struct Entry* b);
  2012.  
  2013.  
  2014.  
  2015. /**
  2016.  
  2017. * Sort the given database according to UID entry attribute and desc argument.
  2018.  
  2019. *
  2020.  
  2021. * @param database Database to be sorted.
  2022.  
  2023. * @param desc 0 = descendant, 1 = ascendant
  2024.  
  2025. * @return NO_ERROR = no error, !0 = otherwise
  2026.  
  2027. */
  2028.  
  2029. int sortDatabase(struct Database* database, int desc);
  2030.  
  2031.  
  2032.  
  2033. /**
  2034.  
  2035. * Change the password to the given user - entry ID.
  2036.  
  2037. *
  2038.  
  2039. * @param database In which database change the entry.
  2040.  
  2041. * @param entryID ID of the changing entry.
  2042.  
  2043. * @param newPassword New user password.
  2044.  
  2045. * @return NO_ERROR = no error, ERROR_ID_NOT_IN_INTERVAL = entry with ID doesn't exist,
  2046.  
  2047. * ERROR_WRONG_ARGUMENTS = wrong arguments, ERROR_ALLOCATION = error during memory allocation
  2048.  
  2049. */
  2050.  
  2051. int changePassword(struct Database* database, int entryID, char* newPassword);
  2052.  
  2053.  
  2054.  
  2055.  
  2056.  
  2057. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement