Download | Plain Text | No Line Numbers


  1. /*
  2.  * Name: insertfile (client)
  3.  * Author: Manuel Mausz, 0728348
  4.  * Description: Server writes data read from client via IPC message queue to
  5.  * file. If filesize is reached server quits automatically. Client
  6.  * sends data read from file via IPC message queue to server
  7.  * Offset specifies file offset to start writing for server.
  8.  * Created: 12.03.2009
  9.  * Exercise: 1h B
  10.  */
  11.  
  12. #include <unistd.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <limits.h>
  17. #include "global.h"
  18.  
  19. /*
  20.  * NAME: sighandler
  21.  * PURPOSE:
  22.  * signal handler sets global error flag to 1
  23.  *
  24.  * PARAMETERS:
  25.  * int signum ... signal number
  26.  *
  27.  * RETURN VALUE:
  28.  * void
  29.  *
  30.  * GLOBAL VARS:
  31.  * error
  32.  */
  33. static void sighandler(int signum)
  34. {
  35. #ifdef DEBUG
  36. (void) printf("signal %d received\n", signum);
  37. #endif
  38. error = 1;
  39. }
  40.  
  41. /*
  42.  * NAME: usage
  43.  * PURPOSE:
  44.  * prints program usage to stderr and terminates with EXIT_FAILURE
  45.  *
  46.  * PARAMETERS:
  47.  * void
  48.  *
  49.  * RETURN VALUE:
  50.  * void
  51.  *
  52.  * GLOBAL VARS:
  53.  * me
  54.  */
  55. static void usage(void)
  56. {
  57. (void) fprintf(stderr, "Usage: %s -o offset [file]\n", me);
  58. (void) exit(EXIT_FAILURE);
  59. }
  60.  
  61. /*
  62.  * NAME: read_send
  63.  * PURPOSE:
  64.  * sends data read from stream pointed to by fp via IPC msg queue to server.
  65.  * offset specifies absolute file offset to start writing for the server.
  66.  * functions returns after all data has been sent or on error.
  67.  *
  68.  * PARAMETERS:
  69.  * FILE *fp ... pointer to stream to read from
  70.  * int msgqid ... msg queue id
  71.  * long offset ... offset
  72.  *
  73.  * RETURN VALUE:
  74.  * void
  75.  *
  76.  * GLOBAL VARS:
  77.  * error
  78.  */
  79. static void read_send(FILE *fp, int msgqid, long offset)
  80. {
  81. int len;
  82. msg_t msg;
  83.  
  84. /* read + send */
  85. if (!error)
  86. {
  87. msg.mtype = offset + 1;
  88. while(!error && !feof(fp))
  89. {
  90. /* read from file */
  91. len = fread(&msg.data, sizeof(msg.data[0]), sizeof(msg.data), fp);
  92. if (ferror(fp))
  93. {
  94. (void) printferr("Error while reading from file");
  95. break;
  96. }
  97. msg.len = len;
  98.  
  99. #ifdef DEBUG
  100. (void) printf("sending [%ld]+%d bytes to msg queue\n", msg.mtype - 1, msg.len);
  101. #endif
  102.  
  103. /* send message */
  104. if (!error && msgsnd(msgqid, &msg, MSGSIZE, 0) == -1)
  105. (void) printferr("Couldn't send message");
  106.  
  107. /* increase offset */
  108. msg.mtype += len;
  109. }
  110. if (!error && ferror(fp))
  111. (void) printferr("Error while reading from file");
  112. }
  113. }
  114.  
  115. /*
  116.  * NAME: main
  117.  * PURPOSE:
  118.  * install signal handler, parse commandline options,
  119.  * get msg queue id and call read_send
  120.  *
  121.  * PARAMETERS:
  122.  * standard parameters of main
  123.  *
  124.  * RETURN VALUE:
  125.  * int ... 0 on success, 1 on error
  126.  *
  127.  * GLOBAL VARS:
  128.  * me, error
  129.  */
  130. int main(int argc, char *argv[])
  131. {
  132. int opt, msgqid = -1;
  133. long offset = -1;
  134. char *endptr;
  135. char *filename = NULL;
  136. FILE *fp = stdin;
  137. struct sigaction new_action, old_action;
  138.  
  139. /* save me */
  140. me = argv[0];
  141.  
  142. /* install signal handler */
  143. new_action.sa_handler = sighandler;
  144. sigemptyset(&new_action.sa_mask);
  145. new_action.sa_flags = 0; /* to avoid restart of blocking syscalls */
  146. INSTALL_SIGNAL(SIGINT, new_action, old_action)
  147. INSTALL_SIGNAL(SIGQUIT, new_action, old_action)
  148. INSTALL_SIGNAL(SIGTERM, new_action, old_action)
  149.  
  150. /* parse cmdline options */
  151. while ((opt = getopt(argc, argv, "o:")) != -1)
  152. {
  153. switch(opt)
  154. {
  155. case 'o':
  156. offset = strtol(optarg, &endptr, 0);
  157.  
  158. if ((errno == ERANGE && (offset == LONG_MAX || offset == LONG_MIN))
  159. || (errno != 0 && offset == 0))
  160. (void) bailout("Invalid offset value");
  161.  
  162. if (*endptr != '\0' || offset < 0)
  163. (void) bailout("Invalid offset value. Only positive numbers allowed.");
  164.  
  165. break;
  166. default:
  167. (void) usage();
  168. break;
  169. }
  170. }
  171. argv += optind;
  172.  
  173. /* parse next commandline option */
  174. if (argv)
  175. filename = *argv;
  176.  
  177. /* check required option value */
  178. if (offset < 0)
  179. (void) usage();
  180.  
  181. #ifdef DEBUG
  182. (void) printf("offset=%ld filename=%s\n", offset, filename);
  183. #endif
  184.  
  185. /* open file to read from */
  186. if (!error && filename != NULL && (fp = fopen(filename, "r")) == NULL)
  187. (void) bailout("%s", filename);
  188.  
  189. /* get message queue id */
  190. if (!error && (msgqid = msgget(IPC_KEY, 0)) == -1)
  191. {
  192. if (errno == ENOENT)
  193. {
  194. errno = 0;
  195. (void) printferr("Couldn't get message queue. Server not running?");
  196. }
  197. else
  198. (void) printferr("Couldn't get message queue");
  199. }
  200. #ifdef DEBUG
  201. if (msgqid != -1)
  202. (void) printf("msgqid=%d\n", msgqid);
  203. #endif
  204.  
  205. /* read and send data */
  206. if (!error)
  207. (void) read_send(fp, msgqid, offset);
  208.  
  209. /* cleanup stuff */
  210. #ifdef DEBUG
  211. (void) printf("doing cleanup...\n");
  212. #endif
  213.  
  214. /* close open fds */
  215. if (filename != NULL && fp != stdin)
  216. (void) fclose(fp);
  217.  
  218. return (error) ? 1 : 0;
  219. }
  220.  
  221. /* vim: set et sw=2 ts=2: */
  222.