+ // Suppose atomic memory move
+ cur = follow ? buf->tail : buf->head;
+
+ do {
+#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
+ char *buf_data;
+ int log_len, j;
+#endif
+ if (semop(log_semid, SMrdn, 2) == -1)
+ error_exit("semop[SMrdn]");
+
+ if (DEBUG)
+ printf("head:%i cur:%d tail:%i size:%i\n",
+ buf->head, cur, buf->tail, buf->size);
+
+ if (buf->head == buf->tail || cur == buf->tail) {
+ if (follow) {
+ sem_up(log_semid);
+ fflush(stdout);
+ sleep(1); /* TODO: replace me with a sleep_on */
+ continue;
+ }
+ puts("<empty syslog>");
+ }
+
+ // Read Memory
+#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
+ log_len = buf->tail - cur;
+ if (log_len < 0)
+ log_len += buf->size;
+ buf_data = xmalloc(log_len);
+
+ if (buf->tail >= cur)
+ j = log_len;
+ else
+ j = buf->size - cur;
+ memcpy(buf_data, buf->data + cur, j);
+
+ if (buf->tail < cur)
+ memcpy(buf_data + buf->size - cur, buf->data, buf->tail);
+ cur = buf->tail;
+#else
+ while (cur != buf->tail) {
+ fputs(buf->data + cur, stdout);
+ cur += strlen(buf->data + cur) + 1;
+ if (cur >= buf->size)
+ cur = 0;
+ }
+#endif
+ // release the lock on the log chain
+ sem_up(log_semid);
+
+#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
+ for (j = 0; j < log_len; j += strlen(buf_data+j) + 1) {
+ fputs(buf_data + j, stdout);
+ }
+ free(buf_data);
+#endif
+ } while (follow);
+
+ shmdt(buf);
+
+ fflush_stdout_and_exit(EXIT_SUCCESS);