Рейтинговые книги
Читем онлайн Разработка приложений в среде Linux. Второе издание - Майкл Джонсон

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 73 74 75 76 77 78 79 80 81 ... 150

Функция setutent() перемещает внутренний указатель базы данных в начало.

Функция endutent() закрывает базу данных. Это закрывает файловый дескриптор и освобождает ассоциированные данные. Вызывайте endutent() как перед использованием utmpname() для доступа к другому файлу utmp, так и после завершения доступа к данным utmp.

Наиболее надежным способом модификации базы данных wtmp являются две функции, определенные BSD и доступные как часть glibc.

Функция updwtmp() принимает файловое имя базы данных wtmp (обычно _PATH_WTMP) и заполненную структуру struct utmp, пытаясь добавить элемент к файлу wtmp. Эта функция не сообщает об ошибках.

Функция logwtmp() является удобной функцией, заполняющей struct utmp и вызывающей updwtmp() для нее. Аргумент line копируется в ut_line, name — в ut_user, host — в ut_host, ut_tv заполняется текущим показанием времени, a ut_pid — текущим идентификатором процесса. Как и updwtmp(), эта функция не сообщает об ошибках.

В программе utmp демонстрируются некоторые методы чтения баз данных utmp и wtmp.

  1: /* utmp.с */

  2:

  3: #include <stdio.h>

  4: #include <unistd.h>

  5: #include <string.h>

  6: #include <time.h>

  7: #include <sys/time.h>

  8: #include <sys/types.h>

  9: #include <sys/socket.h>

 10: #include <netinet/in.h>

 11: #include <arpa/inet.h>

 12: #include <utmp.h>

 13: #include <popt.h>

 14:

 15: void print_utmp_entry(struct utmp * u) {

 16:  struct tm *tp;

 17:  char * type;

 18:  char addrtext[INET6_ADDRSTRLEN];

 19:

 20:  switch (u->ut_type) {

 21:  case EMPTY: type = "EMPTY"; break;

 22:  case RUN_LVL: type = "RUN_LVL"; break;

 23:  case BOOT_TIME: type = "BOOT_TIME"; break;

 24:  case NEW_TIME: type = "NEW_TIME"; break;

 25:  case OLD_TIME: type = "OLD_TIME"; break;

 26:  case INIT_PROCESS: type = "INIT_PROCESS"; break;

 27:  case LOGIN_PROCESS: type = "LOGIN_PROCESS"; break;

 28:  case USER_PROCESS: type = "USER_PROCESS"; break;

 29:  case DEAD_PROCESS: type = "DEAD_PROCESS"; break;

 30:  case ACCOUNTING: type = "ACCOUNTING "; break;

 31:  }

 32:  printf("%-13s:", type);

 33:  switch (u->ut_type) {

 34:  case LOGIN_PROCESS:

 35:  case USER_PROCESS:

 36:  case DEAD_PROCESS:

 37:   printf(" line: %s", u->ut_line);

 38:   /* fall through */

 39:  case INIT_PROCESS:

 40:   printf("n pid: %6d id: %4.4s", u->ut_pid, u->ut_id);

 41:  }

 42:  printf ("n");

 43:  tp = gmtime(&u->ut_tv.tv_sec);

 44:  printf("time: %24.24s.%lun", asctime(tp), u->ut_tv.tv_usec);

 45:  switch (u->ut_type) {

 46:  case USER_PROCESS:

 47:  case LOGIN_PROCESS:

 48:  case RUN_LVL:

 49:  case BOOT_TIME:

 50:   printf("пользователь: %sn", u->ut_user);

 51:  }

 52:  if (u->ut_type == USER_PROCESS) {

 53:   if (u->ut_session)

 54:    printf(" сеанс: %lun", u->ut_session);

 55:   if (u->ut_host)

 56:    printf (" хост: %sn", u->ut_host);

 57:   if (u->ut_addr_v6[0]) {

 58:    if (!(u->ut_addr_v6[1] |

 59:     u->ut_addr_v6[2] |

 60:     u->ut_addr_v6[3])) {

 61:     /* заполнение только первой группы означает адрес IPV4 */

 62:     inet_ntop(AF_INET, u->ut_addr_v6,

 63:     addrtext, sizeof(addrtext));

 64:     printf(" IPV4: %sn", addrtext);

 65:    } else {

 66:     inet_ntop(AF_INET_6, u->ut_addr_v6,

 67:      addrtext, sizeof(addrtext));

 68:     printf (" IPV6: %sn", addrtext);

 69:    }

 70:   }

 71:  }

 72:  if (u->ut_type == DEAD_PROCESS) {

 73:   printf(" завершение : %u: %un",

 74:    u->ut_exit.e_termination,

 75:    u->ut_exit.e_exit);

 76:  }

 77:  printf("n");

 78: }

 79:

 80: struct utmp * get_next_line (char * id, char * line) {

 81:  struct utmp request;

 82:

 83:  if (!id && !line)

 84:   return getutent();

 85:

 86:  memset(&request, 0, sizeof(request));

 87:

 88:  if (line) {

 89:   strncpy(&request.ut_line[0], line, UT_LINESIZE);

 90:   return getutline(&request);

 91:  }

 92:

 93:  request.ut_type = INIT_PROCESS;

 94:  strncpy(&request.ut_id[0], id, 4);

 95:  return getutid(&request);

 96: }

 97:

 98: void print_file(char * name, char * id, char * line) {

 99:  struct utmp * u;

100:

101:  if (utmpname(name)) {

102:   fprintf (stderr, "сбой при открытии базы данных utmp %sn", name);

103:   return;

104:  }

105:  setutent();

106:  printf("%s:n====================n", name);

107:  while ((u = get_next_line(id, line))) {

108:   print_utmp_entry(u);

109:   /* POSIX требует очистки статических данных перед

110:    * повторным вызовом getutline или getutid

111:    */

112:   memset(u, 0, sizeof(struct utmp));

113:  }

114:  endutent();

115: }

