1 /* 2 * Copyright 1987, 1988 by MIT Student Information Processing Board 3 * 4 * Permission to use, copy, modify, and distribute this software and 5 * its documentation for any purpose is hereby granted, provided that 6 * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in 7 * advertising or publicity pertaining to distribution of the software 8 * without specific, written prior permission. M.I.T. and the 9 * M.I.T. S.I.P.B. make no representations about the suitability of 10 * this software for any purpose. It is provided "as is" without 11 * express or implied warranty. 12 */ 13 14 #ifdef HAVE_UNISTD_H 15 #include <unistd.h> 16 #endif 17 #ifdef HAVE_STDLIB_H 18 #include <stdlib.h> 19 #endif 20 #ifdef HAVE_ERRNO_H 21 #include <errno.h> 22 #else 23 extern int errno; 24 #endif 25 #include <fcntl.h> 26 #include <sys/param.h> 27 #include <sys/types.h> 28 #include <sys/file.h> 29 #ifdef NEED_SYS_FCNTL_H 30 /* just for O_* */ 31 #include <sys/fcntl.h> 32 #endif 33 #ifdef HAVE_SYS_WAIT_H 34 #include <sys/wait.h> 35 #endif 36 #include "ss_internal.h" 37 38 void ss_help (argc, argv, sci_idx, info_ptr) 39 int argc; 40 char const * const *argv; 41 int sci_idx; 42 pointer info_ptr; 43 { 44 char *buffer; 45 char const *request_name; 46 int code; 47 int fd, child; 48 register int idx; 49 register ss_data *info; 50 51 request_name = ss_current_request(sci_idx, &code); 52 if (code != 0) { 53 ss_perror(sci_idx, code, ""); 54 return; /* no ss_abort_line, if invalid invocation */ 55 } 56 if (argc == 1) { 57 ss_list_requests(argc, argv, sci_idx, info_ptr); 58 return; 59 } 60 else if (argc != 2) { 61 /* should do something better than this */ 62 buffer = malloc(80+2*strlen(request_name)); 63 if (!buffer) { 64 ss_perror(sci_idx, 0, 65 "couldn't allocate memory to print usage message"); 66 return; 67 } 68 sprintf(buffer, "usage:\n\t%s [topic|command]\nor\t%s\n", 69 request_name, request_name); 70 ss_perror(sci_idx, 0, buffer); 71 free(buffer); 72 return; 73 } 74 info = ss_info(sci_idx); 75 if (info->info_dirs == (char **)NULL) { 76 ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL); 77 return; 78 } 79 if (info->info_dirs[0] == (char *)NULL) { 80 ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL); 81 return; 82 } 83 for (fd = -1, idx = 0; info->info_dirs[idx] != (char *)NULL; idx++) { 84 buffer = malloc(strlen (info->info_dirs[idx]) + 1 + 85 strlen (argv[1]) + 6); 86 if (!buffer) { 87 ss_perror(sci_idx, 0, 88 "couldn't allocate memory for help filename"); 89 return; 90 } 91 (void) strcpy(buffer, info->info_dirs[idx]); 92 (void) strcat(buffer, "/"); 93 (void) strcat(buffer, argv[1]); 94 (void) strcat(buffer, ".info"); 95 fd = open(buffer, O_RDONLY); 96 free(buffer); 97 if (fd >= 0) 98 break; 99 } 100 if (fd < 0) { 101 #define MSG "No info found for " 102 char *buf = malloc(strlen (MSG) + strlen (argv[1]) + 1); 103 strcpy(buf, MSG); 104 strcat(buf, argv[1]); 105 ss_perror(sci_idx, 0, buf); 106 free(buf); 107 return; 108 } 109 switch (child = fork()) { 110 case -1: 111 ss_perror(sci_idx, errno, "Can't fork for pager"); 112 return; 113 case 0: 114 (void) dup2(fd, 0); /* put file on stdin */ 115 ss_page_stdin(); 116 default: 117 (void) close(fd); /* what can we do if it fails? */ 118 while (wait(0) != child) { 119 /* do nothing if wrong pid */ 120 }; 121 } 122 } 123 124 #ifndef HAVE_DIRENT_H 125 #include <sys/dir.h> 126 #else 127 #include <dirent.h> 128 #endif 129 130 void ss_add_info_dir(sci_idx, info_dir, code_ptr) 131 int sci_idx; 132 char *info_dir; 133 int *code_ptr; 134 { 135 register ss_data *info; 136 DIR *d; 137 int n_dirs; 138 register char **dirs; 139 140 info = ss_info(sci_idx); 141 if (info_dir == NULL || *info_dir == '\0') { 142 *code_ptr = SS_ET_NO_INFO_DIR; 143 return; 144 } 145 if ((d = opendir(info_dir)) == (DIR *)NULL) { 146 *code_ptr = errno; 147 return; 148 } 149 closedir(d); 150 dirs = info->info_dirs; 151 for (n_dirs = 0; dirs[n_dirs] != (char *)NULL; n_dirs++) 152 ; /* get number of non-NULL dir entries */ 153 dirs = (char **)realloc((char *)dirs, 154 (unsigned)(n_dirs + 2)*sizeof(char *)); 155 if (dirs == (char **)NULL) { 156 info->info_dirs = (char **)NULL; 157 *code_ptr = errno; 158 return; 159 } 160 info->info_dirs = dirs; 161 dirs[n_dirs + 1] = (char *)NULL; 162 dirs[n_dirs] = malloc((unsigned)strlen(info_dir)+1); 163 strcpy(dirs[n_dirs], info_dir); 164 *code_ptr = 0; 165 } 166 167 void ss_delete_info_dir(sci_idx, info_dir, code_ptr) 168 int sci_idx; 169 char *info_dir; 170 int *code_ptr; 171 { 172 register char **i_d; 173 register char **info_dirs; 174 175 info_dirs = ss_info(sci_idx)->info_dirs; 176 for (i_d = info_dirs; *i_d; i_d++) { 177 if (!strcmp(*i_d, info_dir)) { 178 while (*i_d) { 179 *i_d = *(i_d+1); 180 i_d++; 181 } 182 *code_ptr = 0; 183 return; 184 } 185 } 186 *code_ptr = SS_ET_NO_INFO_DIR; 187 } 188