tail.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "prio.h"
  6. #include "prprf.h"
  7. #include "prinit.h"
  8. #include "prthread.h"
  9. #include "prinrval.h"
  10. #include "plerror.h"
  11. #include "plgetopt.h"
  12. #include <stdlib.h>
  13. #define BUFFER_SIZE 500
  14. static PRFileDesc *out = NULL, *err = NULL;
  15. static void Help(void)
  16. {
  17. PR_fprintf(err, "Usage: tail [-n <n>] [-f] [-h] <filename>\n");
  18. PR_fprintf(err, "\t-t <n> Dally time in milliseconds\n");
  19. PR_fprintf(err, "\t-n <n> Number of bytes before <eof>\n");
  20. PR_fprintf(err, "\t-f Follow the <eof>\n");
  21. PR_fprintf(err, "\t-h This message and nothing else\n");
  22. } /* Help */
  23. PRIntn main(PRIntn argc, char **argv)
  24. {
  25. PRIntn rv = 0;
  26. PLOptStatus os;
  27. PRStatus status;
  28. PRFileDesc *file;
  29. PRFileInfo fileInfo;
  30. PRIntervalTime dally;
  31. char buffer[BUFFER_SIZE];
  32. PRBool follow = PR_FALSE;
  33. const char *filename = NULL;
  34. PRUint32 position = 0, seek = 0, time = 0;
  35. PLOptState *opt = PL_CreateOptState(argc, argv, "hfn:");
  36. out = PR_GetSpecialFD(PR_StandardOutput);
  37. err = PR_GetSpecialFD(PR_StandardError);
  38. while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  39. {
  40. if (PL_OPT_BAD == os) {
  41. continue;
  42. }
  43. switch (opt->option)
  44. {
  45. case 0: /* it's the filename */
  46. filename = opt->value;
  47. break;
  48. case 'n': /* bytes before end of file */
  49. seek = atoi(opt->value);
  50. break;
  51. case 't': /* dally time */
  52. time = atoi(opt->value);
  53. break;
  54. case 'f': /* follow the end of file */
  55. follow = PR_TRUE;
  56. break;
  57. case 'h': /* user wants some guidance */
  58. Help(); /* so give him an earful */
  59. return 2; /* but not a lot else */
  60. break;
  61. default:
  62. break;
  63. }
  64. }
  65. PL_DestroyOptState(opt);
  66. if (0 == time) {
  67. time = 1000;
  68. }
  69. dally = PR_MillisecondsToInterval(time);
  70. if (NULL == filename)
  71. {
  72. (void)PR_fprintf(out, "Input file not specified\n");
  73. rv = 1; goto done;
  74. }
  75. file = PR_Open(filename, PR_RDONLY, 0);
  76. if (NULL == file)
  77. {
  78. PL_FPrintError(err, "File cannot be opened for reading");
  79. return 1;
  80. }
  81. status = PR_GetOpenFileInfo(file, &fileInfo);
  82. if (PR_FAILURE == status)
  83. {
  84. PL_FPrintError(err, "Cannot acquire status of file");
  85. rv = 1; goto done;
  86. }
  87. if (seek > 0)
  88. {
  89. if (seek > fileInfo.size) {
  90. seek = 0;
  91. }
  92. position = PR_Seek(file, (fileInfo.size - seek), PR_SEEK_SET);
  93. if (-1 == (PRInt32)position) {
  94. PL_FPrintError(err, "Cannot seek to starting position");
  95. }
  96. }
  97. do
  98. {
  99. while (position < fileInfo.size)
  100. {
  101. PRInt32 read, bytes = fileInfo.size - position;
  102. if (bytes > sizeof(buffer)) {
  103. bytes = sizeof(buffer);
  104. }
  105. read = PR_Read(file, buffer, bytes);
  106. if (read != bytes) {
  107. PL_FPrintError(err, "Cannot read to eof");
  108. }
  109. position += read;
  110. PR_Write(out, buffer, read);
  111. }
  112. if (follow)
  113. {
  114. PR_Sleep(dally);
  115. status = PR_GetOpenFileInfo(file, &fileInfo);
  116. if (PR_FAILURE == status)
  117. {
  118. PL_FPrintError(err, "Cannot acquire status of file");
  119. rv = 1; goto done;
  120. }
  121. }
  122. } while (follow);
  123. done:
  124. PR_Close(file);
  125. return rv;
  126. } /* main */
  127. /* tail.c */