116:

117: int main(int argc, const char **argv) {

118:  char * id = NULL, *line = NULL;

119:  int show_utmp = 1, show_wtmp = 0;

120:  int c;

121:  poptContext optCon;

122:  struct poptOption optionsTable[] = {

123:   {"utmp", 'u', POPT_ARG_NONE|POPT_ARGFLAG_XOR,

124:    &show_utmp, 0,

125:    "переключить просмотр содержимого файла utmp", NULL},

126:   { "wtmp", 'w', POPT_ARG_NONE | POPT_ARGFLAG_XOR,

127:     &show_wtmp, 0,

128:     "переключить просмотр содержимого файла wtmp", NULL},

129:   {"id", 'i', POPT_ARG_STRING, &id, 0,

130:    "показать записи процесса для заданного идентификатора inittab",

131:    "<inittab id>" },

132:   {"line", 'l', POPT_ARG_STRING, &line, 0,

133:    "показать записи процесса для заданной строки устройства",

134:    "<line>" },

135:   POPT_AUTOHELP

136:   POPT_TABLEEND

137:  };

138:

139:  optCon = poptGetContext("utmp", argc, argv, optionsTable, 0);

140:  if ((c = poptGetNextOpt(optCon)) < -1) {

141:   fprintf(stderr, "%s:%sn",

142:    poptBadOption(optCon, POPT_BADOPTION_NOALIAS),

143:    poptStrerror(c));

144:   return 1;

145:  }

146:  poptFreeContext(optCon);

147:

148:  if (id && line)

149:   fprintf(stderr, "Невозможно выбирать сразу по идентификатору и строке,"

150:    "выбор по строкеn");

151:

152:  if (show_utmp)

153:   print_file(_PATH_UTMP, id, line);

154:  if (show_utmp && show_wtmp)

155:   printf("nnn");

156:  if (show_wtmp)

157:   print_file(_PATH_WTMP, id, line);

158:

159:  return 0;

160: }

16.2. Обзор termios

Все манипуляции tty осуществляются с помощью одной структуры, struct termios, а также нескольких функций, определенных в заголовочном файле <termios.h>. Из этих функций широко применяются только шесть. Когда не нужно устанавливать скорость передачи данных по линии, используются только две наиболее важных функции — tcgetattr() и tcsetattr().

#include <termios.h>

struct termios {

 tcflag_t c_iflag; /* флаги режима ввода */

 tcflag_t c_oflag; /* флаги режима вывода */

 tcflag_t c_cflag; /* флаги управляющего режима */

 tcflag_t c_lflag; /* флаги локального режима */

 cc_t c_line;      /* дисциплина линии связи */

 cc_t c_cc[NCCS];  /* управляющие символы */

};

int tcgetattr(int fd, struct termios * tp);

int tcsetattr(int fd, int oact, struct termios * tp);

Почти в каждом случае программы должны использовать tcgetattr() для получения текущих установок устройства, модифицировать эти установки, а затем применять tcsetattr() для активизации модифицированных установок. Многие программы также сохраняют копии оригинальных установок и восстанавливают их перед завершением. В общем случае, следует модифицировать только интересующие вас установки; изменение других установок может усложнить работу пользователей с необычными системными конфигурациями (или сбоями в вашем коде).

Вызов tcsetattr() может не принять на обработку выбранные вами установки; разрешено игнорировать произвольные установки. Если оборудование просто не поддерживает установку, tcsetattr() игнорирует ее, а не возвращает ошибку. Если вам небезразлично воздействие, оказываемое установкой, следует использовать tcgetattr() после tcsetattr() и проверить, оказало ли воздействие внесенное вами изменение.

Для получения установок устройства tty необходимо открыть устройство и передать файловый дескриптор tcgetattr(). Это вызывает проблемы с некоторыми устройствами tty; некоторые обычно можно открыть лишь один раз с целью предотвращения конфликта устройств. К счастью, передача флага O_NONBLOCK в open() вызывает его немедленное открытие и предотвращает блокирование любых операций. Однако все равно можно предпочесть блокирование read(); в таком случае используйте fcntl() для отключения режима O_NONBLOCK перед тем, как появится возможность читать или записывать в него.

1 ... 73 74 75 76 77 78 79 80 81 ... 150
На этой странице вы можете бесплатно читать книгу Разработка приложений в среде Linux. Второе издание - Майкл Джонсон бесплатно.
Похожие на Разработка приложений в среде Linux. Второе издание - Майкл Джонсон книги

Оставить комментарий