int get_size_argument(long *number, partition_map_header *map) { partition_map * entry; int result = 0; unsigned long multiple; if (get_number_argument("Length in blocks: ", number, kDefault) == 0) { bad_input("Bad length"); } else { multiple = get_multiplier(map->logical_block); if (multiple == 0) { bad_input("Bad multiplier"); } else if (multiple != 1) { *number *= multiple; result = 1; } else if (get_partition_modifier()) { entry = find_entry_by_disk_address(*number, map); if (entry == NULL) { bad_input("Bad partition number"); } else { *number = entry->data->dpme_pblocks; result = 1; } } else { result = 1; } } return result; }
void do_rename_partition(partition_map_header *map) { partition_map * entry; long ix; char *name; if (map == NULL) { bad_input("No partition map exists"); return; } if (!rflag && map->writable == 0) { printf("The map is not writable.\n"); } if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { bad_input("Bad partition number"); return; } if (get_string_argument("New name of partition: ", &name, 1) == 0) { bad_input("Bad name"); return; } // find partition and change it entry = find_entry_by_disk_address(ix, map); if (entry == NULL) { printf("No such partition\n"); } else { // stuff name into partition map entry data strncpy(entry->data->dpme_name, name, DPISTRLEN); map->changed = 1; } free(name); return; }
void do_write_partition_map(partition_map_header *map) { if (map == NULL) { bad_input("No partition map exists"); return; } if (map->changed == 0 && map->written == 0) { bad_input("The map has not been changed."); return; } if (map->writable == 0) { bad_input("The map is not writable."); return; } #if 0 /* this check is not found in linux fdisk-0.1 */ if (map->blocks_in_map > MAX_LINUX_MAP) { error(-1, "Map contains more than %d blocks - Linux may have trouble", MAX_LINUX_MAP); } #endif printf("Writing the map destroys what was there before. "); if (get_okay("Is that okay? [n/y]: ", 0) != 1) { return; } write_partition_map(map); map->changed = 0; map->written = 1; // exit(0); }
void do_delete_partition(partition_map_header *map) { partition_map * cur; long ix; if (map == NULL) { bad_input("No partition map exists"); return; } if (!rflag && map->writable == 0) { printf("The map is not writable.\n"); } if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { bad_input("Bad partition number"); return; } // find partition and delete it cur = find_entry_by_disk_address(ix, map); if (cur == NULL) { printf("No such partition\n"); } else { delete_partition_from_map(cur); } }
void dump_partition_map(partition_map_header *map, int disk_order) { partition_map * entry; int max_type_length; int max_name_length; int digits; char *alternate; if (map == NULL) { bad_input("No partition map exists"); return; } alternate = get_linux_name(map->name); if (alternate) { printf("\nPartition map (with %d byte blocks) on '%s' (%s)\n", map->logical_block, map->name, alternate); free(alternate); } else { printf("\nPartition map (with %d byte blocks) on '%s'\n", map->logical_block, map->name); } digits = number_of_digits(get_max_base_or_length(map)); if (digits < 6) { digits = 6; } if (aflag) { max_type_length = 4; } else { max_type_length = get_max_type_string_length(map); if (max_type_length < 4) { max_type_length = 4; } } max_name_length = get_max_name_string_length(map); if (max_name_length < 6) { max_name_length = 6; } printf(" #: %*s %-*s %*s %-*s ( size )\n", max_type_length, "type", max_name_length, "name", digits, "length", digits, "base"); if (disk_order) { for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { dump_partition_entry(entry, max_type_length, max_name_length, digits); } } else { for (entry = map->base_order; entry != NULL; entry = entry->next_by_base) { dump_partition_entry(entry, max_type_length, max_name_length, digits); } } dump_block_zero(map); }
void do_change_map_size(partition_map_header *map) { long size; if (map == NULL) { bad_input("No partition map exists"); return; } if (!rflag && map->writable == 0) { printf("The map is not writable.\n"); } if (get_number_argument("New size: ", &size, kDefault) == 0) { bad_input("Bad size"); return; } resize_map(size, map); }
int (*getptr(char ch))() { switch(ch){ case '+': return plus; case '-': return − } bad_input("need + or -"); }
void do_change_type(partition_map_header *map) { partition_map * entry; long ix; char *type = NULL; if (map == NULL) { bad_input("No partition map exists"); return; } if (!rflag && map->writable == 0) { printf("The map is not writeable.\n"); } if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { bad_input("Bad partition number"); return; } entry = find_entry_by_disk_address(ix, map); if (entry == NULL ) { printf("No such partition\n"); goto out; } printf("Existing partition type ``%s''.\n", entry->data->dpme_type); if (get_string_argument("New type of partition: ", &type, 1) == 0) { bad_input("Bad type"); goto out; } strncpy(entry->data->dpme_type, type, DPISTRLEN); do_update_dpme(entry); map->changed = 1; out: if (type) free(type); return; }
void do_display_entry(partition_map_header *map) { long number; if (map == NULL) { bad_input("No partition map exists"); return; } if (get_number_argument("Partition number: ", &number, kDefault) == 0) { bad_input("Bad partition number"); return; } if (number == 0) { full_dump_block_zero(map); } else { full_dump_partition_entry(map, number); } }
int get_base_argument(long *number, partition_map_header *map) { partition_map * entry; int result = 0; if (get_number_argument("First block: ", number, kDefault) == 0) { bad_input("Bad block number"); } else { result = 1; if (get_partition_modifier()) { entry = find_entry_by_disk_address(*number, map); if (entry == NULL) { bad_input("Bad partition number"); result = 0; } else { *number = entry->data->dpme_pblock_start; } } } return result; }
void do_reorder(partition_map_header *map) { long old_index; long ix; if (map == NULL) { bad_input("No partition map exists"); return; } if (!rflag && map->writable == 0) { printf("The map is not writable.\n"); } if (get_number_argument("Partition number: ", &old_index, kDefault) == 0) { bad_input("Bad partition number"); return; } if (get_number_argument("New number: ", &ix, kDefault) == 0) { bad_input("Bad partition number"); return; } move_entry_in_map(old_index, ix, map); }
int main(int argc, char **argv) { int a, b; int (*f)(int, int); if(argc != 2 || argv[1][1]) bad_input("arglen"); a = 3; b = 2; f = getptr(argv[1][0]); printf("%d %c %d = %d\n", a, argv[1][0], b, f(a, b)); return 0; }
void do_examine_patch_partition(partition_map_header *map) { partition_map * entry; if (map == NULL) { bad_input("No partition map exists"); return; } entry = find_entry_by_type(kPatchType, map); if (entry == NULL) { printf("No patch partition\n"); } else { display_patches(entry); } }
void do_display_block(partition_map_header *map, char *alt_name) { MEDIA m; long number; char *name; static unsigned char *display_block; static int display_g; int g; static long next_number = -1; if (map != NULL) { name = 0; m = map->m; g = map->logical_block; } else { if (alt_name == 0) { if (get_string_argument("Name of device: ", &name, 1) == 0) { bad_input("Bad name"); return; } } else { name = strdup(alt_name); } m = open_pathname_as_media(name, O_RDONLY); if (m == 0) { error(errno, "can't open file '%s'", name); free(name); return; } g = media_granularity(m); if (g < PBLOCK_SIZE) { g = PBLOCK_SIZE; } } if (get_number_argument("Block number: ", &number, next_number) == 0) { bad_input("Bad block number"); goto xit; } if (display_block == NULL || display_g < g) { if (display_block != NULL) { free(display_block); display_g = 0; } display_block = (unsigned char *) malloc(g); if (display_block == NULL) { error(errno, "can't allocate memory for display block buffer"); goto xit; } display_g = g; } if (read_media(m, ((long long)number) * g, g, (char *)display_block) != 0) { printf("block %ld -", number); dump_block((unsigned char*) display_block, g); next_number = number + 1; } xit: if (name) { close_media(m); free(name); } return; }
int main(int argc, char* argv[]) { int sockfd, serverLen; struct sockaddr_in serverINETAddress; /* Server Inernet address */ struct sockaddr* serverSockAddrPtr; /* Ptr to server address */ struct hostent* server; /* hostent structure */ char command[BUFFER_SIZE], host[100], buf[RESULT_BUFFER]; char user[100],psw[100]; int port = DEFAULT_SERVER_PORT, result; unsigned long inetAddress; /* 32-bit IP address */ /* Ignore SIGINT and SIGQUIT */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); if((argc % 2)==0 || argc > 9) bad_input(argv[0]); int i; for(i = 1; i < argc; i+=2) { char* param = argv[i]; if(strcmp(param, "-h")==0) strcpy(host, argv[i+1]); else if(strcmp(param, "-p")==0) port = atoi(argv[i+1]); else if(strcmp(param, "-usr")==0) strcpy(user, argv[i+1]); else if(strcmp(param, "-psw")==0) strcpy(psw, argv[i+1]); else bad_input(argv[0]); } serverSockAddrPtr = (struct sockaddr*) &serverINETAddress; serverLen = sizeof(serverINETAddress); bzero((char *) &serverINETAddress, serverLen); serverINETAddress.sin_family=AF_INET; serverINETAddress.sin_port=htons(port); inetAddress = inet_addr(host); /* get internet address */ if(inetAddress != INADDR_NONE) { /* is an IP address */ serverINETAddress.sin_addr.s_addr = inetAddress; } else { /* is a "hostname" */ server = gethostbyname(host); if(server == NULL) { fprintf(stderr, "ERROR, no such host\n"); exit(0); } bcopy((char*)server->h_addr, (char*)&serverINETAddress.sin_addr.s_addr, server->h_length); } sockfd = socket(AF_INET,SOCK_STREAM,DEFAULT_PROTOCOL); /* create socket */ if (sockfd < 0) error("ERROR opening socket"); /* Loop until connection is made with the server OR timeout */ int nsec=1; do { result = connect(sockfd, serverSockAddrPtr, serverLen); if(result == -1) { sleep(1); nsec++; } } while(result == -1 && nsec <= MAX_SLEEP); if(nsec > MAX_SLEEP) error("Connection timeout"); /* Set socket to timeout on recv if no data is available */ struct timeval tv; tv.tv_sec = RCV_TIMEOUT; /* set timeout */ setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval*) &tv, sizeof(struct timeval)); instruction(); /* Display instructions */ authenticate(sockfd, user, psw); while(1) { printf("%s ", RS_PROMPT_CHAR); bzero(command, sizeof(command)); fgets(command, BUFFER_SIZE, stdin); bzero(buf, sizeof(buf)); /* Send command */ if(send(sockfd,command,sizeof(command),0) < 0) error("ERROR sending message"); if (strcmp(command, "exit\n") == 0) break; /* Receive message from server */ int total = receive_msg(sockfd, buf); if(total>0){ buf[total]='\0'; printf("%s\n", buf); } } close (sockfd); return 0; }
int do_expert(partition_map_header *map, char *name) { int command; int quit = 0; while (get_command("Expert command (? for help): ", first_get, &command)) { first_get = 0; switch (command) { case '?': print_expert_notes(); // fall through case 'H': case 'h': printf("Commands are:\n"); printf(" h print help\n"); printf(" d dump block n\n"); printf(" p print the partition table\n"); if (dflag) { printf(" P (show data structures - debugging)\n"); } printf(" f full display of nth entry\n"); printf(" v validate map\n"); printf(" e examine patch partition\n"); printf(" q return to main edit menu\n"); printf(" Q quit editing\n"); break; case 'q': flush_to_newline(1); goto finis; break; case 'Q': if (map->changed) { if (get_okay("Discard changes? [n/y]: ", 0) != 1) { break; } } quit = 1; goto finis; break; case 'P': if (dflag) { show_data_structures(map); break; } // fall through case 'p': dump_partition_map(map, 1); break; case 'D': case 'd': do_display_block(map, name); break; case 'F': case 'f': do_display_entry(map); break; case 'V': case 'v': validate_map(map); break; case 'E': case 'e': do_examine_patch_partition(map); break; default: bad_input("No such command (%c)", command); break; } } finis: return quit; }
void interact() { char *name; int command; int ask_logical_size; while (get_command("Top level command (? for help): ", first_get, &command)) { first_get = 0; ask_logical_size = 0; switch (command) { case '?': print_top_notes(); // fall through case 'H': case 'h': printf("Commands are:\n"); printf(" h print help\n"); printf(" v print the version number and release date\n"); printf(" l list device's map\n"); #ifdef __linux__ printf(" L list all devices' maps\n"); #endif printf(" e edit device's map\n"); printf(" E (edit map with specified block size)\n"); printf(" r toggle readonly flag\n"); printf(" f toggle show filesystem name flag\n"); if (dflag) { printf(" a toggle abbreviate flag\n"); printf(" p toggle physical flag\n"); printf(" c toggle compute size flag\n"); printf(" d toggle debug flag\n"); printf(" x examine block n of device\n"); } printf(" q quit the program\n"); break; case 'Q': case 'q': return; break; case 'V': case 'v': printf("version " VERSION " (" RELEASE_DATE ")\n"); break; #ifdef __linux__ case 'L': list_all_disks(); break; #endif case 'l': if (get_string_argument("Name of device: ", &name, 1) == 0) { bad_input("Bad name"); break; } dump(name); free(name); break; case 'E': ask_logical_size = 1; case 'e': if (get_string_argument("Name of device: ", &name, 1) == 0) { bad_input("Bad name"); break; } edit(name, ask_logical_size); free(name); break; case 'R': case 'r': if (rflag) { rflag = 0; } else { rflag = 1; } printf("Now in %s mode.\n", (rflag)?"readonly":"read/write"); break; case 'F': case 'f': if (fflag) { fflag = 0; } else { fflag = 1; } printf("Now in show %s name mode.\n", (fflag)?"filesystem":"partition"); break; case 'A': case 'a': if (dflag) { if (aflag) { aflag = 0; } else { aflag = 1; } printf("Now in %s mode.\n", (aflag)?"abbreviate":"full type"); } else { goto do_error; } break; case 'P': case 'p': if (dflag) { if (pflag) { pflag = 0; } else { pflag = 1; } printf("Now in %s mode.\n", (pflag)?"physical":"logical"); } else { goto do_error; } break; case 'D': case 'd': if (dflag) { dflag = 0; } else { dflag = 1; } printf("Now in %s mode.\n", (dflag)?"debug":"normal"); break; case 'C': case 'c': if (dflag) { if (cflag) { cflag = 0; } else { cflag = 1; } printf("Now in %s device size mode.\n", (cflag)?"always compute":"use existing"); } else { goto do_error; } break; case 'X': case 'x': if (dflag) { do_display_block(0, 0); } else { goto do_error; } break; default: do_error: bad_input("No such command (%c)", command); break; } } }
// // Edit the file // void edit(char *name, int ask_logical_size) { partition_map_header *map; int command; int order; int get_type; int valid_file; map = open_partition_map(name, &valid_file, ask_logical_size); if (!valid_file) { return; } printf("Edit %s -\n", name); #if 0 /* this check is not found in linux fdisk-0.1 */ if (map != NULL && map->blocks_in_map > MAX_LINUX_MAP) { error(-1, "Map contains more than %d blocks - Linux may have trouble", MAX_LINUX_MAP); } #endif while (get_command("Command (? for help): ", first_get, &command)) { first_get = 0; order = 1; get_type = 0; switch (command) { case '?': print_edit_notes(); // fall through case 'H': case 'h': printf("Commands are:\n"); printf(" C (create with type also specified)\n"); printf(" c create new partition (standard unix root)\n"); printf(" d delete a partition\n"); printf(" h help\n"); printf(" i initialize partition map\n"); printf(" n (re)name a partition\n"); printf(" P (print ordered by base address)\n"); printf(" p print the partition table\n"); printf(" q quit editing\n"); printf(" r reorder partition entry in map\n"); printf(" s change size of partition map\n"); printf(" t change a partition's type\n"); if (!rflag) { printf(" w write the partition table\n"); } if (dflag) { printf(" x extra extensions for experts\n"); } break; case 'P': order = 0; // fall through case 'p': dump_partition_map(map, order); break; case 'Q': case 'q': if (map && map->changed) { if (get_okay("Discard changes? [n/y]: ", 0) != 1) { break; } } flush_to_newline(1); goto finis; break; case 'I': case 'i': map = init_partition_map(name, map); break; case 'C': get_type = 1; // fall through case 'c': do_create_partition(map, get_type); break; case 'N': case 'n': do_rename_partition(map); break; case 'D': case 'd': do_delete_partition(map); break; case 'R': case 'r': do_reorder(map); break; case 'S': case 's': do_change_map_size(map); break; case 'T': case 't': do_change_type(map); break; case 'X': case 'x': if (!dflag) { goto do_error; } else if (do_expert(map, name)) { flush_to_newline(1); goto finis; } break; case 'W': case 'w': if (!rflag) { do_write_partition_map(map); } else { goto do_error; } break; default: do_error: bad_input("No such command (%c)", command); break; } } finis: close_partition_map(map); }
void do_create_partition(partition_map_header *map, int get_type) { long base; long length; char *name = 0; char *type_name = 0; if (map == NULL) { bad_input("No partition map exists"); return; } if (!rflag && map->writable == 0) { printf("The map is not writable.\n"); } // XXX add help feature (i.e. '?' in any argument routine prints help string) if (get_base_argument(&base, map) == 0) { return; } if (get_size_argument(&length, map) == 0) { return; } if (get_string_argument("Name of partition: ", &name, 1) == 0) { bad_input("Bad name"); return; } if (get_type == 0) { add_partition_to_map(name, kUnixType, base, length, map); #if 0 /* this check is not found in linux fdisk-0.1 */ if (map->blocks_in_map > MAX_LINUX_MAP) { error(-1, "Map contains more than %d blocks - Linux may have trouble", MAX_LINUX_MAP); } goto xit1; #endif } else if (get_string_argument("Type of partition: ", &type_name, 1) == 0) { bad_input("Bad type"); goto xit1; } else { if (istrncmp(type_name, kFreeType, DPISTRLEN) == 0) { bad_input("Can't create a partition with the Free type"); goto xit2; } if (istrncmp(type_name, kMapType, DPISTRLEN) == 0) { bad_input("Can't create a partition with the Map type"); goto xit2; } add_partition_to_map(name, type_name, base, length, map); #if 0 /* this check is not found in linux fdisk-0.1 */ if (map->blocks_in_map > MAX_LINUX_MAP) { error(-1, "Map contains more than %d blocks - Linux may have trouble", MAX_LINUX_MAP); } #endif } do_update_dpme(find_entry_by_base(base,map)); xit2: if (type_name) free(type_name); xit1: if (name) free(name); return; }
void validate_map(partition_map_header *map) { range_list *list; char *name; unsigned int i; u32 limit; int printed; //printf("Validation not implemented yet.\n"); if (map == NULL) { the_map = 0; if (get_string_argument("Name of device: ", &name, 1) == 0) { bad_input("Bad name"); return; } the_media = open_pathname_as_media(name, O_RDONLY); if (the_media == 0) { error(errno, "can't open file '%s'", name); free(name); return; } g = media_granularity(the_media); if (g < PBLOCK_SIZE) { g = PBLOCK_SIZE; } the_media = open_deblock_media(PBLOCK_SIZE, the_media); buffer = malloc(PBLOCK_SIZE); if (buffer == NULL) { error(errno, "can't allocate memory for disk buffer"); goto done; } } else { name = 0; the_map = map; g = map->logical_block; } initialize_list(&list); // get block 0 if (get_block_zero() == 0) { printf("unable to read block 0\n"); goto check_map; } // XXX signature valid // XXX size & count match DeviceCapacity // XXX number of descriptors matches array size // XXX each descriptor wholly contained in a partition // XXX the range below here is in physical blocks but the map is in logical blocks!!! add_range(&list, 1, b0->sbBlkCount-1, 0); /* subtract one since args are base & len */ check_map: // compute size of map if (map != NULL) { limit = the_map->blocks_in_map; } else { if (get_block_n(1) == 0) { printf("unable to get first block\n"); goto done; } else { if (mb->dpme_signature != DPME_SIGNATURE) { limit = -1; } else { limit = mb->dpme_map_entries; } } } // for each entry for (i = 1; ; i++) { #if 0 if (limit < 0) { /* XXX what to use for end of list? */ if (i > 5) { break; } } else #endif if (i > limit) { break; } printf("block %d:\n", i); // get entry if (get_block_n(i) == 0) { printf("\tunable to get\n"); goto post_processing; } printed = 0; // signature matches if (mb->dpme_signature != DPME_SIGNATURE) { printed = 1; printf("\tsignature is 0x%x, should be 0x%x\n", mb->dpme_signature, DPME_SIGNATURE); } // reserved1 == 0 if (mb->dpme_reserved_1 != 0) { printed = 1; printf("\treserved word is 0x%x, should be 0\n", mb->dpme_reserved_1); } // entry count matches #if 0 if (limit < 0) { printed = 1; printf("\tentry count is 0x%lx, real value unknown\n", mb->dpme_map_entries); } else #endif if (mb->dpme_map_entries != limit) { printed = 1; printf("\tentry count is 0x%lx, should be %ld\n", mb->dpme_map_entries, limit); } // lblocks contained within physical if (mb->dpme_lblock_start >= mb->dpme_pblocks || mb->dpme_lblocks > mb->dpme_pblocks - mb->dpme_lblock_start) { printed = 1; printf("\tlogical blocks (%ld for %ld) not within physical size (%ld)\n", mb->dpme_lblock_start, mb->dpme_lblocks, mb->dpme_pblocks); } // remember stuff for post processing add_range(&list, mb->dpme_pblock_start, mb->dpme_pblocks, 1); // XXX type is known type? // XXX no unknown flags? // XXX boot blocks either within or outside of logical // XXX checksum matches contents // XXX other fields zero if boot_bytes is zero // XXX processor id is known value? // XXX no data in reserved3 if (printed == 0) { printf("\tokay\n"); } } post_processing: // properties of whole map // every block on disk in one & only one partition coalesce_list(list); print_range_list(list); // there is a partition for the map // map fits within partition that contains it // try to detect 512/2048 mixed partition map? done: if (map == NULL) { close_media(the_media); free(buffer); free(name); } }
int main(int argc, char* argv[]) { int sockfd, newsockfd, serverLen, clientLen; int port = DEFAULT_SERVER_PORT; /* port number */ char buffer[BUFFER_SIZE], temp_buf[BUFFER_SIZE]; /* Buffers */ char* cmd_file_pathname = NULL; /* Commands filename */ char* usr_file_pathname = NULL; /* Users filename */ struct sockaddr_in serverINETAddress; /* Server Internet address */ struct sockaddr* serverSockAddrPtr; /* Ptr to server address */ struct sockaddr_in clientINETAddress; /* Client Internet address */ struct sockaddr* clientSockAddrPtr; /* Ptr to client address */ /* Ignore death-of-child signals to prevent zombies */ signal (SIGCHLD, SIG_IGN); if((argc % 2)==0||argc > 7) bad_input(argv[0]); int i; for(i = 1; i < argc; i+=2) { /* Parse command line */ char* param = argv[i]; if(strcmp(param, "-p")==0) port = atoi(argv[i+1]); else if(strcmp(param, "-c")==0) { cmd_file_pathname= malloc(BUFFER_SIZE); strcat(cmd_file_pathname,"/"); strcat(cmd_file_pathname,argv[i+1]); } else if(strcmp(param, "-u")==0) { usr_file_pathname= malloc(BUFFER_SIZE); strcat(usr_file_pathname,"/"); strcat(usr_file_pathname,argv[i+1]); } else bad_input(argv[0]); } if(!file_exists(cmd_file_pathname) || !file_exists(usr_file_pathname)) return 0; /* Create the server Internet socket */ sockfd = socket(AF_INET, SOCK_STREAM, /* DEFAULT_PROTOCOL */ 0); if(sockfd < 0) error("ERROR opening socket"); /* Fill in server socket address fields */ serverLen = sizeof(serverINETAddress); bzero((char*)&serverINETAddress, serverLen); /* Clear structure */ serverINETAddress.sin_family = AF_INET; /* Internet domain */ serverINETAddress.sin_addr.s_addr = htonl(INADDR_ANY); /* Accept all */ serverINETAddress.sin_port = htons(port); /* Server port number */ serverSockAddrPtr = (struct sockaddr*) &serverINETAddress; /* Bind to socket address */ if(bind(sockfd, serverSockAddrPtr, serverLen) < 0) error("ERROR on binding"); /* Set max pending connection queue length */ if(listen(sockfd, QUEUE_LENGTH) < 0) error("ERROR on listening"); clientSockAddrPtr = (struct sockaddr*) &clientINETAddress; clientLen = sizeof(clientINETAddress); instruction(port); /* Display instructions */ while(1) { /* Loop forever */ /* Accept a client connection */ newsockfd = accept(sockfd,/*NULL*/clientSockAddrPtr,/*NULL */&clientLen); if(newsockfd < 0) error("ERROR on accept"); printf("Server %d: connection %d accepted\n", getpid(), newsockfd); int logged = FALSE; /* not logged in */ if(fork() == 0) { /* Create a child to serve client */ /* Perform redirection */ int a = dup2(newsockfd, STDOUT_FILENO); int b = dup2(newsockfd, STDERR_FILENO); if(a < 0 || b < 0) error("ERROR on dup2"); while(1) { bzero(buffer, sizeof(buffer)); /* Receive */ if(recv(newsockfd, buffer, sizeof(buffer), 0) < 0) error("ERROR on receiving"); /* Log in, if necessary */ if( !logged && usr_file_pathname != NULL) { if(!parse_file(usr_file_pathname,&buffer[sizeof(LOGIN_CMD)])) { printf("Access denied\n"); close(newsockfd); exit(0); } else { printf("Logged in\n"); logged=TRUE; continue; } } if (strcmp(buffer, "exit\n") == 0) { /* Exit */ close(newsockfd); exit(0); } /* Tokenize command */ bzero(temp_buf, sizeof(temp_buf)); strcpy(temp_buf, buffer); char* p = strtok(temp_buf, " "); /* token (cmd) */ if(strcmp(p, LOGIN_CMD)==0) continue; /* Ignore LOGIN_CMD */ /* Check if client can run this command */ if(cmd_file_pathname != NULL && !is_allowed_cmd(cmd_file_pathname,p)) { printf("Command not allowed\n"); continue; } /* Manage 'cd' */ if(strcmp(p, "cd")== 0 ) { p = strtok(NULL, " "); /* This is the new path */ p[strlen(p)-1] = '\0'; /* replace newline termination char */ /* Change current working directory */ if(chdir(p) < 0) perror("error"); } else system(buffer); /* Issue a command */ } } else close (newsockfd); /* Close newsocket descriptor */ } close(sockfd); return 0; /* Terminate */ }